@momo-kits/foundation 0.81.1-beta.5 → 0.81.1-optimize.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.tsx +76 -23
- package/Application/Components.tsx +243 -198
- package/Application/ModalScreen.tsx +20 -65
- package/Application/Navigation.ts +15 -4
- package/Application/NavigationContainer.tsx +20 -20
- package/Application/Navigator.ts +61 -28
- package/Application/StackScreen.tsx +41 -23
- package/Application/index.ts +16 -6
- package/Application/types.ts +34 -19
- package/Application/utils.tsx +26 -0
- package/Assets/icon.json +83 -5
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +3 -1
- package/Badge/Badge.tsx +56 -0
- package/Badge/BadgeDot.tsx +11 -0
- package/Badge/BadgeRibbon.tsx +125 -0
- package/Badge/Shape.tsx +29 -0
- package/Badge/index.tsx +7 -0
- package/Badge/styles.ts +58 -0
- package/Badge/types.ts +63 -0
- package/Button/index.tsx +26 -9
- package/Button/styles.ts +19 -0
- package/CheckBox/index.tsx +1 -2
- package/Consts/colors+spacing+radius.ts +3 -3
- package/Icon/index.tsx +7 -3
- package/Icon/types.ts +3 -3
- package/IconButton/index.tsx +0 -1
- package/Image/index.tsx +39 -49
- package/Image/styles.ts +1 -9
- package/Image/types.ts +3 -1
- package/Input/Input.tsx +37 -16
- package/Input/InputDropDown.tsx +5 -14
- package/Input/InputMoney.tsx +28 -11
- package/Input/InputOTP.tsx +169 -145
- package/Input/InputSearch.tsx +9 -13
- package/Input/InputTextArea.tsx +6 -12
- package/Input/common.tsx +5 -3
- package/Input/index.tsx +15 -9
- package/Input/styles.ts +1 -4
- package/Layout/Card.tsx +20 -11
- package/Layout/GridSystem.tsx +1 -2
- package/Layout/Item.tsx +0 -1
- package/Layout/ItemList.tsx +39 -40
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +96 -45
- package/Layout/Section.tsx +17 -19
- package/Layout/index.ts +2 -1
- package/Layout/styles.ts +16 -15
- package/Layout/types.ts +2 -5
- package/Pagination/PaginationNumber.tsx +1 -1
- package/Pagination/PaginationScroll.tsx +0 -1
- package/Popup/PopupNotify.tsx +71 -14
- package/Popup/PopupPromotion.tsx +43 -6
- package/Popup/types.ts +12 -3
- package/Radio/index.tsx +1 -2
- package/Skeleton/index.tsx +1 -1
- package/Switch/index.tsx +0 -1
- package/Tag/index.tsx +2 -4
- package/Text/index.tsx +3 -2
- package/Text/styles.ts +38 -0
- package/Text/types.ts +25 -13
- package/Title/index.tsx +82 -38
- package/Title/styles.ts +16 -10
- package/Title/types.ts +2 -1
- package/index.ts +2 -0
- package/package.json +6 -6
- package/verify.js +15 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import {DownTail, UpTail} from './Shape';
|
|
4
|
+
import styles from './styles';
|
|
5
|
+
import {BadgeRibbonProps} from './types';
|
|
6
|
+
import {ApplicationContext} from '../Application';
|
|
7
|
+
import {Text} from '../Text';
|
|
8
|
+
import {Colors} from '../Consts';
|
|
9
|
+
import {Image} from '../Image';
|
|
10
|
+
|
|
11
|
+
const BadgeRibbon: FC<BadgeRibbonProps> = ({
|
|
12
|
+
position = 'top_right',
|
|
13
|
+
label = 'Label',
|
|
14
|
+
isRound = false,
|
|
15
|
+
style = {},
|
|
16
|
+
}) => {
|
|
17
|
+
const {theme} = useContext(ApplicationContext);
|
|
18
|
+
let ribbonRotate = '0deg';
|
|
19
|
+
let textRotate = '0deg';
|
|
20
|
+
let ribbonTail = <DownTail />;
|
|
21
|
+
let textMargin = 0;
|
|
22
|
+
let skewMargin = 0;
|
|
23
|
+
|
|
24
|
+
if (position === 'top_right' || position === 'bottom_right') {
|
|
25
|
+
ribbonRotate = '180deg';
|
|
26
|
+
textRotate = '180deg';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (position === 'bottom_left' || position === 'top_right') {
|
|
30
|
+
textMargin = 4;
|
|
31
|
+
ribbonTail = <UpTail />;
|
|
32
|
+
skewMargin = 4;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const renderRoundContent = () => {
|
|
36
|
+
return (
|
|
37
|
+
<View
|
|
38
|
+
style={[
|
|
39
|
+
styles.ribbonContent,
|
|
40
|
+
{
|
|
41
|
+
backgroundColor: theme.colors.warning.primary,
|
|
42
|
+
marginTop: textMargin,
|
|
43
|
+
},
|
|
44
|
+
]}>
|
|
45
|
+
<Text
|
|
46
|
+
style={[
|
|
47
|
+
styles.ribbonLabel,
|
|
48
|
+
{
|
|
49
|
+
transform: [
|
|
50
|
+
{
|
|
51
|
+
rotate: textRotate,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
]}
|
|
56
|
+
color={Colors.black_01}
|
|
57
|
+
typography={'label_xs_medium'}>
|
|
58
|
+
{label}
|
|
59
|
+
</Text>
|
|
60
|
+
</View>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const renderSkewContent = () => {
|
|
65
|
+
return (
|
|
66
|
+
<View
|
|
67
|
+
style={{
|
|
68
|
+
flexDirection: 'row',
|
|
69
|
+
marginTop: skewMargin,
|
|
70
|
+
}}>
|
|
71
|
+
<View
|
|
72
|
+
style={[
|
|
73
|
+
styles.ribbonSkewContent,
|
|
74
|
+
{
|
|
75
|
+
backgroundColor: theme.colors.warning.primary,
|
|
76
|
+
},
|
|
77
|
+
]}>
|
|
78
|
+
<Text
|
|
79
|
+
style={[
|
|
80
|
+
styles.ribbonLabel,
|
|
81
|
+
{
|
|
82
|
+
transform: [
|
|
83
|
+
{
|
|
84
|
+
rotate: textRotate,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
]}
|
|
89
|
+
color={Colors.black_01}
|
|
90
|
+
typography={'label_xs_medium'}>
|
|
91
|
+
{label}
|
|
92
|
+
</Text>
|
|
93
|
+
</View>
|
|
94
|
+
<Image
|
|
95
|
+
source={{
|
|
96
|
+
uri: 'https://static.momocdn.net/app/img/kits/utils/Tail_4x.png',
|
|
97
|
+
}}
|
|
98
|
+
style={styles.skew}
|
|
99
|
+
/>
|
|
100
|
+
</View>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const content = isRound ? renderRoundContent() : renderSkewContent();
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<View
|
|
108
|
+
style={[
|
|
109
|
+
style,
|
|
110
|
+
styles.ribbon,
|
|
111
|
+
{
|
|
112
|
+
transform: [
|
|
113
|
+
{
|
|
114
|
+
rotate: ribbonRotate,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
]}>
|
|
119
|
+
{ribbonTail}
|
|
120
|
+
{content}
|
|
121
|
+
</View>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default BadgeRibbon;
|
package/Badge/Shape.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from './styles';
|
|
3
|
+
import {Image} from '../Image';
|
|
4
|
+
|
|
5
|
+
const UpTail = () => {
|
|
6
|
+
return (
|
|
7
|
+
<Image
|
|
8
|
+
resizeMode={'stretch'}
|
|
9
|
+
source={{
|
|
10
|
+
uri: 'https://static.momocdn.net/app/img/kits/utils/Head_down_4x.png',
|
|
11
|
+
}}
|
|
12
|
+
style={[styles.tail, {transform: [{rotate: '180deg'}]}]}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DownTail = () => {
|
|
18
|
+
return (
|
|
19
|
+
<Image
|
|
20
|
+
resizeMode={'stretch'}
|
|
21
|
+
source={{
|
|
22
|
+
uri: 'https://static.momocdn.net/app/img/kits/utils/Head_4x.png',
|
|
23
|
+
}}
|
|
24
|
+
style={styles.tail}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export {UpTail, DownTail};
|
package/Badge/index.tsx
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Badge from './Badge';
|
|
2
|
+
import BadgeDot from './BadgeDot';
|
|
3
|
+
import BadgeRibbon from './BadgeRibbon';
|
|
4
|
+
import {BadgeProps, BadgeDotProps, BadgeRibbonProps} from './types';
|
|
5
|
+
|
|
6
|
+
export {Badge, BadgeRibbon, BadgeDot};
|
|
7
|
+
export type {BadgeProps, BadgeDotProps, BadgeRibbonProps};
|
package/Badge/styles.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {Colors, Radius, Spacing} from '../Consts';
|
|
3
|
+
import {scaleSize} from '../Text';
|
|
4
|
+
|
|
5
|
+
export default StyleSheet.create({
|
|
6
|
+
badge: {
|
|
7
|
+
paddingHorizontal: Spacing.XS,
|
|
8
|
+
borderRadius: Radius.M,
|
|
9
|
+
justifyContent: 'center',
|
|
10
|
+
alignItems: 'center',
|
|
11
|
+
height: scaleSize(16),
|
|
12
|
+
minWidth: scaleSize(16),
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
borderWidth: 1,
|
|
15
|
+
borderColor: Colors.black_01,
|
|
16
|
+
alignSelf: 'baseline',
|
|
17
|
+
},
|
|
18
|
+
dot: {
|
|
19
|
+
width: 16,
|
|
20
|
+
height: 16,
|
|
21
|
+
borderWidth: 2,
|
|
22
|
+
borderColor: Colors.black_01,
|
|
23
|
+
backgroundColor: Colors.red_03,
|
|
24
|
+
borderRadius: 8,
|
|
25
|
+
},
|
|
26
|
+
dotSmall: {
|
|
27
|
+
width: 10,
|
|
28
|
+
height: 10,
|
|
29
|
+
borderWidth: 1,
|
|
30
|
+
borderColor: Colors.black_01,
|
|
31
|
+
backgroundColor: Colors.red_03,
|
|
32
|
+
borderRadius: 5,
|
|
33
|
+
},
|
|
34
|
+
ribbon: {
|
|
35
|
+
alignSelf: 'baseline',
|
|
36
|
+
flexDirection: 'row',
|
|
37
|
+
height: 20,
|
|
38
|
+
overflow: 'hidden',
|
|
39
|
+
},
|
|
40
|
+
ribbonContent: {
|
|
41
|
+
height: 16,
|
|
42
|
+
justifyContent: 'center',
|
|
43
|
+
alignItems: 'center',
|
|
44
|
+
borderBottomRightRadius: 12,
|
|
45
|
+
borderTopRightRadius: 12,
|
|
46
|
+
paddingRight: 6,
|
|
47
|
+
},
|
|
48
|
+
ribbonSkewContent: {
|
|
49
|
+
height: 16,
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
},
|
|
53
|
+
ribbonLabel: {
|
|
54
|
+
color: Colors.black_01,
|
|
55
|
+
},
|
|
56
|
+
skew: {width: 8, height: 16},
|
|
57
|
+
tail: {width: 5, height: 20},
|
|
58
|
+
});
|
package/Badge/types.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {ViewStyle} from 'react-native';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Props for a general Badge component. It can display a wide range of badges including simple labels, numbers, or dots.
|
|
5
|
+
*/
|
|
6
|
+
export type BadgeProps = {
|
|
7
|
+
/**
|
|
8
|
+
* Optional. The text to display on the badge. This could be a number or string, depending on the badge's purpose.
|
|
9
|
+
*/
|
|
10
|
+
label?: string | number;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Optional. Custom styles to apply to the badge component. Can be a single style or an array of styles.
|
|
14
|
+
*/
|
|
15
|
+
style?: ViewStyle | ViewStyle[];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Optional. Custom background badge.
|
|
19
|
+
*/
|
|
20
|
+
backgroundColor?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Props for a BadgeDot component. It specifically represents a dot-style badge, typically used for notification indicators.
|
|
25
|
+
*/
|
|
26
|
+
export type BadgeDotProps = {
|
|
27
|
+
/**
|
|
28
|
+
* Optional. The size of the dot, either 'small' or 'large'. This allows for better visual alignment with different UI elements.
|
|
29
|
+
*/
|
|
30
|
+
size?: 'small' | 'large';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Optional. Custom styles to apply to the badge dot component. Can be a single style or an array of styles.
|
|
34
|
+
*/
|
|
35
|
+
style?: ViewStyle | ViewStyle[];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Props for a BadgeRibbon component. It represents a more specialized badge in the shape of a ribbon, allowing for placement around containers.
|
|
40
|
+
*/
|
|
41
|
+
export type BadgeRibbonProps = {
|
|
42
|
+
/**
|
|
43
|
+
* The text to display on the ribbon-style badge. Unlike other badges, ribbons typically carry more descriptive text.
|
|
44
|
+
*/
|
|
45
|
+
label: string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Optional. Determines the placement of the ribbon on its parent container. The position can be any corner of the container.
|
|
49
|
+
* Defaults to 'top_right' if not specified.
|
|
50
|
+
*/
|
|
51
|
+
position?: 'top_right' | 'top_left' | 'bottom_right' | 'bottom_left';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Optional. If true, the edges of the ribbon badge will be rounded. This is purely a stylistic choice.
|
|
55
|
+
* Defaults to `false` if not provided, resulting in a flat-edged ribbon.
|
|
56
|
+
*/
|
|
57
|
+
isRound?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Optional. Custom styles to apply to the ribbon badge component. Can be a single style or an array of styles.
|
|
61
|
+
*/
|
|
62
|
+
style?: ViewStyle | ViewStyle[];
|
|
63
|
+
};
|
package/Button/index.tsx
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React, {FC, useContext} from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Animated,
|
|
3
4
|
StyleSheet,
|
|
4
5
|
TouchableOpacity,
|
|
5
6
|
TouchableOpacityProps,
|
|
6
7
|
View,
|
|
7
8
|
} from 'react-native';
|
|
9
|
+
|
|
10
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
8
11
|
import {ApplicationContext} from '../Application';
|
|
9
12
|
import {Text} from '../Text';
|
|
10
13
|
import {Typography} from '../Text/types';
|
|
@@ -13,6 +16,8 @@ import styles from './styles';
|
|
|
13
16
|
import {Icon} from '../Icon';
|
|
14
17
|
import {Loader} from '../Loader';
|
|
15
18
|
|
|
19
|
+
const AnimationLinear = Animated.createAnimatedComponent(LinearGradient);
|
|
20
|
+
|
|
16
21
|
export interface ButtonProps extends TouchableOpacityProps {
|
|
17
22
|
/**
|
|
18
23
|
* Defines the visual style of the button.
|
|
@@ -79,7 +84,16 @@ const Button: FC<ButtonProps> = ({
|
|
|
79
84
|
onPress,
|
|
80
85
|
...rest
|
|
81
86
|
}) => {
|
|
82
|
-
const {theme} = useContext(ApplicationContext);
|
|
87
|
+
const {theme, config} = useContext(ApplicationContext);
|
|
88
|
+
const {gradient, color} = config?.navigationBar?.buttonColors ?? {};
|
|
89
|
+
let gradientPros;
|
|
90
|
+
if (gradient?.length > 0 && type == 'primary') {
|
|
91
|
+
gradientPros = {
|
|
92
|
+
colors: gradient,
|
|
93
|
+
start: {x: 1, y: 0.5},
|
|
94
|
+
end: {x: 0, y: 0.5},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
83
97
|
const getSizeStyle = () => {
|
|
84
98
|
const styleSheet: {[key: string]: any} = styles;
|
|
85
99
|
return styleSheet[size ?? 'small'];
|
|
@@ -103,7 +117,7 @@ const Button: FC<ButtonProps> = ({
|
|
|
103
117
|
return {
|
|
104
118
|
backgroundColor: theme.colors.background.surface,
|
|
105
119
|
borderWidth: 1,
|
|
106
|
-
borderColor: theme.colors.primary,
|
|
120
|
+
borderColor: color ?? theme.colors.primary,
|
|
107
121
|
};
|
|
108
122
|
case 'tonal':
|
|
109
123
|
return {
|
|
@@ -158,14 +172,14 @@ const Button: FC<ButtonProps> = ({
|
|
|
158
172
|
const getTypography = (): Typography => {
|
|
159
173
|
switch (size) {
|
|
160
174
|
case 'large':
|
|
161
|
-
return '
|
|
175
|
+
return 'action_default_bold';
|
|
162
176
|
case 'medium':
|
|
163
|
-
return '
|
|
177
|
+
return 'action_s_bold';
|
|
164
178
|
case 'small':
|
|
165
|
-
return '
|
|
179
|
+
return 'action_xs_bold';
|
|
166
180
|
|
|
167
181
|
default:
|
|
168
|
-
return '
|
|
182
|
+
return 'action_default_bold';
|
|
169
183
|
}
|
|
170
184
|
};
|
|
171
185
|
|
|
@@ -178,13 +192,13 @@ const Button: FC<ButtonProps> = ({
|
|
|
178
192
|
case 'secondary':
|
|
179
193
|
return theme.colors.text.default;
|
|
180
194
|
case 'outline':
|
|
181
|
-
return theme.colors.primary;
|
|
195
|
+
return color ?? theme.colors.primary;
|
|
182
196
|
case 'tonal':
|
|
183
197
|
return theme.colors.primary;
|
|
184
198
|
case 'danger':
|
|
185
199
|
return Colors.black_01;
|
|
186
200
|
case 'text':
|
|
187
|
-
return theme.colors.primary;
|
|
201
|
+
return color ?? theme.colors.primary;
|
|
188
202
|
default:
|
|
189
203
|
return Colors.black_01;
|
|
190
204
|
}
|
|
@@ -279,13 +293,16 @@ const Button: FC<ButtonProps> = ({
|
|
|
279
293
|
return (
|
|
280
294
|
<TouchableOpacity
|
|
281
295
|
{...rest}
|
|
282
|
-
accessibilityLabel={`Button/${title}`}
|
|
283
296
|
activeOpacity={activeOpacity}
|
|
284
297
|
onPress={onPressButton}
|
|
285
298
|
style={buttonStyle}>
|
|
286
299
|
{renderLeading()}
|
|
287
300
|
{renderTitle()}
|
|
288
301
|
{renderTrailing()}
|
|
302
|
+
{gradientPros && (
|
|
303
|
+
<AnimationLinear {...gradientPros} style={styles.gradientView} />
|
|
304
|
+
)}
|
|
305
|
+
{gradientPros && <View style={styles.strokeView} />}
|
|
289
306
|
</TouchableOpacity>
|
|
290
307
|
);
|
|
291
308
|
};
|
package/Button/styles.ts
CHANGED
|
@@ -38,4 +38,23 @@ export default StyleSheet.create({
|
|
|
38
38
|
alignItems: 'center',
|
|
39
39
|
justifyContent: 'center',
|
|
40
40
|
},
|
|
41
|
+
gradientView: {
|
|
42
|
+
position: 'absolute',
|
|
43
|
+
zIndex: -1,
|
|
44
|
+
borderRadius: 8,
|
|
45
|
+
top: 0,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
left: 0,
|
|
48
|
+
right: 0,
|
|
49
|
+
},
|
|
50
|
+
strokeView: {
|
|
51
|
+
position: 'absolute',
|
|
52
|
+
top: 2,
|
|
53
|
+
bottom: 2,
|
|
54
|
+
left: 2,
|
|
55
|
+
right: 2,
|
|
56
|
+
borderRadius: 6,
|
|
57
|
+
borderWidth: 0.5,
|
|
58
|
+
borderColor: '#FFF9E1',
|
|
59
|
+
},
|
|
41
60
|
});
|
package/CheckBox/index.tsx
CHANGED
|
@@ -36,7 +36,6 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
38
|
<TouchableOpacity
|
|
39
|
-
accessibilityLabel={`CheckBox/${label}/${value}`}
|
|
40
39
|
activeOpacity={0.8}
|
|
41
40
|
onPress={() => onChange?.(!value)}
|
|
42
41
|
disabled={disabled}
|
|
@@ -54,7 +53,7 @@ const CheckBox: FC<CheckBoxProps> = ({
|
|
|
54
53
|
/>
|
|
55
54
|
)}
|
|
56
55
|
</View>
|
|
57
|
-
{!!label && <Text typography={'
|
|
56
|
+
{!!label && <Text typography={'body_default_regular'}>{label}</Text>}
|
|
58
57
|
</TouchableOpacity>
|
|
59
58
|
);
|
|
60
59
|
};
|
package/Icon/index.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import IconSources from '../Assets/icon.json';
|
|
3
|
+
import IconBankSources from '../Assets/icon_bank.json';
|
|
3
4
|
import {IconProps} from './types';
|
|
4
5
|
import {ApplicationContext} from '../Application';
|
|
5
6
|
import {Image} from '../Image';
|
|
@@ -18,13 +19,16 @@ const Icon: React.FC<IconProps> = ({source, size, color, style = {}}) => {
|
|
|
18
19
|
return {uri: source};
|
|
19
20
|
};
|
|
20
21
|
|
|
22
|
+
const tintColorProps = color !== null && {
|
|
23
|
+
tintColor: color ?? theme.colors.text.default
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
return (
|
|
22
27
|
<Image
|
|
23
|
-
accessibilityLabel={`Icon/${getIconSource()?.uri}`}
|
|
24
28
|
loading={false}
|
|
25
29
|
source={getIconSource()}
|
|
26
30
|
style={[style, {width: size, height: size}]}
|
|
27
|
-
|
|
31
|
+
{...tintColorProps}
|
|
28
32
|
/>
|
|
29
33
|
);
|
|
30
34
|
};
|
|
@@ -34,4 +38,4 @@ Icon.defaultProps = {
|
|
|
34
38
|
size: 24,
|
|
35
39
|
};
|
|
36
40
|
|
|
37
|
-
export {Icon, IconSources};
|
|
41
|
+
export {Icon, IconSources, IconBankSources};
|
package/Icon/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ImageStyle} from 'react-native-fast-image';
|
|
2
2
|
|
|
3
3
|
export type IconProps = {
|
|
4
4
|
/**
|
|
@@ -17,11 +17,11 @@ export type IconProps = {
|
|
|
17
17
|
* Optional. Represents the color of the icon.
|
|
18
18
|
* It can be any valid color in @momo-kits/foundation.
|
|
19
19
|
*/
|
|
20
|
-
color?: string;
|
|
20
|
+
color?: string | null;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Optional. Used to apply custom styling to the Icon component.
|
|
24
24
|
* Accepts an object of style properties.
|
|
25
25
|
*/
|
|
26
|
-
style?:
|
|
26
|
+
style?: ImageStyle;
|
|
27
27
|
};
|
package/IconButton/index.tsx
CHANGED
package/Image/index.tsx
CHANGED
|
@@ -1,87 +1,77 @@
|
|
|
1
1
|
import React, {useContext, useRef, useState} from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {StyleSheet, View} from 'react-native';
|
|
3
3
|
import FastImage from 'react-native-fast-image';
|
|
4
4
|
import styles from './styles';
|
|
5
5
|
import {ApplicationContext} from '../Application';
|
|
6
6
|
import {Skeleton} from '../Skeleton';
|
|
7
7
|
import {Icon} from '../Icon';
|
|
8
8
|
import {Styles} from '../Consts';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
export interface ImageProps extends FastImagePropsWithoutStyle {
|
|
12
|
-
style?: StyleProp<ViewStyle>;
|
|
13
|
-
loading?: boolean;
|
|
14
|
-
accessibilityLabel?: string;
|
|
15
|
-
}
|
|
9
|
+
import {ImageProps} from './types';
|
|
16
10
|
|
|
17
11
|
type Status = 'success' | 'loading' | 'error';
|
|
18
12
|
|
|
19
13
|
const Image: React.FC<ImageProps> = ({
|
|
20
14
|
style,
|
|
21
15
|
source,
|
|
22
|
-
|
|
16
|
+
loading,
|
|
17
|
+
children,
|
|
23
18
|
...rest
|
|
24
19
|
}) => {
|
|
25
20
|
const {theme} = useContext(ApplicationContext);
|
|
26
21
|
const error = useRef(false);
|
|
27
|
-
const [status, setStatus] = useState<Status>(
|
|
28
|
-
rest.loading ? 'loading' : 'success',
|
|
29
|
-
);
|
|
22
|
+
const [status, setStatus] = useState<Status>('success');
|
|
30
23
|
|
|
31
24
|
/**
|
|
32
25
|
* render content loading | fail | rendered
|
|
33
26
|
*/
|
|
34
27
|
const renderContent = () => {
|
|
35
|
-
if (status
|
|
36
|
-
let content =
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
if (status == 'error') {
|
|
28
|
+
if (status === 'loading' || status === 'error') {
|
|
29
|
+
let content = <Skeleton />;
|
|
30
|
+
if (status === 'error') {
|
|
40
31
|
content = (
|
|
41
|
-
<
|
|
42
|
-
<Icon source="media_fail" color={theme.colors.text.disable} />
|
|
43
|
-
</View>
|
|
32
|
+
<Icon source="media_fail" color={theme.colors.text.disable} />
|
|
44
33
|
);
|
|
45
34
|
}
|
|
46
35
|
return (
|
|
47
|
-
<View
|
|
48
|
-
style={[
|
|
49
|
-
StyleSheet.absoluteFill,
|
|
50
|
-
styles.image,
|
|
51
|
-
{backgroundColor: theme.colors.background.disable},
|
|
52
|
-
]}>
|
|
36
|
+
<View style={[StyleSheet.absoluteFill, Styles.flexCenter]}>
|
|
53
37
|
{content}
|
|
54
38
|
</View>
|
|
55
39
|
);
|
|
56
40
|
}
|
|
41
|
+
return children;
|
|
57
42
|
};
|
|
58
43
|
|
|
59
44
|
return (
|
|
60
|
-
<
|
|
45
|
+
<FastImage
|
|
46
|
+
{...rest}
|
|
47
|
+
source={source}
|
|
61
48
|
style={[styles.container, style]}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
49
|
+
onProgress={() => {
|
|
50
|
+
error.current = false;
|
|
51
|
+
if (status !== 'loading' && loading) {
|
|
52
|
+
setStatus('loading');
|
|
53
|
+
}
|
|
54
|
+
}}
|
|
55
|
+
onLoadStart={() => {
|
|
56
|
+
error.current = false;
|
|
57
|
+
}}
|
|
58
|
+
onLoad={() => {
|
|
59
|
+
error.current = false;
|
|
60
|
+
}}
|
|
61
|
+
onLoadEnd={() => {
|
|
62
|
+
let current: Status = 'success';
|
|
63
|
+
if (error.current) {
|
|
64
|
+
current = 'error';
|
|
65
|
+
}
|
|
66
|
+
if (status !== current) {
|
|
67
|
+
setStatus(current);
|
|
68
|
+
}
|
|
69
|
+
}}
|
|
70
|
+
onError={() => {
|
|
71
|
+
error.current = true;
|
|
72
|
+
}}>
|
|
83
73
|
{renderContent()}
|
|
84
|
-
</
|
|
74
|
+
</FastImage>
|
|
85
75
|
);
|
|
86
76
|
};
|
|
87
77
|
|
package/Image/styles.ts
CHANGED
package/Image/types.ts
CHANGED