@momo-kits/foundation 0.169.7-beta.4 → 0.169.7-beta.5

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 (143) hide show
  1. package/Application/BottomSheet.hooks.ts +8 -8
  2. package/Application/BottomSheet.parts.tsx +44 -34
  3. package/Application/BottomSheet.tsx +40 -37
  4. package/Application/BottomTab/ActiveIndicator.tsx +20 -15
  5. package/Application/BottomTab/BottomTabBar.styles.ts +18 -1
  6. package/Application/BottomTab/BottomTabBar.tsx +57 -72
  7. package/Application/BottomTab/BottomTabInset.tsx +8 -4
  8. package/Application/BottomTab/CurvedContainer.tsx +22 -14
  9. package/Application/BottomTab/CustomBottomTabItem.tsx +15 -15
  10. package/Application/BottomTab/DuoBarCompression.tsx +13 -19
  11. package/Application/BottomTab/DuoRailTabBar.tsx +20 -24
  12. package/Application/BottomTab/DuoTabBar.tsx +23 -13
  13. package/Application/BottomTab/TabBarIcon.tsx +15 -29
  14. package/Application/BottomTab/TabScreen.tsx +1 -5
  15. package/Application/BottomTab/index.tsx +33 -30
  16. package/Application/BottomTab/metrics.ts +46 -26
  17. package/Application/BottomTab/tabItems.ts +1 -1
  18. package/Application/BottomTab/usePressLift.ts +2 -2
  19. package/Application/Components/BackgroundImageView.tsx +4 -0
  20. package/Application/Components/DuoGlassBackground.tsx +5 -4
  21. package/Application/Components/HeaderAnimated.tsx +4 -0
  22. package/Application/Components/HeaderBackground.tsx +4 -0
  23. package/Application/Components/HeaderExtendHeader.tsx +11 -10
  24. package/Application/Components/HeaderLeft.tsx +2 -1
  25. package/Application/Components/HeaderRight.tsx +2 -1
  26. package/Application/Components/HeaderTitle.shared.ts +11 -9
  27. package/Application/Components/HeaderTitle.tsx +4 -3
  28. package/Application/Components/HeaderToolkitAction.tsx +17 -20
  29. package/Application/Components/NavigationButton.tsx +2 -1
  30. package/Application/Components/SearchHeader.tsx +17 -10
  31. package/Application/Components/TitleJourney.tsx +2 -2
  32. package/Application/Components/TitleLocation.tsx +2 -2
  33. package/Application/Components/TitleUser.tsx +2 -2
  34. package/Application/Components/useToolkitActions.tsx +17 -32
  35. package/Application/Localize.ts +7 -0
  36. package/Application/ModalScreen.tsx +10 -10
  37. package/Application/Navigation.ts +14 -16
  38. package/Application/NavigationContainer.tsx +19 -18
  39. package/Application/Navigator.ts +20 -48
  40. package/Application/ScaleSizeProvider.tsx +13 -6
  41. package/Application/StackScreen.tracking.ts +11 -33
  42. package/Application/StackScreen.tsx +10 -54
  43. package/Application/TooltipPortal.tsx +12 -5
  44. package/Application/WidgetContainer.tsx +10 -4
  45. package/Application/modalLayout.ts +13 -14
  46. package/Application/navigationOptions.tsx +21 -17
  47. package/Application/types.tabs.ts +0 -1
  48. package/Badge/Badge.tsx +5 -0
  49. package/Badge/BadgeDot.tsx +1 -0
  50. package/Badge/BadgeDotAnimation.tsx +15 -7
  51. package/Badge/BadgeRibbon.tsx +46 -38
  52. package/Badge/Shape.tsx +2 -0
  53. package/Badge/types.ts +2 -2
  54. package/Button/index.tsx +5 -16
  55. package/Button/utils.ts +9 -15
  56. package/CheckBox/index.tsx +4 -0
  57. package/Consts/theme.ts +10 -10
  58. package/Context/index.ts +5 -1
  59. package/Divider/DashDivider.tsx +1 -0
  60. package/Divider/index.tsx +4 -0
  61. package/FoundationList/index.tsx +4 -0
  62. package/Icon/index.tsx +6 -6
  63. package/Icon/types.ts +1 -1
  64. package/IconButton/index.tsx +4 -12
  65. package/Image/index.tsx +9 -7
  66. package/Input/Input.tsx +8 -9
  67. package/Input/InputDropDown.tsx +10 -12
  68. package/Input/InputMoney.tsx +12 -8
  69. package/Input/InputMoneyView.tsx +14 -7
  70. package/Input/InputOTP.tsx +35 -33
  71. package/Input/InputPhoneNumber.tsx +8 -9
  72. package/Input/InputSearch.tsx +4 -6
  73. package/Input/InputTextArea.tsx +4 -0
  74. package/Input/SearchTextTyping.tsx +4 -0
  75. package/Input/SystemTextInput.tsx +7 -2
  76. package/Input/TextTyping.tsx +4 -0
  77. package/Input/common.tsx +26 -12
  78. package/Input/index.tsx +17 -20
  79. package/Input/moneyUtils.ts +10 -4
  80. package/Input/styles.ts +0 -5
  81. package/Input/utils.ts +14 -12
  82. package/Layout/Card.tsx +7 -4
  83. package/Layout/FloatingButton.tsx +4 -0
  84. package/Layout/Item.tsx +6 -2
  85. package/Layout/ItemList.tsx +9 -7
  86. package/Layout/ItemSectionList.tsx +2 -1
  87. package/Layout/ReservedRegions.tsx +25 -25
  88. package/Layout/Screen.tsx +56 -58
  89. package/Layout/Section.tsx +8 -5
  90. package/Layout/TrackingScope.tsx +1 -0
  91. package/Layout/screenContent.tsx +4 -2
  92. package/Layout/screenFooter.tsx +28 -18
  93. package/Layout/screenHeader.tsx +34 -31
  94. package/Layout/screenQuickReturn.tsx +17 -20
  95. package/Layout/screenScroll.ts +4 -7
  96. package/Layout/screenTypes.ts +3 -2
  97. package/Layout/types.ts +2 -4
  98. package/Layout/utils.ts +31 -37
  99. package/Loader/DotLoader.tsx +4 -0
  100. package/Loader/Loader.tsx +4 -0
  101. package/Loader/ProgressBar.tsx +1 -0
  102. package/Loader/Spinner.tsx +4 -0
  103. package/Loader/utils.ts +11 -7
  104. package/Pagination/Dot.tsx +4 -0
  105. package/Pagination/PaginationDot.tsx +1 -0
  106. package/Pagination/PaginationNumber.tsx +5 -3
  107. package/Pagination/PaginationScroll.tsx +5 -0
  108. package/Pagination/PaginationWhiteDot.tsx +1 -0
  109. package/Pagination/index.tsx +4 -0
  110. package/Pagination/types.ts +2 -2
  111. package/Popup/PopupNotify.tsx +44 -48
  112. package/Popup/PopupPromotion.tsx +4 -7
  113. package/Popup/types.ts +4 -4
  114. package/Popup/utils.ts +4 -0
  115. package/Radio/index.tsx +4 -0
  116. package/Skeleton/index.tsx +8 -0
  117. package/Switch/index.tsx +1 -0
  118. package/Tag/index.tsx +5 -1
  119. package/Tag/types.ts +3 -3
  120. package/Text/index.tsx +14 -3
  121. package/Text/styles.ts +1 -1
  122. package/Text/types.ts +1 -6
  123. package/Text/utils.ts +20 -4
  124. package/Title/index.tsx +41 -32
  125. package/ViewBoundary/index.tsx +4 -2
  126. package/index.ts +0 -6
  127. package/package.json +1 -1
  128. package/Application/KitAdoption/AdoptionBadge.tsx +0 -119
  129. package/Application/KitAdoption/AdoptionProbe.tsx +0 -166
  130. package/Application/KitAdoption/AdoptionStore.ts +0 -80
  131. package/Application/KitAdoption/Authorship/utils.ts +0 -137
  132. package/Application/KitAdoption/Slots/utils.ts +0 -68
  133. package/Application/KitAdoption/constants.ts +0 -120
  134. package/Application/KitAdoption/index.ts +0 -12
  135. package/Application/KitAdoption/styles.ts +0 -55
  136. package/Application/KitAdoption/types.ts +0 -61
  137. package/Application/KitAdoption/utils.ts +0 -376
  138. package/Application/__tests__/KitAdoption.integration.test.tsx +0 -253
  139. package/Application/__tests__/KitAdoption.test.ts +0 -283
  140. package/Application/__tests__/KitAdoptionAuthorship.test.ts +0 -132
  141. package/Application/__tests__/KitAdoptionStore.test.ts +0 -110
  142. package/Application/__tests__/KitAdoptionStructural.test.ts +0 -193
  143. package/Application/__tests__/modalLayout.test.ts +0 -128
@@ -15,7 +15,8 @@ type ToolkitActionsParams = {
15
15
  };
16
16
 
17
17
  /**
18
- * state and handlers behind the header toolkit buttons
18
+ * State and handlers behind the header toolkit: the favorite shortcut (kept in sync
19
+ * with the home), single tool or "more" shortcut, help center and close.
19
20
  */
20
21
  const useToolkitActions = ({
21
22
  preventClose,
@@ -31,20 +32,15 @@ const useToolkitActions = ({
31
32
  const [isFavorite, setIsFavorite] = useState<boolean>(false);
32
33
  const [isLoading, setIsLoading] = useState(false);
33
34
 
34
- /**
35
- * check app is favorite
36
- */
37
- const checkAppIsFavorite = useCallback(
38
- () =>
39
- navigator?.maxApi?.dispatchFunction?.(
40
- 'isFavoriteApp',
41
- { code: context?.code },
42
- (result: boolean) => {
43
- setIsFavorite(result);
44
- },
45
- ),
46
- [context?.code, navigator?.maxApi],
47
- );
35
+ const checkAppIsFavorite = useCallback(() => {
36
+ return navigator?.maxApi?.dispatchFunction?.(
37
+ 'isFavoriteApp',
38
+ { code: context?.code },
39
+ (result: boolean) => {
40
+ setIsFavorite(result);
41
+ },
42
+ );
43
+ }, [context?.code, navigator?.maxApi]);
48
44
 
49
45
  useEffect(() => {
50
46
  if (useShortcut) {
@@ -75,9 +71,6 @@ const useToolkitActions = ({
75
71
  }
76
72
  };
77
73
 
78
- /**
79
- * close navigation container
80
- */
81
74
  const onClose = () => {
82
75
  const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
83
76
  context?.autoTracking?.({
@@ -107,9 +100,6 @@ const useToolkitActions = ({
107
100
  }
108
101
  };
109
102
 
110
- /**
111
- * on press shortcut
112
- */
113
103
  const onPressShortcut = () => {
114
104
  const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
115
105
  const expected = !isFavorite;
@@ -139,9 +129,6 @@ const useToolkitActions = ({
139
129
  }, 1000);
140
130
  };
141
131
 
142
- /**
143
- * on press help center
144
- */
145
132
  const onPressHelpCenter = () => {
146
133
  const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
147
134
  context?.autoTracking?.({
@@ -154,9 +141,6 @@ const useToolkitActions = ({
154
141
  navigator?.maxApi?.dispatchFunction?.('showHelpCenter', context);
155
142
  };
156
143
 
157
- /**
158
- * on press icon more
159
- */
160
144
  const onPressIconMore = () => {
161
145
  const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
162
146
  context?.autoTracking?.({
@@ -200,9 +184,10 @@ const useToolkitActions = ({
200
184
  iconShortcut = 'navigation_more_icon';
201
185
  shortcutOnPress = onPressIconMore;
202
186
  } else if (isHaveOneTool) {
203
- const singleTool = tools.find(
187
+ const singleToolGroup = tools.find(
204
188
  (group: ToolGroup) => group?.items?.length === 1,
205
- )?.items[0];
189
+ );
190
+ const singleTool = singleToolGroup?.items[0];
206
191
  iconShortcut = singleTool?.icon;
207
192
  shortcutOnPress = () => {
208
193
  singleTool?.onPress?.();
@@ -216,9 +201,9 @@ const useToolkitActions = ({
216
201
  };
217
202
  }
218
203
 
219
- const showBadge = tools.some((group: ToolGroup) =>
220
- group?.items?.some?.(tool => tool?.showBadge),
221
- );
204
+ const showBadge = tools.some((group: ToolGroup) => {
205
+ return group?.items?.some?.(tool => tool?.showBadge);
206
+ });
222
207
 
223
208
  return {
224
209
  isLoading,
@@ -2,6 +2,10 @@ import { NativeModules } from 'react-native';
2
2
  import { LocalizationObject } from './types';
3
3
  import defaultLanguage from '../Assets/language.json';
4
4
 
5
+ /**
6
+ * String table for kit and feature copy. The language is read once from the
7
+ * native `RNResource` module at construction; Vietnamese is the default.
8
+ */
5
9
  class Localize {
6
10
  private assets: LocalizationObject;
7
11
  private readonly currentLanguage: 'en' | 'vi';
@@ -25,14 +29,17 @@ class Localize {
25
29
  return this.assets;
26
30
  }
27
31
 
32
+ /** Text for `key` in the current language, or the key itself if missing. */
28
33
  translate(key: string) {
29
34
  return this.assets[this.currentLanguage]?.[key] || key;
30
35
  }
31
36
 
37
+ /** Picks the current-language text of a `{ vi, en }` pair, else its JSON. */
32
38
  translateData(data: { vi: string; en: string }) {
33
39
  return data[this.currentLanguage] ?? JSON.stringify(data);
34
40
  }
35
41
 
42
+ /** Merges extra translations; keys that already exist keep their text. */
36
43
  addTranslations(translations: LocalizationObject) {
37
44
  this.assets = {
38
45
  vi: { ...translations?.vi, ...this.assets.vi },
@@ -24,10 +24,13 @@ import Navigation from './Navigation';
24
24
  import { ModalParams } from './types';
25
25
  import BottomSheet from './BottomSheet';
26
26
  import { isIPhoneDuo } from './utils';
27
- import { AdoptionProbe } from './KitAdoption';
28
27
  import { useModalLayout } from './modalLayout';
29
28
  import { scheduleOnRN } from 'react-native-worklets';
30
29
 
30
+ /**
31
+ * Screen of the `Modal` route: a bottom sheet when pushed by
32
+ * `showBottomSheet`, otherwise a centered popup.
33
+ */
31
34
  const ModalScreen: React.FC<any> = props => {
32
35
  if (props.route?.params?.isBottomSheet) {
33
36
  return <BottomSheet {...props} />;
@@ -35,6 +38,10 @@ const ModalScreen: React.FC<any> = props => {
35
38
  return <Modal {...props} />;
36
39
  };
37
40
 
41
+ /**
42
+ * Centered popup that fades and scales in over a scrim. On foldables it is
43
+ * centered in the modal placement area, at most a popup wide.
44
+ */
38
45
  const Modal: React.FC<ModalParams> = props => {
39
46
  const { navigator } = useContext(ApplicationContext);
40
47
  const context = useContext<any>(MiniAppContext);
@@ -51,9 +58,7 @@ const Modal: React.FC<ModalParams> = props => {
51
58
  const isDuo = isIPhoneDuo();
52
59
  const { isFoldable, placement, popup, scrimOpacity } = useModalLayout();
53
60
 
54
- /**
55
- * Fire auto_popup_displayed tracking event on mount
56
- */
61
+ // Auto-tracks the popup as displayed on the current screen.
57
62
  useEffect(() => {
58
63
  navigator?.maxApi?.getDataObserver?.('current_screen', (curScreen: any) => {
59
64
  context.autoTracking({
@@ -183,12 +188,7 @@ const Modal: React.FC<ModalParams> = props => {
183
188
  modalStyle,
184
189
  ]}
185
190
  >
186
- <AdoptionProbe
187
- screenName={Component?.name || Component?.type?.name || 'Invalid'}
188
- navigation={props.navigation}
189
- >
190
- <Component {...params} onRequestClose={onDismiss} />
191
- </AdoptionProbe>
191
+ <Component {...params} onRequestClose={onDismiss} />
192
192
  </Animated.View>
193
193
  </KeyboardAvoidingView>
194
194
  </Container>
@@ -11,6 +11,10 @@ export const WHITE_LIST = [
11
11
  'vn.momo.ekyc',
12
12
  ];
13
13
 
14
+ /**
15
+ * Screen-level navigation handle given to features; `setOptions` enforces the
16
+ * design system's header rules before applying React Navigation options.
17
+ */
14
18
  class Navigation {
15
19
  instance: NavigationProp<any>;
16
20
  context: any;
@@ -21,39 +25,33 @@ class Navigation {
21
25
  }
22
26
 
23
27
  /**
24
- * navigation options filter by design system rule
25
- * @param params
28
+ * Drops header overrides the design system forbids: any `headerLeft`, and
29
+ * render-function `headerRight`/`headerTitle` outside `WHITE_LIST` apps.
26
30
  */
27
31
  private filterParams = (params: NavigationOptions) => {
32
+ const isWhiteListed = WHITE_LIST.includes(this.context?.appId);
33
+ const rightType = typeof params.headerRight;
34
+ const titleType = typeof params.headerTitle;
35
+ const isTitleRenderer = titleType !== 'string' && titleType !== 'object';
36
+
28
37
  if (params.headerLeft) {
29
38
  console.warn('headerLeft not allow override render by design system!');
30
39
  delete params.headerLeft;
31
40
  }
32
41
 
33
- if (
34
- params.headerRight &&
35
- typeof params.headerRight !== 'object' &&
36
- !WHITE_LIST.includes(this.context?.appId)
37
- ) {
42
+ if (params.headerRight && rightType !== 'object' && !isWhiteListed) {
38
43
  console.warn('headerRight not allow type func render by design system!');
39
44
  delete params.headerRight;
40
45
  }
41
46
 
42
- if (
43
- params.headerTitle &&
44
- !['string', 'object'].includes(typeof params.headerTitle) &&
45
- !WHITE_LIST.includes(this.context?.appId)
46
- ) {
47
+ if (params.headerTitle && isTitleRenderer && !isWhiteListed) {
47
48
  console.warn('headerTitle not allow type func render by design system!');
48
49
  delete params.headerTitle;
49
50
  }
50
51
  return params;
51
52
  };
52
53
 
53
- /**
54
- * navigation setOptions support props NavigationOptions base on react-navigation options
55
- * @param params
56
- */
54
+ /** Applies kit `NavigationOptions` to the screen after `filterParams`. */
57
55
  setOptions = (params: NavigationOptions) => {
58
56
  const options = getOptions(this.filterParams(params));
59
57
  this.instance.setOptions(options as StackNavigationOptions);
@@ -30,10 +30,13 @@ import { HeaderBackground } from './Components/HeaderBackground';
30
30
  import { useScreenLayout } from '../Layout';
31
31
  import { getHeaderRowOptions } from '../Layout/utils';
32
32
  import { ReservedRegionsProvider } from '../Layout/ReservedRegions';
33
- import { AdoptionBadge } from './KitAdoption';
34
33
 
35
34
  const Stack = createStackNavigator();
36
35
 
36
+ /**
37
+ * Root of a mini app: safe area, reserved regions and the merged mini app
38
+ * context around the kit's navigator.
39
+ */
37
40
  const NavigationContainer: React.FC<NavigationContainerProps> = ({
38
41
  screen,
39
42
  theme = defaultTheme,
@@ -87,13 +90,16 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
87
90
  initialParams={initialParams}
88
91
  localize={localize}
89
92
  />
90
- <AdoptionBadge />
91
93
  </MiniAppContext.Provider>
92
94
  </ReservedRegionsProvider>
93
95
  </SafeAreaProvider>
94
96
  );
95
97
  };
96
98
 
99
+ /**
100
+ * Stack navigator with its `Stack`, `Dialog` and `Modal` routes, under an
101
+ * `ApplicationContext` carrying the navigator, themed fonts and `translate`.
102
+ */
97
103
  const Navigation: React.FC<any> = ({
98
104
  screen,
99
105
  theme = defaultTheme,
@@ -111,9 +117,10 @@ const Navigation: React.FC<any> = ({
111
117
  const syncCanGoBack = useNativeCanGoBack();
112
118
  const isWhiteList = isWhiteListDesignSystem(context);
113
119
  const fontFamily = isWhiteList ? 'MomoTrustSans' : 'SFProText';
114
- const navigationFontFamily = isWhiteList
115
- ? 'MomoTrustSans-Regular'
116
- : 'SFProText';
120
+ let navigationFontFamily = 'SFProText';
121
+ if (isWhiteList) {
122
+ navigationFontFamily = 'MomoTrustSans-Regular';
123
+ }
117
124
  let headerBackground = context?.designSystemConfig?.config?.headerBar;
118
125
  let headerGradient = theme.colors?.gradient;
119
126
 
@@ -124,15 +131,9 @@ const Navigation: React.FC<any> = ({
124
131
  headerGradient = context?.designSystemConfig?.config?.headerGradient;
125
132
  }
126
133
 
127
- /**
128
- * inject data for navigator
129
- */
130
134
  navigator.current.maxApi = maxApi;
131
135
 
132
- /**
133
- * translate context method
134
- * @param data
135
- */
136
+ /** Text for a localization key, or the current-language side of `{ vi, en }`. */
136
137
  const translate = (data?: string | { vi: string; en: string }) => {
137
138
  if (data && typeof data !== 'string') {
138
139
  return localize?.translateData(data);
@@ -230,12 +231,12 @@ const Navigation: React.FC<any> = ({
230
231
  backgroundColor: theme.colors.background.default,
231
232
  },
232
233
  headerLeft: (props: any) => <HeaderLeft {...props} floating />,
233
- headerBackground: (props: any) => (
234
- <HeaderBackground {...props} />
235
- ),
236
- headerRight: (props: any) => (
237
- <HeaderRight {...props} floating />
238
- ),
234
+ headerBackground: (props: any) => {
235
+ return <HeaderBackground {...props} />;
236
+ },
237
+ headerRight: (props: any) => {
238
+ return <HeaderRight {...props} floating />;
239
+ },
239
240
  headerTintColor: Colors.black_17,
240
241
  ...TransitionPresets.ModalTransition,
241
242
  }}
@@ -1,6 +1,10 @@
1
1
  import {CommonActions, StackActions} from '@react-navigation/native';
2
2
  import {BottomSheetParams, ModalParams, ScreenParams} from './types';
3
3
 
4
+ /**
5
+ * Imperative navigation API exposed to features through `ApplicationContext`.
6
+ * Every action is a no-op until the container reports ready.
7
+ */
4
8
  class Navigator {
5
9
  ref?: any;
6
10
  isReady?: any;
@@ -14,40 +18,28 @@ class Navigator {
14
18
  this.isWidget = isWidget;
15
19
  }
16
20
 
17
- /**
18
- * push new stack screen
19
- * @param params
20
- */
21
+ /** Pushes a new stack screen. */
21
22
  push = (params: ScreenParams) => {
22
23
  if (this.isReady.current) {
23
24
  this.ref.current?.dispatch?.(StackActions.push('Stack', params));
24
25
  }
25
26
  };
26
27
 
27
- /**
28
- * replace current screen with new screen
29
- * @param params
30
- */
28
+ /** Replaces the current screen with a new stack screen. */
31
29
  replace = (params: ScreenParams) => {
32
30
  if (this.isReady.current) {
33
31
  this.ref.current?.dispatch?.(StackActions.replace('Stack', params));
34
32
  }
35
33
  };
36
34
 
37
- /**
38
- * pop to dismiss a screen
39
- * @param count
40
- */
35
+ /** Pops `count` screens, 1 by default. */
41
36
  pop = (count?: number) => {
42
37
  if (this.isReady.current) {
43
38
  this.ref.current?.dispatch?.(StackActions.pop(count ?? 1));
44
39
  }
45
40
  };
46
41
 
47
- /**
48
- * present a new screen, show from bottom iOS
49
- * @param params
50
- */
42
+ /** Presents a screen as a dialog (slides up from the bottom on iOS). */
51
43
  present = (params: ScreenParams) => {
52
44
  if (this.isReady.current) {
53
45
  this.ref.current?.dispatch?.(StackActions.push('Dialog', params));
@@ -55,9 +47,8 @@ class Navigator {
55
47
  };
56
48
 
57
49
  /**
58
- * show a modal popup
59
- * @param params
60
- * @param onError
50
+ * Shows a modal popup; inside a widget it always uses the native modal.
51
+ * Failures are reported through `onError` instead of throwing.
61
52
  */
62
53
  showModal = (params: ModalParams, onError?: (error: string) => void) => {
63
54
  try {
@@ -76,11 +67,7 @@ class Navigator {
76
67
  }
77
68
  };
78
69
 
79
- /**
80
- * show a bottom sheet
81
- * @param params
82
- * @param onError
83
- */
70
+ /** Shows a bottom sheet through the modal route; failures go to `onError`. */
84
71
  showBottomSheet = (
85
72
  params: BottomSheetParams,
86
73
  onError?: (error: string) => void
@@ -102,31 +89,21 @@ class Navigator {
102
89
  }
103
90
  };
104
91
 
105
- /**
106
- * pop all screen route
107
- */
92
+ /** Pops back to the first screen of the stack. */
108
93
  popToTop = () => {
109
94
  if (this.isReady.current) {
110
95
  this.ref.current?.dispatch?.(StackActions.popToTop());
111
96
  }
112
97
  };
113
98
 
114
- /**
115
- * navigate route name bottom tab only
116
- * @param name
117
- */
99
+ /** Navigates to a route by name; meant for bottom tab routes only. */
118
100
  navigate = (name: string) => {
119
101
  if (this.isReady.current) {
120
- this.ref.current?.dispatch?.(
121
- CommonActions.navigate(name)
122
- );
102
+ this.ref.current?.dispatch?.(CommonActions.navigate(name));
123
103
  }
124
104
  };
125
105
 
126
- /**
127
- * reset a navigation flow with new screen
128
- * @param params
129
- */
106
+ /** Resets the flow to a single new stack screen. */
130
107
  reset = (params: ScreenParams) => {
131
108
  if (this.isReady.current) {
132
109
  this.ref.current?.dispatch?.(
@@ -144,26 +121,21 @@ class Navigator {
144
121
  }
145
122
  };
146
123
 
147
- /**
148
- * dismiss a feature data
149
- * @param data
150
- */
124
+ /** Sets the payload the header passes to `maxApi.dismiss` on close. */
151
125
  setDismissData = (data: any) => {
152
126
  this.dismissData = data;
153
127
  };
154
128
 
155
129
  /**
156
- * set app context using for features of kit
157
- * @param context
130
+ * No-op placeholder; `NavigationContainer` and `WidgetContainer` replace it
131
+ * with their context state setter.
158
132
  */
159
- setCurrentContext = (context: {
133
+ setCurrentContext = (_context: {
160
134
  code?: string;
161
135
  name?: {vi: string; en: string};
162
136
  description?: {vi: string; en: string};
163
137
  icon?: string;
164
- }) => {
165
- console.log(context);
166
- };
138
+ }) => {};
167
139
  }
168
140
 
169
141
  export default Navigator;
@@ -1,16 +1,23 @@
1
- import React, { FC } from 'react';
2
- import { ScaleSizeContext } from '../Context';
1
+ import React, { FC, useContext, useMemo } from 'react';
2
+ import { MiniAppContext } from '../Context';
3
3
  import { ScaleSizeProviderProps } from './types';
4
4
 
5
- /** @deprecated Max font scale is fixed at 1.5; this provider no longer affects scaling. */
5
+ /**
6
+ * Caps the font scale of its subtree at `scaleSizeMaxRate` × the design size
7
+ * (`useScaleSize`), passed down in MiniAppContext. The nearest provider wins;
8
+ * an undefined rate lifts an outer cap.
9
+ */
6
10
  const ScaleSizeProvider: FC<ScaleSizeProviderProps> = ({
7
11
  scaleSizeMaxRate,
8
12
  children,
9
13
  }) => {
14
+ const context = useContext<object | undefined>(MiniAppContext);
15
+ const value = useMemo(() => {
16
+ return { ...context, scaleSizeMaxRate };
17
+ }, [context, scaleSizeMaxRate]);
18
+
10
19
  return (
11
- <ScaleSizeContext.Provider value={{ scaleSizeMaxRate }}>
12
- {children}
13
- </ScaleSizeContext.Provider>
20
+ <MiniAppContext.Provider value={value}>{children}</MiniAppContext.Provider>
14
21
  );
15
22
  };
16
23
 
@@ -1,26 +1,24 @@
1
1
  import { Alert } from 'react-native';
2
2
  import { version } from '../package.json';
3
- import { getAdoptionTrackingParams } from './KitAdoption';
4
- import type { AdoptionMeasureRef } from './KitAdoption/types';
5
3
 
6
4
  type ScreenTrackingDeps = {
7
5
  tracking: { current: any };
8
6
  context: any;
9
7
  navigator: any;
10
8
  screenName: string;
11
- adoptionMeasure?: AdoptionMeasureRef;
12
9
  };
13
10
 
11
+ /**
12
+ * Auto-tracking reporters of a stack screen. Each event fires at most once per
13
+ * screen, guarded by the `release*` flags on `tracking.current`.
14
+ */
14
15
  export const createScreenTracking = ({
15
16
  tracking,
16
17
  context,
17
18
  navigator,
18
19
  screenName,
19
- adoptionMeasure,
20
20
  }: ScreenTrackingDeps) => {
21
- /**
22
- * tracking for screen load
23
- */
21
+ /** Reports the screen load time. */
24
22
  const onScreenLoad = () => {
25
23
  if (!tracking.current?.releaseLoad) {
26
24
  let timeLoad = tracking.current.timeLoad;
@@ -28,8 +26,6 @@ export const createScreenTracking = ({
28
26
  timeLoad = tracking.current.endTime - tracking.current.startTime;
29
27
  }
30
28
 
31
- const adoption = getAdoptionTrackingParams(adoptionMeasure?.current?.());
32
-
33
29
  context?.autoTracking?.({
34
30
  ...context,
35
31
  screenName,
@@ -40,7 +36,6 @@ export const createScreenTracking = ({
40
36
  params: tracking.current.params,
41
37
  version: version,
42
38
  lastElement: tracking.current.lastElement,
43
- adoption,
44
39
  });
45
40
  navigator?.maxApi?.stopTrace?.(
46
41
  tracking.current.traceIdLoad,
@@ -49,29 +44,22 @@ export const createScreenTracking = ({
49
44
  );
50
45
  tracking.current.releaseLoad = true;
51
46
 
52
- /**
53
- * debug
54
- */
55
47
  navigator?.maxApi?.showToastDebug?.({
56
48
  appId: context.appId,
57
49
  message: `${screenName} screen_load_time ${timeLoad}`,
58
50
  type: 'ERROR',
59
51
  });
60
- if (
61
- __DEV__ &&
62
- tracking.current.lastElement?.children?.current?.length > 0
63
- ) {
52
+ const lastChildren = tracking.current.lastElement?.children?.current;
53
+ if (__DEV__ && lastChildren?.length > 0) {
64
54
  Alert.alert(
65
55
  `${screenName}- load ${timeLoad}ms`,
66
- JSON.stringify(tracking.current.lastElement?.children?.current),
56
+ JSON.stringify(lastChildren),
67
57
  );
68
58
  }
69
59
  }
70
60
  };
71
61
 
72
- /**
73
- * tracking for screen load
74
- */
62
+ /** Reports the time until the screen became interactive. */
75
63
  const onScreenInteraction = () => {
76
64
  if (!tracking.current?.releaseInteraction) {
77
65
  let timeLoad = tracking.current.timeLoad;
@@ -99,9 +87,6 @@ export const createScreenTracking = ({
99
87
  );
100
88
  tracking.current.releaseInteraction = true;
101
89
 
102
- /**
103
- * debug toast
104
- */
105
90
  navigator?.maxApi?.showToastDebug?.({
106
91
  appId: context.appId,
107
92
  message: `${screenName} screen_interaction_time ${tracking.current.timeInteraction}`,
@@ -110,9 +95,7 @@ export const createScreenTracking = ({
110
95
  }
111
96
  };
112
97
 
113
- /**
114
- * tracking for first interaction by user
115
- */
98
+ /** Reports the user's first interaction with the screen. */
116
99
  const onFirstInteraction = (action: string) => {
117
100
  if (!tracking.current?.releaseUserInteraction) {
118
101
  const timeLoad = tracking.current.endTime - tracking.current.startTime;
@@ -126,9 +109,6 @@ export const createScreenTracking = ({
126
109
  });
127
110
  tracking.current.releaseUserInteraction = true;
128
111
 
129
- /**
130
- * debug
131
- */
132
112
  navigator?.maxApi?.showToastDebug?.({
133
113
  appId: context.appId,
134
114
  message: `${screenName} user_interaction ${timeLoad}`,
@@ -137,9 +117,7 @@ export const createScreenTracking = ({
137
117
  }
138
118
  };
139
119
 
140
- /**
141
- * tracking for loading screen
142
- */
120
+ /** Reports how long the skeleton loading state lasted. */
143
121
  const onScreenLoading = () => {
144
122
  const start = tracking.current.timeStartLoading;
145
123
  const end = tracking.current.timeEndLoading;