@momo-kits/foundation 0.102.6-beta.6 → 0.102.6-beta.7
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/Components.tsx +11 -0
- package/Application/StackScreen.tsx +96 -95
- package/Application/types.ts +2 -2
- package/Badge/BadgeDotAnimation.tsx +5 -32
- package/Badge/index.tsx +2 -1
- package/Badge/styles.ts +50 -6
- package/package.json +1 -1
|
@@ -35,6 +35,7 @@ import {Badge, BadgeDot} from '../Badge';
|
|
|
35
35
|
import {HeaderType} from '../Layout/types';
|
|
36
36
|
import Navigation from './Navigation';
|
|
37
37
|
import {InputRef, InputSearch, InputSearchProps} from '../Input';
|
|
38
|
+
import {BadgeDotAnimation} from '../Badge';
|
|
38
39
|
|
|
39
40
|
const SCREEN_PADDING = 12;
|
|
40
41
|
const BACK_WIDTH = 28;
|
|
@@ -71,6 +72,11 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
71
72
|
if (badgeType === 'dot') {
|
|
72
73
|
return <BadgeDot size="small" style={styles.badgeDot} />;
|
|
73
74
|
}
|
|
75
|
+
if (badgeType === 'dot-animation') {
|
|
76
|
+
return (
|
|
77
|
+
<BadgeDotAnimation size="small" style={styles.badgeDotAnimation} />
|
|
78
|
+
);
|
|
79
|
+
}
|
|
74
80
|
|
|
75
81
|
if (isNumber(badgeValue)) {
|
|
76
82
|
return <Badge label={badgeValue} style={styles.badge} />;
|
|
@@ -763,6 +769,11 @@ const styles = StyleSheet.create({
|
|
|
763
769
|
top: -Spacing.XS,
|
|
764
770
|
right: -Spacing.XS,
|
|
765
771
|
},
|
|
772
|
+
badgeDotAnimation: {
|
|
773
|
+
position: 'absolute',
|
|
774
|
+
top: -Spacing.XS,
|
|
775
|
+
right: -Spacing.XS,
|
|
776
|
+
},
|
|
766
777
|
extendedHeader: {
|
|
767
778
|
aspectRatio: 1.75,
|
|
768
779
|
position: 'absolute',
|
|
@@ -8,6 +8,80 @@ import {GridSystem} from '../Layout';
|
|
|
8
8
|
import {Text} from '../Text';
|
|
9
9
|
import {Colors, Radius, Spacing} from '../Consts';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Empty screen for unvalidated screen name
|
|
13
|
+
* @constructor
|
|
14
|
+
*/
|
|
15
|
+
const EmptyScreen: React.FC = () => {
|
|
16
|
+
return (
|
|
17
|
+
<View
|
|
18
|
+
style={{
|
|
19
|
+
backgroundColor: Colors.black_01,
|
|
20
|
+
padding: Spacing.M,
|
|
21
|
+
borderRadius: Radius.M,
|
|
22
|
+
}}>
|
|
23
|
+
<Text typography={'header_m_bold'}>Unvalidated screen name</Text>
|
|
24
|
+
<Text
|
|
25
|
+
typography={'description_default_regular'}
|
|
26
|
+
style={{paddingVertical: Spacing.S}}>
|
|
27
|
+
Your screen has not been rendered because Platform has not detected the
|
|
28
|
+
screen name. Please migrate to support this feature.
|
|
29
|
+
</Text>
|
|
30
|
+
<Text typography={'header_default'} style={{width: '100%'}}>
|
|
31
|
+
Possible fixes:
|
|
32
|
+
</Text>
|
|
33
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
34
|
+
<Text typography={'body_default_regular'}>1. Off webpack config</Text>
|
|
35
|
+
<Text typography={'body_default_regular'}>
|
|
36
|
+
2. Screen name refactoring
|
|
37
|
+
</Text>
|
|
38
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
39
|
+
<Text
|
|
40
|
+
typography={'description_default_regular'}
|
|
41
|
+
style={{marginBottom: Spacing.S}}>
|
|
42
|
+
- Với các screen push/import dạng arrow function ={'>'} đổi thành
|
|
43
|
+
named function
|
|
44
|
+
</Text>
|
|
45
|
+
<Text
|
|
46
|
+
typography={'description_default_regular'}
|
|
47
|
+
style={{marginBottom: Spacing.S}}>
|
|
48
|
+
- Với các screen import dạng High Order Component ={'>'} rename
|
|
49
|
+
generic function thành named function
|
|
50
|
+
</Text>
|
|
51
|
+
<Text
|
|
52
|
+
typography={'description_default_regular'}
|
|
53
|
+
style={{marginBottom: Spacing.S}}>
|
|
54
|
+
- Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
|
|
55
|
+
Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
|
|
56
|
+
khảo theo docs
|
|
57
|
+
</Text>
|
|
58
|
+
</View>
|
|
59
|
+
</View>
|
|
60
|
+
<Text typography={'header_s_semibold'}>More information: </Text>
|
|
61
|
+
<Text
|
|
62
|
+
typography={'body_default_regular'}
|
|
63
|
+
color={Colors.blue_01}
|
|
64
|
+
onPress={() => {
|
|
65
|
+
Linking.openURL(
|
|
66
|
+
'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
|
|
67
|
+
);
|
|
68
|
+
}}>
|
|
69
|
+
Mini App: vn.momo.uikits/dev
|
|
70
|
+
</Text>
|
|
71
|
+
<Text
|
|
72
|
+
typography={'body_default_regular'}
|
|
73
|
+
color={Colors.blue_01}
|
|
74
|
+
onPress={() => {
|
|
75
|
+
Linking.openURL(
|
|
76
|
+
'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
|
|
77
|
+
);
|
|
78
|
+
}}>
|
|
79
|
+
https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
|
|
80
|
+
</Text>
|
|
81
|
+
</View>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
11
85
|
/**
|
|
12
86
|
* container for stack screen
|
|
13
87
|
* @param props
|
|
@@ -25,6 +99,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
25
99
|
traceIdInteraction: undefined,
|
|
26
100
|
releaseLoad: undefined,
|
|
27
101
|
releaseInteraction: undefined,
|
|
102
|
+
timeoutLoad: undefined,
|
|
103
|
+
timeoutInteraction: undefined,
|
|
28
104
|
});
|
|
29
105
|
const interaction = useRef<any>();
|
|
30
106
|
const context = useContext<any>(MiniAppContext);
|
|
@@ -59,6 +135,15 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
59
135
|
};
|
|
60
136
|
}
|
|
61
137
|
navigation.setOptions(defaultOptions);
|
|
138
|
+
navigator?.maxApi?.startTraceScreenLoad?.(screenName, (data: any) => {
|
|
139
|
+
tracked.current.traceIdLoad = data?.traceId;
|
|
140
|
+
});
|
|
141
|
+
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
142
|
+
screenName,
|
|
143
|
+
(data: any) => {
|
|
144
|
+
tracked.current.traceIdInteraction = data?.traceId;
|
|
145
|
+
}
|
|
146
|
+
);
|
|
62
147
|
}, [options]);
|
|
63
148
|
|
|
64
149
|
/**
|
|
@@ -71,22 +156,16 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
71
156
|
}, 300);
|
|
72
157
|
}
|
|
73
158
|
navigator?.maxApi?.of?.({screenName});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
tracked.current.traceIdLoad = data?.traceId;
|
|
82
|
-
});
|
|
83
|
-
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
84
|
-
screenName,
|
|
85
|
-
(data: any) => {
|
|
86
|
-
tracked.current.traceIdInteraction = data?.traceId;
|
|
87
|
-
}
|
|
88
|
-
);
|
|
159
|
+
tracked.current.timeoutLoad = setTimeout(() => {
|
|
160
|
+
onScreenLoad();
|
|
161
|
+
}, 5000);
|
|
162
|
+
tracked.current.timeoutInteraction = setTimeout(() => {
|
|
163
|
+
onScreenInteraction();
|
|
164
|
+
}, 5000);
|
|
165
|
+
|
|
89
166
|
return () => {
|
|
167
|
+
clearTimeout(tracked.current.timeoutLoad);
|
|
168
|
+
clearTimeout(tracked.current.timeoutInteraction);
|
|
90
169
|
onScreenLoad();
|
|
91
170
|
onScreenInteraction();
|
|
92
171
|
};
|
|
@@ -122,9 +201,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
122
201
|
* debug
|
|
123
202
|
*/
|
|
124
203
|
navigator?.maxApi?.showToastDebug?.({
|
|
125
|
-
appId: context.appId
|
|
204
|
+
appId: `auto - ${context.appId}`,
|
|
126
205
|
message: `${screenName} screen_load_time ${timeLoad.current}`,
|
|
127
|
-
type: 'ERROR',
|
|
128
206
|
});
|
|
129
207
|
if (timeLoad.current <= 0 && context.enableAutoId) {
|
|
130
208
|
Alert.alert(screenName, "Can't get screen load time");
|
|
@@ -164,9 +242,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
164
242
|
* debug toast
|
|
165
243
|
*/
|
|
166
244
|
navigator?.maxApi?.showToastDebug?.({
|
|
167
|
-
appId: context.appId
|
|
245
|
+
appId: `auto - ${context.appId}`,
|
|
168
246
|
message: `${screenName} screen_interaction_time ${timeInteraction.current}`,
|
|
169
|
-
type: 'ERROR',
|
|
170
247
|
});
|
|
171
248
|
if (timeInteraction.current <= 0 && context.enableAutoId) {
|
|
172
249
|
Alert.alert(screenName, "Can't get screen interaction time");
|
|
@@ -189,8 +266,6 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
189
266
|
if (timeLoad.current === 0) {
|
|
190
267
|
timeLoad.current = endTime.current - startTime.current;
|
|
191
268
|
}
|
|
192
|
-
onScreenLoad();
|
|
193
|
-
onScreenInteraction();
|
|
194
269
|
}, 2000);
|
|
195
270
|
},
|
|
196
271
|
}}>
|
|
@@ -205,78 +280,4 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
205
280
|
);
|
|
206
281
|
};
|
|
207
282
|
|
|
208
|
-
/**
|
|
209
|
-
* Empty screen for unvalidated screen name
|
|
210
|
-
* @constructor
|
|
211
|
-
*/
|
|
212
|
-
const EmptyScreen: React.FC = () => {
|
|
213
|
-
return (
|
|
214
|
-
<View
|
|
215
|
-
style={{
|
|
216
|
-
backgroundColor: Colors.black_01,
|
|
217
|
-
padding: Spacing.M,
|
|
218
|
-
borderRadius: Radius.M,
|
|
219
|
-
}}>
|
|
220
|
-
<Text typography={'header_m_bold'}>Unvalidated screen name</Text>
|
|
221
|
-
<Text
|
|
222
|
-
typography={'description_default_regular'}
|
|
223
|
-
style={{paddingVertical: Spacing.S}}>
|
|
224
|
-
Your screen has not been rendered because Platform has not detected the
|
|
225
|
-
screen name. Please migrate to support this feature.
|
|
226
|
-
</Text>
|
|
227
|
-
<Text typography={'header_default'} style={{width: '100%'}}>
|
|
228
|
-
Possible fixes:
|
|
229
|
-
</Text>
|
|
230
|
-
<View style={{marginLeft: Spacing.S}}>
|
|
231
|
-
<Text typography={'body_default_regular'}>1. Off webpack config</Text>
|
|
232
|
-
<Text typography={'body_default_regular'}>
|
|
233
|
-
2. Screen name refactoring
|
|
234
|
-
</Text>
|
|
235
|
-
<View style={{marginLeft: Spacing.S}}>
|
|
236
|
-
<Text
|
|
237
|
-
typography={'description_default_regular'}
|
|
238
|
-
style={{marginBottom: Spacing.S}}>
|
|
239
|
-
- Với các screen push/import dạng arrow function ={'>'} đổi thành
|
|
240
|
-
named function
|
|
241
|
-
</Text>
|
|
242
|
-
<Text
|
|
243
|
-
typography={'description_default_regular'}
|
|
244
|
-
style={{marginBottom: Spacing.S}}>
|
|
245
|
-
- Với các screen import dạng High Order Component ={'>'} rename
|
|
246
|
-
generic function thành named function
|
|
247
|
-
</Text>
|
|
248
|
-
<Text
|
|
249
|
-
typography={'description_default_regular'}
|
|
250
|
-
style={{marginBottom: Spacing.S}}>
|
|
251
|
-
- Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
|
|
252
|
-
Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
|
|
253
|
-
khảo theo docs
|
|
254
|
-
</Text>
|
|
255
|
-
</View>
|
|
256
|
-
</View>
|
|
257
|
-
<Text typography={'header_s_semibold'}>More information: </Text>
|
|
258
|
-
<Text
|
|
259
|
-
typography={'body_default_regular'}
|
|
260
|
-
color={Colors.blue_01}
|
|
261
|
-
onPress={() => {
|
|
262
|
-
Linking.openURL(
|
|
263
|
-
'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
|
|
264
|
-
);
|
|
265
|
-
}}>
|
|
266
|
-
Mini App: vn.momo.uikits/dev
|
|
267
|
-
</Text>
|
|
268
|
-
<Text
|
|
269
|
-
typography={'body_default_regular'}
|
|
270
|
-
color={Colors.blue_01}
|
|
271
|
-
onPress={() => {
|
|
272
|
-
Linking.openURL(
|
|
273
|
-
'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
|
|
274
|
-
);
|
|
275
|
-
}}>
|
|
276
|
-
https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
|
|
277
|
-
</Text>
|
|
278
|
-
</View>
|
|
279
|
-
);
|
|
280
|
-
};
|
|
281
|
-
|
|
282
283
|
export default StackScreen;
|
package/Application/types.ts
CHANGED
|
@@ -129,7 +129,7 @@ export type NavigationButtonProps = {
|
|
|
129
129
|
tintColor?: string;
|
|
130
130
|
useBorder?: boolean;
|
|
131
131
|
onPress: () => void;
|
|
132
|
-
badgeType?: 'dot' | 'number';
|
|
132
|
+
badgeType?: 'dot' | 'number' | 'dot-animation';
|
|
133
133
|
badgeValue?: number;
|
|
134
134
|
accessibilityLabel?: string;
|
|
135
135
|
};
|
|
@@ -137,7 +137,7 @@ export type NavigationButtonProps = {
|
|
|
137
137
|
export type PinnedToolType = {
|
|
138
138
|
key: string;
|
|
139
139
|
badgeValue?: number;
|
|
140
|
-
badgeType?: 'number' | 'dot';
|
|
140
|
+
badgeType?: 'number' | 'dot' | 'dot-animation';
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
export type RuntimeToolType = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, {useEffect, useRef} from 'react';
|
|
2
|
-
import {Animated,
|
|
2
|
+
import {Animated, View} from 'react-native';
|
|
3
3
|
import {BadgeDotProps} from './types';
|
|
4
|
-
import
|
|
4
|
+
import styles from './styles';
|
|
5
5
|
|
|
6
6
|
const DURATION = 500;
|
|
7
7
|
|
|
@@ -11,7 +11,8 @@ const BadgeDotAnimation = ({size, style}: BadgeDotProps) => {
|
|
|
11
11
|
const waveScaleAnim = useRef(new Animated.Value(1)).current;
|
|
12
12
|
const waveOpacityAnim = useRef(new Animated.Value(0)).current;
|
|
13
13
|
|
|
14
|
-
const dotStyle =
|
|
14
|
+
const dotStyle =
|
|
15
|
+
size === 'small' ? styles.dotAnimationSmall : styles.dotAnimation;
|
|
15
16
|
const waveStyle = size === 'small' ? styles.waveSmall : styles.wave;
|
|
16
17
|
|
|
17
18
|
useEffect(() => {
|
|
@@ -67,7 +68,7 @@ const BadgeDotAnimation = ({size, style}: BadgeDotProps) => {
|
|
|
67
68
|
}, []);
|
|
68
69
|
|
|
69
70
|
return (
|
|
70
|
-
<View style={[styles.
|
|
71
|
+
<View style={[styles.dotAnimationContainer, style]}>
|
|
71
72
|
{/* Wave Animation */}
|
|
72
73
|
<Animated.View
|
|
73
74
|
style={[
|
|
@@ -91,32 +92,4 @@ const BadgeDotAnimation = ({size, style}: BadgeDotProps) => {
|
|
|
91
92
|
);
|
|
92
93
|
};
|
|
93
94
|
|
|
94
|
-
const styles = StyleSheet.create({
|
|
95
|
-
...CommonStyle,
|
|
96
|
-
container: {
|
|
97
|
-
position: 'relative',
|
|
98
|
-
alignItems: 'center',
|
|
99
|
-
justifyContent: 'center',
|
|
100
|
-
},
|
|
101
|
-
dot: {
|
|
102
|
-
...CommonStyle.dot,
|
|
103
|
-
borderWidth: 0,
|
|
104
|
-
},
|
|
105
|
-
dotSmall: {
|
|
106
|
-
...CommonStyle.dotSmall,
|
|
107
|
-
borderWidth: 0,
|
|
108
|
-
},
|
|
109
|
-
wave: {
|
|
110
|
-
...CommonStyle.dot,
|
|
111
|
-
opacity: 0,
|
|
112
|
-
position: 'absolute',
|
|
113
|
-
borderWidth: 0,
|
|
114
|
-
},
|
|
115
|
-
waveSmall: {
|
|
116
|
-
...CommonStyle.dotSmall,
|
|
117
|
-
borderWidth: 0,
|
|
118
|
-
position: 'absolute',
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
|
|
122
95
|
export default BadgeDotAnimation;
|
package/Badge/index.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Badge from './Badge';
|
|
2
2
|
import BadgeDot from './BadgeDot';
|
|
3
3
|
import BadgeRibbon from './BadgeRibbon';
|
|
4
|
+
import BadgeDotAnimation from './BadgeDotAnimation';
|
|
4
5
|
import {BadgeProps, BadgeDotProps, BadgeRibbonProps} from './types';
|
|
5
6
|
|
|
6
|
-
export {Badge, BadgeRibbon, BadgeDot};
|
|
7
|
+
export {Badge, BadgeRibbon, BadgeDot, BadgeDotAnimation};
|
|
7
8
|
export type {BadgeProps, BadgeDotProps, BadgeRibbonProps};
|
package/Badge/styles.ts
CHANGED
|
@@ -2,6 +2,10 @@ import {StyleSheet} from 'react-native';
|
|
|
2
2
|
import {Colors, Radius, Spacing} from '../Consts';
|
|
3
3
|
import {scaleSize} from '../Text';
|
|
4
4
|
|
|
5
|
+
const DOT_SIZE = 16;
|
|
6
|
+
|
|
7
|
+
const DOT_SMALL_SIZE = 10;
|
|
8
|
+
|
|
5
9
|
export default StyleSheet.create({
|
|
6
10
|
badge: {
|
|
7
11
|
paddingHorizontal: Spacing.XS,
|
|
@@ -15,21 +19,61 @@ export default StyleSheet.create({
|
|
|
15
19
|
borderColor: Colors.black_01,
|
|
16
20
|
alignSelf: 'baseline',
|
|
17
21
|
},
|
|
22
|
+
dotAnimationContainer: {
|
|
23
|
+
position: 'relative',
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
justifyContent: 'center',
|
|
26
|
+
},
|
|
18
27
|
dot: {
|
|
19
|
-
width:
|
|
20
|
-
height:
|
|
28
|
+
width: DOT_SIZE,
|
|
29
|
+
height: DOT_SIZE,
|
|
21
30
|
borderWidth: 2,
|
|
22
31
|
borderColor: Colors.black_01,
|
|
23
32
|
backgroundColor: Colors.red_03,
|
|
24
|
-
borderRadius:
|
|
33
|
+
borderRadius: DOT_SIZE / 2,
|
|
25
34
|
},
|
|
26
35
|
dotSmall: {
|
|
27
|
-
width:
|
|
28
|
-
height:
|
|
36
|
+
width: DOT_SMALL_SIZE,
|
|
37
|
+
height: DOT_SMALL_SIZE,
|
|
29
38
|
borderWidth: 1,
|
|
30
39
|
borderColor: Colors.black_01,
|
|
31
40
|
backgroundColor: Colors.red_03,
|
|
32
|
-
borderRadius:
|
|
41
|
+
borderRadius: DOT_SMALL_SIZE / 2,
|
|
42
|
+
},
|
|
43
|
+
dotAnimation: {
|
|
44
|
+
width: DOT_SIZE,
|
|
45
|
+
height: DOT_SIZE,
|
|
46
|
+
borderColor: Colors.black_01,
|
|
47
|
+
backgroundColor: Colors.red_03,
|
|
48
|
+
borderRadius: DOT_SIZE / 2,
|
|
49
|
+
borderWidth: 0,
|
|
50
|
+
},
|
|
51
|
+
dotAnimationSmall: {
|
|
52
|
+
width: DOT_SMALL_SIZE,
|
|
53
|
+
height: DOT_SMALL_SIZE,
|
|
54
|
+
borderColor: Colors.black_01,
|
|
55
|
+
backgroundColor: Colors.red_03,
|
|
56
|
+
borderRadius: DOT_SMALL_SIZE / 2,
|
|
57
|
+
borderWidth: 0,
|
|
58
|
+
},
|
|
59
|
+
wave: {
|
|
60
|
+
width: DOT_SIZE,
|
|
61
|
+
height: DOT_SIZE,
|
|
62
|
+
borderColor: Colors.black_01,
|
|
63
|
+
backgroundColor: Colors.red_03,
|
|
64
|
+
borderRadius: DOT_SIZE / 2,
|
|
65
|
+
opacity: 0,
|
|
66
|
+
position: 'absolute',
|
|
67
|
+
borderWidth: 0,
|
|
68
|
+
},
|
|
69
|
+
waveSmall: {
|
|
70
|
+
width: DOT_SMALL_SIZE,
|
|
71
|
+
height: DOT_SMALL_SIZE,
|
|
72
|
+
borderColor: Colors.black_01,
|
|
73
|
+
backgroundColor: Colors.red_03,
|
|
74
|
+
borderRadius: DOT_SMALL_SIZE / 2,
|
|
75
|
+
borderWidth: 0,
|
|
76
|
+
position: 'absolute',
|
|
33
77
|
},
|
|
34
78
|
ribbon: {
|
|
35
79
|
alignSelf: 'baseline',
|