react-native-chatbot-ai 0.1.51 → 0.1.53

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 (32) hide show
  1. package/lib/module/components/Drawer/DrawerContent.js +6 -4
  2. package/lib/module/components/Drawer/DrawerContent.js.map +1 -1
  3. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js +39 -13
  4. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js.map +1 -1
  5. package/lib/module/components/chat/item/ChatTable.js +45 -7
  6. package/lib/module/components/chat/item/ChatTable.js.map +1 -1
  7. package/lib/module/components/product/Card.js +426 -0
  8. package/lib/module/components/product/Card.js.map +1 -0
  9. package/lib/module/components/product/CardHorizontal.js +2 -40
  10. package/lib/module/components/product/CardHorizontal.js.map +1 -1
  11. package/lib/module/translation/resources/i18n.js +4 -1
  12. package/lib/module/translation/resources/i18n.js.map +1 -1
  13. package/lib/module/utils/common.js +10 -0
  14. package/lib/module/utils/common.js.map +1 -1
  15. package/lib/typescript/src/components/Drawer/DrawerContent.d.ts.map +1 -1
  16. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts.map +1 -1
  17. package/lib/typescript/src/components/chat/item/ChatTable.d.ts.map +1 -1
  18. package/lib/typescript/src/components/product/Card.d.ts +9 -0
  19. package/lib/typescript/src/components/product/Card.d.ts.map +1 -0
  20. package/lib/typescript/src/components/product/CardHorizontal.d.ts.map +1 -1
  21. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  22. package/lib/typescript/src/utils/common.d.ts +3 -0
  23. package/lib/typescript/src/utils/common.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/Drawer/DrawerContent.tsx +6 -4
  26. package/src/components/chat/item/ChatAIAnswerMessageItem.tsx +50 -18
  27. package/src/components/chat/item/ChatTable.tsx +51 -5
  28. package/src/components/product/Card.tsx +484 -0
  29. package/src/components/product/CardHorizontal.tsx +2 -39
  30. package/src/ignore.d.ts +1 -1
  31. package/src/translation/resources/i18n.ts +4 -0
  32. package/src/utils/common.ts +17 -0
@@ -1 +1 @@
1
- {"version":3,"file":"DrawerContent.d.ts","sourceRoot":"","sources":["../../../../../src/components/Drawer/DrawerContent.tsx"],"names":[],"mappings":"AAcA,QAAA,MAAM,aAAa,+CAqFlB,CAAC;AAUF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"DrawerContent.d.ts","sourceRoot":"","sources":["../../../../../src/components/Drawer/DrawerContent.tsx"],"names":[],"mappings":"AAcA,QAAA,MAAM,aAAa,+CAuFlB,CAAC;AAUF,eAAe,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChatAIAnswerMessageItem.d.ts","sourceRoot":"","sources":["../../../../../../src/components/chat/item/ChatAIAnswerMessageItem.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAqB9C,UAAU,4BAA4B;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmPD,QAAA,MAAM,uBAAuB,GAAI,mBAG9B,4BAA4B,4CAyG9B,CAAC;AACF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ChatAIAnswerMessageItem.d.ts","sourceRoot":"","sources":["../../../../../../src/components/chat/item/ChatAIAnswerMessageItem.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA2B9C,UAAU,4BAA4B;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA4QD,QAAA,MAAM,uBAAuB,GAAI,mBAG9B,4BAA4B,4CA0G9B,CAAC;AACF,eAAe,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChatTable.d.ts","sourceRoot":"","sources":["../../../../../../src/components/chat/item/ChatTable.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,UAAU;IAClB,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAMD,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAiEnC,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ChatTable.d.ts","sourceRoot":"","sources":["../../../../../../src/components/chat/item/ChatTable.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,UAAU,UAAU;IAClB,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AASD,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA6GnC,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ interface IProductCardProps {
2
+ productId?: string;
3
+ messageId?: string;
4
+ index?: number;
5
+ showSensitiveInfo?: boolean;
6
+ }
7
+ declare const ProductCardWrapper: import("react").MemoExoticComponent<(props: IProductCardProps) => import("react/jsx-runtime").JSX.Element | null>;
8
+ export default ProductCardWrapper;
9
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../../../src/components/product/Card.tsx"],"names":[],"mappings":"AAwBA,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,QAAA,MAAM,kBAAkB,8CAAgB,iBAAiB,oDASvD,CAAC;AAkXH,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"CardHorizontal.d.ts","sourceRoot":"","sources":["../../../../../src/components/product/CardHorizontal.tsx"],"names":[],"mappings":"AAsBA,UAAU,2BAA2B;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,QAAA,MAAM,4BAA4B,8CACxB,2BAA2B,oDAUpC,CAAC;AA8UF,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"CardHorizontal.d.ts","sourceRoot":"","sources":["../../../../../src/components/product/CardHorizontal.tsx"],"names":[],"mappings":"AAsBA,UAAU,2BAA2B;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,QAAA,MAAM,4BAA4B,8CACxB,2BAA2B,oDAUpC,CAAC;AAySF,eAAe,4BAA4B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AAwDA,wBAEE"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AA4DA,wBAEE"}
@@ -6,5 +6,8 @@ interface ShortenOptions {
6
6
  keepEnd?: number;
7
7
  }
8
8
  export declare const shortenFileName: (name: string, options?: ShortenOptions) => string;
9
+ export declare const COMPONENT_REGEX: RegExp;
10
+ export declare const COMPONENT_GLOBAL_REGEX: RegExp;
11
+ export declare const parseProductParams: (raw?: string) => Record<string, string>;
9
12
  export {};
10
13
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,GAAG,GAAG,EAAE,GAAG,GAAG,YAC4B,CAAC;AAEtE,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAU9C,CAAC;AAEF,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,UAAS,cAAmB,WAkBzE,CAAC"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,GAAG,GAAG,EAAE,GAAG,GAAG,YAC4B,CAAC;AAEtE,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAU9C,CAAC;AAEF,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,UAAS,cAAmB,WAkBzE,CAAC;AAEF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,sBAAsB,QACU,CAAC;AAE9C,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAWtE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-chatbot-ai",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "description": "React Native library for Chatbot AI",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -34,10 +34,12 @@ const DrawerContent = () => {
34
34
 
35
35
  const onSearchCallback = useCallback(
36
36
  (isSuccess?: boolean) => {
37
- logGA(GAEvents.sidebarSearchConversationSend, {
38
- content: debouncedSearchTerm,
39
- search_result: isSuccess ? 'yes' : null,
40
- });
37
+ if (debouncedSearchTerm?.trim?.().length > 0) {
38
+ logGA(GAEvents.sidebarSearchConversationSend, {
39
+ content: debouncedSearchTerm,
40
+ search_result: isSuccess ? 'yes' : null,
41
+ });
42
+ }
41
43
  },
42
44
  [logGA, debouncedSearchTerm]
43
45
  );
@@ -19,6 +19,7 @@ import {
19
19
  } from 'react-native-marked';
20
20
  import { useSearchProduct } from '../../../hooks/product/useSearchProduct';
21
21
  import ProductHorizontalCard from '../../product/CardHorizontal';
22
+ import ProductCard from '../../product/Card';
22
23
  import ChatTable from './ChatTable';
23
24
  import DeeplinkItem from './DeeplinkItem';
24
25
  import { useChatContext } from '../../../context/ChatContext';
@@ -26,6 +27,11 @@ import { trans } from '../../../translation';
26
27
  import MessageActionsBar from './MessageActionsBar';
27
28
  import useProductsStore from '../../../store/products';
28
29
  import ShimmerBlock from './ShimmerBlock';
30
+ import {
31
+ COMPONENT_GLOBAL_REGEX,
32
+ COMPONENT_REGEX,
33
+ parseProductParams,
34
+ } from '../../../utils/common';
29
35
 
30
36
  interface ChatAIAnswerMessageItemProps {
31
37
  item: IMessageItem;
@@ -51,22 +57,47 @@ class CustomRenderer extends Renderer implements RendererInterface {
51
57
  productIds?: string[];
52
58
 
53
59
  html(text: string): ReactNode {
54
- const match = /^<!--\s*@component:(\w+)\(id:([\w-]+)\)\s*-->/.exec(text);
55
- switch (match?.[1]) {
60
+ const normalized = text?.trim?.();
61
+ const match = COMPONENT_REGEX.exec(normalized);
62
+ console.log('match:', match);
63
+ if (!match) {
64
+ return (
65
+ <KLabel.Text typo="TextMdNormal" key={this.getKey()}>
66
+ {text}
67
+ </KLabel.Text>
68
+ );
69
+ }
70
+ const component = match?.[1];
71
+ const params = parseProductParams(match?.[2]);
72
+ switch (component) {
56
73
  case 'product':
57
- const productIndex = this.productIds?.indexOf(match?.[2] || '');
58
- return (
59
- <ProductHorizontalCard
60
- productId={match?.[2]}
61
- key={this.getKey()}
62
- messageId={this.messageId}
63
- index={productIndex}
64
- />
65
- );
74
+ const productId = params?.id;
75
+ const type = params?.type ?? 'horizontal';
76
+ const productIndex = this.productIds?.indexOf(productId || '');
77
+ console.log('product params:', params, 'type:', type);
78
+ if (type === 'vertical') {
79
+ return (
80
+ <ProductCard
81
+ productId={productId}
82
+ key={this.getKey()}
83
+ messageId={this.messageId}
84
+ index={productIndex}
85
+ />
86
+ );
87
+ } else {
88
+ return (
89
+ <ProductHorizontalCard
90
+ productId={productId}
91
+ key={this.getKey()}
92
+ messageId={this.messageId}
93
+ index={productIndex}
94
+ />
95
+ );
96
+ }
66
97
  default:
67
98
  return (
68
99
  <KLabel.Text typo="TextMdNormal" key={this.getKey()}>
69
- {match?.[2] || ''}
100
+ {text}
70
101
  </KLabel.Text>
71
102
  );
72
103
  }
@@ -293,14 +324,15 @@ const ChatAIAnswerMessageItem = ({
293
324
  }
294
325
 
295
326
  if (typeof content !== 'string') return [];
296
-
297
- const regex =
298
- /<!--\s*@component:product\([^)]*id:\s*['"]?([\w-]+)['"]?[^)]*\)\s*-->/g;
299
327
  const ids: string[] = [];
300
328
  let match;
301
- while ((match = regex.exec(content)) !== null) {
302
- if (match[1]) {
303
- ids.push(match[1]);
329
+ while ((match = COMPONENT_GLOBAL_REGEX.exec(content)) !== null) {
330
+ const componentName = match?.[1];
331
+ if (componentName !== 'product') continue;
332
+ const params = parseProductParams(match?.[2]);
333
+ const productId = params?.id;
334
+ if (productId) {
335
+ ids.push(productId);
304
336
  }
305
337
  }
306
338
  return ids;
@@ -1,11 +1,10 @@
1
1
  import {
2
2
  KColors,
3
3
  KContainer,
4
- KDims,
5
4
  KRadiusValue,
6
5
  KSpacingValue,
7
6
  } from '@droppii/libs';
8
- import React from 'react';
7
+ import React, { useEffect, useState } from 'react';
9
8
  import { ScrollView, StyleSheet } from 'react-native';
10
9
 
11
10
  interface TableProps {
@@ -20,6 +19,9 @@ const toArray = (
20
19
  node: React.ReactNode | React.ReactNode[]
21
20
  ): React.ReactNode[] => (Array.isArray(node) ? node : [node]);
22
21
 
22
+ const HEADER_CELL_MAX_WIDTH = 165;
23
+ const COLUMN_CELL_MAX_WIDTH = 220;
24
+
23
25
  const ChatTable: React.FC<TableProps> = ({
24
26
  header,
25
27
  rows,
@@ -27,6 +29,42 @@ const ChatTable: React.FC<TableProps> = ({
27
29
  rowStyle,
28
30
  cellStyle,
29
31
  }) => {
32
+ const columnWidthRef = React.useRef<Record<number, number>>({});
33
+ const [columnWidths, setColumnWidths] = useState<Record<number, number>>({});
34
+
35
+ const layoutCountRef = React.useRef(0);
36
+ const expectedLayoutCountRef = React.useRef(0);
37
+
38
+ const onCellLayout = (colIndex: number, width: number) => {
39
+ const prev = columnWidthRef.current[colIndex] ?? 0;
40
+
41
+ if (width > prev) {
42
+ columnWidthRef.current[colIndex] = width;
43
+ }
44
+
45
+ layoutCountRef.current += 1;
46
+
47
+ if (
48
+ layoutCountRef.current >= expectedLayoutCountRef.current &&
49
+ expectedLayoutCountRef.current > 0
50
+ ) {
51
+ setColumnWidths({ ...columnWidthRef.current });
52
+ }
53
+ };
54
+
55
+ useEffect(() => {
56
+ const headerCount = header?.length ?? 0;
57
+ const rowCount =
58
+ rows?.reduce((sum, row) => sum + (row?.length ?? 0), 0) ?? 0;
59
+
60
+ expectedLayoutCountRef.current = headerCount + rowCount;
61
+
62
+ // reset trước mỗi lần render mới
63
+ layoutCountRef.current = 0;
64
+ columnWidthRef.current = {};
65
+ setColumnWidths({});
66
+ }, [header, rows]);
67
+
30
68
  return (
31
69
  <ScrollView
32
70
  horizontal
@@ -44,7 +82,11 @@ const ChatTable: React.FC<TableProps> = ({
44
82
  styles.headerCell,
45
83
  j < header.length - 1 && styles.borderRight,
46
84
  j === 0 && styles.firstCell,
85
+ columnWidths?.[j] && { width: columnWidths[j] },
47
86
  ]}
87
+ onLayout={(e: any) => {
88
+ onCellLayout(j, e?.nativeEvent?.layout?.width);
89
+ }}
48
90
  >
49
91
  {toArray(cell).map((child, k) => (
50
92
  <React.Fragment key={`header-cell-${j}-${k}`}>
@@ -71,7 +113,11 @@ const ChatTable: React.FC<TableProps> = ({
71
113
  styles.cell,
72
114
  j < (row?.length || 0) - 1 && styles.borderRight,
73
115
  j === 0 && styles.firstCell,
116
+ columnWidths?.[j] && { width: columnWidths[j] },
74
117
  ]}
118
+ onLayout={(e: any) => {
119
+ onCellLayout(j, e?.nativeEvent?.layout?.width);
120
+ }}
75
121
  >
76
122
  {toArray(cell).map((child, k) => (
77
123
  <React.Fragment key={`cell-${i}-${j}-${k}`}>
@@ -110,20 +156,20 @@ const styles = StyleSheet.create({
110
156
  padding: 8,
111
157
  borderBottomWidth: 1,
112
158
  borderColor: KColors.hexToRgba(KColors.gray.dark, 0.2),
113
- width: KDims.width * 0.8,
159
+ maxWidth: COLUMN_CELL_MAX_WIDTH,
114
160
  },
115
161
  cell: {
116
162
  padding: 8,
117
163
  borderBottomWidth: 1,
118
164
  borderColor: KColors.hexToRgba(KColors.gray.dark, 0.2),
119
- width: KDims.width * 0.8,
165
+ maxWidth: COLUMN_CELL_MAX_WIDTH,
120
166
  },
121
167
  borderRight: {
122
168
  borderRightWidth: 1,
123
169
  borderColor: KColors.hexToRgba(KColors.gray.dark, 0.2),
124
170
  },
125
171
  firstCell: {
126
- width: 160,
172
+ maxWidth: HEADER_CELL_MAX_WIDTH,
127
173
  },
128
174
  headerText: {
129
175
  fontWeight: 'bold',