@momo-kits/foundation 0.102.6-beta.0 → 0.102.6-beta.10
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/StackScreen.tsx +159 -115
- package/Badge/BadgeDotAnimation.tsx +122 -0
- package/package.json +1 -1
- package/publish.sh +2 -2
|
@@ -8,80 +8,6 @@ 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
|
-
|
|
85
11
|
/**
|
|
86
12
|
* container for stack screen
|
|
87
13
|
* @param props
|
|
@@ -89,18 +15,19 @@ const EmptyScreen: React.FC = () => {
|
|
|
89
15
|
*/
|
|
90
16
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
91
17
|
const {showGrid, navigator} = useContext(ApplicationContext);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const tracked = useRef<any>({
|
|
18
|
+
const tracking = useRef<any>({
|
|
19
|
+
timeoutLoad: undefined,
|
|
20
|
+
interaction: undefined,
|
|
21
|
+
startTime: Date.now(),
|
|
22
|
+
endTime: Date.now(),
|
|
98
23
|
traceIdLoad: undefined,
|
|
99
24
|
traceIdInteraction: undefined,
|
|
100
25
|
releaseLoad: undefined,
|
|
101
26
|
releaseInteraction: undefined,
|
|
27
|
+
timeLoad: 0,
|
|
28
|
+
timeInteraction: 0,
|
|
102
29
|
});
|
|
103
|
-
|
|
30
|
+
|
|
104
31
|
const context = useContext<any>(MiniAppContext);
|
|
105
32
|
const {screen: Component, options, initialParams} = props.route.params;
|
|
106
33
|
const navigation = new Navigation(props.navigation);
|
|
@@ -116,6 +43,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
116
43
|
delete data.initialParams;
|
|
117
44
|
|
|
118
45
|
const screenName = Component?.name || Component?.type?.name || 'Invalid';
|
|
46
|
+
const routes = props.navigation.getState()?.routes || [];
|
|
119
47
|
|
|
120
48
|
/**
|
|
121
49
|
* set options for screen
|
|
@@ -145,18 +73,31 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
145
73
|
}, 300);
|
|
146
74
|
}
|
|
147
75
|
navigator?.maxApi?.of?.({screenName});
|
|
76
|
+
const subscription = props.navigation?.addListener?.('focus', () => {
|
|
77
|
+
navigator?.maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
|
|
78
|
+
let preScreenName = data?.screenName;
|
|
79
|
+
if (routes?.length > 1) {
|
|
80
|
+
const screen = routes?.[routes?.length - 2]?.params?.screen;
|
|
81
|
+
preScreenName = screen?.name || screen?.type?.name || 'Invalid';
|
|
82
|
+
}
|
|
83
|
+
onScreenNavigated(preScreenName);
|
|
84
|
+
navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
148
87
|
navigator?.maxApi?.startTraceScreenLoad?.(screenName, (data: any) => {
|
|
149
|
-
|
|
88
|
+
tracking.current.traceIdLoad = data?.traceId;
|
|
150
89
|
});
|
|
151
90
|
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
152
91
|
screenName,
|
|
153
92
|
(data: any) => {
|
|
154
|
-
|
|
93
|
+
tracking.current.traceIdInteraction = data?.traceId;
|
|
155
94
|
}
|
|
156
95
|
);
|
|
96
|
+
|
|
157
97
|
return () => {
|
|
158
98
|
onScreenLoad();
|
|
159
99
|
onScreenInteraction();
|
|
100
|
+
subscription?.();
|
|
160
101
|
};
|
|
161
102
|
}, []);
|
|
162
103
|
|
|
@@ -164,9 +105,10 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
164
105
|
* tracking for screen load
|
|
165
106
|
*/
|
|
166
107
|
const onScreenLoad = () => {
|
|
167
|
-
if (!
|
|
168
|
-
if (
|
|
169
|
-
|
|
108
|
+
if (!tracking.current?.releaseLoad) {
|
|
109
|
+
if (tracking.current.timeLoad === 0) {
|
|
110
|
+
tracking.current.timeLoad =
|
|
111
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
170
112
|
}
|
|
171
113
|
|
|
172
114
|
context.autoTracking?.({
|
|
@@ -174,27 +116,26 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
174
116
|
code: context.code,
|
|
175
117
|
buildNumber: context.buildNumber,
|
|
176
118
|
screenName,
|
|
177
|
-
action: 'push',
|
|
178
119
|
componentName: 'Screen',
|
|
179
120
|
state: 'load',
|
|
180
|
-
duration:
|
|
121
|
+
duration: tracking.current.timeLoad,
|
|
181
122
|
});
|
|
182
123
|
navigator?.maxApi?.stopTrace?.(
|
|
183
|
-
|
|
184
|
-
{value:
|
|
124
|
+
tracking.current.traceIdLoad,
|
|
125
|
+
{value: tracking.current.timeLoad / 1000},
|
|
185
126
|
null
|
|
186
127
|
);
|
|
187
|
-
|
|
128
|
+
tracking.current.releaseLoad = true;
|
|
188
129
|
|
|
189
130
|
/**
|
|
190
131
|
* debug
|
|
191
132
|
*/
|
|
192
133
|
navigator?.maxApi?.showToastDebug?.({
|
|
193
134
|
appId: context.appId,
|
|
194
|
-
message: `${screenName} screen_load_time ${
|
|
195
|
-
type: '
|
|
135
|
+
message: `${screenName} screen_load_time ${tracking.current.timeLoad}`,
|
|
136
|
+
type: 'ERROR',
|
|
196
137
|
});
|
|
197
|
-
if (
|
|
138
|
+
if (tracking.current.timeLoad <= 0 && context.enableAutoId) {
|
|
198
139
|
Alert.alert(screenName, "Can't get screen load time");
|
|
199
140
|
}
|
|
200
141
|
}
|
|
@@ -204,12 +145,13 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
204
145
|
* tracking for screen load
|
|
205
146
|
*/
|
|
206
147
|
const onScreenInteraction = () => {
|
|
207
|
-
if (!
|
|
208
|
-
if (
|
|
209
|
-
|
|
148
|
+
if (!tracking.current?.releaseInteraction) {
|
|
149
|
+
if (tracking.current.timeLoad === 0) {
|
|
150
|
+
tracking.current.timeLoad =
|
|
151
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
210
152
|
}
|
|
211
|
-
if (
|
|
212
|
-
|
|
153
|
+
if (tracking.current.timeInteraction === 0) {
|
|
154
|
+
tracking.current.timeInteraction = tracking.current.timeLoad;
|
|
213
155
|
}
|
|
214
156
|
|
|
215
157
|
context.autoTracking?.({
|
|
@@ -219,43 +161,71 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
219
161
|
screenName,
|
|
220
162
|
componentName: 'Screen',
|
|
221
163
|
state: 'interaction',
|
|
222
|
-
duration:
|
|
164
|
+
duration: tracking.current.timeInteraction - tracking.current.timeLoad,
|
|
165
|
+
totalDuration: tracking.current.timeInteraction,
|
|
223
166
|
});
|
|
224
167
|
navigator?.maxApi?.stopTrace?.(
|
|
225
|
-
|
|
226
|
-
{value:
|
|
168
|
+
tracking.current.traceIdInteraction,
|
|
169
|
+
{value: tracking.current.timeInteraction / 1000},
|
|
227
170
|
null
|
|
228
171
|
);
|
|
229
|
-
|
|
172
|
+
tracking.current.releaseInteraction = true;
|
|
230
173
|
|
|
231
174
|
/**
|
|
232
175
|
* debug toast
|
|
233
176
|
*/
|
|
234
177
|
navigator?.maxApi?.showToastDebug?.({
|
|
235
178
|
appId: context.appId,
|
|
236
|
-
message: `${screenName} screen_interaction_time ${
|
|
237
|
-
type: '
|
|
179
|
+
message: `${screenName} screen_interaction_time ${tracking.current.timeInteraction}`,
|
|
180
|
+
type: 'ERROR',
|
|
238
181
|
});
|
|
239
|
-
if (
|
|
182
|
+
if (tracking.current.timeInteraction <= 0 && context.enableAutoId) {
|
|
240
183
|
Alert.alert(screenName, "Can't get screen interaction time");
|
|
241
184
|
}
|
|
242
185
|
}
|
|
243
186
|
};
|
|
244
187
|
|
|
188
|
+
/**
|
|
189
|
+
* tracking for screen navigated
|
|
190
|
+
*/
|
|
191
|
+
const onScreenNavigated = (preScreenName: string) => {
|
|
192
|
+
context.autoTracking?.({
|
|
193
|
+
appId: context.appId,
|
|
194
|
+
code: context.code,
|
|
195
|
+
buildNumber: context.buildNumber,
|
|
196
|
+
preScreenName,
|
|
197
|
+
screenName,
|
|
198
|
+
componentName: 'Screen',
|
|
199
|
+
state: 'navigated',
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* debug toast
|
|
204
|
+
*/
|
|
205
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
206
|
+
appId: context.appId,
|
|
207
|
+
message: `${screenName} screen_navigated`,
|
|
208
|
+
type: 'ERROR',
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
|
|
245
212
|
return (
|
|
246
213
|
<ScreenContext.Provider
|
|
247
214
|
value={{
|
|
248
215
|
screenName,
|
|
249
216
|
onElementLoad: () => {
|
|
250
|
-
clearTimeout(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
217
|
+
clearTimeout(tracking.current.timeoutLoad);
|
|
218
|
+
tracking.current.endTime = Date.now();
|
|
219
|
+
tracking.current.interaction?.cancel?.();
|
|
220
|
+
tracking.current.interaction =
|
|
221
|
+
InteractionManager.runAfterInteractions(() => {
|
|
222
|
+
tracking.current.timeInteraction =
|
|
223
|
+
Date.now() - tracking.current.startTime;
|
|
224
|
+
});
|
|
225
|
+
tracking.current.timeoutLoad = setTimeout(() => {
|
|
226
|
+
if (tracking.current.timeLoad === 0) {
|
|
227
|
+
tracking.current.timeLoad =
|
|
228
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
259
229
|
}
|
|
260
230
|
onScreenLoad();
|
|
261
231
|
onScreenInteraction();
|
|
@@ -273,4 +243,78 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
273
243
|
);
|
|
274
244
|
};
|
|
275
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Empty screen for unvalidated screen name
|
|
248
|
+
* @constructor
|
|
249
|
+
*/
|
|
250
|
+
const EmptyScreen: React.FC = () => {
|
|
251
|
+
return (
|
|
252
|
+
<View
|
|
253
|
+
style={{
|
|
254
|
+
backgroundColor: Colors.black_01,
|
|
255
|
+
padding: Spacing.M,
|
|
256
|
+
borderRadius: Radius.M,
|
|
257
|
+
}}>
|
|
258
|
+
<Text typography={'header_m_bold'}>Unvalidated screen name</Text>
|
|
259
|
+
<Text
|
|
260
|
+
typography={'description_default_regular'}
|
|
261
|
+
style={{paddingVertical: Spacing.S}}>
|
|
262
|
+
Your screen has not been rendered because Platform has not detected the
|
|
263
|
+
screen name. Please migrate to support this feature.
|
|
264
|
+
</Text>
|
|
265
|
+
<Text typography={'header_default'} style={{width: '100%'}}>
|
|
266
|
+
Possible fixes:
|
|
267
|
+
</Text>
|
|
268
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
269
|
+
<Text typography={'body_default_regular'}>1. Off webpack config</Text>
|
|
270
|
+
<Text typography={'body_default_regular'}>
|
|
271
|
+
2. Screen name refactoring
|
|
272
|
+
</Text>
|
|
273
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
274
|
+
<Text
|
|
275
|
+
typography={'description_default_regular'}
|
|
276
|
+
style={{marginBottom: Spacing.S}}>
|
|
277
|
+
- Với các screen push/import dạng arrow function ={'>'} đổi thành
|
|
278
|
+
named function
|
|
279
|
+
</Text>
|
|
280
|
+
<Text
|
|
281
|
+
typography={'description_default_regular'}
|
|
282
|
+
style={{marginBottom: Spacing.S}}>
|
|
283
|
+
- Với các screen import dạng High Order Component ={'>'} rename
|
|
284
|
+
generic function thành named function
|
|
285
|
+
</Text>
|
|
286
|
+
<Text
|
|
287
|
+
typography={'description_default_regular'}
|
|
288
|
+
style={{marginBottom: Spacing.S}}>
|
|
289
|
+
- Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
|
|
290
|
+
Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
|
|
291
|
+
khảo theo docs
|
|
292
|
+
</Text>
|
|
293
|
+
</View>
|
|
294
|
+
</View>
|
|
295
|
+
<Text typography={'header_s_semibold'}>More information: </Text>
|
|
296
|
+
<Text
|
|
297
|
+
typography={'body_default_regular'}
|
|
298
|
+
color={Colors.blue_01}
|
|
299
|
+
onPress={() => {
|
|
300
|
+
Linking.openURL(
|
|
301
|
+
'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
|
|
302
|
+
);
|
|
303
|
+
}}>
|
|
304
|
+
Mini App: vn.momo.uikits/dev
|
|
305
|
+
</Text>
|
|
306
|
+
<Text
|
|
307
|
+
typography={'body_default_regular'}
|
|
308
|
+
color={Colors.blue_01}
|
|
309
|
+
onPress={() => {
|
|
310
|
+
Linking.openURL(
|
|
311
|
+
'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
|
|
312
|
+
);
|
|
313
|
+
}}>
|
|
314
|
+
https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
|
|
315
|
+
</Text>
|
|
316
|
+
</View>
|
|
317
|
+
);
|
|
318
|
+
};
|
|
319
|
+
|
|
276
320
|
export default StackScreen;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React, {useEffect, useRef} from 'react';
|
|
2
|
+
import {Animated, StyleSheet, View} from 'react-native';
|
|
3
|
+
import {BadgeDotProps} from './types';
|
|
4
|
+
import CommonStyle from './styles';
|
|
5
|
+
|
|
6
|
+
const DURATION = 500;
|
|
7
|
+
|
|
8
|
+
const BadgeDotAnimation = ({size, style}: BadgeDotProps) => {
|
|
9
|
+
// Refs for animated values
|
|
10
|
+
const scaleAnim = useRef(new Animated.Value(1)).current;
|
|
11
|
+
const waveScaleAnim = useRef(new Animated.Value(1)).current;
|
|
12
|
+
const waveOpacityAnim = useRef(new Animated.Value(0)).current;
|
|
13
|
+
|
|
14
|
+
const dotStyle = size === 'small' ? styles.dotSmall : styles.dot;
|
|
15
|
+
const waveStyle = size === 'small' ? styles.waveSmall : styles.wave;
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
// Infinite loop animation for the scale and wave effect
|
|
19
|
+
const animation = Animated.loop(
|
|
20
|
+
Animated.parallel([
|
|
21
|
+
// Dot pulse animation
|
|
22
|
+
Animated.sequence([
|
|
23
|
+
Animated.spring(scaleAnim, {
|
|
24
|
+
toValue: 1, // Scale up slightly
|
|
25
|
+
friction: 5, // Controls the "bounciness" of the spring
|
|
26
|
+
tension: 30, // Controls the "stiffness" of the spring
|
|
27
|
+
useNativeDriver: true,
|
|
28
|
+
}),
|
|
29
|
+
Animated.spring(scaleAnim, {
|
|
30
|
+
toValue: 1.1,
|
|
31
|
+
friction: 5,
|
|
32
|
+
tension: 30,
|
|
33
|
+
useNativeDriver: true,
|
|
34
|
+
}),
|
|
35
|
+
]), // Wave animation
|
|
36
|
+
Animated.sequence([
|
|
37
|
+
Animated.timing(waveScaleAnim, {
|
|
38
|
+
toValue: 2.5,
|
|
39
|
+
duration: DURATION * 3,
|
|
40
|
+
useNativeDriver: true,
|
|
41
|
+
}),
|
|
42
|
+
Animated.timing(waveScaleAnim, {
|
|
43
|
+
toValue: 1, // Reset wave size
|
|
44
|
+
duration: 0,
|
|
45
|
+
useNativeDriver: true,
|
|
46
|
+
}),
|
|
47
|
+
]), // Wave opacity animation
|
|
48
|
+
Animated.sequence([
|
|
49
|
+
Animated.timing(waveOpacityAnim, {
|
|
50
|
+
toValue: 0.3, // Wave becomes visible
|
|
51
|
+
duration: DURATION * 2,
|
|
52
|
+
useNativeDriver: true,
|
|
53
|
+
}),
|
|
54
|
+
Animated.timing(waveOpacityAnim, {
|
|
55
|
+
toValue: 0, // Wave fades out
|
|
56
|
+
duration: DURATION,
|
|
57
|
+
useNativeDriver: true,
|
|
58
|
+
}),
|
|
59
|
+
]),
|
|
60
|
+
])
|
|
61
|
+
);
|
|
62
|
+
animation.start();
|
|
63
|
+
|
|
64
|
+
return () => {
|
|
65
|
+
animation.stop();
|
|
66
|
+
};
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<View style={[styles.container, style]}>
|
|
71
|
+
{/* Wave Animation */}
|
|
72
|
+
<Animated.View
|
|
73
|
+
style={[
|
|
74
|
+
waveStyle,
|
|
75
|
+
{
|
|
76
|
+
transform: [{scale: waveScaleAnim}],
|
|
77
|
+
opacity: waveOpacityAnim,
|
|
78
|
+
},
|
|
79
|
+
]}
|
|
80
|
+
/>
|
|
81
|
+
{/* Dot Animation */}
|
|
82
|
+
<Animated.View
|
|
83
|
+
style={[
|
|
84
|
+
dotStyle,
|
|
85
|
+
{
|
|
86
|
+
transform: [{scale: scaleAnim}],
|
|
87
|
+
},
|
|
88
|
+
]}
|
|
89
|
+
/>
|
|
90
|
+
</View>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
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
|
+
export default BadgeDotAnimation;
|
package/package.json
CHANGED
package/publish.sh
CHANGED
|
@@ -9,8 +9,8 @@ elif [ "$1" == "latest" ]; then
|
|
|
9
9
|
npm version prerelease --preid=rc
|
|
10
10
|
npm publish --tag latest --access=public
|
|
11
11
|
else
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
npm version $(npm view @momo-kits/foundation@beta version)
|
|
13
|
+
npm version prerelease --preid=beta
|
|
14
14
|
npm publish --tag beta --access=public
|
|
15
15
|
fi
|
|
16
16
|
|