@momo-kits/foundation 0.112.1-beta.8 → 0.112.1-doc.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.
@@ -1,8 +1,13 @@
1
1
  import React, {useContext, useEffect, useRef, useState} from 'react';
2
- import {SafeAreaProvider} from 'react-native-safe-area-context';
2
+ import type {NavigationState} from '@react-navigation/routers';
3
+ import {
4
+ SafeAreaProvider,
5
+ useSafeAreaInsets,
6
+ } from 'react-native-safe-area-context';
3
7
  import {
4
8
  NavigationContainer as ReactNavigationContainer,
5
9
  NavigationContainerRef,
10
+ NavigationIndependentTree,
6
11
  } from '@react-navigation/native';
7
12
  import {
8
13
  createStackNavigator,
@@ -16,7 +21,7 @@ import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
16
21
  import {NavigationContainerProps} from './types';
17
22
  import {ApplicationContext, MiniAppContext} from './index';
18
23
  import Localize from './Localize';
19
- import {defaultTheme, Configs} from '../Consts';
24
+ import {defaultTheme} from '../Consts';
20
25
 
21
26
  const Stack = createStackNavigator();
22
27
 
@@ -29,12 +34,47 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
29
34
  localize = new Localize({vi: {}, en: {}}),
30
35
  }) => {
31
36
  const context = useContext<any>(MiniAppContext);
32
- const navigationRef = useRef<NavigationContainerRef>(null);
37
+ return (
38
+ <SafeAreaProvider>
39
+ <MiniAppContext.Provider value={context}>
40
+ <Navigation
41
+ screen={screen}
42
+ theme={theme}
43
+ options={options}
44
+ maxApi={maxApi}
45
+ initialParams={initialParams}
46
+ localize={localize}
47
+ />
48
+ </MiniAppContext.Provider>
49
+ </SafeAreaProvider>
50
+ );
51
+ };
52
+
53
+ const Navigation: React.FC<any> = ({
54
+ screen,
55
+ theme = defaultTheme,
56
+ options,
57
+ maxApi,
58
+ initialParams,
59
+ localize = new Localize({vi: {}, en: {}}),
60
+ }) => {
61
+ const context = useContext<any>(MiniAppContext);
62
+ const navigationRef = useRef<NavigationContainerRef<any>>(null);
33
63
  const routes = useRef<any>();
34
64
  const isReady = useRef(false);
35
65
  const navigator = useRef(new Navigator(navigationRef, isReady));
36
66
  const [showGrid, setShowGrid] = useState(false);
37
- const [currentContext, setCurrentContext] = useState({});
67
+ const insets = useSafeAreaInsets();
68
+
69
+ let headerBackground = context?.designConfig?.headerBar;
70
+ let headerGradient = theme.colors?.gradient;
71
+
72
+ if (theme.assets?.headerBackground) {
73
+ headerBackground = theme.assets?.headerBackground;
74
+ }
75
+ if (context?.designConfig?.headerGradient) {
76
+ headerGradient = context?.designConfig?.headerGradient;
77
+ }
38
78
 
39
79
  /**
40
80
  * inject data for navigator
@@ -50,7 +90,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
50
90
  'onChangeGrid',
51
91
  enable => {
52
92
  setShowGrid(!!enable);
53
- }
93
+ },
54
94
  );
55
95
 
56
96
  return () => {
@@ -58,6 +98,10 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
58
98
  };
59
99
  }, []);
60
100
 
101
+ /**
102
+ * translate context method
103
+ * @param data
104
+ */
61
105
  const translate = (data?: string | {vi: string; en: string}) => {
62
106
  if (data && typeof data !== 'string') {
63
107
  return localize?.translateData(data);
@@ -74,7 +118,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
74
118
  const onScreenNavigated = (
75
119
  preScreenName: string,
76
120
  screenName: string,
77
- action: string
121
+ action: string,
78
122
  ) => {
79
123
  console.log(preScreenName, screenName, action);
80
124
  context?.autoTracking?.({
@@ -86,9 +130,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
86
130
  action,
87
131
  });
88
132
 
89
- /**
90
- * debug toast
91
- */
92
133
  maxApi?.showToastDebug?.({
93
134
  appId: context.appId,
94
135
  message: `${screenName} screen_navigated`,
@@ -96,104 +137,129 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
96
137
  });
97
138
  };
98
139
 
99
- const headerBackground = theme.assets?.headerBackground || Configs.headerBar;
100
- const headerGradient = Configs?.headerGradient || theme.colors?.gradient;
140
+ /**
141
+ * onStateChange
142
+ * @param state
143
+ */
144
+ const onStateChange = (state: Readonly<NavigationState> | undefined) => {
145
+ const lastedRoute: any = state?.routes?.[state?.routes?.length - 1];
146
+ const oldRoute: any = routes.current?.[routes.current?.length - 1];
147
+ const lasted = lastedRoute?.params?.screen;
148
+ const previous = oldRoute?.params?.screen;
149
+ const preScreenName = previous?.name ?? previous?.type?.name;
150
+ const screenName = lasted?.name ?? lasted?.type?.name;
101
151
 
102
- navigator.current.setCurrentContext = setCurrentContext;
152
+ let action = 'push';
153
+ if (routes.current?.length > (state?.routes?.length ?? 0)) {
154
+ action = 'back';
155
+ }
156
+ onScreenNavigated(preScreenName, screenName, action);
157
+ maxApi?.setObserver('CURRENT_SCREEN', {screenName});
158
+ routes.current = state?.routes;
159
+ };
160
+
161
+ /**
162
+ * onReady
163
+ */
164
+ const onReady = () => {
165
+ isReady.current = true;
166
+ routes.current = navigationRef.current?.getRootState?.()?.routes;
167
+ maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
168
+ onScreenNavigated(data?.screenName, screen?.name, 'push');
169
+ maxApi?.setObserver('CURRENT_SCREEN', {
170
+ screenName: screen?.name,
171
+ });
172
+ });
173
+ };
103
174
 
104
175
  return (
105
- <SafeAreaProvider>
106
- <MiniAppContext.Provider
107
- value={{
108
- ...context,
109
- ...currentContext,
110
- }}>
111
- <ApplicationContext.Provider
112
- value={{
113
- navigator: navigator.current,
114
- theme: {
115
- ...theme,
116
- colors: {
117
- ...theme.colors,
118
- gradient: headerGradient,
176
+ <ApplicationContext.Provider
177
+ value={{
178
+ navigator: navigator.current,
179
+ theme: {
180
+ ...theme,
181
+ colors: {
182
+ ...theme.colors,
183
+ gradient: headerGradient,
184
+ },
185
+ assets: {
186
+ ...theme.assets,
187
+ headerBackground,
188
+ },
189
+ },
190
+ showGrid,
191
+ translate,
192
+ }}>
193
+ <NavigationIndependentTree>
194
+ <ReactNavigationContainer
195
+ theme={{
196
+ dark: false,
197
+ colors: {
198
+ primary: theme.colors.primary,
199
+ background: theme.colors.background.default,
200
+ card: theme.colors.background.surface,
201
+ text: theme.colors.text.default,
202
+ border: theme.colors.border.default,
203
+ notification: theme.colors.error.primary,
204
+ },
205
+ fonts: {
206
+ regular: {
207
+ fontFamily: 'SFProText',
208
+ fontWeight: '400',
119
209
  },
120
- assets: {
121
- ...theme.assets,
122
- headerBackground,
210
+ medium: {
211
+ fontFamily: 'SFProText',
212
+ fontWeight: '400',
213
+ },
214
+ bold: {
215
+ fontFamily: 'SFProText',
216
+ fontWeight: '400',
217
+ },
218
+ heavy: {
219
+ fontFamily: 'SFProText',
220
+ fontWeight: '400',
123
221
  },
124
222
  },
125
- showGrid,
126
- translate,
127
- }}>
128
- <ReactNavigationContainer
129
- theme={{
130
- ...theme,
131
- colors: {
132
- ...theme.colors,
133
- background: theme.colors.background.default,
134
- card: theme.colors.background.surface,
135
- text: theme.colors.text.default,
136
- border: theme.colors.border.default,
137
- notification: theme.colors.error.primary,
223
+ }}
224
+ ref={navigationRef}
225
+ onReady={onReady}
226
+ onStateChange={onStateChange}>
227
+ <Stack.Navigator
228
+ initialRouteName="Stack"
229
+ screenOptions={{
230
+ headerMode: 'screen',
231
+ gestureEnabled: false,
232
+ headerTitleAlign: 'left',
233
+ headerTintColor: theme.colors.text.default,
234
+ headerStyle: {
235
+ height: 52 + insets.top,
138
236
  },
139
- }}
140
- ref={navigationRef}
141
- onReady={() => {
142
- isReady.current = true;
143
- routes.current = navigationRef.current?.getRootState?.()?.routes;
144
- maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
145
- onScreenNavigated(data?.screenName, screen?.name, 'push');
146
- maxApi?.setObserver('CURRENT_SCREEN', {
147
- screenName: screen?.name,
148
- });
149
- });
150
- }}
151
- onStateChange={state => {
152
- const lastedRoute: any =
153
- state?.routes?.[state?.routes?.length - 1];
154
- const oldRoute: any =
155
- routes.current?.[routes.current?.length - 1];
156
- const lasted = lastedRoute?.params?.screen;
157
- const previous = oldRoute?.params?.screen;
158
- const preScreenName = previous?.name ?? previous?.type?.name;
159
- const screenName = lasted?.name ?? lasted?.type?.name;
160
-
161
- let action = 'push';
162
- if (routes.current?.length > (state?.routes?.length ?? 0)) {
163
- action = 'back';
164
- }
165
- onScreenNavigated(preScreenName, screenName, action);
166
- maxApi?.setObserver('CURRENT_SCREEN', {screenName});
167
- routes.current = state?.routes;
168
- }}
169
- independent={true}>
170
- <Stack.Navigator initialRouteName="Stack" headerMode="screen">
171
- <Stack.Screen
172
- name="Stack"
173
- component={StackScreen}
174
- initialParams={{screen, initialParams}}
175
- options={{
176
- ...getStackOptions(),
177
- ...(options as StackNavigationOptions),
178
- }}
179
- />
180
- <Stack.Screen
181
- name="Dialog"
182
- component={StackScreen}
183
- options={getDialogOptions()}
184
- initialParams={{screen}}
185
- />
186
- <Stack.Screen
187
- name="Modal"
188
- component={ModalScreen}
189
- options={getModalOptions()}
190
- initialParams={{screen}}
191
- />
192
- </Stack.Navigator>
193
- </ReactNavigationContainer>
194
- </ApplicationContext.Provider>
195
- </MiniAppContext.Provider>
196
- </SafeAreaProvider>
237
+ }}>
238
+ <Stack.Screen
239
+ name="Stack"
240
+ component={StackScreen}
241
+ initialParams={{screen, initialParams}}
242
+ options={{
243
+ ...getStackOptions(),
244
+ ...(options as StackNavigationOptions),
245
+ }}
246
+ />
247
+ <Stack.Screen
248
+ name="Dialog"
249
+ component={StackScreen}
250
+ options={getDialogOptions()}
251
+ initialParams={{screen}}
252
+ />
253
+ <Stack.Screen
254
+ name="Modal"
255
+ component={ModalScreen}
256
+ options={getModalOptions()}
257
+ initialParams={{screen}}
258
+ />
259
+ </Stack.Navigator>
260
+ </ReactNavigationContainer>
261
+ </NavigationIndependentTree>
262
+ </ApplicationContext.Provider>
197
263
  );
198
264
  };
199
265
 
@@ -1,10 +1,17 @@
1
- import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
2
- import {useHeaderHeight} from '@react-navigation/stack';
1
+ import React, {
2
+ useCallback,
3
+ useContext,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useRef,
7
+ } from 'react';
3
8
  import {Alert, InteractionManager} from 'react-native';
4
- import {ScreenParams} from './types';
9
+ import {useHeaderHeight} from '@react-navigation/elements';
10
+ import {ScreenTrackingParams} from './types';
5
11
  import Navigation from './Navigation';
6
12
  import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
7
13
  import {GridSystem} from '../Layout';
14
+ import {version} from '../package.json';
8
15
 
9
16
  const runAfterInteractions = InteractionManager.runAfterInteractions;
10
17
 
@@ -13,7 +20,7 @@ const runAfterInteractions = InteractionManager.runAfterInteractions;
13
20
  * @param props
14
21
  * @constructor
15
22
  */
16
- const StackScreen: React.FC<ScreenParams> = props => {
23
+ const StackScreen: React.FC<any> = props => {
17
24
  const {showGrid, navigator} = useContext(ApplicationContext);
18
25
  const tracking = useRef<any>({
19
26
  timeoutLoad: undefined,
@@ -27,11 +34,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
27
34
  releaseInteraction: undefined,
28
35
  timeLoad: 0,
29
36
  timeInteraction: 0,
37
+ widgets: [],
38
+ params: undefined,
30
39
  });
40
+ const widgets = useRef<any>([]);
31
41
  const context = useContext<any>(MiniAppContext);
32
42
  const lastElement = useRef<any>(null);
33
43
  const {screen: Component, options, initialParams} = props.route.params;
34
- const navigation = new Navigation(props.navigation, context);
44
+ const navigation = useRef(new Navigation(props.navigation, context)).current;
35
45
  const heightHeader = useHeaderHeight();
36
46
 
37
47
  const data = {
@@ -52,56 +62,12 @@ const StackScreen: React.FC<ScreenParams> = props => {
52
62
  if (options) {
53
63
  navigation.setOptions(options);
54
64
  }
55
- }, [options]);
56
-
57
- /**
58
- * tracking for screen
59
- */
60
- useEffect(() => {
61
- if (['Invalid', 'screen'].includes(screenName)) {
62
- navigator?.maxApi?.showPopup?.('notice', {
63
- title: 'Invalid screen name',
64
- message:
65
- 'Your screen has not been rendered because Platform has not detected the screen name. Please migrate to support this feature.',
66
- });
67
- }
68
-
69
- const subscription = props.navigation?.addListener?.('focus', () => {
70
- navigator?.maxApi?.of?.({screenName});
71
- navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
72
- });
73
- navigator?.maxApi?.startTraceScreenLoad?.(
74
- screenName,
75
- context,
76
- (data: any) => {
77
- tracking.current.traceIdLoad = data?.traceId;
78
- }
79
- );
80
- navigator?.maxApi?.startTraceScreenInteraction?.(
81
- screenName,
82
- context,
83
- (data: any) => {
84
- tracking.current.traceIdInteraction = data?.traceId;
85
- }
86
- );
87
-
88
- tracking.current.timeoutTracking = setTimeout(() => {
89
- onScreenLoad();
90
- onScreenInteraction();
91
- }, 5000);
92
-
93
- return () => {
94
- onScreenLoad();
95
- onScreenInteraction();
96
- clearTimeout(tracking.current.timeoutTracking);
97
- subscription?.();
98
- };
99
- }, []);
65
+ }, [navigation, options]);
100
66
 
101
67
  /**
102
68
  * tracking for screen load
103
69
  */
104
- const onScreenLoad = () => {
70
+ const onScreenLoad = useCallback(() => {
105
71
  if (!tracking.current?.releaseLoad) {
106
72
  let timeLoad = tracking.current.timeLoad;
107
73
  if (timeLoad === 0) {
@@ -114,11 +80,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
114
80
  componentName: 'Screen',
115
81
  state: 'load',
116
82
  duration: timeLoad,
83
+ widgets: tracking.current.widgets,
84
+ params: tracking.current.params,
85
+ version: version,
117
86
  });
118
87
  navigator?.maxApi?.stopTrace?.(
119
88
  tracking.current.traceIdLoad,
120
89
  {value: timeLoad / 1000},
121
- null
90
+ null,
122
91
  );
123
92
  tracking.current.releaseLoad = true;
124
93
 
@@ -136,16 +105,16 @@ const StackScreen: React.FC<ScreenParams> = props => {
136
105
  ) {
137
106
  Alert.alert(
138
107
  `${screenName}- load ${timeLoad}ms`,
139
- JSON.stringify(lastElement.current?.children?.current)
108
+ JSON.stringify(lastElement.current?.children?.current),
140
109
  );
141
110
  }
142
111
  }
143
- };
112
+ }, [context, navigator?.maxApi, screenName]);
144
113
 
145
114
  /**
146
115
  * tracking for screen load
147
116
  */
148
- const onScreenInteraction = () => {
117
+ const onScreenInteraction = useCallback(() => {
149
118
  if (!tracking.current?.releaseInteraction) {
150
119
  let timeLoad = tracking.current.timeLoad;
151
120
  if (timeLoad === 0) {
@@ -162,11 +131,13 @@ const StackScreen: React.FC<ScreenParams> = props => {
162
131
  state: 'interaction',
163
132
  duration: tracking.current.timeInteraction - timeLoad,
164
133
  totalDuration: tracking.current.timeInteraction,
134
+ params: tracking.current.params,
135
+ version: version,
165
136
  });
166
137
  navigator?.maxApi?.stopTrace?.(
167
138
  tracking.current.traceIdInteraction,
168
139
  {value: tracking.current.timeInteraction / 1000},
169
- null
140
+ null,
170
141
  );
171
142
  tracking.current.releaseInteraction = true;
172
143
 
@@ -179,13 +150,88 @@ const StackScreen: React.FC<ScreenParams> = props => {
179
150
  type: 'ERROR',
180
151
  });
181
152
  }
182
- };
153
+ }, [context, navigator?.maxApi, screenName]);
154
+
155
+ /**
156
+ * tracking for screen
157
+ */
158
+ useEffect(() => {
159
+ if (['Invalid', 'screen'].includes(screenName)) {
160
+ navigator?.maxApi?.showPopup?.('notice', {
161
+ title: 'Invalid screen name',
162
+ message:
163
+ 'Your screen has not been rendered because Platform has not detected the screen name. Please migrate to support this feature.',
164
+ });
165
+ }
166
+
167
+ const subscription = props.navigation?.addListener?.('focus', () => {
168
+ navigator?.maxApi?.of?.({screenName});
169
+ navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
170
+ });
171
+ navigator?.maxApi?.startTraceScreenLoad?.(
172
+ screenName,
173
+ context,
174
+ (item: any) => {
175
+ tracking.current.traceIdLoad = item?.traceId;
176
+ },
177
+ );
178
+ navigator?.maxApi?.startTraceScreenInteraction?.(
179
+ screenName,
180
+ context,
181
+ (item: any) => {
182
+ tracking.current.traceIdInteraction = item?.traceId;
183
+ },
184
+ );
185
+
186
+ tracking.current.timeoutTracking = setTimeout(() => {
187
+ onScreenLoad();
188
+ onScreenInteraction();
189
+ }, 5000);
190
+
191
+ return () => {
192
+ onScreenLoad();
193
+ onScreenInteraction();
194
+ subscription?.();
195
+ };
196
+ }, [
197
+ context,
198
+ navigator?.maxApi,
199
+ onScreenInteraction,
200
+ onScreenLoad,
201
+ props.navigation,
202
+ screenName,
203
+ ]);
183
204
 
184
205
  return (
185
206
  <ScreenContext.Provider
186
207
  value={{
187
208
  screenName,
188
- onElementLoad: (data: any) => {
209
+ onElementLoad: (item: any) => {
210
+ /**
211
+ * widget handle
212
+ */
213
+ if (item?.componentName === 'Widget') {
214
+ const index = widgets.current.findIndex(
215
+ (e: any) => e.componentId === item.componentId,
216
+ );
217
+ const time = Date.now() - tracking.current.startTime;
218
+ if (index === -1) {
219
+ widgets.current.push({
220
+ componentId: item.componentId,
221
+ appId: item.params?.appId,
222
+ code: item.params?.code,
223
+ start: time,
224
+ });
225
+ } else {
226
+ const exist = widgets.current[index];
227
+ widgets.current[index] = {
228
+ ...exist,
229
+ end: time,
230
+ duration: time - exist.start,
231
+ };
232
+ }
233
+ return;
234
+ }
189
235
  /**
190
236
  * tracking for element screen load
191
237
  */
@@ -200,14 +246,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
200
246
  /**
201
247
  * support for debug last element
202
248
  */
203
- if (data?.componentName) {
204
- lastElement.current = data;
249
+ if (item?.componentName) {
250
+ lastElement.current = item;
205
251
  }
206
252
 
207
253
  /**
208
254
  * for stop tracking when user interaction
209
255
  */
210
- if (data?.interaction) {
256
+ if (item?.interaction) {
211
257
  onScreenLoad();
212
258
  onScreenInteraction();
213
259
  }
@@ -216,6 +262,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
216
262
  */
217
263
  tracking.current.timeoutLoad = setTimeout(() => {
218
264
  const time = tracking.current.endTime - tracking.current.startTime;
265
+ tracking.current.widgets = widgets.current;
266
+
219
267
  if (tracking.current.timeLoad === 0) {
220
268
  tracking.current.timeLoad = time;
221
269
  }
@@ -224,6 +272,9 @@ const StackScreen: React.FC<ScreenParams> = props => {
224
272
  onScreenInteraction();
225
273
  }, 2000);
226
274
  },
275
+ onSetParams: (data: ScreenTrackingParams) => {
276
+ tracking.current.params = data;
277
+ },
227
278
  }}>
228
279
  <Component heightHeader={heightHeader} {...data} />
229
280
  {showGrid && <GridSystem />}
@@ -16,15 +16,17 @@ import {setAutomationID} from './utils';
16
16
  const Context = createContext({});
17
17
  const ApplicationContext = createContext(defaultContext);
18
18
 
19
- const MiniAppContext = (Platform as any).MiniAppContext ?? createContext({});
20
- const ScreenContext = (Platform as any).ScreenContext ?? createContext({});
19
+ const MiniAppContext = (Platform as any).MiniAppContext ?? Context;
20
+ const ScreenContext = (Platform as any).ScreenContext ?? Context;
21
21
  const ComponentContext = (Platform as any).ComponentContext ?? Context;
22
+ const SkeletonContext = createContext({loading: false});
22
23
 
23
24
  export {
24
25
  ApplicationContext,
25
26
  MiniAppContext,
26
27
  ScreenContext,
27
28
  ComponentContext,
29
+ SkeletonContext,
28
30
  NavigationContainer,
29
31
  Localize,
30
32
  HeaderTitle,
@@ -117,6 +117,11 @@ export type ScreenParams = {
117
117
  options?: NavigationOptions;
118
118
  };
119
119
 
120
+ export type ScreenTrackingParams = {
121
+ value1?: any;
122
+ value2?: any;
123
+ };
124
+
120
125
  export type ModalParams = {
121
126
  [key: string]: any;
122
127
  screen: React.ComponentType;
@@ -55,7 +55,8 @@ const getModalOptions = (): StackNavigationOptions => {
55
55
  headerBackground: undefined,
56
56
  cardStyle: {backgroundColor: 'transparent'},
57
57
  cardOverlayEnabled: true,
58
- animationEnabled: false,
58
+ animation: 'none',
59
+ presentation: 'transparentModal',
59
60
  };
60
61
  };
61
62
 
@@ -64,7 +65,7 @@ const getModalOptions = (): StackNavigationOptions => {
64
65
  */
65
66
  const getOptions = (
66
67
  params: NavigationOptions,
67
- animatedValue?: Animated.Value
68
+ animatedValue?: Animated.Value,
68
69
  ) => {
69
70
  let options: StackNavigationOptions = {};
70
71
 
@@ -126,7 +127,7 @@ const getOptions = (
126
127
 
127
128
  const exportHeaderTitle = (
128
129
  params: NavigationOptions,
129
- animatedValue?: Animated.Value
130
+ animatedValue?: Animated.Value,
130
131
  ): StackNavigationOptions => {
131
132
  if (typeof params.headerTitle === 'object') {
132
133
  return {