@droppii-org/chat-sdk 0.4.8 → 0.4.10

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 (63) hide show
  1. package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
  2. package/dist/components/conversation/DeskConversationList.js +8 -2
  3. package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
  4. package/dist/components/conversation-detail/ConversationDetailInput.js +10 -5
  5. package/dist/components/conversation-inbox/contact-search/ContactSearchPanel.d.ts.map +1 -1
  6. package/dist/components/conversation-inbox/contact-search/ContactSearchPanel.js +36 -0
  7. package/dist/components/conversation-inbox/contact-search/ContactSearchResultItem.d.ts.map +1 -1
  8. package/dist/components/conversation-inbox/contact-search/ContactSearchResultItem.js +4 -2
  9. package/dist/components/conversation-inbox/contact-search/PublicGroupAvatar.d.ts +9 -0
  10. package/dist/components/conversation-inbox/contact-search/PublicGroupAvatar.d.ts.map +1 -0
  11. package/dist/components/conversation-inbox/contact-search/PublicGroupAvatar.js +19 -0
  12. package/dist/components/conversation-inbox/contact-search/PublicGroupResultItem.d.ts +8 -0
  13. package/dist/components/conversation-inbox/contact-search/PublicGroupResultItem.d.ts.map +1 -0
  14. package/dist/components/conversation-inbox/contact-search/PublicGroupResultItem.js +29 -0
  15. package/dist/components/conversation-inbox/contact-search/constants.d.ts +4 -1
  16. package/dist/components/conversation-inbox/contact-search/constants.d.ts.map +1 -1
  17. package/dist/components/conversation-inbox/contact-search/constants.js +5 -0
  18. package/dist/components/conversation-inbox/contact-search/index.d.ts +2 -0
  19. package/dist/components/conversation-inbox/contact-search/index.d.ts.map +1 -1
  20. package/dist/components/conversation-inbox/contact-search/index.js +2 -0
  21. package/dist/components/message/MessageList.d.ts.map +1 -1
  22. package/dist/components/message/MessageList.js +3 -1
  23. package/dist/components/message/footer/index.d.ts.map +1 -1
  24. package/dist/components/message/footer/index.js +2 -2
  25. package/dist/components/message/footer/mention/MentionMenu.d.ts +1 -0
  26. package/dist/components/message/footer/mention/MentionMenu.d.ts.map +1 -1
  27. package/dist/components/message/footer/mention/MentionMenu.js +66 -6
  28. package/dist/components/message/footer/mention/MentionNode.d.ts +1 -1
  29. package/dist/components/message/footer/mention/MentionNode.d.ts.map +1 -1
  30. package/dist/components/message/footer/mention/MentionNode.js +2 -2
  31. package/dist/components/message/footer/mention/useMentionOptions.d.ts.map +1 -1
  32. package/dist/components/message/footer/mention/useMentionOptions.js +6 -3
  33. package/dist/components/search-conversation/index.d.ts.map +1 -1
  34. package/dist/components/search-conversation/index.js +20 -2
  35. package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -1
  36. package/dist/components/search-conversation/item/SearchItemAsGroup.js +2 -1
  37. package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
  38. package/dist/components/search-conversation/item/SearchItemAsMessage.js +4 -1
  39. package/dist/hooks/conversation/useResolveConversation.d.ts.map +1 -1
  40. package/dist/hooks/conversation/useResolveConversation.js +2 -1
  41. package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
  42. package/dist/hooks/global/useGlobalEvent.js +10 -1
  43. package/dist/hooks/group/useJoinPublicGroup.d.ts +6 -0
  44. package/dist/hooks/group/useJoinPublicGroup.d.ts.map +1 -0
  45. package/dist/hooks/group/useJoinPublicGroup.js +20 -0
  46. package/dist/hooks/search/useSearchMessage.d.ts.map +1 -1
  47. package/dist/hooks/search/useSearchMessage.js +11 -1
  48. package/dist/hooks/search/useSearchPublicGroups.d.ts +16 -0
  49. package/dist/hooks/search/useSearchPublicGroups.d.ts.map +1 -0
  50. package/dist/hooks/search/useSearchPublicGroups.js +55 -0
  51. package/dist/locales/vi/common.json +1 -1
  52. package/dist/locales/vi/conversation-inbox.json +7 -2
  53. package/dist/services/query.d.ts +1 -0
  54. package/dist/services/query.d.ts.map +1 -1
  55. package/dist/services/query.js +1 -0
  56. package/dist/store/conversation.d.ts.map +1 -1
  57. package/dist/store/conversation.js +22 -9
  58. package/dist/store/type.d.ts +6 -2
  59. package/dist/store/type.d.ts.map +1 -1
  60. package/dist/styles/global.css +1 -1
  61. package/dist/types/dto.d.ts +1 -0
  62. package/dist/types/dto.d.ts.map +1 -1
  63. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AA4BA,QAAA,MAAM,oBAAoB,+CAqUzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AA4BA,QAAA,MAAM,oBAAoB,+CA2UzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -90,8 +90,12 @@ const DeskConversationList = () => {
90
90
  }
91
91
  setSelectedConversationId(threadId);
92
92
  const selectedConversation = conversationList.find((conv) => conv.conversationID === threadId);
93
+ // threadId can come from a notification/stale search click — force a
94
+ // fresh membership check instead of trusting the groupID cache.
93
95
  if (selectedConversation) {
94
- setConversationData(selectedConversation);
96
+ setConversationData(selectedConversation, undefined, {
97
+ forceRevalidate: true,
98
+ });
95
99
  }
96
100
  else {
97
101
  DChatSDK.getMultipleConversation([threadId]).then((res) => {
@@ -99,7 +103,9 @@ const DeskConversationList = () => {
99
103
  // (e.g. the user was removed from that group mid-flight) — only
100
104
  // apply the result if the URL still points at this conversation.
101
105
  if (res.data.length > 0 && searchParams.get("threadId") === threadId) {
102
- setConversationData(res.data[0]);
106
+ setConversationData(res.data[0], undefined, {
107
+ forceRevalidate: true,
108
+ });
103
109
  updateConversationList(res.data, "filter");
104
110
  }
105
111
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAkB/D,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,QAAA,MAAM,uBAAuB,GAAI,4EAM9B,4BAA4B,4CA+mB9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAkB/D,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,QAAA,MAAM,uBAAuB,GAAI,4EAM9B,4BAA4B,4CAynB9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -19,7 +19,7 @@ import { ReplyPreviewBar } from "../../components/message/reply/ReplyPreviewBar"
19
19
  import ConversationMoreOptionPanel from "./ConversationMoreOptionPanel";
20
20
  import { useMentionTrigger } from "./mention/useMentionTrigger";
21
21
  import { useMentionOptions } from "../../components/message/footer/mention/useMentionOptions";
22
- import { countMentionedUsers, useMentionTokens } from "./mention/useMentionTokens";
22
+ import { useMentionTokens } from "./mention/useMentionTokens";
23
23
  import BizMentionMenu from "./mention/BizMentionMenu";
24
24
  import { getCaretCoordinates, disposeCaretCoordinates, } from "./mention/getCaretCoordinates";
25
25
  import { buildMentionPayload } from "./mention/buildMentionPayload";
@@ -69,11 +69,16 @@ const ConversationDetailInput = ({ placeholder, onSendMessage, onInputChange, mo
69
69
  const { tokens: mentionTokens, addToken, onValueChange, resetTokens } = useMentionTokens();
70
70
  // "Tất cả" doesn't count against the per-user cap and stays selectable;
71
71
  // only specific-member options are hidden once the limit is hit.
72
- const mentionedUsersCount = useMemo(() => countMentionedUsers(mentionTokens), [mentionTokens]);
72
+ const mentionedUserIDs = useMemo(() => new Set(mentionTokens.filter((token) => !token.isAtAll).map((token) => token.userID)), [mentionTokens]);
73
+ const mentionedUsersCount = mentionedUserIDs.size;
73
74
  const mentionLimitReached = mentionedUsersCount >= MAX_MENTIONED_USERS;
74
- const mentionOptions = mentionLimitReached
75
- ? rawMentionOptions.filter((option) => option.isAtAll)
76
- : rawMentionOptions;
75
+ // Already-tagged users don't need to appear again in the same draft.
76
+ const mentionOptions = useMemo(() => {
77
+ const notYetMentioned = rawMentionOptions.filter((option) => option.isAtAll || !mentionedUserIDs.has(option.userID));
78
+ return mentionLimitReached
79
+ ? notYetMentioned.filter((option) => option.isAtAll)
80
+ : notYetMentioned;
81
+ }, [rawMentionOptions, mentionedUserIDs, mentionLimitReached]);
77
82
  const [mentionMenuPosition, setMentionMenuPosition] = useState(null);
78
83
  const previewUrl = useMemo(() => {
79
84
  const urls = extractLinkUrls(value);
@@ -1 +1 @@
1
- {"version":3,"file":"ContactSearchPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/ContactSearchPanel.tsx"],"names":[],"mappings":"AA2BA,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,kBAAkB,GAAI,mBAAmB,uBAAuB,4CAoOrE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ContactSearchPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/ContactSearchPanel.tsx"],"names":[],"mappings":"AA8BA,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,kBAAkB,GAAI,mBAAmB,uBAAuB,4CAuTrE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -8,15 +8,18 @@ import { useTranslation } from "react-i18next";
8
8
  import { Icon } from "../../../components/icon";
9
9
  import { useChatContext } from "../../../context/ChatContext";
10
10
  import { useSearchContacts } from "../../../hooks/search/useSearchContacts";
11
+ import { useSearchPublicGroups } from "../../../hooks/search/useSearchPublicGroups";
11
12
  import ContactSearchFilters from "./ContactSearchFilters";
12
13
  import ContactSearchResultItem from "./ContactSearchResultItem";
13
14
  import ContactSearchSectionHeader from "./ContactSearchSectionHeader";
14
15
  import ContactSearchStateMessage from "./ContactSearchStateMessage";
15
16
  import ContactSearchTabs from "./ContactSearchTabs";
16
17
  import ContactSearchViewMoreBar from "./ContactSearchViewMoreBar";
18
+ import PublicGroupResultItem from "./PublicGroupResultItem";
17
19
  import { CONTACT_SEARCH_DEBOUNCE_MS, CONTACT_SEARCH_ICON_SIZE, CONTACT_SEARCH_PREVIEW_LIMIT, ContactSearchTab, } from "./constants";
18
20
  import { buildContactSearchParams } from "./utils";
19
21
  const SCROLL_TARGET_ID = "contact-search-scroll";
22
+ const COMMUNITY_SCROLL_TARGET_ID = "contact-search-community-scroll";
20
23
  const ContactSearchPanel = ({ open, onClose }) => {
21
24
  const { t } = useTranslation("conversation-inbox");
22
25
  const { onNavigate } = useChatContext();
@@ -41,6 +44,19 @@ const ContactSearchPanel = ({ open, onClose }) => {
41
44
  type: activeType,
42
45
  enabled: open,
43
46
  });
47
+ const publicGroups = useSearchPublicGroups({
48
+ searchTerm: trimmedKeyword,
49
+ enabled: open && activeTab === ContactSearchTab.Community,
50
+ });
51
+ const handleOpenGroup = (groupID) => {
52
+ const params = new URLSearchParams(window.location.search);
53
+ params.delete("threadId");
54
+ params.delete("userId");
55
+ params.delete("botId");
56
+ params.set("groupId", groupID);
57
+ onClose();
58
+ onNavigate === null || onNavigate === void 0 ? void 0 : onNavigate(`${window.location.pathname}?${params.toString()}`);
59
+ };
44
60
  const handleSelectContact = (contact) => {
45
61
  const params = buildContactSearchParams(contact);
46
62
  onClose();
@@ -82,6 +98,21 @@ const ContactSearchPanel = ({ open, onClose }) => {
82
98
  return (_jsxs("div", { className: "flex-1 overflow-y-auto", children: [_jsx(ContactSearchSectionHeader, { title: t("contact_search.tabs.contacts"), count: totalElements || undefined, onSelect: openContactsTab }), renderContactItems(contacts.slice(0, CONTACT_SEARCH_PREVIEW_LIMIT)), hasMore && _jsx(ContactSearchViewMoreBar, { onSelect: openContactsTab })] }));
83
99
  };
84
100
  const renderContactList = () => (_jsx("div", { id: SCROLL_TARGET_ID, className: "flex-1 overflow-y-auto", children: _jsx(InfiniteScroll, { dataLength: contacts.length, next: fetchNextPage, hasMore: !!hasNextPage, scrollableTarget: SCROLL_TARGET_ID, loader: isFetchingNextPage ? (_jsx("div", { className: "flex items-center justify-center py-3", children: _jsx(Spin, { size: "small" }) })) : null, children: renderContactItems(contacts) }) }));
101
+ const renderCommunityTab = () => {
102
+ if (!trimmedKeyword) {
103
+ return (_jsx(ContactSearchStateMessage, { testId: "contact-search-community-initial", children: t("contact_search.initial") }));
104
+ }
105
+ if (publicGroups.isLoading) {
106
+ return (_jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Spin, {}) }));
107
+ }
108
+ if (publicGroups.isError) {
109
+ return (_jsx(ContactSearchStateMessage, { testId: "contact-search-community-failed", children: t("contact_search.failed") }));
110
+ }
111
+ if (publicGroups.groups.length === 0) {
112
+ return (_jsxs(ContactSearchStateMessage, { testId: "contact-search-community-no-result", children: [t("contact_search.no_result_title"), _jsx("br", {}), t("contact_search.no_result_hint")] }));
113
+ }
114
+ return (_jsx("div", { id: COMMUNITY_SCROLL_TARGET_ID, className: "flex-1 overflow-y-auto", children: _jsx(InfiniteScroll, { dataLength: publicGroups.groups.length, next: publicGroups.fetchNextPage, hasMore: !!publicGroups.hasNextPage, scrollableTarget: COMMUNITY_SCROLL_TARGET_ID, loader: publicGroups.isFetchingNextPage ? (_jsx("div", { className: "flex items-center justify-center py-3", children: _jsx(Spin, { size: "small" }) })) : null, children: publicGroups.groups.map((group) => (_jsx(PublicGroupResultItem, { group: group, onOpen: handleOpenGroup }, group.groupID))) }) }));
115
+ };
85
116
  // Filters stay mounted even with no results so the seller can switch type.
86
117
  const renderContactsTab = () => {
87
118
  var _a;
@@ -103,6 +134,11 @@ const ContactSearchPanel = ({ open, onClose }) => {
103
134
  label: t("contact_search.tabs.messages"),
104
135
  children: (_jsx(ContactSearchStateMessage, { testId: "contact-search-messages", children: t("contact_search.messages_not_available") })),
105
136
  },
137
+ {
138
+ key: ContactSearchTab.Community,
139
+ label: t("contact_search.tabs.community"),
140
+ children: renderCommunityTab(),
141
+ },
106
142
  ];
107
143
  return (_jsx(Drawer, { open: open, onClose: onClose, placement: "right", closeIcon: false, width: "100%", "data-cp-name": "ContactSearchPanel", styles: { body: { padding: 0 } }, getContainer: false, destroyOnHidden: true, children: _jsxs("div", { className: "flex h-full flex-col bg-white", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [_jsx("button", { type: "button", "data-testid": "contact-search-back", "aria-label": t("contact_search.back"), className: "flex shrink-0 cursor-pointer items-center justify-center p-1 text-primary-400", onClick: onClose, children: _jsx(Icon, { icon: "arrow-left-o", size: 24 }) }), _jsx(Input, { allowClear: true, autoFocus: true, value: keyword, "data-testid": "contact-search-input", placeholder: t("search_placeholder"), prefix: _jsx("span", { className: "flex h-10 w-10 items-center justify-center", children: _jsx(Icon, { icon: "search-o", size: CONTACT_SEARCH_ICON_SIZE }) }),
108
144
  // Padding lives on the prefix/input instead of the wrapper so the
@@ -1 +1 @@
1
- {"version":3,"file":"ContactSearchResultItem.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/ContactSearchResultItem.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAqB,MAAM,aAAa,CAAC;AAGnE,UAAU,4BAA4B;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAChD;AAED,QAAA,MAAM,uBAAuB,GAAI,oCAI9B,4BAA4B,4CAiE9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ContactSearchResultItem.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/ContactSearchResultItem.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAqB,MAAM,aAAa,CAAC;AAGnE,UAAU,4BAA4B;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAChD;AAED,QAAA,MAAM,uBAAuB,GAAI,oCAI9B,4BAA4B,4CAqE9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -14,11 +14,13 @@ const ContactSearchResultItem = ({ contact, searchTerm, onSelect, }) => {
14
14
  // Supporting line differs per contact type (spec §Contact Result Content).
15
15
  // PDP intentionally has none — its last online time was dropped from spec.
16
16
  const buildSupportingText = () => {
17
- var _a;
17
+ var _a, _b;
18
18
  if (isGroup) {
19
- return t("contact_search.member_count", {
19
+ const memberCount = t("contact_search.member_count", {
20
20
  count: (_a = contact.memberCount) !== null && _a !== void 0 ? _a : 0,
21
21
  });
22
+ const description = ((_b = contact.description) === null || _b === void 0 ? void 0 : _b.trim()) || t("contact_search.group_no_description");
23
+ return `${memberCount} • ${description}`;
22
24
  }
23
25
  if (contact.type === ContactSearchType.PdpBot)
24
26
  return "";
@@ -0,0 +1,9 @@
1
+ import type { SearchPublicGroupMemberInfo } from "@droppii-org/wasm-client-sdk";
2
+ interface PublicGroupAvatarProps {
3
+ faceURL?: string;
4
+ groupName?: string;
5
+ members?: SearchPublicGroupMemberInfo[];
6
+ }
7
+ declare const PublicGroupAvatar: ({ faceURL, groupName, members, }: PublicGroupAvatarProps) => import("react/jsx-runtime").JSX.Element;
8
+ export default PublicGroupAvatar;
9
+ //# sourceMappingURL=PublicGroupAvatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublicGroupAvatar.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/PublicGroupAvatar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAMhF,UAAU,sBAAsB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,2BAA2B,EAAE,CAAC;CACzC;AAKD,QAAA,MAAM,iBAAiB,GAAI,kCAIxB,sBAAsB,4CAwCxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Avatar } from "antd";
4
+ import { CONTACT_SEARCH_AVATAR_SIZE, PUBLIC_GROUP_STACKED_AVATAR_SIZE, } from "./constants";
5
+ // Public-group results carry their own member list, so the composite is built
6
+ // from that instead of GroupCompositeAvatar — which fetches members and would
7
+ // fail for a group the seller has not joined yet.
8
+ const PublicGroupAvatar = ({ faceURL, groupName, members = [], }) => {
9
+ var _a, _b;
10
+ if (faceURL) {
11
+ return (_jsx(Avatar, { size: CONTACT_SEARCH_AVATAR_SIZE, src: faceURL, alt: groupName, className: "shrink-0 uppercase", children: (groupName === null || groupName === void 0 ? void 0 : groupName.charAt(0)) || "G" }));
12
+ }
13
+ const [first, second] = members;
14
+ return (_jsxs("div", { className: "relative shrink-0", style: {
15
+ height: CONTACT_SEARCH_AVATAR_SIZE,
16
+ width: CONTACT_SEARCH_AVATAR_SIZE,
17
+ }, children: [_jsx(Avatar, { size: PUBLIC_GROUP_STACKED_AVATAR_SIZE, src: (second === null || second === void 0 ? void 0 : second.faceURL) || undefined, className: "absolute right-0 top-0 border border-white bg-gray-400 uppercase", children: ((_a = second === null || second === void 0 ? void 0 : second.nickname) === null || _a === void 0 ? void 0 : _a.charAt(0)) || (groupName === null || groupName === void 0 ? void 0 : groupName.charAt(0)) || "G" }), _jsx(Avatar, { size: PUBLIC_GROUP_STACKED_AVATAR_SIZE, src: (first === null || first === void 0 ? void 0 : first.faceURL) || undefined, className: "absolute bottom-0 left-0 border border-white bg-gray-400 uppercase", children: ((_b = first === null || first === void 0 ? void 0 : first.nickname) === null || _b === void 0 ? void 0 : _b.charAt(0)) || (groupName === null || groupName === void 0 ? void 0 : groupName.charAt(0)) || "G" })] }));
18
+ };
19
+ export default PublicGroupAvatar;
@@ -0,0 +1,8 @@
1
+ import type { SearchPublicGroupInfo } from "@droppii-org/wasm-client-sdk";
2
+ interface PublicGroupResultItemProps {
3
+ group: SearchPublicGroupInfo;
4
+ onOpen: (groupID: string) => void;
5
+ }
6
+ declare const PublicGroupResultItem: ({ group, onOpen, }: PublicGroupResultItemProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default PublicGroupResultItem;
8
+ //# sourceMappingURL=PublicGroupResultItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublicGroupResultItem.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/PublicGroupResultItem.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAI1E,UAAU,0BAA0B;IAClC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,QAAA,MAAM,qBAAqB,GAAI,oBAG5B,0BAA0B,4CA2E5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import clsx from "clsx";
4
+ import { Spin } from "antd";
5
+ import { useTranslation } from "react-i18next";
6
+ import { useJoinPublicGroup } from "../../../hooks/group/useJoinPublicGroup";
7
+ import PublicGroupAvatar from "./PublicGroupAvatar";
8
+ const PublicGroupResultItem = ({ group, onOpen, }) => {
9
+ var _a, _b;
10
+ const { t } = useTranslation("conversation-inbox");
11
+ const { mutate: joinGroup, isPending } = useJoinPublicGroup();
12
+ // Joined groups open straight away; the rest join first, then open.
13
+ const handleAction = () => {
14
+ if (group.isJoined) {
15
+ onOpen(group.groupID);
16
+ return;
17
+ }
18
+ joinGroup({ groupID: group.groupID }, { onSuccess: () => onOpen(group.groupID) });
19
+ };
20
+ return (_jsxs("div", { "data-cp-name": "PublicGroupResultItem", "data-testid": `contact-search-public-group-${group.groupID}`, className: "flex items-center gap-2 border-b border-gray-25 bg-white p-3", children: [_jsxs("button", { type: "button", className: "flex min-w-0 flex-1 items-center gap-2 text-left", onClick: () => onOpen(group.groupID), children: [_jsx(PublicGroupAvatar, { faceURL: group.faceURL, groupName: group.groupName, members: group.members }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1 pb-0.5", children: [_jsx("span", { className: "truncate text-[16px] font-medium leading-[1.6] text-black", children: group.groupName }), _jsxs("span", { className: "flex min-w-0 flex-col text-[14px] leading-[1.6] tracking-[0.14px] text-gray-600", children: [_jsx("span", { className: "truncate", children: t("contact_search.member_count", {
21
+ count: (_a = group.memberCount) !== null && _a !== void 0 ? _a : 0,
22
+ }) }), _jsx("span", { className: "truncate", children: ((_b = group.introduction) === null || _b === void 0 ? void 0 : _b.trim()) ||
23
+ t("contact_search.public_group_fallback") })] })] })] }), _jsxs("button", { type: "button", disabled: isPending, "data-testid": `contact-search-public-group-action-${group.groupID}`, className: clsx("flex h-7 shrink-0 items-center justify-center gap-2 rounded-lg px-3", "whitespace-nowrap text-center text-[12px] font-medium leading-[1.6] tracking-[0.12px]", group.isJoined
24
+ ? "bg-gray-25 text-gray-900"
25
+ : "bg-primary-25 text-primary-400", isPending && "opacity-60"), onClick: handleAction, children: [isPending && _jsx(Spin, { size: "small" }), t(group.isJoined
26
+ ? "contact_search.group_access"
27
+ : "contact_search.group_join")] })] }));
28
+ };
29
+ export default PublicGroupResultItem;
@@ -1,11 +1,14 @@
1
1
  import { ContactSearchType } from "../../../types/dto";
2
2
  export declare const CONTACT_SEARCH_DEBOUNCE_MS = 300;
3
3
  export declare const CONTACT_SEARCH_ICON_SIZE = 18;
4
+ export declare const CONTACT_SEARCH_AVATAR_SIZE = 48;
5
+ export declare const PUBLIC_GROUP_STACKED_AVATAR_SIZE = 33;
4
6
  export declare const CONTACT_SEARCH_PREVIEW_LIMIT = 5;
5
7
  export declare enum ContactSearchTab {
6
8
  All = "ALL",
7
9
  Contacts = "CONTACTS",
8
- Messages = "MESSAGES"
10
+ Messages = "MESSAGES",
11
+ Community = "COMMUNITY"
9
12
  }
10
13
  export declare const CONTACT_SEARCH_TABS: {
11
14
  tab: ContactSearchTab;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAI3C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,QAAQ,aAAa;IACrB,QAAQ,aAAa;CACtB;AAED,eAAO,MAAM,mBAAmB,EAAE;IAChC,GAAG,EAAE,gBAAgB,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,EAIA,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,EAKA,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAG7C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAInD,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,oBAAY,gBAAgB;IAC1B,GAAG,QAAQ;IACX,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,SAAS,cAAc;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAE;IAChC,GAAG,EAAE,gBAAgB,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,EAKA,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE;IACnC,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,EAKA,CAAC"}
@@ -1,6 +1,9 @@
1
1
  import { ContactSearchType } from "../../../types/dto";
2
2
  export const CONTACT_SEARCH_DEBOUNCE_MS = 300;
3
3
  export const CONTACT_SEARCH_ICON_SIZE = 18;
4
+ export const CONTACT_SEARCH_AVATAR_SIZE = 48;
5
+ // The two overlapping circles of the public-group composite avatar.
6
+ export const PUBLIC_GROUP_STACKED_AVATAR_SIZE = 33;
4
7
  // `Tất cả` shows a capped preview of the contact section before handing the
5
8
  // seller over to the full `Liên hệ` tab.
6
9
  export const CONTACT_SEARCH_PREVIEW_LIMIT = 5;
@@ -9,11 +12,13 @@ export var ContactSearchTab;
9
12
  ContactSearchTab["All"] = "ALL";
10
13
  ContactSearchTab["Contacts"] = "CONTACTS";
11
14
  ContactSearchTab["Messages"] = "MESSAGES";
15
+ ContactSearchTab["Community"] = "COMMUNITY";
12
16
  })(ContactSearchTab || (ContactSearchTab = {}));
13
17
  export const CONTACT_SEARCH_TABS = [
14
18
  { tab: ContactSearchTab.All, labelKey: "contact_search.tabs.all" },
15
19
  { tab: ContactSearchTab.Contacts, labelKey: "contact_search.tabs.contacts" },
16
20
  { tab: ContactSearchTab.Messages, labelKey: "contact_search.tabs.messages" },
21
+ { tab: ContactSearchTab.Community, labelKey: "contact_search.tabs.community" },
17
22
  ];
18
23
  export const CONTACT_SEARCH_FILTERS = [
19
24
  { type: ContactSearchType.Customer, labelKey: "contact_search.filters.customer" },
@@ -5,6 +5,8 @@ export { default as ContactSearchStateMessage } from "./ContactSearchStateMessag
5
5
  export { default as ContactSearchTabs } from "./ContactSearchTabs";
6
6
  export { default as ContactSearchSectionHeader } from "./ContactSearchSectionHeader";
7
7
  export { default as ContactSearchViewMoreBar } from "./ContactSearchViewMoreBar";
8
+ export { default as PublicGroupResultItem } from "./PublicGroupResultItem";
9
+ export { default as PublicGroupAvatar } from "./PublicGroupAvatar";
8
10
  export * from "./constants";
9
11
  export * from "./utils";
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-inbox/contact-search/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
@@ -5,5 +5,7 @@ export { default as ContactSearchStateMessage } from "./ContactSearchStateMessag
5
5
  export { default as ContactSearchTabs } from "./ContactSearchTabs";
6
6
  export { default as ContactSearchSectionHeader } from "./ContactSearchSectionHeader";
7
7
  export { default as ContactSearchViewMoreBar } from "./ContactSearchViewMoreBar";
8
+ export { default as PublicGroupResultItem } from "./PublicGroupResultItem";
9
+ export { default as PublicGroupAvatar } from "./PublicGroupAvatar";
8
10
  export * from "./constants";
9
11
  export * from "./utils";
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAgCA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAuT3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAgCA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAwT3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -160,6 +160,8 @@ const MessageList = (props) => {
160
160
  if (!conversationData) {
161
161
  return (_jsx("div", { className: "flex flex-1 items-center justify-center h-full", children: connectStatus !== ConnectStatus.Connected ? (_jsx(Spin, {})) : (_jsx(Empty, { description: t("no_conversation_data") })) }));
162
162
  }
163
- return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, "data-cp-name": "MessageList", children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, isGroupChat: isGroupChat, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), (isGroupChat && isCheckingMembership) || !isGroupStateFresh ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : isViewOnlyMember ? (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : !canSendMessage ? (_jsx("div", { className: "border-t bg-[#f5f5f5] py-3 flex items-center justify-center", children: _jsx("p", { className: "text-sm text-gray-500", children: t(isRestrictedByGroupMute ? "send_message_disabled_group_mute" : "send_message_disabled") }) })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(ConfirmModal, { open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, children: _jsx("p", { children: t("revoke_message_confirm_message") }) }), _jsx(PinLimitModal, { open: pinLimitModalOpen, max: pinnedTotalCount, onClose: () => setPinLimitModalOpen(false) })] }));
163
+ return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, "data-cp-name": "MessageList", children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, isGroupChat: isGroupChat, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), (isGroupChat && isCheckingMembership) || !isGroupStateFresh ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : isViewOnlyMember ? (
164
+ // Brief fallback while isJoined catches up after the kick event.
165
+ _jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })) : !canSendMessage ? (_jsx("div", { className: "border-t bg-[#f5f5f5] py-3 flex items-center justify-center", children: _jsx("p", { className: "text-sm text-gray-500", children: t(isRestrictedByGroupMute ? "send_message_disabled_group_mute" : "send_message_disabled") }) })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(ConfirmModal, { open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, children: _jsx("p", { children: t("revoke_message_confirm_message") }) }), _jsx(PinLimitModal, { open: pinLimitModalOpen, max: pinnedTotalCount, onClose: () => setPinLimitModalOpen(false) })] }));
164
166
  };
165
167
  export default MessageList;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CAuUpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CA0UpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -27,7 +27,7 @@ import useConversationStore from "../../../store/conversation";
27
27
  import { useCurrentUserAccountType } from "../../../hooks/user/useCurrentUserAccountType";
28
28
  import ComposerTabs from "./ComposerTabs";
29
29
  import ComposerEditor from "./ComposerEditor";
30
- import MentionMenu from "./mention/MentionMenu";
30
+ import MentionMenu, { COMPOSER_AREA_CP_NAME } from "./mention/MentionMenu";
31
31
  import SessionClosedModal from "./SessionClosedModal";
32
32
  import { useCreateSession, useReopenSession, } from "../../../hooks/session/useReopenOrCreateSession";
33
33
  import { emit } from "../../../utils/events";
@@ -234,6 +234,6 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
234
234
  setIsMentionMenuOpen,
235
235
  }, children: [_jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Popover, { open: isOpenCanned, content: _jsx(CannedResponse, { onClose: closeCanned, openCreateCannedModal: onOpenCreateCannedModal, cannedQuery: cannedQuery }), placement: "topLeft", trigger: "click", arrow: false, classNames: {
236
236
  body: "mx-1 !p-0",
237
- }, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setIsLinkPreviewDismissed(true) })), _jsx(ToolbarPlugin, {}), _jsxs("div", { children: [_jsx(ComposerTabs, { canUseInternal: canUseInternal, hintText: t("canned_response_hint"), isInternal: isInternal, lockToInternal: lockToInternal, setIsInternal: setIsInternal }), _jsx(ComposerEditor, { isInternal: isInternal, placeholderText: placeholderText })] }), _jsx(ActionBar, {})] }) }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(ComposerTextSyncPlugin, { onChange: setComposerText }), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined) && (_jsx(MentionMenu, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID })), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
237
+ }, destroyOnHidden: true, children: _jsxs("div", { "data-cp-name": COMPOSER_AREA_CP_NAME, className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setIsLinkPreviewDismissed(true) })), _jsx(ToolbarPlugin, {}), _jsxs("div", { children: [_jsx(ComposerTabs, { canUseInternal: canUseInternal, hintText: t("canned_response_hint"), isInternal: isInternal, lockToInternal: lockToInternal, setIsInternal: setIsInternal }), _jsx(ComposerEditor, { isInternal: isInternal, placeholderText: placeholderText })] }), _jsx(ActionBar, {})] }) }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(ComposerTextSyncPlugin, { onChange: setComposerText }), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined) && (_jsx(MentionMenu, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID })), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
238
238
  };
239
239
  export default MessageFooterProvider;
@@ -1,3 +1,4 @@
1
+ export declare const COMPOSER_AREA_CP_NAME = "MessageFooterComposerArea";
1
2
  interface MentionMenuProps {
2
3
  groupID: string | undefined;
3
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MentionMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/MentionMenu.tsx"],"names":[],"mappings":"AA4BA,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,QAAA,MAAM,WAAW,GAAI,aAAa,gBAAgB,mDA8HjD,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MentionMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/MentionMenu.tsx"],"names":[],"mappings":"AA8BA,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAWjE,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,QAAA,MAAM,WAAW,GAAI,aAAa,gBAAgB,mDAyIjD,CAAC;AA+CF,eAAe,WAAW,CAAC"}
@@ -1,16 +1,32 @@
1
1
  "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
2
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useMemo, useState } from "react";
14
+ import { useCallback, useLayoutEffect, useMemo, useRef, useState, } from "react";
4
15
  import { createPortal } from "react-dom";
5
16
  import { useTranslation } from "react-i18next";
6
17
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
7
18
  import { LexicalTypeaheadMenuPlugin, MenuOption, useBasicTypeaheadTriggerMatch, } from "@lexical/react/LexicalTypeaheadMenuPlugin";
8
19
  import { $createTextNode, $getRoot } from "lexical";
9
- import { $createMentionNode, $countMentionedUsers } from "./MentionNode";
20
+ import { $createMentionNode, $getMentionedUserIDs } from "./MentionNode";
10
21
  import { useMentionOptions } from "./useMentionOptions";
11
22
  import { Avatar } from "antd";
12
23
  import { useMessageFooterContext } from "..";
13
24
  const MAX_MENTIONED_USERS = 10;
25
+ // Marks the composer's outer boundary (footer/index.tsx) so
26
+ // MentionMenuOffset below can measure against it despite Lexical's
27
+ // typeahead container being portaled outside the composer's own DOM
28
+ // subtree. Exported so both sides of this coupling share one literal.
29
+ export const COMPOSER_AREA_CP_NAME = "MessageFooterComposerArea";
14
30
  class MentionTypeaheadOption extends MenuOption {
15
31
  constructor(option) {
16
32
  super(option.userID);
@@ -28,11 +44,18 @@ const MentionMenu = ({ groupID }) => {
28
44
  const options = useMentionOptions(groupID, query !== null && query !== void 0 ? query : "");
29
45
  // Re-evaluated per query change (menu re-opens/re-queries on every "@"),
30
46
  // so this stays in sync with mentions added/removed since the last count.
31
- const mentionedUsersCount = useMemo(() => editor.getEditorState().read(() => $countMentionedUsers($getRoot())), [editor, query]);
47
+ const mentionedUserIDs = useMemo(() => editor.getEditorState().read(() => $getMentionedUserIDs($getRoot())), [editor, query]);
48
+ const mentionedUsersCount = mentionedUserIDs.size;
32
49
  const limitReached = mentionedUsersCount >= MAX_MENTIONED_USERS;
50
+ // Already-tagged users don't need to appear again in the same draft.
33
51
  // "Tất cả" doesn't count against the per-user cap and stays selectable;
34
52
  // only specific-member options are hidden once the limit is hit.
35
- const visibleOptions = useMemo(() => (limitReached ? options.filter((option) => option.isAtAll) : options), [options, limitReached]);
53
+ const visibleOptions = useMemo(() => {
54
+ const notYetMentioned = options.filter((option) => option.isAtAll || !mentionedUserIDs.has(option.userID));
55
+ return limitReached
56
+ ? notYetMentioned.filter((option) => option.isAtAll)
57
+ : notYetMentioned;
58
+ }, [options, mentionedUserIDs, limitReached]);
36
59
  const typeaheadOptions = useMemo(() => visibleOptions.map((option) => new MentionTypeaheadOption(option)), [visibleOptions]);
37
60
  const onSelectOption = useCallback((selected, textNodeContainingQuery, closeMenu) => {
38
61
  editor.update(() => {
@@ -60,10 +83,47 @@ const MentionMenu = ({ groupID }) => {
60
83
  // that much room, so it always renders downward and gets clipped
61
84
  // by the page. Anchoring this menu to the container's bottom
62
85
  // edge instead makes it grow upward from the caret line
63
- // unconditionally, independent of that flip heuristic.
64
- _jsxs("div", { "data-cp-name": "MentionMenu", className: "absolute bottom-0 left-0 z-50 max-h-[220px] w-[260px] overflow-y-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg", children: [_jsx("div", { className: "px-3 py-1 text-xs font-medium text-gray-400", children: t("mention.menu_title") }), typeaheadOptions.length === 0 ? (_jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: limitReached
86
+ // unconditionally, independent of that flip heuristic. But the
87
+ // caret line itself sits inside the composer box (it's the text
88
+ // cursor position), not above it — so "grow up from here" still
89
+ // overlapped the composer's own top portion. MentionMenuOffset
90
+ // pushes the extra distance from the caret up to the composer's
91
+ // actual top edge, so the menu clears the input entirely.
92
+ _jsxs(MentionMenuOffset, { "data-cp-name": "MentionMenu", className: "absolute left-0 z-50 max-h-[220px] w-[260px] overflow-y-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg", children: [_jsx("div", { className: "px-3 py-1 text-xs font-medium text-gray-400", children: t("mention.menu_title") }), typeaheadOptions.length === 0 ? (_jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: limitReached
65
93
  ? t("mention.limit_reached", { max: MAX_MENTIONED_USERS })
66
94
  : t("mention.no_result") })) : (typeaheadOptions.map((option, index) => (_jsxs("button", { type: "button", className: `flex w-full items-center gap-2 px-3 py-2 text-left text-sm ${index === selectedIndex ? "bg-blue-50" : "hover:bg-gray-50"}`, onMouseEnter: () => setHighlightedIndex(index), onClick: () => selectOptionAndCleanUp(option), children: [option.option.isAtAll ? (_jsx("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gray-100 text-gray-500", children: "@" })) : (_jsx(Avatar, { size: 24, src: option.option.faceURL, children: option.option.displayName.charAt(0) })), _jsx("span", { className: "min-w-0 flex-1 truncate", children: option.option.displayName })] }, option.key))))] }), anchorElementRef.current);
67
95
  } }));
68
96
  };
97
+ // Renders inside Lexical's own typeahead container, which it portals
98
+ // straight to document.body — detached from the composer's own DOM
99
+ // subtree, so `closest()` can't find the composer from here. Look it up
100
+ // globally instead: only one composer is ever focused/active at a time.
101
+ // Measures the distance from the caret-position anchor up to the
102
+ // composer's top edge and applies it as `bottom`, so the menu's own bottom
103
+ // edge lands there instead of at the caret's — clearing the input instead
104
+ // of overlapping it.
105
+ //
106
+ // No dependency array: this component's identity survives across the
107
+ // re-renders LexicalTypeaheadMenuPlugin fires on every keystroke while the
108
+ // menu stays open (same tree position, not remounted), so a one-time
109
+ // measurement would go stale the moment the composer's own height changes
110
+ // mid-session (e.g. a reply preview or file attachment toggling on/off).
111
+ // Re-measuring every render keeps it correct at the cost of one cheap
112
+ // getBoundingClientRect() call per keystroke.
113
+ const MentionMenuOffset = (_a) => {
114
+ var { className, children } = _a, rest = __rest(_a, ["className", "children"]);
115
+ const ref = useRef(null);
116
+ const [bottomOffset, setBottomOffset] = useState(0);
117
+ useLayoutEffect(() => {
118
+ var _a;
119
+ const anchorNode = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.parentElement;
120
+ const composer = document.querySelector(`[data-cp-name="${COMPOSER_AREA_CP_NAME}"]`);
121
+ if (!anchorNode || !composer)
122
+ return;
123
+ const anchorRect = anchorNode.getBoundingClientRect();
124
+ const composerRect = composer.getBoundingClientRect();
125
+ setBottomOffset(Math.max(0, anchorRect.top - composerRect.top));
126
+ });
127
+ return (_jsx("div", Object.assign({ ref: ref, className: className, style: { bottom: bottomOffset } }, rest, { children: children })));
128
+ };
69
129
  export default MentionMenu;
@@ -17,5 +17,5 @@ export declare class MentionNode extends TextNode {
17
17
  }
18
18
  export declare function $createMentionNode(userID: string, isAtAll: boolean, displayText: string): MentionNode;
19
19
  export declare function $isMentionNode(node: LexicalNode | null | undefined): node is MentionNode;
20
- export declare function $countMentionedUsers(root: LexicalNode): number;
20
+ export declare function $getMentionedUserIDs(root: LexicalNode): Set<string>;
21
21
  //# sourceMappingURL=MentionNode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MentionNode.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/MentionNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,MAAM,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAAG,MAAM,CACxC;IACE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,EACD,kBAAkB,CACnB,CAAC;AAEF,qBAAa,WAAY,SAAQ,QAAQ;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IAEnB,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;gBAU1C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,OAAO;IAOf,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAM5C,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,qBAAqB,GAAG,WAAW;IAQrE,UAAU,IAAI,qBAAqB;IASnC,mBAAmB,IAAI,OAAO;IAI9B,YAAY,IAAI,IAAI;CAGrB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,WAAW,CAIb;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GACnC,IAAI,IAAI,WAAW,CAErB;AAID,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAc9D"}
1
+ {"version":3,"file":"MentionNode.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/MentionNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,MAAM,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAAG,MAAM,CACxC;IACE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,EACD,kBAAkB,CACnB,CAAC;AAEF,qBAAa,WAAY,SAAQ,QAAQ;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IAEnB,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;gBAU1C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,OAAO;IAOf,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAM5C,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,qBAAqB,GAAG,WAAW;IAQrE,UAAU,IAAI,qBAAqB;IASnC,mBAAmB,IAAI,OAAO;IAI9B,YAAY,IAAI,IAAI;CAGrB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,WAAW,CAIb;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GACnC,IAAI,IAAI,WAAW,CAErB;AAID,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAcnE"}
@@ -39,7 +39,7 @@ export function $isMentionNode(node) {
39
39
  }
40
40
  // Distinct specific users tagged so far — "Tất cả" (isAtAll) mentions aren't
41
41
  // individual users and don't count toward the per-user cap.
42
- export function $countMentionedUsers(root) {
42
+ export function $getMentionedUserIDs(root) {
43
43
  const userIDs = new Set();
44
44
  const walk = (node) => {
45
45
  if ($isMentionNode(node) && !node.__isAtAll) {
@@ -50,5 +50,5 @@ export function $countMentionedUsers(root) {
50
50
  }
51
51
  };
52
52
  walk(root);
53
- return userIDs.size;
53
+ return userIDs;
54
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useMentionOptions.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/useMentionOptions.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAW7C,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,GAAG,SAAS,EAC3B,OAAO,MAAM,KACZ,aAAa,EAuCf,CAAC"}
1
+ {"version":3,"file":"useMentionOptions.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/useMentionOptions.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAW7C,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,GAAG,SAAS,EAC3B,OAAO,MAAM,KACZ,aAAa,EAyCf,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from "react";
2
2
  import { useTranslation } from "react-i18next";
3
3
  import { useGroupMembers } from "../../../../hooks/group/useGroupMembers";
4
+ import useAuthStore from "../../../../store/auth";
4
5
  export const ALL_MEMBERS_USER_ID = "__all__";
5
6
  // Prefix matches rank above mid-string matches, then alphabetical — matches
6
7
  // the "closest match first" ranking spec'd for this feature (not just a
@@ -14,11 +15,13 @@ const matchRank = (displayName, keyword) => {
14
15
  export const useMentionOptions = (groupID, query) => {
15
16
  const { t } = useTranslation();
16
17
  const { members } = useGroupMembers(groupID);
18
+ const currentUserID = useAuthStore((state) => state.userID);
17
19
  return useMemo(() => {
18
20
  const keyword = query.trim().toLowerCase();
19
- // Self-tagging is a valid, ordinary mention target per spec the
20
- // sender selecting their own name is processed like any other tag.
21
+ // Self-tagging isn't a useful mention target the sender already
22
+ // knows who they are so the current user is filtered out entirely.
21
23
  const memberOptions = members
24
+ .filter((member) => member.userID !== currentUserID)
22
25
  .map((member) => ({
23
26
  userID: member.userID,
24
27
  displayName: member.nickname || member.userID,
@@ -41,5 +44,5 @@ export const useMentionOptions = (groupID, query) => {
41
44
  };
42
45
  const matchesAll = !keyword || allOption.displayName.toLowerCase().includes(keyword);
43
46
  return matchesAll ? [allOption, ...memberOptions] : memberOptions;
44
- }, [members, query, t]);
47
+ }, [members, query, t, currentUserID]);
45
48
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"AAWA,oBAAY,wBAAwB;IAClC,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,kBAAkB,GAAI,gBAAgB,uBAAuB,4CAqDlE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"AAWA,oBAAY,wBAAwB;IAClC,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,kBAAkB,GAAI,gBAAgB,uBAAuB,4CA4ElE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}