@momo-kits/foundation 0.76.1-beta.1 → 0.77.1-optimize.2

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 (100) hide show
  1. package/Application/BottomTab/BottomTabBar.tsx +478 -0
  2. package/Application/BottomTab/index.tsx +134 -0
  3. package/Application/Components.tsx +339 -161
  4. package/Application/ModalScreen.tsx +113 -99
  5. package/Application/Navigation.ts +22 -16
  6. package/Application/NavigationContainer.tsx +99 -48
  7. package/Application/Navigator.ts +110 -41
  8. package/Application/StackScreen.tsx +126 -8
  9. package/Application/index.ts +23 -4
  10. package/Application/types.ts +84 -33
  11. package/Application/utils.tsx +90 -50
  12. package/Assets/DotAnimation.json +256 -0
  13. package/Assets/SpinnerAnimation.json +1027 -0
  14. package/Assets/icon.json +83 -5
  15. package/Assets/icon_bank.json +506 -0
  16. package/Assets/language.json +202 -0
  17. package/Badge/Badge.tsx +56 -0
  18. package/Badge/BadgeDot.tsx +11 -0
  19. package/Badge/BadgeRibbon.tsx +125 -0
  20. package/Badge/Shape.tsx +29 -0
  21. package/Badge/index.tsx +7 -0
  22. package/Badge/styles.ts +58 -0
  23. package/Badge/types.ts +63 -0
  24. package/Button/index.tsx +90 -39
  25. package/Button/styles.ts +19 -0
  26. package/CheckBox/index.tsx +58 -43
  27. package/CheckBox/styles.ts +1 -1
  28. package/CheckBox/types.ts +6 -4
  29. package/Consts/colors+spacing+radius.ts +18 -0
  30. package/Consts/styles.ts +0 -26
  31. package/Consts/theme.ts +4 -0
  32. package/Divider/index.tsx +2 -0
  33. package/Icon/index.tsx +13 -9
  34. package/Icon/types.ts +4 -3
  35. package/IconButton/index.tsx +24 -15
  36. package/Image/index.tsx +60 -48
  37. package/Image/styles.ts +1 -9
  38. package/Image/types.ts +5 -1
  39. package/Input/Input.tsx +227 -116
  40. package/Input/InputDropDown.tsx +132 -0
  41. package/Input/InputMoney.tsx +174 -111
  42. package/Input/InputOTP.tsx +257 -0
  43. package/Input/InputSearch.tsx +160 -132
  44. package/Input/InputTextArea.tsx +150 -123
  45. package/Input/common.tsx +42 -17
  46. package/Input/index.tsx +204 -18
  47. package/Input/styles.ts +44 -7
  48. package/Input/utils.ts +2 -2
  49. package/Layout/Card.tsx +67 -29
  50. package/Layout/FloatingButton.tsx +128 -0
  51. package/Layout/GridSystem.tsx +31 -21
  52. package/Layout/Item.tsx +21 -25
  53. package/Layout/ItemList.tsx +55 -0
  54. package/Layout/ItemSectionList.tsx +39 -0
  55. package/Layout/Screen.tsx +348 -153
  56. package/Layout/Section.tsx +66 -34
  57. package/Layout/index.ts +13 -3
  58. package/Layout/styles.ts +101 -0
  59. package/Layout/types.ts +1 -39
  60. package/Layout/utils.ts +27 -52
  61. package/Loader/DotLoader.tsx +37 -0
  62. package/Loader/Loader.tsx +13 -0
  63. package/Loader/ProgressBar.tsx +44 -0
  64. package/Loader/Spinner.tsx +29 -0
  65. package/Loader/index.tsx +4 -0
  66. package/Loader/styles.ts +10 -0
  67. package/Loader/types.ts +35 -0
  68. package/Loader/utils.ts +25 -0
  69. package/Pagination/PaginationDot.tsx +7 -2
  70. package/Pagination/PaginationNumber.tsx +8 -6
  71. package/Pagination/PaginationScroll.tsx +0 -1
  72. package/Pagination/PaginationWhiteDot.tsx +8 -5
  73. package/Pagination/styles.ts +3 -0
  74. package/Pagination/types.ts +2 -0
  75. package/Popup/PopupNotify.tsx +102 -44
  76. package/Popup/PopupPromotion.tsx +63 -22
  77. package/Popup/types.ts +15 -4
  78. package/Radio/index.tsx +35 -21
  79. package/Radio/types.ts +7 -5
  80. package/Skeleton/index.tsx +1 -1
  81. package/Skeleton/types.ts +3 -0
  82. package/Switch/index.tsx +35 -24
  83. package/Switch/types.ts +5 -3
  84. package/Tag/index.tsx +2 -4
  85. package/Text/index.tsx +27 -22
  86. package/Text/styles.ts +38 -0
  87. package/Text/types.ts +25 -13
  88. package/Text/utils.ts +1 -1
  89. package/Title/index.tsx +186 -0
  90. package/Title/styles.ts +79 -0
  91. package/Title/types.ts +20 -0
  92. package/code-scanner.js +143 -0
  93. package/index.ts +8 -1
  94. package/migrate_typo.js +56 -0
  95. package/package.json +14 -9
  96. package/tsconfig.json +24 -0
  97. package/verify.js +47 -0
  98. package/Application/BottomTab.tsx +0 -52
  99. package/Application/NavigationButton.tsx +0 -54
  100. package/Assets/header-background.png +0 -0
@@ -1,81 +1,85 @@
1
- import React, {useContext, useEffect, useState} from 'react';
1
+ import React, {
2
+ Fragment,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useState,
7
+ } from 'react';
2
8
  import {
3
9
  Animated,
10
+ BackHandler,
4
11
  DeviceEventEmitter,
5
12
  StatusBar,
6
13
  StyleSheet,
7
14
  TouchableOpacity,
8
15
  View,
16
+ ViewStyle,
9
17
  } from 'react-native';
10
- import {ApplicationContext, NavigationButton} from './index';
18
+ import {ApplicationContext, MiniAppContext} from './index';
11
19
  import {Colors, Radius, Spacing, Styles} from '../Consts';
12
20
  import {Image} from '../Image';
13
21
  import {
22
+ HeaderAnimatedProps,
14
23
  HeaderBackgroundProps,
15
24
  HeaderBackProps,
16
- HeaderToolkitProps,
25
+ NavigationButtonProps,
17
26
  TitleCustomProps,
18
27
  } from './types';
19
28
  import {scaleSize, Text} from '../Text';
20
29
  import {Icon} from '../Icon';
21
30
  import {PopupNotify} from '../Popup';
31
+ import {Badge, BadgeDot} from '../Badge';
22
32
 
23
- const styles = StyleSheet.create({
24
- headerBackground: {
25
- width: '100%',
26
- height: undefined,
27
- position: 'absolute',
28
- aspectRatio: 375 / 154,
29
- },
30
- headerTitleContainer: {
31
- alignItems: 'center',
32
- justifyContent: 'center',
33
- width: '100%',
34
- },
35
- circle: {width: 36, height: 36, borderRadius: 18},
36
- square: {width: 36, height: 36, borderRadius: Radius.XS},
37
- dotAvatar: {
38
- position: 'absolute',
39
- width: 12,
40
- height: 12,
41
- borderRadius: 6,
42
- bottom: 0,
43
- right: 0,
44
- borderWidth: 1,
45
- borderColor: Colors.black_01,
46
- },
47
- headerButton: {paddingHorizontal: 4},
48
- headerRightButton: {
49
- flexDirection: 'row',
50
- overflow: 'hidden',
51
- justifyContent: 'center',
52
- alignItems: 'center',
53
- paddingRight: Spacing.S,
54
- },
55
- toolkitContainer: {
56
- marginLeft: Spacing.S,
57
- padding: Spacing.XS,
58
- height: 28,
59
- borderRadius: 14,
60
- borderColor: '#00000066',
61
- justifyContent: 'center',
62
- alignItems: 'center',
63
- flexDirection: 'row',
64
- },
65
- divider: {
66
- width: 1,
67
- height: 12,
68
- marginHorizontal: 4,
69
- },
70
- headerLeft: {
71
- marginLeft: 12,
72
- },
73
- title: {
74
- fontSize: scaleSize(15),
75
- lineHeight: scaleSize(22),
76
- fontWeight: 'bold',
77
- },
78
- });
33
+ const NavigationButton: React.FC<NavigationButtonProps> = ({
34
+ icon,
35
+ tintColor,
36
+ onPress,
37
+ useBorder = true,
38
+ badgeType,
39
+ badgeValue,
40
+ accessibilityLabel = '',
41
+ }) => {
42
+ const {theme} = useContext(ApplicationContext);
43
+ let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
44
+ if (tintColor != Colors.black_01) {
45
+ buttonStyle = {
46
+ backgroundColor: 'transparent',
47
+ borderColor: '#00000066',
48
+ borderWidth: useBorder ? 0.5 : 0,
49
+ };
50
+ }
51
+
52
+ const isNumber = (label: any) => {
53
+ const numberRegex = /^\d+$/;
54
+ return numberRegex.test(String(label));
55
+ };
56
+
57
+ const renderBadge = useCallback(() => {
58
+ if (badgeType === 'dot') {
59
+ return <BadgeDot size="small" style={styles.badgeDot} />;
60
+ }
61
+
62
+ if (isNumber(badgeValue)) {
63
+ return <Badge label={badgeValue} style={styles.badge} />;
64
+ }
65
+ }, [badgeType, badgeValue]);
66
+
67
+ return (
68
+ <View style={{width: scaleSize(28)}}>
69
+ <TouchableOpacity
70
+ accessibilityLabel={accessibilityLabel}
71
+ style={[styles.navigationButton, buttonStyle]}
72
+ onPress={onPress}>
73
+ <Icon
74
+ source={icon}
75
+ color={tintColor ?? theme.colors.text.default}
76
+ size={20}
77
+ />
78
+ </TouchableOpacity>
79
+ {renderBadge()}
80
+ </View>
81
+ );
82
+ };
79
83
 
80
84
  const HeaderTitle: React.FC<any> = props => {
81
85
  const {theme} = useContext(ApplicationContext);
@@ -88,7 +92,7 @@ const HeaderTitle: React.FC<any> = props => {
88
92
  return (
89
93
  <Animated.Text
90
94
  {...props}
91
- accessibilityLabel={`HeaderTitle/${props.children}`}
95
+ accessibilityLabel={'title_navigation_header'}
92
96
  style={[
93
97
  styles.title,
94
98
  {fontFamily: `${theme.font}-Bold`, opacity, color: props.tintColor},
@@ -100,47 +104,78 @@ const HeaderTitle: React.FC<any> = props => {
100
104
  const HeaderLeft: React.FC<HeaderBackProps> = ({
101
105
  tintColor,
102
106
  preventBack,
107
+ onPressLeftHeader,
103
108
  useBorder,
104
- backgroundColor,
105
109
  }) => {
110
+ const context = useContext<any>(MiniAppContext);
106
111
  const {navigator} = useContext(ApplicationContext);
107
- const goBack = () => {
108
- const canGoBack = navigator?.ref.current?.canGoBack();
109
- if (canGoBack) {
110
- if (preventBack) {
111
- navigator?.showModal({
112
- screen: () => (
113
- <PopupNotify
114
- {...preventBack}
115
- primary={{
116
- title: preventBack.primary.title,
117
- onPress: () => {
118
- preventBack?.primary.onPress();
119
- navigator?.ref.current?.goBack();
120
- },
121
- }}
122
- />
123
- ),
124
- });
112
+
113
+ useEffect(() => {
114
+ const backHandler = BackHandler.addEventListener(
115
+ 'hardwareBackPress',
116
+ goBackSafe,
117
+ );
118
+
119
+ return () => backHandler.remove();
120
+ }, []);
121
+
122
+ const goBackSafe = () => {
123
+ const goBack = () => {
124
+ const canGoBack = navigator?.ref?.current?.canGoBack?.();
125
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
126
+ const params = {
127
+ appId: context.appId,
128
+ code: context.code,
129
+ screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
130
+ trigger_id: '111154000000000000',
131
+ icon_name: 'back',
132
+ };
133
+ navigator?.maxApi?.showToastDebug?.({
134
+ appId: `auto - ${context.appId}`,
135
+ message: 'service_icon_clicked',
136
+ params,
137
+ });
138
+ navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
139
+ if (canGoBack) {
140
+ navigator?.ref?.current?.goBack?.();
141
+ } else if (navigator?.maxApi) {
142
+ navigator?.maxApi?.dismiss?.(navigator?.dismissData);
125
143
  } else {
126
- navigator?.ref.current?.goBack();
144
+ const currentTime = new Date().getTime();
145
+ const requestId = `navigationBackPress#${currentTime}`;
146
+ DeviceEventEmitter.emit('dismiss', {requestId});
127
147
  }
148
+ onPressLeftHeader?.();
149
+ };
150
+
151
+ if (preventBack) {
152
+ navigator?.showModal({
153
+ screen: () => (
154
+ <PopupNotify
155
+ {...preventBack}
156
+ primary={{
157
+ title: preventBack.primary.title,
158
+ onPress: () => {
159
+ preventBack?.primary.onPress();
160
+ goBack();
161
+ },
162
+ }}
163
+ />
164
+ ),
165
+ });
128
166
  } else {
129
- const currentTime = new Date().getTime();
130
- const requestId = `navigationBackPress#${currentTime}`;
131
- DeviceEventEmitter.emit('dismiss', {requestId});
167
+ goBack();
132
168
  }
169
+ return true;
133
170
  };
134
-
135
171
  return (
136
172
  <View style={styles.headerLeft}>
137
173
  <NavigationButton
174
+ accessibilityLabel="btn_navigation_back"
138
175
  icon="ic_back"
139
176
  tintColor={tintColor}
140
- onPress={goBack}
141
- accessibilityLabel={'Back'}
177
+ onPress={goBackSafe}
142
178
  useBorder={useBorder}
143
- backgroundColor={backgroundColor}
144
179
  />
145
180
  </View>
146
181
  );
@@ -158,7 +193,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
158
193
  headerImage = undefined;
159
194
  }
160
195
  const opacity = animatedValue?.interpolate({
161
- inputRange: [0, 200],
196
+ inputRange: [0, 114],
162
197
  outputRange: [0, 1],
163
198
  extrapolate: 'clamp',
164
199
  });
@@ -177,9 +212,15 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
177
212
  ]}>
178
213
  <StatusBar
179
214
  barStyle={headerImage || theme.dark ? 'light-content' : 'dark-content'}
215
+ translucent={true}
216
+ backgroundColor={'transparent'}
180
217
  />
181
218
  {!!headerImage && (
182
- <Image style={styles.headerBackground} source={{uri: headerImage}} />
219
+ <Image
220
+ style={styles.headerBackground}
221
+ source={{uri: headerImage}}
222
+ loading={false}
223
+ />
183
224
  )}
184
225
  </Animated.View>
185
226
  );
@@ -203,11 +244,14 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
203
244
  <View style={[styles.dotAvatar, {backgroundColor: dotColor}]} />
204
245
  )}
205
246
  </View>
206
- <View style={[Styles.flex, Styles.paddingHorizontal8]}>
207
- <Text typography="title_xs" color={tintColor}>
247
+ <View style={[Styles.flex, {paddingHorizontal: 8}]}>
248
+ <Text
249
+ accessibilityLabel={'title_navigation_header'}
250
+ typography="header_default_bold"
251
+ color={tintColor}>
208
252
  {title}
209
253
  </Text>
210
- <Text typography="description_s" color={tintColor}>
254
+ <Text typography="description_default_regular" color={tintColor}>
211
255
  {subTitle}
212
256
  </Text>
213
257
  </View>
@@ -217,40 +261,46 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
217
261
  };
218
262
 
219
263
  const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
220
- const validType = (item: any) => {
221
- if (__DEV__ && item.type !== NavigationButton) {
264
+ const validateType = (child: React.ReactElement) => {
265
+ const valid = child?.type === NavigationButton || child?.type == Fragment;
266
+ if (__DEV__ && !valid) {
222
267
  console.warn(
223
- 'element type of NavigationButton, Please migrate to use NavigationButton of kits.',
268
+ 'HeaderRightAction contains element type of NavigationButton, Please check again.',
224
269
  );
225
- return <View />;
226
270
  }
271
+ return child;
227
272
  };
273
+
228
274
  const renderAction = () => {
229
275
  if (Array.isArray(children)) {
230
276
  return children.map((child, index) => {
231
- validType(child);
232
277
  return (
233
- <View key={index} style={styles.headerButton}>
234
- {React.cloneElement(child, {...restProps})}
278
+ <View key={`HeaderRightAction ${index}`} style={styles.headerButton}>
279
+ {React.cloneElement(validateType(child), {...restProps})}
235
280
  </View>
236
281
  );
237
282
  });
238
283
  }
239
284
 
240
- validType(children);
241
285
  return (
242
286
  <View style={styles.headerButton}>
243
- {React.cloneElement(children, {...restProps})}
287
+ {React.cloneElement(validateType(children), {...restProps})}
244
288
  </View>
245
289
  );
246
290
  };
247
291
  return <View style={styles.headerRightButton}>{renderAction()}</View>;
248
292
  };
249
293
 
250
- const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
294
+ const HeaderToolkitAction: React.FC<any> = ({
295
+ tintColor,
296
+ pinnedTool,
297
+ runtimeTools = [],
298
+ preventClose,
299
+ }) => {
251
300
  const {theme, navigator} = useContext(ApplicationContext);
252
- const [toolConfig, setToolConfig] = useState<HeaderToolkitProps>();
253
- const {appCode, hidden, type, onAction} = toolConfig ?? {};
301
+ const miniContext = useContext<any>(MiniAppContext);
302
+ const [toolConfig, setToolConfig] = useState<any>();
303
+ const {onAction} = toolConfig ?? {};
254
304
 
255
305
  let backgroundColor;
256
306
  if (tintColor != Colors.black_01) {
@@ -258,81 +308,94 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
258
308
  }
259
309
 
260
310
  useEffect(() => {
261
- navigator?.getToolkit().then((toolConfig: any) => {
262
- setToolConfig(toolConfig);
263
- });
264
- }, []);
265
-
266
- useEffect(() => {
267
- let addFavorite: any;
268
- let removeFavorite: any;
269
- if (appCode) {
270
- const addSchema = `observerToolkit_addFavorite_${appCode}`;
271
- const removeSchema = `observerToolkit_removeFavorite_${appCode}`;
272
- addFavorite = navigator?.requestApi(
273
- 'observer',
274
- [addSchema],
275
- (data: any) => {
276
- if (data?.status) {
277
- setToolConfig({
278
- ...(toolConfig as HeaderToolkitProps),
279
- hidden: true,
280
- });
281
- }
282
- },
283
- );
284
- addFavorite = navigator?.requestApi(
285
- 'observer',
286
- [removeSchema],
287
- (data: any) => {
288
- if (data?.status) {
289
- setToolConfig({
290
- ...(toolConfig as HeaderToolkitProps),
291
- hidden: false,
292
- });
293
- }
294
- },
295
- );
311
+ if (miniContext?.toolkitConfig?.hidden === false) {
312
+ if (navigator?.toolkitConfig) {
313
+ setToolConfig(navigator?.toolkitConfig);
314
+ } else {
315
+ getToolkitConfig();
316
+ }
296
317
  }
318
+ }, []);
297
319
 
298
- return () => {
299
- addFavorite?.();
300
- removeFavorite?.();
301
- };
302
- }, [appCode]);
303
-
304
- const onUtilityTool = () => {
305
- onAction?.('onUtilityTool');
306
- navigator?.requestApi(type, undefined, undefined);
320
+ const getToolkitConfig = () => {
321
+ navigator?.maxApi?.dispatchFunction?.(
322
+ 'getToolsConfig',
323
+ [undefined],
324
+ (config: any) => {
325
+ navigator.toolkitConfig = config;
326
+ setToolConfig(navigator?.toolkitConfig);
327
+ },
328
+ );
307
329
  };
308
330
 
309
331
  const onMore = () => {
310
332
  onAction?.('onMore');
311
- navigator?.requestApi('showToolkit', [toolConfig], undefined);
333
+ navigator?.maxApi?.dispatchFunction?.(
334
+ 'showTools',
335
+ {runtimeTools},
336
+ (res: {item: {action?: string; key: string}}) => {
337
+ const {item} = res;
338
+ navigator?.toolkitCallback?.(item);
339
+ getToolkitConfig();
340
+ },
341
+ );
312
342
  };
313
343
 
314
344
  const onClose = () => {
315
- onAction?.('onClose');
316
- navigator?.requestApi('dismiss', undefined, undefined);
345
+ if (preventClose) {
346
+ navigator?.showModal({
347
+ screen: () => (
348
+ <PopupNotify
349
+ {...preventClose}
350
+ primary={{
351
+ title: preventClose.primary.title,
352
+ onPress: () => {
353
+ preventClose?.primary.onPress();
354
+ navigator?.maxApi?.dispatchFunction?.(
355
+ 'dismiss',
356
+ undefined,
357
+ undefined,
358
+ );
359
+ },
360
+ }}
361
+ />
362
+ ),
363
+ });
364
+ } else {
365
+ navigator?.maxApi?.dispatchFunction?.('dismiss', undefined, undefined);
366
+ }
317
367
  };
318
368
 
319
- const renderUtilityTool = () => {
320
- if (hidden === false) {
369
+ const renderPinnedTool = () => {
370
+ const pinKey = pinnedTool?.key || toolConfig?.pinnedTool?.key;
371
+ const pinTool = toolConfig?.tools?.find((i: any) => i.key === pinKey);
372
+ const {badgeValue, badgeType} = pinnedTool ?? {};
373
+
374
+ if (pinTool)
321
375
  return (
322
376
  <NavigationButton
323
- accessibilityLabel={'UtilityTool'}
324
- icon={type as string}
377
+ accessibilityLabel="btn_navigation_pin"
378
+ icon={pinTool.icon as string}
325
379
  tintColor={tintColor}
326
- onPress={onUtilityTool}
380
+ badgeValue={badgeValue}
381
+ badgeType={badgeType}
382
+ onPress={() => {
383
+ navigator?.maxApi?.dispatchFunction?.(
384
+ 'onToolAction',
385
+ [pinTool?.key],
386
+ () => {
387
+ getToolkitConfig();
388
+ },
389
+ );
390
+ navigator?.toolkitCallback?.(pinTool.key);
391
+ }}
327
392
  />
328
393
  );
329
- }
330
394
  };
331
-
332
395
  if (toolConfig) {
333
396
  return (
334
397
  <View style={styles.headerRightButton}>
335
- {renderUtilityTool()}
398
+ {renderPinnedTool()}
336
399
  <View
337
400
  style={[
338
401
  styles.toolkitContainer,
@@ -342,13 +405,13 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
342
405
  },
343
406
  ]}>
344
407
  <TouchableOpacity
345
- accessibilityLabel={'Toolkit/More'}
408
+ accessibilityLabel={'btn_navigation_more'}
346
409
  onPress={onMore}>
347
410
  <Icon color={tintColor} source="navigation_more_horiz" size={20} />
348
411
  </TouchableOpacity>
349
412
  <View style={[styles.divider, {backgroundColor: tintColor}]} />
350
413
  <TouchableOpacity
351
- accessibilityLabel={`Toolkit/Close`}
414
+ accessibilityLabel={'btn_navigation_close'}
352
415
  onPress={onClose}>
353
416
  <Icon
354
417
  color={tintColor}
@@ -364,11 +427,126 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
364
427
  return <View />;
365
428
  };
366
429
 
430
+ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
431
+ animatedValue,
432
+ image,
433
+ children,
434
+ }) => {
435
+ const scale = animatedValue.interpolate({
436
+ inputRange: [-300, 0, 300],
437
+ outputRange: [4, 1, 1],
438
+ extrapolate: 'clamp',
439
+ });
440
+ const opacity = animatedValue.interpolate({
441
+ inputRange: [0, 150, 300],
442
+ outputRange: [1, 0.5, 0],
443
+ extrapolate: 'clamp',
444
+ });
445
+ const translateY = animatedValue.interpolate({
446
+ inputRange: [-300, 0],
447
+ outputRange: [-80, -2],
448
+ extrapolate: 'clamp',
449
+ });
450
+
451
+ return (
452
+ <Animated.View
453
+ style={{
454
+ height: 210,
455
+ opacity: opacity,
456
+ transform: [{scale}, {translateY}],
457
+ }}>
458
+ {children ?? (
459
+ <Image
460
+ source={{
461
+ uri: image,
462
+ }}
463
+ style={{width: '100%', height: '100%'}}
464
+ />
465
+ )}
466
+ </Animated.View>
467
+ );
468
+ };
469
+
470
+ const styles = StyleSheet.create({
471
+ navigationButton: {
472
+ height: 28,
473
+ width: 28,
474
+ borderRadius: 14,
475
+ justifyContent: 'center',
476
+ alignItems: 'center',
477
+ },
478
+ headerBackground: {
479
+ width: '100%',
480
+ height: undefined,
481
+ position: 'absolute',
482
+ aspectRatio: 375 / 154,
483
+ },
484
+ headerTitleContainer: {
485
+ alignItems: 'center',
486
+ justifyContent: 'center',
487
+ width: '100%',
488
+ },
489
+ circle: {width: 36, height: 36, borderRadius: 18},
490
+ square: {width: 36, height: 36, borderRadius: Radius.XS},
491
+ dotAvatar: {
492
+ position: 'absolute',
493
+ width: 12,
494
+ height: 12,
495
+ borderRadius: 6,
496
+ bottom: 0,
497
+ right: 0,
498
+ borderWidth: 1,
499
+ borderColor: Colors.black_01,
500
+ },
501
+ headerButton: {paddingHorizontal: 4},
502
+ headerRightButton: {
503
+ flexDirection: 'row',
504
+ justifyContent: 'center',
505
+ alignItems: 'center',
506
+ paddingRight: Spacing.S,
507
+ },
508
+ toolkitContainer: {
509
+ marginLeft: Spacing.S,
510
+ padding: Spacing.XS,
511
+ height: 28,
512
+ borderRadius: 14,
513
+ borderColor: '#00000066',
514
+ justifyContent: 'center',
515
+ alignItems: 'center',
516
+ flexDirection: 'row',
517
+ },
518
+ divider: {
519
+ width: 1,
520
+ height: 12,
521
+ marginHorizontal: 4,
522
+ },
523
+ headerLeft: {
524
+ marginLeft: 12,
525
+ },
526
+ title: {
527
+ fontSize: scaleSize(15),
528
+ lineHeight: scaleSize(22),
529
+ fontWeight: 'bold',
530
+ },
531
+ badge: {
532
+ position: 'absolute',
533
+ top: -Spacing.S,
534
+ right: -6,
535
+ },
536
+ badgeDot: {
537
+ position: 'absolute',
538
+ top: -Spacing.XS,
539
+ right: -Spacing.XS,
540
+ },
541
+ });
542
+
367
543
  export {
544
+ NavigationButton,
368
545
  HeaderTitle,
369
546
  HeaderLeft,
370
547
  HeaderBackground,
371
548
  HeaderRightAction,
372
549
  HeaderToolkitAction,
373
550
  HeaderCustom,
551
+ HeaderAnimated,
374
552
  };