@momo-kits/foundation 0.92.21-beta.3 → 0.92.21-beta.5
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/index.tsx +1 -2
- package/Application/Components.tsx +221 -39
- package/Application/ModalScreen.tsx +2 -2
- package/Application/Navigation.ts +4 -18
- package/Application/StackScreen.tsx +89 -6
- package/Application/index.ts +0 -2
- package/Application/types.ts +25 -8
- package/Application/utils.tsx +64 -18
- package/Button/index.tsx +0 -1
- package/Input/InputMoney.tsx +3 -3
- package/Input/InputOTP.tsx +4 -4
- package/Input/InputSearch.tsx +249 -144
- package/Input/TextTyping.tsx +113 -0
- package/Input/index.tsx +19 -1
- package/Input/styles.ts +10 -3
- package/Layout/AnimatedInputSearch.tsx +66 -0
- package/Layout/FloatingButton.tsx +1 -1
- package/Layout/Screen.tsx +171 -92
- package/Layout/styles.ts +0 -6
- package/Layout/types.ts +20 -1
- package/package.json +2 -2
|
@@ -17,10 +17,9 @@ const Tab = createBottomTabNavigator();
|
|
|
17
17
|
const Stack = createStackNavigator();
|
|
18
18
|
|
|
19
19
|
const TabScreen: React.FC<NavigationScreenProps> = ({route}) => {
|
|
20
|
-
const {theme} = useContext(ApplicationContext);
|
|
21
20
|
let options = {};
|
|
22
21
|
if (route.params?.options) {
|
|
23
|
-
options = getOptions(route.params?.options
|
|
22
|
+
options = getOptions(route.params?.options);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
if (route.params?.nested) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
Fragment,
|
|
3
2
|
useCallback,
|
|
4
3
|
useContext,
|
|
5
4
|
useEffect,
|
|
5
|
+
useRef,
|
|
6
6
|
useState,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import {
|
|
@@ -29,7 +29,14 @@ import {scaleSize, Text} from '../Text';
|
|
|
29
29
|
import {Icon} from '../Icon';
|
|
30
30
|
import {PopupNotify} from '../Popup';
|
|
31
31
|
import {Badge, BadgeDot} from '../Badge';
|
|
32
|
+
import {HeaderType} from '../Layout/types';
|
|
33
|
+
import Navigation from './Navigation';
|
|
34
|
+
import {InputSearchProps} from '../Input';
|
|
35
|
+
import AnimatedInputSearch from '../Layout/AnimatedInputSearch';
|
|
32
36
|
|
|
37
|
+
/**
|
|
38
|
+
* default navigation button used header nav
|
|
39
|
+
*/
|
|
33
40
|
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
34
41
|
icon,
|
|
35
42
|
tintColor,
|
|
@@ -81,13 +88,18 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
81
88
|
);
|
|
82
89
|
};
|
|
83
90
|
|
|
91
|
+
/**
|
|
92
|
+
* default header title used for nav
|
|
93
|
+
*/
|
|
84
94
|
const HeaderTitle: React.FC<any> = props => {
|
|
85
95
|
const {theme} = useContext(ApplicationContext);
|
|
86
|
-
const opacity = props.animatedValue?.interpolate(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
const opacity = props.animatedValue?.interpolate(
|
|
97
|
+
props.interpolate ?? {
|
|
98
|
+
inputRange: [0, 200],
|
|
99
|
+
outputRange: [0, 1],
|
|
100
|
+
extrapolate: 'clamp',
|
|
101
|
+
}
|
|
102
|
+
);
|
|
91
103
|
|
|
92
104
|
return (
|
|
93
105
|
<Animated.Text
|
|
@@ -101,6 +113,9 @@ const HeaderTitle: React.FC<any> = props => {
|
|
|
101
113
|
);
|
|
102
114
|
};
|
|
103
115
|
|
|
116
|
+
/**
|
|
117
|
+
* default header left used for nav
|
|
118
|
+
*/
|
|
104
119
|
const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
105
120
|
tintColor,
|
|
106
121
|
preventBack,
|
|
@@ -113,7 +128,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
113
128
|
useEffect(() => {
|
|
114
129
|
const backHandler = BackHandler.addEventListener(
|
|
115
130
|
'hardwareBackPress',
|
|
116
|
-
goBackSafe
|
|
131
|
+
goBackSafe
|
|
117
132
|
);
|
|
118
133
|
|
|
119
134
|
return () => backHandler.remove();
|
|
@@ -168,6 +183,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
168
183
|
}
|
|
169
184
|
return true;
|
|
170
185
|
};
|
|
186
|
+
|
|
171
187
|
return (
|
|
172
188
|
<View style={styles.headerLeft}>
|
|
173
189
|
<NavigationButton
|
|
@@ -181,6 +197,9 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
181
197
|
);
|
|
182
198
|
};
|
|
183
199
|
|
|
200
|
+
/**
|
|
201
|
+
* header background for default
|
|
202
|
+
*/
|
|
184
203
|
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
185
204
|
image,
|
|
186
205
|
animatedValue,
|
|
@@ -229,6 +248,10 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
229
248
|
);
|
|
230
249
|
};
|
|
231
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Header custom with image, title, subtitle
|
|
253
|
+
* @constructor
|
|
254
|
+
*/
|
|
232
255
|
const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
233
256
|
title,
|
|
234
257
|
subTitle,
|
|
@@ -263,37 +286,42 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
263
286
|
return <View style={styles.headerTitleContainer}>{content ?? header}</View>;
|
|
264
287
|
};
|
|
265
288
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return child;
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const renderAction = () => {
|
|
278
|
-
if (Array.isArray(children)) {
|
|
279
|
-
return children.map((child, index) => {
|
|
280
|
-
return (
|
|
281
|
-
<View key={`HeaderRightAction ${index}`} style={styles.headerButton}>
|
|
282
|
-
{React.cloneElement(validateType(child), {...restProps})}
|
|
283
|
-
</View>
|
|
284
|
-
);
|
|
285
|
-
});
|
|
289
|
+
/**
|
|
290
|
+
* main component for header right
|
|
291
|
+
*/
|
|
292
|
+
const HeaderRight: React.FC<any> = ({type, children, onLayout, ...props}) => {
|
|
293
|
+
if (type === 'icon') {
|
|
294
|
+
let buttons = props?.buttons || [];
|
|
295
|
+
if (buttons?.length > 3) {
|
|
296
|
+
buttons = buttons.slice(0, 3);
|
|
286
297
|
}
|
|
287
|
-
|
|
288
298
|
return (
|
|
289
|
-
<View style={styles.
|
|
290
|
-
{
|
|
299
|
+
<View style={styles.headerRightButton} onLayout={onLayout}>
|
|
300
|
+
{buttons?.map?.((item: NavigationButtonProps, index: number) => {
|
|
301
|
+
return (
|
|
302
|
+
<View
|
|
303
|
+
key={`HeaderRightAction ${index}`}
|
|
304
|
+
style={{
|
|
305
|
+
marginLeft: index !== 0 ? Spacing.S : 0,
|
|
306
|
+
}}>
|
|
307
|
+
<NavigationButton {...item} tintColor={props?.tintColor} />
|
|
308
|
+
</View>
|
|
309
|
+
);
|
|
310
|
+
})}
|
|
291
311
|
</View>
|
|
292
312
|
);
|
|
293
|
-
}
|
|
294
|
-
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return (
|
|
316
|
+
<View style={styles.headerRightButton} onLayout={onLayout}>
|
|
317
|
+
{children ?? <HeaderToolkitAction {...props} />}
|
|
318
|
+
</View>
|
|
319
|
+
);
|
|
295
320
|
};
|
|
296
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Header toolkit action
|
|
324
|
+
*/
|
|
297
325
|
const HeaderToolkitAction: React.FC<any> = ({
|
|
298
326
|
tintColor,
|
|
299
327
|
pinnedTool,
|
|
@@ -327,7 +355,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
327
355
|
(config: any) => {
|
|
328
356
|
navigator.toolkitConfig = config;
|
|
329
357
|
setToolConfig(navigator?.toolkitConfig);
|
|
330
|
-
}
|
|
358
|
+
}
|
|
331
359
|
);
|
|
332
360
|
};
|
|
333
361
|
|
|
@@ -340,7 +368,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
340
368
|
const {item} = res;
|
|
341
369
|
navigator?.toolkitCallback?.(item);
|
|
342
370
|
getToolkitConfig();
|
|
343
|
-
}
|
|
371
|
+
}
|
|
344
372
|
);
|
|
345
373
|
};
|
|
346
374
|
|
|
@@ -357,7 +385,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
357
385
|
navigator?.maxApi?.dispatchFunction?.(
|
|
358
386
|
'dismiss',
|
|
359
387
|
undefined,
|
|
360
|
-
undefined
|
|
388
|
+
undefined
|
|
361
389
|
);
|
|
362
390
|
},
|
|
363
391
|
}}
|
|
@@ -388,7 +416,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
388
416
|
[pinTool?.key],
|
|
389
417
|
() => {
|
|
390
418
|
getToolkitConfig();
|
|
391
|
-
}
|
|
419
|
+
}
|
|
392
420
|
);
|
|
393
421
|
navigator?.toolkitCallback?.(pinTool.key);
|
|
394
422
|
}}
|
|
@@ -397,7 +425,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
397
425
|
};
|
|
398
426
|
if (toolConfig) {
|
|
399
427
|
return (
|
|
400
|
-
<View style={
|
|
428
|
+
<View style={Styles.row}>
|
|
401
429
|
{renderPinnedTool()}
|
|
402
430
|
<View
|
|
403
431
|
style={[
|
|
@@ -405,6 +433,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
405
433
|
{
|
|
406
434
|
backgroundColor: backgroundColor ?? '#00000066',
|
|
407
435
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
436
|
+
marginLeft: renderPinnedTool() ? Spacing.S : 0,
|
|
408
437
|
},
|
|
409
438
|
]}>
|
|
410
439
|
<TouchableOpacity
|
|
@@ -430,6 +459,9 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
430
459
|
return <View />;
|
|
431
460
|
};
|
|
432
461
|
|
|
462
|
+
/**
|
|
463
|
+
* default header banner for header animated
|
|
464
|
+
*/
|
|
433
465
|
const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
|
|
434
466
|
animatedValue,
|
|
435
467
|
image,
|
|
@@ -470,6 +502,150 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
|
|
|
470
502
|
);
|
|
471
503
|
};
|
|
472
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Header extended with background image
|
|
507
|
+
* @constructor
|
|
508
|
+
*/
|
|
509
|
+
const HeaderExtendBackground: React.FC<{
|
|
510
|
+
headerType?: HeaderType;
|
|
511
|
+
animatedValue: Animated.Value;
|
|
512
|
+
heightHeader: number;
|
|
513
|
+
inputSearchProps?: InputSearchProps;
|
|
514
|
+
navigation?: Navigation;
|
|
515
|
+
}> = ({
|
|
516
|
+
headerType = 'default',
|
|
517
|
+
animatedValue,
|
|
518
|
+
heightHeader,
|
|
519
|
+
inputSearchProps,
|
|
520
|
+
navigation,
|
|
521
|
+
}) => {
|
|
522
|
+
const {theme} = useContext(ApplicationContext);
|
|
523
|
+
|
|
524
|
+
const heightAnimated = useRef(new Animated.Value(0));
|
|
525
|
+
|
|
526
|
+
useEffect(() => {
|
|
527
|
+
const listener = animatedValue.addListener(({value}) => {
|
|
528
|
+
heightAnimated.current.setValue(value);
|
|
529
|
+
});
|
|
530
|
+
return () => {
|
|
531
|
+
animatedValue?.removeListener(listener);
|
|
532
|
+
};
|
|
533
|
+
}, []);
|
|
534
|
+
|
|
535
|
+
if (inputSearchProps) {
|
|
536
|
+
if (headerType === 'surface') {
|
|
537
|
+
return (
|
|
538
|
+
<View
|
|
539
|
+
style={{
|
|
540
|
+
backgroundColor: theme.colors.background.surface,
|
|
541
|
+
borderBottomWidth: 1,
|
|
542
|
+
borderColor: theme.colors.border.default,
|
|
543
|
+
}}>
|
|
544
|
+
<Animated.View
|
|
545
|
+
style={{
|
|
546
|
+
justifyContent: 'flex-end',
|
|
547
|
+
height: heightAnimated.current.interpolate({
|
|
548
|
+
inputRange: [0, 100],
|
|
549
|
+
outputRange: [heightHeader + 52, heightHeader],
|
|
550
|
+
extrapolate: 'clamp',
|
|
551
|
+
}),
|
|
552
|
+
}}>
|
|
553
|
+
<AnimatedInputSearch
|
|
554
|
+
hasColorBG
|
|
555
|
+
animatedValue={animatedValue}
|
|
556
|
+
navigation={navigation}
|
|
557
|
+
{...inputSearchProps}
|
|
558
|
+
/>
|
|
559
|
+
</Animated.View>
|
|
560
|
+
</View>
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (headerType === 'extended') {
|
|
565
|
+
return (
|
|
566
|
+
<>
|
|
567
|
+
<Image
|
|
568
|
+
source={{
|
|
569
|
+
uri: theme.assets?.headerBackground,
|
|
570
|
+
}}
|
|
571
|
+
style={styles.extendedHeader}
|
|
572
|
+
/>
|
|
573
|
+
<Animated.View
|
|
574
|
+
style={{
|
|
575
|
+
justifyContent: 'flex-end',
|
|
576
|
+
height: heightAnimated.current.interpolate({
|
|
577
|
+
inputRange: [0, 100],
|
|
578
|
+
outputRange: [heightHeader + 52, heightHeader],
|
|
579
|
+
extrapolate: 'clamp',
|
|
580
|
+
}),
|
|
581
|
+
}}>
|
|
582
|
+
<AnimatedInputSearch
|
|
583
|
+
animatedValue={animatedValue}
|
|
584
|
+
navigation={navigation}
|
|
585
|
+
{...inputSearchProps}
|
|
586
|
+
/>
|
|
587
|
+
</Animated.View>
|
|
588
|
+
</>
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return (
|
|
593
|
+
<>
|
|
594
|
+
<View
|
|
595
|
+
style={{
|
|
596
|
+
height: heightHeader + 52,
|
|
597
|
+
width: '100%',
|
|
598
|
+
position: 'absolute',
|
|
599
|
+
overflow: 'hidden',
|
|
600
|
+
}}>
|
|
601
|
+
<Image
|
|
602
|
+
source={{
|
|
603
|
+
uri: theme.assets?.headerBackground,
|
|
604
|
+
}}
|
|
605
|
+
style={{
|
|
606
|
+
width: '100%',
|
|
607
|
+
height: undefined,
|
|
608
|
+
position: 'absolute',
|
|
609
|
+
aspectRatio: 1.75,
|
|
610
|
+
}}
|
|
611
|
+
/>
|
|
612
|
+
</View>
|
|
613
|
+
|
|
614
|
+
<Animated.View
|
|
615
|
+
style={{
|
|
616
|
+
justifyContent: 'flex-end',
|
|
617
|
+
height: heightAnimated.current.interpolate({
|
|
618
|
+
inputRange: [0, 100],
|
|
619
|
+
outputRange: [heightHeader + 52, heightHeader],
|
|
620
|
+
extrapolate: 'clamp',
|
|
621
|
+
}),
|
|
622
|
+
}}>
|
|
623
|
+
<AnimatedInputSearch
|
|
624
|
+
animatedValue={animatedValue}
|
|
625
|
+
navigation={navigation}
|
|
626
|
+
{...inputSearchProps}
|
|
627
|
+
/>
|
|
628
|
+
</Animated.View>
|
|
629
|
+
</>
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (headerType === 'extended') {
|
|
634
|
+
return (
|
|
635
|
+
<View style={{minHeight: heightHeader}}>
|
|
636
|
+
<Image
|
|
637
|
+
source={{
|
|
638
|
+
uri: theme.assets?.headerBackground,
|
|
639
|
+
}}
|
|
640
|
+
style={styles.extendedHeader}
|
|
641
|
+
/>
|
|
642
|
+
</View>
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return <View />;
|
|
647
|
+
};
|
|
648
|
+
|
|
473
649
|
const styles = StyleSheet.create({
|
|
474
650
|
navigationButton: {
|
|
475
651
|
height: 28,
|
|
@@ -509,7 +685,6 @@ const styles = StyleSheet.create({
|
|
|
509
685
|
paddingRight: Spacing.M,
|
|
510
686
|
},
|
|
511
687
|
toolkitContainer: {
|
|
512
|
-
marginLeft: Spacing.S,
|
|
513
688
|
padding: Spacing.XS,
|
|
514
689
|
height: 28,
|
|
515
690
|
borderRadius: 14,
|
|
@@ -541,6 +716,12 @@ const styles = StyleSheet.create({
|
|
|
541
716
|
top: -Spacing.XS,
|
|
542
717
|
right: -Spacing.XS,
|
|
543
718
|
},
|
|
719
|
+
extendedHeader: {
|
|
720
|
+
aspectRatio: 1.75,
|
|
721
|
+
position: 'absolute',
|
|
722
|
+
width: '100%',
|
|
723
|
+
height: 210,
|
|
724
|
+
},
|
|
544
725
|
});
|
|
545
726
|
|
|
546
727
|
export {
|
|
@@ -548,8 +729,9 @@ export {
|
|
|
548
729
|
HeaderTitle,
|
|
549
730
|
HeaderLeft,
|
|
550
731
|
HeaderBackground,
|
|
551
|
-
HeaderRightAction,
|
|
552
732
|
HeaderToolkitAction,
|
|
553
733
|
HeaderCustom,
|
|
554
734
|
HeaderAnimated,
|
|
735
|
+
HeaderRight,
|
|
736
|
+
HeaderExtendBackground,
|
|
555
737
|
};
|
|
@@ -21,10 +21,10 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const Modal: React.FC<ModalParams> = props => {
|
|
24
|
-
const {
|
|
24
|
+
const {navigator} = useContext(ApplicationContext);
|
|
25
25
|
const {screen, barrierDismissible} = props.route.params;
|
|
26
26
|
const Component = useRef(screen).current;
|
|
27
|
-
const navigation = new Navigation(props.navigation
|
|
27
|
+
const navigation = new Navigation(props.navigation);
|
|
28
28
|
const params = {
|
|
29
29
|
...props.route.params,
|
|
30
30
|
navigation,
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import {NavigationProp} from '@react-navigation/native';
|
|
3
|
-
import {NavigationOptions
|
|
4
|
-
import {HeaderRightAction} from './index';
|
|
2
|
+
import {NavigationOptions} from './types';
|
|
5
3
|
import {getOptions} from './utils';
|
|
6
|
-
import {HeaderToolkitAction} from './Components';
|
|
7
4
|
|
|
8
5
|
class Navigation {
|
|
9
6
|
instance: NavigationProp<any>;
|
|
10
|
-
|
|
7
|
+
rightHeaderWidth?: number;
|
|
11
8
|
|
|
12
|
-
constructor(instance: any
|
|
9
|
+
constructor(instance: any) {
|
|
13
10
|
this.instance = instance;
|
|
14
|
-
this.theme = theme;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
/**
|
|
@@ -19,16 +15,6 @@ class Navigation {
|
|
|
19
15
|
* @param params
|
|
20
16
|
*/
|
|
21
17
|
private filterParams = (params: NavigationOptions) => {
|
|
22
|
-
if (params.headerRight) {
|
|
23
|
-
const headerRight = params.headerRight?.({}) as React.ReactElement;
|
|
24
|
-
const type = headerRight?.type;
|
|
25
|
-
if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
|
|
26
|
-
console.warn(
|
|
27
|
-
'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
18
|
if (params.headerLeft) {
|
|
33
19
|
console.warn('headerLeft not allow override render by design system!');
|
|
34
20
|
delete params.headerLeft;
|
|
@@ -42,7 +28,7 @@ class Navigation {
|
|
|
42
28
|
* @param params
|
|
43
29
|
*/
|
|
44
30
|
setOptions = (params: NavigationOptions) => {
|
|
45
|
-
params = getOptions(this.filterParams(params), this
|
|
31
|
+
params = getOptions(this.filterParams(params), this);
|
|
46
32
|
this.instance.setOptions(params);
|
|
47
33
|
};
|
|
48
34
|
}
|
|
@@ -1,13 +1,94 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
|
|
2
|
+
import {useHeaderHeight} from '@react-navigation/stack';
|
|
3
|
+
import {InteractionManager, Linking, View} from 'react-native';
|
|
2
4
|
import {ScreenParams} from './types';
|
|
3
5
|
import Navigation from './Navigation';
|
|
4
6
|
import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
|
|
5
7
|
import {GridSystem} from '../Layout';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
+
import {Text} from '../Text';
|
|
9
|
+
import {Colors, Radius, Spacing} from '../Consts';
|
|
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
|
+
};
|
|
8
84
|
|
|
85
|
+
/**
|
|
86
|
+
* container for stack screen
|
|
87
|
+
* @param props
|
|
88
|
+
* @constructor
|
|
89
|
+
*/
|
|
9
90
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
10
|
-
const {
|
|
91
|
+
const {showGrid, navigator} = useContext(ApplicationContext);
|
|
11
92
|
const startTime = useRef(Date.now());
|
|
12
93
|
const endTime = useRef(Date.now());
|
|
13
94
|
const timeLoad = useRef(0);
|
|
@@ -23,7 +104,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
23
104
|
const context = useContext<any>(MiniAppContext);
|
|
24
105
|
|
|
25
106
|
const {screen: Component, options, initialParams} = props.route.params;
|
|
26
|
-
const navigation = new Navigation(props.navigation
|
|
107
|
+
const navigation = new Navigation(props.navigation);
|
|
27
108
|
const heightHeader = useHeaderHeight();
|
|
28
109
|
|
|
29
110
|
const data = {
|
|
@@ -50,8 +131,10 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
50
131
|
* tracking for screen
|
|
51
132
|
*/
|
|
52
133
|
useEffect(() => {
|
|
53
|
-
if (
|
|
54
|
-
|
|
134
|
+
if (['Invalid', 'screen'].includes(screenName) && context.enableAutoId) {
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
navigator?.showModal({screen: EmptyScreen});
|
|
137
|
+
}, 300);
|
|
55
138
|
}
|
|
56
139
|
|
|
57
140
|
navigator?.maxApi?.of?.({screenName});
|
package/Application/index.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
HeaderAnimated,
|
|
6
6
|
HeaderBackground,
|
|
7
7
|
HeaderCustom,
|
|
8
|
-
HeaderRightAction,
|
|
9
8
|
HeaderTitle,
|
|
10
9
|
NavigationButton,
|
|
11
10
|
} from './Components';
|
|
@@ -31,7 +30,6 @@ export {
|
|
|
31
30
|
NavigationButton,
|
|
32
31
|
HeaderTitle,
|
|
33
32
|
HeaderBackground,
|
|
34
|
-
HeaderRightAction,
|
|
35
33
|
HeaderCustom,
|
|
36
34
|
HeaderAnimated,
|
|
37
35
|
};
|
package/Application/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
2
|
+
import {EventArg} from '@react-navigation/core';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import {Animated, ViewProps} from 'react-native';
|
|
4
5
|
import {PopupNotifyProps} from '../Popup/types';
|
|
@@ -144,19 +145,29 @@ export type RuntimeToolType = {
|
|
|
144
145
|
key: string;
|
|
145
146
|
};
|
|
146
147
|
|
|
147
|
-
export interface NavigationOptions
|
|
148
|
+
export interface NavigationOptions
|
|
149
|
+
extends Omit<StackNavigationOptions, 'headerRight'> {
|
|
148
150
|
preventBack?: PopupNotifyProps;
|
|
149
151
|
onPressLeftHeader?: () => void;
|
|
150
152
|
surface?: boolean;
|
|
151
153
|
hiddenBack?: boolean;
|
|
152
154
|
customTitle?: TitleCustomProps;
|
|
153
|
-
|
|
154
|
-
pinnedTool?: PinnedToolType;
|
|
155
|
-
runtimeTools?: RuntimeToolType[];
|
|
156
|
-
preventClose?: PopupNotifyProps;
|
|
157
|
-
};
|
|
155
|
+
headerRight?: HeaderRightToolkit | HeaderRightActions | any;
|
|
158
156
|
}
|
|
159
157
|
|
|
158
|
+
export type HeaderRightToolkit = {
|
|
159
|
+
type?: 'toolkit';
|
|
160
|
+
pinnedTool?: PinnedToolType;
|
|
161
|
+
runtimeTools?: RuntimeToolType[];
|
|
162
|
+
preventClose?: PopupNotifyProps;
|
|
163
|
+
useMore?: boolean;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export type HeaderRightActions = {
|
|
167
|
+
type?: 'icon';
|
|
168
|
+
buttons: NavigationButtonProps[];
|
|
169
|
+
};
|
|
170
|
+
|
|
160
171
|
export interface HeaderBackProps extends NavigationButtonProps {
|
|
161
172
|
preventBack?: PopupNotifyProps;
|
|
162
173
|
onPressLeftHeader?: () => void;
|
|
@@ -198,6 +209,11 @@ export type BottomTabItemProps = {
|
|
|
198
209
|
screen: Screen;
|
|
199
210
|
options: NavigationOptions;
|
|
200
211
|
initialParams?: any;
|
|
212
|
+
listeners?: {
|
|
213
|
+
tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
|
|
214
|
+
focus?: (e: EventArg<'focus', false, unknown>) => void;
|
|
215
|
+
blur?: (e: EventArg<'blur', false, unknown>) => void;
|
|
216
|
+
};
|
|
201
217
|
};
|
|
202
218
|
|
|
203
219
|
export type BottomTabProps = {
|
|
@@ -206,8 +222,9 @@ export type BottomTabProps = {
|
|
|
206
222
|
initialRouteName?: string;
|
|
207
223
|
navigation: Navigation;
|
|
208
224
|
listeners?: {
|
|
209
|
-
tabPress?:
|
|
210
|
-
focus?:
|
|
225
|
+
tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
|
|
226
|
+
focus?: (e: EventArg<'focus', false, unknown>) => void;
|
|
227
|
+
blur?: (e: EventArg<'blur', false, unknown>) => void;
|
|
211
228
|
};
|
|
212
229
|
floatingButton?: FloatingButtonProps;
|
|
213
230
|
};
|