@momo-kits/foundation 0.89.5 → 0.89.6-rc.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 (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 +350 -86
  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 +53 -35
  10. package/Application/StackScreen.tsx +289 -32
  11. package/Application/index.ts +13 -15
  12. package/Application/types.ts +64 -35
  13. package/Application/utils.tsx +76 -30
  14. package/Assets/icon_bank.json +1 -1
  15. package/Badge/Badge.tsx +1 -1
  16. package/Badge/BadgeDotAnimation.tsx +95 -0
  17. package/Badge/index.tsx +2 -1
  18. package/Badge/styles.ts +50 -6
  19. package/Button/index.tsx +44 -26
  20. package/CheckBox/index.tsx +37 -26
  21. package/CheckBox/types.ts +5 -3
  22. package/Consts/colors+spacing+radius.ts +14 -0
  23. package/Icon/index.tsx +9 -8
  24. package/Icon/types.ts +2 -2
  25. package/IconButton/index.tsx +24 -14
  26. package/Image/index.tsx +23 -8
  27. package/Image/types.ts +2 -0
  28. package/Input/Input.tsx +116 -26
  29. package/Input/InputDropDown.tsx +66 -51
  30. package/Input/InputMoney.tsx +106 -15
  31. package/Input/InputOTP.tsx +49 -26
  32. package/Input/InputSearch.tsx +252 -99
  33. package/Input/InputTextArea.tsx +26 -6
  34. package/Input/TextTyping.tsx +113 -0
  35. package/Input/common.tsx +48 -22
  36. package/Input/index.tsx +112 -77
  37. package/Input/styles.ts +48 -11
  38. package/Input/utils.ts +1 -1
  39. package/Layout/Card.tsx +4 -3
  40. package/Layout/FloatingButton.tsx +168 -0
  41. package/Layout/GridSystem.tsx +1 -1
  42. package/Layout/ItemList.tsx +3 -2
  43. package/Layout/Screen.tsx +242 -121
  44. package/Layout/Section.tsx +4 -3
  45. package/Layout/styles.ts +11 -13
  46. package/Layout/types.ts +1 -1
  47. package/Layout/utils.ts +4 -4
  48. package/Loader/index.tsx +2 -0
  49. package/Pagination/PaginationScroll.tsx +2 -2
  50. package/Pagination/styles.ts +1 -1
  51. package/Popup/PopupNotify.tsx +56 -45
  52. package/Popup/PopupPromotion.tsx +5 -7
  53. package/Popup/types.ts +1 -7
  54. package/Radio/index.tsx +35 -20
  55. package/Radio/types.ts +5 -3
  56. package/Switch/index.tsx +32 -18
  57. package/Switch/types.ts +5 -3
  58. package/Tag/index.tsx +9 -2
  59. package/Tag/styles.ts +3 -2
  60. package/Tag/types.ts +12 -0
  61. package/Text/index.tsx +24 -5
  62. package/Text/styles.ts +8 -8
  63. package/Text/types.ts +19 -1
  64. package/Title/index.tsx +170 -103
  65. package/Title/styles.ts +36 -9
  66. package/Title/types.ts +16 -48
  67. package/code-scanner.js +125 -16
  68. package/index.ts +7 -0
  69. package/migrate_typo.js +56 -0
  70. package/package.json +11 -10
  71. package/publish.sh +16 -21
  72. package/tsconfig.json +1 -1
  73. package/verify.js +37 -40
@@ -1,70 +1,327 @@
1
- import React, {useContext, useEffect, useLayoutEffect} from 'react';
1
+ import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
2
+ import {useHeaderHeight} from '@react-navigation/stack';
3
+ import {Alert, InteractionManager, Linking, View} from 'react-native';
2
4
  import {ScreenParams} from './types';
3
5
  import Navigation from './Navigation';
4
- import {ApplicationContext, MiniAppContext} from './index';
6
+ import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
5
7
  import {GridSystem} from '../Layout';
6
- import {useHeaderHeight} from '@react-navigation/stack';
8
+ import {Text} from '../Text';
9
+ import {Colors, Radius, Spacing} from '../Consts';
7
10
 
11
+ /**
12
+ * container for stack screen
13
+ * @param props
14
+ * @constructor
15
+ */
8
16
  const StackScreen: React.FC<ScreenParams> = props => {
9
- const {theme, showGrid, navigator} = useContext(ApplicationContext);
10
- const context = useContext(MiniAppContext);
17
+ const {showGrid, navigator} = useContext(ApplicationContext);
18
+ const tracking = useRef<any>({
19
+ timeoutLoad: undefined,
20
+ timeoutInteraction: undefined,
21
+ timeoutTracking: undefined,
22
+ startTime: Date.now(),
23
+ endTime: Date.now(),
24
+ traceIdLoad: undefined,
25
+ traceIdInteraction: undefined,
26
+ releaseLoad: undefined,
27
+ releaseInteraction: undefined,
28
+ timeLoad: 0,
29
+ timeInteraction: 0,
30
+ });
11
31
 
12
- const {screen: Component, options}: ScreenParams = props.route.params;
13
- const navigation = new Navigation(props.navigation, theme);
32
+ const context = useContext<any>(MiniAppContext);
33
+ const {screen: Component, options, initialParams} = props.route.params;
34
+ const navigation = new Navigation(props.navigation);
14
35
  const heightHeader = useHeaderHeight();
15
36
 
16
- const params = {
37
+ const data = {
38
+ ...initialParams,
17
39
  ...props.route.params,
18
40
  navigation,
19
41
  };
20
42
 
21
- delete params.screen;
43
+ delete data.screen;
44
+ delete data.initialParams;
45
+
46
+ const screenName = Component?.name || Component?.type?.name || 'Invalid';
47
+ const routes = props.navigation.getState()?.routes || [];
22
48
 
23
49
  /**
24
50
  * set options for screen
25
51
  */
26
52
  useLayoutEffect(() => {
53
+ let defaultOptions = {
54
+ headerRight: {
55
+ type: 'toolkit',
56
+ },
57
+ };
27
58
  if (options) {
28
- navigation.setOptions(options);
59
+ defaultOptions = {
60
+ ...defaultOptions,
61
+ ...options,
62
+ };
29
63
  }
64
+ navigation.setOptions(defaultOptions);
30
65
  }, [options]);
31
66
 
32
67
  /**
33
68
  * tracking for screen
34
69
  */
35
70
  useEffect(() => {
36
- const tracking = {
37
- ...context,
38
- screen_name: Component.name,
71
+ if (['Invalid', 'screen'].includes(screenName) && context.enableAutoId) {
72
+ setTimeout(() => {
73
+ navigator?.showModal({screen: EmptyScreen});
74
+ }, 300);
75
+ }
76
+
77
+ const subscription = props.navigation?.addListener?.('focus', () => {
78
+ navigator?.maxApi?.of?.({screenName});
79
+ navigator?.maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
80
+ let preScreenName = data?.screenName;
81
+ if (routes?.length > 1) {
82
+ const screen = routes?.[routes?.length - 2]?.params?.screen;
83
+ preScreenName = screen?.name || screen?.type?.name || 'Invalid';
84
+ }
85
+ onScreenNavigated(preScreenName);
86
+ navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
87
+ });
88
+ });
89
+ navigator?.maxApi?.startTraceScreenLoad?.(screenName, (data: any) => {
90
+ tracking.current.traceIdLoad = data?.traceId;
91
+ });
92
+ navigator?.maxApi?.startTraceScreenInteraction?.(
93
+ screenName,
94
+ (data: any) => {
95
+ tracking.current.traceIdInteraction = data?.traceId;
96
+ }
97
+ );
98
+
99
+ tracking.current.timeoutTracking = setTimeout(() => {
100
+ onScreenLoad();
101
+ onScreenInteraction();
102
+ }, 5000);
103
+
104
+ return () => {
105
+ onScreenLoad();
106
+ onScreenInteraction();
107
+ clearTimeout(tracking.current.timeoutTracking);
108
+ subscription?.();
39
109
  };
110
+ }, []);
111
+
112
+ /**
113
+ * tracking for screen load
114
+ */
115
+ const onScreenLoad = () => {
116
+ if (!tracking.current?.releaseLoad) {
117
+ if (tracking.current.timeLoad === 0) {
118
+ tracking.current.timeLoad =
119
+ tracking.current.endTime - tracking.current.startTime;
120
+ }
40
121
 
41
- const routes = props.navigation.getState()?.routes || [];
42
- const routesLength = routes.length;
43
- let pre_screen_name = '';
44
- if (routesLength > 1) {
45
- pre_screen_name = routes[routesLength - 2]?.params?.screen?.name;
122
+ context.autoTracking?.({
123
+ appId: context.appId,
124
+ code: context.code,
125
+ buildNumber: context.buildNumber,
126
+ screenName,
127
+ componentName: 'Screen',
128
+ state: 'load',
129
+ duration: tracking.current.timeLoad,
130
+ });
131
+ navigator?.maxApi?.stopTrace?.(
132
+ tracking.current.traceIdLoad,
133
+ {value: tracking.current.timeLoad / 1000},
134
+ null
135
+ );
136
+ tracking.current.releaseLoad = true;
137
+
138
+ /**
139
+ * debug
140
+ */
141
+ navigator?.maxApi?.showToastDebug?.({
142
+ appId: context.appId,
143
+ message: `${screenName} screen_load_time ${tracking.current.timeLoad}`,
144
+ type: 'ERROR',
145
+ });
146
+ if (tracking.current.timeLoad <= 0 && context.enableAutoId) {
147
+ Alert.alert(screenName, "Can't get screen load time");
148
+ }
46
149
  }
150
+ };
47
151
 
48
- navigator?.maxApi?.trackEvent?.('service_frame_displayed', {
49
- ...tracking,
50
- pre_screen_name,
51
- trigger_id: '111378000000000000',
52
- });
152
+ /**
153
+ * tracking for screen load
154
+ */
155
+ const onScreenInteraction = () => {
156
+ if (!tracking.current?.releaseInteraction) {
157
+ if (tracking.current.timeLoad === 0) {
158
+ tracking.current.timeLoad =
159
+ tracking.current.endTime - tracking.current.startTime;
160
+ }
161
+ if (tracking.current.timeInteraction === 0) {
162
+ tracking.current.timeInteraction = tracking.current.timeLoad;
163
+ }
164
+
165
+ context.autoTracking?.({
166
+ appId: context.appId,
167
+ code: context.code,
168
+ buildNumber: context.buildNumber,
169
+ screenName,
170
+ componentName: 'Screen',
171
+ state: 'interaction',
172
+ duration: tracking.current.timeInteraction - tracking.current.timeLoad,
173
+ totalDuration: tracking.current.timeInteraction,
174
+ });
175
+ navigator?.maxApi?.stopTrace?.(
176
+ tracking.current.traceIdInteraction,
177
+ {value: tracking.current.timeInteraction / 1000},
178
+ null
179
+ );
180
+ tracking.current.releaseInteraction = true;
53
181
 
54
- return props.navigation.addListener('beforeRemove', () => {
55
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', {
56
- ...tracking,
57
- trigger_id: '111154000000000000',
58
- icon_name: 'back',
182
+ /**
183
+ * debug toast
184
+ */
185
+ navigator?.maxApi?.showToastDebug?.({
186
+ appId: context.appId,
187
+ message: `${screenName} screen_interaction_time ${tracking.current.timeInteraction}`,
188
+ type: 'ERROR',
59
189
  });
190
+ if (tracking.current.timeInteraction <= 0 && context.enableAutoId) {
191
+ Alert.alert(screenName, "Can't get screen interaction time");
192
+ }
193
+ }
194
+ };
195
+
196
+ /**
197
+ * tracking for screen navigated
198
+ */
199
+ const onScreenNavigated = (preScreenName: string) => {
200
+ context.autoTracking?.({
201
+ appId: context.appId,
202
+ code: context.code,
203
+ buildNumber: context.buildNumber,
204
+ preScreenName,
205
+ screenName,
206
+ componentName: 'Screen',
207
+ state: 'navigated',
60
208
  });
61
- }, []);
209
+
210
+ /**
211
+ * debug toast
212
+ */
213
+ navigator?.maxApi?.showToastDebug?.({
214
+ appId: context.appId,
215
+ message: `${screenName} screen_navigated`,
216
+ type: 'ERROR',
217
+ });
218
+ };
62
219
 
63
220
  return (
64
- <>
65
- <Component heightHeader={heightHeader} {...params} />
221
+ <ScreenContext.Provider
222
+ value={{
223
+ screenName,
224
+ onElementLoad: () => {
225
+ clearTimeout(tracking.current.timeoutLoad);
226
+ tracking.current.endTime = Date.now();
227
+ tracking.current.timeoutInteraction?.cancel?.();
228
+ tracking.current.timeoutInteraction =
229
+ InteractionManager.runAfterInteractions(() => {
230
+ tracking.current.timeInteraction =
231
+ Date.now() - tracking.current.startTime;
232
+ });
233
+ tracking.current.timeoutLoad = setTimeout(() => {
234
+ if (tracking.current.timeLoad === 0) {
235
+ tracking.current.timeLoad =
236
+ tracking.current.endTime - tracking.current.startTime;
237
+ }
238
+ onScreenLoad();
239
+ onScreenInteraction();
240
+ }, 2000);
241
+ },
242
+ }}>
243
+ <Component
244
+ heightHeader={heightHeader}
245
+ {...data}
246
+ onScreenLoad={onScreenLoad}
247
+ onScreenInteraction={onScreenInteraction}
248
+ />
66
249
  {showGrid && <GridSystem />}
67
- </>
250
+ </ScreenContext.Provider>
251
+ );
252
+ };
253
+
254
+ /**
255
+ * Empty screen for unvalidated screen name
256
+ * @constructor
257
+ */
258
+ const EmptyScreen: React.FC = () => {
259
+ return (
260
+ <View
261
+ style={{
262
+ backgroundColor: Colors.black_01,
263
+ padding: Spacing.M,
264
+ borderRadius: Radius.M,
265
+ }}>
266
+ <Text typography={'header_m_bold'}>Unvalidated screen name</Text>
267
+ <Text
268
+ typography={'description_default_regular'}
269
+ style={{paddingVertical: Spacing.S}}>
270
+ Your screen has not been rendered because Platform has not detected the
271
+ screen name. Please migrate to support this feature.
272
+ </Text>
273
+ <Text typography={'header_default'} style={{width: '100%'}}>
274
+ Possible fixes:
275
+ </Text>
276
+ <View style={{marginLeft: Spacing.S}}>
277
+ <Text typography={'body_default_regular'}>1. Off webpack config</Text>
278
+ <Text typography={'body_default_regular'}>
279
+ 2. Screen name refactoring
280
+ </Text>
281
+ <View style={{marginLeft: Spacing.S}}>
282
+ <Text
283
+ typography={'description_default_regular'}
284
+ style={{marginBottom: Spacing.S}}>
285
+ - Với các screen push/import dạng arrow function ={'>'} đổi thành
286
+ named function
287
+ </Text>
288
+ <Text
289
+ typography={'description_default_regular'}
290
+ style={{marginBottom: Spacing.S}}>
291
+ - Với các screen import dạng High Order Component ={'>'} rename
292
+ generic function thành named function
293
+ </Text>
294
+ <Text
295
+ typography={'description_default_regular'}
296
+ style={{marginBottom: Spacing.S}}>
297
+ - Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
298
+ Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
299
+ khảo theo docs
300
+ </Text>
301
+ </View>
302
+ </View>
303
+ <Text typography={'header_s_semibold'}>More information: </Text>
304
+ <Text
305
+ typography={'body_default_regular'}
306
+ color={Colors.blue_01}
307
+ onPress={() => {
308
+ Linking.openURL(
309
+ 'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
310
+ );
311
+ }}>
312
+ Mini App: vn.momo.uikits/dev
313
+ </Text>
314
+ <Text
315
+ typography={'body_default_regular'}
316
+ color={Colors.blue_01}
317
+ onPress={() => {
318
+ Linking.openURL(
319
+ 'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
320
+ );
321
+ }}>
322
+ https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
323
+ </Text>
324
+ </View>
68
325
  );
69
326
  };
70
327
 
@@ -1,41 +1,39 @@
1
+ import {Platform} from 'react-native';
2
+ import {createContext} from 'react';
1
3
  import {NavigationContainer} from './NavigationContainer';
4
+ import Localize from './Localize';
2
5
  import Screen from '../Layout/Screen';
3
6
  import {
4
7
  HeaderAnimated,
5
8
  HeaderBackground,
6
9
  HeaderCustom,
7
- HeaderLeft,
8
- HeaderRightAction,
9
10
  HeaderTitle,
10
- HeaderToolkitAction,
11
11
  NavigationButton,
12
+ HeaderRightAction,
12
13
  } from './Components';
13
14
  import BottomTab from './BottomTab';
14
- import {createContext} from 'react';
15
15
  import {defaultContext} from '../Consts';
16
- import {MiniAppInfo} from './types';
17
16
 
17
+ const Context = createContext({});
18
18
  const ApplicationContext = createContext(defaultContext);
19
- const MiniAppContext = createContext<MiniAppInfo>({
20
- appId: '',
21
- buildNumber: 0,
22
- code: '',
23
- toolkitConfig: {},
24
- fromCode: '',
25
- });
19
+
20
+ const MiniAppContext = (Platform as any).MiniAppContext ?? createContext({});
21
+ const ScreenContext = (Platform as any).ScreenContext ?? createContext({});
22
+ const ComponentContext = (Platform as any).ComponentContext ?? Context;
26
23
 
27
24
  export {
28
25
  ApplicationContext,
29
26
  MiniAppContext,
27
+ ScreenContext,
28
+ ComponentContext,
30
29
  NavigationContainer,
30
+ Localize,
31
31
  Screen,
32
32
  BottomTab,
33
33
  NavigationButton,
34
+ HeaderRightAction,
34
35
  HeaderTitle,
35
- HeaderLeft,
36
36
  HeaderBackground,
37
- HeaderRightAction,
38
- HeaderToolkitAction,
39
37
  HeaderCustom,
40
38
  HeaderAnimated,
41
39
  };
@@ -1,9 +1,11 @@
1
- import {Animated} from 'react-native';
1
+ import {EventArg} from '@react-navigation/core';
2
2
  import {StackNavigationOptions} from '@react-navigation/stack';
3
3
  import React from 'react';
4
- import Navigator from './Navigator';
4
+ import {Animated, ViewProps} from 'react-native';
5
5
  import {PopupNotifyProps} from '../Popup/types';
6
+ import Localize from './Localize';
6
7
  import Navigation from './Navigation';
8
+ import Navigator from './Navigator';
7
9
 
8
10
  type Screen = React.ComponentType<NavigationScreenProps>;
9
11
 
@@ -70,16 +72,6 @@ export type Context = {
70
72
  translate?: (key: string) => string;
71
73
  };
72
74
 
73
- export type MiniAppInfo = {
74
- [key: string]: any;
75
- code: string;
76
- appId: string;
77
- buildNumber: number;
78
- flowPartnerId?: string;
79
- toolkitConfig?: any;
80
- fromCode?: string;
81
- };
82
-
83
75
  export type LocalizationObject = {
84
76
  vi: {
85
77
  [key: string]: string;
@@ -94,7 +86,8 @@ export type NavigationContainerProps = {
94
86
  options?: NavigationOptions;
95
87
  theme: Theme;
96
88
  maxApi: any;
97
- localization?: LocalizationObject;
89
+ initialParams?: any;
90
+ localize: Localize;
98
91
  };
99
92
 
100
93
  export type NavigationScreenProps = {
@@ -109,32 +102,43 @@ export type ScreenParams = {
109
102
  options?: NavigationOptions;
110
103
  };
111
104
 
112
- export interface ModalParams extends ScreenParams {
105
+ export type ModalParams = {
113
106
  [key: string]: any;
107
+ screen: React.ComponentType;
114
108
  onDismiss?: () => void;
115
109
  barrierDismissible?: boolean;
116
- }
110
+ };
117
111
 
118
- export interface BottomSheetParams extends ScreenParams {
112
+ export type BottomSheetParams = {
119
113
  [key: string]: any;
120
- onDismiss?: () => void;
121
- snapPoint?: '30%' | '50%' | '70%' | '90%' | 'content';
122
- indicatorColor?: string;
123
- }
114
+ screen: React.ComponentType;
115
+ options: {
116
+ title: string;
117
+ surface?: boolean;
118
+ };
119
+ useNativeModal?: boolean;
120
+ surface?: boolean;
121
+ onDismiss?: (type?: string) => void;
122
+ barrierDismissible?: boolean;
123
+ draggable?: boolean;
124
+ useBottomInset?: boolean;
125
+ keyboardVerticalOffset?: number;
126
+ };
124
127
 
125
128
  export type NavigationButtonProps = {
126
129
  icon: string;
127
130
  tintColor?: string;
128
131
  useBorder?: boolean;
129
132
  onPress: () => void;
130
- badgeType?: 'dot' | 'number';
133
+ badgeType?: 'dot' | 'number' | 'dot-animation';
131
134
  badgeValue?: number;
135
+ accessibilityLabel?: string;
132
136
  };
133
137
 
134
138
  export type PinnedToolType = {
135
139
  key: string;
136
140
  badgeValue?: number;
137
- badgeType?: 'number' | 'dot';
141
+ badgeType?: 'number' | 'dot' | 'dot-animation';
138
142
  };
139
143
 
140
144
  export type RuntimeToolType = {
@@ -143,18 +147,29 @@ export type RuntimeToolType = {
143
147
  key: string;
144
148
  };
145
149
 
146
- export interface NavigationOptions extends StackNavigationOptions {
150
+ export interface NavigationOptions
151
+ extends Omit<StackNavigationOptions, 'headerRight'> {
147
152
  preventBack?: PopupNotifyProps;
148
153
  onPressLeftHeader?: () => void;
149
154
  surface?: boolean;
150
155
  hiddenBack?: boolean;
151
156
  customTitle?: TitleCustomProps;
152
- toolkitParams?: {
153
- pinnedTool?: PinnedToolType;
154
- runtimeTools?: RuntimeToolType[];
155
- };
157
+ headerRight?: HeaderRightToolkit | HeaderRightActions | any;
156
158
  }
157
159
 
160
+ export type HeaderRightToolkit = {
161
+ type?: 'toolkit';
162
+ pinnedTool?: PinnedToolType;
163
+ runtimeTools?: RuntimeToolType[];
164
+ preventClose?: PopupNotifyProps;
165
+ useMore?: boolean;
166
+ };
167
+
168
+ export type HeaderRightActions = {
169
+ type?: 'icon';
170
+ buttons: NavigationButtonProps[];
171
+ };
172
+
158
173
  export interface HeaderBackProps extends NavigationButtonProps {
159
174
  preventBack?: PopupNotifyProps;
160
175
  onPressLeftHeader?: () => void;
@@ -162,9 +177,8 @@ export interface HeaderBackProps extends NavigationButtonProps {
162
177
 
163
178
  export type HeaderBackgroundProps = {
164
179
  image?: string | null;
165
- backgroundColor?: string | null;
166
180
  animatedValue?: Animated.Value;
167
- useBorder?: boolean;
181
+ useSurface?: boolean;
168
182
  };
169
183
 
170
184
  export type TitleCustomProps = {
@@ -183,20 +197,25 @@ export type HeaderToolkitProps = {
183
197
  configs: any[];
184
198
  };
185
199
 
186
- export type HeaderAnimatedProps = {
200
+ export interface HeaderAnimatedProps extends ViewProps {
187
201
  animatedValue: Animated.Value;
188
202
  image: string;
189
- onPress?: () => void;
190
- };
203
+ }
191
204
 
192
205
  export type BottomTabItemProps = {
193
206
  name: string;
194
207
  label: string;
195
208
  icon: string;
196
209
  showDot?: boolean;
197
- badgeLabel?: string;
210
+ badgeLabel?: string | number;
198
211
  screen: Screen;
199
212
  options: NavigationOptions;
213
+ initialParams?: any;
214
+ listeners?: {
215
+ tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
216
+ focus?: (e: EventArg<'focus', false, unknown>) => void;
217
+ blur?: (e: EventArg<'blur', false, unknown>) => void;
218
+ };
200
219
  };
201
220
 
202
221
  export type BottomTabProps = {
@@ -205,12 +224,22 @@ export type BottomTabProps = {
205
224
  initialRouteName?: string;
206
225
  navigation: Navigation;
207
226
  listeners?: {
208
- tabPress?: any;
209
- focus?: any;
227
+ tabPress?: (e: EventArg<'tabPress', true, undefined>) => void;
228
+ focus?: (e: EventArg<'focus', false, unknown>) => void;
229
+ blur?: (e: EventArg<'blur', false, unknown>) => void;
210
230
  };
231
+ floatingButton?: FloatingButtonProps;
232
+ };
233
+
234
+ export type FloatingButtonProps = {
235
+ container?: React.ReactNode;
236
+ icon: string | React.ReactNode;
237
+ label: string;
238
+ onPress: () => void;
211
239
  };
212
240
 
213
241
  export type AnimatedHeader = {
214
242
  type: 'default' | 'surface';
215
243
  component?: (props?: any) => React.ReactElement;
244
+ headerTitle?: (props?: any) => React.ReactElement;
216
245
  };