@cossistant/react 0.0.4 → 0.0.6

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 (321) hide show
  1. package/README.md +27 -0
  2. package/_virtual/rolldown_runtime.js +19 -0
  3. package/conversation.d.ts +23 -0
  4. package/conversation.d.ts.map +1 -1
  5. package/hooks/index.d.ts +5 -3
  6. package/hooks/index.js +7 -5
  7. package/hooks/private/store/use-conversations-store.d.ts +8 -0
  8. package/hooks/private/store/use-conversations-store.d.ts.map +1 -1
  9. package/hooks/private/store/use-conversations-store.js +8 -0
  10. package/hooks/private/store/use-conversations-store.js.map +1 -1
  11. package/hooks/private/store/use-store-selector.d.ts +4 -0
  12. package/hooks/private/store/use-store-selector.d.ts.map +1 -1
  13. package/hooks/private/store/use-store-selector.js +5 -2
  14. package/hooks/private/store/use-store-selector.js.map +1 -1
  15. package/hooks/private/store/use-website-store.d.ts +4 -0
  16. package/hooks/private/store/use-website-store.d.ts.map +1 -1
  17. package/hooks/private/store/use-website-store.js +6 -3
  18. package/hooks/private/store/use-website-store.js.map +1 -1
  19. package/hooks/private/typing.d.ts +35 -0
  20. package/hooks/private/typing.d.ts.map +1 -0
  21. package/hooks/private/typing.js +49 -0
  22. package/hooks/private/typing.js.map +1 -0
  23. package/hooks/private/use-client-query.d.ts +5 -0
  24. package/hooks/private/use-client-query.d.ts.map +1 -1
  25. package/hooks/private/use-client-query.js +5 -0
  26. package/hooks/private/use-client-query.js.map +1 -1
  27. package/hooks/private/use-grouped-messages.d.ts +10 -4
  28. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  29. package/hooks/private/use-grouped-messages.js +24 -4
  30. package/hooks/private/use-grouped-messages.js.map +1 -1
  31. package/hooks/private/use-multimodal-input.d.ts.map +1 -1
  32. package/hooks/private/use-rest-client.d.ts.map +1 -1
  33. package/hooks/private/use-visitor-typing-reporter.d.ts +6 -0
  34. package/hooks/private/use-visitor-typing-reporter.d.ts.map +1 -1
  35. package/hooks/private/use-visitor-typing-reporter.js +6 -0
  36. package/hooks/private/use-visitor-typing-reporter.js.map +1 -1
  37. package/hooks/use-composer-refocus.d.ts.map +1 -1
  38. package/hooks/use-conversation-auto-seen.d.ts +9 -0
  39. package/hooks/use-conversation-auto-seen.d.ts.map +1 -1
  40. package/hooks/use-conversation-auto-seen.js +44 -3
  41. package/hooks/use-conversation-auto-seen.js.map +1 -1
  42. package/hooks/use-conversation-history-page.d.ts.map +1 -1
  43. package/hooks/use-conversation-history-page.js +16 -18
  44. package/hooks/use-conversation-history-page.js.map +1 -1
  45. package/hooks/use-conversation-lifecycle.d.ts.map +1 -1
  46. package/hooks/use-conversation-lifecycle.js +2 -4
  47. package/hooks/use-conversation-lifecycle.js.map +1 -1
  48. package/hooks/use-conversation-page.d.ts +6 -0
  49. package/hooks/use-conversation-page.d.ts.map +1 -1
  50. package/hooks/use-conversation-page.js +41 -3
  51. package/hooks/use-conversation-page.js.map +1 -1
  52. package/hooks/use-conversation-preview.d.ts +61 -0
  53. package/hooks/use-conversation-preview.d.ts.map +1 -0
  54. package/hooks/use-conversation-preview.js +173 -0
  55. package/hooks/use-conversation-preview.js.map +1 -0
  56. package/hooks/use-conversation-seen.d.ts +4 -0
  57. package/hooks/use-conversation-seen.d.ts.map +1 -1
  58. package/hooks/use-conversation-seen.js +4 -0
  59. package/hooks/use-conversation-seen.js.map +1 -1
  60. package/hooks/use-conversation-timeline-items.d.ts +4 -0
  61. package/hooks/use-conversation-timeline-items.d.ts.map +1 -1
  62. package/hooks/use-conversation-timeline-items.js +4 -0
  63. package/hooks/use-conversation-timeline-items.js.map +1 -1
  64. package/hooks/use-conversation-timeline.d.ts +32 -0
  65. package/hooks/use-conversation-timeline.d.ts.map +1 -0
  66. package/hooks/use-conversation-timeline.js +41 -0
  67. package/hooks/use-conversation-timeline.js.map +1 -0
  68. package/hooks/use-conversation-typing.d.ts +4 -0
  69. package/hooks/use-conversation-typing.d.ts.map +1 -1
  70. package/hooks/use-conversation-typing.js +4 -0
  71. package/hooks/use-conversation-typing.js.map +1 -1
  72. package/hooks/use-conversation.d.ts +11 -0
  73. package/hooks/use-conversation.d.ts.map +1 -1
  74. package/hooks/use-conversation.js +11 -0
  75. package/hooks/use-conversation.js.map +1 -1
  76. package/hooks/use-conversations.d.ts +12 -0
  77. package/hooks/use-conversations.d.ts.map +1 -1
  78. package/hooks/use-conversations.js +12 -0
  79. package/hooks/use-conversations.js.map +1 -1
  80. package/hooks/use-create-conversation.d.ts +5 -0
  81. package/hooks/use-create-conversation.d.ts.map +1 -1
  82. package/hooks/use-create-conversation.js +12 -9
  83. package/hooks/use-create-conversation.js.map +1 -1
  84. package/hooks/use-home-page.d.ts.map +1 -1
  85. package/hooks/use-home-page.js +6 -4
  86. package/hooks/use-home-page.js.map +1 -1
  87. package/hooks/use-message-composer.d.ts.map +1 -1
  88. package/hooks/use-realtime-support.d.ts.map +1 -1
  89. package/hooks/use-send-message.d.ts +9 -0
  90. package/hooks/use-send-message.d.ts.map +1 -1
  91. package/hooks/use-send-message.js +15 -13
  92. package/hooks/use-send-message.js.map +1 -1
  93. package/hooks/use-visitor.d.ts.map +1 -1
  94. package/hooks/use-visitor.js +28 -30
  95. package/hooks/use-visitor.js.map +1 -1
  96. package/hooks/use-window-visibility-focus.d.ts +4 -0
  97. package/hooks/use-window-visibility-focus.d.ts.map +1 -1
  98. package/hooks/use-window-visibility-focus.js +5 -2
  99. package/hooks/use-window-visibility-focus.js.map +1 -1
  100. package/identify-visitor.d.ts +12 -3
  101. package/identify-visitor.d.ts.map +1 -1
  102. package/identify-visitor.js +58 -9
  103. package/identify-visitor.js.map +1 -1
  104. package/index.d.ts +10 -7
  105. package/index.js +10 -9
  106. package/package.json +12 -16
  107. package/primitives/avatar/avatar.d.ts.map +1 -1
  108. package/primitives/avatar/fallback.d.ts.map +1 -1
  109. package/primitives/avatar/fallback.js +1 -3
  110. package/primitives/avatar/fallback.js.map +1 -1
  111. package/primitives/avatar/image.d.ts.map +1 -1
  112. package/primitives/avatar/index.d.ts +1 -0
  113. package/primitives/bubble.d.ts +2 -0
  114. package/primitives/bubble.d.ts.map +1 -1
  115. package/primitives/bubble.js +8 -2
  116. package/primitives/bubble.js.map +1 -1
  117. package/primitives/button.d.ts.map +1 -1
  118. package/primitives/conversation-timeline.d.ts.map +1 -1
  119. package/primitives/conversation-timeline.js +58 -5
  120. package/primitives/conversation-timeline.js.map +1 -1
  121. package/primitives/index.d.ts +1 -0
  122. package/primitives/index.parts.d.ts +1 -0
  123. package/primitives/multimodal-input.d.ts.map +1 -1
  124. package/primitives/timeline-item-group.d.ts +7 -7
  125. package/primitives/timeline-item-group.d.ts.map +1 -1
  126. package/primitives/timeline-item-group.js.map +1 -1
  127. package/primitives/timeline-item.d.ts +1 -1
  128. package/primitives/timeline-item.d.ts.map +1 -1
  129. package/primitives/timeline-item.js +7 -1
  130. package/primitives/timeline-item.js.map +1 -1
  131. package/primitives/window.d.ts +1 -1
  132. package/primitives/window.d.ts.map +1 -1
  133. package/primitives/window.js +4 -4
  134. package/primitives/window.js.map +1 -1
  135. package/provider.d.ts +23 -43
  136. package/provider.d.ts.map +1 -1
  137. package/provider.js +152 -49
  138. package/provider.js.map +1 -1
  139. package/realtime/event-filter.d.ts +4 -0
  140. package/realtime/event-filter.d.ts.map +1 -1
  141. package/realtime/event-filter.js +4 -0
  142. package/realtime/event-filter.js.map +1 -1
  143. package/realtime/index.js +1 -1
  144. package/realtime/provider.d.ts +7 -2
  145. package/realtime/provider.d.ts.map +1 -1
  146. package/realtime/provider.js +23 -1
  147. package/realtime/provider.js.map +1 -1
  148. package/realtime/seen-store.d.ts +13 -0
  149. package/realtime/seen-store.d.ts.map +1 -1
  150. package/realtime/seen-store.js +14 -2
  151. package/realtime/seen-store.js.map +1 -1
  152. package/realtime/support-provider.d.ts +1 -2
  153. package/realtime/support-provider.d.ts.map +1 -1
  154. package/realtime/support-provider.js +19 -20
  155. package/realtime/support-provider.js.map +1 -1
  156. package/realtime/typing-store.d.ts +18 -0
  157. package/realtime/typing-store.d.ts.map +1 -1
  158. package/realtime/typing-store.js +19 -2
  159. package/realtime/typing-store.js.map +1 -1
  160. package/realtime/use-realtime.d.ts +8 -4
  161. package/realtime/use-realtime.d.ts.map +1 -1
  162. package/realtime/use-realtime.js +4 -0
  163. package/realtime/use-realtime.js.map +1 -1
  164. package/realtime-events.d.ts +15 -1
  165. package/realtime-events.d.ts.map +1 -1
  166. package/schemas.d.ts +6 -0
  167. package/schemas.d.ts.map +1 -1
  168. package/support/components/avatar-stack.d.ts +8 -4
  169. package/support/components/avatar-stack.d.ts.map +1 -1
  170. package/support/components/avatar-stack.js +4 -0
  171. package/support/components/avatar-stack.js.map +1 -1
  172. package/support/components/avatar.d.ts +11 -6
  173. package/support/components/avatar.d.ts.map +1 -1
  174. package/support/components/avatar.js +4 -0
  175. package/support/components/avatar.js.map +1 -1
  176. package/support/components/bubble.d.ts.map +1 -1
  177. package/support/components/bubble.js +29 -6
  178. package/support/components/bubble.js.map +1 -1
  179. package/support/components/button.d.ts +8 -5
  180. package/support/components/button.d.ts.map +1 -1
  181. package/support/components/button.js +5 -1
  182. package/support/components/button.js.map +1 -1
  183. package/support/components/container.d.ts +0 -1
  184. package/support/components/container.d.ts.map +1 -1
  185. package/support/components/container.js +2 -8
  186. package/support/components/container.js.map +1 -1
  187. package/support/components/conversation-button-link.d.ts +8 -21
  188. package/support/components/conversation-button-link.d.ts.map +1 -1
  189. package/support/components/conversation-button-link.js +62 -178
  190. package/support/components/conversation-button-link.js.map +1 -1
  191. package/support/components/conversation-event.d.ts.map +1 -1
  192. package/support/components/conversation-event.js +4 -0
  193. package/support/components/conversation-event.js.map +1 -1
  194. package/support/components/conversation-timeline.d.ts +10 -1
  195. package/support/components/conversation-timeline.d.ts.map +1 -1
  196. package/support/components/conversation-timeline.js +63 -57
  197. package/support/components/conversation-timeline.js.map +1 -1
  198. package/support/components/cossistant-branding.d.ts +5 -2
  199. package/support/components/cossistant-branding.d.ts.map +1 -1
  200. package/support/components/cossistant-branding.js +3 -0
  201. package/support/components/cossistant-branding.js.map +1 -1
  202. package/support/components/header.d.ts.map +1 -1
  203. package/support/components/header.js +2 -2
  204. package/support/components/header.js.map +1 -1
  205. package/support/components/icons.d.ts.map +1 -1
  206. package/support/components/multimodal-input.d.ts.map +1 -1
  207. package/support/components/multimodal-input.js +5 -24
  208. package/support/components/multimodal-input.js.map +1 -1
  209. package/support/components/navigation-tab.d.ts +7 -2
  210. package/support/components/navigation-tab.d.ts.map +1 -1
  211. package/support/components/navigation-tab.js +4 -0
  212. package/support/components/navigation-tab.js.map +1 -1
  213. package/support/components/support-content.d.ts +1 -1
  214. package/support/components/support-content.d.ts.map +1 -1
  215. package/support/components/support-content.js +7 -10
  216. package/support/components/support-content.js.map +1 -1
  217. package/support/components/text-effect.d.ts +5 -2
  218. package/support/components/text-effect.d.ts.map +1 -1
  219. package/support/components/text-effect.js +4 -0
  220. package/support/components/text-effect.js.map +1 -1
  221. package/support/components/timeline-identification-tool.d.ts +7 -0
  222. package/support/components/timeline-identification-tool.d.ts.map +1 -0
  223. package/support/components/timeline-identification-tool.js +139 -0
  224. package/support/components/timeline-identification-tool.js.map +1 -0
  225. package/support/components/timeline-message-group.d.ts +2 -1
  226. package/support/components/timeline-message-group.d.ts.map +1 -1
  227. package/support/components/timeline-message-group.js +4 -19
  228. package/support/components/timeline-message-group.js.map +1 -1
  229. package/support/components/timeline-message-item.d.ts +6 -2
  230. package/support/components/timeline-message-item.d.ts.map +1 -1
  231. package/support/components/timeline-message-item.js +8 -4
  232. package/support/components/timeline-message-item.js.map +1 -1
  233. package/support/components/typing-indicator.d.ts +5 -2
  234. package/support/components/typing-indicator.d.ts.map +1 -1
  235. package/support/components/typing-indicator.js +4 -4
  236. package/support/components/typing-indicator.js.map +1 -1
  237. package/support/components/watermark.d.ts.map +1 -1
  238. package/support/context/websocket.d.ts +8 -0
  239. package/support/context/websocket.d.ts.map +1 -1
  240. package/support/context/websocket.js +12 -6
  241. package/support/context/websocket.js.map +1 -1
  242. package/support/index.d.ts +8 -8
  243. package/support/index.d.ts.map +1 -1
  244. package/support/index.js +18 -18
  245. package/support/index.js.map +1 -1
  246. package/support/pages/conversation-history.js +46 -54
  247. package/support/pages/conversation-history.js.map +1 -1
  248. package/support/pages/conversation.d.ts +3 -6
  249. package/support/pages/conversation.d.ts.map +1 -1
  250. package/support/pages/conversation.js +19 -9
  251. package/support/pages/conversation.js.map +1 -1
  252. package/support/pages/home.d.ts +2 -2
  253. package/support/pages/home.d.ts.map +1 -1
  254. package/support/pages/home.js +64 -77
  255. package/support/pages/home.js.map +1 -1
  256. package/support/store/support-store.d.ts +18 -2
  257. package/support/store/support-store.d.ts.map +1 -1
  258. package/support/store/support-store.js +20 -5
  259. package/support/store/support-store.js.map +1 -1
  260. package/support/{support-CMoDLQoC.css → support-Ck4jy29i.css} +1 -2
  261. package/support/support-Ck4jy29i.css.map +1 -0
  262. package/support/text/index.d.ts +15 -2
  263. package/support/text/index.d.ts.map +1 -1
  264. package/support/text/index.js +15 -2
  265. package/support/text/index.js.map +1 -1
  266. package/support/text/locales/en.js +22 -4
  267. package/support/text/locales/en.js.map +1 -1
  268. package/support/text/locales/es.js +18 -0
  269. package/support/text/locales/es.js.map +1 -1
  270. package/support/text/locales/fr.js +18 -0
  271. package/support/text/locales/fr.js.map +1 -1
  272. package/support/text/locales/keys.d.ts +69 -9
  273. package/support/text/locales/keys.d.ts.map +1 -1
  274. package/support/text/locales/keys.js +18 -0
  275. package/support/text/locales/keys.js.map +1 -1
  276. package/support/text/runtime.d.ts +21 -0
  277. package/support/text/runtime.d.ts.map +1 -1
  278. package/support/text/runtime.js +21 -0
  279. package/support/text/runtime.js.map +1 -1
  280. package/support/utils/index.d.ts +4 -0
  281. package/support/utils/index.d.ts.map +1 -1
  282. package/support/utils/index.js +4 -1
  283. package/support/utils/index.js.map +1 -1
  284. package/support/utils/time.d.ts +3 -0
  285. package/support/utils/time.d.ts.map +1 -1
  286. package/support/utils/time.js +3 -0
  287. package/support/utils/time.js.map +1 -1
  288. package/support-config.d.ts +2 -1
  289. package/support-config.d.ts.map +1 -1
  290. package/support-config.js.map +1 -1
  291. package/support.css +2 -2
  292. package/tailwind.css +404 -0
  293. package/timeline-item.d.ts +10 -0
  294. package/timeline-item.d.ts.map +1 -1
  295. package/utils/conversation.d.ts +7 -0
  296. package/utils/conversation.d.ts.map +1 -0
  297. package/utils/conversation.js +18 -0
  298. package/utils/conversation.js.map +1 -0
  299. package/utils/id.d.ts +3 -0
  300. package/utils/id.d.ts.map +1 -1
  301. package/utils/id.js +3 -0
  302. package/utils/id.js.map +1 -1
  303. package/utils/index.d.ts +2 -1
  304. package/utils/index.js +2 -1
  305. package/utils/metadata-hash.d.ts +12 -0
  306. package/utils/metadata-hash.d.ts.map +1 -0
  307. package/utils/metadata-hash.js +26 -0
  308. package/utils/metadata-hash.js.map +1 -0
  309. package/utils/text.d.ts +3 -0
  310. package/utils/text.d.ts.map +1 -1
  311. package/utils/text.js +3 -0
  312. package/utils/text.js.map +1 -1
  313. package/utils/use-render-element.d.ts +3 -0
  314. package/utils/use-render-element.d.ts.map +1 -1
  315. package/utils/use-render-element.js +3 -0
  316. package/utils/use-render-element.js.map +1 -1
  317. package/support/context/config.d.ts +0 -32
  318. package/support/context/config.d.ts.map +0 -1
  319. package/support/context/config.js +0 -27
  320. package/support/context/config.js.map +0 -1
  321. package/support/support-CMoDLQoC.css.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-button-link.js","names":["senderImage: string | null","state: ConversationButtonLinkState","Icon"],"sources":["../../../src/support/components/conversation-button-link.tsx"],"sourcesContent":["import { type Conversation, ConversationStatus } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport {\n\tuseConversationTimelineItems,\n\tuseConversationTyping,\n\tuseSupport,\n} from \"../..\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport { formatTimeAgo } from \"../utils/time\";\nimport { Avatar } from \"./avatar\";\nimport { coButtonVariants } from \"./button\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\nexport type ConversationButtonLinkProps = {\n\tconversation: Conversation;\n\tonClick?: () => void;\n\tclassName?: string | ((state: ConversationButtonLinkState) => string);\n\trender?: (\n\t\tprops: React.HTMLProps<HTMLButtonElement>,\n\t\tstate: ConversationButtonLinkState\n\t) => React.ReactElement;\n};\n\nexport type ConversationButtonLinkAgent = {\n\tname: string;\n\timage: string | null;\n\ttype: \"human\" | \"ai\" | \"fallback\";\n};\n\nexport type ConversationButtonLinkState = {\n\tconversation: Conversation;\n\tlastMessage: {\n\t\tcontent: string;\n\t\ttime: string;\n\t\tisFromVisitor: boolean;\n\t\tsenderName?: string;\n\t\tsenderImage?: string | null;\n\t} | null;\n\tassignedAgent: ConversationButtonLinkAgent;\n};\n\nfunction getLastTimelineItemInfo(\n\titem: NonNullable<Conversation[\"lastTimelineItem\"]>,\n\tavailableHumanAgents: ReturnType<typeof useSupport>[\"availableHumanAgents\"],\n\twebsite: ReturnType<typeof useSupport>[\"website\"],\n\ttext: ReturnType<typeof useSupportText>\n) {\n\tconst isFromVisitor = item.visitorId !== null;\n\n\tlet senderName = text(\"common.fallbacks.unknown\");\n\tlet senderImage: string | null = null;\n\n\tif (isFromVisitor) {\n\t\tsenderName = text(\"common.fallbacks.you\");\n\t} else if (item.userId) {\n\t\tconst agent = availableHumanAgents.find((a) => a.id === item.userId);\n\t\tif (agent) {\n\t\t\tsenderName = agent.name;\n\t\t\tsenderImage = agent.image;\n\t\t} else {\n\t\t\tsenderName = text(\"common.fallbacks.supportTeam\");\n\t\t}\n\t} else if (item.aiAgentId && website?.availableAIAgents) {\n\t\tconst aiAgent = website.availableAIAgents.find(\n\t\t\t(a) => a.id === item.aiAgentId\n\t\t);\n\t\tif (aiAgent) {\n\t\t\tsenderName = aiAgent.name;\n\t\t\tsenderImage = aiAgent.image;\n\t\t} else {\n\t\t\tsenderName = text(\"common.fallbacks.aiAssistant\");\n\t\t}\n\t} else {\n\t\tsenderName = text(\"common.fallbacks.supportTeam\");\n\t}\n\n\treturn {\n\t\tcontent: item.text || \"\",\n\t\ttime: formatTimeAgo(item.createdAt),\n\t\tisFromVisitor,\n\t\tsenderName,\n\t\tsenderImage,\n\t};\n}\n\nexport function ConversationButtonLink({\n\tconversation,\n\tonClick,\n\t...props\n}: ConversationButtonLinkProps) {\n\tconst { availableHumanAgents, availableAIAgents, website, visitor } =\n\t\tuseSupport();\n\tconst { items } = useConversationTimelineItems(conversation.id);\n\tconst text = useSupportText();\n\tconst typingEntries = useConversationTyping(conversation.id, {\n\t\texcludeVisitorId: visitor?.id ?? null,\n\t});\n\n\t// Check if anyone is typing in this conversation\n\tconst typingInfo = useMemo(() => {\n\t\tif (typingEntries.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst entry = typingEntries[0];\n\t\tlet name = text(\"common.fallbacks.someone\");\n\t\tlet image: string | null = null;\n\n\t\tif (entry?.actorType === \"user\") {\n\t\t\tconst human = availableHumanAgents.find(\n\t\t\t\t(agent) => agent.id === entry.actorId\n\t\t\t);\n\t\t\tname = human?.name || text(\"common.fallbacks.supportTeam\");\n\t\t\timage = human?.image || null;\n\t\t} else if (entry?.actorType === \"ai_agent\") {\n\t\t\tconst ai = availableAIAgents.find((agent) => agent.id === entry.actorId);\n\t\t\tname = ai?.name || text(\"common.fallbacks.aiAssistant\");\n\t\t\timage = ai?.image || null;\n\t\t}\n\n\t\treturn { name };\n\t}, [typingEntries, availableHumanAgents, availableAIAgents, text]);\n\n\t// Process the last timeline item (memoized to avoid expensive recomputation)\n\tconst lastMessage = useMemo(() => {\n\t\tconst cachedLastTimelineItem =\n\t\t\t// biome-ignore lint/style/useAtIndex: ok here\n\t\t\titems.length > 0 ? items[items.length - 1] : null;\n\n\t\tconst timelineItemToDisplay =\n\t\t\tcachedLastTimelineItem || conversation.lastTimelineItem;\n\n\t\treturn timelineItemToDisplay\n\t\t\t? getLastTimelineItemInfo(\n\t\t\t\t\ttimelineItemToDisplay,\n\t\t\t\t\tavailableHumanAgents,\n\t\t\t\t\twebsite,\n\t\t\t\t\ttext\n\t\t\t\t)\n\t\t\t: null;\n\t}, [\n\t\titems,\n\t\tconversation.lastTimelineItem,\n\t\tavailableHumanAgents,\n\t\twebsite,\n\t\ttext,\n\t]);\n\n\tconst assignedAgent = useMemo<ConversationButtonLinkAgent>(() => {\n\t\tconst supportFallbackName = text(\"common.fallbacks.supportTeam\");\n\t\tconst aiFallbackName = text(\"common.fallbacks.aiAssistant\");\n\n\t\tconst knownItems = items.slice();\n\t\tif (\n\t\t\tconversation.lastTimelineItem &&\n\t\t\t!knownItems.some((item) => item.id === conversation.lastTimelineItem?.id)\n\t\t) {\n\t\t\tknownItems.push(conversation.lastTimelineItem);\n\t\t}\n\n\t\tconst lastAgentItem = [...knownItems]\n\t\t\t.reverse()\n\t\t\t.find((item) => item.userId !== null || item.aiAgentId !== null);\n\n\t\tif (lastAgentItem?.userId) {\n\t\t\tconst human = availableHumanAgents.find(\n\t\t\t\t(agent) => agent.id === lastAgentItem.userId\n\t\t\t);\n\n\t\t\tif (human) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"human\",\n\t\t\t\t\tname: human.name,\n\t\t\t\t\timage: human.image ?? null,\n\t\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttype: \"human\",\n\t\t\t\tname: supportFallbackName,\n\t\t\t\timage: null,\n\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t}\n\n\t\tif (lastAgentItem?.aiAgentId) {\n\t\t\tconst ai = availableAIAgents.find(\n\t\t\t\t(agent) => agent.id === lastAgentItem.aiAgentId\n\t\t\t);\n\n\t\t\tif (ai) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"ai\",\n\t\t\t\t\tname: ai.name,\n\t\t\t\t\timage: ai.image ?? null,\n\t\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttype: \"ai\",\n\t\t\t\tname: aiFallbackName,\n\t\t\t\timage: null,\n\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t}\n\n\t\tconst fallbackHuman = availableHumanAgents[0];\n\t\tif (fallbackHuman) {\n\t\t\treturn {\n\t\t\t\ttype: \"human\",\n\t\t\t\tname: fallbackHuman.name,\n\t\t\t\timage: fallbackHuman.image ?? null,\n\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t}\n\n\t\tconst fallbackAi = availableAIAgents[0];\n\t\tif (fallbackAi) {\n\t\t\treturn {\n\t\t\t\ttype: \"ai\",\n\t\t\t\tname: fallbackAi.name,\n\t\t\t\timage: fallbackAi.image ?? null,\n\t\t\t} satisfies ConversationButtonLinkAgent;\n\t\t}\n\n\t\treturn {\n\t\t\ttype: \"fallback\",\n\t\t\tname: supportFallbackName,\n\t\t\timage: null,\n\t\t} satisfies ConversationButtonLinkAgent;\n\t}, [\n\t\titems,\n\t\tconversation.lastTimelineItem,\n\t\tavailableHumanAgents,\n\t\tavailableAIAgents,\n\t\ttext,\n\t]);\n\n\tconst conversationTitle = useMemo(() => {\n\t\tif (conversation.title) {\n\t\t\treturn conversation.title;\n\t\t}\n\n\t\tif (lastMessage?.content) {\n\t\t\treturn lastMessage.content;\n\t\t}\n\n\t\treturn text(\"component.conversationButtonLink.fallbackTitle\");\n\t}, [conversation.title, lastMessage?.content, text]);\n\n\tconst state: ConversationButtonLinkState = {\n\t\tconversation,\n\t\tlastMessage,\n\t\tassignedAgent,\n\t};\n\n\treturn useRenderElement(\"button\", props, {\n\t\tstate,\n\t\tprops: {\n\t\t\tonClick,\n\t\t\ttype: \"button\",\n\t\t\tclassName: cn(\n\t\t\t\tcoButtonVariants({ variant: \"secondary\", size: \"large\" }),\n\t\t\t\t\"relative gap-3 border-0 border-co-border/50 border-b text-left transition-colors first-of-type:rounded-t last-of-type:rounded-b last-of-type:border-b-0\",\n\t\t\t\ttypeof props.className === \"function\"\n\t\t\t\t\t? props.className(state)\n\t\t\t\t\t: props.className\n\t\t\t),\n\t\t\tchildren: (\n\t\t\t\t<>\n\t\t\t\t\t<Avatar\n\t\t\t\t\t\tclassName=\"size-8 flex-shrink-0\"\n\t\t\t\t\t\timage={assignedAgent.image}\n\t\t\t\t\t\tname={assignedAgent.name}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n\t\t\t\t\t\t{typingInfo ? (\n\t\t\t\t\t\t\t<BouncingDots />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<div className=\"flex max-w-[90%] items-center justify-between gap-2\">\n\t\t\t\t\t\t\t\t\t<h3 className=\"truncate font-medium text-co-primary text-sm\">\n\t\t\t\t\t\t\t\t\t\t{conversationTitle}\n\t\t\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t{lastMessage ? (\n\t\t\t\t\t\t\t\t\t<p className=\"text-co-primary/60 text-xs\">\n\t\t\t\t\t\t\t\t\t\t{lastMessage.isFromVisitor ? (\n\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t{text(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"component.conversationButtonLink.lastMessage.visitor\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttime: lastMessage.time,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t{text(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"component.conversationButtonLink.lastMessage.agent\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tname:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlastMessage.senderName ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttext(\"common.fallbacks.supportTeam\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttime: lastMessage.time,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"mr-6 inline-flex items-center rounded px-2 py-0.5 font-medium text-[9px] uppercase\",\n\t\t\t\t\t\t\tconversation.status === ConversationStatus.OPEN\n\t\t\t\t\t\t\t\t? \"bg-co-success/20 text-co-success-foreground\"\n\t\t\t\t\t\t\t\t: conversation.status === ConversationStatus.RESOLVED\n\t\t\t\t\t\t\t\t\t? \"bg-co-neutral/20 text-co-neutral-foreground\"\n\t\t\t\t\t\t\t\t\t: \"bg-co-warning/20 text-co-warning-foreground\"\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{conversation.status}\n\t\t\t\t\t</div>\n\t\t\t\t\t<Icon\n\t\t\t\t\t\tclassName=\"-translate-y-1/2 absolute top-1/2 right-4 size-3 text-co-primary/60 transition-transform duration-200 group-hover/btn:translate-x-0.5 group-hover/btn:text-co-primary\"\n\t\t\t\t\t\tname=\"arrow-right\"\n\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t),\n\t\t},\n\t});\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversation-button-link.js","names":["STATUS_BADGE_CLASSNAMES: Record<ConversationStatus, string>","STATUS_TEXT_KEYS: Record<ConversationStatus, SupportTextKey>","Icon"],"sources":["../../../src/support/components/conversation-button-link.tsx"],"sourcesContent":["import { type Conversation, ConversationStatus } from \"@cossistant/types\";\nimport type React from \"react\";\nimport { useConversationPreview } from \"../../hooks/use-conversation-preview\";\nimport { type SupportTextKey, useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport { Avatar } from \"./avatar\";\nimport { coButtonVariants } from \"./button\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\nexport type ConversationButtonLinkProps = {\n\tconversation: Conversation;\n\tonClick?: () => void;\n\tclassName?: string;\n};\n\nconst STATUS_BADGE_CLASSNAMES: Record<ConversationStatus, string> = {\n\t[ConversationStatus.OPEN]: \"bg-co-success/20 text-co-success-foreground\",\n\t[ConversationStatus.RESOLVED]: \"bg-co-neutral/20 text-co-neutral-foreground\",\n\t[ConversationStatus.SPAM]: \"bg-co-warning/20 text-co-warning-foreground\",\n};\n\nconst DEFAULT_STATUS_BADGE_CLASSNAME =\n\t\"bg-co-neutral/20 text-co-neutral-foreground\";\n\nconst STATUS_TEXT_KEYS: Record<ConversationStatus, SupportTextKey> = {\n\t[ConversationStatus.OPEN]: \"component.conversationButtonLink.status.open\",\n\t[ConversationStatus.RESOLVED]:\n\t\t\"component.conversationButtonLink.status.resolved\",\n\t[ConversationStatus.SPAM]: \"component.conversationButtonLink.status.spam\",\n};\n\n/**\n * Renders a navigable preview card for a conversation including assigned agent\n * details, last message snippets and typing indicators.\n */\nexport function ConversationButtonLink({\n\tconversation,\n\tonClick,\n\tclassName,\n}: ConversationButtonLinkProps): React.ReactElement | null {\n\tconst preview = useConversationPreview({ conversation });\n\tconst text = useSupportText();\n\tconst { lastMessage, assignedAgent, typing } = preview;\n\n\tconst statusBadgeClassName = conversation.deletedAt\n\t\t? STATUS_BADGE_CLASSNAMES[ConversationStatus.RESOLVED]\n\t\t: (STATUS_BADGE_CLASSNAMES[conversation.status] ??\n\t\t\tDEFAULT_STATUS_BADGE_CLASSNAME);\n\n\tconst statusTextKey = conversation.deletedAt\n\t\t? STATUS_TEXT_KEYS[ConversationStatus.RESOLVED]\n\t\t: STATUS_TEXT_KEYS[conversation.status];\n\n\tconst statusText = conversation.deletedAt\n\t\t? text(\"component.conversationButtonLink.status.closed\")\n\t\t: statusTextKey\n\t\t\t? text(statusTextKey)\n\t\t\t: text(\"common.fallbacks.unknown\");\n\n\tconst lastMessageContent = lastMessage ? (\n\t\tlastMessage.isFromVisitor ? (\n\t\t\t<span>\n\t\t\t\t{text(\"component.conversationButtonLink.lastMessage.visitor\", {\n\t\t\t\t\ttime: lastMessage.time,\n\t\t\t\t})}\n\t\t\t</span>\n\t\t) : (\n\t\t\t<span>\n\t\t\t\t{text(\"component.conversationButtonLink.lastMessage.agent\", {\n\t\t\t\t\tname: lastMessage.senderName || text(\"common.fallbacks.supportTeam\"),\n\t\t\t\t\ttime: lastMessage.time,\n\t\t\t\t})}\n\t\t\t</span>\n\t\t)\n\t) : undefined;\n\n\treturn (\n\t\t<button\n\t\t\tclassName={cn(\n\t\t\t\tcoButtonVariants({\n\t\t\t\t\tvariant: \"secondary\",\n\t\t\t\t\tsize: \"large\",\n\t\t\t\t}),\n\t\t\t\t\"group/btn relative gap-3 border-0 border-co-border/50 border-b text-left transition-colors first-of-type:rounded-t last-of-type:rounded-b last-of-type:border-b-0\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tonClick={onClick}\n\t\t\ttype=\"button\"\n\t\t>\n\t\t\t<Avatar\n\t\t\t\tclassName=\"flex size-8 flex-shrink-0 items-center justify-center overflow-clip rounded-full bg-co-background-200 dark:bg-co-background-500\"\n\t\t\t\timage={assignedAgent?.image}\n\t\t\t\tname={assignedAgent?.name ?? text(\"common.fallbacks.supportTeam\")}\n\t\t\t/>\n\n\t\t\t<div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n\t\t\t\t{typing.isTyping ? (\n\t\t\t\t\t<BouncingDots />\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div className=\"flex max-w-[90%] items-center justify-between gap-2\">\n\t\t\t\t\t\t\t<h3 className=\"truncate font-medium text-co-primary text-sm\">\n\t\t\t\t\t\t\t\t{preview.title}\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{lastMessageContent ? (\n\t\t\t\t\t\t\t<p className=\"text-co-primary/60 text-xs\">{lastMessageContent}</p>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"mr-6 inline-flex items-center rounded px-2 py-0.5 font-medium text-[9px] uppercase\",\n\t\t\t\t\tstatusBadgeClassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{statusText}\n\t\t\t</div>\n\n\t\t\t<Icon\n\t\t\t\tclassName=\"-translate-y-1/2 absolute top-1/2 right-4 size-3 text-co-primary/60 transition-transform duration-200 group-hover/btn:translate-x-0.5 group-hover/btn:text-co-primary\"\n\t\t\t\tname=\"arrow-right\"\n\t\t\t\tvariant=\"default\"\n\t\t\t/>\n\t\t</button>\n\t);\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAMA,0BAA8D;EAClE,mBAAmB,OAAO;EAC1B,mBAAmB,WAAW;EAC9B,mBAAmB,OAAO;CAC3B;AAED,MAAM,iCACL;AAED,MAAMC,mBAA+D;EACnE,mBAAmB,OAAO;EAC1B,mBAAmB,WACnB;EACA,mBAAmB,OAAO;CAC3B;;;;;AAMD,SAAgB,uBAAuB,EACtC,cACA,SACA,aAC0D;CAC1D,MAAM,UAAU,uBAAuB,EAAE,cAAc,CAAC;CACxD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,EAAE,aAAa,eAAe,WAAW;CAE/C,MAAM,uBAAuB,aAAa,YACvC,wBAAwB,mBAAmB,YAC1C,wBAAwB,aAAa,WACvC;CAEF,MAAM,gBAAgB,aAAa,YAChC,iBAAiB,mBAAmB,YACpC,iBAAiB,aAAa;CAEjC,MAAM,aAAa,aAAa,YAC7B,KAAK,iDAAiD,GACtD,gBACC,KAAK,cAAc,GACnB,KAAK,2BAA2B;CAEpC,MAAM,qBAAqB,cAC1B,YAAY,gBACX,oBAAC,oBACC,KAAK,wDAAwD,EAC7D,MAAM,YAAY,MAClB,CAAC,GACI,GAEP,oBAAC,oBACC,KAAK,sDAAsD;EAC3D,MAAM,YAAY,cAAc,KAAK,+BAA+B;EACpE,MAAM,YAAY;EAClB,CAAC,GACI,GAEL;AAEJ,QACC,qBAAC;EACA,WAAW,GACV,iBAAiB;GAChB,SAAS;GACT,MAAM;GACN,CAAC,EACF,qKACA,UACA;EACQ;EACT,MAAK;;GAEL,oBAAC;IACA,WAAU;IACV,OAAO,eAAe;IACtB,MAAM,eAAe,QAAQ,KAAK,+BAA+B;KAChE;GAEF,oBAAC;IAAI,WAAU;cACb,OAAO,WACP,oBAAC,iBAAe,GAEhB,4CACC,oBAAC;KAAI,WAAU;eACd,oBAAC;MAAG,WAAU;gBACZ,QAAQ;OACL;MACA,EACL,qBACA,oBAAC;KAAE,WAAU;eAA8B;MAAuB,GAC/D,QACF;KAEC;GAEN,oBAAC;IACA,WAAW,GACV,sFACA,qBACA;cAEA;KACI;GAEN,oBAACC;IACA,WAAU;IACV,MAAK;IACL,SAAQ;KACP;;GACM"}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-event.d.ts","names":[],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":[],"mappings":";;;;KAWY,sBAAA;SACJ;EADI,iBAAA,EAEQ,gBAFc,EAAA;EAAA,oBAAA,EAGX,mBAHW,EAAA;WAC1B,CAAA,EAAA,MAAA;;AAEe,cAIV,iBAJU,EAIS,KAAA,CAAM,EAJf,CAIkB,sBAJlB,CAAA"}
1
+ {"version":3,"file":"conversation-event.d.ts","names":[],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":[],"mappings":";;;;KAWY,sBAAA;SACJ;EADI,iBAAA,EAEQ,gBAFc,EAAA;EAC1B,oBAAA,EAEe,mBAFf,EAAA;EACY,SAAA,CAAA,EAAA,MAAA;CACG;AAAmB,cAI7B,iBAJ6B,EAIV,KAAA,CAAM,EAJI,CAID,sBAJC,CAAA"}
@@ -24,6 +24,9 @@ const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHuman
24
24
  case "tag_removed": return text("component.conversationEvent.tagRemoved", { actorName });
25
25
  case "resolved": return text("component.conversationEvent.resolved", { actorName });
26
26
  case "reopened": return text("component.conversationEvent.reopened", { actorName });
27
+ case "visitor_blocked": return text("component.conversationEvent.visitorBlocked", { actorName });
28
+ case "visitor_unblocked": return text("component.conversationEvent.visitorUnblocked", { actorName });
29
+ case "visitor_identified": return text("component.conversationEvent.visitorIdentified", { actorName });
27
30
  default: return text("component.conversationEvent.default", { actorName });
28
31
  }
29
32
  };
@@ -70,6 +73,7 @@ const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHuman
70
73
  })
71
74
  });
72
75
  };
76
+ ConversationEvent.displayName = "ConversationEvent";
73
77
 
74
78
  //#endregion
75
79
  export { ConversationEvent };
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-event.js","names":["ConversationEvent: React.FC<ConversationEventProps>"],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":["import type {\n\tAvailableAIAgent,\n\tAvailableHumanAgent,\n\tTimelinePartEvent,\n} from \"@cossistant/types\";\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useSupportText } from \"../text\";\nimport { Avatar } from \"./avatar\";\nimport { CossistantLogo } from \"./cossistant-branding\";\n\nexport type ConversationEventProps = {\n\tevent: TimelinePartEvent;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcreatedAt?: string;\n};\n\nexport const ConversationEvent: React.FC<ConversationEventProps> = ({\n\tevent,\n\tavailableAIAgents,\n\tcreatedAt,\n\tavailableHumanAgents,\n}) => {\n\tconst text = useSupportText();\n\tconst isAI = event.actorAiAgentId !== null;\n\tconst humanAgent = availableHumanAgents.find(\n\t\t(agent) => agent.id === event.actorUserId\n\t);\n\tconst aiAgent = availableAIAgents.find(\n\t\t(agent) => agent.id === event.actorAiAgentId\n\t);\n\n\t// Get the actor name\n\tconst actorName = isAI\n\t\t? aiAgent?.name || text(\"common.fallbacks.cossistant\")\n\t\t: humanAgent?.name || text(\"common.fallbacks.someone\");\n\n\t// Convert event type to plain English\n\tconst getEventText = () => {\n\t\tswitch (event.eventType) {\n\t\t\tcase \"assigned\":\n\t\t\t\treturn text(\"component.conversationEvent.assigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"unassigned\":\n\t\t\t\treturn text(\"component.conversationEvent.unassigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_requested\":\n\t\t\t\treturn text(\"component.conversationEvent.participantRequested\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_joined\":\n\t\t\t\treturn text(\"component.conversationEvent.participantJoined\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_left\":\n\t\t\t\treturn text(\"component.conversationEvent.participantLeft\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"status_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.statusChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"priority_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.priorityChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_added\":\n\t\t\t\treturn text(\"component.conversationEvent.tagAdded\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_removed\":\n\t\t\t\treturn text(\"component.conversationEvent.tagRemoved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"resolved\":\n\t\t\t\treturn text(\"component.conversationEvent.resolved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"reopened\":\n\t\t\t\treturn text(\"component.conversationEvent.reopened\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tdefault:\n\t\t\t\treturn text(\"component.conversationEvent.default\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<motion.div\n\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\tclassName=\"flex items-center justify-center py-4\"\n\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\n\t\t\ttransition={{ duration: 0.3, ease: \"easeOut\" }}\n\t\t>\n\t\t\t<div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n\t\t\t\t<div className=\"flex flex-col justify-end\">\n\t\t\t\t\t{isAI ? (\n\t\t\t\t\t\t<div className=\"flex size-5 items-center justify-center rounded-full bg-primary/10\">\n\t\t\t\t\t\t\t<CossistantLogo className=\"h-3 w-3 text-primary\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\tclassName=\"size-5 flex-shrink-0 overflow-clip rounded-full\"\n\t\t\t\t\t\t\timage={humanAgent?.image}\n\t\t\t\t\t\t\tname={humanAgent?.name || text(\"common.fallbacks.someone\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<span className=\"px-2\">{getEventText()}</span>\n\t\t\t\t{createdAt && (\n\t\t\t\t\t<time className=\"text-[10px]\">\n\t\t\t\t\t\t{new Date(createdAt).toLocaleTimeString([], {\n\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t})}\n\t\t\t\t\t</time>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</motion.div>\n\t);\n};\n"],"mappings":";;;;;;;AAkBA,MAAaA,qBAAuD,EACnE,OACA,mBACA,WACA,2BACK;CACL,MAAM,OAAO,gBAAgB;CAC7B,MAAM,OAAO,MAAM,mBAAmB;CACtC,MAAM,aAAa,qBAAqB,MACtC,UAAU,MAAM,OAAO,MAAM,YAC9B;CACD,MAAM,UAAU,kBAAkB,MAChC,UAAU,MAAM,OAAO,MAAM,eAC9B;CAGD,MAAM,YAAY,OACf,SAAS,QAAQ,KAAK,8BAA8B,GACpD,YAAY,QAAQ,KAAK,2BAA2B;CAGvD,MAAM,qBAAqB;AAC1B,UAAQ,MAAM,WAAd;GACC,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,aACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,wBACJ,QAAO,KAAK,oDAAoD,EAC/D,WACA,CAAC;GACH,KAAK,qBACJ,QAAO,KAAK,iDAAiD,EAC5D,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,iBACJ,QAAO,KAAK,6CAA6C,EACxD,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,YACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,cACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,QACC,QAAO,KAAK,uCAAuC,EAClD,WACA,CAAC;;;AAIL,QACC,oBAAC,OAAO;EACP,SAAS;GAAE,SAAS;GAAG,OAAO;GAAG;EACjC,WAAU;EACV,SAAS;GAAE,SAAS;GAAG,OAAO;GAAM;EACpC,YAAY;GAAE,UAAU;GAAK,MAAM;GAAW;YAE9C,qBAAC;GAAI,WAAU;;IACd,oBAAC;KAAI,WAAU;eACb,OACA,oBAAC;MAAI,WAAU;gBACd,oBAAC,kBAAe,WAAU,yBAAyB;OAC9C,GAEN,oBAAC;MACA,WAAU;MACV,OAAO,YAAY;MACnB,MAAM,YAAY,QAAQ,KAAK,2BAA2B;OACzD;MAEE;IACN,oBAAC;KAAK,WAAU;eAAQ,cAAc;MAAQ;IAC7C,aACA,oBAAC;KAAK,WAAU;eACd,IAAI,KAAK,UAAU,CAAC,mBAAmB,EAAE,EAAE;MAC3C,MAAM;MACN,QAAQ;MACR,CAAC;MACI;;IAEH;GACM"}
1
+ {"version":3,"file":"conversation-event.js","names":["ConversationEvent: React.FC<ConversationEventProps>"],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":["import type {\n\tAvailableAIAgent,\n\tAvailableHumanAgent,\n\tTimelinePartEvent,\n} from \"@cossistant/types\";\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useSupportText } from \"../text\";\nimport { Avatar } from \"./avatar\";\nimport { CossistantLogo } from \"./cossistant-branding\";\n\nexport type ConversationEventProps = {\n\tevent: TimelinePartEvent;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcreatedAt?: string;\n};\n\nexport const ConversationEvent: React.FC<ConversationEventProps> = ({\n\tevent,\n\tavailableAIAgents,\n\tcreatedAt,\n\tavailableHumanAgents,\n}) => {\n\tconst text = useSupportText();\n\tconst isAI = event.actorAiAgentId !== null;\n\tconst humanAgent = availableHumanAgents.find(\n\t\t(agent) => agent.id === event.actorUserId\n\t);\n\tconst aiAgent = availableAIAgents.find(\n\t\t(agent) => agent.id === event.actorAiAgentId\n\t);\n\n\t// Get the actor name\n\tconst actorName = isAI\n\t\t? aiAgent?.name || text(\"common.fallbacks.cossistant\")\n\t\t: humanAgent?.name || text(\"common.fallbacks.someone\");\n\n\t// Convert event type to plain English\n\tconst getEventText = () => {\n\t\tswitch (event.eventType) {\n\t\t\tcase \"assigned\":\n\t\t\t\treturn text(\"component.conversationEvent.assigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"unassigned\":\n\t\t\t\treturn text(\"component.conversationEvent.unassigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_requested\":\n\t\t\t\treturn text(\"component.conversationEvent.participantRequested\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_joined\":\n\t\t\t\treturn text(\"component.conversationEvent.participantJoined\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_left\":\n\t\t\t\treturn text(\"component.conversationEvent.participantLeft\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"status_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.statusChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"priority_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.priorityChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_added\":\n\t\t\t\treturn text(\"component.conversationEvent.tagAdded\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_removed\":\n\t\t\t\treturn text(\"component.conversationEvent.tagRemoved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"resolved\":\n\t\t\t\treturn text(\"component.conversationEvent.resolved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"reopened\":\n\t\t\t\treturn text(\"component.conversationEvent.reopened\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_blocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorBlocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_unblocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorUnblocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_identified\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorIdentified\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tdefault:\n\t\t\t\treturn text(\"component.conversationEvent.default\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<motion.div\n\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\tclassName=\"flex items-center justify-center py-4\"\n\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\n\t\t\ttransition={{ duration: 0.3, ease: \"easeOut\" }}\n\t\t>\n\t\t\t<div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n\t\t\t\t<div className=\"flex flex-col justify-end\">\n\t\t\t\t\t{isAI ? (\n\t\t\t\t\t\t<div className=\"flex size-5 items-center justify-center rounded-full bg-primary/10\">\n\t\t\t\t\t\t\t<CossistantLogo className=\"h-3 w-3 text-primary\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\tclassName=\"size-5 flex-shrink-0 overflow-clip rounded-full\"\n\t\t\t\t\t\t\timage={humanAgent?.image}\n\t\t\t\t\t\t\tname={humanAgent?.name || text(\"common.fallbacks.someone\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<span className=\"px-2\">{getEventText()}</span>\n\t\t\t\t{createdAt && (\n\t\t\t\t\t<time className=\"text-[10px]\">\n\t\t\t\t\t\t{new Date(createdAt).toLocaleTimeString([], {\n\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t})}\n\t\t\t\t\t</time>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</motion.div>\n\t);\n};\n\nConversationEvent.displayName = \"ConversationEvent\";\n"],"mappings":";;;;;;;AAkBA,MAAaA,qBAAuD,EACnE,OACA,mBACA,WACA,2BACK;CACL,MAAM,OAAO,gBAAgB;CAC7B,MAAM,OAAO,MAAM,mBAAmB;CACtC,MAAM,aAAa,qBAAqB,MACtC,UAAU,MAAM,OAAO,MAAM,YAC9B;CACD,MAAM,UAAU,kBAAkB,MAChC,UAAU,MAAM,OAAO,MAAM,eAC9B;CAGD,MAAM,YAAY,OACf,SAAS,QAAQ,KAAK,8BAA8B,GACpD,YAAY,QAAQ,KAAK,2BAA2B;CAGvD,MAAM,qBAAqB;AAC1B,UAAQ,MAAM,WAAd;GACC,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,aACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,wBACJ,QAAO,KAAK,oDAAoD,EAC/D,WACA,CAAC;GACH,KAAK,qBACJ,QAAO,KAAK,iDAAiD,EAC5D,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,iBACJ,QAAO,KAAK,6CAA6C,EACxD,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,YACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,cACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,kBACJ,QAAO,KAAK,8CAA8C,EACzD,WACA,CAAC;GACH,KAAK,oBACJ,QAAO,KAAK,gDAAgD,EAC3D,WACA,CAAC;GACH,KAAK,qBACJ,QAAO,KAAK,iDAAiD,EAC5D,WACA,CAAC;GACH,QACC,QAAO,KAAK,uCAAuC,EAClD,WACA,CAAC;;;AAIL,QACC,oBAAC,OAAO;EACP,SAAS;GAAE,SAAS;GAAG,OAAO;GAAG;EACjC,WAAU;EACV,SAAS;GAAE,SAAS;GAAG,OAAO;GAAM;EACpC,YAAY;GAAE,UAAU;GAAK,MAAM;GAAW;YAE9C,qBAAC;GAAI,WAAU;;IACd,oBAAC;KAAI,WAAU;eACb,OACA,oBAAC;MAAI,WAAU;gBACd,oBAAC,kBAAe,WAAU,yBAAyB;OAC9C,GAEN,oBAAC;MACA,WAAU;MACV,OAAO,YAAY;MACnB,MAAM,YAAY,QAAQ,KAAK,2BAA2B;OACzD;MAEE;IACN,oBAAC;KAAK,WAAU;eAAQ,cAAc;MAAQ;IAC7C,aACA,oBAAC;KAAK,WAAU;eACd,IAAI,KAAK,UAAU,CAAC,mBAAmB,EAAE,EAAE;MAC3C,MAAM;MACN,QAAQ;MACR,CAAC;MACI;;IAEH;GACM;;AAIf,kBAAkB,cAAc"}
@@ -3,6 +3,14 @@ import React from "react";
3
3
  import { AvailableAIAgent, AvailableHumanAgent } from "@cossistant/types";
4
4
 
5
5
  //#region src/support/components/conversation-timeline.d.ts
6
+ type ConversationTimelineToolProps = {
7
+ item: TimelineItem;
8
+ conversationId: string;
9
+ };
10
+ type ConversationTimelineToolDefinition = {
11
+ component: React.ComponentType<ConversationTimelineToolProps>;
12
+ };
13
+ type ConversationTimelineTools = Record<string, ConversationTimelineToolDefinition>;
6
14
  type ConversationTimelineProps = {
7
15
  conversationId: string;
8
16
  items: TimelineItem[];
@@ -10,8 +18,9 @@ type ConversationTimelineProps = {
10
18
  availableAIAgents: AvailableAIAgent[];
11
19
  availableHumanAgents: AvailableHumanAgent[];
12
20
  currentVisitorId?: string;
21
+ tools?: ConversationTimelineTools;
13
22
  };
14
23
  declare const ConversationTimelineList: React.FC<ConversationTimelineProps>;
15
24
  //#endregion
16
- export { ConversationTimelineList, ConversationTimelineProps };
25
+ export { ConversationTimelineList, ConversationTimelineProps, ConversationTimelineToolDefinition, ConversationTimelineToolProps, ConversationTimelineTools };
17
26
  //# sourceMappingURL=conversation-timeline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;KAoCY,yBAAA;;EAAA,KAAA,EAEJ,YAFI,EAAA;EAAyB,SAAA,CAAA,EAAA,MAAA;mBAE7B,EAEY,gBAFZ,EAAA;sBAEY,EACG,mBADH,EAAA;kBACG,CAAA,EAAA,MAAA;CAAmB;AAI7B,cAAA,wBAsIZ,EAtIsC,KAAA,CAAM,EAsI5C,CAtI+C,yBAsI/C,CAAA"}
1
+ {"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;KAiCY,6BAAA;QACL;EADK,cAAA,EAAA,MAAA;AAKZ,CAAA;AAIY,KAJA,kCAAA,GAMX;EAGW,SAAA,EARA,KAAA,CAAM,aAQmB,CARL,6BAQK,CAAA;CAE7B;AAEY,KATR,yBAAA,GAA4B,MASpB,CAAA,MAAA,EAPnB,kCAOmB,CAAA;AACG,KALX,yBAAA,GAKW;EAEd,cAAA,EAAA,MAAA;EAAyB,KAAA,EAL1B,YAK0B,EAAA;EAGrB,SAAA,CAAA,EAAA,MAAA;qBANO;wBACG;;UAEd;;cAGI,0BAA0B,KAAA,CAAM,GAAG"}
@@ -1,51 +1,48 @@
1
1
  import { cn } from "../utils/index.js";
2
2
  import { TypingIndicator } from "./typing-indicator.js";
3
3
  import { ConversationTimeline, ConversationTimelineContainer } from "../../primitives/conversation-timeline.js";
4
- import { useGroupedMessages } from "../../hooks/private/use-grouped-messages.js";
4
+ import { useConversationTimeline } from "../../hooks/use-conversation-timeline.js";
5
5
  import { ConversationEvent } from "./conversation-event.js";
6
6
  import { TimelineMessageGroup } from "./timeline-message-group.js";
7
- import { useDebouncedConversationSeen } from "../../hooks/use-conversation-seen.js";
8
- import { useConversationTyping } from "../../hooks/use-conversation-typing.js";
9
- import { useMemo } from "react";
10
- import { SenderType } from "@cossistant/types";
7
+ import { useCallback, useMemo } from "react";
11
8
  import { jsx, jsxs } from "react/jsx-runtime";
12
- import { AnimatePresence } from "motion/react";
13
9
 
14
10
  //#region src/support/components/conversation-timeline.tsx
15
11
  function extractEventPart(item) {
16
12
  if (item.type !== "event") return null;
17
13
  return item.parts.find((part) => part.type === "event") || null;
18
14
  }
19
- const ConversationTimelineList = ({ conversationId, items: timelineItems, className, availableAIAgents = [], availableHumanAgents = [], currentVisitorId }) => {
20
- const seenData = useDebouncedConversationSeen(conversationId);
21
- const typingEntries = useConversationTyping(conversationId, { excludeVisitorId: currentVisitorId ?? null });
22
- const { items, getMessageSeenBy } = useGroupedMessages({
15
+ const EMPTY_SEEN_BY_IDS = Object.freeze([]);
16
+ const EMPTY_SEEN_BY_NAMES = Object.freeze([]);
17
+ const ConversationTimelineList = ({ conversationId, items: timelineItems, className, availableAIAgents = [], availableHumanAgents = [], currentVisitorId, tools }) => {
18
+ const timeline = useConversationTimeline({
19
+ conversationId,
23
20
  items: timelineItems,
24
- seenData,
25
- currentViewerId: currentVisitorId,
26
- viewerType: SenderType.VISITOR
21
+ currentVisitorId
27
22
  });
28
- const lastVisitorMessageGroupIndex = useMemo(() => {
29
- for (let i = items.length - 1; i >= 0; i--) {
30
- const item = items[i];
31
- if (!item) continue;
32
- if (item.type === "message_group") {
33
- if ((item.items?.[0])?.visitorId === currentVisitorId) return i;
34
- }
23
+ const typingIndicatorParticipants = useMemo(() => timeline.typingParticipants.map((participant) => ({
24
+ id: participant.id,
25
+ type: participant.type
26
+ })), [timeline.typingParticipants]);
27
+ const seenNameLookup = useMemo(() => {
28
+ const map = /* @__PURE__ */ new Map();
29
+ for (const agent of availableHumanAgents) if (agent.name) map.set(agent.id, agent.name);
30
+ for (const agent of availableAIAgents) if (agent.name) map.set(agent.id, agent.name);
31
+ return map;
32
+ }, [availableHumanAgents, availableAIAgents]);
33
+ const getSeenByNames = useCallback((ids = EMPTY_SEEN_BY_IDS) => {
34
+ if (ids.length === 0 || seenNameLookup.size === 0) return EMPTY_SEEN_BY_NAMES;
35
+ const uniqueNames = /* @__PURE__ */ new Set();
36
+ const names = [];
37
+ for (const id of ids) {
38
+ const name = seenNameLookup.get(id);
39
+ if (!name || uniqueNames.has(name)) continue;
40
+ uniqueNames.add(name);
41
+ names.push(name);
35
42
  }
36
- return -1;
37
- }, [items, currentVisitorId]);
38
- const typingParticipants = useMemo(() => typingEntries.map((entry) => {
39
- if (entry.actorType === "user") return {
40
- id: entry.actorId,
41
- type: "team_member"
42
- };
43
- if (entry.actorType === "ai_agent") return {
44
- id: entry.actorId,
45
- type: "ai"
46
- };
47
- return null;
48
- }).filter((participant) => participant !== null), [typingEntries]);
43
+ if (names.length === 0) return EMPTY_SEEN_BY_NAMES;
44
+ return Object.freeze(names);
45
+ }, [seenNameLookup]);
49
46
  return /* @__PURE__ */ jsx(ConversationTimeline, {
50
47
  autoScroll: true,
51
48
  className: cn("overflow-y-auto scroll-smooth px-3 py-6", "scrollbar-thin scrollbar-thumb-co-background-300 scrollbar-track-transparent", "h-full w-full", className),
@@ -53,37 +50,46 @@ const ConversationTimelineList = ({ conversationId, items: timelineItems, classN
53
50
  items: timelineItems,
54
51
  children: /* @__PURE__ */ jsxs(ConversationTimelineContainer, {
55
52
  className: "flex min-h-full w-full flex-col gap-3",
56
- children: [/* @__PURE__ */ jsx(AnimatePresence, {
57
- initial: false,
58
- mode: "popLayout",
59
- children: items.map((item, index) => {
60
- if (item.type === "timeline_event") {
61
- const eventPart = extractEventPart(item.item);
62
- if (!eventPart) return null;
63
- return /* @__PURE__ */ jsx(ConversationEvent, {
64
- availableAIAgents,
65
- availableHumanAgents,
66
- createdAt: item.item.createdAt,
67
- event: eventPart
68
- }, item.item.id || `timeline-event-${index}`);
69
- }
70
- const seenByIds = index === lastVisitorMessageGroupIndex && item.lastMessageId ? getMessageSeenBy(item.lastMessageId) : [];
71
- const groupKey = item.items?.[0]?.id || `group-${index}`;
72
- return /* @__PURE__ */ jsx(TimelineMessageGroup, {
53
+ children: [timeline.groupedMessages.items.map((item, index) => {
54
+ if (item.type === "timeline_event") {
55
+ const eventPart = extractEventPart(item.item);
56
+ if (!eventPart) return null;
57
+ return /* @__PURE__ */ jsx(ConversationEvent, {
73
58
  availableAIAgents,
74
59
  availableHumanAgents,
75
- currentVisitorId,
76
- items: item.items || [],
77
- seenByIds
78
- }, groupKey);
79
- })
60
+ createdAt: item.item.createdAt,
61
+ event: eventPart
62
+ }, item.item.id ?? `timeline-event-${item.item.createdAt}`);
63
+ }
64
+ if (item.type === "timeline_tool") {
65
+ const toolName = item.tool ?? item.item.tool ?? item.item.type;
66
+ const toolDefinition = toolName ? tools?.[toolName] : void 0;
67
+ if (!toolDefinition) return null;
68
+ const ToolComponent = toolDefinition.component;
69
+ const toolKey = item.item.id ?? `${toolName}-${item.item.createdAt}-${index}`;
70
+ return /* @__PURE__ */ jsx(ToolComponent, {
71
+ conversationId,
72
+ item: item.item
73
+ }, toolKey);
74
+ }
75
+ const seenByIds = index === timeline.lastVisitorMessageGroupIndex && item.lastMessageId ? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId) : EMPTY_SEEN_BY_IDS;
76
+ const seenByNames = seenByIds.length > 0 ? getSeenByNames(seenByIds) : EMPTY_SEEN_BY_NAMES;
77
+ const groupKey = item.lastMessageId ?? item.items?.[0]?.id ?? `group-${item.items?.[0]?.createdAt ?? index}`;
78
+ return /* @__PURE__ */ jsx(TimelineMessageGroup, {
79
+ availableAIAgents,
80
+ availableHumanAgents,
81
+ currentVisitorId,
82
+ items: item.items || [],
83
+ seenByIds,
84
+ seenByNames
85
+ }, groupKey);
80
86
  }), /* @__PURE__ */ jsx("div", {
81
87
  className: "h-6 w-full",
82
- children: typingParticipants.length > 0 ? /* @__PURE__ */ jsx(TypingIndicator, {
88
+ children: typingIndicatorParticipants.length > 0 ? /* @__PURE__ */ jsx(TypingIndicator, {
83
89
  availableAIAgents,
84
90
  availableHumanAgents,
85
91
  className: "mt-2",
86
- participants: typingParticipants
92
+ participants: typingIndicatorParticipants
87
93
  }) : null
88
94
  })]
89
95
  })
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-timeline.js","names":["ConversationTimelineList: React.FC<ConversationTimelineProps>","PrimitiveConversationTimeline","ConversationEventComponent"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport { SenderType } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport { AnimatePresence } from \"motion/react\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport {\n\tuseConversationTyping,\n\tuseDebouncedConversationSeen,\n} from \"../../hooks\";\nimport { useGroupedMessages } from \"../../hooks/private/use-grouped-messages\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent as ConversationEventComponent } from \"./conversation-event\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n}) => {\n\tconst seenData = useDebouncedConversationSeen(conversationId);\n\tconst typingEntries = useConversationTyping(conversationId, {\n\t\texcludeVisitorId: currentVisitorId ?? null,\n\t});\n\n\tconst { items, getMessageSeenBy } = useGroupedMessages({\n\t\titems: timelineItems,\n\t\tseenData,\n\t\tcurrentViewerId: currentVisitorId,\n\t\tviewerType: SenderType.VISITOR,\n\t});\n\n\t// Find the last message group sent by the current visitor\n\tconst lastVisitorMessageGroupIndex = useMemo(() => {\n\t\tfor (let i = items.length - 1; i >= 0; i--) {\n\t\t\tconst item = items[i];\n\t\t\tif (!item) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (item.type === \"message_group\") {\n\t\t\t\tconst firstItem = item.items?.[0];\n\t\t\t\tif (firstItem?.visitorId === currentVisitorId) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}, [items, currentVisitorId]);\n\n\tconst typingParticipants = useMemo(\n\t\t() =>\n\t\t\ttypingEntries\n\t\t\t\t.map((entry): TypingParticipant | null => {\n\t\t\t\t\tif (entry.actorType === \"user\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: entry.actorId,\n\t\t\t\t\t\t\ttype: \"team_member\" as const,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entry.actorType === \"ai_agent\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: entry.actorId,\n\t\t\t\t\t\t\ttype: \"ai\" as const,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn null;\n\t\t\t\t})\n\t\t\t\t.filter(\n\t\t\t\t\t(participant): participant is TypingParticipant =>\n\t\t\t\t\t\tparticipant !== null\n\t\t\t\t),\n\t\t[typingEntries]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-auto scroll-smooth px-3 py-6\",\n\t\t\t\t\"scrollbar-thin scrollbar-thumb-co-background-300 scrollbar-track-transparent\",\n\t\t\t\t\"h-full w-full\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tid=\"conversation-timeline\"\n\t\t\titems={timelineItems}\n\t\t>\n\t\t\t<ConversationTimelineContainer className=\"flex min-h-full w-full flex-col gap-3\">\n\t\t\t\t<AnimatePresence initial={false} mode=\"popLayout\">\n\t\t\t\t\t{items.map((item, index) => {\n\t\t\t\t\t\tif (item.type === \"timeline_event\") {\n\t\t\t\t\t\t\t// Extract event data from parts\n\t\t\t\t\t\t\tconst eventPart = extractEventPart(item.item);\n\n\t\t\t\t\t\t\t// Only render if we have valid event data\n\t\t\t\t\t\t\tif (!eventPart) {\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<ConversationEventComponent\n\t\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\t\tcreatedAt={item.item.createdAt}\n\t\t\t\t\t\t\t\t\tevent={eventPart}\n\t\t\t\t\t\t\t\t\tkey={item.item.id || `timeline-event-${index}`}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Only show seen indicator on the LAST message group sent by the visitor\n\t\t\t\t\t\tconst isLastVisitorGroup = index === lastVisitorMessageGroupIndex;\n\t\t\t\t\t\tconst seenByIds =\n\t\t\t\t\t\t\tisLastVisitorGroup && item.lastMessageId\n\t\t\t\t\t\t\t\t? getMessageSeenBy(item.lastMessageId)\n\t\t\t\t\t\t\t\t: [];\n\n\t\t\t\t\t\t// Use first timeline item ID as stable key\n\t\t\t\t\t\tconst groupKey = item.items?.[0]?.id || `group-${index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<TimelineMessageGroup\n\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\t\titems={item.items || []}\n\t\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\t\tseenByIds={seenByIds}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</AnimatePresence>\n\t\t\t\t<div className=\"h-6 w-full\">\n\t\t\t\t\t{typingParticipants.length > 0 ? (\n\t\t\t\t\t\t<TypingIndicator\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\t\t\tparticipants={typingParticipants}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</ConversationTimelineContainer>\n\t\t</PrimitiveConversationTimeline>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;AAwBA,SAAS,iBAAiB,MAA8C;AACvE,KAAI,KAAK,SAAS,QACjB,QAAO;AAOR,QAJkB,KAAK,MAAM,MAC3B,SAAoC,KAAK,SAAS,QACnD,IAEmB;;AAYrB,MAAaA,4BAAiE,EAC7E,gBACA,OAAO,eACP,WACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,uBACK;CACL,MAAM,WAAW,6BAA6B,eAAe;CAC7D,MAAM,gBAAgB,sBAAsB,gBAAgB,EAC3D,kBAAkB,oBAAoB,MACtC,CAAC;CAEF,MAAM,EAAE,OAAO,qBAAqB,mBAAmB;EACtD,OAAO;EACP;EACA,iBAAiB;EACjB,YAAY,WAAW;EACvB,CAAC;CAGF,MAAM,+BAA+B,cAAc;AAClD,OAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;GAC3C,MAAM,OAAO,MAAM;AACnB,OAAI,CAAC,KACJ;AAED,OAAI,KAAK,SAAS,iBAEjB;SADkB,KAAK,QAAQ,KAChB,cAAc,iBAC5B,QAAO;;;AAIV,SAAO;IACL,CAAC,OAAO,iBAAiB,CAAC;CAE7B,MAAM,qBAAqB,cAEzB,cACE,KAAK,UAAoC;AACzC,MAAI,MAAM,cAAc,OACvB,QAAO;GACN,IAAI,MAAM;GACV,MAAM;GACN;AAGF,MAAI,MAAM,cAAc,WACvB,QAAO;GACN,IAAI,MAAM;GACV,MAAM;GACN;AAGF,SAAO;GACN,CACD,QACC,gBACA,gBAAgB,KACjB,EACH,CAAC,cAAc,CACf;AAED,QACC,oBAACC;EACA,YAAY;EACZ,WAAW,GACV,2CACA,gFACA,iBACA,UACA;EACD,IAAG;EACH,OAAO;YAEP,qBAAC;GAA8B,WAAU;cACxC,oBAAC;IAAgB,SAAS;IAAO,MAAK;cACpC,MAAM,KAAK,MAAM,UAAU;AAC3B,SAAI,KAAK,SAAS,kBAAkB;MAEnC,MAAM,YAAY,iBAAiB,KAAK,KAAK;AAG7C,UAAI,CAAC,UACJ,QAAO;AAGR,aACC,oBAACC;OACmB;OACG;OACtB,WAAW,KAAK,KAAK;OACrB,OAAO;SACF,KAAK,KAAK,MAAM,kBAAkB,QACtC;;KAMJ,MAAM,YADqB,UAAU,gCAEd,KAAK,gBACxB,iBAAiB,KAAK,cAAc,GACpC,EAAE;KAGN,MAAM,WAAW,KAAK,QAAQ,IAAI,MAAM,SAAS;AAEjD,YACC,oBAAC;MACmB;MACG;MACJ;MAClB,OAAO,KAAK,SAAS,EAAE;MAEZ;QADN,SAEJ;MAEF;KACe,EAClB,oBAAC;IAAI,WAAU;cACb,mBAAmB,SAAS,IAC5B,oBAAC;KACmB;KACG;KACtB,WAAU;KACV,cAAc;MACb,GACC;KACC;IACyB;GACD"}
1
+ {"version":3,"file":"conversation-timeline.js","names":["EMPTY_SEEN_BY_IDS: readonly string[]","EMPTY_SEEN_BY_NAMES: readonly string[]","ConversationTimelineList: React.FC<ConversationTimelineProps>","names: string[]","PrimitiveConversationTimeline"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport { useConversationTimeline } from \"../../hooks/use-conversation-timeline\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent } from \"./conversation-event\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nconst EMPTY_SEEN_BY_IDS: readonly string[] = Object.freeze([]);\nconst EMPTY_SEEN_BY_NAMES: readonly string[] = Object.freeze([]);\n\nexport type ConversationTimelineToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\nexport type ConversationTimelineToolDefinition = {\n\tcomponent: React.ComponentType<ConversationTimelineToolProps>;\n};\n\nexport type ConversationTimelineTools = Record<\n\tstring,\n\tConversationTimelineToolDefinition\n>;\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: ConversationTimelineTools;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n\ttools,\n}) => {\n\tconst timeline = useConversationTimeline({\n\t\tconversationId,\n\t\titems: timelineItems,\n\t\tcurrentVisitorId,\n\t});\n\n\tconst typingIndicatorParticipants = useMemo(\n\t\t() =>\n\t\t\ttimeline.typingParticipants.map<TypingParticipant>((participant) => ({\n\t\t\t\tid: participant.id,\n\t\t\t\ttype: participant.type,\n\t\t\t})),\n\t\t[timeline.typingParticipants]\n\t);\n\n\tconst seenNameLookup = useMemo(() => {\n\t\tconst map = new Map<string, string>();\n\n\t\tfor (const agent of availableHumanAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\tfor (const agent of availableAIAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\treturn map;\n\t}, [availableHumanAgents, availableAIAgents]);\n\n\tconst getSeenByNames = useCallback(\n\t\t(ids: readonly string[] = EMPTY_SEEN_BY_IDS): readonly string[] => {\n\t\t\tif (ids.length === 0 || seenNameLookup.size === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\tconst uniqueNames = new Set<string>();\n\t\t\tconst names: string[] = [];\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst name = seenNameLookup.get(id);\n\t\t\t\tif (!name || uniqueNames.has(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tuniqueNames.add(name);\n\t\t\t\tnames.push(name);\n\t\t\t}\n\n\t\t\tif (names.length === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\treturn Object.freeze(names);\n\t\t},\n\t\t[seenNameLookup]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-auto scroll-smooth px-3 py-6\",\n\t\t\t\t\"scrollbar-thin scrollbar-thumb-co-background-300 scrollbar-track-transparent\",\n\t\t\t\t\"h-full w-full\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tid=\"conversation-timeline\"\n\t\t\titems={timelineItems}\n\t\t>\n\t\t\t<ConversationTimelineContainer className=\"flex min-h-full w-full flex-col gap-3\">\n\t\t\t\t{timeline.groupedMessages.items.map((item, index) => {\n\t\t\t\t\tif (item.type === \"timeline_event\") {\n\t\t\t\t\t\t// Extract event data from parts\n\t\t\t\t\t\tconst eventPart = extractEventPart(item.item);\n\n\t\t\t\t\t\t// Only render if we have valid event data\n\t\t\t\t\t\tif (!eventPart) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ConversationEvent\n\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\tcreatedAt={item.item.createdAt}\n\t\t\t\t\t\t\t\tevent={eventPart}\n\t\t\t\t\t\t\t\tkey={item.item.id ?? `timeline-event-${item.item.createdAt}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_tool\") {\n\t\t\t\t\t\tconst toolName = item.tool ?? item.item.tool ?? item.item.type;\n\t\t\t\t\t\tconst toolDefinition = toolName ? tools?.[toolName] : undefined;\n\n\t\t\t\t\t\tif (!toolDefinition) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst ToolComponent = toolDefinition.component;\n\n\t\t\t\t\t\tconst toolKey =\n\t\t\t\t\t\t\titem.item.id ?? `${toolName}-${item.item.createdAt}-${index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ToolComponent\n\t\t\t\t\t\t\t\tconversationId={conversationId}\n\t\t\t\t\t\t\t\titem={item.item}\n\t\t\t\t\t\t\t\tkey={toolKey}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only show seen indicator on the LAST message group sent by the visitor\n\t\t\t\t\tconst isLastVisitorGroup =\n\t\t\t\t\t\tindex === timeline.lastVisitorMessageGroupIndex;\n\t\t\t\t\tconst seenByIds =\n\t\t\t\t\t\tisLastVisitorGroup && item.lastMessageId\n\t\t\t\t\t\t\t? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_IDS;\n\t\t\t\t\tconst seenByNames =\n\t\t\t\t\t\tseenByIds.length > 0\n\t\t\t\t\t\t\t? getSeenByNames(seenByIds)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_NAMES;\n\n\t\t\t\t\t// Use first timeline item ID as stable key\n\t\t\t\t\tconst groupKey =\n\t\t\t\t\t\titem.lastMessageId ??\n\t\t\t\t\t\titem.items?.[0]?.id ??\n\t\t\t\t\t\t`group-${item.items?.[0]?.createdAt ?? index}`;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TimelineMessageGroup\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\titems={item.items || []}\n\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\tseenByIds={seenByIds}\n\t\t\t\t\t\t\tseenByNames={seenByNames}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\t<div className=\"h-6 w-full\">\n\t\t\t\t\t{typingIndicatorParticipants.length > 0 ? (\n\t\t\t\t\t\t<TypingIndicator\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\t\t\tparticipants={typingIndicatorParticipants}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</ConversationTimelineContainer>\n\t\t</PrimitiveConversationTimeline>\n\t);\n};\n"],"mappings":"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"}
@@ -1,12 +1,15 @@
1
- import * as react_jsx_runtime4 from "react/jsx-runtime";
1
+ import { ReactElement } from "react";
2
2
 
3
3
  //#region src/support/components/cossistant-branding.d.ts
4
4
  type CossistantLogoProps = {
5
5
  className?: string;
6
6
  };
7
+ /**
8
+ * Inline SVG of the Cossistant logomark.
9
+ */
7
10
  declare function CossistantLogo({
8
11
  className
9
- }: CossistantLogoProps): react_jsx_runtime4.JSX.Element;
12
+ }: CossistantLogoProps): ReactElement;
10
13
  //#endregion
11
14
  export { CossistantLogo };
12
15
  //# sourceMappingURL=cossistant-branding.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cossistant-branding.d.ts","names":[],"sources":["../../../src/support/components/cossistant-branding.tsx"],"sourcesContent":[],"mappings":";;;KAEK,mBAAA;;;AAAA,iBAIW,cAAA,CAJQ;EAAA;AAAA,CAAA,EAIsB,mBAJtB,CAAA,EAIyC,kBAAA,CAAA,GAAA,CAAA,OAJzC"}
1
+ {"version":3,"file":"cossistant-branding.d.ts","names":[],"sources":["../../../src/support/components/cossistant-branding.tsx"],"sourcesContent":[],"mappings":";;;KAIK,mBAAA;;AAJqC,CAAA;AAW1C;;;AAEyB,iBAFT,cAAA,CAES;EAAA;AAAA,CAAA,EAAtB,mBAAsB,CAAA,EAAA,YAAA"}
@@ -2,6 +2,9 @@ import { cn } from "../utils/index.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
 
4
4
  //#region src/support/components/cossistant-branding.tsx
5
+ /**
6
+ * Inline SVG of the Cossistant logomark.
7
+ */
5
8
  function CossistantLogo({ className }) {
6
9
  return /* @__PURE__ */ jsxs("svg", {
7
10
  className: cn("h-5 w-5", className),
@@ -1 +1 @@
1
- {"version":3,"file":"cossistant-branding.js","names":[],"sources":["../../../src/support/components/cossistant-branding.tsx"],"sourcesContent":["import { cn } from \"../utils\";\n\ntype CossistantLogoProps = {\n\tclassName?: string;\n};\n\nexport function CossistantLogo({ className }: CossistantLogoProps) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={cn(\"h-5 w-5\", className)}\n\t\t\tfill=\"none\"\n\t\t\tviewBox=\"0 0 350 286\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t>\n\t\t\t<title>Cossistant Logo</title>\n\t\t\t<path\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t\td=\"M349.071 60.9512V286H65.5293L.508789 225.719V60.9512L65.5293 0H284.051l65.02 60.9512Zm-267.9558 37.33c-3.8102.0002-7.4549 1.5574-10.0888 4.3108l-11.2569 11.767c-2.5097 2.624-3.8991 6.122-3.873 9.752l.1826 25.368H81.043l-.2237-13.446c0-9.826 2.3423-11.681 12.751-11.681h22.8487c10.409 0 11.96 1.855 11.96 12.457v12.67h25.218v-25.373c0-3.627-1.412-7.112-3.937-9.717l-11.497-11.863c-2.63-2.7131-6.247-4.2447-10.026-4.2448H81.1152Zm125.6658 0c-3.81 0-7.455 1.5571-10.09 4.3108l-11.256 11.767c-2.51 2.624-3.9 6.122-3.873 9.752l.182 25.368h24.965l-.224-13.446c0-9.826 2.343-11.681 12.751-11.681h22.849c10.408 0 11.959 1.855 11.959 12.457v12.67h25.219v-25.373c0-3.627-1.413-7.112-3.938-9.717l-11.497-11.863c-2.63-2.713-6.247-4.2448-10.026-4.2448h-47.021Z\"\n\t\t\t\tfill=\"currentColor\"\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n"],"mappings":";;;;AAMA,SAAgB,eAAe,EAAE,aAAkC;AAClE,QACC,qBAAC;EACA,WAAW,GAAG,WAAW,UAAU;EACnC,MAAK;EACL,SAAQ;EACR,OAAM;aAEN,oBAAC,qBAAM,oBAAuB,EAC9B,oBAAC;GACA,UAAS;GACT,GAAE;GACF,MAAK;GACL,UAAS;IACR;GACG"}
1
+ {"version":3,"file":"cossistant-branding.js","names":[],"sources":["../../../src/support/components/cossistant-branding.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nimport { cn } from \"../utils\";\n\ntype CossistantLogoProps = {\n\tclassName?: string;\n};\n\n/**\n * Inline SVG of the Cossistant logomark.\n */\nexport function CossistantLogo({\n\tclassName,\n}: CossistantLogoProps): ReactElement {\n\treturn (\n\t\t<svg\n\t\t\tclassName={cn(\"h-5 w-5\", className)}\n\t\t\tfill=\"none\"\n\t\t\tviewBox=\"0 0 350 286\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t>\n\t\t\t<title>Cossistant Logo</title>\n\t\t\t<path\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t\td=\"M349.071 60.9512V286H65.5293L.508789 225.719V60.9512L65.5293 0H284.051l65.02 60.9512Zm-267.9558 37.33c-3.8102.0002-7.4549 1.5574-10.0888 4.3108l-11.2569 11.767c-2.5097 2.624-3.8991 6.122-3.873 9.752l.1826 25.368H81.043l-.2237-13.446c0-9.826 2.3423-11.681 12.751-11.681h22.8487c10.409 0 11.96 1.855 11.96 12.457v12.67h25.218v-25.373c0-3.627-1.412-7.112-3.937-9.717l-11.497-11.863c-2.63-2.7131-6.247-4.2447-10.026-4.2448H81.1152Zm125.6658 0c-3.81 0-7.455 1.5571-10.09 4.3108l-11.256 11.767c-2.51 2.624-3.9 6.122-3.873 9.752l.182 25.368h24.965l-.224-13.446c0-9.826 2.343-11.681 12.751-11.681h22.849c10.408 0 11.959 1.855 11.959 12.457v12.67h25.219v-25.373c0-3.627-1.413-7.112-3.938-9.717l-11.497-11.863c-2.63-2.713-6.247-4.2448-10.026-4.2448h-47.021Z\"\n\t\t\t\tfill=\"currentColor\"\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,eAAe,EAC9B,aACqC;AACrC,QACC,qBAAC;EACA,WAAW,GAAG,WAAW,UAAU;EACnC,MAAK;EACL,SAAQ;EACR,OAAM;aAEN,oBAAC,qBAAM,oBAAuB,EAC9B,oBAAC;GACA,UAAS;GACT,GAAE;GACF,MAAK;GACL,UAAS;IACR;GACG"}
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","names":[],"sources":["../../../src/support/components/header.tsx"],"sourcesContent":[],"mappings":";KAKY,WAAA;EAAA,SAAA,CAAA,EAAA,MAAW;EAAA,QAAA,CAAA,EAEX,KAAA,CAAM,SAFK;SAEX,CAAA,EACD,KAAA,CAAM,SADC;UACP,CAAM,EAAA,GAAA,GAAA,IAAA;CAAS;AAIb,cAAA,MAiCZ,EAjCoB,KAAA,CAAM,EAiC1B,CAjC6B,WAiC7B,CAAA"}
1
+ {"version":3,"file":"header.d.ts","names":[],"sources":["../../../src/support/components/header.tsx"],"sourcesContent":[],"mappings":";KAKY,WAAA;EAAA,SAAA,CAAA,EAAA,MAAW;EAOV,QAAA,CA+BZ,EApCW,KAAA,CAAM,SAKY;YAJnB,KAAA,CAAM;;;cAIJ,QAAQ,KAAA,CAAM,GAAG"}
@@ -6,7 +6,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
6
6
 
7
7
  //#region src/support/components/header.tsx
8
8
  const Header = ({ className, children, actions, onGoBack }) => {
9
- const { close, mode } = useSupportConfig();
9
+ const { close } = useSupportConfig();
10
10
  return /* @__PURE__ */ jsx("div", {
11
11
  className: cn("absolute inset-x-0 top-0 z-10 h-18", className),
12
12
  children: /* @__PURE__ */ jsxs("div", {
@@ -26,7 +26,7 @@ const Header = ({ className, children, actions, onGoBack }) => {
26
26
  className: "flex items-center gap-2",
27
27
  children: actions
28
28
  }),
29
- mode !== "responsive" && /* @__PURE__ */ jsx(Button, {
29
+ /* @__PURE__ */ jsx(Button, {
30
30
  onClick: close,
31
31
  size: "icon",
32
32
  type: "button",
@@ -1 +1 @@
1
- {"version":3,"file":"header.js","names":["Header: React.FC<HeaderProps>","Icon"],"sources":["../../../src/support/components/header.tsx"],"sourcesContent":["import { useSupportConfig } from \"../store\";\nimport { cn } from \"../utils\";\nimport { Button } from \"./button\";\nimport Icon from \"./icons\";\n\nexport type HeaderProps = {\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n\tactions?: React.ReactNode;\n\tonGoBack?: () => void;\n};\n\nexport const Header: React.FC<HeaderProps> = ({\n\tclassName,\n\tchildren,\n\tactions,\n\tonGoBack,\n}) => {\n\tconst { close, mode } = useSupportConfig();\n\n\treturn (\n\t\t<div className={cn(\"absolute inset-x-0 top-0 z-10 h-18\", className)}>\n\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-between gap-3 px-4\">\n\t\t\t\t<div className=\"flex flex-1 items-center gap-3\">\n\t\t\t\t\t{onGoBack && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tonClick={onGoBack}\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"arrow-left\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t\t{actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n\t\t\t\t{mode !== \"responsive\" && (\n\t\t\t\t\t<Button onClick={close} size=\"icon\" type=\"button\" variant=\"ghost\">\n\t\t\t\t\t\t<Icon name=\"close\" />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n"],"mappings":";;;;;;;AAYA,MAAaA,UAAiC,EAC7C,WACA,UACA,SACA,eACK;CACL,MAAM,EAAE,OAAO,SAAS,kBAAkB;AAE1C,QACC,oBAAC;EAAI,WAAW,GAAG,sCAAsC,UAAU;YAClE,qBAAC;GAAI,WAAU;;IACd,qBAAC;KAAI,WAAU;gBACb,YACA,oBAAC;MACA,SAAS;MACT,MAAK;MACL,MAAK;MACL,SAAQ;gBAER,oBAACC,iBAAK,MAAK,eAAe;OAClB,EAET;MACI;IACL,WAAW,oBAAC;KAAI,WAAU;eAA2B;MAAc;IACnE,SAAS,gBACT,oBAAC;KAAO,SAAS;KAAO,MAAK;KAAO,MAAK;KAAS,SAAQ;eACzD,oBAACA,iBAAK,MAAK,UAAU;MACb;;IAEL;GACD"}
1
+ {"version":3,"file":"header.js","names":["Header: React.FC<HeaderProps>","Icon"],"sources":["../../../src/support/components/header.tsx"],"sourcesContent":["import { useSupportConfig } from \"../store\";\nimport { cn } from \"../utils\";\nimport { Button } from \"./button\";\nimport Icon from \"./icons\";\n\nexport type HeaderProps = {\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n\tactions?: React.ReactNode;\n\tonGoBack?: () => void;\n};\n\nexport const Header: React.FC<HeaderProps> = ({\n\tclassName,\n\tchildren,\n\tactions,\n\tonGoBack,\n}) => {\n\tconst { close } = useSupportConfig();\n\n\treturn (\n\t\t<div className={cn(\"absolute inset-x-0 top-0 z-10 h-18\", className)}>\n\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-between gap-3 px-4\">\n\t\t\t\t<div className=\"flex flex-1 items-center gap-3\">\n\t\t\t\t\t{onGoBack && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tonClick={onGoBack}\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"arrow-left\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t\t{actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n\t\t\t\t<Button onClick={close} size=\"icon\" type=\"button\" variant=\"ghost\">\n\t\t\t\t\t<Icon name=\"close\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n"],"mappings":";;;;;;;AAYA,MAAaA,UAAiC,EAC7C,WACA,UACA,SACA,eACK;CACL,MAAM,EAAE,UAAU,kBAAkB;AAEpC,QACC,oBAAC;EAAI,WAAW,GAAG,sCAAsC,UAAU;YAClE,qBAAC;GAAI,WAAU;;IACd,qBAAC;KAAI,WAAU;gBACb,YACA,oBAAC;MACA,SAAS;MACT,MAAK;MACL,MAAK;MACL,SAAQ;gBAER,oBAACC,iBAAK,MAAK,eAAe;OAClB,EAET;MACI;IACL,WAAW,oBAAC;KAAI,WAAU;eAA2B;MAAc;IACpE,oBAAC;KAAO,SAAS;KAAO,MAAK;KAAO,MAAK;KAAS,SAAQ;eACzD,oBAACA,iBAAK,MAAK,UAAU;MACb;;IACJ;GACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","names":[],"sources":["../../../src/support/components/icons.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA;KAEA,QAAA;AAFA,KAmBA,SAAA,GAnBW;EAEX,IAAA,EAkBL,QAlBa;EAiBR,OAAA,CAAA,EAED,WAFU;EAAA,SAAA,CAAA,EAAA,MAAA;eACd,CAAA,EAAA,OAAA;;AACe,cA6FT,IA7FS,EA6FH,KAAA,CAAM,EA7FH,CA6FM,SA7FN,CAAA;AA6FT,KAqGD,kBAAA,GAFX;EAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA;IAnG2B,OAAA,EAAA,MAAA;IAAT,MAAM,EAAA,MAAA;EAAE,CAAA;AAqG3B,CAAA"}
1
+ {"version":3,"file":"icons.d.ts","names":[],"sources":["../../../src/support/components/icons.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA;KAEA,QAAA;AAFA,KAmBA,SAAA,GAnBW;EAEX,IAAA,EAkBL,QAlBa;EAiBR,OAAA,CAAA,EAED,WAFU;EA+FR,SAmGZ,CAAA,EAAA,MAAA;EAEW,aAAA,CAAA,EAAA,OAAkB;;cArGjB,MAAM,KAAA,CAAM,GAAG;KAqGhB,kBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAWY,oBAAA;;EAAA,KAAA,EAAA,MAAA;EAAoB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;UAKR,EAAA,GAAA,GAAA,IAAA;cAIf,CAAA,EAAA,CAAA,KAAA,EAJe,IAIf,EAAA,EAAA,GAAA,IAAA;aACA,CAAA,EAAA,MAAA;EAAI,QAAA,CAAA,EAAA,OAAA;EAOA,YAAA,CAAA,EAAA,OA8JZ;EAAA,KAAA,CAAA,EAtKQ,KAsKR,GAAA,IAAA;OA9JsC,CAAA,EAP9B,IAO8B,EAAA;cAAH,CAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAE,QAAA,CAAA,EAAA,MAAA;EAgK1B,WAAA,CAAA,EAAA,MAAe;EAKd,gBAcZ,CAAA,EAAA,MAAA,EAAA;CAAA;AAdiC,cArKrB,eAqKqB,EArKJ,KAAA,CAAM,EAqKF,CArKK,oBAqKL,CAAA;AAAT,KALb,eAAA,GAKmB;EAAE,SAAA,CAAA,EAAA,MAAA;;;cAApB,YAAY,KAAA,CAAM,GAAG"}
1
+ {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAWY,oBAAA;;EAAA,KAAA,EAAA,MAAA;EAKY,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAIf,QAAA,EAAA,GAAA,GAAA,IAAA;EACA,YAAA,CAAA,EAAA,CAAA,KAAA,EALe,IAKf,EAAA,EAAA,GAAA,IAAA;EAAI,WAAA,CAAA,EAAA,MAAA;EAOA,QAAA,CAAA,EAAA,OA8JZ;EAEW,YAAA,CAAA,EAAA,OAAe;EAKd,KAAA,CAAA,EA7KJ,KA2LR,GAAA,IAAA;UA1LQ;;;;;;cAOI,iBAAiB,KAAA,CAAM,GAAG;KAgK3B,eAAA;;;;cAKC,YAAY,KAAA,CAAM,GAAG"}
@@ -3,13 +3,13 @@
3
3
 
4
4
  import { cn } from "../utils/index.js";
5
5
  import { Button } from "../../primitives/button.js";
6
- import { FileInput, MultimodalInput as MultimodalInput$1 } from "../../primitives/multimodal-input.js";
6
+ import { MultimodalInput as MultimodalInput$1 } from "../../primitives/multimodal-input.js";
7
7
  import icons_default from "./icons.js";
8
8
  import { useSupportText } from "../text/index.js";
9
9
  import { useComposerRefocus } from "../../hooks/use-composer-refocus.js";
10
10
  import { Watermark } from "./watermark.js";
11
11
  import { useRef } from "react";
12
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
13
 
14
14
  //#region src/support/components/multimodal-input.tsx
15
15
  const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, placeholder, disabled = false, isSubmitting = false, error, files = [], onRemoveFile, maxFiles = 5, maxFileSize = 10 * 1024 * 1024, allowedFileTypes = [
@@ -17,7 +17,7 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
17
17
  "application/pdf",
18
18
  "text/*"
19
19
  ] }) => {
20
- const fileInputRef = useRef(null);
20
+ useRef(null);
21
21
  const hasContent = value.trim().length > 0 || files.length > 0;
22
22
  const { focusComposer, inputRef } = useComposerRefocus({
23
23
  disabled,
@@ -36,9 +36,6 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
36
36
  e.preventDefault();
37
37
  handleSubmit();
38
38
  };
39
- const handleAttachClick = () => {
40
- if (files.length < maxFiles) fileInputRef.current?.click();
41
- };
42
39
  const formatFileSize = (bytes) => {
43
40
  if (bytes < 1024) return `${bytes} B`;
44
41
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -97,25 +94,9 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
97
94
  value
98
95
  }), /* @__PURE__ */ jsxs("div", {
99
96
  className: "flex items-center justify-between py-1 pr-1 pl-3",
100
- children: [/* @__PURE__ */ jsx(Watermark, {}), /* @__PURE__ */ jsxs("div", {
97
+ children: [/* @__PURE__ */ jsx(Watermark, {}), /* @__PURE__ */ jsx("div", {
101
98
  className: "flex items-center gap-0.5",
102
- children: [onFileSelect && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
103
- "aria-label": text("common.actions.attachFiles"),
104
- className: cn("group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50", files.length >= maxFiles && "opacity-50"),
105
- disabled: disabled || isSubmitting || files.length >= maxFiles,
106
- onClick: handleAttachClick,
107
- type: "button",
108
- children: /* @__PURE__ */ jsx(icons_default, {
109
- className: "h-4 w-4",
110
- name: "attachment"
111
- })
112
- }), /* @__PURE__ */ jsx(FileInput, {
113
- accept: allowedFileTypes.join(","),
114
- className: "hidden",
115
- disabled: disabled || isSubmitting || files.length >= maxFiles,
116
- onFileSelect,
117
- ref: fileInputRef
118
- })] }), /* @__PURE__ */ jsx(SendButton, { disabled: !canSubmit })]
99
+ children: /* @__PURE__ */ jsx(SendButton, { disabled: !canSubmit })
119
100
  })]
120
101
  })]
121
102
  })
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","Primitive.FileInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !(disabled || isSubmitting) && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\tfocusComposer();\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"flex flex-col rounded border border-co-border/50 bg-co-background-100 dark:bg-co-background-200\">\n\t\t\t\t<Primitive.MultimodalInput\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-primary/40 focus-visible:outline-none\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\terror={error}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tplaceholder={resolvedPlaceholder}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tvalue={value}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex items-center justify-between py-1 pr-1 pl-3\">\n\t\t\t\t\t<Watermark />\n\n\t\t\t\t\t<div className=\"flex items-center gap-0.5\">\n\t\t\t\t\t\t{/* File attachment button */}\n\t\t\t\t\t\t{onFileSelect && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.attachFiles\")}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t\t\t\tfiles.length >= maxFiles && \"opacity-50\"\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonClick={handleAttachClick}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" name=\"attachment\" />\n\t\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t\t<Primitive.FileInput\n\t\t\t\t\t\t\t\t\taccept={allowedFileTypes.join(\",\")}\n\t\t\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Send button */}\n\t\t\t\t\t\t<SendButton disabled={!canSubmit} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t);\n};\n\nexport type SendButtonProps = {\n\tclassName?: string;\n\tdisabled?: boolean;\n};\n\nexport const SendButton: React.FC<SendButtonProps> = ({\n\tclassName,\n\tdisabled = false,\n}) => (\n\t<Primitive.Button\n\t\tclassName={cn(\n\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-primary hover:bg-co-muted disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tclassName\n\t\t)}\n\t\tdisabled={disabled}\n\t\ttype=\"submit\"\n\t>\n\t\t<Icon className=\"h-4 w-4\" filledOnHover name=\"send\" />\n\t</Primitive.Button>\n);\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAaA,mBAAmD,EAC/D,WACA,OACA,UACA,UACA,cACA,aACA,WAAW,OACX,eAAe,OACf,OACA,QAAQ,EAAE,EACV,cACA,WAAW,GACX,cAAc,KAAK,OAAO,MAC1B,mBAAmB;CAAC;CAAW;CAAmB;CAAS,OACtD;CACL,MAAM,eAAe,OAAyB,KAAK;CACnD,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;CAC7D,MAAM,EAAE,eAAe,aAAa,mBAAmB;EACtD;EACA;EACA;EACA,CAAC;CACF,MAAM,YAAY,EAAE,YAAY,iBAAiB;CACjD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBACL,eAAe,KAAK,wCAAwC;CAE7D,MAAM,qBAAqB;AAC1B,MAAI,CAAC,UACJ;AAGD,YAAU;AACV,iBAAe;;CAGhB,MAAM,oBAAoB,MAAuB;AAChD,IAAE,gBAAgB;AAClB,gBAAc;;CAGf,MAAM,0BAA0B;AAC/B,MAAI,MAAM,SAAS,SAClB,cAAa,SAAS,OAAO;;CAI/B,MAAM,kBAAkB,UAAkB;AACzC,MAAI,QAAQ,KACX,QAAO,GAAG,MAAM;AAEjB,MAAI,QAAQ,OAAO,KAClB,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAErC,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,QACC,qBAAC;EAAK,WAAU;EAAsB,UAAU;;GAE9C,SACA,oBAAC;IACA,WAAU;IACV,IAAG;cAEF,MAAM;KACF;GAIN,MAAM,SAAS,KACf,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,MAAM,UACjB,qBAAC;KACA,WAAU;;MAGV,oBAACC;OAAK,WAAU;OAAU,MAAK;QAAe;MAC9C,oBAAC;OAAK,WAAU;iBAA0B,KAAK;QAAY;MAC3D,oBAAC;OAAK,WAAU;iBACd,eAAe,KAAK,KAAK;QACpB;MACN,gBACA,oBAAC;OACA,cAAY,KAAK,6BAA6B,EAC7C,UAAU,KAAK,MACf,CAAC;OACF,WAAU;OACV,eAAe,aAAa,MAAM;OAClC,MAAK;iBAEL,oBAACA;QAAK,WAAU;QAAU,MAAK;SAAU;QACjC;;OAjBL,GAAG,KAAK,KAAK,GAAG,QAmBhB,CACL;KACG;GAIP,qBAAC;IAAI,WAAU;eACd,oBAACC;KACA,WAAW,GACV,4HACA,UACA;KACD,UAAU,YAAY;KACf;KACG;KACI;KACd,UAAU;KACV,aAAa;KACb,KAAK;KACE;MACN,EAEF,qBAAC;KAAI,WAAU;gBACd,oBAAC,cAAY,EAEb,qBAAC;MAAI,WAAU;iBAEb,gBACA,4CACC,oBAAC;OACA,cAAY,KAAK,6BAA6B;OAC9C,WAAW,GACV,iLACA,MAAM,UAAU,YAAY,aAC5B;OACD,UACC,YAAY,gBAAgB,MAAM,UAAU;OAE7C,SAAS;OACT,MAAK;iBAEL,oBAACD;QAAK,WAAU;QAAU,MAAK;SAAe;QACtC,EAET,oBAACE;OACA,QAAQ,iBAAiB,KAAK,IAAI;OAClC,WAAU;OACV,UACC,YAAY,gBAAgB,MAAM,UAAU;OAE/B;OACd,KAAK;QACJ,IACA,EAIJ,oBAAC,cAAW,UAAU,CAAC,YAAa;OAC/B;MACD;KACD;;GACA;;AAST,MAAaC,cAAyC,EACrD,WACA,WAAW,YAEX,oBAACC;CACA,WAAW,GACV,+IACA,UACA;CACS;CACV,MAAK;WAEL,oBAACJ;EAAK,WAAU;EAAU;EAAc,MAAK;GAAS;EACpC"}
1
+ {"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !(disabled || isSubmitting) && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\tfocusComposer();\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"flex flex-col rounded border border-co-border/50 bg-co-background-100 dark:bg-co-background-200\">\n\t\t\t\t<Primitive.MultimodalInput\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-primary/40 focus-visible:outline-none\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\terror={error}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tplaceholder={resolvedPlaceholder}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tvalue={value}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex items-center justify-between py-1 pr-1 pl-3\">\n\t\t\t\t\t<Watermark />\n\n\t\t\t\t\t<div className=\"flex items-center gap-0.5\">\n\t\t\t\t\t\t{/* File attachment button */}\n\t\t\t\t\t\t{/* {onFileSelect && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.attachFiles\")}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t\t\t\tfiles.length >= maxFiles && \"opacity-50\"\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonClick={handleAttachClick}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" name=\"attachment\" />\n\t\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t\t<Primitive.FileInput\n\t\t\t\t\t\t\t\t\taccept={allowedFileTypes.join(\",\")}\n\t\t\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)} */}\n\n\t\t\t\t\t\t{/* Send button */}\n\t\t\t\t\t\t<SendButton disabled={!canSubmit} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t);\n};\n\nexport type SendButtonProps = {\n\tclassName?: string;\n\tdisabled?: boolean;\n};\n\nexport const SendButton: React.FC<SendButtonProps> = ({\n\tclassName,\n\tdisabled = false,\n}) => (\n\t<Primitive.Button\n\t\tclassName={cn(\n\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-primary hover:bg-co-muted disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tclassName\n\t\t)}\n\t\tdisabled={disabled}\n\t\ttype=\"submit\"\n\t>\n\t\t<Icon className=\"h-4 w-4\" filledOnHover name=\"send\" />\n\t</Primitive.Button>\n);\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAaA,mBAAmD,EAC/D,WACA,OACA,UACA,UACA,cACA,aACA,WAAW,OACX,eAAe,OACf,OACA,QAAQ,EAAE,EACV,cACA,WAAW,GACX,cAAc,KAAK,OAAO,MAC1B,mBAAmB;CAAC;CAAW;CAAmB;CAAS,OACtD;AACgB,QAAyB,KAAK;CACnD,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;CAC7D,MAAM,EAAE,eAAe,aAAa,mBAAmB;EACtD;EACA;EACA;EACA,CAAC;CACF,MAAM,YAAY,EAAE,YAAY,iBAAiB;CACjD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBACL,eAAe,KAAK,wCAAwC;CAE7D,MAAM,qBAAqB;AAC1B,MAAI,CAAC,UACJ;AAGD,YAAU;AACV,iBAAe;;CAGhB,MAAM,oBAAoB,MAAuB;AAChD,IAAE,gBAAgB;AAClB,gBAAc;;CASf,MAAM,kBAAkB,UAAkB;AACzC,MAAI,QAAQ,KACX,QAAO,GAAG,MAAM;AAEjB,MAAI,QAAQ,OAAO,KAClB,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAErC,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,QACC,qBAAC;EAAK,WAAU;EAAsB,UAAU;;GAE9C,SACA,oBAAC;IACA,WAAU;IACV,IAAG;cAEF,MAAM;KACF;GAIN,MAAM,SAAS,KACf,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,MAAM,UACjB,qBAAC;KACA,WAAU;;MAGV,oBAACC;OAAK,WAAU;OAAU,MAAK;QAAe;MAC9C,oBAAC;OAAK,WAAU;iBAA0B,KAAK;QAAY;MAC3D,oBAAC;OAAK,WAAU;iBACd,eAAe,KAAK,KAAK;QACpB;MACN,gBACA,oBAAC;OACA,cAAY,KAAK,6BAA6B,EAC7C,UAAU,KAAK,MACf,CAAC;OACF,WAAU;OACV,eAAe,aAAa,MAAM;OAClC,MAAK;iBAEL,oBAACA;QAAK,WAAU;QAAU,MAAK;SAAU;QACjC;;OAjBL,GAAG,KAAK,KAAK,GAAG,QAmBhB,CACL;KACG;GAIP,qBAAC;IAAI,WAAU;eACd,oBAACC;KACA,WAAW,GACV,4HACA,UACA;KACD,UAAU,YAAY;KACf;KACG;KACI;KACd,UAAU;KACV,aAAa;KACb,KAAK;KACE;MACN,EAEF,qBAAC;KAAI,WAAU;gBACd,oBAAC,cAAY,EAEb,oBAAC;MAAI,WAAU;gBAgCd,oBAAC,cAAW,UAAU,CAAC,YAAa;OAC/B;MACD;KACD;;GACA;;AAST,MAAaC,cAAyC,EACrD,WACA,WAAW,YAEX,oBAACC;CACA,WAAW,GACV,+IACA,UACA;CACS;CACV,MAAK;WAEL,oBAACH;EAAK,WAAU;EAAU;EAAc,MAAK;GAAS;EACpC"}
@@ -1,7 +1,12 @@
1
- import * as react_jsx_runtime6 from "react/jsx-runtime";
1
+ import { ReactElement } from "react";
2
2
 
3
3
  //#region src/support/components/navigation-tab.d.ts
4
- declare function NavigationTab(): react_jsx_runtime6.JSX.Element;
4
+
5
+ /**
6
+ * Tab bar used inside the widget header to switch between home and knowledge
7
+ * base views.
8
+ */
9
+ declare function NavigationTab(): ReactElement;
5
10
  //#endregion
6
11
  export { NavigationTab };
7
12
  //# sourceMappingURL=navigation-tab.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-tab.d.ts","names":[],"sources":["../../../src/support/components/navigation-tab.tsx"],"sourcesContent":[],"mappings":";;;iBAKgB,aAAA,CAAA,GAAa,kBAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"navigation-tab.d.ts","names":[],"sources":["../../../src/support/components/navigation-tab.tsx"],"sourcesContent":[],"mappings":";;;;;;AAWA;;iBAAgB,aAAA,CAAA,GAAiB"}
@@ -5,6 +5,10 @@ import { Text } from "../text/index.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
 
7
7
  //#region src/support/components/navigation-tab.tsx
8
+ /**
9
+ * Tab bar used inside the widget header to switch between home and knowledge
10
+ * base views.
11
+ */
8
12
  function NavigationTab() {
9
13
  const { current, navigate } = useSupportNavigation();
10
14
  return /* @__PURE__ */ jsxs("div", {