@momo-kits/foundation 0.168.1-beta.28 → 0.168.1-beta.29

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.
@@ -8,12 +8,18 @@ import { Image } from '../Image';
8
8
  import { Text, useScaleSize } from '../Text';
9
9
  import { PopupNotifyProps } from './types';
10
10
  import { scheduleOnRN } from 'react-native-worklets';
11
- import { getPopupRadius, usePopupMaxHeight, usePopupWidth } from './utils';
11
+ import {
12
+ getPopupRadius,
13
+ splitHighlightText,
14
+ usePopupMaxHeight,
15
+ usePopupWidth,
16
+ } from './utils';
12
17
 
13
18
  const PopupNotify: React.FC<PopupNotifyProps> = ({
14
19
  image,
15
20
  title = 'Title',
16
21
  description = 'Description',
22
+ highlightText,
17
23
  error,
18
24
  secondary,
19
25
  primary,
@@ -135,6 +141,25 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
135
141
  return renderColumn();
136
142
  };
137
143
 
144
+ /**
145
+ * build description text, highlighted keywords keep size/lineHeight and use weight 600
146
+ */
147
+ const renderDescription = (text: string) => {
148
+ const segments = splitHighlightText(text, highlightText);
149
+ if (!segments) {
150
+ return text;
151
+ }
152
+ return segments.map((segment, index) =>
153
+ segment.highlight ? (
154
+ <Text key={index} typography={'header_s_semibold'}>
155
+ {segment.text}
156
+ </Text>
157
+ ) : (
158
+ segment.text
159
+ ),
160
+ );
161
+ };
162
+
138
163
  /**
139
164
  * build close action
140
165
  */
@@ -200,7 +225,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
200
225
  }
201
226
  }}
202
227
  >
203
- {description}
228
+ {renderDescription(description)}
204
229
  </Text>
205
230
  ) : (
206
231
  description
package/Popup/types.ts CHANGED
@@ -20,6 +20,13 @@ export type PopupNotifyProps = {
20
20
  */
21
21
  description?: string | React.ReactNode;
22
22
 
23
+ /**
24
+ * `highlightText`: Optional. List of words/phrases within `description` to be rendered in semibold.
25
+ * Only applies when `description` is a string. Matching is whole-word and case-sensitive;
26
+ * every occurrence of each string is highlighted.
27
+ */
28
+ highlightText?: string[];
29
+
23
30
  /**
24
31
  * `error`: Optional. Represents additional error text to be displayed in the PopupNotify component.
25
32
  */
package/Popup/utils.ts CHANGED
@@ -3,6 +3,8 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
3
3
  import { Radius, Spacing } from '../Consts';
4
4
  import { getDuoModalBounds, isIPhoneDuo } from '../Application/device';
5
5
 
6
+ type HighlightSegment = { text: string; highlight: boolean };
7
+
6
8
  const usePopupWidth = () => {
7
9
  const insets = useSafeAreaInsets();
8
10
  const { width, height } = useWindowDimensions();
@@ -23,4 +25,47 @@ const usePopupMaxHeight = () => {
23
25
 
24
26
  const getPopupRadius = () => (isIPhoneDuo() ? Radius.XL : Radius.L);
25
27
 
26
- export { usePopupWidth, usePopupMaxHeight, getPopupRadius };
28
+ const isWordChar = (char?: string) =>
29
+ !!char && (char.toLowerCase() !== char.toUpperCase() || /[0-9_]/.test(char));
30
+
31
+ /**
32
+ * Split `text` into plain/highlighted segments (same matching as Information `highlightText`):
33
+ * whole-word, case-sensitive, every occurrence, longest keyword first.
34
+ * Returns `undefined` when there is nothing to highlight.
35
+ */
36
+ const splitHighlightText = (
37
+ text: string,
38
+ highlightText?: string[],
39
+ ): HighlightSegment[] | undefined => {
40
+ const keywords = highlightText?.filter(
41
+ keyword => typeof keyword === 'string' && keyword,
42
+ );
43
+ if (!keywords?.length) {
44
+ return undefined;
45
+ }
46
+ const pattern = [...keywords]
47
+ .sort((a, b) => b.length - a.length)
48
+ .map(keyword => keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
49
+ .join('|');
50
+ const regex = new RegExp(pattern, 'g');
51
+ const segments: HighlightSegment[] = [];
52
+ let lastIndex = 0;
53
+ let match;
54
+ while ((match = regex.exec(text))) {
55
+ const start = match.index;
56
+ const end = start + match[0].length;
57
+ if (isWordChar(text[start - 1]) || isWordChar(text[end])) {
58
+ regex.lastIndex = start + 1;
59
+ continue;
60
+ }
61
+ if (start > lastIndex) {
62
+ segments.push({ text: text.slice(lastIndex, start), highlight: false });
63
+ }
64
+ segments.push({ text: match[0], highlight: true });
65
+ lastIndex = end;
66
+ }
67
+ segments.push({ text: text.slice(lastIndex), highlight: false });
68
+ return segments;
69
+ };
70
+
71
+ export { usePopupWidth, usePopupMaxHeight, getPopupRadius, splitHighlightText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.168.1-beta.28",
3
+ "version": "0.168.1-beta.29",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},
@@ -8,21 +8,21 @@
8
8
  "@momo-kits/foundation"
9
9
  ],
10
10
  "dependencies": {
11
- "react-native-fast-image": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-fast-image.git#v8.11.0",
12
11
  "@react-navigation/bottom-tabs": "7.4.2",
13
12
  "@react-navigation/core": "7.12.1",
14
13
  "@react-navigation/elements": "2.5.2",
15
14
  "@react-navigation/native": "7.1.14",
16
15
  "@react-navigation/routers": "7.4.1",
17
16
  "@react-navigation/stack": "7.4.2",
17
+ "@shopify/flash-list": "2.1.0",
18
+ "lottie-react-native": "7.2.4",
19
+ "react-native-fast-image": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-fast-image.git#v8.11.0",
18
20
  "react-native-gesture-handler": "2.27.1",
19
21
  "react-native-linear-gradient": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-linear-gradient#v3.0.0",
20
22
  "react-native-reanimated": "4.2.2",
21
- "react-native-worklets": "0.6.1",
22
- "react-native-safe-area-context": "5.5.2",
23
23
  "react-native-reserved-regions": "0.2.0",
24
- "@shopify/flash-list": "2.1.0",
25
- "lottie-react-native": "7.2.4"
24
+ "react-native-safe-area-context": "5.5.2",
25
+ "react-native-worklets": "0.6.1"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "react-native": "*",
@@ -35,4 +35,4 @@
35
35
  "registry": "https://registry.npmjs.org/"
36
36
  },
37
37
  "license": "MoMo"
38
- }
38
+ }