@droppii-org/chat-sdk 0.3.8 → 0.4.1

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 (290) hide show
  1. package/dist/components/canned-response/CannedResponseBody.js +1 -1
  2. package/dist/components/canned-response/CannedResponseFooter.js +1 -1
  3. package/dist/components/canned-response/CannedResponseHeader.js +1 -1
  4. package/dist/components/canned-response/index.js +1 -1
  5. package/dist/components/canned-response/team/TeamItem.js +1 -1
  6. package/dist/components/common/ConfirmModal.d.ts.map +1 -1
  7. package/dist/components/common/ConfirmModal.js +1 -1
  8. package/dist/components/common/InfoModal.d.ts.map +1 -1
  9. package/dist/components/common/InfoModal.js +1 -1
  10. package/dist/components/compose/ComposeNewMessageModal.d.ts.map +1 -1
  11. package/dist/components/compose/ComposeNewMessageModal.js +1 -1
  12. package/dist/components/conversation/ConversationByGroupItem.d.ts.map +1 -1
  13. package/dist/components/conversation/ConversationByGroupItem.js +2 -1
  14. package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
  15. package/dist/components/conversation/ConversationBySessionItem.js +2 -1
  16. package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
  17. package/dist/components/conversation/DeskConversationList.js +1 -1
  18. package/dist/components/conversation/MentionIndicatorIcon.d.ts +7 -0
  19. package/dist/components/conversation/MentionIndicatorIcon.d.ts.map +1 -0
  20. package/dist/components/conversation/MentionIndicatorIcon.js +17 -0
  21. package/dist/components/conversation/SwipeActionButton.d.ts.map +1 -1
  22. package/dist/components/conversation/SwipeActionButton.js +1 -1
  23. package/dist/components/conversation/SwipeableRow.d.ts.map +1 -1
  24. package/dist/components/conversation/SwipeableRow.js +1 -1
  25. package/dist/components/conversation/ThreadCard.d.ts +2 -1
  26. package/dist/components/conversation/ThreadCard.d.ts.map +1 -1
  27. package/dist/components/conversation/ThreadCard.js +4 -4
  28. package/dist/components/conversation-detail/ConversationDetailHeader.d.ts.map +1 -1
  29. package/dist/components/conversation-detail/ConversationDetailHeader.js +2 -2
  30. package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
  31. package/dist/components/conversation-detail/ConversationDetailInput.js +5 -1
  32. package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
  33. package/dist/components/conversation-detail/ConversationMessageList.js +1 -1
  34. package/dist/components/conversation-detail/ConversationMoreOptionItem.d.ts.map +1 -1
  35. package/dist/components/conversation-detail/ConversationMoreOptionItem.js +1 -1
  36. package/dist/components/conversation-detail/ConversationMoreOptionPanel.d.ts.map +1 -1
  37. package/dist/components/conversation-detail/ConversationMoreOptionPanel.js +1 -1
  38. package/dist/components/conversation-detail/LeaveGroupBlockedModal.d.ts +12 -0
  39. package/dist/components/conversation-detail/LeaveGroupBlockedModal.d.ts.map +1 -0
  40. package/dist/components/conversation-detail/LeaveGroupBlockedModal.js +18 -0
  41. package/dist/components/conversation-detail/LeaveGroupConfirmModal.d.ts +16 -0
  42. package/dist/components/conversation-detail/LeaveGroupConfirmModal.d.ts.map +1 -0
  43. package/dist/components/conversation-detail/LeaveGroupConfirmModal.js +21 -0
  44. package/dist/components/conversation-detail/PinLimitModal.d.ts.map +1 -1
  45. package/dist/components/conversation-detail/PinLimitModal.js +1 -1
  46. package/dist/components/conversation-detail/PinnedMessageBar.d.ts.map +1 -1
  47. package/dist/components/conversation-detail/PinnedMessageBar.js +8 -4
  48. package/dist/components/conversation-detail/PinnedMessageItem.d.ts.map +1 -1
  49. package/dist/components/conversation-detail/PinnedMessageItem.js +1 -1
  50. package/dist/components/conversation-detail/PinnedMessagesPanel.d.ts.map +1 -1
  51. package/dist/components/conversation-detail/PinnedMessagesPanel.js +1 -1
  52. package/dist/components/conversation-detail/ThreadProfilePanel.d.ts.map +1 -1
  53. package/dist/components/conversation-detail/ThreadProfilePanel.js +12 -2
  54. package/dist/components/conversation-detail/bot/BotButtonMessage.d.ts.map +1 -1
  55. package/dist/components/conversation-detail/bot/BotButtonMessage.js +1 -1
  56. package/dist/components/conversation-detail/bot/BotInactiveNotice.d.ts.map +1 -1
  57. package/dist/components/conversation-detail/bot/BotInactiveNotice.js +1 -1
  58. package/dist/components/conversation-detail/bot/BotMenuSheet.d.ts.map +1 -1
  59. package/dist/components/conversation-detail/bot/BotMenuSheet.js +1 -1
  60. package/dist/components/conversation-detail/bot/BotStartButton.d.ts.map +1 -1
  61. package/dist/components/conversation-detail/bot/BotStartButton.js +1 -1
  62. package/dist/components/conversation-detail/bot/BotSuggest.d.ts.map +1 -1
  63. package/dist/components/conversation-detail/bot/BotSuggest.js +2 -2
  64. package/dist/components/conversation-detail/bot/CsSessionConfirmModal.d.ts.map +1 -1
  65. package/dist/components/conversation-detail/bot/CsSessionConfirmModal.js +1 -1
  66. package/dist/components/conversation-detail/index.d.ts +4 -0
  67. package/dist/components/conversation-detail/index.d.ts.map +1 -1
  68. package/dist/components/conversation-detail/index.js +2 -0
  69. package/dist/components/conversation-inbox/ConversationInboxHeader.d.ts.map +1 -1
  70. package/dist/components/conversation-inbox/ConversationInboxHeader.js +1 -1
  71. package/dist/components/conversation-inbox/ConversationInboxItem.d.ts.map +1 -1
  72. package/dist/components/conversation-inbox/ConversationInboxItem.js +2 -1
  73. package/dist/components/conversation-inbox/ConversationInboxList.d.ts.map +1 -1
  74. package/dist/components/conversation-inbox/ConversationInboxList.js +1 -1
  75. package/dist/components/conversation-inbox/ConversationInboxTitle.d.ts.map +1 -1
  76. package/dist/components/conversation-inbox/ConversationInboxTitle.js +1 -1
  77. package/dist/components/conversation-inbox/ConversationPeerAvatar.d.ts.map +1 -1
  78. package/dist/components/conversation-inbox/ConversationPeerAvatar.js +1 -1
  79. package/dist/components/conversation-inbox/MuteConversationConfirmModal.d.ts.map +1 -1
  80. package/dist/components/conversation-inbox/MuteConversationConfirmModal.js +1 -1
  81. package/dist/components/group/AddMemberModal.d.ts.map +1 -1
  82. package/dist/components/group/AddMemberModal.js +1 -1
  83. package/dist/components/group/CreateGroupForm.d.ts.map +1 -1
  84. package/dist/components/group/CreateGroupForm.js +1 -3
  85. package/dist/components/group/GroupMemberPicker.js +1 -1
  86. package/dist/components/group/MemberPermissionPanel.js +1 -1
  87. package/dist/components/icon/index.d.ts.map +1 -1
  88. package/dist/components/icon/index.js +1 -1
  89. package/dist/components/media-collection/FileCollection.d.ts.map +1 -1
  90. package/dist/components/media-collection/FileCollection.js +1 -1
  91. package/dist/components/media-collection/ImageCollection.d.ts.map +1 -1
  92. package/dist/components/media-collection/ImageCollection.js +1 -1
  93. package/dist/components/media-collection/LinkCollection.d.ts.map +1 -1
  94. package/dist/components/media-collection/LinkCollection.js +2 -2
  95. package/dist/components/media-collection/VideoCollection.d.ts.map +1 -1
  96. package/dist/components/media-collection/VideoCollection.js +1 -1
  97. package/dist/components/media-collection/index.js +1 -1
  98. package/dist/components/media-resources/FileResourceList.d.ts.map +1 -1
  99. package/dist/components/media-resources/FileResourceList.js +1 -1
  100. package/dist/components/media-resources/ImageResourceGrid.d.ts.map +1 -1
  101. package/dist/components/media-resources/ImageResourceGrid.js +1 -1
  102. package/dist/components/media-resources/LinkResourceItem.d.ts.map +1 -1
  103. package/dist/components/media-resources/LinkResourceItem.js +1 -1
  104. package/dist/components/media-resources/LinkResourceList.d.ts.map +1 -1
  105. package/dist/components/media-resources/LinkResourceList.js +1 -1
  106. package/dist/components/media-resources/MediaEntryCard.d.ts.map +1 -1
  107. package/dist/components/media-resources/MediaEntryCard.js +1 -1
  108. package/dist/components/media-resources/MediaResourcePanel.d.ts.map +1 -1
  109. package/dist/components/media-resources/MediaResourcePanel.js +1 -1
  110. package/dist/components/media-resources/MediaResourceTabBar.d.ts.map +1 -1
  111. package/dist/components/media-resources/MediaResourceTabBar.js +1 -1
  112. package/dist/components/media-resources/MediaResourceTabs.js +1 -1
  113. package/dist/components/media-resources/ResourceEmptyState.d.ts.map +1 -1
  114. package/dist/components/media-resources/ResourceEmptyState.js +1 -1
  115. package/dist/components/media-resources/ResourceScrollContainer.d.ts.map +1 -1
  116. package/dist/components/media-resources/ResourceScrollContainer.js +1 -1
  117. package/dist/components/media-resources/VideoResourceGrid.d.ts.map +1 -1
  118. package/dist/components/media-resources/VideoResourceGrid.js +1 -1
  119. package/dist/components/message/GroupMembersDrawer.js +1 -1
  120. package/dist/components/message/MessageHeader.d.ts.map +1 -1
  121. package/dist/components/message/MessageHeader.js +3 -2
  122. package/dist/components/message/MessageInfiniteScroll.d.ts.map +1 -1
  123. package/dist/components/message/MessageInfiniteScroll.js +1 -1
  124. package/dist/components/message/MessageList.d.ts.map +1 -1
  125. package/dist/components/message/MessageList.js +22 -12
  126. package/dist/components/message/SelectSession.js +1 -1
  127. package/dist/components/message/UnassignedSessionFooter.d.ts.map +1 -1
  128. package/dist/components/message/UnassignedSessionFooter.js +1 -1
  129. package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
  130. package/dist/components/message/footer/ActionBar.js +4 -1
  131. package/dist/components/message/footer/ComposerEditor.js +1 -1
  132. package/dist/components/message/footer/ComposerTabs.d.ts.map +1 -1
  133. package/dist/components/message/footer/ComposerTabs.js +1 -1
  134. package/dist/components/message/footer/EmojiPicker.js +1 -1
  135. package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
  136. package/dist/components/message/footer/EnterHandler.js +10 -1
  137. package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
  138. package/dist/components/message/footer/FilePreview.js +4 -4
  139. package/dist/components/message/footer/LinkInputPreview.d.ts.map +1 -1
  140. package/dist/components/message/footer/LinkInputPreview.js +1 -1
  141. package/dist/components/message/footer/MediaActions.js +1 -1
  142. package/dist/components/message/footer/SessionClosedModal.d.ts.map +1 -1
  143. package/dist/components/message/footer/SessionClosedModal.js +1 -1
  144. package/dist/components/message/footer/ToolbarPlugin.js +1 -1
  145. package/dist/components/message/footer/editorConfig.d.ts +2 -1
  146. package/dist/components/message/footer/editorConfig.d.ts.map +1 -1
  147. package/dist/components/message/footer/editorConfig.js +2 -0
  148. package/dist/components/message/footer/index.d.ts.map +1 -1
  149. package/dist/components/message/footer/index.js +16 -2
  150. package/dist/components/message/footer/mention/MentionMenu.d.ts +6 -0
  151. package/dist/components/message/footer/mention/MentionMenu.d.ts.map +1 -0
  152. package/dist/components/message/footer/mention/MentionMenu.js +51 -0
  153. package/dist/components/message/footer/mention/MentionNode.d.ts +20 -0
  154. package/dist/components/message/footer/mention/MentionNode.d.ts.map +1 -0
  155. package/dist/components/message/footer/mention/MentionNode.js +39 -0
  156. package/dist/components/message/footer/mention/extractMentions.d.ts +6 -0
  157. package/dist/components/message/footer/mention/extractMentions.d.ts.map +1 -0
  158. package/dist/components/message/footer/mention/extractMentions.js +66 -0
  159. package/dist/components/message/footer/mention/useMentionOptions.d.ts +8 -0
  160. package/dist/components/message/footer/mention/useMentionOptions.d.ts.map +1 -0
  161. package/dist/components/message/footer/mention/useMentionOptions.js +45 -0
  162. package/dist/components/message/item/AtTextMessage.d.ts +16 -0
  163. package/dist/components/message/item/AtTextMessage.d.ts.map +1 -0
  164. package/dist/components/message/item/AtTextMessage.js +112 -0
  165. package/dist/components/message/item/FileMessage.js +1 -1
  166. package/dist/components/message/item/GroupNotificationMessage.d.ts.map +1 -1
  167. package/dist/components/message/item/GroupNotificationMessage.js +2 -2
  168. package/dist/components/message/item/ImageMessage.js +1 -1
  169. package/dist/components/message/item/LinkCard.d.ts.map +1 -1
  170. package/dist/components/message/item/LinkCard.js +1 -1
  171. package/dist/components/message/item/LinkText.d.ts.map +1 -1
  172. package/dist/components/message/item/LinkText.js +1 -1
  173. package/dist/components/message/item/MergeImageMessage.js +1 -1
  174. package/dist/components/message/item/MessageBubble.d.ts.map +1 -1
  175. package/dist/components/message/item/MessageBubble.js +2 -2
  176. package/dist/components/message/item/QuoteMessage.d.ts.map +1 -1
  177. package/dist/components/message/item/QuoteMessage.js +1 -1
  178. package/dist/components/message/item/RevokeMessage.d.ts.map +1 -1
  179. package/dist/components/message/item/RevokeMessage.js +1 -1
  180. package/dist/components/message/item/VideoMessage.js +1 -1
  181. package/dist/components/message/item/index.d.ts.map +1 -1
  182. package/dist/components/message/item/index.js +3 -3
  183. package/dist/components/message/item/renderMessageContent.d.ts.map +1 -1
  184. package/dist/components/message/item/renderMessageContent.js +3 -0
  185. package/dist/components/message/reply/ReplyPreviewBar.d.ts.map +1 -1
  186. package/dist/components/message/reply/ReplyPreviewBar.js +1 -1
  187. package/dist/components/message/reply/ReplyQuoteContent.d.ts.map +1 -1
  188. package/dist/components/message/reply/ReplyQuoteContent.js +7 -5
  189. package/dist/components/message/toolbox/MessageToolboxMenu.js +1 -1
  190. package/dist/components/message/toolbox/getCopyableMessageText.d.ts.map +1 -1
  191. package/dist/components/message/toolbox/getCopyableMessageText.js +5 -3
  192. package/dist/components/message/toolbox/isPinnableMessageType.d.ts.map +1 -1
  193. package/dist/components/message/toolbox/isPinnableMessageType.js +1 -0
  194. package/dist/components/search-conversation/SearchAll.d.ts.map +1 -1
  195. package/dist/components/search-conversation/SearchAll.js +9 -3
  196. package/dist/components/search-conversation/SearchConversationAsGroups.d.ts +6 -0
  197. package/dist/components/search-conversation/SearchConversationAsGroups.d.ts.map +1 -0
  198. package/dist/components/search-conversation/SearchConversationAsGroups.js +20 -0
  199. package/dist/components/search-conversation/SearchConversationAsMessages.d.ts.map +1 -1
  200. package/dist/components/search-conversation/SearchConversationAsMessages.js +1 -1
  201. package/dist/components/search-conversation/SearchConversationAsUsers.d.ts.map +1 -1
  202. package/dist/components/search-conversation/SearchConversationAsUsers.js +1 -1
  203. package/dist/components/search-conversation/SearchConversationMyInbox.js +1 -1
  204. package/dist/components/search-conversation/SearchDrawer.js +1 -1
  205. package/dist/components/search-conversation/SearchMessageOnCurrentConversation.d.ts.map +1 -1
  206. package/dist/components/search-conversation/SearchMessageOnCurrentConversation.js +1 -1
  207. package/dist/components/search-conversation/index.d.ts +2 -1
  208. package/dist/components/search-conversation/index.d.ts.map +1 -1
  209. package/dist/components/search-conversation/index.js +8 -1
  210. package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts +8 -0
  211. package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -0
  212. package/dist/components/search-conversation/item/SearchItemAsGroup.js +34 -0
  213. package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
  214. package/dist/components/search-conversation/item/SearchItemAsMessage.js +1 -1
  215. package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
  216. package/dist/components/search-conversation/item/SearchItemAsUser.js +1 -1
  217. package/dist/components/session/DeskTeamInbox.d.ts.map +1 -1
  218. package/dist/components/session/DeskTeamInbox.js +3 -2
  219. package/dist/components/session/SessionFilterMenu.d.ts.map +1 -1
  220. package/dist/components/session/SessionFilterMenu.js +1 -1
  221. package/dist/components/thread/AssignConfirmModal.d.ts.map +1 -1
  222. package/dist/components/thread/AssignConfirmModal.js +1 -1
  223. package/dist/components/thread/GroupThreadInfo.d.ts.map +1 -1
  224. package/dist/components/thread/GroupThreadInfo.js +7 -4
  225. package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -1
  226. package/dist/components/thread/ManualAssignPopover.js +1 -1
  227. package/dist/components/thread/SessionSection.d.ts.map +1 -1
  228. package/dist/components/thread/SessionSection.js +2 -2
  229. package/dist/components/thread/SingleThreadInfo.d.ts.map +1 -1
  230. package/dist/components/thread/SingleThreadInfo.js +1 -1
  231. package/dist/components/thread/ThreadInfo.js +1 -1
  232. package/dist/components/thread/UserSection.d.ts.map +1 -1
  233. package/dist/components/thread/UserSection.js +1 -1
  234. package/dist/components/video-player/VideoPlayerModal.d.ts.map +1 -1
  235. package/dist/components/video-player/VideoPlayerModal.js +1 -1
  236. package/dist/context/ChatContext.d.ts +1 -1
  237. package/dist/context/ChatContext.d.ts.map +1 -1
  238. package/dist/context/ChatContext.js +2 -1
  239. package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
  240. package/dist/hooks/global/useGlobalEvent.js +125 -25
  241. package/dist/hooks/group/useConversationGroups.d.ts +5 -1
  242. package/dist/hooks/group/useConversationGroups.d.ts.map +1 -1
  243. package/dist/hooks/group/useConversationGroups.js +3 -3
  244. package/dist/hooks/group/useGroupPermission.d.ts +1 -1
  245. package/dist/hooks/group/useGroupPermission.d.ts.map +1 -1
  246. package/dist/hooks/group/useGroupPermission.js +2 -2
  247. package/dist/hooks/group/useLeaveGroupAction.d.ts +24 -0
  248. package/dist/hooks/group/useLeaveGroupAction.d.ts.map +1 -0
  249. package/dist/hooks/group/useLeaveGroupAction.js +79 -0
  250. package/dist/hooks/group/useQuitGroup.d.ts +6 -0
  251. package/dist/hooks/group/useQuitGroup.d.ts.map +1 -0
  252. package/dist/hooks/group/useQuitGroup.js +62 -0
  253. package/dist/hooks/message/useMessage.d.ts +4 -1
  254. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  255. package/dist/hooks/message/useMessage.js +9 -2
  256. package/dist/hooks/message/useSendMessage.d.ts +8 -4
  257. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  258. package/dist/hooks/message/useSendMessage.js +46 -12
  259. package/dist/hooks/search/useSearchGroups.d.ts +16 -0
  260. package/dist/hooks/search/useSearchGroups.d.ts.map +1 -0
  261. package/dist/hooks/search/useSearchGroups.js +65 -0
  262. package/dist/hooks/session/useConversationSessionState.d.ts +2 -1
  263. package/dist/hooks/session/useConversationSessionState.d.ts.map +1 -1
  264. package/dist/hooks/session/useConversationSessionState.js +5 -5
  265. package/dist/layout/index.d.ts.map +1 -1
  266. package/dist/layout/index.js +10 -1
  267. package/dist/locales/vi/common.json +12 -0
  268. package/dist/locales/vi/conversation-inbox.json +18 -1
  269. package/dist/services/query.d.ts +1 -0
  270. package/dist/services/query.d.ts.map +1 -1
  271. package/dist/services/query.js +1 -0
  272. package/dist/services/routes.d.ts +1 -0
  273. package/dist/services/routes.d.ts.map +1 -1
  274. package/dist/services/routes.js +1 -0
  275. package/dist/store/auth.js +1 -1
  276. package/dist/store/conversation.d.ts.map +1 -1
  277. package/dist/store/conversation.js +96 -51
  278. package/dist/store/type.d.ts +8 -2
  279. package/dist/store/type.d.ts.map +1 -1
  280. package/dist/styles/global.css +1 -1
  281. package/dist/types/chat.d.ts +28 -2
  282. package/dist/types/chat.d.ts.map +1 -1
  283. package/dist/types/dto.d.ts +3 -1
  284. package/dist/types/dto.d.ts.map +1 -1
  285. package/dist/utils/common.d.ts.map +1 -1
  286. package/dist/utils/common.js +19 -9
  287. package/dist/utils/messageLog.d.ts +2 -2
  288. package/dist/utils/messageLog.d.ts.map +1 -1
  289. package/dist/utils/messageLog.js +33 -3
  290. package/package.json +17 -3
@@ -1,6 +1,7 @@
1
1
  import { LinkNode } from "@lexical/link";
2
2
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
3
3
  import { ListItemNode, ListNode } from "@lexical/list";
4
+ import { MentionNode } from "./mention/MentionNode";
4
5
  export declare const editorTheme: {
5
6
  text: {
6
7
  bold: string;
@@ -18,7 +19,7 @@ export declare const editorTheme: {
18
19
  };
19
20
  link: string;
20
21
  };
21
- export declare const editorNodes: (typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
22
+ export declare const editorNodes: (typeof MentionNode | typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
22
23
  export declare const editorOnError: (error: Error) => void;
23
24
  export declare const DOCUMENT_TYPES: string[];
24
25
  //# sourceMappingURL=editorConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editorConfig.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/editorConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,eAAO,MAAM,WAAW,qGAMvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,SAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAI1B,CAAC"}
1
+ {"version":3,"file":"editorConfig.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/editorConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,eAAO,MAAM,WAAW,0HAOvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,SAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAI1B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { LinkNode } from "@lexical/link";
2
2
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
3
3
  import { ListItemNode, ListNode } from "@lexical/list";
4
+ import { MentionNode } from "./mention/MentionNode";
4
5
  export const editorTheme = {
5
6
  text: {
6
7
  bold: "font-bold",
@@ -22,6 +23,7 @@ export const editorNodes = [
22
23
  ListItemNode,
23
24
  QuoteNode,
24
25
  LinkNode,
26
+ MentionNode,
25
27
  ];
26
28
  export const editorOnError = (error) => {
27
29
  console.error(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAEL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAY/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CA4SpB,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,4CAuUpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -27,6 +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
31
  import SessionClosedModal from "./SessionClosedModal";
31
32
  import { useCreateSession, useReopenSession, } from "../../../hooks/session/useReopenOrCreateSession";
32
33
  import { emit } from "../../../utils/events";
@@ -49,10 +50,13 @@ export const MessageFooterContext = createContext({
49
50
  setActiveCannedIndex: () => { },
50
51
  maxActiveCannedIndex: 0,
51
52
  setMaxActiveCannedIndex: () => { },
53
+ isMentionMenuOpen: false,
54
+ setIsMentionMenuOpen: () => { },
52
55
  });
53
56
  export const useMessageFooterContext = () => useContext(MessageFooterContext);
54
57
  const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
55
58
  const { t } = useTranslation();
59
+ const { t: tConversationInbox } = useTranslation("conversation-inbox");
56
60
  const { sendMergeMessage } = useSendMessage();
57
61
  const accountType = useCurrentUserAccountType();
58
62
  const [listUploadFiles, setListUploadFiles] = useState([]);
@@ -64,8 +68,10 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
64
68
  const [activeCannedIndex, setActiveCannedIndex] = useState(0);
65
69
  const [maxActiveCannedIndex, setMaxActiveCannedIndex] = useState(0);
66
70
  const [isInternal, setIsInternal] = useState(false);
71
+ const [isMentionMenuOpen, setIsMentionMenuOpen] = useState(false);
67
72
  const quotedMessage = useConversationStore((state) => state.quotedMessage);
68
73
  const conversationData = useConversationStore((state) => state.conversationData);
74
+ const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
69
75
  // Internal notes are a CX-support concept (team-only remarks not sent to
70
76
  // the customer) — meaningless inside a real member-managed group, where
71
77
  // everyone in the thread already is the "team".
@@ -112,7 +118,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
112
118
  const placeholderText = isInternal
113
119
  ? t("enter_internal_message")
114
120
  : t("enter_message");
115
- const onSendMessage = useCallback(({ plainText, richText, type, isInternal, }) => {
121
+ const onSendMessage = useCallback(({ plainText, richText, type, isInternal, mentions, }) => {
116
122
  if ((currentSession === null || currentSession === void 0 ? void 0 : currentSession.isClosed) && !isInternal) {
117
123
  pendingMessageRef.current = {
118
124
  plainText,
@@ -121,6 +127,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
121
127
  isInternal,
122
128
  files: [...listUploadFiles],
123
129
  urlMetadata: resolveUrlMetadata(),
130
+ mentions,
124
131
  };
125
132
  openSessionClosedModal();
126
133
  return false;
@@ -132,6 +139,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
132
139
  currentSession,
133
140
  isInternal,
134
141
  urlMetadata: resolveUrlMetadata(),
142
+ mentions,
135
143
  });
136
144
  setListUploadFiles([]);
137
145
  return true;
@@ -154,6 +162,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
154
162
  currentSession: sessionToUse,
155
163
  isInternal: pending.isInternal,
156
164
  urlMetadata: pending.urlMetadata,
165
+ mentions: pending.mentions,
157
166
  });
158
167
  setListUploadFiles([]);
159
168
  pendingMessageRef.current = null;
@@ -206,6 +215,9 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
206
215
  }
207
216
  closeCanned();
208
217
  };
218
+ if (isViewOnlyMember) {
219
+ return (_jsx("div", { "data-testid": "message-footer-view-only", className: "flex w-full items-center justify-center border-t border-gray-25 bg-white px-4 py-3 text-center text-sm text-gray-500", children: tConversationInbox("thread_detail.view_only_notice") }));
220
+ }
209
221
  return (_jsxs(MessageFooterContext.Provider, { value: {
210
222
  onSendMessage,
211
223
  isInternal,
@@ -218,8 +230,10 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
218
230
  setActiveCannedIndex,
219
231
  maxActiveCannedIndex,
220
232
  setMaxActiveCannedIndex,
233
+ isMentionMenuOpen,
234
+ setIsMentionMenuOpen,
221
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: {
222
236
  body: "mx-1 !p-0",
223
- }, 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, {}), 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", { 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 })] }));
224
238
  };
225
239
  export default MessageFooterProvider;
@@ -0,0 +1,6 @@
1
+ interface MentionMenuProps {
2
+ groupID: string | undefined;
3
+ }
4
+ declare const MentionMenu: ({ groupID }: MentionMenuProps) => import("react/jsx-runtime").JSX.Element | null;
5
+ export default MentionMenu;
6
+ //# sourceMappingURL=MentionMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/MentionMenu.tsx"],"names":[],"mappings":"AA0BA,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,QAAA,MAAM,WAAW,GAAI,aAAa,gBAAgB,mDAqGjD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ import { useTranslation } from "react-i18next";
6
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
7
+ import { LexicalTypeaheadMenuPlugin, MenuOption, useBasicTypeaheadTriggerMatch, } from "@lexical/react/LexicalTypeaheadMenuPlugin";
8
+ import { $createTextNode } from "lexical";
9
+ import { $createMentionNode } from "./MentionNode";
10
+ import { useMentionOptions } from "./useMentionOptions";
11
+ import { Avatar } from "antd";
12
+ import { useMessageFooterContext } from "..";
13
+ class MentionTypeaheadOption extends MenuOption {
14
+ constructor(option) {
15
+ super(option.userID);
16
+ this.option = option;
17
+ }
18
+ }
19
+ const MentionMenu = ({ groupID }) => {
20
+ const { t } = useTranslation();
21
+ const [editor] = useLexicalComposerContext();
22
+ const [query, setQuery] = useState(null);
23
+ const { setIsMentionMenuOpen } = useMessageFooterContext();
24
+ const checkForMentionMatch = useBasicTypeaheadTriggerMatch("@", {
25
+ minLength: 0,
26
+ });
27
+ const options = useMentionOptions(groupID, query !== null && query !== void 0 ? query : "");
28
+ const typeaheadOptions = useMemo(() => options.map((option) => new MentionTypeaheadOption(option)), [options]);
29
+ const onSelectOption = useCallback((selected, textNodeContainingQuery, closeMenu) => {
30
+ editor.update(() => {
31
+ const mentionNode = $createMentionNode(selected.option.userID, selected.option.isAtAll, `@${selected.option.displayName}`);
32
+ if (textNodeContainingQuery) {
33
+ textNodeContainingQuery.replace(mentionNode);
34
+ }
35
+ // Trailing space detaches the cursor from the segmented mention
36
+ // node — without it, typing right after would extend/replace it.
37
+ const spaceNode = $createTextNode(" ");
38
+ mentionNode.insertAfter(spaceNode);
39
+ spaceNode.select();
40
+ });
41
+ closeMenu();
42
+ }, [editor]);
43
+ if (!groupID)
44
+ return null;
45
+ return (_jsx(LexicalTypeaheadMenuPlugin, { onQueryChange: setQuery, onSelectOption: onSelectOption, onOpen: () => setIsMentionMenuOpen(true), onClose: () => setIsMentionMenuOpen(false), triggerFn: checkForMentionMatch, options: typeaheadOptions, menuRenderFn: (anchorElementRef, { selectedIndex, setHighlightedIndex, selectOptionAndCleanUp }) => {
46
+ if (!anchorElementRef.current)
47
+ return null;
48
+ return createPortal(_jsxs("div", { "data-cp-name": "MentionMenu", className: "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: 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);
49
+ } }));
50
+ };
51
+ export default MentionMenu;
@@ -0,0 +1,20 @@
1
+ import { TextNode, type EditorConfig, type LexicalNode, type NodeKey, type SerializedTextNode, type Spread } from "lexical";
2
+ export type SerializedMentionNode = Spread<{
3
+ userID: string;
4
+ isAtAll: boolean;
5
+ }, SerializedTextNode>;
6
+ export declare class MentionNode extends TextNode {
7
+ __userID: string;
8
+ __isAtAll: boolean;
9
+ static getType(): string;
10
+ static clone(node: MentionNode): MentionNode;
11
+ constructor(userID: string, isAtAll: boolean, text: string, key?: NodeKey);
12
+ createDOM(config: EditorConfig): HTMLElement;
13
+ static importJSON(serializedNode: SerializedMentionNode): MentionNode;
14
+ exportJSON(): SerializedMentionNode;
15
+ canInsertTextBefore(): boolean;
16
+ isTextEntity(): true;
17
+ }
18
+ export declare function $createMentionNode(userID: string, isAtAll: boolean, displayText: string): MentionNode;
19
+ export declare function $isMentionNode(node: LexicalNode | null | undefined): node is MentionNode;
20
+ //# sourceMappingURL=MentionNode.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,39 @@
1
+ import { $applyNodeReplacement, TextNode, } from "lexical";
2
+ export class MentionNode extends TextNode {
3
+ static getType() {
4
+ return "mention";
5
+ }
6
+ static clone(node) {
7
+ return new MentionNode(node.__userID, node.__isAtAll, node.__text, node.__key);
8
+ }
9
+ constructor(userID, isAtAll, text, key) {
10
+ super(text, key);
11
+ this.__userID = userID;
12
+ this.__isAtAll = isAtAll;
13
+ }
14
+ createDOM(config) {
15
+ const dom = super.createDOM(config);
16
+ dom.className = "text-blue-500 font-medium";
17
+ return dom;
18
+ }
19
+ static importJSON(serializedNode) {
20
+ return $createMentionNode(serializedNode.userID, serializedNode.isAtAll, serializedNode.text).updateFromJSON(serializedNode);
21
+ }
22
+ exportJSON() {
23
+ return Object.assign(Object.assign({}, super.exportJSON()), { userID: this.__userID, isAtAll: this.__isAtAll, type: "mention" });
24
+ }
25
+ canInsertTextBefore() {
26
+ return false;
27
+ }
28
+ isTextEntity() {
29
+ return true;
30
+ }
31
+ }
32
+ export function $createMentionNode(userID, isAtAll, displayText) {
33
+ const node = new MentionNode(userID, isAtAll, displayText);
34
+ node.setMode("segmented").toggleDirectionless();
35
+ return $applyNodeReplacement(node);
36
+ }
37
+ export function $isMentionNode(node) {
38
+ return node instanceof MentionNode;
39
+ }
@@ -0,0 +1,6 @@
1
+ import { type LexicalEditor } from "lexical";
2
+ import type { MentionSendPayload } from "../../../../types/chat";
3
+ declare const ALL_MEMBERS_USER_ID = "__all__";
4
+ export declare const extractMentions: (editor: LexicalEditor) => MentionSendPayload;
5
+ export { ALL_MEMBERS_USER_ID };
6
+ //# sourceMappingURL=extractMentions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractMentions.d.ts","sourceRoot":"","sources":["../../../../../src/components/message/footer/mention/extractMentions.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,QAAA,MAAM,mBAAmB,YAAY,CAAC;AA2DtC,eAAO,MAAM,eAAe,GAAI,QAAQ,aAAa,KAAG,kBAavD,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { $getRoot, $isElementNode, } from "lexical";
2
+ import { $isMentionNode } from "./MentionNode";
3
+ const ALL_MEMBERS_USER_ID = "__all__";
4
+ // Single pass, mirroring ElementNode.getTextContent()'s own join logic
5
+ // (child text content, plus a double line break between non-inline block
6
+ // children) so offsets always match the plainText Lexical actually
7
+ // produces. One pass — not a separate node-collection step — so the
8
+ // offsets and the atUserIDList/atUsersInfo they describe can never drift
9
+ // out of sync with each other.
10
+ const walk = (node, state) => {
11
+ if ($isMentionNode(node)) {
12
+ const text = node.getTextContent();
13
+ if (node.__isAtAll) {
14
+ state.payload.isAtAll = true;
15
+ state.payload.mentionOffsets.push({
16
+ userID: ALL_MEMBERS_USER_ID,
17
+ offset: state.offset,
18
+ length: text.length,
19
+ });
20
+ }
21
+ else {
22
+ state.payload.atUserIDList.push(node.__userID);
23
+ state.payload.atUsersInfo.push({
24
+ atUserID: node.__userID,
25
+ groupNickname: text.replace(/^@/, ""),
26
+ });
27
+ state.payload.mentionOffsets.push({
28
+ userID: node.__userID,
29
+ offset: state.offset,
30
+ length: text.length,
31
+ });
32
+ }
33
+ state.offset += text.length;
34
+ return;
35
+ }
36
+ if (!$isElementNode(node)) {
37
+ state.offset += node.getTextContent().length;
38
+ return;
39
+ }
40
+ const children = node.getChildren();
41
+ children.forEach((child, index) => {
42
+ walk(child, state);
43
+ const isLastChild = index === children.length - 1;
44
+ if ($isElementNode(child) && !isLastChild && !child.isInline()) {
45
+ state.offset += 2; // DOUBLE_LINE_BREAK
46
+ }
47
+ });
48
+ };
49
+ // Reads MentionNode instances straight from the editor state at send time —
50
+ // only list-selected mentions become MentionNode, so free-typed "@text"
51
+ // stays plain TextNode and is naturally excluded (BR-002). Offsets are
52
+ // captured here because this is the only point with real node identity —
53
+ // once sent, AtTextElem collapses everything into a flat string.
54
+ export const extractMentions = (editor) => {
55
+ const payload = {
56
+ atUserIDList: [],
57
+ atUsersInfo: [],
58
+ isAtAll: false,
59
+ mentionOffsets: [],
60
+ };
61
+ editor.getEditorState().read(() => {
62
+ walk($getRoot(), { offset: 0, payload });
63
+ });
64
+ return payload;
65
+ };
66
+ export { ALL_MEMBERS_USER_ID };
@@ -0,0 +1,8 @@
1
+ export interface MentionOption {
2
+ userID: string;
3
+ displayName: string;
4
+ faceURL?: string;
5
+ isAtAll: boolean;
6
+ }
7
+ export declare const useMentionOptions: (groupID: string | undefined, query: string) => MentionOption[];
8
+ //# sourceMappingURL=useMentionOptions.d.ts.map
@@ -0,0 +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;AAaD,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,GAAG,SAAS,EAC3B,OAAO,MAAM,KACZ,aAAa,EAuCf,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { useMemo } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { useGroupMembers } from "../../../../hooks/group/useGroupMembers";
4
+ const ALL_MEMBERS_USER_ID = "__all__";
5
+ // Prefix matches rank above mid-string matches, then alphabetical — matches
6
+ // the "closest match first" ranking spec'd for this feature (not just a
7
+ // plain filter). No keyword: falls back to plain A-Z (AC-Open default).
8
+ const matchRank = (displayName, keyword) => {
9
+ const lower = displayName.toLowerCase();
10
+ if (lower.startsWith(keyword))
11
+ return 0;
12
+ return 1;
13
+ };
14
+ export const useMentionOptions = (groupID, query) => {
15
+ const { t } = useTranslation();
16
+ const { members } = useGroupMembers(groupID);
17
+ return useMemo(() => {
18
+ 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
+ const memberOptions = members
22
+ .map((member) => ({
23
+ userID: member.userID,
24
+ displayName: member.nickname || member.userID,
25
+ faceURL: member.faceURL,
26
+ isAtAll: false,
27
+ }))
28
+ .filter((option) => keyword ? option.displayName.toLowerCase().includes(keyword) : true)
29
+ .sort((a, b) => {
30
+ if (!keyword)
31
+ return a.displayName.localeCompare(b.displayName);
32
+ const rankDiff = matchRank(a.displayName, keyword) - matchRank(b.displayName, keyword);
33
+ return rankDiff !== 0
34
+ ? rankDiff
35
+ : a.displayName.localeCompare(b.displayName);
36
+ });
37
+ const allOption = {
38
+ userID: ALL_MEMBERS_USER_ID,
39
+ displayName: t("mention.all_members"),
40
+ isAtAll: true,
41
+ };
42
+ const matchesAll = !keyword || allOption.displayName.toLowerCase().includes(keyword);
43
+ return matchesAll ? [allOption, ...memberOptions] : memberOptions;
44
+ }, [members, query, t]);
45
+ };
@@ -0,0 +1,16 @@
1
+ import { MessageItem } from "@droppii-org/wasm-client-sdk";
2
+ import type { MentionOffset } from "../../../types/chat";
3
+ interface AtTextMessageItemProps {
4
+ message: MessageItem;
5
+ }
6
+ export declare const splitByMentions: (text: string, mentionLabels: string[]) => Array<{
7
+ text: string;
8
+ isMention: boolean;
9
+ }>;
10
+ export declare const splitByOffsets: (text: string, offsets: MentionOffset[]) => Array<{
11
+ text: string;
12
+ isMention: boolean;
13
+ }>;
14
+ declare const AtTextMessageItem: (props: AtTextMessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
15
+ export default AtTextMessageItem;
16
+ //# sourceMappingURL=AtTextMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AtTextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/AtTextMessage.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAM3D,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,cAAc,CAAC;AAErE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAOD,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,eAAe,MAAM,EAAE,KACtB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAmC5C,CAAC;AAKF,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,SAAS,aAAa,EAAE,KACvB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAmB5C,CAAC;AAaF,QAAA,MAAM,iBAAiB,GAAI,OAAO,sBAAsB,mDAyDvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,112 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Fragment } from "react";
4
+ import clsx from "clsx";
5
+ import { extractLinkUrls } from "../../../utils/link";
6
+ import LinkText from "./LinkText";
7
+ import { MESSAGE_TEXT_CLASS } from "./textStyle";
8
+ import { useTranslation } from "react-i18next";
9
+ import { AT_ALL_TAG } from "../../../hooks/message/useSendMessage";
10
+ // AtTextElem has no offset/index, so mentions are recovered by matching
11
+ // "@displayName" text: longest-label-first (avoids "@Anna" being cut short
12
+ // by "@An"), each label consumed only as many times as it's really mentioned.
13
+ // Residual gap (accepted, tracked as follow-up): coincidental "@name" text
14
+ // before the real mention can still be mis-highlighted — needs SDK offsets.
15
+ export const splitByMentions = (text, mentionLabels) => {
16
+ var _a, _b;
17
+ if (mentionLabels.length === 0)
18
+ return [{ text, isMention: false }];
19
+ const remainingCount = new Map();
20
+ for (const label of mentionLabels) {
21
+ remainingCount.set(label, ((_a = remainingCount.get(label)) !== null && _a !== void 0 ? _a : 0) + 1);
22
+ }
23
+ const sortedLabels = [...remainingCount.keys()].sort((a, b) => b.length - a.length);
24
+ const segments = [];
25
+ let cursor = 0;
26
+ while (cursor < text.length) {
27
+ const match = sortedLabels
28
+ .filter((label) => { var _a; return ((_a = remainingCount.get(label)) !== null && _a !== void 0 ? _a : 0) > 0; })
29
+ .map((label) => ({ label, index: text.indexOf(label, cursor) }))
30
+ .filter(({ index }) => index !== -1)
31
+ .sort((a, b) => a.index - b.index || b.label.length - a.label.length)[0];
32
+ if (!match) {
33
+ segments.push({ text: text.slice(cursor), isMention: false });
34
+ break;
35
+ }
36
+ if (match.index > cursor) {
37
+ segments.push({ text: text.slice(cursor, match.index), isMention: false });
38
+ }
39
+ segments.push({ text: match.label, isMention: true });
40
+ remainingCount.set(match.label, ((_b = remainingCount.get(match.label)) !== null && _b !== void 0 ? _b : 0) - 1);
41
+ cursor = match.index + match.label.length;
42
+ }
43
+ return segments;
44
+ };
45
+ // Exact split using real offsets recorded at compose time (`ex.mentions`) —
46
+ // no guessing, so it's immune to the substring/coincidental-text gap that
47
+ // splitByMentions has to work around for messages sent before this existed.
48
+ export const splitByOffsets = (text, offsets) => {
49
+ const segments = [];
50
+ const sorted = [...offsets].sort((a, b) => a.offset - b.offset);
51
+ let cursor = 0;
52
+ for (const { offset, length } of sorted) {
53
+ if (offset < cursor || offset + length > text.length)
54
+ continue; // stale/corrupt ex — skip rather than misrender
55
+ if (offset > cursor) {
56
+ segments.push({ text: text.slice(cursor, offset), isMention: false });
57
+ }
58
+ segments.push({ text: text.slice(offset, offset + length), isMention: true });
59
+ cursor = offset + length;
60
+ }
61
+ if (cursor < text.length) {
62
+ segments.push({ text: text.slice(cursor), isMention: false });
63
+ }
64
+ return segments;
65
+ };
66
+ const parseMentionOffsets = (ex) => {
67
+ var _a;
68
+ if (!ex)
69
+ return null;
70
+ try {
71
+ const parsed = JSON.parse(ex);
72
+ const offsets = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.mentions) === null || _a === void 0 ? void 0 : _a.offsets;
73
+ return offsets && offsets.length > 0 ? offsets : null;
74
+ }
75
+ catch (_b) {
76
+ return null;
77
+ }
78
+ };
79
+ const AtTextMessageItem = (props) => {
80
+ var _a, _b, _c;
81
+ const { message } = props;
82
+ const { t } = useTranslation();
83
+ const atTextElem = message === null || message === void 0 ? void 0 : message.atTextElem;
84
+ if (!(atTextElem === null || atTextElem === void 0 ? void 0 : atTextElem.text))
85
+ return null;
86
+ const isAtAll = (_a = atTextElem.atUserList) === null || _a === void 0 ? void 0 : _a.some((userID) => userID === AT_ALL_TAG);
87
+ const memberMentionLabels = (_c = (_b = atTextElem.atUsersInfo) === null || _b === void 0 ? void 0 : _b.map((info) => `@${info.groupNickname}`)) !== null && _c !== void 0 ? _c : [];
88
+ const urls = extractLinkUrls(atTextElem.text);
89
+ if (memberMentionLabels.length === 0 &&
90
+ !isAtAll &&
91
+ urls.length > 0) {
92
+ return _jsx(LinkText, { text: atTextElem.text });
93
+ }
94
+ const mentionOffsets = parseMentionOffsets(message === null || message === void 0 ? void 0 : message.ex);
95
+ let segments;
96
+ if (mentionOffsets) {
97
+ segments = splitByOffsets(atTextElem.text, mentionOffsets);
98
+ }
99
+ else {
100
+ // Fallback for messages sent before offsets existed (no `ex.mentions`).
101
+ // "Tất cả" here is matched against the viewer's live translation, not
102
+ // the sender's persisted string — safe only while a single locale exists.
103
+ const allMembersLabel = `@${t("mention.all_members")}`;
104
+ const mentionLabels = [
105
+ ...memberMentionLabels,
106
+ ...(isAtAll ? [allMembersLabel] : []),
107
+ ];
108
+ segments = splitByMentions(atTextElem.text, mentionLabels);
109
+ }
110
+ return (_jsx("p", { className: clsx("min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: segments.map((segment, index) => (_jsx(Fragment, { children: segment.isMention ? (_jsx("span", { className: "font-medium text-blue-500", children: segment.text })) : (segment.text) }, index))) }));
111
+ };
112
+ export default AtTextMessageItem;
@@ -22,6 +22,6 @@ const FileMessageItem = (props) => {
22
22
  const handleDownload = () => {
23
23
  downloadFileFromUrl(sourceUrl, fileName);
24
24
  };
25
- return (_jsx(Spin, { spinning: isSending, children: _jsxs("div", { className: "flex h-[51px] w-[292px] items-center gap-3 rounded-xl border border-gray-200/20 bg-white px-3 py-1", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 w-[168px] flex-col justify-center", children: [_jsx("span", { className: "truncate text-[14px] font-medium leading-[160%] text-gray-900", children: shortenFileName(fileName) }), _jsx("span", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: renderFileSize(fileSize) })] }), _jsxs("div", { className: "flex w-[52px] shrink-0 items-center justify-end gap-3", children: [_jsx("button", { type: "button", onClick: handleView, disabled: !hasUrl, "aria-label": "Xem file", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "eye-o", size: 20, className: "text-gray-900" }) }), _jsx("button", { type: "button", onClick: handleDownload, disabled: !hasUrl, "aria-label": "T\u1EA3i xu\u1ED1ng", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "download-o", size: 20, className: "text-gray-900" }) })] })] }) }));
25
+ return (_jsx(Spin, { spinning: isSending, "data-cp-name": "FileMessageItem", children: _jsxs("div", { className: "flex h-[51px] w-[292px] items-center gap-3 rounded-xl border border-gray-200/20 bg-white px-3 py-1", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 w-[168px] flex-col justify-center", children: [_jsx("span", { className: "truncate text-[14px] font-medium leading-[160%] text-gray-900", children: shortenFileName(fileName) }), _jsx("span", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: renderFileSize(fileSize) })] }), _jsxs("div", { className: "flex w-[52px] shrink-0 items-center justify-end gap-3", children: [_jsx("button", { type: "button", onClick: handleView, disabled: !hasUrl, "aria-label": "Xem file", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "eye-o", size: 20, className: "text-gray-900" }) }), _jsx("button", { type: "button", onClick: handleDownload, disabled: !hasUrl, "aria-label": "T\u1EA3i xu\u1ED1ng", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "download-o", size: 20, className: "text-gray-900" }) })] })] }) }));
26
26
  };
27
27
  export default FileMessageItem;
@@ -1 +1 @@
1
- {"version":3,"file":"GroupNotificationMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/GroupNotificationMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAI3D,UAAU,iCAAiC;IACzC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,4BAA4B,GAAI,aAAa,iCAAiC,mDAiBnF,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"GroupNotificationMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/GroupNotificationMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAI3D,UAAU,iCAAiC;IACzC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,4BAA4B,GAAI,aAAa,iCAAiC,mDAkBnF,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
@@ -5,9 +5,9 @@ import { getGroupNotificationText } from "../../../utils/messageLog";
5
5
  const GroupNotificationMessageItem = ({ message }) => {
6
6
  var _a;
7
7
  const { t } = useTranslation();
8
- const text = getGroupNotificationText(message.contentType, (_a = message.notificationElem) === null || _a === void 0 ? void 0 : _a.detail, t);
8
+ const text = getGroupNotificationText(message.contentType, (_a = message.notificationElem) === null || _a === void 0 ? void 0 : _a.detail, t, message.senderNickname);
9
9
  if (!text)
10
10
  return null;
11
- return (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "rounded-full bg-gray-200 px-3 py-1.5 text-center text-[13px] font-normal text-gray-900", children: text }) }));
11
+ return (_jsx("div", { className: "flex justify-center", "data-cp-name": "GroupNotificationMessageItem", children: _jsx("span", { className: "rounded-full bg-gray-200 px-3 py-1.5 text-center text-[13px] font-normal text-gray-900", children: text }) }));
12
12
  };
13
13
  export default GroupNotificationMessageItem;
@@ -17,7 +17,7 @@ const ImageMessageItem = (props) => {
17
17
  snapshotHeight: (_k = pictureElem === null || pictureElem === void 0 ? void 0 : pictureElem.snapshotPicture) === null || _k === void 0 ? void 0 : _k.height,
18
18
  });
19
19
  const isSending = message.status === MessageStatus.Sending;
20
- return (_jsx(Spin, { spinning: isSending, children: _jsx("div", { className: "relative flex max-w-[200px] overflow-hidden rounded-xl", style: minStyle, children: _jsx(Image, { src: sourceUrl, width: minStyle.width, className: "block cursor-pointer rounded-xl object-cover", preview: {
20
+ return (_jsx(Spin, { spinning: isSending, "data-cp-name": "ImageMessageItem", children: _jsx("div", { className: "relative flex max-w-[200px] overflow-hidden rounded-xl", style: minStyle, children: _jsx(Image, { src: sourceUrl, width: minStyle.width, className: "block cursor-pointer rounded-xl object-cover", preview: {
21
21
  src: bigUrl,
22
22
  toolbarRender: (originalNode, info) => { var _a; return renderImagePreviewToolbar(originalNode, (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url, t); },
23
23
  }, placeholder: _jsx("div", { className: "flex items-center justify-center rounded-xl bg-black/10", style: minStyle, children: _jsx(Spin, {}) }) }) }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"LinkCard.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkCard.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,QAAQ,GAAI,mBAAmB,aAAa,mDA6CjD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"LinkCard.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkCard.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,QAAQ,GAAI,mBAAmB,aAAa,mDA8CjD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -14,6 +14,6 @@ const LinkCard = ({ metadata, url }) => {
14
14
  return;
15
15
  openLink(url, t);
16
16
  };
17
- return (_jsxs("button", { type: "button", onClick: handleOpen, "data-testid": "link-message-card", className: "flex w-full max-w-[292px] flex-col overflow-hidden rounded-[12px] border border-gray-900/10 bg-white text-left", children: [image && (_jsx("div", { className: "aspect-[16/9] w-full overflow-hidden", children: _jsx("img", { src: image, alt: "", className: "h-full w-full object-cover" }) })), _jsxs("div", { className: "flex flex-col px-3 py-2", children: [title && (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: title })), url && (_jsx("p", { className: "truncate text-[12px] font-medium leading-[1.6] tracking-[0.12px] text-primary-400", children: getHostLabel(url) })), description && (_jsx("p", { className: "line-clamp-2 text-[12px] leading-[1.6] text-gray-600", children: description }))] })] }));
17
+ return (_jsxs("button", { type: "button", onClick: handleOpen, "data-testid": "link-message-card", "data-cp-name": "LinkCard", className: "flex w-full max-w-[292px] flex-col overflow-hidden rounded-[12px] border border-gray-900/10 bg-white text-left", children: [image && (_jsx("div", { className: "aspect-[16/9] w-full overflow-hidden", children: _jsx("img", { src: image, alt: "", className: "h-full w-full object-cover" }) })), _jsxs("div", { className: "flex flex-col px-3 py-2", children: [title && (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: title })), url && (_jsx("p", { className: "truncate text-[12px] font-medium leading-[1.6] tracking-[0.12px] text-primary-400", children: getHostLabel(url) })), description && (_jsx("p", { className: "line-clamp-2 text-[12px] leading-[1.6] text-gray-600", children: description }))] })] }));
18
18
  };
19
19
  export default LinkCard;
@@ -1 +1 @@
1
- {"version":3,"file":"LinkText.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkText.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,QAAQ,GAAI,UAAU,aAAa,4CA2BxC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"LinkText.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkText.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,QAAQ,GAAI,UAAU,aAAa,4CA4BxC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -8,6 +8,6 @@ import { MESSAGE_TEXT_CLASS } from "./textStyle";
8
8
  const LinkText = ({ text }) => {
9
9
  const { t } = useTranslation("conversation-inbox");
10
10
  const segments = parseTextWithLinks(text);
11
- return (_jsx("span", { className: clsx("min-w-0 whitespace-pre-wrap text-left [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: segments.map((segment, index) => segment.type === "link" ? (_jsx("button", { type: "button", onClick: () => openLink(segment.url, t), className: "inline text-left font-medium text-primary-400 underline-offset-2 hover:underline", children: segment.value }, `${segment.url}-${index}`)) : (_jsx("span", { children: segment.value }, `text-${index}`))) }));
11
+ return (_jsx("span", { className: clsx("min-w-0 whitespace-pre-wrap text-left [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), "data-cp-name": "LinkText", children: segments.map((segment, index) => segment.type === "link" ? (_jsx("button", { type: "button", onClick: () => openLink(segment.url, t), className: "inline text-left font-medium text-primary-400 underline-offset-2 hover:underline", children: segment.value }, `${segment.url}-${index}`)) : (_jsx("span", { children: segment.value }, `text-${index}`))) }));
12
12
  };
13
13
  export default LinkText;
@@ -16,7 +16,7 @@ const MergeImageMessageItem = (props) => {
16
16
  const subMessages = (_b = (_a = message.mergeElem) === null || _a === void 0 ? void 0 : _a.multiMessage) !== null && _b !== void 0 ? _b : [];
17
17
  const isSending = message.status === MessageStatus.Sending;
18
18
  const cols = Math.min(subMessages.length, 3);
19
- return (_jsx("div", { className: "-mx-1", children: _jsx(Spin, { spinning: isSending, children: _jsx(Image.PreviewGroup, { preview: {
19
+ return (_jsx("div", { className: "-mx-1", "data-cp-name": "MergeImageMessageItem", children: _jsx(Spin, { spinning: isSending, children: _jsx(Image.PreviewGroup, { preview: {
20
20
  toolbarRender: (originalNode, info) => { var _a; return renderImagePreviewToolbar(originalNode, (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url, t); },
21
21
  }, children: _jsx("div", { className: clsx("grid gap-1", MERGE_IMAGE_GRID_COLS_CLASS[cols]), children: subMessages.map((item) => {
22
22
  var _a, _b, _c, _d, _e, _f;