@momo-kits/foundation 1.0.3 → 1.0.4
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/Button/index.tsx +0 -1
- package/CheckBox/index.tsx +1 -3
- package/ContentLoader/index.tsx +1 -1
- package/Icon/icon.json +3 -0
- package/Icon/index.tsx +6 -4
- package/Icon/types.ts +4 -1
- package/Image/index.tsx +8 -9
- package/Image/types.ts +1 -3
- package/Input/Input.tsx +15 -16
- package/Input/TextArea.tsx +12 -11
- package/Input/styles.ts +1 -5
- package/Layout/ScreenContainer.tsx +2 -22
- package/Navigation/Components.tsx +37 -14
- package/Navigation/ModalScreen.tsx +10 -12
- package/Navigation/Navigation.ts +7 -6
- package/Navigation/NavigationContainer.tsx +22 -17
- package/Navigation/StackScreen.tsx +12 -7
- package/Navigation/types.ts +4 -8
- package/Navigation/utils.tsx +60 -25
- package/Playground/index.tsx +122 -5
- package/Playground/types.ts +3 -2
- package/Popup/PopupPromotion.tsx +1 -5
- package/Popup/types.ts +0 -1
- package/Radio/index.tsx +16 -8
- package/Radio/styles.ts +0 -1
- package/Radio/types.ts +4 -1
- package/Switch/index.tsx +6 -2
- package/Switch/types.ts +4 -1
- package/package.json +2 -2
package/Button/index.tsx
CHANGED
package/CheckBox/index.tsx
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import React, {FC, useContext} from 'react';
|
|
2
2
|
import {TouchableOpacity, View} from 'react-native';
|
|
3
|
-
|
|
4
3
|
import {CheckBoxProps} from './types';
|
|
5
|
-
import {Text} from '@momo-kits/foundation';
|
|
6
4
|
import styles from './styles';
|
|
7
5
|
import Image from 'react-native-fast-image';
|
|
8
6
|
import {ApplicationContext} from '../Navigation';
|
|
9
|
-
import {
|
|
7
|
+
import {Text} from '../Text';
|
|
10
8
|
|
|
11
9
|
const IC_INDETERMINATED = 'https://img.mservice.com.vn/app/img/kits/minus.png';
|
|
12
10
|
const IC_CHECKED_DEFAULT =
|
package/ContentLoader/index.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useMemo, useRef} from 'react';
|
|
2
2
|
import {Animated, Platform, useWindowDimensions, View} from 'react-native';
|
|
3
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
3
4
|
import {ContentLoaderTypes} from './types';
|
|
4
5
|
import {ApplicationContext} from '../Navigation';
|
|
5
|
-
import LinearGradient from 'react-native-linear-gradient';
|
|
6
6
|
import {Styles} from '../Consts';
|
|
7
7
|
import styles from './styles';
|
|
8
8
|
const ContentLoader: React.FC<ContentLoaderTypes> = ({style}) => {
|
package/Icon/icon.json
CHANGED
package/Icon/index.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
|
-
import {IconProps, Image, ApplicationContext} from '../index';
|
|
3
2
|
import IconSources from './icon.json';
|
|
3
|
+
import {IconProps} from './types';
|
|
4
|
+
import {ApplicationContext} from '../Navigation';
|
|
5
|
+
import {Image} from '../Image';
|
|
4
6
|
|
|
5
|
-
const Icon: React.FC<IconProps> = ({source, size, color}) => {
|
|
7
|
+
const Icon: React.FC<IconProps> = ({source, size, color, style = {}}) => {
|
|
6
8
|
const {theme} = useContext(ApplicationContext);
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -10,7 +12,7 @@ const Icon: React.FC<IconProps> = ({source, size, color}) => {
|
|
|
10
12
|
*/
|
|
11
13
|
const getIconSource = (): any => {
|
|
12
14
|
if (source && !source.includes('http')) {
|
|
13
|
-
let icon: {[key: string]:
|
|
15
|
+
let icon: {[key: string]: {uri: string}} = IconSources;
|
|
14
16
|
return icon[source] ?? icon.ic_warning;
|
|
15
17
|
}
|
|
16
18
|
return {uri: source};
|
|
@@ -19,7 +21,7 @@ const Icon: React.FC<IconProps> = ({source, size, color}) => {
|
|
|
19
21
|
return (
|
|
20
22
|
<Image
|
|
21
23
|
source={getIconSource()}
|
|
22
|
-
style={{width: size, height: size}}
|
|
24
|
+
style={[style, {width: size, height: size}]}
|
|
23
25
|
tintColor={color ?? theme.colors.text.default}
|
|
24
26
|
/>
|
|
25
27
|
);
|
package/Icon/types.ts
CHANGED
package/Image/index.tsx
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import React, {useContext, useState} from 'react';
|
|
2
|
-
import {StyleSheet, View} from 'react-native';
|
|
2
|
+
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
|
|
3
3
|
import FastImage from 'react-native-fast-image';
|
|
4
|
-
|
|
5
4
|
import styles from './styles';
|
|
6
|
-
import {ImageProps} from './types';
|
|
7
5
|
import {ApplicationContext} from '../Navigation';
|
|
8
6
|
import {ContentLoader} from '../ContentLoader';
|
|
9
7
|
import {Icon} from '../Icon';
|
|
10
8
|
import {Styles} from '../Consts';
|
|
9
|
+
import {FastImagePropsWithoutStyle} from './types';
|
|
10
|
+
|
|
11
|
+
export interface ImageProps extends FastImagePropsWithoutStyle {
|
|
12
|
+
style?: StyleProp<ViewStyle>;
|
|
13
|
+
}
|
|
11
14
|
|
|
12
|
-
const Image: React.FC<ImageProps> = ({style,
|
|
15
|
+
const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
13
16
|
const {theme} = useContext(ApplicationContext);
|
|
14
17
|
const [loading, setLoading] = useState(typeof source === 'object');
|
|
15
18
|
const [fail, setFail] = useState(false);
|
|
@@ -20,7 +23,7 @@ const Image: React.FC<ImageProps> = ({style, placeholder, source, ...rest}) => {
|
|
|
20
23
|
*/
|
|
21
24
|
const renderContent = () => {
|
|
22
25
|
if (loading || fail) {
|
|
23
|
-
let content =
|
|
26
|
+
let content = (
|
|
24
27
|
<ContentLoader style={[StyleSheet.absoluteFill, styles.image]} />
|
|
25
28
|
);
|
|
26
29
|
if (fail) {
|
|
@@ -61,8 +64,4 @@ const Image: React.FC<ImageProps> = ({style, placeholder, source, ...rest}) => {
|
|
|
61
64
|
);
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
Image.defaultProps = {
|
|
65
|
-
style: {},
|
|
66
|
-
};
|
|
67
|
-
|
|
68
67
|
export {Image};
|
package/Image/types.ts
CHANGED
package/Input/Input.tsx
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
5
5
|
TextInputFocusEventData,
|
|
6
|
-
TextInputProps,
|
|
7
6
|
TouchableOpacity,
|
|
8
7
|
View,
|
|
9
8
|
} from 'react-native';
|
|
@@ -13,12 +12,7 @@ import {Text} from '../Text';
|
|
|
13
12
|
import {Image} from '../Image';
|
|
14
13
|
import {getBorderColor, renderFloatingView} from './common';
|
|
15
14
|
import {InputProps} from './index';
|
|
16
|
-
|
|
17
|
-
const errorMessageIcon =
|
|
18
|
-
'https://img.mservice.com.vn/app/img/kits/error_mess_icon.png';
|
|
19
|
-
const ic_clear =
|
|
20
|
-
'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_close_circle_full.png';
|
|
21
|
-
const MAX_LENGTH = 100;
|
|
15
|
+
import {Icon} from '../Icon';
|
|
22
16
|
|
|
23
17
|
const Input: FC<InputProps> = ({
|
|
24
18
|
value,
|
|
@@ -34,11 +28,11 @@ const Input: FC<InputProps> = ({
|
|
|
34
28
|
disabled,
|
|
35
29
|
floatingIconColor,
|
|
36
30
|
iconColor,
|
|
31
|
+
...props
|
|
37
32
|
}) => {
|
|
38
33
|
const {theme} = useContext(ApplicationContext);
|
|
39
|
-
|
|
40
34
|
const [focused, setFocused] = useState(false);
|
|
41
|
-
const inputRef = useRef(null);
|
|
35
|
+
const inputRef = useRef<any>(null);
|
|
42
36
|
|
|
43
37
|
const onClearText = () => {
|
|
44
38
|
inputRef?.current?.clear();
|
|
@@ -91,6 +85,7 @@ const Input: FC<InputProps> = ({
|
|
|
91
85
|
)}
|
|
92
86
|
<View style={styles.inputView}>
|
|
93
87
|
<TextInput
|
|
88
|
+
{...props}
|
|
94
89
|
editable={!disabled}
|
|
95
90
|
textAlignVertical="top"
|
|
96
91
|
ref={inputRef}
|
|
@@ -112,10 +107,10 @@ const Input: FC<InputProps> = ({
|
|
|
112
107
|
<View style={styles.iconView}>
|
|
113
108
|
{focused && (
|
|
114
109
|
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
<Icon
|
|
111
|
+
source="24_navigation_close_circle_full"
|
|
112
|
+
size={16}
|
|
113
|
+
color={theme.colors.text.hint}
|
|
119
114
|
/>
|
|
120
115
|
</TouchableOpacity>
|
|
121
116
|
)}
|
|
@@ -135,7 +130,13 @@ const Input: FC<InputProps> = ({
|
|
|
135
130
|
if (errorMessage) {
|
|
136
131
|
return (
|
|
137
132
|
<View style={styles.errorView}>
|
|
138
|
-
<
|
|
133
|
+
<View style={styles.errorIcon}>
|
|
134
|
+
<Icon
|
|
135
|
+
source="ic_error"
|
|
136
|
+
size={16}
|
|
137
|
+
color={theme.colors.error.primary}
|
|
138
|
+
/>
|
|
139
|
+
</View>
|
|
139
140
|
<Text color={theme.colors.error.primary} typography={'description_s'}>
|
|
140
141
|
{errorMessage}
|
|
141
142
|
</Text>
|
|
@@ -154,8 +155,6 @@ const Input: FC<InputProps> = ({
|
|
|
154
155
|
|
|
155
156
|
Input.defaultProps = {
|
|
156
157
|
size: 'large',
|
|
157
|
-
maxLength: MAX_LENGTH,
|
|
158
|
-
disabled: false,
|
|
159
158
|
};
|
|
160
159
|
|
|
161
160
|
export default Input;
|
package/Input/TextArea.tsx
CHANGED
|
@@ -3,21 +3,16 @@ import {
|
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
5
5
|
TextInputFocusEventData,
|
|
6
|
-
TextInputProps,
|
|
7
6
|
TouchableOpacity,
|
|
8
7
|
View,
|
|
9
8
|
} from 'react-native';
|
|
10
9
|
import styles from './styles';
|
|
11
|
-
import {Image} from '../Image';
|
|
12
10
|
import {Text} from '../Text';
|
|
13
11
|
import {ApplicationContext} from '../Navigation';
|
|
14
12
|
import {getBorderColor, renderFloatingView} from './common';
|
|
15
13
|
import {TextAreaProps} from './index';
|
|
14
|
+
import {Icon} from '../Icon';
|
|
16
15
|
|
|
17
|
-
const errorMessageIcon =
|
|
18
|
-
'https://img.mservice.com.vn/app/img/kits/error_mess_icon.png';
|
|
19
|
-
const ic_clear =
|
|
20
|
-
'https://img.mservice.io/momo_app_v2/new_version/img/appx_icon/24_navigation_close_circle_full.png';
|
|
21
16
|
const DEFAULT_HEIGHT = 112;
|
|
22
17
|
const MAX_LENGTH = 300;
|
|
23
18
|
|
|
@@ -122,10 +117,10 @@ const TextArea: FC<TextAreaProps> = props => {
|
|
|
122
117
|
</View>
|
|
123
118
|
{focused && (
|
|
124
119
|
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
<Icon
|
|
121
|
+
source="24_navigation_close_circle_full"
|
|
122
|
+
size={16}
|
|
123
|
+
color={theme.colors.text.hint}
|
|
129
124
|
/>
|
|
130
125
|
</TouchableOpacity>
|
|
131
126
|
)}
|
|
@@ -139,7 +134,13 @@ const TextArea: FC<TextAreaProps> = props => {
|
|
|
139
134
|
if (errorMessage) {
|
|
140
135
|
return (
|
|
141
136
|
<View style={styles.errorView}>
|
|
142
|
-
<
|
|
137
|
+
<View style={styles.errorIcon}>
|
|
138
|
+
<Icon
|
|
139
|
+
source="ic_error"
|
|
140
|
+
size={16}
|
|
141
|
+
color={theme.colors.error.primary}
|
|
142
|
+
/>
|
|
143
|
+
</View>
|
|
143
144
|
<Text color={theme.colors.error.primary} typography={'description_s'}>
|
|
144
145
|
{errorMessage}
|
|
145
146
|
</Text>
|
package/Input/styles.ts
CHANGED
|
@@ -29,7 +29,7 @@ export default StyleSheet.create({
|
|
|
29
29
|
flexDirection: 'row',
|
|
30
30
|
},
|
|
31
31
|
floatingIcon: {width: 16, height: 16, marginLeft: Spacing.XS},
|
|
32
|
-
errorIcon: {
|
|
32
|
+
errorIcon: {marginRight: Spacing.XS},
|
|
33
33
|
errorView: {
|
|
34
34
|
flexDirection: 'row',
|
|
35
35
|
alignItems: 'center',
|
|
@@ -38,10 +38,6 @@ export default StyleSheet.create({
|
|
|
38
38
|
justifyContent: 'space-between',
|
|
39
39
|
flex: 1,
|
|
40
40
|
},
|
|
41
|
-
iconClose: {
|
|
42
|
-
width: 16,
|
|
43
|
-
height: 16,
|
|
44
|
-
},
|
|
45
41
|
iconView: {
|
|
46
42
|
flexDirection: 'row',
|
|
47
43
|
alignItems: 'center',
|
|
@@ -1,36 +1,23 @@
|
|
|
1
1
|
import {KeyboardAvoidingView, Platform, ScrollView, View} from 'react-native';
|
|
2
2
|
import {useHeaderHeight} from '@react-navigation/stack';
|
|
3
3
|
import {SafeAreaView} from 'react-native-safe-area-context';
|
|
4
|
-
import React
|
|
4
|
+
import React from 'react';
|
|
5
5
|
import {ScreenContainerProps} from '../Navigation/types';
|
|
6
|
-
import {ApplicationContext} from '../Navigation';
|
|
7
6
|
import {Spacing, Styles} from '../Consts';
|
|
8
7
|
import {ScreenSection, validateChildren} from './index';
|
|
9
8
|
|
|
10
9
|
const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
11
10
|
children,
|
|
12
|
-
navigation,
|
|
13
|
-
options,
|
|
14
11
|
edges,
|
|
15
12
|
enableKeyboardAvoidingView,
|
|
16
13
|
scrollable,
|
|
17
14
|
}) => {
|
|
18
15
|
let Component: any = View;
|
|
19
|
-
const {theme} = useContext(ApplicationContext);
|
|
20
16
|
const headerHeight = useHeaderHeight();
|
|
21
17
|
if (scrollable) {
|
|
22
18
|
Component = ScrollView;
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
/**
|
|
26
|
-
* handle set options for navigation if have props options
|
|
27
|
-
*/
|
|
28
|
-
useLayoutEffect(() => {
|
|
29
|
-
if (options) {
|
|
30
|
-
navigation.setOptions(options);
|
|
31
|
-
}
|
|
32
|
-
}, [navigation, options]);
|
|
33
|
-
|
|
34
21
|
/**
|
|
35
22
|
* build content for screen
|
|
36
23
|
*/
|
|
@@ -54,14 +41,7 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
54
41
|
};
|
|
55
42
|
|
|
56
43
|
return (
|
|
57
|
-
<SafeAreaView
|
|
58
|
-
style={[
|
|
59
|
-
Styles.flex,
|
|
60
|
-
{
|
|
61
|
-
backgroundColor: theme.colors.background.default,
|
|
62
|
-
},
|
|
63
|
-
]}
|
|
64
|
-
edges={edges}>
|
|
44
|
+
<SafeAreaView style={Styles.flex} edges={edges}>
|
|
65
45
|
<KeyboardAvoidingView
|
|
66
46
|
style={Styles.flex}
|
|
67
47
|
keyboardVerticalOffset={headerHeight}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {StatusBar, StyleSheet, View} from 'react-native';
|
|
3
3
|
import {ApplicationContext, NavigationButton} from './index';
|
|
4
|
-
import {Styles} from '../Consts';
|
|
4
|
+
import {Colors, Styles} from '../Consts';
|
|
5
5
|
import {Image} from '../Image';
|
|
6
6
|
import {HeaderBackgroundProps, TitleCustomProps} from './types';
|
|
7
7
|
import {useGridSystem} from '../Layout';
|
|
8
|
+
import {Text} from '../Text';
|
|
8
9
|
|
|
9
10
|
const styles = StyleSheet.create({
|
|
10
11
|
headerBackground: {
|
|
@@ -17,14 +18,21 @@ const styles = StyleSheet.create({
|
|
|
17
18
|
alignItems: 'center',
|
|
18
19
|
justifyContent: 'center',
|
|
19
20
|
},
|
|
21
|
+
avatar: {width: 36, height: 36, borderRadius: 18},
|
|
22
|
+
dotAvatar: {
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
width: 12,
|
|
25
|
+
height: 12,
|
|
26
|
+
borderRadius: 6,
|
|
27
|
+
bottom: 0,
|
|
28
|
+
right: 0,
|
|
29
|
+
borderWidth: 1,
|
|
30
|
+
borderColor: Colors.black_01,
|
|
31
|
+
},
|
|
20
32
|
});
|
|
21
33
|
|
|
22
|
-
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
23
|
-
surface = false,
|
|
24
|
-
image,
|
|
25
|
-
}) => {
|
|
34
|
+
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({image}) => {
|
|
26
35
|
const {theme} = useContext(ApplicationContext);
|
|
27
|
-
const allowImage = !surface && theme.assets?.headerBackground;
|
|
28
36
|
return (
|
|
29
37
|
<View
|
|
30
38
|
style={[
|
|
@@ -32,14 +40,9 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
32
40
|
{backgroundColor: theme.colors.background.surface, overflow: 'hidden'},
|
|
33
41
|
]}>
|
|
34
42
|
<StatusBar
|
|
35
|
-
barStyle={
|
|
43
|
+
barStyle={image || theme.dark ? 'light-content' : 'dark-content'}
|
|
36
44
|
/>
|
|
37
|
-
{
|
|
38
|
-
<Image
|
|
39
|
-
style={styles.headerBackground}
|
|
40
|
-
source={{uri: image ?? theme.assets?.headerBackground}}
|
|
41
|
-
/>
|
|
42
|
-
)}
|
|
45
|
+
{image && <Image style={styles.headerBackground} source={{uri: image}} />}
|
|
43
46
|
</View>
|
|
44
47
|
);
|
|
45
48
|
};
|
|
@@ -49,12 +52,32 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
49
52
|
subTitle,
|
|
50
53
|
image,
|
|
51
54
|
content,
|
|
55
|
+
tintColor,
|
|
56
|
+
dotColor,
|
|
52
57
|
}) => {
|
|
53
58
|
const {getSizeSpan} = useGridSystem();
|
|
54
59
|
|
|
60
|
+
const header = (
|
|
61
|
+
<View style={Styles.row}>
|
|
62
|
+
<View>
|
|
63
|
+
<Image source={{uri: image}} style={styles.avatar} />
|
|
64
|
+
{dotColor && (
|
|
65
|
+
<View style={[styles.dotAvatar, {backgroundColor: dotColor}]} />
|
|
66
|
+
)}
|
|
67
|
+
</View>
|
|
68
|
+
<View style={[Styles.flex, Styles.paddingHorizontal8]}>
|
|
69
|
+
<Text typography="title_xs" color={tintColor}>
|
|
70
|
+
{title}
|
|
71
|
+
</Text>
|
|
72
|
+
<Text typography="description_s" color={tintColor}>
|
|
73
|
+
{subTitle}
|
|
74
|
+
</Text>
|
|
75
|
+
</View>
|
|
76
|
+
</View>
|
|
77
|
+
);
|
|
55
78
|
return (
|
|
56
79
|
<View style={[styles.headerTitleContainer, {width: getSizeSpan(10)}]}>
|
|
57
|
-
{content ??
|
|
80
|
+
{content ?? header}
|
|
58
81
|
</View>
|
|
59
82
|
);
|
|
60
83
|
};
|
|
@@ -26,11 +26,12 @@ const ModalScreen: React.FC<ModalParams> = ({navigation, route, ...rest}) => {
|
|
|
26
26
|
backgroundColor,
|
|
27
27
|
screen,
|
|
28
28
|
barrierDismissible,
|
|
29
|
+
options,
|
|
29
30
|
}: ModalParams = route.params;
|
|
30
31
|
const Component = useRef(screen).current;
|
|
31
32
|
const params = {
|
|
32
33
|
...route.params,
|
|
33
|
-
navigation: new Navigation(navigation),
|
|
34
|
+
navigation: new Navigation(navigation, theme),
|
|
34
35
|
};
|
|
35
36
|
delete params.screen;
|
|
36
37
|
|
|
@@ -54,6 +55,7 @@ const ModalScreen: React.FC<ModalParams> = ({navigation, route, ...rest}) => {
|
|
|
54
55
|
*/
|
|
55
56
|
if (isBottomSheet) {
|
|
56
57
|
const bgColor = backgroundColor ?? theme.colors.background.surface;
|
|
58
|
+
const sheetTheme = {...theme, assets: undefined};
|
|
57
59
|
return (
|
|
58
60
|
<BottomSheet {...rest} onDismiss={onDismiss}>
|
|
59
61
|
<View style={[styles.sheetContainer, {backgroundColor: bgColor}]}>
|
|
@@ -66,26 +68,22 @@ const ModalScreen: React.FC<ModalParams> = ({navigation, route, ...rest}) => {
|
|
|
66
68
|
/>
|
|
67
69
|
</View>
|
|
68
70
|
<NavigationContainer
|
|
69
|
-
theme={
|
|
70
|
-
screen={props => <Component {...
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
theme={sheetTheme}
|
|
72
|
+
screen={props => <Component {...props} {...params} />}
|
|
73
|
+
options={{
|
|
74
|
+
...options,
|
|
75
|
+
hiddenBack: true,
|
|
76
|
+
headerTitleAlign: 'center',
|
|
75
77
|
headerRight: (props: any) => (
|
|
76
78
|
<HeaderRightAction>
|
|
77
79
|
<NavigationButton
|
|
78
80
|
icon="24_navigation_close"
|
|
79
81
|
{...props}
|
|
80
|
-
onPress={
|
|
82
|
+
onPress={() => navigation.pop()}
|
|
81
83
|
/>
|
|
82
84
|
</HeaderRightAction>
|
|
83
85
|
),
|
|
84
|
-
headerBackground: () => (
|
|
85
|
-
<View style={[Styles.flex, {backgroundColor: bgColor}]} />
|
|
86
|
-
),
|
|
87
86
|
}}
|
|
88
|
-
hideBackFirst={true}
|
|
89
87
|
/>
|
|
90
88
|
</View>
|
|
91
89
|
</BottomSheet>
|
package/Navigation/Navigation.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {NavigationProp} from '@react-navigation/native';
|
|
2
|
-
import {NavigationOptions} from './types';
|
|
2
|
+
import {NavigationOptions, Theme} from './types';
|
|
3
3
|
import {HeaderRightAction} from './index';
|
|
4
4
|
import {getOptions} from './utils';
|
|
5
5
|
|
|
6
6
|
class Navigation {
|
|
7
7
|
instance: NavigationProp<any>;
|
|
8
|
+
theme: Theme;
|
|
8
9
|
|
|
9
|
-
constructor(instance: any) {
|
|
10
|
+
constructor(instance: any, theme: Theme) {
|
|
10
11
|
this.instance = instance;
|
|
12
|
+
this.theme = theme;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
verifyParams = (params: NavigationOptions) => {
|
|
@@ -17,9 +19,9 @@ class Navigation {
|
|
|
17
19
|
console.warn(
|
|
18
20
|
'headerRight not return element type of HeaderRightAction, Please migrate to use HeaderRightAction of kits.',
|
|
19
21
|
);
|
|
20
|
-
return;
|
|
21
22
|
}
|
|
22
23
|
}
|
|
24
|
+
return params;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
filterParams = (params: NavigationOptions) => {
|
|
@@ -27,9 +29,8 @@ class Navigation {
|
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
setOptions = (params: NavigationOptions) => {
|
|
30
|
-
this.verifyParams(params);
|
|
31
|
-
params = this.
|
|
32
|
-
params = getOptions(params);
|
|
32
|
+
params = this.verifyParams(params);
|
|
33
|
+
params = getOptions(params, this.theme);
|
|
33
34
|
this.instance.setOptions(params);
|
|
34
35
|
};
|
|
35
36
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {createContext, useRef} from 'react';
|
|
1
|
+
import React, {createContext, useEffect, useRef} from 'react';
|
|
2
2
|
import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
|
|
3
3
|
import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
4
4
|
import {
|
|
@@ -11,7 +11,7 @@ import ModalScreen from './ModalScreen';
|
|
|
11
11
|
import Navigator from './Navigator';
|
|
12
12
|
import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
13
13
|
import {GridSystem, useGridSystem} from '../Layout';
|
|
14
|
-
import {defaultContext
|
|
14
|
+
import {defaultContext} from '../Consts';
|
|
15
15
|
import {NavigationContainerProps} from './types';
|
|
16
16
|
|
|
17
17
|
const Stack = createStackNavigator();
|
|
@@ -20,23 +20,17 @@ const ApplicationContext = createContext(defaultContext);
|
|
|
20
20
|
const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
21
21
|
screen,
|
|
22
22
|
theme,
|
|
23
|
-
|
|
24
|
-
screenOptions,
|
|
25
|
-
hideBackFirst,
|
|
23
|
+
options,
|
|
26
24
|
}) => {
|
|
27
25
|
const grid = useGridSystem();
|
|
28
26
|
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
29
27
|
const navigator = useRef(new Navigator(navigationRef));
|
|
30
|
-
const themed: any = theme;
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
navigationRef?.current?.goBack();
|
|
36
|
-
} else {
|
|
37
|
-
onDismiss?.();
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (options) {
|
|
31
|
+
navigationRef.current?.setParams({options: options});
|
|
38
32
|
}
|
|
39
|
-
};
|
|
33
|
+
}, []);
|
|
40
34
|
|
|
41
35
|
return (
|
|
42
36
|
<SafeAreaProvider>
|
|
@@ -44,20 +38,31 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
44
38
|
<ApplicationContext.Provider
|
|
45
39
|
value={{theme, navigator: navigator.current}}>
|
|
46
40
|
<ReactNavigationContainer
|
|
47
|
-
theme={
|
|
41
|
+
theme={{
|
|
42
|
+
...theme,
|
|
43
|
+
dark: false,
|
|
44
|
+
colors: {
|
|
45
|
+
...theme.colors,
|
|
46
|
+
background: theme.colors.background.default,
|
|
47
|
+
card: theme.colors.background.surface,
|
|
48
|
+
text: theme.colors.text.default,
|
|
49
|
+
border: theme.colors.border.default,
|
|
50
|
+
notification: theme.colors.error.primary,
|
|
51
|
+
},
|
|
52
|
+
}}
|
|
48
53
|
ref={navigator.current?.ref}
|
|
49
54
|
independent={true}>
|
|
50
55
|
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
51
56
|
<Stack.Screen
|
|
52
57
|
name="Stack"
|
|
53
58
|
component={StackScreen}
|
|
54
|
-
initialParams={{screen
|
|
55
|
-
options={
|
|
59
|
+
initialParams={{screen}}
|
|
60
|
+
options={getStackOptions(theme)}
|
|
56
61
|
/>
|
|
57
62
|
<Stack.Screen
|
|
58
63
|
name="Dialog"
|
|
59
64
|
component={StackScreen}
|
|
60
|
-
options={getDialogOptions(theme
|
|
65
|
+
options={getDialogOptions(theme)}
|
|
61
66
|
initialParams={{screen}}
|
|
62
67
|
/>
|
|
63
68
|
<Stack.Screen
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {useContext, useEffect} from 'react';
|
|
2
2
|
import {ScreenParams} from './types';
|
|
3
3
|
import Navigation from './Navigation';
|
|
4
|
+
import {ApplicationContext} from './NavigationContainer';
|
|
4
5
|
|
|
5
6
|
const StackScreen: React.FC<any> = props => {
|
|
6
7
|
const {route, navigation} = props;
|
|
7
|
-
const {screen: Component,
|
|
8
|
+
const {screen: Component, options}: ScreenParams = route.params;
|
|
9
|
+
const {theme} = useContext(ApplicationContext);
|
|
8
10
|
|
|
9
11
|
const params = {
|
|
10
12
|
...route.params,
|
|
11
|
-
navigation: new Navigation(navigation),
|
|
13
|
+
navigation: new Navigation(navigation, theme),
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
delete params.screen;
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* handle set options for navigation if have props options
|
|
20
|
+
*/
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (options) {
|
|
23
|
+
params.navigation.setOptions(options);
|
|
19
24
|
}
|
|
20
|
-
}, []);
|
|
25
|
+
}, [navigation, options]);
|
|
21
26
|
|
|
22
27
|
return <Component {...params} />;
|
|
23
28
|
};
|
package/Navigation/types.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {ViewProps} from 'react-native';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Navigator from './Navigator';
|
|
4
|
-
import Navigation from './Navigation';
|
|
5
|
-
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
6
4
|
|
|
7
5
|
export type Theme = {
|
|
8
6
|
dark: boolean;
|
|
@@ -66,15 +64,11 @@ export type Context = {
|
|
|
66
64
|
|
|
67
65
|
export type NavigationContainerProps = {
|
|
68
66
|
screen: React.ElementType;
|
|
69
|
-
|
|
70
|
-
hideBackFirst?: boolean;
|
|
67
|
+
options?: NavigationOptions;
|
|
71
68
|
theme: Theme;
|
|
72
|
-
onDismiss?: () => void;
|
|
73
69
|
};
|
|
74
70
|
|
|
75
71
|
export interface ScreenContainerProps extends ViewProps {
|
|
76
|
-
navigation: Navigation;
|
|
77
|
-
options?: NavigationOptions;
|
|
78
72
|
edges?: any[];
|
|
79
73
|
enableKeyboardAvoidingView?: boolean;
|
|
80
74
|
scrollable: boolean;
|
|
@@ -102,6 +96,7 @@ export type NavigationButtonProps = {
|
|
|
102
96
|
|
|
103
97
|
export type NavigationOptions = {
|
|
104
98
|
surface?: boolean;
|
|
99
|
+
hiddenBack?: boolean;
|
|
105
100
|
title?: string;
|
|
106
101
|
headerTitleAlign?: 'left' | 'center';
|
|
107
102
|
customTitle?: TitleCustomProps;
|
|
@@ -109,7 +104,6 @@ export type NavigationOptions = {
|
|
|
109
104
|
};
|
|
110
105
|
|
|
111
106
|
export type HeaderBackgroundProps = {
|
|
112
|
-
surface?: boolean;
|
|
113
107
|
image?: string;
|
|
114
108
|
};
|
|
115
109
|
|
|
@@ -117,5 +111,7 @@ export type TitleCustomProps = {
|
|
|
117
111
|
title?: string;
|
|
118
112
|
subTitle?: string;
|
|
119
113
|
image?: string;
|
|
114
|
+
dotColor?: string;
|
|
115
|
+
tintColor?: string;
|
|
120
116
|
content?: React.ReactNode;
|
|
121
117
|
};
|
package/Navigation/utils.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
StackNavigationOptions,
|
|
4
4
|
TransitionPresets,
|
|
@@ -7,9 +7,9 @@ import {HeaderBackground, HeaderCustom} from './Components';
|
|
|
7
7
|
import {NavigationOptions, Theme} from './types';
|
|
8
8
|
import {Colors} from '../Consts';
|
|
9
9
|
import {Text} from '../Text';
|
|
10
|
-
import {NavigationButton} from './index';
|
|
10
|
+
import {ApplicationContext, NavigationButton} from './index';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const HeaderTitle = (props: any) => {
|
|
13
13
|
return (
|
|
14
14
|
<Text
|
|
15
15
|
{...props}
|
|
@@ -20,6 +20,17 @@ const renderTitle = (props: any) => {
|
|
|
20
20
|
);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
const HeaderLeft = (props: any) => {
|
|
24
|
+
const {navigator} = useContext(ApplicationContext);
|
|
25
|
+
const goBack = () => {
|
|
26
|
+
const canGoBack = navigator?.ref.current?.canGoBack();
|
|
27
|
+
if (canGoBack) {
|
|
28
|
+
navigator?.ref.current?.goBack();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return <NavigationButton icon="ic_back" {...props} onPress={goBack} />;
|
|
32
|
+
};
|
|
33
|
+
|
|
23
34
|
const getTintColor = (theme: Theme): any => {
|
|
24
35
|
if (theme.assets?.headerBackground) {
|
|
25
36
|
return {
|
|
@@ -31,32 +42,26 @@ const getTintColor = (theme: Theme): any => {
|
|
|
31
42
|
};
|
|
32
43
|
};
|
|
33
44
|
|
|
34
|
-
const getStackOptions = (
|
|
35
|
-
theme: Theme,
|
|
36
|
-
goBack: () => void,
|
|
37
|
-
): StackNavigationOptions => {
|
|
45
|
+
const getStackOptions = (theme: Theme): StackNavigationOptions => {
|
|
38
46
|
return {
|
|
39
47
|
headerTitleAlign: 'center',
|
|
40
|
-
headerTitle:
|
|
41
|
-
headerBackground:
|
|
42
|
-
|
|
43
|
-
<NavigationButton icon="ic_back" {...props} onPress={goBack} />
|
|
48
|
+
headerTitle: HeaderTitle,
|
|
49
|
+
headerBackground: () => (
|
|
50
|
+
<HeaderBackground image={theme.assets?.headerBackground} />
|
|
44
51
|
),
|
|
52
|
+
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
45
53
|
...getTintColor(theme),
|
|
46
54
|
};
|
|
47
55
|
};
|
|
48
56
|
|
|
49
|
-
const getDialogOptions = (
|
|
50
|
-
theme: Theme,
|
|
51
|
-
goBack: () => void,
|
|
52
|
-
): StackNavigationOptions => {
|
|
57
|
+
const getDialogOptions = (theme: Theme): StackNavigationOptions => {
|
|
53
58
|
return {
|
|
54
59
|
headerTitleAlign: 'center',
|
|
55
|
-
headerTitle:
|
|
56
|
-
headerLeft: (props: any) =>
|
|
57
|
-
|
|
60
|
+
headerTitle: HeaderTitle,
|
|
61
|
+
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
62
|
+
headerBackground: () => (
|
|
63
|
+
<HeaderBackground image={theme.assets?.headerBackground} />
|
|
58
64
|
),
|
|
59
|
-
headerBackground: HeaderBackground,
|
|
60
65
|
...getTintColor(theme),
|
|
61
66
|
...TransitionPresets.ModalTransition,
|
|
62
67
|
};
|
|
@@ -87,21 +92,51 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
87
92
|
};
|
|
88
93
|
};
|
|
89
94
|
|
|
90
|
-
const getOptions = (params: NavigationOptions) => {
|
|
95
|
+
const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
96
|
+
let backTheme = {};
|
|
91
97
|
let surfaceTheme = {};
|
|
92
98
|
let titleTheme = {};
|
|
93
|
-
|
|
99
|
+
|
|
100
|
+
if (params.hiddenBack == true) {
|
|
101
|
+
backTheme = {
|
|
102
|
+
headerLeft: null,
|
|
103
|
+
};
|
|
104
|
+
} else {
|
|
105
|
+
backTheme = {
|
|
106
|
+
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (params.surface == true) {
|
|
94
111
|
surfaceTheme = {
|
|
95
|
-
headerBackground: () => <HeaderBackground
|
|
96
|
-
|
|
112
|
+
headerBackground: () => <HeaderBackground />,
|
|
113
|
+
...getTintColor({
|
|
114
|
+
...theme,
|
|
115
|
+
assets: {...theme.assets, headerBackground: undefined},
|
|
116
|
+
}),
|
|
117
|
+
};
|
|
118
|
+
} else {
|
|
119
|
+
surfaceTheme = {
|
|
120
|
+
headerBackground: () => (
|
|
121
|
+
<HeaderBackground image={theme.assets?.headerBackground} />
|
|
122
|
+
),
|
|
123
|
+
...getTintColor(theme),
|
|
97
124
|
};
|
|
98
125
|
}
|
|
126
|
+
|
|
99
127
|
if (params.customTitle) {
|
|
100
128
|
titleTheme = {
|
|
101
|
-
headerTitle: () =>
|
|
129
|
+
headerTitle: (props: any) => {
|
|
130
|
+
return <HeaderCustom {...params.customTitle} {...props} />;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
} else {
|
|
134
|
+
titleTheme = {
|
|
135
|
+
headerTitle: HeaderTitle,
|
|
102
136
|
};
|
|
103
137
|
}
|
|
104
|
-
|
|
138
|
+
|
|
139
|
+
return {...params, ...backTheme, ...surfaceTheme, ...titleTheme};
|
|
105
140
|
};
|
|
106
141
|
|
|
107
142
|
export {getStackOptions, getDialogOptions, getModalOptions, getOptions};
|
package/Playground/index.tsx
CHANGED
|
@@ -1,13 +1,88 @@
|
|
|
1
1
|
import React, {FC, useContext, useEffect, useState} from 'react';
|
|
2
|
-
import {View} from 'react-native';
|
|
2
|
+
import {FlatList, TouchableOpacity, View} from 'react-native';
|
|
3
3
|
import {CheckBox, Input, Radio, Text} from '@momo-kits/foundation';
|
|
4
4
|
import {PlaygroundProps, PropValue} from './types';
|
|
5
5
|
import styles from './styles';
|
|
6
|
-
import {Spacing} from '../Consts';
|
|
6
|
+
import {Colors, Radius, Spacing} from '../Consts';
|
|
7
7
|
import {ApplicationContext} from '../Navigation';
|
|
8
|
+
import {ScreenSection, SectionItem} from '../Layout';
|
|
9
|
+
import {Icon, IconSources} from '../Icon';
|
|
10
|
+
import {string} from 'prop-types';
|
|
8
11
|
|
|
9
|
-
const
|
|
12
|
+
const ChooseOptionScreen = (
|
|
13
|
+
data: string[] = [],
|
|
14
|
+
optionType: 'color' | 'icon' | 'text' = 'text',
|
|
15
|
+
onPress: (value: string) => void,
|
|
16
|
+
) => {
|
|
10
17
|
const {theme} = useContext(ApplicationContext);
|
|
18
|
+
|
|
19
|
+
let mapData = data;
|
|
20
|
+
if (optionType === 'color') {
|
|
21
|
+
mapData = Object.values(Colors);
|
|
22
|
+
}
|
|
23
|
+
if (optionType === 'icon') {
|
|
24
|
+
mapData = Object.keys(IconSources);
|
|
25
|
+
}
|
|
26
|
+
const renderItemView = (item: string) => {
|
|
27
|
+
switch (optionType) {
|
|
28
|
+
case 'color': {
|
|
29
|
+
return (
|
|
30
|
+
<View
|
|
31
|
+
style={{
|
|
32
|
+
width: 36,
|
|
33
|
+
height: 36,
|
|
34
|
+
borderRadius: Radius.M,
|
|
35
|
+
backgroundColor: item,
|
|
36
|
+
marginRight: Spacing.S,
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
case 'icon': {
|
|
42
|
+
return <Icon source={item} style={{marginRight: Spacing.S}} />;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const renderItem = ({item, index}) => {
|
|
48
|
+
const iconSource: {[key: string]: {uri: string}} = IconSources;
|
|
49
|
+
let key = item;
|
|
50
|
+
let chosenItem = item;
|
|
51
|
+
if (optionType === 'color') key = Object.keys(Colors)[index];
|
|
52
|
+
if (optionType === 'icon') chosenItem = iconSource[key].uri;
|
|
53
|
+
return (
|
|
54
|
+
<TouchableOpacity
|
|
55
|
+
key={`${item.toString()} ${index}`}
|
|
56
|
+
onPress={() => onPress(chosenItem)}
|
|
57
|
+
style={{
|
|
58
|
+
flexDirection: 'row',
|
|
59
|
+
alignItems: 'center',
|
|
60
|
+
marginBottom: Spacing.M,
|
|
61
|
+
borderBottomWidth: index !== mapData.length - 1 ? 1 : 0,
|
|
62
|
+
borderColor: theme.colors.border.default,
|
|
63
|
+
paddingBottom: Spacing.M,
|
|
64
|
+
}}>
|
|
65
|
+
{renderItemView(item)}
|
|
66
|
+
<Text typography={'description_default'}>{key}</Text>
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
return (
|
|
71
|
+
<ScreenSection>
|
|
72
|
+
<SectionItem widthSpan={12}>
|
|
73
|
+
<FlatList
|
|
74
|
+
data={mapData}
|
|
75
|
+
renderItem={renderItem}
|
|
76
|
+
keyExtractor={(item, index) => `${item.toString()} ${index}`}
|
|
77
|
+
showsVerticalScrollIndicator={false}
|
|
78
|
+
/>
|
|
79
|
+
</SectionItem>
|
|
80
|
+
</ScreenSection>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
85
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
11
86
|
const {props} = params;
|
|
12
87
|
const [compProps, setCompProps] = useState<{[key: string]: any}>({});
|
|
13
88
|
useEffect(() => {
|
|
@@ -37,6 +112,19 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
37
112
|
setCompProps(newProps);
|
|
38
113
|
};
|
|
39
114
|
|
|
115
|
+
const showOptions = (prop: any, key: string) => {
|
|
116
|
+
navigator?.showBottomSheet({
|
|
117
|
+
options: {
|
|
118
|
+
title: 'Choose option',
|
|
119
|
+
},
|
|
120
|
+
screen: () =>
|
|
121
|
+
ChooseOptionScreen(prop.data, prop.optionType, optionValue => {
|
|
122
|
+
onChangeOptions(optionValue, key);
|
|
123
|
+
navigator?.pop();
|
|
124
|
+
}),
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
40
128
|
const generateView = (key: string, prop: PropValue) => {
|
|
41
129
|
let PlayGroundView = <View />;
|
|
42
130
|
switch (prop.type) {
|
|
@@ -50,6 +138,7 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
50
138
|
value={option}
|
|
51
139
|
onChange={() => onChangeOptions(option, key)}
|
|
52
140
|
groupValue={compProps?.[key]}
|
|
141
|
+
style={{marginBottom: Spacing.S}}
|
|
53
142
|
/>
|
|
54
143
|
);
|
|
55
144
|
})}
|
|
@@ -62,6 +151,7 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
62
151
|
<Input
|
|
63
152
|
size={'small'}
|
|
64
153
|
floatingValue={key}
|
|
154
|
+
value={compProps?.[key]}
|
|
65
155
|
onChangeText={text => onChangeOptions(text, key)}
|
|
66
156
|
/>
|
|
67
157
|
);
|
|
@@ -79,6 +169,29 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
79
169
|
onChange={value => onChangeOptions(value, key)}
|
|
80
170
|
/>
|
|
81
171
|
);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
case 'options': {
|
|
175
|
+
PlayGroundView = (
|
|
176
|
+
<TouchableOpacity
|
|
177
|
+
style={{
|
|
178
|
+
width: '100%',
|
|
179
|
+
height: 48,
|
|
180
|
+
borderRadius: Radius.M,
|
|
181
|
+
borderColor: theme.colors.border.default,
|
|
182
|
+
borderWidth: 1,
|
|
183
|
+
justifyContent: 'center',
|
|
184
|
+
alignItems: 'center',
|
|
185
|
+
flexDirection: 'row',
|
|
186
|
+
backgroundColor: theme.colors.background.surface,
|
|
187
|
+
}}
|
|
188
|
+
onPress={() => showOptions(prop, key)}>
|
|
189
|
+
<Text typography={'description_default'}>{compProps?.[key]}</Text>
|
|
190
|
+
<View style={{position: 'absolute', right: Spacing.M}}>
|
|
191
|
+
<Icon source={'arrow_chevron_down_small'} size={24} />
|
|
192
|
+
</View>
|
|
193
|
+
</TouchableOpacity>
|
|
194
|
+
);
|
|
82
195
|
}
|
|
83
196
|
}
|
|
84
197
|
|
|
@@ -106,6 +219,7 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
106
219
|
|
|
107
220
|
const Component = params.component ?? <View />;
|
|
108
221
|
const propsKeys = Object.keys(props);
|
|
222
|
+
|
|
109
223
|
return (
|
|
110
224
|
<View>
|
|
111
225
|
<Text style={{marginBottom: Spacing.M}} typography={'title_s'}>
|
|
@@ -114,9 +228,12 @@ const Playground: FC<PlaygroundProps> = ({params}) => {
|
|
|
114
228
|
<View
|
|
115
229
|
style={[
|
|
116
230
|
styles.propView,
|
|
117
|
-
{
|
|
231
|
+
{
|
|
232
|
+
backgroundColor: theme.colors.background.surface,
|
|
233
|
+
justifyContent: 'center',
|
|
234
|
+
alignItems: 'center',
|
|
235
|
+
},
|
|
118
236
|
]}>
|
|
119
|
-
<Text typography={'header_default'}>{params.displayName}</Text>
|
|
120
237
|
<Component {...compProps} />
|
|
121
238
|
</View>
|
|
122
239
|
<Text style={{marginBottom: Spacing.M}} typography={'title_s'}>
|
package/Playground/types.ts
CHANGED
|
@@ -3,13 +3,14 @@ import {ReactElement} from 'react';
|
|
|
3
3
|
export type PropValue = {
|
|
4
4
|
value: any;
|
|
5
5
|
options?: string[];
|
|
6
|
-
type: 'string' | 'enum' | 'bool';
|
|
6
|
+
type: 'string' | 'options' | 'enum' | 'bool';
|
|
7
7
|
description?: string;
|
|
8
|
+
data?: {[key: string]: string}[];
|
|
9
|
+
optionType?: 'icon' | 'color';
|
|
8
10
|
};
|
|
9
11
|
export type PlaygroundProps = {
|
|
10
12
|
params: {
|
|
11
13
|
component: ReactElement;
|
|
12
|
-
displayName: string;
|
|
13
14
|
props: {[key: string]: PropValue};
|
|
14
15
|
};
|
|
15
16
|
};
|
package/Popup/PopupPromotion.tsx
CHANGED
|
@@ -6,11 +6,7 @@ import {Image} from '../Image';
|
|
|
6
6
|
import {Button} from '../Button';
|
|
7
7
|
import {Spacing} from '../Consts';
|
|
8
8
|
|
|
9
|
-
const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
10
|
-
image,
|
|
11
|
-
primary,
|
|
12
|
-
onIconClose,
|
|
13
|
-
}) => {
|
|
9
|
+
const PopupPromotion: React.FC<PopupPromotionProps> = ({image, primary}) => {
|
|
14
10
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
15
11
|
|
|
16
12
|
/**
|
package/Popup/types.ts
CHANGED
package/Radio/index.tsx
CHANGED
|
@@ -13,6 +13,7 @@ const Radio: FC<RadioProps> = ({
|
|
|
13
13
|
disabled,
|
|
14
14
|
onChange,
|
|
15
15
|
label,
|
|
16
|
+
style,
|
|
16
17
|
}) => {
|
|
17
18
|
const {theme} = useContext(ApplicationContext);
|
|
18
19
|
const selected = value === groupValue;
|
|
@@ -26,15 +27,22 @@ const Radio: FC<RadioProps> = ({
|
|
|
26
27
|
|
|
27
28
|
return (
|
|
28
29
|
<TouchableOpacity
|
|
29
|
-
onPress={
|
|
30
|
+
onPress={onChange}
|
|
30
31
|
disabled={disabled}
|
|
31
|
-
style={
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
style={[
|
|
33
|
+
style,
|
|
34
|
+
{
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
},
|
|
38
|
+
]}>
|
|
39
|
+
<View
|
|
40
|
+
style={[
|
|
41
|
+
styles.radio,
|
|
42
|
+
{borderWidth, borderColor, marginRight: !!label ? Spacing.XS : 0},
|
|
43
|
+
]}
|
|
44
|
+
/>
|
|
45
|
+
{!!label && <Text typography={'description_default'}>{label}</Text>}
|
|
38
46
|
</TouchableOpacity>
|
|
39
47
|
);
|
|
40
48
|
};
|
package/Radio/styles.ts
CHANGED
package/Radio/types.ts
CHANGED
package/Switch/index.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import {Colors} from '../Consts';
|
|
|
7
7
|
|
|
8
8
|
const Switch: FC<SwitchProps> = props => {
|
|
9
9
|
const {theme} = useContext(ApplicationContext);
|
|
10
|
-
const {value, onChange, disabled} = props;
|
|
10
|
+
const {value, onChange, disabled, style} = props;
|
|
11
11
|
const circleBackgroundColor = value ? Colors.black_01 : Colors.black_03;
|
|
12
12
|
const circleAlign = value ? 'flex-end' : 'flex-start';
|
|
13
13
|
|
|
@@ -20,7 +20,11 @@ const Switch: FC<SwitchProps> = props => {
|
|
|
20
20
|
<TouchableOpacity
|
|
21
21
|
disabled={disabled}
|
|
22
22
|
onPress={() => onChange?.(!value)}
|
|
23
|
-
style={[
|
|
23
|
+
style={[
|
|
24
|
+
style,
|
|
25
|
+
styles.container,
|
|
26
|
+
{backgroundColor, alignItems: circleAlign},
|
|
27
|
+
]}>
|
|
24
28
|
<View style={[styles.circle, {backgroundColor: circleBackgroundColor}]}>
|
|
25
29
|
<View style={[styles.circleSmall, {backgroundColor}]} />
|
|
26
30
|
</View>
|
package/Switch/types.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/foundation",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "React Native Component Kits",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"react-native-safe-area-context": "3.1.4",
|
|
14
|
-
"@react-navigation/bottom-tabs": "
|
|
14
|
+
"@react-navigation/bottom-tabs": "git+https://gitlab.com/dung.huynh1/react-navigation-bottom-tabs.git#main",
|
|
15
15
|
"@react-navigation/core": "5.16.1",
|
|
16
16
|
"@react-navigation/native": "5.9.8",
|
|
17
17
|
"@react-navigation/routers": "5.7.4",
|