@momo-kits/foundation 0.81.49 → 0.81.51-beta.0

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.
Files changed (73) hide show
  1. package/Application/BottomSheet.tsx +216 -0
  2. package/Application/BottomTab/BottomTabBar.tsx +278 -0
  3. package/Application/{BottomTab.tsx → BottomTab/index.tsx} +42 -18
  4. package/Application/Components.tsx +356 -91
  5. package/Application/Localize.ts +44 -0
  6. package/Application/ModalScreen.tsx +14 -185
  7. package/Application/Navigation.ts +5 -19
  8. package/Application/NavigationContainer.tsx +62 -72
  9. package/Application/Navigator.ts +154 -48
  10. package/Application/StackScreen.tsx +289 -32
  11. package/Application/constants.ts +9 -0
  12. package/Application/index.ts +13 -15
  13. package/Application/types.ts +81 -35
  14. package/Application/utils.tsx +76 -30
  15. package/Assets/icon_bank.json +1 -1
  16. package/Badge/Badge.tsx +1 -1
  17. package/Badge/BadgeDotAnimation.tsx +95 -0
  18. package/Badge/index.tsx +2 -1
  19. package/Badge/styles.ts +50 -6
  20. package/Button/index.tsx +44 -26
  21. package/CheckBox/index.tsx +37 -26
  22. package/CheckBox/types.ts +5 -3
  23. package/Consts/colors+spacing+radius.ts +14 -0
  24. package/Icon/index.tsx +9 -8
  25. package/Icon/types.ts +2 -2
  26. package/IconButton/index.tsx +24 -14
  27. package/Image/index.tsx +23 -8
  28. package/Image/types.ts +2 -0
  29. package/Input/Input.tsx +116 -26
  30. package/Input/InputDropDown.tsx +66 -51
  31. package/Input/InputMoney.tsx +106 -15
  32. package/Input/InputOTP.tsx +49 -26
  33. package/Input/InputSearch.tsx +252 -99
  34. package/Input/InputTextArea.tsx +26 -6
  35. package/Input/TextTyping.tsx +113 -0
  36. package/Input/common.tsx +48 -22
  37. package/Input/index.tsx +112 -77
  38. package/Input/styles.ts +48 -11
  39. package/Input/utils.ts +1 -1
  40. package/Layout/Card.tsx +4 -3
  41. package/Layout/FloatingButton.tsx +168 -0
  42. package/Layout/GridSystem.tsx +1 -1
  43. package/Layout/ItemList.tsx +3 -2
  44. package/Layout/Screen.tsx +242 -121
  45. package/Layout/Section.tsx +4 -3
  46. package/Layout/styles.ts +11 -13
  47. package/Layout/types.ts +1 -1
  48. package/Layout/utils.ts +4 -4
  49. package/Loader/index.tsx +2 -0
  50. package/Pagination/PaginationScroll.tsx +2 -2
  51. package/Pagination/styles.ts +1 -1
  52. package/Popup/PopupNotify.tsx +57 -46
  53. package/Popup/PopupPromotion.tsx +6 -8
  54. package/Popup/types.ts +1 -7
  55. package/Radio/index.tsx +35 -20
  56. package/Radio/types.ts +5 -3
  57. package/Switch/index.tsx +32 -18
  58. package/Switch/types.ts +5 -3
  59. package/Tag/index.tsx +9 -2
  60. package/Tag/styles.ts +3 -2
  61. package/Tag/types.ts +12 -0
  62. package/Text/index.tsx +24 -5
  63. package/Text/styles.ts +8 -8
  64. package/Text/types.ts +19 -1
  65. package/Title/index.tsx +170 -103
  66. package/Title/styles.ts +36 -9
  67. package/Title/types.ts +16 -48
  68. package/code-scanner.js +125 -16
  69. package/index.ts +7 -0
  70. package/migrate_typo.js +56 -0
  71. package/package.json +10 -9
  72. package/publish.sh +16 -21
  73. package/tsconfig.json +1 -1
@@ -1,14 +1,17 @@
1
1
  import React, {
2
- Fragment,
2
+ Ref,
3
3
  useCallback,
4
4
  useContext,
5
5
  useEffect,
6
+ useRef,
6
7
  useState,
7
8
  } from 'react';
8
9
  import {
10
+ Alert,
9
11
  Animated,
10
12
  BackHandler,
11
13
  DeviceEventEmitter,
14
+ Dimensions,
12
15
  StatusBar,
13
16
  StyleSheet,
14
17
  TouchableOpacity,
@@ -29,7 +32,18 @@ import {scaleSize, Text} from '../Text';
29
32
  import {Icon} from '../Icon';
30
33
  import {PopupNotify} from '../Popup';
31
34
  import {Badge, BadgeDot} from '../Badge';
32
-
35
+ import {HeaderType} from '../Layout/types';
36
+ import Navigation from './Navigation';
37
+ import {InputRef, InputSearch, InputSearchProps} from '../Input';
38
+ import {BadgeDotAnimation} from '../Badge';
39
+
40
+ const SCREEN_PADDING = 12;
41
+ const BACK_WIDTH = 28;
42
+ const {width: screenWidth} = Dimensions.get('window');
43
+
44
+ /**
45
+ * default navigation button used header nav
46
+ */
33
47
  const NavigationButton: React.FC<NavigationButtonProps> = ({
34
48
  icon,
35
49
  tintColor,
@@ -37,10 +51,11 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
37
51
  useBorder = true,
38
52
  badgeType,
39
53
  badgeValue,
54
+ accessibilityLabel = '',
40
55
  }) => {
41
56
  const {theme} = useContext(ApplicationContext);
42
57
  let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
43
- if (tintColor != Colors.black_01) {
58
+ if (tintColor !== Colors.black_01) {
44
59
  buttonStyle = {
45
60
  backgroundColor: 'transparent',
46
61
  borderColor: '#00000066',
@@ -57,6 +72,11 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
57
72
  if (badgeType === 'dot') {
58
73
  return <BadgeDot size="small" style={styles.badgeDot} />;
59
74
  }
75
+ if (badgeType === 'dot-animation') {
76
+ return (
77
+ <BadgeDotAnimation size="small" style={styles.badgeDotAnimation} />
78
+ );
79
+ }
60
80
 
61
81
  if (isNumber(badgeValue)) {
62
82
  return <Badge label={badgeValue} style={styles.badge} />;
@@ -64,8 +84,9 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
64
84
  }, [badgeType, badgeValue]);
65
85
 
66
86
  return (
67
- <View style={{width: scaleSize(28)}}>
87
+ <View style={{width: 28}}>
68
88
  <TouchableOpacity
89
+ accessibilityLabel={accessibilityLabel}
69
90
  style={[styles.navigationButton, buttonStyle]}
70
91
  onPress={onPress}>
71
92
  <Icon
@@ -79,17 +100,23 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
79
100
  );
80
101
  };
81
102
 
103
+ /**
104
+ * default header title used for nav
105
+ */
82
106
  const HeaderTitle: React.FC<any> = props => {
83
107
  const {theme} = useContext(ApplicationContext);
84
- const opacity = props.animatedValue?.interpolate({
85
- inputRange: [0, 200],
86
- outputRange: [0, 1],
87
- extrapolate: 'clamp',
88
- });
108
+ const opacity = props.animatedValue?.interpolate(
109
+ props.interpolate ?? {
110
+ inputRange: [0, 200],
111
+ outputRange: [0, 1],
112
+ extrapolate: 'clamp',
113
+ }
114
+ );
89
115
 
90
116
  return (
91
117
  <Animated.Text
92
118
  {...props}
119
+ accessibilityLabel={'title_navigation_header'}
93
120
  style={[
94
121
  styles.title,
95
122
  {fontFamily: `${theme.font}-Bold`, opacity, color: props.tintColor},
@@ -98,19 +125,22 @@ const HeaderTitle: React.FC<any> = props => {
98
125
  );
99
126
  };
100
127
 
128
+ /**
129
+ * default header left used for nav
130
+ */
101
131
  const HeaderLeft: React.FC<HeaderBackProps> = ({
102
132
  tintColor,
103
133
  preventBack,
104
134
  onPressLeftHeader,
105
135
  useBorder,
106
136
  }) => {
107
- const context = useContext(MiniAppContext);
137
+ const context = useContext<any>(MiniAppContext);
108
138
  const {navigator} = useContext(ApplicationContext);
109
139
 
110
140
  useEffect(() => {
111
141
  const backHandler = BackHandler.addEventListener(
112
142
  'hardwareBackPress',
113
- goBackSafe,
143
+ goBackSafe
114
144
  );
115
145
 
116
146
  return () => backHandler.remove();
@@ -118,20 +148,25 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
118
148
 
119
149
  const goBackSafe = () => {
120
150
  const goBack = () => {
121
- const canGoBack = navigator?.ref.current?.canGoBack();
122
- if (!canGoBack) {
123
- const currentRoute = navigator?.ref?.current.getCurrentRoute();
124
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', {
125
- ...context,
126
- screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
127
- trigger_id: '111154000000000000',
128
- icon_name: 'back',
129
- });
130
- }
151
+ const canGoBack = navigator?.ref?.current?.canGoBack?.();
152
+ const currentRoute: any = navigator?.ref?.current?.getCurrentRoute?.();
153
+ const params = {
154
+ appId: context.appId,
155
+ code: context.code,
156
+ screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
157
+ trigger_id: '111154000000000000',
158
+ icon_name: 'back',
159
+ };
160
+ navigator?.maxApi?.showToastDebug?.({
161
+ appId: `auto - ${context.appId}`,
162
+ message: 'service_icon_clicked',
163
+ params,
164
+ });
165
+ navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
131
166
  if (canGoBack) {
132
- navigator?.ref.current?.goBack();
167
+ navigator?.ref?.current?.goBack?.();
133
168
  } else if (navigator?.maxApi) {
134
- navigator?.maxApi?.dismiss(navigator.dismissData);
169
+ navigator?.maxApi?.dismiss?.(navigator?.dismissData);
135
170
  } else {
136
171
  const currentTime = new Date().getTime();
137
172
  const requestId = `navigationBackPress#${currentTime}`;
@@ -164,6 +199,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
164
199
  return (
165
200
  <View style={styles.headerLeft}>
166
201
  <NavigationButton
202
+ accessibilityLabel="btn_navigation_back"
167
203
  icon="ic_back"
168
204
  tintColor={tintColor}
169
205
  onPress={goBackSafe}
@@ -173,17 +209,23 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
173
209
  );
174
210
  };
175
211
 
212
+ /**
213
+ * header background for default
214
+ */
176
215
  const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
177
216
  image,
178
- backgroundColor,
179
217
  animatedValue,
180
- useBorder = false,
218
+ useSurface = false,
181
219
  }) => {
182
220
  const {theme} = useContext(ApplicationContext);
183
221
  let headerImage = theme.assets?.headerBackground;
222
+ let backgroundColor;
184
223
  if (image === null) {
185
224
  headerImage = undefined;
186
225
  }
226
+ if (useSurface) {
227
+ backgroundColor = theme.colors.background.surface;
228
+ }
187
229
  const opacity = animatedValue?.interpolate({
188
230
  inputRange: [0, 114],
189
231
  outputRange: [0, 1],
@@ -195,9 +237,9 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
195
237
  style={[
196
238
  Styles.flex,
197
239
  {
198
- backgroundColor: backgroundColor ?? theme.colors.background.default,
240
+ backgroundColor,
199
241
  overflow: 'hidden',
200
- borderBottomWidth: useBorder ? 1 : 0,
242
+ borderBottomWidth: useSurface ? 1 : 0,
201
243
  borderColor: theme.colors.border.default,
202
244
  opacity,
203
245
  },
@@ -218,6 +260,10 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
218
260
  );
219
261
  };
220
262
 
263
+ /**
264
+ * Header custom with image, title, subtitle
265
+ * @constructor
266
+ */
221
267
  const HeaderCustom: React.FC<TitleCustomProps> = ({
222
268
  title,
223
269
  subTitle,
@@ -227,7 +273,7 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
227
273
  tintColor,
228
274
  dotColor,
229
275
  }) => {
230
- const avatarStyle = imageShape == 'circle' ? styles.circle : styles.square;
276
+ const avatarStyle = imageShape === 'circle' ? styles.circle : styles.square;
231
277
  const header = (
232
278
  <View style={Styles.row}>
233
279
  <View>
@@ -237,7 +283,10 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
237
283
  )}
238
284
  </View>
239
285
  <View style={[Styles.flex, {paddingHorizontal: 8}]}>
240
- <Text typography="header_default_bold" color={tintColor}>
286
+ <Text
287
+ accessibilityLabel={'title_navigation_header'}
288
+ typography="header_default_bold"
289
+ color={tintColor}>
241
290
  {title}
242
291
  </Text>
243
292
  <Text typography="description_default_regular" color={tintColor}>
@@ -249,51 +298,55 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
249
298
  return <View style={styles.headerTitleContainer}>{content ?? header}</View>;
250
299
  };
251
300
 
252
- const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
253
- const validateType = (child: React.ReactElement) => {
254
- const valid = child?.type === NavigationButton || child?.type == Fragment;
255
- if (__DEV__ && !valid) {
256
- console.warn(
257
- 'HeaderRightAction contains element type of NavigationButton, Please check again.',
258
- );
259
- }
260
- return child;
261
- };
262
-
263
- const renderAction = () => {
264
- if (Array.isArray(children)) {
265
- return children.map((child, index) => {
266
- return (
267
- <View key={`HeaderRightAction ${index}`} style={styles.headerButton}>
268
- {React.cloneElement(validateType(child), {...restProps})}
269
- </View>
270
- );
271
- });
301
+ /**
302
+ * main component for header right
303
+ */
304
+ const HeaderRight: React.FC<any> = ({type, children, onLayout, ...props}) => {
305
+ if (type === 'icon') {
306
+ let buttons = props?.buttons || [];
307
+ if (buttons?.length > 3) {
308
+ buttons = buttons.slice(0, 3);
272
309
  }
273
-
274
310
  return (
275
- <View style={styles.headerButton}>
276
- {React.cloneElement(validateType(children), {...restProps})}
311
+ <View style={styles.headerRightButton} onLayout={onLayout}>
312
+ {buttons?.map?.((item: NavigationButtonProps, index: number) => {
313
+ return (
314
+ <View
315
+ key={`HeaderRightAction ${index}`}
316
+ style={{
317
+ marginLeft: index !== 0 ? Spacing.S : 0,
318
+ }}>
319
+ <NavigationButton {...item} tintColor={props?.tintColor} />
320
+ </View>
321
+ );
322
+ })}
277
323
  </View>
278
324
  );
279
- };
280
- return <View style={styles.headerRightButton}>{renderAction()}</View>;
325
+ }
326
+
327
+ return (
328
+ <View style={styles.headerRightButton} onLayout={onLayout}>
329
+ {children ?? <HeaderToolkitAction {...props} />}
330
+ </View>
331
+ );
281
332
  };
282
333
 
334
+ /**
335
+ * Header toolkit action
336
+ */
283
337
  const HeaderToolkitAction: React.FC<any> = ({
284
338
  tintColor,
285
339
  pinnedTool,
286
- runtimeTools = [],
287
- preventBack,
340
+ preventClose,
288
341
  }) => {
289
- const {theme, navigator} = useContext(ApplicationContext);
290
- const miniContext = useContext(MiniAppContext);
342
+ const {navigator} = useContext(ApplicationContext);
343
+ const miniContext = useContext<any>(MiniAppContext);
291
344
  const [toolConfig, setToolConfig] = useState<any>();
292
345
  const {onAction} = toolConfig ?? {};
293
346
 
294
347
  let backgroundColor;
295
- if (tintColor != Colors.black_01) {
296
- backgroundColor = theme.colors.background.surface;
348
+ if (tintColor !== Colors.black_01) {
349
+ backgroundColor = 'transparent';
297
350
  }
298
351
 
299
352
  useEffect(() => {
@@ -313,37 +366,39 @@ const HeaderToolkitAction: React.FC<any> = ({
313
366
  (config: any) => {
314
367
  navigator.toolkitConfig = config;
315
368
  setToolConfig(navigator?.toolkitConfig);
316
- },
369
+ }
317
370
  );
318
371
  };
319
372
 
320
373
  const onMore = () => {
321
374
  onAction?.('onMore');
322
375
  navigator?.maxApi?.dispatchFunction?.(
323
- 'showTools',
324
- {runtimeTools},
325
- (res: {item: {action?: string; key: string}}) => {
326
- const {item} = res;
327
- navigator?.toolkitCallback?.(item);
328
- getToolkitConfig();
376
+ 'showToolkit',
377
+ {
378
+ tools: miniContext?.toolkitConfig?.oldTools ?? [
379
+ 'addFavorite',
380
+ 'addShortcut',
381
+ 'share',
382
+ ],
329
383
  },
384
+ () => {}
330
385
  );
331
386
  };
332
387
 
333
388
  const onClose = () => {
334
- if (preventBack) {
389
+ if (preventClose) {
335
390
  navigator?.showModal({
336
391
  screen: () => (
337
392
  <PopupNotify
338
- {...preventBack}
393
+ {...preventClose}
339
394
  primary={{
340
- title: preventBack.primary.title,
395
+ title: preventClose.primary.title,
341
396
  onPress: () => {
342
- preventBack?.primary.onPress();
397
+ preventClose?.primary.onPress();
343
398
  navigator?.maxApi?.dispatchFunction?.(
344
399
  'dismiss',
345
400
  undefined,
346
- undefined,
401
+ undefined
347
402
  );
348
403
  },
349
404
  }}
@@ -363,6 +418,7 @@ const HeaderToolkitAction: React.FC<any> = ({
363
418
  if (pinTool)
364
419
  return (
365
420
  <NavigationButton
421
+ accessibilityLabel="btn_navigation_pin"
366
422
  icon={pinTool.icon as string}
367
423
  tintColor={tintColor}
368
424
  badgeValue={badgeValue}
@@ -370,20 +426,19 @@ const HeaderToolkitAction: React.FC<any> = ({
370
426
  onPress={() => {
371
427
  navigator?.maxApi?.dispatchFunction?.(
372
428
  'onToolAction',
373
- [pinTool?.key],
429
+ {item: pinTool},
374
430
  () => {
375
431
  getToolkitConfig();
376
- },
432
+ }
377
433
  );
378
434
  navigator?.toolkitCallback?.(pinTool.key);
379
435
  }}
380
436
  />
381
437
  );
382
438
  };
383
-
384
439
  if (toolConfig) {
385
440
  return (
386
- <View style={styles.headerRightButton}>
441
+ <View style={Styles.row}>
387
442
  {renderPinnedTool()}
388
443
  <View
389
444
  style={[
@@ -391,13 +446,18 @@ const HeaderToolkitAction: React.FC<any> = ({
391
446
  {
392
447
  backgroundColor: backgroundColor ?? '#00000066',
393
448
  borderWidth: backgroundColor ? 0.5 : 0,
449
+ marginLeft: renderPinnedTool() ? Spacing.S : 0,
394
450
  },
395
451
  ]}>
396
- <TouchableOpacity onPress={onMore}>
452
+ <TouchableOpacity
453
+ accessibilityLabel={'btn_navigation_more'}
454
+ onPress={onMore}>
397
455
  <Icon color={tintColor} source="navigation_more_horiz" size={20} />
398
456
  </TouchableOpacity>
399
457
  <View style={[styles.divider, {backgroundColor: tintColor}]} />
400
- <TouchableOpacity onPress={onClose}>
458
+ <TouchableOpacity
459
+ accessibilityLabel={'btn_navigation_close'}
460
+ onPress={onClose}>
401
461
  <Icon
402
462
  color={tintColor}
403
463
  source="16_navigation_close_circle"
@@ -412,10 +472,13 @@ const HeaderToolkitAction: React.FC<any> = ({
412
472
  return <View />;
413
473
  };
414
474
 
475
+ /**
476
+ * default header banner for header animated
477
+ */
415
478
  const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
416
479
  animatedValue,
417
480
  image,
418
- onPress,
481
+ children,
419
482
  }) => {
420
483
  const scale = animatedValue.interpolate({
421
484
  inputRange: [-300, 0, 300],
@@ -434,24 +497,209 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
434
497
  });
435
498
 
436
499
  return (
437
- <TouchableOpacity onPress={onPress}>
438
- <Animated.View
439
- style={{
440
- height: 210,
441
- opacity: opacity,
442
- transform: [{scale}, {translateY}],
443
- }}>
500
+ <Animated.View
501
+ style={{
502
+ height: 210,
503
+ opacity: opacity,
504
+ transform: [{scale}, {translateY}],
505
+ }}>
506
+ {children ?? (
444
507
  <Image
445
508
  source={{
446
509
  uri: image,
447
510
  }}
448
511
  style={{width: '100%', height: '100%'}}
449
512
  />
450
- </Animated.View>
451
- </TouchableOpacity>
513
+ )}
514
+ </Animated.View>
452
515
  );
453
516
  };
454
517
 
518
+ /**
519
+ * Header extended with background image
520
+ * @constructor
521
+ */
522
+ const HeaderExtendHeader: React.FC<{
523
+ headerType?: HeaderType;
524
+ animatedValue: Animated.Value;
525
+ heightHeader: number;
526
+ inputSearchProps?: InputSearchProps;
527
+ inputSearchRef?: Ref<InputRef>;
528
+ navigation?: Navigation;
529
+ }> = ({
530
+ headerType = 'default',
531
+ animatedValue,
532
+ heightHeader,
533
+ inputSearchProps,
534
+ inputSearchRef,
535
+ navigation,
536
+ }) => {
537
+ const {theme} = useContext(ApplicationContext);
538
+ const [rightSpace, setRightSpace] = useState(0);
539
+ const animated = useRef(new Animated.Value(0));
540
+
541
+ useEffect(() => {
542
+ const listener = animatedValue.addListener(({value}) => {
543
+ animated.current.setValue(value);
544
+ });
545
+ return () => {
546
+ animatedValue?.removeListener(listener);
547
+ };
548
+ }, []);
549
+
550
+ const height = animated.current.interpolate({
551
+ inputRange: [0, 100],
552
+ outputRange: [heightHeader + 52, heightHeader],
553
+ extrapolate: 'clamp',
554
+ });
555
+
556
+ const translateX = animated.current.interpolate({
557
+ inputRange: [0, 100],
558
+ outputRange: [SCREEN_PADDING, BACK_WIDTH + SCREEN_PADDING * 2],
559
+ extrapolate: 'clamp',
560
+ });
561
+
562
+ if (navigation) {
563
+ navigation.onHeaderRightChange = (width: number) => {
564
+ setRightSpace(width);
565
+ };
566
+ }
567
+
568
+ const renderInputView = (hasColorBG: boolean = false) => {
569
+ return (
570
+ <Animated.View
571
+ style={{
572
+ justifyContent: 'flex-end',
573
+ height,
574
+ }}>
575
+ <Animated.View
576
+ style={{
577
+ transform: [{translateX}],
578
+ marginVertical: Spacing.S,
579
+ width: animated.current.interpolate({
580
+ inputRange: [0, 100],
581
+ outputRange: [
582
+ screenWidth - SCREEN_PADDING * 2,
583
+ screenWidth - SCREEN_PADDING * 3 - BACK_WIDTH - rightSpace,
584
+ ],
585
+ extrapolate: 'clamp',
586
+ }),
587
+ }}>
588
+ <InputSearch
589
+ {...inputSearchProps}
590
+ ref={inputSearchRef}
591
+ hasColorBG={hasColorBG}
592
+ showButtonText={false}
593
+ />
594
+ </Animated.View>
595
+ </Animated.View>
596
+ );
597
+ };
598
+
599
+ if (inputSearchProps) {
600
+ if (headerType === 'surface') {
601
+ return (
602
+ <>
603
+ <Animated.View
604
+ style={[
605
+ styles.headerBox,
606
+ {
607
+ backgroundColor: theme.colors.background.surface,
608
+ borderBottomWidth: 1,
609
+ borderColor: theme.colors.border.default,
610
+ height,
611
+ },
612
+ ]}
613
+ />
614
+ {renderInputView(true)}
615
+ </>
616
+ );
617
+ }
618
+
619
+ if (headerType === 'extended') {
620
+ return (
621
+ <>
622
+ <Animated.View
623
+ style={[
624
+ styles.headerBox,
625
+ {
626
+ height,
627
+ },
628
+ ]}>
629
+ <Image
630
+ source={{
631
+ uri: theme.assets?.headerBackground,
632
+ }}
633
+ style={styles.headerBackground}
634
+ />
635
+ </Animated.View>
636
+ {renderInputView()}
637
+ </>
638
+ );
639
+ }
640
+
641
+ return (
642
+ <>
643
+ <View style={[styles.headerBox, {height: heightHeader}]}>
644
+ <Image
645
+ source={{
646
+ uri: theme.assets?.headerBackground,
647
+ }}
648
+ style={styles.headerBackground}
649
+ />
650
+ </View>
651
+ {renderInputView()}
652
+ </>
653
+ );
654
+ }
655
+
656
+ if (headerType === 'extended') {
657
+ return (
658
+ <View style={{minHeight: heightHeader}}>
659
+ <Image
660
+ source={{
661
+ uri: theme.assets?.headerBackground,
662
+ }}
663
+ style={styles.extendedHeader}
664
+ />
665
+ </View>
666
+ );
667
+ }
668
+
669
+ return <View />;
670
+ };
671
+
672
+ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
673
+ if (__DEV__) {
674
+ Alert.alert(
675
+ 'HeaderRightAction',
676
+ 'This component is deprecated and will removed 10/2024, please use new type headerRight specs instead v0.92.34'
677
+ );
678
+ }
679
+ const validateType = (child: React.ReactElement) => {
680
+ return child;
681
+ };
682
+
683
+ const renderAction = () => {
684
+ if (Array.isArray(children)) {
685
+ return children.map((child, index) => {
686
+ return (
687
+ <View key={`HeaderRightAction ${index}`} style={styles.headerButton}>
688
+ {React.cloneElement(validateType(child), {...restProps})}
689
+ </View>
690
+ );
691
+ });
692
+ }
693
+
694
+ return (
695
+ <View style={styles.headerButton}>
696
+ {React.cloneElement(validateType(children), {...restProps})}
697
+ </View>
698
+ );
699
+ };
700
+ return <View style={styles.headerRightButton}>{renderAction()}</View>;
701
+ };
702
+
455
703
  const styles = StyleSheet.create({
456
704
  navigationButton: {
457
705
  height: 28,
@@ -488,10 +736,9 @@ const styles = StyleSheet.create({
488
736
  flexDirection: 'row',
489
737
  justifyContent: 'center',
490
738
  alignItems: 'center',
491
- paddingRight: Spacing.S,
739
+ paddingRight: Spacing.M,
492
740
  },
493
741
  toolkitContainer: {
494
- marginLeft: Spacing.S,
495
742
  padding: Spacing.XS,
496
743
  height: 28,
497
744
  borderRadius: 14,
@@ -523,6 +770,22 @@ const styles = StyleSheet.create({
523
770
  top: -Spacing.XS,
524
771
  right: -Spacing.XS,
525
772
  },
773
+ badgeDotAnimation: {
774
+ position: 'absolute',
775
+ top: -Spacing.XS,
776
+ right: -Spacing.XS,
777
+ },
778
+ extendedHeader: {
779
+ aspectRatio: 1.75,
780
+ position: 'absolute',
781
+ width: '100%',
782
+ height: 210,
783
+ },
784
+ headerBox: {
785
+ width: '100%',
786
+ position: 'absolute',
787
+ overflow: 'hidden',
788
+ },
526
789
  });
527
790
 
528
791
  export {
@@ -530,8 +793,10 @@ export {
530
793
  HeaderTitle,
531
794
  HeaderLeft,
532
795
  HeaderBackground,
533
- HeaderRightAction,
534
796
  HeaderToolkitAction,
535
797
  HeaderCustom,
536
798
  HeaderAnimated,
799
+ HeaderRight,
800
+ HeaderExtendHeader,
801
+ HeaderRightAction,
537
802
  };