@momo-kits/foundation 0.92.26-beta.0 → 0.92.26-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.
@@ -19,7 +19,6 @@ import {Icon} from '../Icon';
19
19
 
20
20
  const BottomSheet: React.FC<BottomSheetParams> = props => {
21
21
  const {theme, navigator} = useContext(ApplicationContext);
22
- const closed = useRef(false);
23
22
  const heightDevice = Dimensions.get('screen').height;
24
23
  const insets = useSafeAreaInsets();
25
24
  const {
@@ -75,12 +74,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
75
74
  Animated.timing(pan, {
76
75
  toValue: {x: 0, y: 0},
77
76
  useNativeDriver: false,
78
- duration: 200,
77
+ duration: 150,
79
78
  }).start();
80
79
  return () => {
81
- if (!closed.current) {
82
- navigator?.pop();
83
- }
84
80
  props.route.params?.onDismiss?.();
85
81
  };
86
82
  }, []);
@@ -92,16 +88,17 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
92
88
  if (barrierDismissible && !force) {
93
89
  return;
94
90
  }
95
- closed.current = true;
96
91
  setTimeout(() => {
97
- navigator?.pop();
98
92
  callback?.();
99
- }, 300);
93
+ }, 350);
94
+
100
95
  Animated.timing(pan, {
101
96
  toValue: {x: 0, y: heightDevice},
102
97
  useNativeDriver: false,
103
- duration: 200,
104
- }).start();
98
+ duration: 100,
99
+ }).start(() => {
100
+ navigator?.pop();
101
+ });
105
102
  };
106
103
 
107
104
  /**
@@ -168,7 +165,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
168
165
  <Screen
169
166
  {...props}
170
167
  {...props.route.params}
171
- // requestClose={requestClose}
168
+ requestClose={requestClose}
172
169
  />
173
170
  {useBottomInset && (
174
171
  <View style={{height: Math.min(insets.bottom, 21)}} />
@@ -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, theme);
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
- inputRange: [0, 200],
88
- outputRange: [0, 1],
89
- extrapolate: 'clamp',
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
- const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
267
- const validateType = (child: React.ReactElement) => {
268
- const valid = child?.type === NavigationButton || child?.type === Fragment;
269
- if (__DEV__ && !valid) {
270
- console.warn(
271
- 'HeaderRightAction contains element type of NavigationButton, Please check again.',
272
- );
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);
273
297
  }
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
- });
286
- }
287
-
288
298
  return (
289
- <View style={styles.headerButton}>
290
- {React.cloneElement(validateType(children), {...restProps})}
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
- return <View style={styles.headerRightButton}>{renderAction()}</View>;
313
+ }
314
+
315
+ return (
316
+ <View style={styles.headerRightButton} onLayout={onLayout}>
317
+ <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,
@@ -305,6 +333,7 @@ const HeaderToolkitAction: React.FC<any> = ({
305
333
  const [toolConfig, setToolConfig] = useState<any>();
306
334
  const {onAction} = toolConfig ?? {};
307
335
 
336
+ console.log('Toolconfig--------', toolConfig);
308
337
  let backgroundColor;
309
338
  if (tintColor !== Colors.black_01) {
310
339
  backgroundColor = 'transparent';
@@ -327,7 +356,7 @@ const HeaderToolkitAction: React.FC<any> = ({
327
356
  (config: any) => {
328
357
  navigator.toolkitConfig = config;
329
358
  setToolConfig(navigator?.toolkitConfig);
330
- },
359
+ }
331
360
  );
332
361
  };
333
362
 
@@ -340,7 +369,7 @@ const HeaderToolkitAction: React.FC<any> = ({
340
369
  const {item} = res;
341
370
  navigator?.toolkitCallback?.(item);
342
371
  getToolkitConfig();
343
- },
372
+ }
344
373
  );
345
374
  };
346
375
 
@@ -357,7 +386,7 @@ const HeaderToolkitAction: React.FC<any> = ({
357
386
  navigator?.maxApi?.dispatchFunction?.(
358
387
  'dismiss',
359
388
  undefined,
360
- undefined,
389
+ undefined
361
390
  );
362
391
  },
363
392
  }}
@@ -388,7 +417,7 @@ const HeaderToolkitAction: React.FC<any> = ({
388
417
  [pinTool?.key],
389
418
  () => {
390
419
  getToolkitConfig();
391
- },
420
+ }
392
421
  );
393
422
  navigator?.toolkitCallback?.(pinTool.key);
394
423
  }}
@@ -397,7 +426,7 @@ const HeaderToolkitAction: React.FC<any> = ({
397
426
  };
398
427
  if (toolConfig) {
399
428
  return (
400
- <View style={styles.headerRightButton}>
429
+ <View style={Styles.row}>
401
430
  {renderPinnedTool()}
402
431
  <View
403
432
  style={[
@@ -405,6 +434,7 @@ const HeaderToolkitAction: React.FC<any> = ({
405
434
  {
406
435
  backgroundColor: backgroundColor ?? '#00000066',
407
436
  borderWidth: backgroundColor ? 0.5 : 0,
437
+ marginLeft: renderPinnedTool() ? Spacing.S : 0,
408
438
  },
409
439
  ]}>
410
440
  <TouchableOpacity
@@ -430,6 +460,9 @@ const HeaderToolkitAction: React.FC<any> = ({
430
460
  return <View />;
431
461
  };
432
462
 
463
+ /**
464
+ * default header banner for header animated
465
+ */
433
466
  const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
434
467
  animatedValue,
435
468
  image,
@@ -470,6 +503,152 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
470
503
  );
471
504
  };
472
505
 
506
+ /**
507
+ * Header extended with background image
508
+ * @constructor
509
+ */
510
+ const HeaderExtendHeader: React.FC<{
511
+ headerType?: HeaderType;
512
+ animatedValue: Animated.Value;
513
+ heightHeader: number;
514
+ inputSearchProps?: InputSearchProps;
515
+ navigation?: Navigation;
516
+ }> = ({
517
+ headerType = 'default',
518
+ animatedValue,
519
+ heightHeader,
520
+ inputSearchProps,
521
+ navigation,
522
+ }) => {
523
+ const {theme} = useContext(ApplicationContext);
524
+
525
+ const heightAnimated = useRef(new Animated.Value(0));
526
+
527
+ useEffect(() => {
528
+ const listener = animatedValue.addListener(({value}) => {
529
+ heightAnimated.current.setValue(value);
530
+ });
531
+ return () => {
532
+ animatedValue?.removeListener(listener);
533
+ };
534
+ }, []);
535
+
536
+ if (inputSearchProps) {
537
+ if (headerType === 'surface') {
538
+ return (
539
+ <View
540
+ style={{
541
+ backgroundColor: theme.colors.background.surface,
542
+ borderBottomWidth: 1,
543
+ borderColor: theme.colors.border.default,
544
+ }}>
545
+ <Animated.View
546
+ style={{
547
+ justifyContent: 'flex-end',
548
+ height: heightAnimated.current.interpolate({
549
+ inputRange: [0, 100],
550
+ outputRange: [heightHeader + 52, heightHeader],
551
+ extrapolate: 'clamp',
552
+ }),
553
+ }}>
554
+ <AnimatedInputSearch
555
+ animatedValue={animatedValue}
556
+ navigation={navigation}
557
+ {...inputSearchProps}
558
+ hasColorBG={true}
559
+ />
560
+ </Animated.View>
561
+ </View>
562
+ );
563
+ }
564
+
565
+ if (headerType === 'extended') {
566
+ return (
567
+ <>
568
+ <Animated.View
569
+ style={[
570
+ styles.headerBox,
571
+ {
572
+ height: heightAnimated.current.interpolate({
573
+ inputRange: [0, 100],
574
+ outputRange: [heightHeader + 52, heightHeader],
575
+ extrapolate: 'clamp',
576
+ }),
577
+ },
578
+ ]}>
579
+ <Image
580
+ source={{
581
+ uri: theme.assets?.headerBackground,
582
+ }}
583
+ style={styles.headerBackground}
584
+ />
585
+ </Animated.View>
586
+
587
+ <Animated.View
588
+ style={{
589
+ justifyContent: 'flex-end',
590
+ height: heightAnimated.current.interpolate({
591
+ inputRange: [0, 100],
592
+ outputRange: [heightHeader + 52, heightHeader],
593
+ extrapolate: 'clamp',
594
+ }),
595
+ }}>
596
+ <AnimatedInputSearch
597
+ animatedValue={animatedValue}
598
+ navigation={navigation}
599
+ {...inputSearchProps}
600
+ />
601
+ </Animated.View>
602
+ </>
603
+ );
604
+ }
605
+
606
+ return (
607
+ <>
608
+ <View style={[styles.headerBox, {height: heightHeader}]}>
609
+ <Image
610
+ source={{
611
+ uri: theme.assets?.headerBackground,
612
+ }}
613
+ style={styles.headerBackground}
614
+ />
615
+ </View>
616
+
617
+ <Animated.View
618
+ style={{
619
+ justifyContent: 'flex-end',
620
+ height: heightAnimated.current.interpolate({
621
+ inputRange: [0, 100],
622
+ outputRange: [heightHeader + 52, heightHeader],
623
+ extrapolate: 'clamp',
624
+ }),
625
+ }}>
626
+ <AnimatedInputSearch
627
+ animatedValue={animatedValue}
628
+ navigation={navigation}
629
+ {...inputSearchProps}
630
+ />
631
+ </Animated.View>
632
+ </>
633
+ );
634
+ }
635
+
636
+ if (headerType === 'extended') {
637
+ return (
638
+ <View style={{minHeight: heightHeader}}>
639
+ <Image
640
+ source={{
641
+ uri: theme.assets?.headerBackground,
642
+ }}
643
+ style={styles.extendedHeader}
644
+ />
645
+ </View>
646
+ );
647
+ }
648
+
649
+ return <View />;
650
+ };
651
+
473
652
  const styles = StyleSheet.create({
474
653
  navigationButton: {
475
654
  height: 28,
@@ -509,7 +688,6 @@ const styles = StyleSheet.create({
509
688
  paddingRight: Spacing.M,
510
689
  },
511
690
  toolkitContainer: {
512
- marginLeft: Spacing.S,
513
691
  padding: Spacing.XS,
514
692
  height: 28,
515
693
  borderRadius: 14,
@@ -541,6 +719,17 @@ const styles = StyleSheet.create({
541
719
  top: -Spacing.XS,
542
720
  right: -Spacing.XS,
543
721
  },
722
+ extendedHeader: {
723
+ aspectRatio: 1.75,
724
+ position: 'absolute',
725
+ width: '100%',
726
+ height: 210,
727
+ },
728
+ headerBox: {
729
+ width: '100%',
730
+ position: 'absolute',
731
+ overflow: 'hidden',
732
+ },
544
733
  });
545
734
 
546
735
  export {
@@ -548,8 +737,9 @@ export {
548
737
  HeaderTitle,
549
738
  HeaderLeft,
550
739
  HeaderBackground,
551
- HeaderRightAction,
552
740
  HeaderToolkitAction,
553
741
  HeaderCustom,
554
742
  HeaderAnimated,
743
+ HeaderRight,
744
+ HeaderExtendHeader,
555
745
  };
@@ -21,10 +21,10 @@ const ModalScreen: React.FC<any> = props => {
21
21
  };
22
22
 
23
23
  const Modal: React.FC<ModalParams> = props => {
24
- const {theme, navigator} = useContext(ApplicationContext);
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, theme);
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, Theme} from './types';
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
- readonly theme: Theme;
7
+ rightHeaderWidth?: number;
11
8
 
12
- constructor(instance: any, theme: Theme) {
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.theme);
31
+ params = getOptions(this.filterParams(params), this);
46
32
  this.instance.setOptions(params);
47
33
  };
48
34
  }
@@ -88,7 +88,7 @@ const EmptyScreen: React.FC = () => {
88
88
  * @constructor
89
89
  */
90
90
  const StackScreen: React.FC<ScreenParams> = props => {
91
- const {theme, showGrid, navigator} = useContext(ApplicationContext);
91
+ const {showGrid, navigator} = useContext(ApplicationContext);
92
92
  const startTime = useRef(Date.now());
93
93
  const endTime = useRef(Date.now());
94
94
  const timeLoad = useRef(0);
@@ -104,7 +104,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
104
104
  const context = useContext<any>(MiniAppContext);
105
105
 
106
106
  const {screen: Component, options, initialParams} = props.route.params;
107
- const navigation = new Navigation(props.navigation, theme);
107
+ const navigation = new Navigation(props.navigation);
108
108
  const heightHeader = useHeaderHeight();
109
109
 
110
110
  const data = {
@@ -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
  };
@@ -145,19 +145,29 @@ export type RuntimeToolType = {
145
145
  key: string;
146
146
  };
147
147
 
148
- export interface NavigationOptions extends StackNavigationOptions {
148
+ export interface NavigationOptions
149
+ extends Omit<StackNavigationOptions, 'headerRight'> {
149
150
  preventBack?: PopupNotifyProps;
150
151
  onPressLeftHeader?: () => void;
151
152
  surface?: boolean;
152
153
  hiddenBack?: boolean;
153
154
  customTitle?: TitleCustomProps;
154
- toolkitParams?: {
155
- pinnedTool?: PinnedToolType;
156
- runtimeTools?: RuntimeToolType[];
157
- preventClose?: PopupNotifyProps;
158
- };
155
+ headerRight?: HeaderRightToolkit | HeaderRightActions | any;
159
156
  }
160
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
+
161
171
  export interface HeaderBackProps extends NavigationButtonProps {
162
172
  preventBack?: PopupNotifyProps;
163
173
  onPressLeftHeader?: () => void;