@momo-kits/foundation 0.167.1-beta.7 → 0.167.1-duo-test.1

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 (47) hide show
  1. package/Application/BottomSheet.tsx +115 -14
  2. package/Application/BottomTab/BottomTabBar.tsx +6 -3
  3. package/Application/BottomTab/DuoBarCompression.tsx +135 -0
  4. package/Application/BottomTab/DuoTabBar.tsx +462 -0
  5. package/Application/BottomTab/index.tsx +150 -134
  6. package/Application/Components/DuoGlassBackground.tsx +179 -0
  7. package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
  8. package/Application/Components/HeaderExtendHeader.tsx +75 -28
  9. package/Application/Components/HeaderLeft.tsx +38 -0
  10. package/Application/Components/HeaderRight.tsx +142 -9
  11. package/Application/Components/HeaderTitle.tsx +61 -21
  12. package/Application/Components/OptionalGlassView.ts +11 -0
  13. package/Application/Components/OptionalScrollObserver.ts +12 -0
  14. package/Application/Components/SearchHeader.tsx +22 -15
  15. package/Application/Components/SideBarButton.tsx +139 -0
  16. package/Application/ModalScreen.tsx +16 -2
  17. package/Application/NavigationContainer.tsx +36 -50
  18. package/Application/Navigator.ts +1 -3
  19. package/Application/StackScreen.tsx +63 -9
  20. package/Application/WidgetContainer.tsx +9 -15
  21. package/Application/device.ts +29 -0
  22. package/Application/types.ts +27 -1
  23. package/Application/utils.tsx +255 -7
  24. package/Consts/index.ts +0 -1
  25. package/Consts/theme.ts +3 -4
  26. package/Input/Input.tsx +3 -4
  27. package/Input/InputMoney.tsx +31 -51
  28. package/Input/InputPhoneNumber.tsx +3 -4
  29. package/Input/InputSearch.tsx +3 -4
  30. package/Input/InputTextArea.tsx +3 -4
  31. package/Layout/Card.tsx +8 -26
  32. package/Layout/FloatingButton.tsx +3 -3
  33. package/Layout/Item.tsx +1 -10
  34. package/Layout/ReservedRegions.tsx +47 -0
  35. package/Layout/Screen.tsx +199 -52
  36. package/Layout/Section.tsx +5 -18
  37. package/Layout/index.ts +4 -4
  38. package/Layout/styles.ts +5 -0
  39. package/Layout/utils.ts +465 -5
  40. package/Popup/PopupNotify.tsx +33 -22
  41. package/Popup/PopupPromotion.tsx +20 -8
  42. package/Popup/utils.ts +32 -0
  43. package/Text/index.tsx +5 -15
  44. package/Text/utils.ts +1 -2
  45. package/package.json +3 -2
  46. package/Consts/designSystemFont.ts +0 -25
  47. package/Layout/GridSystem.tsx +0 -137
@@ -1,6 +1,6 @@
1
1
  import React, { Ref, useContext } from 'react';
2
2
  import LinearGradient from 'react-native-linear-gradient';
3
- import { Dimensions, Platform, StyleSheet, View } from 'react-native';
3
+ import { Platform, StyleSheet, View } from 'react-native';
4
4
  import Animated, {
5
5
  Extrapolation,
6
6
  interpolate,
@@ -14,21 +14,19 @@ import { Colors, Radius, Spacing } from '../../Consts';
14
14
  import { Image } from '../../Image';
15
15
  import { SearchHeaderProps } from '../types';
16
16
  import BackgroundImageView from './BackgroundImageView';
17
- import {
18
- AnimatedCompatValue,
19
- useNormalizedSharedValue,
20
- } from '../utils';
17
+ import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
18
+ import { useScreenLayout } from '../../Layout';
19
+ import { DuoMetrics, HeaderMetrics } from '../../Layout/utils';
21
20
 
22
21
  const SCREEN_PADDING = 12;
23
22
  const BACK_WIDTH = 28;
24
-
25
- const { width: screenWidth } = Dimensions.get('window');
23
+ const TOOLKIT_WIDTH = 73;
26
24
 
27
25
  const HeaderExtendHeader: React.FC<{
28
26
  headerType?: HeaderType;
29
27
  animatedValue: AnimatedCompatValue;
30
28
  heightHeader: number;
31
- headerRightWidth: number;
29
+ headerRightWidth?: number;
32
30
  inputSearchProps?: SearchHeaderProps;
33
31
  inputSearchRef?: Ref<InputRef>;
34
32
  navigation?: Navigation;
@@ -39,7 +37,7 @@ const HeaderExtendHeader: React.FC<{
39
37
  headerType = 'default',
40
38
  animatedValue,
41
39
  heightHeader,
42
- headerRightWidth = 73,
40
+ headerRightWidth: customHeaderRightWidth,
43
41
  inputSearchProps,
44
42
  inputSearchRef,
45
43
  useShadowHeader: useShadowHeaderProp = true,
@@ -51,7 +49,35 @@ const HeaderExtendHeader: React.FC<{
51
49
  const sharedValue = useNormalizedSharedValue(animatedValue);
52
50
  const gradientColor = customGradientColor ?? theme.colors.gradient;
53
51
  const headerBackground = customBackground ?? theme.assets?.headerBackground;
54
- const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20;
52
+ const layout = useScreenLayout();
53
+
54
+ // the iPhone Duo status bar row keeps side bar sized back and toolkit
55
+ const backWidth = layout.statusBarClearance
56
+ ? DuoMetrics.controlSize
57
+ : BACK_WIDTH;
58
+ const toolkitWidth = layout.statusBarClearance
59
+ ? DuoMetrics.itemPitch * 2 + SCREEN_PADDING
60
+ : TOOLKIT_WIDTH;
61
+ const leftPosition =
62
+ inputSearchProps?.leftPosition ||
63
+ (layout.sideBar ? SCREEN_PADDING : backWidth + 20);
64
+ const headerRightWidth =
65
+ customHeaderRightWidth ?? (layout.sideBar ? 0 : toolkitWidth);
66
+ const contentLeft = layout.insetLeft + SCREEN_PADDING;
67
+ const contentRight = layout.insetLeft + layout.contentWidth;
68
+ // collapsed on the status bar row, the search stays between its clusters
69
+ const collapsedLeft =
70
+ layout.insetLeft + leftPosition + (layout.statusBarClearance?.left ?? 0);
71
+ const collapsedRight = contentRight - (layout.statusBarClearance?.right ?? 0);
72
+ const searchWidth = layout.contentWidth - SCREEN_PADDING * 2;
73
+ const collapsedSearchWidth =
74
+ collapsedRight - collapsedLeft - SCREEN_PADDING - headerRightWidth;
75
+ // a row taller than barHeight (iPhone Duo) centers the collapsed search on the title
76
+ const collapsedRaise =
77
+ (layout.headerHeight -
78
+ layout.headerStatusBarHeight -
79
+ HeaderMetrics.barHeight) /
80
+ 2;
55
81
 
56
82
  let useShadowHeader = useShadowHeaderProp;
57
83
  if (inputSearchProps && Platform.OS === 'android') {
@@ -70,7 +96,12 @@ const HeaderExtendHeader: React.FC<{
70
96
  }));
71
97
 
72
98
  const gradientOpacityStyle = useAnimatedStyle(() => ({
73
- opacity: interpolate(sharedValue.value, [0, 52], [1, 0], Extrapolation.CLAMP),
99
+ opacity: interpolate(
100
+ sharedValue.value,
101
+ [0, 52],
102
+ [1, 0],
103
+ Extrapolation.CLAMP,
104
+ ),
74
105
  }));
75
106
 
76
107
  const searchTranslateStyle = useAnimatedStyle(() => ({
@@ -79,7 +110,15 @@ const HeaderExtendHeader: React.FC<{
79
110
  translateX: interpolate(
80
111
  sharedValue.value,
81
112
  [0, 100],
82
- [SCREEN_PADDING, leftPosition],
113
+ [contentLeft, collapsedLeft],
114
+ Extrapolation.CLAMP,
115
+ ),
116
+ },
117
+ {
118
+ translateY: interpolate(
119
+ sharedValue.value,
120
+ [0, 100],
121
+ [0, -collapsedRaise],
83
122
  Extrapolation.CLAMP,
84
123
  ),
85
124
  },
@@ -87,19 +126,19 @@ const HeaderExtendHeader: React.FC<{
87
126
  width: interpolate(
88
127
  sharedValue.value,
89
128
  [0, 100],
90
- [
91
- screenWidth - SCREEN_PADDING * 2,
92
- screenWidth - leftPosition - 12 - headerRightWidth,
93
- ],
129
+ [searchWidth, collapsedSearchWidth],
94
130
  Extrapolation.CLAMP,
95
131
  ),
96
132
  }));
97
133
 
98
134
  const searchBackgroundStyle = useAnimatedStyle(() => {
99
135
  const t = Math.min(Math.max(sharedValue.value / 100, 0), 1);
100
- return { backgroundColor: t === 0
101
- ? theme.colors.background.surface
102
- : theme.colors.background.default };
136
+ return {
137
+ backgroundColor:
138
+ t === 0
139
+ ? theme.colors.background.surface
140
+ : theme.colors.background.default,
141
+ };
103
142
  });
104
143
 
105
144
  const extendedHeightStyle = useAnimatedStyle(() => ({
@@ -124,14 +163,17 @@ const HeaderExtendHeader: React.FC<{
124
163
  <Animated.View
125
164
  style={[
126
165
  styles.headerBox,
127
- headerType === 'extended'
128
- ? heightStyle
129
- : { height: heightHeader },
166
+ headerType === 'extended' ? heightStyle : { height: heightHeader },
130
167
  ]}
131
168
  >
132
169
  {!!gradientColor && (
133
170
  <Animated.View
134
- style={[styles.extendedHeader, gradientOpacityStyle]}
171
+ style={[
172
+ styles.extendedHeader,
173
+ // fade out within the header box, as DuoScrollGradient does
174
+ !!layout.sideBar && styles.fillHeaderBox,
175
+ gradientOpacityStyle,
176
+ ]}
135
177
  >
136
178
  <LinearGradient
137
179
  colors={[gradientColor, gradientColor + '00']}
@@ -162,10 +204,7 @@ const HeaderExtendHeader: React.FC<{
162
204
  style={[{ marginVertical: Spacing.S }, searchTranslateStyle]}
163
205
  >
164
206
  <Animated.View
165
- style={[
166
- { borderRadius: Radius.XL },
167
- searchBackgroundStyle,
168
- ]}
207
+ style={[{ borderRadius: Radius.XL }, searchBackgroundStyle]}
169
208
  >
170
209
  <InputSearch
171
210
  {...inputSearchProps}
@@ -191,7 +230,11 @@ const HeaderExtendHeader: React.FC<{
191
230
  />
192
231
  {!!gradientColor && (
193
232
  <Animated.View
194
- style={[styles.extendedHeader, gradientOpacityStyle, extendedHeightStyle]}
233
+ style={[
234
+ styles.extendedHeader,
235
+ gradientOpacityStyle,
236
+ extendedHeightStyle,
237
+ ]}
195
238
  >
196
239
  <LinearGradient
197
240
  colors={[gradientColor, gradientColor + '00']}
@@ -227,6 +270,10 @@ const styles = StyleSheet.create({
227
270
  position: 'absolute',
228
271
  width: '100%',
229
272
  },
273
+ fillHeaderBox: {
274
+ aspectRatio: undefined,
275
+ height: '100%',
276
+ },
230
277
  headerBox: {
231
278
  width: '100%',
232
279
  position: 'absolute',
@@ -4,6 +4,10 @@ import React, { useCallback, useContext, useEffect } from 'react';
4
4
  import { ApplicationContext, MiniAppContext } from '../../Context';
5
5
  import { PopupNotify } from '../../Popup';
6
6
  import { NavigationButton } from './NavigationButton';
7
+ import { SideBarButton } from './SideBarButton';
8
+ import Animated from 'react-native-reanimated';
9
+ import { useScreenLayout, useSideBarItemStyle } from '../../Layout/utils';
10
+ import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
7
11
 
8
12
  /**
9
13
  * default header left used for nav
@@ -13,9 +17,13 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
13
17
  preventBack,
14
18
  onPressLeftHeader,
15
19
  onBackHandler,
20
+ floating = false,
16
21
  }) => {
17
22
  const context = useContext<any>(MiniAppContext);
18
23
  const { navigator } = useContext(ApplicationContext);
24
+ const sideBarStyle = useSideBarItemStyle('left', 0);
25
+ const counterStyle = useSideBarCounterStyle();
26
+ const { statusBarClearance } = useScreenLayout();
19
27
 
20
28
  const goBack = useCallback(() => {
21
29
  const canGoBack = navigator?.ref?.current?.canGoBack?.();
@@ -72,6 +80,36 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
72
80
  return () => backHandler.remove();
73
81
  }, [goBackSafe]);
74
82
 
83
+ if (floating && sideBarStyle) {
84
+ return (
85
+ <Animated.View
86
+ style={[sideBarStyle, counterStyle]}
87
+ pointerEvents={'box-none'}
88
+ >
89
+ <SideBarButton
90
+ accessibilityLabel="btn_navigation_back"
91
+ icon="arrow-back"
92
+ tintColor={tintColor}
93
+ onPress={goBackSafe}
94
+ />
95
+ </Animated.View>
96
+ );
97
+ }
98
+
99
+ // on the status bar row the controls keep the side bar size
100
+ if (statusBarClearance) {
101
+ return (
102
+ <View style={styles.headerLeft}>
103
+ <SideBarButton
104
+ accessibilityLabel="btn_navigation_back"
105
+ icon="arrow-back"
106
+ tintColor={tintColor}
107
+ onPress={goBackSafe}
108
+ />
109
+ </View>
110
+ );
111
+ }
112
+
75
113
  return (
76
114
  <View style={styles.headerLeft}>
77
115
  <NavigationButton
@@ -13,6 +13,12 @@ import { PopupNotify } from '../../Popup';
13
13
  import { Tool, ToolGroup } from '../types';
14
14
  import { Icon } from '../../Icon';
15
15
  import { Text } from '../../Text';
16
+ import Animated from 'react-native-reanimated';
17
+ import { useScreenLayout, useSideBarItemStyle } from '../../Layout/utils';
18
+ import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
19
+ import { SideBarButton, SideBarGroup, SideBarGroupItem } from './SideBarButton';
20
+ import { useDuoBarCompression } from '../BottomTab/DuoBarCompression';
21
+ import { DuoMetrics } from '../../Layout/utils';
16
22
 
17
23
  const DID_SYNC_NEW_HOME = 'did_sync_new_home';
18
24
 
@@ -21,8 +27,10 @@ const DID_SYNC_NEW_HOME = 'did_sync_new_home';
21
27
  */
22
28
  const HeaderRight: React.FC<any> = props => {
23
29
  const { translate } = useContext(ApplicationContext);
24
- const { headerRight = {} } = props;
30
+ const { headerRight = {}, floating = false } = props;
25
31
  const { useOnBoarding = false, buttonOnBoarding, onPress } = headerRight;
32
+ const sideBarStyle = useSideBarItemStyle('right', 1);
33
+ const counterStyle = useSideBarCounterStyle();
26
34
 
27
35
  if (typeof props.headerRight === 'function') {
28
36
  return props.headerRight(props);
@@ -38,6 +46,21 @@ const HeaderRight: React.FC<any> = props => {
38
46
  );
39
47
  }
40
48
 
49
+ if (floating && sideBarStyle) {
50
+ return (
51
+ <Animated.View
52
+ style={[sideBarStyle, counterStyle]}
53
+ pointerEvents={'box-none'}
54
+ >
55
+ <HeaderToolkitAction
56
+ {...props.headerRight}
57
+ tintColor={props.tintColor}
58
+ vertical
59
+ />
60
+ </Animated.View>
61
+ );
62
+ }
63
+
41
64
  return (
42
65
  <View style={styles.headerRightButton}>
43
66
  <HeaderToolkitAction {...props.headerRight} tintColor={props.tintColor} />
@@ -56,9 +79,13 @@ const HeaderToolkitAction: React.FC<any> = ({
56
79
  useMore = false,
57
80
  tools = [],
58
81
  useCloseIcon = false,
82
+ vertical = false,
59
83
  }) => {
60
84
  const { navigator } = useContext(ApplicationContext);
61
85
  const context = useContext<any>(MiniAppContext);
86
+ const { toolbarCompressed, toolbarHidden, expandToolbar, setToolbarHeight } =
87
+ useDuoBarCompression();
88
+ const { statusBarClearance } = useScreenLayout();
62
89
 
63
90
  const [isFavorite, setIsFavorite] = useState<boolean>(false);
64
91
  const [isLoading, setIsLoading] = useState(false);
@@ -260,6 +287,111 @@ const HeaderToolkitAction: React.FC<any> = ({
260
287
  group?.items?.some?.(tool => tool?.showBadge),
261
288
  );
262
289
 
290
+ const useHelpCenter = context.appId !== 'vn.momo.helpcenter';
291
+ const closeIcon = useCloseIcon
292
+ ? '16_navigation_close_circle'
293
+ : '16_basic_home';
294
+
295
+ const groupCount = useHelpCenter ? 2 : 1;
296
+ // Back slot, the optional shortcut, then the help/home capsule
297
+ const fullToolbarHeight =
298
+ DuoMetrics.controlSize +
299
+ Spacing.M +
300
+ (useShortcut ? DuoMetrics.controlSize + Spacing.M : 0) +
301
+ (groupCount > 1
302
+ ? groupCount * DuoMetrics.itemPitch
303
+ : DuoMetrics.controlSize);
304
+
305
+ useEffect(() => {
306
+ if (vertical) {
307
+ setToolbarHeight?.(fullToolbarHeight);
308
+ }
309
+ }, [vertical, fullToolbarHeight, setToolbarHeight]);
310
+
311
+ // an open tab rail takes this slot for a moment
312
+ if (vertical && toolbarHidden) {
313
+ return null;
314
+ }
315
+
316
+ // HIG "Toolbar compressed": tools fold into one button; tapping it expands the
317
+ // toolbar and compresses the tab bar instead. Not the useMore icon, to tell them apart
318
+ if (vertical && toolbarCompressed) {
319
+ return (
320
+ <SideBarButton
321
+ accessibilityLabel={'btn_navigation_toolbar'}
322
+ icon={'navigation_menu'}
323
+ tintColor={tintColor}
324
+ showBadge={showBadge}
325
+ onPress={expandToolbar}
326
+ />
327
+ );
328
+ }
329
+
330
+ if (vertical) {
331
+ return (
332
+ <View style={styles.sideBarColumn}>
333
+ {useShortcut && (
334
+ <SideBarButton
335
+ disabled={isLoading}
336
+ icon={iconShortcut}
337
+ onPress={shortcutOnPress}
338
+ tintColor={tintColor}
339
+ showBadge={showBadge}
340
+ />
341
+ )}
342
+ <SideBarGroup tintColor={tintColor}>
343
+ {useHelpCenter && (
344
+ <SideBarGroupItem
345
+ accessibilityLabel={'btn_navigation_help_center'}
346
+ icon={'help_center'}
347
+ tintColor={tintColor}
348
+ onPress={onPressHelpCenter}
349
+ />
350
+ )}
351
+ <SideBarGroupItem
352
+ accessibilityLabel={'btn_navigation_close'}
353
+ icon={closeIcon}
354
+ tintColor={tintColor}
355
+ onPress={onClose}
356
+ />
357
+ </SideBarGroup>
358
+ </View>
359
+ );
360
+ }
361
+
362
+ // on the status bar row the controls keep the side bar size
363
+ if (statusBarClearance) {
364
+ return (
365
+ <View style={styles.sideBarRow}>
366
+ {useShortcut && (
367
+ <SideBarButton
368
+ disabled={isLoading}
369
+ icon={iconShortcut}
370
+ onPress={shortcutOnPress}
371
+ tintColor={tintColor}
372
+ showBadge={showBadge}
373
+ />
374
+ )}
375
+ <SideBarGroup tintColor={tintColor} horizontal>
376
+ {useHelpCenter && (
377
+ <SideBarGroupItem
378
+ accessibilityLabel={'btn_navigation_help_center'}
379
+ icon={'help_center'}
380
+ tintColor={tintColor}
381
+ onPress={onPressHelpCenter}
382
+ />
383
+ )}
384
+ <SideBarGroupItem
385
+ accessibilityLabel={'btn_navigation_close'}
386
+ icon={closeIcon}
387
+ tintColor={tintColor}
388
+ onPress={onClose}
389
+ />
390
+ </SideBarGroup>
391
+ </View>
392
+ );
393
+ }
394
+
263
395
  return (
264
396
  <View style={Styles.row}>
265
397
  {useShortcut && (
@@ -280,7 +412,7 @@ const HeaderToolkitAction: React.FC<any> = ({
280
412
  },
281
413
  ]}
282
414
  >
283
- {context.appId !== 'vn.momo.helpcenter' && (
415
+ {useHelpCenter && (
284
416
  <>
285
417
  <TouchableOpacity
286
418
  accessibilityLabel={'btn_navigation_help_center'}
@@ -299,13 +431,7 @@ const HeaderToolkitAction: React.FC<any> = ({
299
431
  style={styles.toolkitButton}
300
432
  hitSlop={{ top: 7, bottom: 7, left: 0, right: 7 }}
301
433
  >
302
- <Icon
303
- color={tintColor}
304
- source={
305
- useCloseIcon ? '16_navigation_close_circle' : '16_basic_home'
306
- }
307
- size={20}
308
- />
434
+ <Icon color={tintColor} source={closeIcon} size={20} />
309
435
  </TouchableOpacity>
310
436
  </View>
311
437
  </View>
@@ -376,6 +502,13 @@ const styles = StyleSheet.create({
376
502
  width: 0.5,
377
503
  height: 12,
378
504
  },
505
+ sideBarColumn: {
506
+ gap: Spacing.M,
507
+ },
508
+ sideBarRow: {
509
+ flexDirection: 'row',
510
+ gap: Spacing.M,
511
+ },
379
512
  headerLeft: {
380
513
  marginLeft: 12,
381
514
  },
@@ -7,13 +7,7 @@ import Animated, {
7
7
  } from 'react-native-reanimated';
8
8
  import { ApplicationContext, MiniAppContext } from '../../Context';
9
9
  import { exportFontFamily, Text, useScaleSize } from '../../Text';
10
- import {
11
- Colors,
12
- Radius,
13
- Spacing,
14
- Styles,
15
- useHeaderFontFamily,
16
- } from '../../Consts';
10
+ import { Colors, Radius, Spacing, Styles } from '../../Consts';
17
11
  import {
18
12
  TitleJourneyProps,
19
13
  TitleLocationProps,
@@ -22,7 +16,47 @@ import {
22
16
  import { Image } from '../../Image';
23
17
  import { Icon } from '../../Icon';
24
18
  import { Skeleton } from '../../Skeleton';
25
- import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
19
+ import {
20
+ AnimatedCompatValue,
21
+ isWhiteListDesignSystem,
22
+ useNormalizedSharedValue,
23
+ } from '../utils';
24
+ import { useScreenLayout } from '../../Layout';
25
+
26
+ const useHeaderFontFamily = (): string => {
27
+ const context = useContext<any>(MiniAppContext);
28
+ return isWhiteListDesignSystem(context) ? 'MoMoTrustDisplay' : 'SFProText';
29
+ };
30
+
31
+ /**
32
+ * back button and toolkit sharing the navigation bar with the title
33
+ */
34
+ const HEADER_ACTIONS_WIDTH = 172;
35
+
36
+ /**
37
+ * extra width the 48pt back and toolkit take on the iPhone Duo status bar row
38
+ */
39
+ const STATUS_BAR_ROW_ACTIONS_EXTRA = 55;
40
+
41
+ /**
42
+ * max title width, the iPhone Duo side bar takes back and toolkit out of the bar
43
+ */
44
+ const useTitleMaxWidth = () => {
45
+ const { width, contentWidth, sideBar, statusBarClearance } =
46
+ useScreenLayout();
47
+ const clearance = statusBarClearance
48
+ ? statusBarClearance.left + statusBarClearance.right
49
+ : 0;
50
+ if (sideBar) {
51
+ return contentWidth - Spacing.M * 2 - clearance;
52
+ }
53
+ return (
54
+ width -
55
+ HEADER_ACTIONS_WIDTH -
56
+ (statusBarClearance ? STATUS_BAR_ROW_ACTIONS_EXTRA : 0) -
57
+ clearance
58
+ );
59
+ };
26
60
 
27
61
  type HeaderTitleInterpolate = {
28
62
  inputRange: number[];
@@ -44,6 +78,7 @@ const HeaderTitle: React.FC<
44
78
  > = props => {
45
79
  const context = useContext<any>(MiniAppContext);
46
80
  const headerFontFamily = useHeaderFontFamily();
81
+ const maxWidth = useTitleMaxWidth();
47
82
 
48
83
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
49
84
 
@@ -74,7 +109,7 @@ const HeaderTitle: React.FC<
74
109
  style={[
75
110
  {
76
111
  justifyContent: 'center',
77
- maxWidth: Dimensions.get('window').width - 172,
112
+ maxWidth,
78
113
  },
79
114
  showBaseLineDebug && styles.debugBaseLine,
80
115
  ]}
@@ -138,7 +173,7 @@ const TitleUser: React.FC<TitleUserProps> = ({
138
173
  }) => {
139
174
  const { theme } = useContext(ApplicationContext);
140
175
  const headerFontFamily = useHeaderFontFamily();
141
- const maxWidth = Dimensions.get('window').width - 172;
176
+ const maxWidth = useTitleMaxWidth();
142
177
  const getShortName = (name: string) => {
143
178
  const words = name.split(' ');
144
179
  const lastTwoWords = words.slice(-2);
@@ -421,7 +456,7 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
421
456
  isLoading,
422
457
  }) => {
423
458
  const headerFontFamily = useHeaderFontFamily();
424
- const maxWidth = Dimensions.get('window').width - 172;
459
+ const maxWidth = useTitleMaxWidth();
425
460
  const renderShimmer = () => {
426
461
  return (
427
462
  <View style={Styles.flex}>
@@ -457,9 +492,12 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
457
492
  </Text>
458
493
  )}
459
494
  <View style={Styles.row}>
460
- <Text typography="action_xs_bold"
495
+ <Text
496
+ typography="action_xs_bold"
461
497
  fontFamily={headerFontFamily}
462
- color={tintColor} numberOfLines={1}>
498
+ color={tintColor}
499
+ numberOfLines={1}
500
+ >
463
501
  {location}
464
502
  </Text>
465
503
  <Icon
@@ -487,10 +525,14 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
487
525
  isLoading,
488
526
  }) => {
489
527
  const headerFontFamily = useHeaderFontFamily();
490
- const { width } = Dimensions.get('screen');
491
- const maxWidth = Dimensions.get('window').width - 172;
492
- const startWidth = width * 0.25;
493
- const endWidth = width * 0.75 - 212;
528
+ const maxWidth = useTitleMaxWidth();
529
+ const { sideBar } = useScreenLayout();
530
+ // journey split is tuned against the whole bar width
531
+ const barWidth = sideBar
532
+ ? maxWidth + HEADER_ACTIONS_WIDTH
533
+ : Dimensions.get('screen').width;
534
+ const startWidth = barWidth * 0.25;
535
+ const endWidth = barWidth * 0.75 - 212;
494
536
  const renderShimmer = () => {
495
537
  return (
496
538
  <View style={Styles.flex}>
@@ -522,8 +564,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
522
564
  style={{ maxWidth: startWidth }}
523
565
  color={tintColor}
524
566
  numberOfLines={1}
525
- fontFamily={headerFontFamily}
526
-
567
+ fontFamily={headerFontFamily}
527
568
  >
528
569
  {start}
529
570
  </Text>
@@ -539,8 +580,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
539
580
  typography="action_xs_bold"
540
581
  color={tintColor}
541
582
  numberOfLines={1}
542
- fontFamily={headerFontFamily}
543
-
583
+ fontFamily={headerFontFamily}
544
584
  >
545
585
  {end}
546
586
  </Text>
@@ -0,0 +1,11 @@
1
+ import type React from 'react';
2
+
3
+ // native glass is optional so apps without @momo-kits/glass-view still bundle
4
+ let GlassView: React.ComponentType<any> | undefined;
5
+ try {
6
+ GlassView = require('@momo-kits/glass-view').GlassView;
7
+ } catch {
8
+ GlassView = undefined;
9
+ }
10
+
11
+ export { GlassView };
@@ -0,0 +1,12 @@
1
+ import type React from 'react';
2
+
3
+ // native observer is optional so apps without it in @momo-kits/reserved-regions still bundle
4
+ let ScrollObserverView: React.ComponentType<any> | undefined;
5
+ try {
6
+ ScrollObserverView =
7
+ require('@momo-kits/reserved-regions').ScrollObserverView;
8
+ } catch {
9
+ ScrollObserverView = undefined;
10
+ }
11
+
12
+ export { ScrollObserverView };