@messenger-box/tailwind-ui-inbox 10.0.3-alpha.100

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 (373) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/LICENSE +21 -0
  3. package/jest.config.js +9 -0
  4. package/lib/cdm-locales/en/translations.json +31 -0
  5. package/lib/cdm-locales/es/translations.json +31 -0
  6. package/lib/components/AIAgent/AIAgent.d.ts +21 -0
  7. package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
  8. package/lib/components/AIAgent/AIAgent.js +904 -0
  9. package/lib/components/AIAgent/AIAgent.js.map +1 -0
  10. package/lib/components/AIAgent/index.d.ts +2 -0
  11. package/lib/components/AIAgent/index.d.ts.map +1 -0
  12. package/lib/components/InboxMessage/CommonMessage.d.ts +8 -0
  13. package/lib/components/InboxMessage/CommonMessage.d.ts.map +1 -0
  14. package/lib/components/InboxMessage/CommonMessage.js +35 -0
  15. package/lib/components/InboxMessage/CommonMessage.js.map +1 -0
  16. package/lib/components/InboxMessage/ConversationItem.d.ts +14 -0
  17. package/lib/components/InboxMessage/ConversationItem.d.ts.map +1 -0
  18. package/lib/components/InboxMessage/ConversationItem.js +200 -0
  19. package/lib/components/InboxMessage/ConversationItem.js.map +1 -0
  20. package/lib/components/InboxMessage/InputComponent.d.ts +12 -0
  21. package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
  22. package/lib/components/InboxMessage/InputComponent.js +359 -0
  23. package/lib/components/InboxMessage/InputComponent.js.map +1 -0
  24. package/lib/components/InboxMessage/LeftSidebar.d.ts +20 -0
  25. package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -0
  26. package/lib/components/InboxMessage/LeftSidebar.js +102 -0
  27. package/lib/components/InboxMessage/LeftSidebar.js.map +1 -0
  28. package/lib/components/InboxMessage/MessageInput.d.ts +9 -0
  29. package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -0
  30. package/lib/components/InboxMessage/MessageInput.js +154 -0
  31. package/lib/components/InboxMessage/MessageInput.js.map +1 -0
  32. package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
  33. package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
  34. package/lib/components/InboxMessage/Messages.d.ts +17 -0
  35. package/lib/components/InboxMessage/Messages.d.ts.map +1 -0
  36. package/lib/components/InboxMessage/Messages.js +99 -0
  37. package/lib/components/InboxMessage/Messages.js.map +1 -0
  38. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
  39. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
  40. package/lib/components/InboxMessage/Popover.d.ts +3 -0
  41. package/lib/components/InboxMessage/Popover.d.ts.map +1 -0
  42. package/lib/components/InboxMessage/Popover.js +31 -0
  43. package/lib/components/InboxMessage/Popover.js.map +1 -0
  44. package/lib/components/InboxMessage/RightSidebar.d.ts +9 -0
  45. package/lib/components/InboxMessage/RightSidebar.d.ts.map +1 -0
  46. package/lib/components/InboxMessage/RightSidebar.js +9 -0
  47. package/lib/components/InboxMessage/RightSidebar.js.map +1 -0
  48. package/lib/components/InboxMessage/RightSidebarAi.d.ts +23 -0
  49. package/lib/components/InboxMessage/RightSidebarAi.d.ts.map +1 -0
  50. package/lib/components/InboxMessage/RightSidebarAi.js +9 -0
  51. package/lib/components/InboxMessage/RightSidebarAi.js.map +1 -0
  52. package/lib/components/InboxMessage/ServiceConversationItem.d.ts +12 -0
  53. package/lib/components/InboxMessage/ServiceConversationItem.d.ts.map +1 -0
  54. package/lib/components/InboxMessage/ServiceConversationItem.js +185 -0
  55. package/lib/components/InboxMessage/ServiceConversationItem.js.map +1 -0
  56. package/lib/components/InboxMessage/ServiceInboxItem.d.ts +12 -0
  57. package/lib/components/InboxMessage/ServiceInboxItem.d.ts.map +1 -0
  58. package/lib/components/InboxMessage/ServiceInboxItem.js +182 -0
  59. package/lib/components/InboxMessage/ServiceInboxItem.js.map +1 -0
  60. package/lib/components/InboxMessage/SubscriptionHandler.d.ts +19 -0
  61. package/lib/components/InboxMessage/SubscriptionHandler.d.ts.map +1 -0
  62. package/lib/components/InboxMessage/SubscriptionHandler.js +41 -0
  63. package/lib/components/InboxMessage/SubscriptionHandler.js.map +1 -0
  64. package/lib/components/InboxMessage/UploadImageButton.d.ts +7 -0
  65. package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -0
  66. package/lib/components/InboxMessage/UploadImageButton.js +34 -0
  67. package/lib/components/InboxMessage/UploadImageButton.js.map +1 -0
  68. package/lib/components/InboxMessage/UserModalContent.d.ts +3 -0
  69. package/lib/components/InboxMessage/UserModalContent.d.ts.map +1 -0
  70. package/lib/components/InboxMessage/UserModalContent.js +60 -0
  71. package/lib/components/InboxMessage/UserModalContent.js.map +1 -0
  72. package/lib/components/InboxMessage/index.d.ts +17 -0
  73. package/lib/components/InboxMessage/index.d.ts.map +1 -0
  74. package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts +11 -0
  75. package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -0
  76. package/lib/components/InboxMessage/message-widgets/CommonMessage.js +44 -0
  77. package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -0
  78. package/lib/components/InboxMessage/message-widgets/ErrorFixCard.d.ts +11 -0
  79. package/lib/components/InboxMessage/message-widgets/ErrorFixCard.d.ts.map +1 -0
  80. package/lib/components/InboxMessage/message-widgets/ErrorFixCard.js +194 -0
  81. package/lib/components/InboxMessage/message-widgets/ErrorFixCard.js.map +1 -0
  82. package/lib/components/InboxMessage/message-widgets/MessageCard.d.ts +8 -0
  83. package/lib/components/InboxMessage/message-widgets/MessageCard.d.ts.map +1 -0
  84. package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.d.ts +12 -0
  85. package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.d.ts.map +1 -0
  86. package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.js +37 -0
  87. package/lib/components/InboxMessage/message-widgets/MessageSliceRenderer.js.map +1 -0
  88. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +18 -0
  89. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
  90. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1082 -0
  91. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
  92. package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts +8 -0
  93. package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -0
  94. package/lib/components/InboxMessage/message-widgets/PlainMessage.js +14 -0
  95. package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -0
  96. package/lib/components/InboxMessage/message-widgets/PropertyMessageWidget.d.ts +9 -0
  97. package/lib/components/InboxMessage/message-widgets/PropertyMessageWidget.d.ts.map +1 -0
  98. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +14 -0
  99. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -0
  100. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +333 -0
  101. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -0
  102. package/lib/components/InboxMessage/message-widgets/index.d.ts +4 -0
  103. package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -0
  104. package/lib/components/ModelConfigPanel.d.ts +37 -0
  105. package/lib/components/ModelConfigPanel.d.ts.map +1 -0
  106. package/lib/components/ModelConfigPanel.js +317 -0
  107. package/lib/components/ModelConfigPanel.js.map +1 -0
  108. package/lib/components/filler-components/RightSiderBar.d.ts +24 -0
  109. package/lib/components/filler-components/RightSiderBar.d.ts.map +1 -0
  110. package/lib/components/filler-components/RightSiderBar.js +335 -0
  111. package/lib/components/filler-components/RightSiderBar.js.map +1 -0
  112. package/lib/components/inbox/FilesList.d.ts +20 -0
  113. package/lib/components/inbox/FilesList.d.ts.map +1 -0
  114. package/lib/components/inbox/FilesList.js +68 -0
  115. package/lib/components/inbox/FilesList.js.map +1 -0
  116. package/lib/components/inbox/MessageItem.d.ts +17 -0
  117. package/lib/components/inbox/MessageItem.d.ts.map +1 -0
  118. package/lib/components/inbox/MessageItem.js +50 -0
  119. package/lib/components/inbox/MessageItem.js.map +1 -0
  120. package/lib/components/inbox/ThreadItem.d.ts +11 -0
  121. package/lib/components/inbox/ThreadItem.d.ts.map +1 -0
  122. package/lib/components/inbox/ThreadItem.js +147 -0
  123. package/lib/components/inbox/ThreadItem.js.map +1 -0
  124. package/lib/components/inbox/index.d.ts +4 -0
  125. package/lib/components/inbox/index.d.ts.map +1 -0
  126. package/lib/components/index.d.ts +7 -0
  127. package/lib/components/index.d.ts.map +1 -0
  128. package/lib/components/live-code-editor/hybrid-live-editor.d.ts +20 -0
  129. package/lib/components/live-code-editor/hybrid-live-editor.d.ts.map +1 -0
  130. package/lib/components/live-code-editor/hybrid-live-editor.js +68 -0
  131. package/lib/components/live-code-editor/hybrid-live-editor.js.map +1 -0
  132. package/lib/components/live-code-editor/index.d.ts +4 -0
  133. package/lib/components/live-code-editor/index.d.ts.map +1 -0
  134. package/lib/components/live-code-editor/live-code-editor.d.ts +14 -0
  135. package/lib/components/live-code-editor/live-code-editor.d.ts.map +1 -0
  136. package/lib/components/live-code-editor/live-code-editor.js +207 -0
  137. package/lib/components/live-code-editor/live-code-editor.js.map +1 -0
  138. package/lib/components/slot-fill/chat-message-filler.d.ts +4 -0
  139. package/lib/components/slot-fill/chat-message-filler.d.ts.map +1 -0
  140. package/lib/components/slot-fill/chat-message-filler.js +5 -0
  141. package/lib/components/slot-fill/chat-message-filler.js.map +1 -0
  142. package/lib/components/slot-fill/chat-message-slot.d.ts +11 -0
  143. package/lib/components/slot-fill/chat-message-slot.d.ts.map +1 -0
  144. package/lib/components/slot-fill/chat-message-slot.js +6 -0
  145. package/lib/components/slot-fill/chat-message-slot.js.map +1 -0
  146. package/lib/components/slot-fill/index.d.ts +4 -0
  147. package/lib/components/slot-fill/index.d.ts.map +1 -0
  148. package/lib/components/slot-fill/right-sidebar-filler.d.ts +4 -0
  149. package/lib/components/slot-fill/right-sidebar-filler.d.ts.map +1 -0
  150. package/lib/components/slot-fill/right-sidebar-filler.js +13 -0
  151. package/lib/components/slot-fill/right-sidebar-filler.js.map +1 -0
  152. package/lib/components/ui/button.d.ts +9 -0
  153. package/lib/components/ui/button.d.ts.map +1 -0
  154. package/lib/compute.d.ts +8 -0
  155. package/lib/compute.d.ts.map +1 -0
  156. package/lib/compute.js +137 -0
  157. package/lib/compute.js.map +1 -0
  158. package/lib/config/env-config.d.ts +13 -0
  159. package/lib/config/env-config.d.ts.map +1 -0
  160. package/lib/config/env-config.js +34 -0
  161. package/lib/config/env-config.js.map +1 -0
  162. package/lib/config/index.d.ts +2 -0
  163. package/lib/config/index.d.ts.map +1 -0
  164. package/lib/constants/breakpoints.d.ts +8 -0
  165. package/lib/constants/breakpoints.d.ts.map +1 -0
  166. package/lib/constants/index.d.ts +3 -0
  167. package/lib/constants/index.d.ts.map +1 -0
  168. package/lib/container/AiInbox.d.ts +15 -0
  169. package/lib/container/AiInbox.d.ts.map +1 -0
  170. package/lib/container/AiInboxWithLoader.d.ts +36 -0
  171. package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
  172. package/lib/container/AiLandingInput.d.ts +4 -0
  173. package/lib/container/AiLandingInput.d.ts.map +1 -0
  174. package/lib/container/AiLandingInput.js +101 -0
  175. package/lib/container/AiLandingInput.js.map +1 -0
  176. package/lib/container/Inbox.d.ts +15 -0
  177. package/lib/container/Inbox.d.ts.map +1 -0
  178. package/lib/container/Inbox.js +955 -0
  179. package/lib/container/Inbox.js.map +1 -0
  180. package/lib/container/InboxAiMessagesLoader.d.ts +15 -0
  181. package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
  182. package/lib/container/InboxAiMessagesLoader.js +30 -0
  183. package/lib/container/InboxAiMessagesLoader.js.map +1 -0
  184. package/lib/container/InboxContainer.d.ts +12 -0
  185. package/lib/container/InboxContainer.d.ts.map +1 -0
  186. package/lib/container/InboxContainer.js +31 -0
  187. package/lib/container/InboxContainer.js.map +1 -0
  188. package/lib/container/InboxTemplate1.d.ts +15 -0
  189. package/lib/container/InboxTemplate1.d.ts.map +1 -0
  190. package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
  191. package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
  192. package/lib/container/InboxTemplate2.d.ts +15 -0
  193. package/lib/container/InboxTemplate2.d.ts.map +1 -0
  194. package/lib/container/InboxWithAiLoader.d.ts +15 -0
  195. package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
  196. package/lib/container/InboxWithAiLoader.js +56 -0
  197. package/lib/container/InboxWithAiLoader.js.map +1 -0
  198. package/lib/container/InboxWithLoader.d.ts +36 -0
  199. package/lib/container/InboxWithLoader.d.ts.map +1 -0
  200. package/lib/container/InboxWithLoader.js +277 -0
  201. package/lib/container/InboxWithLoader.js.map +1 -0
  202. package/lib/container/ServiceInbox.d.ts +9 -0
  203. package/lib/container/ServiceInbox.d.ts.map +1 -0
  204. package/lib/container/ServiceInbox.js +144 -0
  205. package/lib/container/ServiceInbox.js.map +1 -0
  206. package/lib/container/ThreadMessages.d.ts +13 -0
  207. package/lib/container/ThreadMessages.d.ts.map +1 -0
  208. package/lib/container/ThreadMessages.js +314 -0
  209. package/lib/container/ThreadMessages.js.map +1 -0
  210. package/lib/container/ThreadMessagesInbox.d.ts +14 -0
  211. package/lib/container/ThreadMessagesInbox.d.ts.map +1 -0
  212. package/lib/container/ThreadMessagesInbox.js +341 -0
  213. package/lib/container/ThreadMessagesInbox.js.map +1 -0
  214. package/lib/container/Threads.d.ts +8 -0
  215. package/lib/container/Threads.d.ts.map +1 -0
  216. package/lib/container/Threads.js +231 -0
  217. package/lib/container/Threads.js.map +1 -0
  218. package/lib/container/ThreadsInbox.d.ts +21 -0
  219. package/lib/container/ThreadsInbox.d.ts.map +1 -0
  220. package/lib/container/ThreadsInbox.js +244 -0
  221. package/lib/container/ThreadsInbox.js.map +1 -0
  222. package/lib/container/apply-footer-styles.d.ts +2 -0
  223. package/lib/container/apply-footer-styles.d.ts.map +1 -0
  224. package/lib/container/apply-footer-styles.js +16 -0
  225. package/lib/container/apply-footer-styles.js.map +1 -0
  226. package/lib/container/index.d.ts +13 -0
  227. package/lib/container/index.d.ts.map +1 -0
  228. package/lib/enums/index.d.ts +2 -0
  229. package/lib/enums/index.d.ts.map +1 -0
  230. package/lib/enums/messenger-slot-fill-name-enum.d.ts +5 -0
  231. package/lib/enums/messenger-slot-fill-name-enum.d.ts.map +1 -0
  232. package/lib/enums/messenger-slot-fill-name-enum.js +5 -0
  233. package/lib/enums/messenger-slot-fill-name-enum.js.map +1 -0
  234. package/lib/hooks/index.d.ts +3 -0
  235. package/lib/hooks/index.d.ts.map +1 -0
  236. package/lib/hooks/use-file-sync.d.ts +16 -0
  237. package/lib/hooks/use-file-sync.d.ts.map +1 -0
  238. package/lib/hooks/use-file-sync.js +63 -0
  239. package/lib/hooks/use-file-sync.js.map +1 -0
  240. package/lib/hooks/usePersistentModelConfig.d.ts +15 -0
  241. package/lib/hooks/usePersistentModelConfig.d.ts.map +1 -0
  242. package/lib/hooks/usePersistentModelConfig.js +46 -0
  243. package/lib/hooks/usePersistentModelConfig.js.map +1 -0
  244. package/lib/index.d.ts +10 -0
  245. package/lib/index.d.ts.map +1 -0
  246. package/lib/index.js +1 -0
  247. package/lib/index.js.map +1 -0
  248. package/lib/interfaces/index.d.ts +2 -0
  249. package/lib/interfaces/index.d.ts.map +1 -0
  250. package/lib/interfaces/message-widgets.interface.d.ts +21 -0
  251. package/lib/interfaces/message-widgets.interface.d.ts.map +1 -0
  252. package/lib/machines/aiAgentMachine.d.ts +3 -0
  253. package/lib/machines/aiAgentMachine.d.ts.map +1 -0
  254. package/lib/machines/aiAgentMachine.js +1083 -0
  255. package/lib/machines/aiAgentMachine.js.map +1 -0
  256. package/lib/machines/aiAgentMachine.simple.d.ts +3 -0
  257. package/lib/machines/aiAgentMachine.simple.d.ts.map +1 -0
  258. package/lib/machines/aiAgentMachine.simple.js +108 -0
  259. package/lib/machines/aiAgentMachine.simple.js.map +1 -0
  260. package/lib/machines/index.d.ts +3 -0
  261. package/lib/machines/index.d.ts.map +1 -0
  262. package/lib/machines/types.d.ts +77 -0
  263. package/lib/machines/types.d.ts.map +1 -0
  264. package/lib/module.d.ts +7 -0
  265. package/lib/module.d.ts.map +1 -0
  266. package/lib/module.js +26 -0
  267. package/lib/module.js.map +1 -0
  268. package/lib/routes.json +98 -0
  269. package/lib/styles/responsive.css +76 -0
  270. package/lib/templates/InboxWithAi.d.ts +15 -0
  271. package/lib/templates/InboxWithAi.d.ts.map +1 -0
  272. package/lib/templates/InboxWithAi.js +440 -0
  273. package/lib/templates/InboxWithAi.js.map +1 -0
  274. package/lib/templates/InboxWithAi.tsx +533 -0
  275. package/lib/templates/index.d.ts +2 -0
  276. package/lib/templates/index.d.ts.map +1 -0
  277. package/lib/templates/index.ts +1 -0
  278. package/lib/utils/utils.d.ts +2 -0
  279. package/lib/utils/utils.d.ts.map +1 -0
  280. package/lib/utils/utils.js +3 -0
  281. package/lib/utils/utils.js.map +1 -0
  282. package/package.json +62 -0
  283. package/rollup.config.mjs +35 -0
  284. package/src/cdm-locales/en/translations.json +31 -0
  285. package/src/cdm-locales/es/translations.json +31 -0
  286. package/src/components/AIAgent/AIAgent.tsx +1103 -0
  287. package/src/components/AIAgent/AIAgent.tsx.bk +1365 -0
  288. package/src/components/AIAgent/README.md +82 -0
  289. package/src/components/AIAgent/index.ts +1 -0
  290. package/src/components/InboxMessage/CommonMessage.tsx +40 -0
  291. package/src/components/InboxMessage/ConversationItem.tsx +255 -0
  292. package/src/components/InboxMessage/InputComponent.tsx +462 -0
  293. package/src/components/InboxMessage/LeftSidebar.tsx +140 -0
  294. package/src/components/InboxMessage/MessageInput.tsx +209 -0
  295. package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
  296. package/src/components/InboxMessage/Messages.tsx +137 -0
  297. package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
  298. package/src/components/InboxMessage/Popover.tsx +42 -0
  299. package/src/components/InboxMessage/RightSidebar.tsx +22 -0
  300. package/src/components/InboxMessage/RightSidebarAi.tsx +37 -0
  301. package/src/components/InboxMessage/ServiceConversationItem.tsx +234 -0
  302. package/src/components/InboxMessage/ServiceInboxItem.tsx +223 -0
  303. package/src/components/InboxMessage/SubscriptionHandler.tsx +55 -0
  304. package/src/components/InboxMessage/UploadImageButton.tsx +46 -0
  305. package/src/components/InboxMessage/UserModalContent.tsx +60 -0
  306. package/src/components/InboxMessage/index.ts +16 -0
  307. package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +69 -0
  308. package/src/components/InboxMessage/message-widgets/ErrorFixCard.tsx +240 -0
  309. package/src/components/InboxMessage/message-widgets/MessageCard.tsx +127 -0
  310. package/src/components/InboxMessage/message-widgets/MessageSliceRenderer.tsx +40 -0
  311. package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1295 -0
  312. package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +18 -0
  313. package/src/components/InboxMessage/message-widgets/PropertyMessageWidget.tsx +29 -0
  314. package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +492 -0
  315. package/src/components/InboxMessage/message-widgets/index.ts +3 -0
  316. package/src/components/ModelConfigPanel.tsx +345 -0
  317. package/src/components/filler-components/RightSiderBar.tsx +408 -0
  318. package/src/components/inbox/FilesList.tsx +89 -0
  319. package/src/components/inbox/MessageItem.tsx +50 -0
  320. package/src/components/inbox/ThreadItem.tsx +295 -0
  321. package/src/components/inbox/index.ts +3 -0
  322. package/src/components/index.ts +22 -0
  323. package/src/components/live-code-editor/hybrid-live-editor.tsx +105 -0
  324. package/src/components/live-code-editor/index.ts +3 -0
  325. package/src/components/live-code-editor/live-code-editor.tsx +257 -0
  326. package/src/components/slot-fill/chat-message-filler.tsx +18 -0
  327. package/src/components/slot-fill/chat-message-slot.tsx +18 -0
  328. package/src/components/slot-fill/index.ts +3 -0
  329. package/src/components/slot-fill/right-sidebar-filler.tsx +39 -0
  330. package/src/components/ui/button.tsx +32 -0
  331. package/src/compute.ts +134 -0
  332. package/src/config/env-config.ts +17 -0
  333. package/src/config/index.ts +1 -0
  334. package/src/constants/breakpoints.ts +7 -0
  335. package/src/constants/index.ts +5 -0
  336. package/src/container/AiInbox.tsx +1819 -0
  337. package/src/container/AiInboxWithLoader.tsx +356 -0
  338. package/src/container/AiLandingInput.tsx +221 -0
  339. package/src/container/Inbox.tsx +1092 -0
  340. package/src/container/InboxAiMessagesLoader.tsx +44 -0
  341. package/src/container/InboxContainer.tsx +35 -0
  342. package/src/container/InboxTemplate1.tsx +1542 -0
  343. package/src/container/InboxTemplate1WithLoader.tsx +338 -0
  344. package/src/container/InboxTemplate2.tsx +1606 -0
  345. package/src/container/InboxWithAiLoader.tsx +76 -0
  346. package/src/container/InboxWithLoader.tsx +341 -0
  347. package/src/container/ServiceInbox.tsx +190 -0
  348. package/src/container/ThreadMessages.tsx +371 -0
  349. package/src/container/ThreadMessagesInbox.tsx +450 -0
  350. package/src/container/Threads.tsx +270 -0
  351. package/src/container/ThreadsInbox.tsx +354 -0
  352. package/src/container/apply-footer-styles.ts +17 -0
  353. package/src/container/index.ts +31 -0
  354. package/src/enums/index.ts +1 -0
  355. package/src/enums/messenger-slot-fill-name-enum.ts +4 -0
  356. package/src/hooks/index.ts +2 -0
  357. package/src/hooks/use-file-sync.ts +91 -0
  358. package/src/hooks/usePersistentModelConfig.ts +63 -0
  359. package/src/index.ts +37 -0
  360. package/src/interfaces/index.ts +1 -0
  361. package/src/interfaces/message-widgets.interface.ts +21 -0
  362. package/src/machines/aiAgentMachine.simple.ts +89 -0
  363. package/src/machines/aiAgentMachine.ts +1296 -0
  364. package/src/machines/aiAgentMachine.ts.bk +1296 -0
  365. package/src/machines/index.ts +2 -0
  366. package/src/machines/types.ts +59 -0
  367. package/src/module.tsx +32 -0
  368. package/src/styles/responsive.css +76 -0
  369. package/src/templates/InboxWithAi.tsx +533 -0
  370. package/src/templates/index.ts +1 -0
  371. package/src/utils/utils.ts +3 -0
  372. package/tsconfig.json +14 -0
  373. package/webpack.config.js +92 -0
@@ -0,0 +1,1295 @@
1
+ import React, { useEffect } from 'react';
2
+ import { format, differenceInMinutes } from 'date-fns';
3
+ import { IAuthUser, IPost, ISandboxError } from 'common';
4
+ import { FilesList } from '../../inbox';
5
+ import { ErrorFixCard } from './ErrorFixCard';
6
+ import ReactMarkdown from 'react-markdown';
7
+ import remarkGfm from 'remark-gfm';
8
+
9
+ // Enhanced CSS styles for HTML content rendering with prettification
10
+ const htmlContentStyles = `
11
+ .html-content {
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
13
+ line-height: 1.6;
14
+ color: #374151;
15
+ }
16
+
17
+ .html-content h1, .html-content h2, .html-content h3, .html-content h4, .html-content h5, .html-content h6 {
18
+ margin-top: 1.5rem;
19
+ margin-bottom: 1rem;
20
+ font-weight: 600;
21
+ line-height: 1.25;
22
+ color: #111827;
23
+ }
24
+
25
+ .html-content h1 {
26
+ font-size: 1.875rem;
27
+ border-bottom: 2px solid #e5e7eb;
28
+ padding-bottom: 0.5rem;
29
+ }
30
+
31
+ .html-content h2 {
32
+ font-size: 1.5rem;
33
+ border-bottom: 1px solid #e5e7eb;
34
+ padding-bottom: 0.375rem;
35
+ }
36
+
37
+ .html-content h3 {
38
+ font-size: 1.25rem;
39
+ }
40
+
41
+ .html-content p {
42
+ margin-bottom: 1rem;
43
+ line-height: 1.7;
44
+ }
45
+
46
+ .html-content ul, .html-content ol {
47
+ margin-bottom: 1rem;
48
+ padding-left: 1.5rem;
49
+ }
50
+
51
+ .html-content ul {
52
+ list-style-type: disc;
53
+ }
54
+
55
+ .html-content ol {
56
+ list-style-type: decimal;
57
+ }
58
+
59
+ .html-content li {
60
+ margin-bottom: 0.5rem;
61
+ line-height: 1.6;
62
+ }
63
+
64
+ .html-content li > ul, .html-content li > ol {
65
+ margin-top: 0.5rem;
66
+ margin-bottom: 0.5rem;
67
+ }
68
+
69
+ .html-content a {
70
+ color: #2563eb;
71
+ text-decoration: none;
72
+ border-bottom: 1px solid transparent;
73
+ transition: all 0.2s ease;
74
+ }
75
+
76
+ .html-content a:hover {
77
+ color: #1d4ed8;
78
+ border-bottom-color: #1d4ed8;
79
+ }
80
+
81
+ .html-content strong, .html-content b {
82
+ font-weight: 600;
83
+ color: #111827;
84
+ }
85
+
86
+ .html-content em, .html-content i {
87
+ font-style: italic;
88
+ color: #6b7280;
89
+ }
90
+
91
+ .html-content code {
92
+ background-color: #f3f4f6;
93
+ padding: 0.25rem 0.5rem;
94
+ border-radius: 0.375rem;
95
+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
96
+ font-size: 0.875rem;
97
+ color: #dc2626;
98
+ border: 1px solid #e5e7eb;
99
+ }
100
+
101
+ .html-content pre {
102
+ background-color: #f9fafb;
103
+ padding: 1rem;
104
+ border-radius: 0.5rem;
105
+ overflow-x: auto;
106
+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
107
+ font-size: 0.875rem;
108
+ line-height: 1.5;
109
+ border: 1px solid #e5e7eb;
110
+ margin: 1.5rem 0;
111
+ }
112
+
113
+ .html-content pre code {
114
+ background-color: transparent;
115
+ padding: 0;
116
+ border: none;
117
+ color: #374151;
118
+ font-size: inherit;
119
+ }
120
+
121
+ .html-content blockquote {
122
+ border-left: 4px solid #3b82f6;
123
+ padding-left: 1rem;
124
+ margin: 1.5rem 0;
125
+ font-style: italic;
126
+ color: #6b7280;
127
+ background-color: #f8fafc;
128
+ padding: 1rem;
129
+ border-radius: 0.375rem;
130
+ }
131
+
132
+ .html-content blockquote p {
133
+ margin-bottom: 0;
134
+ }
135
+
136
+ .html-content table {
137
+ border-collapse: collapse;
138
+ border: 1px solid #e5e7eb;
139
+ width: 100%;
140
+ margin: 1.5rem 0;
141
+ border-radius: 0.5rem;
142
+ overflow: hidden;
143
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
144
+ }
145
+
146
+ .html-content th,
147
+ .html-content td {
148
+ border: 1px solid #e5e7eb;
149
+ padding: 0.75rem;
150
+ text-align: left;
151
+ vertical-align: top;
152
+ }
153
+
154
+ .html-content th {
155
+ background-color: #f9fafb;
156
+ font-weight: 600;
157
+ color: #111827;
158
+ border-bottom: 2px solid #e5e7eb;
159
+ }
160
+
161
+ .html-content tr:nth-child(even) {
162
+ background-color: #f9fafb;
163
+ }
164
+
165
+ .html-content tr:hover {
166
+ background-color: #f3f4f6;
167
+ }
168
+
169
+ .html-content hr {
170
+ border: none;
171
+ border-top: 2px solid #e5e7eb;
172
+ margin: 2rem 0;
173
+ }
174
+
175
+ .html-content img {
176
+ max-width: 100%;
177
+ height: auto;
178
+ border-radius: 0.5rem;
179
+ margin: 1rem 0;
180
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
181
+ }
182
+
183
+ /* Enhanced message container styling */
184
+ .message-container {
185
+ background: #ffffff;
186
+ padding-top: 16px;
187
+ padding-bottom: 16px;
188
+ margin: 12px 0;
189
+ transition: all 0.2s ease-in-out;
190
+ }
191
+
192
+ /* Markdown content styling */
193
+ .markdown-content {
194
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
195
+ line-height: 1.6;
196
+ color: #374151;
197
+ }
198
+
199
+ .markdown-content h1 {
200
+ font-size: 1.5rem;
201
+ font-weight: 700;
202
+ margin-top: 1.5rem;
203
+ margin-bottom: 1rem;
204
+ color: #111827;
205
+ padding-bottom: 0.5rem;
206
+ border-bottom: 2px solid #e5e7eb;
207
+ }
208
+
209
+ .markdown-content h2 {
210
+ font-size: 1.25rem;
211
+ font-weight: 600;
212
+ margin-top: 1.25rem;
213
+ margin-bottom: 0.75rem;
214
+ color: #1f2937;
215
+ padding-bottom: 0.375rem;
216
+ border-bottom: 1px solid #e5e7eb;
217
+ }
218
+
219
+ .markdown-content h3 {
220
+ font-size: 1.125rem;
221
+ font-weight: 600;
222
+ margin-top: 1rem;
223
+ margin-bottom: 0.5rem;
224
+ color: #374151;
225
+ }
226
+
227
+ .markdown-content p {
228
+ margin-bottom: 0.75rem;
229
+ line-height: 1.6;
230
+ color: #4b5563;
231
+ }
232
+
233
+ .markdown-content ul, .markdown-content ol {
234
+ margin: 1rem 0;
235
+ padding-left: 1.5rem;
236
+ }
237
+
238
+ .markdown-content li {
239
+ margin-bottom: 0.5rem;
240
+ line-height: 1.6;
241
+ }
242
+
243
+ .markdown-content code {
244
+ background-color: #f3f4f6;
245
+ padding: 0.125rem 0.375rem;
246
+ border-radius: 0.25rem;
247
+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
248
+ font-size: 0.875rem;
249
+ color: #dc2626;
250
+ border: 1px solid #e5e7eb;
251
+ }
252
+
253
+ .markdown-content pre {
254
+ color: #1f2937;
255
+ border-radius: 8px;
256
+ overflow-x: auto;
257
+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
258
+ font-size: 0.875rem;
259
+ line-height: 1.5;
260
+ margin: 1rem 0;
261
+ }
262
+
263
+ .markdown-content pre code {
264
+ background-color: transparent;
265
+ padding: 0;
266
+ border: none;
267
+ color: #1f2937;
268
+ font-size: inherit;
269
+ }
270
+
271
+ .markdown-content blockquote {
272
+ border-left: 4px solid #3b82f6;
273
+ background-color: #f8fafc;
274
+ padding: 1rem;
275
+ margin: 1rem 0;
276
+ border-radius: 6px;
277
+ font-style: italic;
278
+ color: #475569;
279
+ border-top: 1px solid #e5e7eb;
280
+ border-right: 1px solid #e5e7eb;
281
+ border-bottom: 1px solid #e5e7eb;
282
+ }
283
+
284
+ .markdown-content table {
285
+ border-collapse: collapse;
286
+ border: 1px solid #e5e7eb;
287
+ width: 100%;
288
+ margin: 1rem 0;
289
+ border-radius: 8px;
290
+ overflow: hidden;
291
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
292
+ }
293
+
294
+ .markdown-content th {
295
+ background-color: #f9fafb;
296
+ color: #374151;
297
+ font-weight: 600;
298
+ padding: 0.75rem;
299
+ text-align: left;
300
+ border-bottom: 1px solid #e5e7eb;
301
+ font-size: 0.875rem;
302
+ }
303
+
304
+ .markdown-content td {
305
+ border: 1px solid #e5e7eb;
306
+ padding: 0.75rem;
307
+ text-align: left;
308
+ vertical-align: top;
309
+ background-color: white;
310
+ font-size: 0.875rem;
311
+ }
312
+
313
+ .markdown-content tr:nth-child(even) td {
314
+ background-color: #f9fafb;
315
+ }
316
+
317
+ .markdown-content tr:hover td {
318
+ background-color: #f3f4f6;
319
+ }
320
+
321
+ /* Enhanced list styling */
322
+ .markdown-content ul li {
323
+ position: relative;
324
+ padding-left: 0.5rem;
325
+ }
326
+
327
+ .markdown-content ul li::before {
328
+ content: "•";
329
+ color: #000;
330
+ font-weight: bold;
331
+ position: absolute;
332
+ left: -1rem;
333
+ }
334
+
335
+ .markdown-content ol li {
336
+ position: relative;
337
+ padding-left: 0.5rem;
338
+ }
339
+
340
+ .markdown-content ol li::before {
341
+ content: counter(list-item) ".";
342
+ font-weight: 600;
343
+ position: absolute;
344
+ left: -1.5rem;
345
+ }
346
+
347
+ /* Code block container styling */
348
+ .code-block-container {
349
+ background: #ffffff;
350
+ border: 1px solid #e5e7eb;
351
+ border-radius: 8px;
352
+ overflow: hidden;
353
+ margin: 1rem 0;
354
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
355
+ }
356
+
357
+ .code-block-header {
358
+ background: #f9fafb;
359
+ padding: 0.5rem 1rem;
360
+ border-bottom: 1px solid #e5e7eb;
361
+ font-weight: 600;
362
+ color: #374151;
363
+ font-size: 0.875rem;
364
+ text-transform: uppercase;
365
+ letter-spacing: 0.05em;
366
+ }
367
+
368
+ .code-block-content {
369
+ padding: 1rem;
370
+ overflow-x: auto;
371
+ }
372
+
373
+ .hover\:bg-gray-100:hover {
374
+ background-color: transparent !important;
375
+ }
376
+ `;
377
+
378
+ // Hook to inject CSS styles
379
+ const useInjectStyles = () => {
380
+ useEffect(() => {
381
+ // Check if styles are already injected
382
+ if (document.getElementById('html-content-styles')) {
383
+ return;
384
+ }
385
+
386
+ // Create and inject style element
387
+ const styleElement = document.createElement('style');
388
+ styleElement.id = 'html-content-styles';
389
+ styleElement.textContent = htmlContentStyles;
390
+ document.head.appendChild(styleElement);
391
+
392
+ // Cleanup function
393
+ return () => {
394
+ const existingStyle = document.getElementById('html-content-styles');
395
+ if (existingStyle) {
396
+ existingStyle.remove();
397
+ }
398
+ };
399
+ }, []);
400
+ };
401
+
402
+ interface ModernMessageGroupProps {
403
+ messages: IPost[];
404
+ currentUser: IAuthUser;
405
+ onOpen: (element?: any) => void;
406
+ onMessageClick: (msg: IPost) => void;
407
+ isDesktopView?: boolean;
408
+ isSmallScreen?: boolean;
409
+ sandboxErrors?: ISandboxError[];
410
+ currentFiles?: Record<string, string>;
411
+ onFixError?: (errorMessage: string) => Promise<void>;
412
+ onRecreateSandbox?: (fragmentId: string) => void;
413
+ }
414
+
415
+ interface MessageGroupProps {
416
+ author: any;
417
+ messages: IPost[];
418
+ currentUser: IAuthUser;
419
+ onOpen: (element?: any) => void;
420
+ onMessageClick: (msg: IPost) => void;
421
+ isDesktopView?: boolean;
422
+ isSmallScreen?: boolean;
423
+ }
424
+
425
+ // Enhanced utility function to group messages by user and time
426
+ export const groupMessagesByUserAndTime = (messages: IPost[], timeThresholdMinutes = 5): IPost[][] => {
427
+ if (!messages || messages.length === 0) return [];
428
+
429
+ const groups: IPost[][] = [];
430
+ let currentGroup: IPost[] = [];
431
+ let lastMessage: IPost | null = null;
432
+
433
+ for (const message of messages) {
434
+ if (typeof message === 'string') continue; // Skip date separators
435
+
436
+ const shouldStartNewGroup =
437
+ !lastMessage ||
438
+ lastMessage.author?.id !== message.author?.id ||
439
+ differenceInMinutes(new Date(message.createdAt), new Date(lastMessage.createdAt)) > timeThresholdMinutes;
440
+
441
+ if (shouldStartNewGroup) {
442
+ if (currentGroup.length > 0) {
443
+ groups.push(currentGroup);
444
+ }
445
+ currentGroup = [message];
446
+ } else {
447
+ currentGroup.push(message);
448
+ }
449
+
450
+ lastMessage = message;
451
+ }
452
+
453
+ if (currentGroup.length > 0) {
454
+ groups.push(currentGroup);
455
+ }
456
+
457
+ return groups;
458
+ };
459
+
460
+ // Enhanced content detection that properly identifies different content types
461
+ const detectContentType = (value: string): 'html' | 'markdown' | 'code' | 'text' => {
462
+ if (!value) return 'text';
463
+
464
+ const trimmed = value.trim();
465
+
466
+ // Check for code patterns first (most specific)
467
+ const codePatterns = [
468
+ /```[\s\S]*?```/g, // Fenced code blocks
469
+ /`[^`\n]+`/g, // Inline code
470
+ /---\s*\w+\.\w+\s*---/g, // File separators like "--- src/index.css ---"
471
+ /@tailwind\s+\w+/g, // Tailwind directives
472
+ /export\s+default\s*\{/g, // JS/TS exports
473
+ /import\s+.*\s+from\s+['"]/g, // Import statements
474
+ /\/\*\*[\s\S]*?\*\//g, // JSDoc comments
475
+ /\/\*[\s\S]*?\*\//g, // Block comments
476
+ /\/\/.*$/gm, // Line comments
477
+ ];
478
+
479
+ const hasCodePatterns = codePatterns.some((pattern) => pattern.test(trimmed));
480
+ if (hasCodePatterns) return 'code';
481
+
482
+ // Check for markdown patterns
483
+ const markdownPatterns = [
484
+ /^#{1,6}\s+/gm, // Headers
485
+ /\*\*.*?\*\*/g, // Bold
486
+ /\*.*?\*/g, // Italic
487
+ /^\s*[-*+]\s+/gm, // Lists
488
+ /^\s*\d+\.\s+/gm, // Numbered lists
489
+ /\[.*?\]\(.*?\)/g, // Links
490
+ /!\[.*?\]\(.*?\)/g, // Images
491
+ ];
492
+
493
+ const hasMarkdownPatterns = markdownPatterns.some((pattern) => pattern.test(trimmed));
494
+ if (hasMarkdownPatterns) return 'markdown';
495
+
496
+ // Check for HTML patterns
497
+ const htmlPatterns = [
498
+ /<\/?[a-z][\s\S]*>/i, // HTML tags
499
+ /&[a-z0-9#]+;/i, // HTML entities
500
+ /\s+[a-z-]+\s*=\s*["'][^"']*["']/i, // HTML attributes
501
+ /<[^>]+>[^<]*<\/[^>]+>/i, // HTML structure
502
+ ];
503
+
504
+ const hasHtmlPatterns = htmlPatterns.some((pattern) => pattern.test(trimmed));
505
+ if (hasHtmlPatterns) return 'html';
506
+
507
+ return 'text';
508
+ };
509
+
510
+ // Legacy function for backward compatibility
511
+ const isProbablyHTML = (value: string): boolean => {
512
+ return detectContentType(value) === 'html';
513
+ };
514
+
515
+ // Enhanced sanitizer that allows most HTML tags while maintaining security
516
+ const sanitizeHtml = (html: string): string => {
517
+ try {
518
+ if (typeof window === 'undefined' || typeof window.DOMParser === 'undefined') {
519
+ return html
520
+ .replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '')
521
+ .replace(/<style[\s\S]*?>[\s\S]*?<\/style>/gi, '')
522
+ .replace(/on\w+\s*=\s*"[^"]*"/gi, '')
523
+ .replace(/on\w+\s*=\s*'[^']*'/gi, '')
524
+ .replace(/on\w+\s*=\s*[^\s>]+/gi, '')
525
+ .replace(/javascript:/gi, '')
526
+ .replace(/data:text\/html/gi, '');
527
+ }
528
+
529
+ const parser = new window.DOMParser();
530
+ const doc = parser.parseFromString(html, 'text/html');
531
+
532
+ // Only remove the most dangerous tags
533
+ const dangerousTags = ['script', 'style'];
534
+ dangerousTags.forEach((tag) => {
535
+ doc.querySelectorAll(tag).forEach((el) => el.remove());
536
+ });
537
+
538
+ const walker = doc.createTreeWalker(doc.body, (NodeFilter as any).SHOW_ELEMENT);
539
+ let node = walker.nextNode() as Element | null;
540
+ while (node) {
541
+ Array.from(node.attributes).forEach((attr) => {
542
+ const name = attr.name.toLowerCase();
543
+ const value = (attr.value || '').toLowerCase();
544
+
545
+ // Remove event handlers and javascript protocols
546
+ if (name.startsWith('on') || value.startsWith('javascript:')) {
547
+ node?.removeAttribute(attr.name);
548
+ }
549
+
550
+ // Allow most attributes but validate URLs for src/href
551
+ if ((name === 'src' || name === 'href') && !/^https?:|^\/.*/.test(attr.value)) {
552
+ node?.removeAttribute(attr.name);
553
+ }
554
+ });
555
+ node = walker.nextNode() as Element | null;
556
+ }
557
+
558
+ return doc.body.innerHTML;
559
+ } catch (e) {
560
+ return html.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '');
561
+ }
562
+ };
563
+
564
+ // Function to prettify HTML content
565
+ const prettifyHtmlContent = (htmlContent: string): string => {
566
+ // Add semantic classes for better styling
567
+ let prettified = htmlContent;
568
+
569
+ // Enhance headings with better styling
570
+ prettified = prettified.replace(/<h([1-6])>/g, '<h$1 class="html-heading html-heading-$1">');
571
+
572
+ // Enhance lists with better styling
573
+ prettified = prettified.replace(/<ul>/g, '<ul class="html-list html-list-unordered">');
574
+ prettified = prettified.replace(/<ol>/g, '<ol class="html-list html-list-ordered">');
575
+
576
+ // Enhance paragraphs with better spacing
577
+ prettified = prettified.replace(/<p>/g, '<p class="html-paragraph">');
578
+
579
+ // Enhance code blocks
580
+ prettified = prettified.replace(/<code>/g, '<code class="html-inline-code">');
581
+ prettified = prettified.replace(/<pre>/g, '<pre class="html-code-block">');
582
+
583
+ // Enhance blockquotes
584
+ prettified = prettified.replace(/<blockquote>/g, '<blockquote class="html-blockquote">');
585
+
586
+ // Enhance tables
587
+ prettified = prettified.replace(/<table>/g, '<table class="html-table">');
588
+ prettified = prettified.replace(/<th>/g, '<th class="html-table-header">');
589
+ prettified = prettified.replace(/<td>/g, '<td class="html-table-cell">');
590
+
591
+ // Add info boxes for certain content patterns
592
+ prettified = prettified.replace(
593
+ /<p>(Note|Tip|Info|Warning|Error):\s*(.*?)<\/p>/gi,
594
+ '<div class="html-info-box"><strong>$1:</strong> $2</div>',
595
+ );
596
+
597
+ return prettified;
598
+ };
599
+
600
+ // Minimal Builder-like blocks renderer (text/image/button/columns)
601
+ const BuilderLikeRenderer: React.FC<{ blocks?: any[] }> = ({ blocks }) => {
602
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0) return null;
603
+
604
+ return (
605
+ <div className="space-y-3">
606
+ {blocks.map((block, idx) => {
607
+ const type = block?.['@type'] || block?.type;
608
+ if (!type) return null;
609
+
610
+ if (/text/i.test(type)) {
611
+ const html = sanitizeHtml(block?.text || block?.data?.text || '');
612
+ return (
613
+ <div
614
+ key={idx}
615
+ className="max-w-none text-gray-800"
616
+ dangerouslySetInnerHTML={{ __html: html }}
617
+ />
618
+ );
619
+ }
620
+
621
+ if (/image/i.test(type)) {
622
+ const src = block?.src || block?.image || block?.data?.src;
623
+ const alt = block?.alt || block?.data?.alt || '';
624
+ if (!src) return null;
625
+ return (
626
+ <div key={idx} className="rounded-lg overflow-hidden border border-gray-200">
627
+ <img className="w-full h-auto" src={src} alt={alt} />
628
+ </div>
629
+ );
630
+ }
631
+
632
+ if (/button/i.test(type)) {
633
+ const text = block?.text || block?.data?.text || 'Button';
634
+ const href = block?.href || block?.link || block?.data?.href || '#';
635
+ return (
636
+ <a
637
+ key={idx}
638
+ href={href}
639
+ target="_blank"
640
+ rel="noopener noreferrer"
641
+ className="inline-flex items-center px-3 py-1.5 rounded-md bg-blue-600 text-white text-sm hover:bg-blue-700"
642
+ >
643
+ {text}
644
+ </a>
645
+ );
646
+ }
647
+
648
+ if (/columns?/i.test(type)) {
649
+ const cols = block?.columns || block?.data?.columns || [];
650
+ return (
651
+ <div key={idx} className="grid grid-cols-1 sm:grid-cols-2 gap-3">
652
+ {cols.map((col: any, colIdx: number) => (
653
+ <div key={colIdx} className="space-y-2">
654
+ <BuilderLikeRenderer blocks={col?.blocks || col?.children} />
655
+ </div>
656
+ ))}
657
+ </div>
658
+ );
659
+ }
660
+
661
+ return (
662
+ <div key={idx} className="message-container">
663
+ <pre className="text-xs text-gray-600 overflow-x-auto">{JSON.stringify(block, null, 2)}</pre>
664
+ </div>
665
+ );
666
+ })}
667
+ </div>
668
+ );
669
+ };
670
+
671
+ // Enhanced code formatter for raw code content
672
+ const CodeFormatter: React.FC<{ content: string }> = ({ content }) => {
673
+ if (!content) return null;
674
+
675
+ // Split content by file separators and format each section
676
+ const sections = content.split(/(---\s*\w+\.\w+\s*---)/g);
677
+
678
+ return (
679
+ <div className="message-container">
680
+ <div className="space-y-4">
681
+ {sections.map((section, index) => {
682
+ if (!section.trim()) return null;
683
+
684
+ // Check if this is a file separator
685
+ const fileMatch = section.match(/---\s*(\w+\.\w+)\s*---/);
686
+ if (fileMatch) {
687
+ return (
688
+ <div key={index} className="code-block-container">
689
+ <div className="code-block-header">📄 {fileMatch[1]}</div>
690
+ </div>
691
+ );
692
+ }
693
+
694
+ // Format the code content
695
+ const lines = section.trim().split('\n');
696
+ const isCode = lines.some(
697
+ (line) =>
698
+ line.includes('@tailwind') ||
699
+ line.includes('export default') ||
700
+ line.includes('import ') ||
701
+ line.includes('{') ||
702
+ line.includes('}') ||
703
+ line.includes('//') ||
704
+ line.includes('/*'),
705
+ );
706
+
707
+ if (isCode) {
708
+ return (
709
+ <div key={index} className="code-block-container">
710
+ <div className="code-block-content">
711
+ <pre className="text-sm text-gray-900 font-mono leading-relaxed whitespace-pre-wrap">
712
+ <code>{section.trim()}</code>
713
+ </pre>
714
+ </div>
715
+ </div>
716
+ );
717
+ }
718
+
719
+ // Regular text content
720
+ return (
721
+ <div key={index} className="text-gray-700 leading-relaxed whitespace-pre-wrap">
722
+ {section.trim()}
723
+ </div>
724
+ );
725
+ })}
726
+ </div>
727
+ </div>
728
+ );
729
+ };
730
+
731
+ // Enhanced markdown renderer using react-markdown with remark-gfm
732
+ const FormattedMessageContent: React.FC<{ content: string }> = ({ content }) => {
733
+ if (!content) return null;
734
+
735
+ // Check if content contains markdown patterns
736
+ const hasMarkdown = /[#*`>|]/.test(content) || content.includes('```');
737
+
738
+ if (hasMarkdown) {
739
+ return (
740
+ <div className="message-container">
741
+ <div className="markdown-content">
742
+ <ReactMarkdown
743
+ remarkPlugins={[remarkGfm]}
744
+ components={{
745
+ // Custom styling for code blocks
746
+ code: ({ className, children, ...props }: any) => {
747
+ const match = /language-(\w+)/.exec(className || '');
748
+ const isInline = !className?.includes('language-');
749
+ return !isInline ? (
750
+ <div className="code-block-container">
751
+ <div className="code-block-header">{match?.[1] || 'code'}</div>
752
+ <div className="code-block-content">
753
+ <pre className="text-sm text-gray-900 font-mono leading-relaxed whitespace-pre-wrap">
754
+ <code className={className} {...props}>
755
+ {children}
756
+ </code>
757
+ </pre>
758
+ </div>
759
+ </div>
760
+ ) : (
761
+ <code
762
+ className="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono text-gray-800 border border-gray-200"
763
+ {...props}
764
+ >
765
+ {children}
766
+ </code>
767
+ );
768
+ },
769
+ // Custom styling for headings
770
+ h1: ({ children, ...props }) => (
771
+ <h1 className="text-xl font-bold text-gray-900 mb-3" {...props}>
772
+ {children}
773
+ </h1>
774
+ ),
775
+ h2: ({ children, ...props }) => (
776
+ <h2 className="text-lg font-semibold text-gray-800 mb-2" {...props}>
777
+ {children}
778
+ </h2>
779
+ ),
780
+ h3: ({ children, ...props }) => (
781
+ <h3 className="text-base font-medium text-gray-700 mb-2" {...props}>
782
+ {children}
783
+ </h3>
784
+ ),
785
+ // Custom styling for lists
786
+ ul: ({ children, ...props }) => (
787
+ <ul className="space-y-1" {...props}>
788
+ {children}
789
+ </ul>
790
+ ),
791
+ ol: ({ children, ...props }) => (
792
+ <ol className="space-y-1" {...props}>
793
+ {children}
794
+ </ol>
795
+ ),
796
+ li: ({ children, ...props }) => (
797
+ <li className="text-gray-700 leading-relaxed" {...props}>
798
+ {children}
799
+ </li>
800
+ ),
801
+ // Custom styling for blockquotes
802
+ blockquote: ({ children, ...props }) => (
803
+ <blockquote
804
+ className="border-l-4 border-blue-400 pl-3 py-2 bg-blue-50 rounded-r-md my-3"
805
+ {...props}
806
+ >
807
+ {children}
808
+ </blockquote>
809
+ ),
810
+ // Custom styling for tables
811
+ table: ({ children, ...props }) => (
812
+ <div className="overflow-x-auto my-3">
813
+ <table
814
+ className="min-w-full border border-gray-200 rounded-md overflow-hidden"
815
+ {...props}
816
+ >
817
+ {children}
818
+ </table>
819
+ </div>
820
+ ),
821
+ th: ({ children, ...props }) => (
822
+ <th
823
+ className="px-3 py-2 text-left font-medium text-gray-700 border border-gray-200"
824
+ {...props}
825
+ >
826
+ {children}
827
+ </th>
828
+ ),
829
+ td: ({ children, ...props }) => (
830
+ <td className="px-3 py-2 border border-gray-200 text-gray-700" {...props}>
831
+ {children}
832
+ </td>
833
+ ),
834
+ // Custom styling for task lists (from remark-gfm)
835
+ input: ({ checked, ...props }: any) => (
836
+ <input
837
+ type="checkbox"
838
+ checked={checked}
839
+ readOnly
840
+ className="mr-2 mt-1 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
841
+ {...props}
842
+ />
843
+ ),
844
+ // Custom styling for strikethrough (from remark-gfm)
845
+ del: ({ children, ...props }) => (
846
+ <del className="text-gray-500 line-through" {...props}>
847
+ {children}
848
+ </del>
849
+ ),
850
+ }}
851
+ >
852
+ {content}
853
+ </ReactMarkdown>
854
+ </div>
855
+ </div>
856
+ );
857
+ }
858
+
859
+ // For plain text content
860
+ return (
861
+ <div className="message-container">
862
+ <p className="text-gray-700 leading-relaxed whitespace-pre-wrap">{content}</p>
863
+ </div>
864
+ );
865
+ };
866
+
867
+ // Detect predominant text direction (RTL/LTR) for international content
868
+ const detectTextDirection = (text: string): 'rtl' | 'ltr' => {
869
+ if (!text) return 'ltr';
870
+ const rtlRanges = /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/g; // Hebrew, Arabic, etc.
871
+ const ltrRanges = /[A-Za-z\u00C0-\u024F\u1E00-\u1EFF]/g;
872
+ const rtlCount = (text.match(rtlRanges) || []).length;
873
+ const ltrCount = (text.match(ltrRanges) || []).length;
874
+ return rtlCount > ltrCount ? 'rtl' : 'ltr';
875
+ };
876
+
877
+ // Lightweight language heuristic for lang attribute
878
+ const detectLanguageTag = (text: string): string => {
879
+ if (!text) return 'en';
880
+ if (/\p{Script=Arabic}/u.test(text)) return 'ar';
881
+ if (/[\u0590-\u05FF]/.test(text)) return 'he';
882
+ if (/[\u0600-\u06FF]/.test(text)) return 'fa';
883
+ if (/[\u0900-\u097F]/.test(text)) return 'hi';
884
+ if (/[\u4E00-\u9FFF]/.test(text)) return 'zh';
885
+ if (/[\u3040-\u309F\u30A0-\u30FF]/.test(text)) return 'ja';
886
+ if (/[\uAC00-\uD7AF]/.test(text)) return 'ko';
887
+ if (/[\u0400-\u04FF]/.test(text)) return 'ru';
888
+ if (/[\u0E00-\u0E7F]/.test(text)) return 'th';
889
+ return 'en';
890
+ };
891
+
892
+ // Attempt to parse Builder.io-like JSON blocks embedded as message string
893
+ const tryExtractBuilderBlocks = (content?: string): any[] | null => {
894
+ if (!content || content.length < 2) return null;
895
+ try {
896
+ const trimmed = content.trim();
897
+ const jsonMatch = trimmed.match(/([\[{][\s\S]*[\]}])/);
898
+ const jsonText = jsonMatch ? jsonMatch[1] : trimmed;
899
+ const parsed = JSON.parse(jsonText);
900
+ if (Array.isArray(parsed)) {
901
+ if (parsed.length && (parsed[0]['@type'] || parsed[0].type)) return parsed;
902
+ } else if (parsed && typeof parsed === 'object') {
903
+ if (Array.isArray(parsed.blocks)) return parsed.blocks;
904
+ if (Array.isArray(parsed?.data?.blocks)) return parsed.data.blocks;
905
+ }
906
+ return null;
907
+ } catch {
908
+ return null;
909
+ }
910
+ };
911
+
912
+ const ModernMessageGroup: React.FC<MessageGroupProps> = ({
913
+ author,
914
+ messages,
915
+ currentUser,
916
+ onOpen,
917
+ onMessageClick,
918
+ isDesktopView = false,
919
+ isSmallScreen = false,
920
+ }) => {
921
+ // Inject CSS styles for HTML content
922
+ useInjectStyles();
923
+
924
+ const isOwnMessage = author?.id === currentUser?.id;
925
+ const authorName =
926
+ author?.givenName && author?.familyName
927
+ ? `${author.givenName} ${author.familyName}`
928
+ : author?.username || 'Unknown User';
929
+
930
+ const firstMessage = messages[0];
931
+ const formatTime = (timestamp: string) => {
932
+ const date = new Date(timestamp);
933
+ return format(date, 'h:mm a');
934
+ };
935
+
936
+ // Determine if this is an AI/system message for special styling
937
+ const isSystemMessage =
938
+ author?.username?.toLowerCase().includes('ai') ||
939
+ author?.username?.toLowerCase().includes('assistant') ||
940
+ author?.username?.toLowerCase().includes('system');
941
+
942
+ // For user messages, don't show group header, just individual messages with avatars
943
+ if (isOwnMessage) {
944
+ return (
945
+ <div
946
+ className={`min-h-fit ${
947
+ isDesktopView ? 'space-y-1 mb-3' : isSmallScreen ? 'space-y-0.5 mb-2' : 'space-y-0.5 mb-2'
948
+ }`}
949
+ >
950
+ {messages.map((message, index) => (
951
+ <ModernMessageBubble
952
+ key={message.id}
953
+ message={message}
954
+ isOwnMessage={isOwnMessage}
955
+ isSystemMessage={isSystemMessage}
956
+ isFirstInGroup={index === 0}
957
+ isLastInGroup={index === messages.length - 1}
958
+ onMessageClick={onMessageClick}
959
+ formatTime={formatTime}
960
+ />
961
+ ))}
962
+ </div>
963
+ );
964
+ }
965
+
966
+ // For other messages (non-user), show the traditional group layout
967
+ return (
968
+ <div
969
+ className={`group transition-all duration-300 ease-in-out ${
970
+ isDesktopView ? 'mb-4 px-4 py-3' : isSmallScreen ? 'mb-2 px-2 py-1' : 'mb-3 px-3 py-1'
971
+ } ${isSystemMessage ? 'bg-white rounded-lg' : ' rounded-lg'}`}
972
+ >
973
+ <div
974
+ className={`flex items-start ${
975
+ isDesktopView ? 'space-x-4' : isSmallScreen ? 'space-x-2' : 'space-x-3'
976
+ }`}
977
+ >
978
+ {/* Enhanced Avatar - Only show for non-system messages */}
979
+ {!isSystemMessage && (
980
+ <div className="flex-shrink-0 mt-1">
981
+ <div className="relative rounded-lg overflow-hidden">
982
+ <img
983
+ className={`cursor-pointer hover:opacity-80 transition-opacity ${
984
+ isDesktopView ? 'w-12 h-12' : isSmallScreen ? 'w-8 h-8' : 'w-10 h-10'
985
+ } rounded-lg object-cover`}
986
+ src={author?.picture || '/default-avatar.svg'}
987
+ alt={authorName}
988
+ onClick={() => onOpen(firstMessage)}
989
+ onError={(e) => {
990
+ e.currentTarget.src = '/default-avatar.svg';
991
+ }}
992
+ />
993
+ </div>
994
+ </div>
995
+ )}
996
+
997
+ <div className="flex-1 min-w-0 overflow-hidden">
998
+ {/* Enhanced author header - Only show for non-system messages */}
999
+ {!isSystemMessage && (
1000
+ <div className="flex items-center space-x-3 mb-2">
1001
+ <span className="font-semibold truncate text-gray-900">{authorName}</span>
1002
+ </div>
1003
+ )}
1004
+
1005
+ {/* Enhanced Messages with rich formatting */}
1006
+ <div className="space-y-1">
1007
+ {messages.map((message, index) => (
1008
+ <ModernMessageBubble
1009
+ key={message.id}
1010
+ message={message}
1011
+ isOwnMessage={isOwnMessage}
1012
+ isSystemMessage={isSystemMessage}
1013
+ isFirstInGroup={index === 0}
1014
+ isLastInGroup={index === messages.length - 1}
1015
+ onMessageClick={onMessageClick}
1016
+ formatTime={formatTime}
1017
+ />
1018
+ ))}
1019
+ </div>
1020
+ </div>
1021
+ </div>
1022
+ </div>
1023
+ );
1024
+ };
1025
+
1026
+ interface ModernMessageBubbleProps {
1027
+ message: IPost;
1028
+ isOwnMessage: boolean;
1029
+ isSystemMessage: boolean;
1030
+ isFirstInGroup: boolean;
1031
+ isLastInGroup: boolean;
1032
+ onMessageClick: (msg: IPost) => void;
1033
+ formatTime: (timestamp: string) => string;
1034
+ }
1035
+
1036
+ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1037
+ message,
1038
+ isOwnMessage,
1039
+ isSystemMessage,
1040
+ isFirstInGroup,
1041
+ isLastInGroup,
1042
+ onMessageClick,
1043
+ formatTime,
1044
+ }) => {
1045
+ const handleClick = () => {
1046
+ onMessageClick?.(message);
1047
+ };
1048
+
1049
+ const isAssistantRole = (message as any)?.propsConfiguration?.contents?.role === 'ASSISTANT';
1050
+
1051
+ // For user messages, create a right-aligned layout with avatar and name
1052
+ if (isOwnMessage) {
1053
+ const authorName =
1054
+ message.author?.givenName && message.author?.familyName
1055
+ ? `${message.author.givenName} ${message.author.familyName}`
1056
+ : message.author?.username || 'You';
1057
+
1058
+ return (
1059
+ <div
1060
+ className={`py-1 hover:bg-gray-50 hover:bg-opacity-50 rounded px-1 sm:px-2 -mx-1 sm:-mx-2 group ${
1061
+ isAssistantRole ? 'border border-gray-200' : ''
1062
+ }`}
1063
+ >
1064
+ <div className="flex items-start justify-end gap-2">
1065
+ {/* Message content and timestamp on the left */}
1066
+ {/* <div className="flex flex-col items-end max-w-xs lg:max-w-md"> */}
1067
+ <div className="flex flex-col items-end ">
1068
+ {!isAssistantRole && (
1069
+ <div className="flex items-end space-x-2 mb-0.5">
1070
+ <span className="text-sm font-semibold text-gray-900">{authorName}</span>
1071
+ </div>
1072
+ )}
1073
+
1074
+ <div
1075
+ className={`text-sm text-gray-900 ${
1076
+ isAssistantRole ? 'cursor-pointer' : ''
1077
+ } px-1 sm:px-2 py-1 rounded`}
1078
+ onClick={isAssistantRole ? handleClick : undefined}
1079
+ dir={detectTextDirection((message as any)?.message || '')}
1080
+ lang={detectLanguageTag((message as any)?.message || '')}
1081
+ >
1082
+ {message.message && (
1083
+ <div className="max-w-none">
1084
+ {(() => {
1085
+ const contentType = detectContentType(message.message);
1086
+
1087
+ if (contentType === 'code') {
1088
+ return <CodeFormatter content={message.message} />;
1089
+ } else if (contentType === 'html') {
1090
+ return (
1091
+ <div
1092
+ className="text-gray-800 html-content"
1093
+ dangerouslySetInnerHTML={{
1094
+ __html: prettifyHtmlContent(sanitizeHtml(message.message)),
1095
+ }}
1096
+ />
1097
+ );
1098
+ } else {
1099
+ return <FormattedMessageContent content={message.message} />;
1100
+ }
1101
+ })()}
1102
+ </div>
1103
+ )}
1104
+
1105
+ {tryExtractBuilderBlocks((message as any)?.message)?.length ? (
1106
+ <div className="mt-2">
1107
+ <BuilderLikeRenderer blocks={tryExtractBuilderBlocks((message as any)?.message)} />
1108
+ </div>
1109
+ ) : null}
1110
+
1111
+ {(message as any)?.props?.blocks?.length ? (
1112
+ <div className="mt-2">
1113
+ <BuilderLikeRenderer blocks={(message as any).props.blocks} />
1114
+ </div>
1115
+ ) : null}
1116
+
1117
+ {message.files?.totalCount > 0 && (
1118
+ <div className="mt-2">
1119
+ <FilesList uploaded files={message.files.data} />
1120
+ </div>
1121
+ )}
1122
+ </div>
1123
+ </div>
1124
+
1125
+ {/* User avatar on the right */}
1126
+ {!isAssistantRole && (
1127
+ <div className="flex-shrink-0 mt-0.5">
1128
+ <img
1129
+ className={`w-8 h-8 sm:w-10 sm:h-10 rounded-lg ${
1130
+ isAssistantRole ? '' : 'cursor-pointer hover:opacity-80'
1131
+ } transition-opacity object-cover`}
1132
+ src={message.author?.picture || '/default-avatar.svg'}
1133
+ alt={authorName}
1134
+ onClick={isAssistantRole ? undefined : handleClick}
1135
+ onError={(e) => {
1136
+ e.currentTarget.src = '/default-avatar.svg';
1137
+ }}
1138
+ />
1139
+ </div>
1140
+ )}
1141
+ </div>
1142
+ </div>
1143
+ );
1144
+ }
1145
+
1146
+ // For other messages (left-aligned with full formatting)
1147
+ return (
1148
+ <div
1149
+ className={`group/message transition-all duration-200 hover:bg-gray-50 rounded-lg px-3 py-1 -mx-3 ${
1150
+ isSystemMessage || isAssistantRole ? '' : 'cursor-pointer'
1151
+ }`}
1152
+ onClick={isSystemMessage || isAssistantRole ? undefined : handleClick}
1153
+ >
1154
+ <div className="flex items-start justify-between gap-3">
1155
+ <div className="flex-1 min-w-0">
1156
+ {message.message && (
1157
+ <div
1158
+ className={`max-w-none ${isSystemMessage ? 'text-gray-800' : 'text-gray-900'}`}
1159
+ dir={detectTextDirection((message as any)?.message || '')}
1160
+ lang={detectLanguageTag((message as any)?.message || '')}
1161
+ >
1162
+ {(() => {
1163
+ const contentType = detectContentType(message.message);
1164
+
1165
+ if (contentType === 'code') {
1166
+ return <CodeFormatter content={message.message} />;
1167
+ } else if (contentType === 'html') {
1168
+ return (
1169
+ <div
1170
+ className="max-w-none text-gray-800 html-content"
1171
+ dangerouslySetInnerHTML={{
1172
+ __html: prettifyHtmlContent(sanitizeHtml(message.message)),
1173
+ }}
1174
+ />
1175
+ );
1176
+ } else {
1177
+ return <FormattedMessageContent content={message.message} />;
1178
+ }
1179
+ })()}
1180
+ </div>
1181
+ )}
1182
+
1183
+ {tryExtractBuilderBlocks((message as any)?.message)?.length ? (
1184
+ <div className="mt-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
1185
+ <BuilderLikeRenderer blocks={tryExtractBuilderBlocks((message as any)?.message)} />
1186
+ </div>
1187
+ ) : null}
1188
+
1189
+ {(message as any)?.props?.blocks?.length ? (
1190
+ <div className="mt-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
1191
+ <BuilderLikeRenderer blocks={(message as any).props.blocks} />
1192
+ </div>
1193
+ ) : null}
1194
+
1195
+ {message.files?.totalCount > 0 && (
1196
+ <div className="mt-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
1197
+ <FilesList uploaded files={message.files.data} />
1198
+ </div>
1199
+ )}
1200
+ </div>
1201
+
1202
+ {/* Action buttons on hover - Only show for non-system messages */}
1203
+ {!isSystemMessage && (
1204
+ <div className="flex-shrink-0 mt-1">
1205
+ <div className="opacity-0 group-hover/message:opacity-100 transition-opacity duration-200 flex space-x-1">
1206
+ <button className="p-1 hover:bg-gray-200 rounded transition-colors">
1207
+ <svg
1208
+ className="w-3 h-3 text-gray-400"
1209
+ fill="none"
1210
+ stroke="currentColor"
1211
+ viewBox="0 0 24 24"
1212
+ >
1213
+ <path
1214
+ strokeLinecap="round"
1215
+ strokeLinejoin="round"
1216
+ strokeWidth={2}
1217
+ d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z"
1218
+ />
1219
+ </svg>
1220
+ </button>
1221
+ <button className="p-1 hover:bg-gray-200 rounded transition-colors">
1222
+ <svg
1223
+ className="w-3 h-3 text-gray-400"
1224
+ fill="none"
1225
+ stroke="currentColor"
1226
+ viewBox="0 0 24 24"
1227
+ >
1228
+ <path
1229
+ strokeLinecap="round"
1230
+ strokeLinejoin="round"
1231
+ strokeWidth={2}
1232
+ d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
1233
+ />
1234
+ </svg>
1235
+ </button>
1236
+ </div>
1237
+ </div>
1238
+ )}
1239
+ </div>
1240
+ </div>
1241
+ );
1242
+ };
1243
+
1244
+ export const ModernMessageGroupComponent: React.FC<ModernMessageGroupProps> = ({
1245
+ messages,
1246
+ currentUser,
1247
+ onOpen,
1248
+ onMessageClick,
1249
+ isDesktopView = false,
1250
+ isSmallScreen = false,
1251
+ sandboxErrors = [],
1252
+ currentFiles = {},
1253
+ onFixError,
1254
+ onRecreateSandbox,
1255
+ }) => {
1256
+ // Inject CSS styles for HTML content
1257
+ useInjectStyles();
1258
+
1259
+ // Filter out non-message items (like date strings)
1260
+ const actualMessages = messages.filter((msg) => typeof msg !== 'string') as IPost[];
1261
+
1262
+ // Group messages by user and time
1263
+ const messageGroups = groupMessagesByUserAndTime(actualMessages);
1264
+
1265
+ return (
1266
+ <div className={`min-h-fit ${isDesktopView ? 'space-y-6' : isSmallScreen ? 'space-y-4' : 'space-y-5'}`}>
1267
+ {messageGroups.map((group, groupIndex) => {
1268
+ const author = group[0]?.author;
1269
+ return (
1270
+ <ModernMessageGroup
1271
+ key={`group-${groupIndex}-${group[0]?.id}`}
1272
+ author={author}
1273
+ messages={group}
1274
+ currentUser={currentUser}
1275
+ onOpen={onOpen}
1276
+ onMessageClick={onMessageClick}
1277
+ isDesktopView={isDesktopView}
1278
+ isSmallScreen={isSmallScreen}
1279
+ />
1280
+ );
1281
+ })}
1282
+
1283
+ {sandboxErrors?.map((error) => (
1284
+ <div key={error.id} className="px-2">
1285
+ <ErrorFixCard
1286
+ error={error}
1287
+ onFixError={onFixError || (() => Promise.resolve())}
1288
+ currentFiles={currentFiles}
1289
+ isFixing={false}
1290
+ />
1291
+ </div>
1292
+ ))}
1293
+ </div>
1294
+ );
1295
+ };