@momo-kits/foundation 0.167.1-beta.10 → 0.167.1-beta.11

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.
@@ -16,16 +16,7 @@ import {
16
16
  import { Image } from '../../Image';
17
17
  import { Icon } from '../../Icon';
18
18
  import { Skeleton } from '../../Skeleton';
19
- import {
20
- AnimatedCompatValue,
21
- isWhiteListDesignSystem,
22
- useNormalizedSharedValue,
23
- } from '../utils';
24
-
25
- const useHeaderFontFamily = (): string => {
26
- const context = useContext<any>(MiniAppContext);
27
- return isWhiteListDesignSystem(context) ? 'MoMoTrustDisplay' : 'SFProText';
28
- };
19
+ import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
29
20
 
30
21
  type HeaderTitleInterpolate = {
31
22
  inputRange: number[];
@@ -46,7 +37,6 @@ const HeaderTitle: React.FC<
46
37
  HeaderTitleExtraProps & { [key: string]: any }
47
38
  > = props => {
48
39
  const context = useContext<any>(MiniAppContext);
49
- const headerFontFamily = useHeaderFontFamily();
50
40
 
51
41
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
52
42
 
@@ -95,7 +85,7 @@ const HeaderTitle: React.FC<
95
85
  fontFamily: exportFontFamily(
96
86
  'bold',
97
87
  'action_xs_bold',
98
- headerFontFamily,
88
+ 'MoMoTrustDisplay',
99
89
  ),
100
90
  color: props.tintColor,
101
91
  },
@@ -140,7 +130,6 @@ const TitleUser: React.FC<TitleUserProps> = ({
140
130
  isLoading,
141
131
  }) => {
142
132
  const { theme } = useContext(ApplicationContext);
143
- const headerFontFamily = useHeaderFontFamily();
144
133
  const maxWidth = Dimensions.get('window').width - 172;
145
134
  const getShortName = (name: string) => {
146
135
  const words = name.split(' ');
@@ -389,7 +378,7 @@ const TitleUser: React.FC<TitleUserProps> = ({
389
378
  <View style={Styles.row}>
390
379
  <Text
391
380
  typography="action_xs_bold"
392
- fontFamily={headerFontFamily}
381
+ fontFamily='MoMoTrustDisplay'
393
382
  color={tintColor}
394
383
  numberOfLines={1}
395
384
  >
@@ -423,7 +412,6 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
423
412
  onPress,
424
413
  isLoading,
425
414
  }) => {
426
- const headerFontFamily = useHeaderFontFamily();
427
415
  const maxWidth = Dimensions.get('window').width - 172;
428
416
  const renderShimmer = () => {
429
417
  return (
@@ -460,12 +448,9 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
460
448
  </Text>
461
449
  )}
462
450
  <View style={Styles.row}>
463
- <Text
464
- typography="action_xs_bold"
465
- fontFamily={headerFontFamily}
466
- color={tintColor}
467
- numberOfLines={1}
468
- >
451
+ <Text typography="action_xs_bold"
452
+ fontFamily='MoMoTrustDisplay'
453
+ color={tintColor} numberOfLines={1}>
469
454
  {location}
470
455
  </Text>
471
456
  <Icon
@@ -492,7 +477,6 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
492
477
  onPress,
493
478
  isLoading,
494
479
  }) => {
495
- const headerFontFamily = useHeaderFontFamily();
496
480
  const { width } = Dimensions.get('screen');
497
481
  const maxWidth = Dimensions.get('window').width - 172;
498
482
  const startWidth = width * 0.25;
@@ -528,7 +512,8 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
528
512
  style={{ maxWidth: startWidth }}
529
513
  color={tintColor}
530
514
  numberOfLines={1}
531
- fontFamily={headerFontFamily}
515
+ fontFamily='MoMoTrustDisplay'
516
+
532
517
  >
533
518
  {start}
534
519
  </Text>
@@ -544,7 +529,8 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
544
529
  typography="action_xs_bold"
545
530
  color={tintColor}
546
531
  numberOfLines={1}
547
- fontFamily={headerFontFamily}
532
+ fontFamily='MoMoTrustDisplay'
533
+
548
534
  >
549
535
  {end}
550
536
  </Text>
@@ -17,14 +17,10 @@ import { DeviceEventEmitter } from 'react-native';
17
17
  import StackScreen from './StackScreen';
18
18
  import ModalScreen from './ModalScreen';
19
19
  import Navigator from './Navigator';
20
- import {
21
- getModalOptions,
22
- getStackOptions,
23
- isWhiteListDesignSystem,
24
- useNativeCanGoBack,
25
- } from './utils';
20
+ import { getModalOptions, getStackOptions, useNativeCanGoBack } from './utils';
26
21
  import { NavigationContainerProps } from './types';
27
22
  import { ApplicationContext, MiniAppContext } from '../Context';
23
+ import { useDefaultRegularFontFamily } from '../Consts/designSystemFont';
28
24
  import Localize from './Localize';
29
25
  import { Colors, defaultTheme } from '../Consts';
30
26
  import { HeaderLeft } from './Components/HeaderLeft';
@@ -107,10 +103,8 @@ const Navigation: React.FC<any> = ({
107
103
  const navigator = useRef(new Navigator(navigationRef, isReady));
108
104
  const [showGrid, setShowGrid] = useState(false);
109
105
  const insets = useSafeAreaInsets();
106
+ const defaultRegularFontFamily = useDefaultRegularFontFamily();
110
107
  const syncCanGoBack = useNativeCanGoBack();
111
- const isWhiteList = isWhiteListDesignSystem(context);
112
- const fontFamily = isWhiteList ? 'MomoTrustSans' : 'SFProText';
113
- const navigationFontFamily = isWhiteList ? 'MomoTrustSans-Regular' : 'SFProText';
114
108
  let headerBackground = context?.designSystemConfig?.config?.headerBar;
115
109
  let headerGradient = theme.colors?.gradient;
116
110
 
@@ -162,7 +156,6 @@ const Navigation: React.FC<any> = ({
162
156
  navigator: navigator.current,
163
157
  theme: {
164
158
  ...theme,
165
- font: fontFamily,
166
159
  colors: {
167
160
  ...theme.colors,
168
161
  gradient: headerGradient,
@@ -190,19 +183,19 @@ const Navigation: React.FC<any> = ({
190
183
  },
191
184
  fonts: {
192
185
  regular: {
193
- fontFamily: navigationFontFamily,
186
+ fontFamily: defaultRegularFontFamily,
194
187
  fontWeight: '400',
195
188
  },
196
189
  medium: {
197
- fontFamily: navigationFontFamily,
190
+ fontFamily: defaultRegularFontFamily,
198
191
  fontWeight: '400',
199
192
  },
200
193
  bold: {
201
- fontFamily: navigationFontFamily,
194
+ fontFamily: defaultRegularFontFamily,
202
195
  fontWeight: '400',
203
196
  },
204
197
  heavy: {
205
- fontFamily: navigationFontFamily,
198
+ fontFamily: defaultRegularFontFamily,
206
199
  fontWeight: '400',
207
200
  },
208
201
  },
@@ -3,6 +3,7 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
3
3
  import Navigator from './Navigator';
4
4
  import { WidgetContainerProps } from './types';
5
5
  import { ApplicationContext, MiniAppContext } from '../Context';
6
+ import { useDefaultRegularFontFamily } from '../Consts/designSystemFont';
6
7
  import Localize from './Localize';
7
8
  import { defaultTheme } from '../Consts';
8
9
  import {
@@ -10,7 +11,7 @@ import {
10
11
  NavigationContainerRef,
11
12
  NavigationIndependentTree,
12
13
  } from '@react-navigation/native';
13
- import { getModalOptions, isWhiteListDesignSystem } from './utils';
14
+ import { getModalOptions } from './utils';
14
15
  import { createStackNavigator } from '@react-navigation/stack';
15
16
  import ModalScreen from './ModalScreen';
16
17
  import { View } from 'react-native';
@@ -42,6 +43,7 @@ const WidgetContainer: React.FC<WidgetContainerProps> = ({
42
43
  const isReady = useRef(false);
43
44
  const navigator = useRef(new Navigator(navigationRef, isReady, true));
44
45
  const [currentContext, setCurrentContext] = useState({});
46
+ const defaultRegularFontFamily = useDefaultRegularFontFamily();
45
47
 
46
48
  useEffect(() => {
47
49
  const sub = maxApi?.observer?.('font_scale_config', (data: any) => {
@@ -78,9 +80,6 @@ const WidgetContainer: React.FC<WidgetContainerProps> = ({
78
80
  ...context,
79
81
  ...currentContext,
80
82
  };
81
- const isWhiteList = isWhiteListDesignSystem(mergedContext);
82
- const fontFamily = isWhiteList ? 'MomoTrustSans' : 'SFProText';
83
- const navigationFontFamily = isWhiteList ? 'MomoTrustSans-Regular' : 'SFProText';
84
83
 
85
84
  return (
86
85
  <View style={{ height: height ?? '100%', minHeight: 1 }}>
@@ -91,7 +90,6 @@ const WidgetContainer: React.FC<WidgetContainerProps> = ({
91
90
  navigator: navigator.current,
92
91
  theme: {
93
92
  ...theme,
94
- font: fontFamily,
95
93
  colors: {
96
94
  ...theme.colors,
97
95
  gradient: headerGradient,
@@ -118,19 +116,19 @@ const WidgetContainer: React.FC<WidgetContainerProps> = ({
118
116
  },
119
117
  fonts: {
120
118
  regular: {
121
- fontFamily: navigationFontFamily,
119
+ fontFamily: defaultRegularFontFamily,
122
120
  fontWeight: '400',
123
121
  },
124
122
  medium: {
125
- fontFamily: navigationFontFamily,
123
+ fontFamily: defaultRegularFontFamily,
126
124
  fontWeight: '400',
127
125
  },
128
126
  bold: {
129
- fontFamily: navigationFontFamily,
127
+ fontFamily: defaultRegularFontFamily,
130
128
  fontWeight: '400',
131
129
  },
132
130
  heavy: {
133
- fontFamily: navigationFontFamily,
131
+ fontFamily: defaultRegularFontFamily,
134
132
  fontWeight: '400',
135
133
  },
136
134
  },
@@ -475,9 +475,6 @@ const SwipeBackHaptic = () => {
475
475
  return null;
476
476
  };
477
477
 
478
- const isWhiteListDesignSystem = (context: any): boolean =>
479
- context?.designSystemConfig?.isWhiteListDesignSystem === true;
480
-
481
478
  export {
482
479
  getStackOptions,
483
480
  getModalOptions,
@@ -490,5 +487,4 @@ export {
490
487
  useNativeCanGoBack,
491
488
  useNormalizedSharedValue,
492
489
  SwipeBackHaptic,
493
- isWhiteListDesignSystem,
494
490
  };
@@ -0,0 +1,38 @@
1
+ import { useContext } from 'react';
2
+ import { MiniAppContext } from '../Context';
3
+
4
+ export const NEW_DEFAULT_FONT_FAMILY = 'MomoTrustSans';
5
+ export const LEGACY_DEFAULT_FONT_FAMILY = 'SFProText';
6
+
7
+ /**
8
+ * Font thuoc bo design system moi. Ngoai whitelist thi ha het ve font cu:
9
+ * MoMoTrustDisplay chi duoc dung tu commit header title 5bfde6251 (DS-791),
10
+ * truoc do header lay font theo theme.
11
+ */
12
+ const NEW_FONT_FAMILIES = [NEW_DEFAULT_FONT_FAMILY, 'MoMoTrustDisplay'];
13
+
14
+ /**
15
+ * Cờ whitelist design system, host đẩy xuống qua `decorateProps`
16
+ * (`designSystemConfig.isWhiteListDesignSystem`). Ngoài whitelist thì kit giữ
17
+ * nguyên font cũ.
18
+ */
19
+ export const useIsDesignSystemWhiteList = (): boolean => {
20
+ const context = useContext<any>(MiniAppContext);
21
+ return context?.designSystemConfig?.isWhiteListDesignSystem === true;
22
+ };
23
+
24
+ /**
25
+ * Hạ font mặc định mới về font cũ khi user không nằm trong whitelist.
26
+ * Font do caller chỉ định tường minh (MoMoSignature, AlegreyaSans...) giữ nguyên.
27
+ */
28
+ export const useResolvedFontFamily = (font: string): string => {
29
+ const isWhiteList = useIsDesignSystemWhiteList();
30
+ if (NEW_FONT_FAMILIES.includes(font) && !isWhiteList) {
31
+ return LEGACY_DEFAULT_FONT_FAMILY;
32
+ }
33
+ return font;
34
+ };
35
+
36
+ /** Tên file font Regular tương ứng với nhánh whitelist đang áp dụng. */
37
+ export const useDefaultRegularFontFamily = (): string =>
38
+ `${useResolvedFontFamily(NEW_DEFAULT_FONT_FAMILY)}-Regular`;
package/Consts/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from './colors+spacing+radius';
2
2
  export * from './theme';
3
3
  export * from './styles';
4
4
  export const GRIDVIEW = false;
5
+ export * from './designSystemFont';
package/Consts/theme.ts CHANGED
@@ -51,7 +51,7 @@ const defaultTheme: Theme = {
51
51
  container: Colors.blue_08,
52
52
  },
53
53
  },
54
- font: 'SFProText',
54
+ font: 'MomoTrustSans',
55
55
  assets: {},
56
56
  };
57
57
 
@@ -105,7 +105,7 @@ const defaultDarkTheme: Theme = {
105
105
  container: Colors.blue_08,
106
106
  },
107
107
  },
108
- font: 'SFProText',
108
+ font: 'MomoTrustSans',
109
109
  assets: {},
110
110
  };
111
111
 
@@ -10,7 +10,6 @@ import React, {
10
10
  } from 'react';
11
11
  import {
12
12
  NativeSyntheticEvent,
13
- Platform,
14
13
  TextInput,
15
14
  TextInputFocusEventData,
16
15
  TextInputSelectionChangeEventData,
@@ -57,13 +56,10 @@ const caretFromDigitIndex = (display: string, digitIndex: number) => {
57
56
  return 0;
58
57
  };
59
58
 
60
- // Finds which range of `old` was replaced to produce `next`. `selection` is
61
- // the pre-edit selection on iOS and already the post-edit caret on Android,
62
- // where onSelectionChange fires before onChangeText.
63
59
  const detectEdit = (old: string, next: string, selection: Selection): Edit => {
64
60
  const { start, end } = selection;
65
61
  const removed = old.length - next.length;
66
- const preEdit: Edit[] = [
62
+ const candidates: Edit[] = [
67
63
  {
68
64
  start,
69
65
  end,
@@ -72,26 +68,6 @@ const detectEdit = (old: string, next: string, selection: Selection): Edit => {
72
68
  { start: start - removed, end: start, inserted: '' },
73
69
  { start, end: start + removed, inserted: '' },
74
70
  ];
75
- const postEdit: Edit[] = [];
76
- const tail = next.length - start;
77
- if (start === end && tail <= old.length) {
78
- let prefix = 0;
79
- while (
80
- prefix < Math.min(start, old.length - tail) &&
81
- old[prefix] === next[prefix]
82
- ) {
83
- prefix += 1;
84
- }
85
- postEdit.push({
86
- start: prefix,
87
- end: old.length - tail,
88
- inserted: next.slice(prefix, start),
89
- });
90
- }
91
- const candidates =
92
- Platform.OS === 'android'
93
- ? [...postEdit, ...preEdit]
94
- : [...preEdit, ...postEdit];
95
71
  const match = candidates.find(
96
72
  e =>
97
73
  e.start >= 0 &&
@@ -196,9 +172,8 @@ const InputMoney = forwardRef(
196
172
  const selectionRef = useRef<Selection>({ start: 0, end: 0 });
197
173
  // Caret to push to native once the committed text is rendered.
198
174
  const pendingCaretRef = useRef<number | null>(null);
199
- // Caret the native input reports for the raw, unformatted text. On iOS that
200
- // event lands after onChangeText and must not override the formatted caret.
201
- const rawCaretRef = useRef<number | null>(null);
175
+ const pendingSelectionRef = useRef<Selection | null>(null);
176
+ const editingRef = useRef(false);
202
177
  const inputRef = useRef<TextInput>(null);
203
178
  const componentName = 'InputMoney';
204
179
 
@@ -265,10 +240,13 @@ const InputMoney = forwardRef(
265
240
  const _onChangeText = (text: string) => {
266
241
  let digits = '';
267
242
  let caretDigit = 0;
268
- rawCaretRef.current = 0;
243
+ pendingSelectionRef.current = null;
244
+ editingRef.current = true;
245
+ setTimeout(() => {
246
+ editingRef.current = false;
247
+ });
269
248
  if (text) {
270
249
  const edit = detectEdit(displayRef.current, text, selectionRef.current);
271
- rawCaretRef.current = edit.start + edit.inserted.length;
272
250
  ({ digits, caretDigit } = applyEdit(
273
251
  displayRef.current,
274
252
  edit,
@@ -285,19 +263,24 @@ const InputMoney = forwardRef(
285
263
  e: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
286
264
  ) => {
287
265
  props.onSelectionChange?.(e);
288
- const { start, end } = e.nativeEvent.selection;
289
- const rawCaret = rawCaretRef.current;
290
- rawCaretRef.current = null;
291
- if (start === end && start === rawCaret) {
292
- return;
293
- }
294
- const display = displayRef.current;
295
- const max = display ? display.length - currency.length : 0;
296
- const clamped = { start: Math.min(start, max), end: Math.min(end, max) };
297
- selectionRef.current = clamped;
298
- if (clamped.start !== start || clamped.end !== end) {
299
- inputRef.current?.setSelection(clamped.start, clamped.end);
300
- }
266
+ if (editingRef.current) return;
267
+ const selection = e.nativeEvent.selection;
268
+ pendingSelectionRef.current = selection;
269
+ setTimeout(() => {
270
+ if (pendingSelectionRef.current !== selection) return;
271
+ pendingSelectionRef.current = null;
272
+ const { start, end } = selection;
273
+ const display = displayRef.current;
274
+ const max = display ? display.length - currency.length : 0;
275
+ const clamped = {
276
+ start: Math.min(start, max),
277
+ end: Math.min(end, max),
278
+ };
279
+ selectionRef.current = clamped;
280
+ if (clamped.start !== start || clamped.end !== end) {
281
+ inputRef.current?.setSelection(clamped.start, clamped.end);
282
+ }
283
+ });
301
284
  };
302
285
 
303
286
  const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
package/Text/index.tsx CHANGED
@@ -7,6 +7,10 @@ import {
7
7
  MiniAppContext,
8
8
  SkeletonContext,
9
9
  } from '../Context';
10
+ import {
11
+ NEW_DEFAULT_FONT_FAMILY,
12
+ useResolvedFontFamily,
13
+ } from '../Consts/designSystemFont';
10
14
  import { scaleSize, useScaleSize } from './utils';
11
15
  import { Skeleton } from '../Skeleton';
12
16
 
@@ -114,7 +118,8 @@ const TypoStyles = (typo: Typography, newFontFamily?: string) => {
114
118
  const typoStyle = styleSheet[typo] ?? styleSheet.paragraph_default;
115
119
  const { fontWeight, fontSize, fontStyle, lineHeight } = typoStyle;
116
120
  const style = FontStyle[fontStyle ?? 'normal'];
117
- const font = newFontFamily ?? theme.font;
121
+ const font = useResolvedFontFamily(newFontFamily ?? theme.font);
122
+ const resolvedDefaultFamily = useResolvedFontFamily(NEW_DEFAULT_FONT_FAMILY);
118
123
  let fontFamily: string;
119
124
 
120
125
  switch (font) {
@@ -143,7 +148,11 @@ const TypoStyles = (typo: Typography, newFontFamily?: string) => {
143
148
  break;
144
149
  }
145
150
  default: {
146
- fontFamily = `${font}-${SFProText[fontWeight]}${style}`;
151
+ fontFamily = `${resolvedDefaultFamily}-${
152
+ resolvedDefaultFamily === NEW_DEFAULT_FONT_FAMILY
153
+ ? MomoTrustSans[fontWeight]
154
+ : SFProText[fontWeight]
155
+ }`;
147
156
  }
148
157
  }
149
158
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.167.1-beta.10",
3
+ "version": "0.167.1-beta.11",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},