@momo-kits/foundation 0.81.23 → 0.81.24
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 +1 -0
- package/Application/Components.tsx +28 -6
- package/Application/StackScreen.tsx +18 -5
- package/Application/types.ts +2 -0
- 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 +57 -0
- package/Badge/types.ts +65 -0
- package/Image/styles.ts +1 -4
- package/Layout/Card.tsx +16 -7
- package/Layout/styles.ts +1 -2
- package/Popup/PopupNotify.tsx +25 -34
- package/Popup/PopupPromotion.tsx +22 -27
- package/Popup/types.ts +9 -0
- package/Text/index.tsx +1 -0
- package/index.ts +2 -0
- package/package.json +1 -1
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
Fragment,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
Animated,
|
|
4
10
|
BackHandler,
|
|
@@ -23,6 +29,7 @@ import {
|
|
|
23
29
|
import {scaleSize, Text} from '../Text';
|
|
24
30
|
import {Icon} from '../Icon';
|
|
25
31
|
import {PopupNotify} from '../Popup';
|
|
32
|
+
import {Badge, BadgeDot} from '../Badge';
|
|
26
33
|
|
|
27
34
|
const styles = StyleSheet.create({
|
|
28
35
|
navigationButton: {
|
|
@@ -58,7 +65,6 @@ const styles = StyleSheet.create({
|
|
|
58
65
|
headerButton: {paddingHorizontal: 4},
|
|
59
66
|
headerRightButton: {
|
|
60
67
|
flexDirection: 'row',
|
|
61
|
-
overflow: 'hidden',
|
|
62
68
|
justifyContent: 'center',
|
|
63
69
|
alignItems: 'center',
|
|
64
70
|
paddingRight: Spacing.S,
|
|
@@ -86,6 +92,11 @@ const styles = StyleSheet.create({
|
|
|
86
92
|
lineHeight: scaleSize(22),
|
|
87
93
|
fontWeight: 'bold',
|
|
88
94
|
},
|
|
95
|
+
badge: {
|
|
96
|
+
position: 'absolute',
|
|
97
|
+
top: -6,
|
|
98
|
+
right: -6,
|
|
99
|
+
},
|
|
89
100
|
});
|
|
90
101
|
|
|
91
102
|
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
@@ -94,6 +105,8 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
94
105
|
onPress,
|
|
95
106
|
useBorder = true,
|
|
96
107
|
accessibilityLabel,
|
|
108
|
+
badgeType,
|
|
109
|
+
badgeValue,
|
|
97
110
|
}) => {
|
|
98
111
|
const {theme} = useContext(ApplicationContext);
|
|
99
112
|
let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
|
|
@@ -105,6 +118,14 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
105
118
|
};
|
|
106
119
|
}
|
|
107
120
|
|
|
121
|
+
const renderBadge = useCallback(() => {
|
|
122
|
+
if (!badgeValue && !badgeType) return null;
|
|
123
|
+
if (badgeType === 'dot') {
|
|
124
|
+
return <BadgeDot size="small" style={styles.badge} />;
|
|
125
|
+
}
|
|
126
|
+
return <Badge label={badgeValue} style={styles.badge} />;
|
|
127
|
+
}, [badgeType, badgeValue]);
|
|
128
|
+
|
|
108
129
|
return (
|
|
109
130
|
<TouchableOpacity
|
|
110
131
|
accessibilityLabel={`NavigationButton/${accessibilityLabel}`}
|
|
@@ -115,6 +136,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
115
136
|
color={tintColor ?? theme.colors.text.default}
|
|
116
137
|
size={20}
|
|
117
138
|
/>
|
|
139
|
+
{renderBadge()}
|
|
118
140
|
</TouchableOpacity>
|
|
119
141
|
);
|
|
120
142
|
};
|
|
@@ -159,9 +181,8 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
159
181
|
|
|
160
182
|
const goBack = () => {
|
|
161
183
|
const canGoBack = navigator?.ref.current?.canGoBack();
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (navigator?.trackingInfo) {
|
|
184
|
+
if (!canGoBack && navigator?.trackingInfo) {
|
|
185
|
+
const currentRoute = navigator?.ref?.current.getCurrentRoute();
|
|
165
186
|
navigator?.maxApi?.trackEvent('service_icon_clicked', {
|
|
166
187
|
feature_code: navigator.trackingInfo.code,
|
|
167
188
|
app_id: navigator.trackingInfo.appId,
|
|
@@ -172,7 +193,6 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
172
193
|
icon_name: 'back',
|
|
173
194
|
});
|
|
174
195
|
}
|
|
175
|
-
|
|
176
196
|
if (canGoBack) {
|
|
177
197
|
if (preventBack) {
|
|
178
198
|
navigator?.showModal({
|
|
@@ -247,6 +267,8 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
247
267
|
]}>
|
|
248
268
|
<StatusBar
|
|
249
269
|
barStyle={headerImage || theme.dark ? 'light-content' : 'dark-content'}
|
|
270
|
+
translucent={true}
|
|
271
|
+
backgroundColor={'transparent'}
|
|
250
272
|
/>
|
|
251
273
|
{!!headerImage && (
|
|
252
274
|
<Image
|
|
@@ -32,21 +32,34 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
32
32
|
*/
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
if (navigator?.trackingInfo) {
|
|
35
|
+
const tracking = {
|
|
36
|
+
feature_code: navigator.trackingInfo.code,
|
|
37
|
+
app_id: navigator.trackingInfo.appId,
|
|
38
|
+
miniapp_version: navigator.trackingInfo.buildNumber,
|
|
39
|
+
flow_partner_id: navigator.trackingInfo.flowPartnerId,
|
|
40
|
+
screen_name: Component.name,
|
|
41
|
+
};
|
|
42
|
+
|
|
35
43
|
const routes = props.navigation.getState()?.routes || [];
|
|
36
44
|
const routesLength = routes.length;
|
|
37
45
|
let pre_screen_name = '';
|
|
38
46
|
if (routesLength > 1) {
|
|
39
47
|
pre_screen_name = routes[routesLength - 2]?.params?.screen?.name;
|
|
40
48
|
}
|
|
49
|
+
|
|
41
50
|
navigator?.maxApi?.trackEvent('service_frame_displayed', {
|
|
42
|
-
|
|
43
|
-
app_id: navigator.trackingInfo.appId,
|
|
44
|
-
miniapp_version: navigator.trackingInfo.buildNumber,
|
|
45
|
-
flow_partner_id: navigator.trackingInfo.flowPartnerId,
|
|
46
|
-
screen_name: Component.name,
|
|
51
|
+
...tracking,
|
|
47
52
|
pre_screen_name,
|
|
48
53
|
trigger_id: '111378000000000000',
|
|
49
54
|
});
|
|
55
|
+
|
|
56
|
+
return props.navigation.addListener('beforeRemove', () => {
|
|
57
|
+
navigator?.maxApi?.trackEvent('service_icon_clicked', {
|
|
58
|
+
...tracking,
|
|
59
|
+
trigger_id: '111154000000000000',
|
|
60
|
+
icon_name: 'back',
|
|
61
|
+
});
|
|
62
|
+
});
|
|
50
63
|
}
|
|
51
64
|
}, []);
|
|
52
65
|
|
package/Application/types.ts
CHANGED
|
@@ -126,6 +126,8 @@ export type NavigationButtonProps = {
|
|
|
126
126
|
useBorder?: boolean;
|
|
127
127
|
onPress: () => void;
|
|
128
128
|
accessibilityLabel?: string;
|
|
129
|
+
badgeType?: 'dot' | 'number' | 'string';
|
|
130
|
+
badgeValue?: number | string;
|
|
129
131
|
};
|
|
130
132
|
|
|
131
133
|
export interface NavigationOptions extends StackNavigationOptions {
|
package/Badge/Badge.tsx
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
|
|
4
|
+
import {ApplicationContext} from '../Application';
|
|
5
|
+
import {BadgeProps} from './types';
|
|
6
|
+
import styles from './styles';
|
|
7
|
+
import {Colors} from '../Consts';
|
|
8
|
+
import {Text} from '../Text';
|
|
9
|
+
|
|
10
|
+
const Badge: FC<BadgeProps> = ({label = 'Label', style, backgroundColor}) => {
|
|
11
|
+
const {theme} = useContext(ApplicationContext);
|
|
12
|
+
|
|
13
|
+
const isValidatedColor = () => {
|
|
14
|
+
const colorKeys = Object.keys(Colors);
|
|
15
|
+
const colorValue = Object.values(Colors);
|
|
16
|
+
if (backgroundColor) {
|
|
17
|
+
const colorIndex = colorValue.indexOf(backgroundColor);
|
|
18
|
+
if (colorIndex !== -1) {
|
|
19
|
+
if (colorKeys[colorIndex]?.includes('_03')) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const isNumber = () => {
|
|
28
|
+
const numberRegex = /^\d+$/;
|
|
29
|
+
return numberRegex.test(String(label));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const formatTitle = () => {
|
|
33
|
+
if (isNumber() && Number(label) > 99) {
|
|
34
|
+
return '99+';
|
|
35
|
+
}
|
|
36
|
+
return label.toString();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let badgeColor = isNumber()
|
|
40
|
+
? theme.colors.error.primary
|
|
41
|
+
: theme.colors.warning.primary;
|
|
42
|
+
|
|
43
|
+
if (backgroundColor && isValidatedColor()) {
|
|
44
|
+
badgeColor = backgroundColor;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<View style={[style, styles.badge, {backgroundColor: badgeColor}]}>
|
|
49
|
+
<Text color={Colors.black_01} typography={'action_xxs'}>
|
|
50
|
+
{formatTitle()}
|
|
51
|
+
</Text>
|
|
52
|
+
</View>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default Badge;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, {FC} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import {BadgeDotProps} from './types';
|
|
4
|
+
import styles from './styles';
|
|
5
|
+
|
|
6
|
+
const BadgeDot: FC<BadgeDotProps> = ({size = 'large', style}) => {
|
|
7
|
+
const dotStyle = size === 'small' ? styles.dotSmall : styles.dot;
|
|
8
|
+
return <View style={[style, dotStyle]} />;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default BadgeDot;
|
|
@@ -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'}>
|
|
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'}>
|
|
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,57 @@
|
|
|
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
|
+
flexDirection: 'row',
|
|
13
|
+
borderWidth: 1,
|
|
14
|
+
borderColor: Colors.black_01,
|
|
15
|
+
alignSelf: 'baseline',
|
|
16
|
+
},
|
|
17
|
+
dot: {
|
|
18
|
+
width: 16,
|
|
19
|
+
height: 16,
|
|
20
|
+
borderWidth: 2,
|
|
21
|
+
borderColor: Colors.black_01,
|
|
22
|
+
backgroundColor: Colors.red_03,
|
|
23
|
+
borderRadius: 8,
|
|
24
|
+
},
|
|
25
|
+
dotSmall: {
|
|
26
|
+
width: 10,
|
|
27
|
+
height: 10,
|
|
28
|
+
borderWidth: 1,
|
|
29
|
+
borderColor: Colors.black_01,
|
|
30
|
+
backgroundColor: Colors.red_03,
|
|
31
|
+
borderRadius: 5,
|
|
32
|
+
},
|
|
33
|
+
ribbon: {
|
|
34
|
+
alignSelf: 'baseline',
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
height: 20,
|
|
37
|
+
overflow: 'hidden',
|
|
38
|
+
},
|
|
39
|
+
ribbonContent: {
|
|
40
|
+
height: 16,
|
|
41
|
+
justifyContent: 'center',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
borderBottomRightRadius: 12,
|
|
44
|
+
borderTopRightRadius: 12,
|
|
45
|
+
paddingRight: 6,
|
|
46
|
+
},
|
|
47
|
+
ribbonSkewContent: {
|
|
48
|
+
height: 16,
|
|
49
|
+
justifyContent: 'center',
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
},
|
|
52
|
+
ribbonLabel: {
|
|
53
|
+
color: Colors.black_01,
|
|
54
|
+
},
|
|
55
|
+
skew: {width: 8, height: 16},
|
|
56
|
+
tail: {width: 5, height: 20},
|
|
57
|
+
});
|
package/Badge/types.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {ViewStyle} from 'react-native';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines the types of badges that can be used. This helps in rendering the appropriate badge style.
|
|
5
|
+
*/
|
|
6
|
+
export type BadgeType = 'badge' | 'badge_number' | 'dot' | 'dot_small';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Props for a general Badge component. It can display a wide range of badges including simple labels, numbers, or dots.
|
|
10
|
+
*/
|
|
11
|
+
export type BadgeProps = {
|
|
12
|
+
/**
|
|
13
|
+
* Optional. The text to display on the badge. This could be a number or string, depending on the badge's purpose.
|
|
14
|
+
*/
|
|
15
|
+
label?: string | number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Optional. Custom styles to apply to the badge component. Can be a single style or an array of styles.
|
|
19
|
+
*/
|
|
20
|
+
style?: ViewStyle | ViewStyle[];
|
|
21
|
+
|
|
22
|
+
backgroundColor?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Props for a BadgeDot component. It specifically represents a dot-style badge, typically used for notification indicators.
|
|
27
|
+
*/
|
|
28
|
+
export type BadgeDotProps = {
|
|
29
|
+
/**
|
|
30
|
+
* Optional. The size of the dot, either 'small' or 'large'. This allows for better visual alignment with different UI elements.
|
|
31
|
+
*/
|
|
32
|
+
size?: 'small' | 'large';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Optional. Custom styles to apply to the badge dot component. Can be a single style or an array of styles.
|
|
36
|
+
*/
|
|
37
|
+
style?: ViewStyle | ViewStyle[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Props for a BadgeRibbon component. It represents a more specialized badge in the shape of a ribbon, allowing for placement around containers.
|
|
42
|
+
*/
|
|
43
|
+
export type BadgeRibbonProps = {
|
|
44
|
+
/**
|
|
45
|
+
* The text to display on the ribbon-style badge. Unlike other badges, ribbons typically carry more descriptive text.
|
|
46
|
+
*/
|
|
47
|
+
label: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Optional. Determines the placement of the ribbon on its parent container. The position can be any corner of the container.
|
|
51
|
+
* Defaults to 'top_right' if not specified.
|
|
52
|
+
*/
|
|
53
|
+
position?: 'top_right' | 'top_left' | 'bottom_right' | 'bottom_left';
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Optional. If true, the edges of the ribbon badge will be rounded. This is purely a stylistic choice.
|
|
57
|
+
* Defaults to `false` if not provided, resulting in a flat-edged ribbon.
|
|
58
|
+
*/
|
|
59
|
+
isRound?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Optional. Custom styles to apply to the ribbon badge component. Can be a single style or an array of styles.
|
|
63
|
+
*/
|
|
64
|
+
style?: ViewStyle | ViewStyle[];
|
|
65
|
+
};
|
package/Image/styles.ts
CHANGED
package/Layout/Card.tsx
CHANGED
|
@@ -140,6 +140,19 @@ const Card: React.FC<CardProps> = ({
|
|
|
140
140
|
const {theme} = useContext(ApplicationContext);
|
|
141
141
|
return (
|
|
142
142
|
<GridContext.Provider value={gridContext}>
|
|
143
|
+
{!!backgroundImage && (
|
|
144
|
+
<Image
|
|
145
|
+
source={{uri: backgroundImage}}
|
|
146
|
+
style={[
|
|
147
|
+
styles.imageBackground,
|
|
148
|
+
{
|
|
149
|
+
width: widthSection,
|
|
150
|
+
marginHorizontal: margin,
|
|
151
|
+
borderRadius: Spacing.M,
|
|
152
|
+
},
|
|
153
|
+
]}
|
|
154
|
+
/>
|
|
155
|
+
)}
|
|
143
156
|
<View
|
|
144
157
|
accessibilityLabel={`Card`}
|
|
145
158
|
style={[
|
|
@@ -149,16 +162,12 @@ const Card: React.FC<CardProps> = ({
|
|
|
149
162
|
{
|
|
150
163
|
width: widthSection,
|
|
151
164
|
marginHorizontal: margin,
|
|
152
|
-
backgroundColor:
|
|
165
|
+
backgroundColor: backgroundImage
|
|
166
|
+
? undefined
|
|
167
|
+
: theme.colors.background.surface,
|
|
153
168
|
},
|
|
154
169
|
useShadow && Shadow.Light,
|
|
155
170
|
]}>
|
|
156
|
-
{!!backgroundImage && (
|
|
157
|
-
<Image
|
|
158
|
-
source={{uri: backgroundImage}}
|
|
159
|
-
style={styles.imageBackground}
|
|
160
|
-
/>
|
|
161
|
-
)}
|
|
162
171
|
{renderView(validateChildren(children, [Item, ItemList]))}
|
|
163
172
|
{showGrid && renderOverlay()}
|
|
164
173
|
</View>
|
package/Layout/styles.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {StyleSheet} from 'react-native';
|
|
2
|
-
import {Radius
|
|
2
|
+
import {Radius} from '../Consts';
|
|
3
3
|
|
|
4
4
|
export default StyleSheet.create({
|
|
5
5
|
extendedHeader: {
|
|
@@ -63,7 +63,6 @@ export default StyleSheet.create({
|
|
|
63
63
|
bottom: 0,
|
|
64
64
|
left: 0,
|
|
65
65
|
right: 0,
|
|
66
|
-
borderRadius: Spacing.M,
|
|
67
66
|
},
|
|
68
67
|
protectedStyle: {
|
|
69
68
|
marginTop: undefined,
|
package/Popup/PopupNotify.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {Button} from '../Button';
|
|
|
9
9
|
import {Icon} from '../Icon';
|
|
10
10
|
|
|
11
11
|
const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
12
|
+
id,
|
|
12
13
|
image,
|
|
13
14
|
title = 'Title',
|
|
14
15
|
description = 'Description',
|
|
@@ -33,29 +34,6 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
33
34
|
* tracking
|
|
34
35
|
*/
|
|
35
36
|
useEffect(() => {
|
|
36
|
-
onTracking('service_component_displayed', undefined, '111012100000000000');
|
|
37
|
-
return () => {
|
|
38
|
-
onTracking(
|
|
39
|
-
'service_popup_dismissed',
|
|
40
|
-
closeAction.current,
|
|
41
|
-
'111154100000000001',
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
}, []);
|
|
45
|
-
/**
|
|
46
|
-
* on action popup
|
|
47
|
-
* @param callback
|
|
48
|
-
*/
|
|
49
|
-
const onAction = (callback?: () => void) => {
|
|
50
|
-
navigator?.pop();
|
|
51
|
-
callback?.();
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const onTracking = (
|
|
55
|
-
event: string,
|
|
56
|
-
actionType: string | undefined,
|
|
57
|
-
trigger_id: string,
|
|
58
|
-
) => {
|
|
59
37
|
if (navigator?.trackingInfo) {
|
|
60
38
|
const routes = navigator.ref.current?.getRootState()?.routes || [];
|
|
61
39
|
const routesLength = routes.length;
|
|
@@ -63,19 +41,37 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
63
41
|
if (routesLength > 1) {
|
|
64
42
|
screen_name = routes[routesLength - 2]?.params?.screen?.name;
|
|
65
43
|
}
|
|
66
|
-
|
|
44
|
+
const tracking = {
|
|
67
45
|
feature_code: navigator?.trackingInfo?.code,
|
|
68
46
|
app_id: navigator?.trackingInfo?.appId,
|
|
69
47
|
miniapp_version: navigator?.trackingInfo?.buildNumber,
|
|
70
48
|
flow_partner_id: navigator?.trackingInfo?.flowPartnerId,
|
|
71
49
|
screen_name,
|
|
72
50
|
component_type: 'popup',
|
|
73
|
-
component_name:
|
|
74
|
-
error_code: error,
|
|
75
|
-
|
|
76
|
-
|
|
51
|
+
component_name: id,
|
|
52
|
+
error_code: error ? error : undefined,
|
|
53
|
+
};
|
|
54
|
+
navigator?.maxApi?.trackEvent('service_component_displayed', {
|
|
55
|
+
...tracking,
|
|
56
|
+
trigger_id: '111012100000000000',
|
|
77
57
|
});
|
|
58
|
+
return () => {
|
|
59
|
+
navigator?.maxApi?.trackEvent('service_popup_dismissed', {
|
|
60
|
+
...tracking,
|
|
61
|
+
trigger_id: '111154100000000001',
|
|
62
|
+
action_type: closeAction.current,
|
|
63
|
+
});
|
|
64
|
+
};
|
|
78
65
|
}
|
|
66
|
+
}, []);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* on action popup
|
|
70
|
+
* @param callback
|
|
71
|
+
*/
|
|
72
|
+
const onAction = (callback?: () => void) => {
|
|
73
|
+
navigator?.pop();
|
|
74
|
+
callback?.();
|
|
79
75
|
};
|
|
80
76
|
|
|
81
77
|
/**
|
|
@@ -194,11 +190,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
194
190
|
styles.container,
|
|
195
191
|
{backgroundColor: theme.colors.background.surface},
|
|
196
192
|
]}>
|
|
197
|
-
{!!image &&
|
|
198
|
-
<View style={styles.image}>
|
|
199
|
-
<Image source={{uri: image}} />
|
|
200
|
-
</View>
|
|
201
|
-
)}
|
|
193
|
+
{!!image && <Image source={{uri: image}} style={styles.image} />}
|
|
202
194
|
<View style={styles.content}>
|
|
203
195
|
<Text typography={'title_xs'} numberOfLines={1}>
|
|
204
196
|
{title}
|
|
@@ -206,7 +198,6 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
206
198
|
<Description style={[styles.description, descriptionStyle]}>
|
|
207
199
|
<Text
|
|
208
200
|
typography={'paragraph_default'}
|
|
209
|
-
numberOfLines={4}
|
|
210
201
|
onTextLayout={({nativeEvent: {lines}}) => {
|
|
211
202
|
const enableScroll = lines.length > 3;
|
|
212
203
|
if (enableScroll != scrollContent) {
|
package/Popup/PopupPromotion.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {Radius, Spacing} from '../Consts';
|
|
|
7
7
|
import {Icon} from '../Icon';
|
|
8
8
|
|
|
9
9
|
const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
10
|
+
id,
|
|
10
11
|
image,
|
|
11
12
|
onIconClose,
|
|
12
13
|
}) => {
|
|
@@ -17,21 +18,6 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
|
17
18
|
* tracking
|
|
18
19
|
*/
|
|
19
20
|
useEffect(() => {
|
|
20
|
-
onTracking('service_component_displayed', undefined, '111012100000000000');
|
|
21
|
-
return () => {
|
|
22
|
-
onTracking(
|
|
23
|
-
'service_popup_dismissed',
|
|
24
|
-
closeAction.current,
|
|
25
|
-
'111154100000000001',
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
}, []);
|
|
29
|
-
|
|
30
|
-
const onTracking = (
|
|
31
|
-
event: string,
|
|
32
|
-
actionType: string | undefined,
|
|
33
|
-
trigger_id: string,
|
|
34
|
-
) => {
|
|
35
21
|
if (navigator?.trackingInfo) {
|
|
36
22
|
const routes = navigator.ref.current?.getRootState()?.routes || [];
|
|
37
23
|
const routesLength = routes.length;
|
|
@@ -39,19 +25,28 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
|
39
25
|
if (routesLength > 1) {
|
|
40
26
|
screen_name = routes[routesLength - 2]?.params?.screen?.name;
|
|
41
27
|
}
|
|
42
|
-
|
|
28
|
+
const tracking = {
|
|
43
29
|
feature_code: navigator?.trackingInfo?.code,
|
|
44
30
|
app_id: navigator?.trackingInfo?.appId,
|
|
45
31
|
miniapp_version: navigator?.trackingInfo?.buildNumber,
|
|
46
32
|
flow_partner_id: navigator?.trackingInfo?.flowPartnerId,
|
|
47
33
|
screen_name,
|
|
48
34
|
component_type: 'popup',
|
|
49
|
-
component_name:
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
component_name: id,
|
|
36
|
+
};
|
|
37
|
+
navigator?.maxApi?.trackEvent('service_component_displayed', {
|
|
38
|
+
...tracking,
|
|
39
|
+
trigger_id: '111012100000000000',
|
|
52
40
|
});
|
|
41
|
+
return () => {
|
|
42
|
+
navigator?.maxApi?.trackEvent('service_popup_dismissed', {
|
|
43
|
+
...tracking,
|
|
44
|
+
trigger_id: '111154100000000001',
|
|
45
|
+
action_type: closeAction.current,
|
|
46
|
+
});
|
|
47
|
+
};
|
|
53
48
|
}
|
|
54
|
-
};
|
|
49
|
+
}, []);
|
|
55
50
|
|
|
56
51
|
/**
|
|
57
52
|
* build close action
|
|
@@ -87,13 +82,12 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
|
87
82
|
|
|
88
83
|
return (
|
|
89
84
|
<View accessibilityLabel={'PopupPromotion'}>
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
</View>
|
|
85
|
+
<Image
|
|
86
|
+
source={{
|
|
87
|
+
uri: image,
|
|
88
|
+
}}
|
|
89
|
+
style={styles.container}
|
|
90
|
+
/>
|
|
97
91
|
{buildCloseIcon()}
|
|
98
92
|
</View>
|
|
99
93
|
);
|
|
@@ -102,6 +96,7 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
|
102
96
|
const styles = StyleSheet.create({
|
|
103
97
|
container: {
|
|
104
98
|
aspectRatio: 0.72,
|
|
99
|
+
width: '100%',
|
|
105
100
|
},
|
|
106
101
|
iconCloseContainer: {
|
|
107
102
|
width: '100%',
|
package/Popup/types.ts
CHANGED
|
@@ -2,6 +2,10 @@ import {TextStyle} from 'react-native';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
export type PopupNotifyProps = {
|
|
5
|
+
/**
|
|
6
|
+
* `id`: Optional. id component_name for tracking component.
|
|
7
|
+
*/
|
|
8
|
+
id?: string;
|
|
5
9
|
/**
|
|
6
10
|
* `image`: Optional. Represents the URL or path of the image to be displayed in the PopupNotify component.
|
|
7
11
|
*/
|
|
@@ -47,6 +51,11 @@ export type PopupNotifyProps = {
|
|
|
47
51
|
};
|
|
48
52
|
|
|
49
53
|
export type PopupPromotionProps = {
|
|
54
|
+
/**
|
|
55
|
+
* `id`: Optional. id component_name for tracking component.
|
|
56
|
+
*/
|
|
57
|
+
id?: string;
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* `image`: Represents the URL or path of the image to be displayed in the PopupPromotion component.
|
|
52
61
|
*/
|
package/Text/index.tsx
CHANGED
package/index.ts
CHANGED