@cossistant/react 0.0.4 → 0.0.5

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 (319) hide show
  1. package/_virtual/rolldown_runtime.js +19 -0
  2. package/conversation.d.ts +26 -3
  3. package/conversation.d.ts.map +1 -1
  4. package/hooks/index.d.ts +5 -3
  5. package/hooks/index.js +7 -5
  6. package/hooks/private/store/use-conversations-store.d.ts +8 -0
  7. package/hooks/private/store/use-conversations-store.d.ts.map +1 -1
  8. package/hooks/private/store/use-conversations-store.js +8 -0
  9. package/hooks/private/store/use-conversations-store.js.map +1 -1
  10. package/hooks/private/store/use-store-selector.d.ts +4 -0
  11. package/hooks/private/store/use-store-selector.d.ts.map +1 -1
  12. package/hooks/private/store/use-store-selector.js +5 -2
  13. package/hooks/private/store/use-store-selector.js.map +1 -1
  14. package/hooks/private/store/use-website-store.d.ts +4 -0
  15. package/hooks/private/store/use-website-store.d.ts.map +1 -1
  16. package/hooks/private/store/use-website-store.js +6 -3
  17. package/hooks/private/store/use-website-store.js.map +1 -1
  18. package/hooks/private/typing.d.ts +35 -0
  19. package/hooks/private/typing.d.ts.map +1 -0
  20. package/hooks/private/typing.js +49 -0
  21. package/hooks/private/typing.js.map +1 -0
  22. package/hooks/private/use-client-query.d.ts +5 -0
  23. package/hooks/private/use-client-query.d.ts.map +1 -1
  24. package/hooks/private/use-client-query.js +5 -0
  25. package/hooks/private/use-client-query.js.map +1 -1
  26. package/hooks/private/use-grouped-messages.d.ts +10 -4
  27. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  28. package/hooks/private/use-grouped-messages.js +24 -4
  29. package/hooks/private/use-grouped-messages.js.map +1 -1
  30. package/hooks/private/use-multimodal-input.d.ts.map +1 -1
  31. package/hooks/private/use-rest-client.d.ts.map +1 -1
  32. package/hooks/private/use-visitor-typing-reporter.d.ts +6 -0
  33. package/hooks/private/use-visitor-typing-reporter.d.ts.map +1 -1
  34. package/hooks/private/use-visitor-typing-reporter.js +6 -0
  35. package/hooks/private/use-visitor-typing-reporter.js.map +1 -1
  36. package/hooks/use-composer-refocus.d.ts.map +1 -1
  37. package/hooks/use-conversation-auto-seen.d.ts +9 -0
  38. package/hooks/use-conversation-auto-seen.d.ts.map +1 -1
  39. package/hooks/use-conversation-auto-seen.js +44 -3
  40. package/hooks/use-conversation-auto-seen.js.map +1 -1
  41. package/hooks/use-conversation-history-page.d.ts.map +1 -1
  42. package/hooks/use-conversation-history-page.js +16 -18
  43. package/hooks/use-conversation-history-page.js.map +1 -1
  44. package/hooks/use-conversation-lifecycle.d.ts.map +1 -1
  45. package/hooks/use-conversation-lifecycle.js +2 -4
  46. package/hooks/use-conversation-lifecycle.js.map +1 -1
  47. package/hooks/use-conversation-page.d.ts +6 -0
  48. package/hooks/use-conversation-page.d.ts.map +1 -1
  49. package/hooks/use-conversation-page.js +41 -3
  50. package/hooks/use-conversation-page.js.map +1 -1
  51. package/hooks/use-conversation-preview.d.ts +61 -0
  52. package/hooks/use-conversation-preview.d.ts.map +1 -0
  53. package/hooks/use-conversation-preview.js +173 -0
  54. package/hooks/use-conversation-preview.js.map +1 -0
  55. package/hooks/use-conversation-seen.d.ts +4 -0
  56. package/hooks/use-conversation-seen.d.ts.map +1 -1
  57. package/hooks/use-conversation-seen.js +4 -0
  58. package/hooks/use-conversation-seen.js.map +1 -1
  59. package/hooks/use-conversation-timeline-items.d.ts +4 -0
  60. package/hooks/use-conversation-timeline-items.d.ts.map +1 -1
  61. package/hooks/use-conversation-timeline-items.js +4 -0
  62. package/hooks/use-conversation-timeline-items.js.map +1 -1
  63. package/hooks/use-conversation-timeline.d.ts +32 -0
  64. package/hooks/use-conversation-timeline.d.ts.map +1 -0
  65. package/hooks/use-conversation-timeline.js +41 -0
  66. package/hooks/use-conversation-timeline.js.map +1 -0
  67. package/hooks/use-conversation-typing.d.ts +4 -0
  68. package/hooks/use-conversation-typing.d.ts.map +1 -1
  69. package/hooks/use-conversation-typing.js +4 -0
  70. package/hooks/use-conversation-typing.js.map +1 -1
  71. package/hooks/use-conversation.d.ts +11 -0
  72. package/hooks/use-conversation.d.ts.map +1 -1
  73. package/hooks/use-conversation.js +11 -0
  74. package/hooks/use-conversation.js.map +1 -1
  75. package/hooks/use-conversations.d.ts +12 -0
  76. package/hooks/use-conversations.d.ts.map +1 -1
  77. package/hooks/use-conversations.js +12 -0
  78. package/hooks/use-conversations.js.map +1 -1
  79. package/hooks/use-create-conversation.d.ts +5 -0
  80. package/hooks/use-create-conversation.d.ts.map +1 -1
  81. package/hooks/use-create-conversation.js +12 -9
  82. package/hooks/use-create-conversation.js.map +1 -1
  83. package/hooks/use-home-page.d.ts.map +1 -1
  84. package/hooks/use-home-page.js +6 -4
  85. package/hooks/use-home-page.js.map +1 -1
  86. package/hooks/use-message-composer.d.ts.map +1 -1
  87. package/hooks/use-realtime-support.d.ts.map +1 -1
  88. package/hooks/use-send-message.d.ts +9 -0
  89. package/hooks/use-send-message.d.ts.map +1 -1
  90. package/hooks/use-send-message.js +15 -13
  91. package/hooks/use-send-message.js.map +1 -1
  92. package/hooks/use-visitor.d.ts.map +1 -1
  93. package/hooks/use-visitor.js +28 -30
  94. package/hooks/use-visitor.js.map +1 -1
  95. package/hooks/use-window-visibility-focus.d.ts +4 -0
  96. package/hooks/use-window-visibility-focus.d.ts.map +1 -1
  97. package/hooks/use-window-visibility-focus.js +5 -2
  98. package/hooks/use-window-visibility-focus.js.map +1 -1
  99. package/identify-visitor.d.ts +12 -3
  100. package/identify-visitor.d.ts.map +1 -1
  101. package/identify-visitor.js +58 -9
  102. package/identify-visitor.js.map +1 -1
  103. package/index.d.ts +10 -7
  104. package/index.js +10 -9
  105. package/package.json +11 -16
  106. package/primitives/avatar/avatar.d.ts.map +1 -1
  107. package/primitives/avatar/fallback.d.ts.map +1 -1
  108. package/primitives/avatar/fallback.js +1 -3
  109. package/primitives/avatar/fallback.js.map +1 -1
  110. package/primitives/avatar/image.d.ts.map +1 -1
  111. package/primitives/avatar/index.d.ts +1 -0
  112. package/primitives/bubble.d.ts +2 -0
  113. package/primitives/bubble.d.ts.map +1 -1
  114. package/primitives/bubble.js +8 -2
  115. package/primitives/bubble.js.map +1 -1
  116. package/primitives/button.d.ts.map +1 -1
  117. package/primitives/conversation-timeline.d.ts.map +1 -1
  118. package/primitives/conversation-timeline.js +58 -5
  119. package/primitives/conversation-timeline.js.map +1 -1
  120. package/primitives/index.d.ts +1 -0
  121. package/primitives/index.parts.d.ts +1 -0
  122. package/primitives/multimodal-input.d.ts.map +1 -1
  123. package/primitives/timeline-item-group.d.ts +7 -7
  124. package/primitives/timeline-item-group.d.ts.map +1 -1
  125. package/primitives/timeline-item-group.js.map +1 -1
  126. package/primitives/timeline-item.d.ts +1 -1
  127. package/primitives/timeline-item.d.ts.map +1 -1
  128. package/primitives/timeline-item.js +7 -1
  129. package/primitives/timeline-item.js.map +1 -1
  130. package/primitives/window.d.ts +1 -1
  131. package/primitives/window.d.ts.map +1 -1
  132. package/primitives/window.js +4 -4
  133. package/primitives/window.js.map +1 -1
  134. package/provider.d.ts +23 -43
  135. package/provider.d.ts.map +1 -1
  136. package/provider.js +152 -49
  137. package/provider.js.map +1 -1
  138. package/realtime/event-filter.d.ts +4 -0
  139. package/realtime/event-filter.d.ts.map +1 -1
  140. package/realtime/event-filter.js +4 -0
  141. package/realtime/event-filter.js.map +1 -1
  142. package/realtime/index.js +1 -1
  143. package/realtime/provider.d.ts +7 -2
  144. package/realtime/provider.d.ts.map +1 -1
  145. package/realtime/provider.js +23 -1
  146. package/realtime/provider.js.map +1 -1
  147. package/realtime/seen-store.d.ts +13 -0
  148. package/realtime/seen-store.d.ts.map +1 -1
  149. package/realtime/seen-store.js +14 -2
  150. package/realtime/seen-store.js.map +1 -1
  151. package/realtime/support-provider.d.ts +1 -2
  152. package/realtime/support-provider.d.ts.map +1 -1
  153. package/realtime/support-provider.js +19 -20
  154. package/realtime/support-provider.js.map +1 -1
  155. package/realtime/typing-store.d.ts +18 -0
  156. package/realtime/typing-store.d.ts.map +1 -1
  157. package/realtime/typing-store.js +19 -2
  158. package/realtime/typing-store.js.map +1 -1
  159. package/realtime/use-realtime.d.ts +8 -4
  160. package/realtime/use-realtime.d.ts.map +1 -1
  161. package/realtime/use-realtime.js +4 -0
  162. package/realtime/use-realtime.js.map +1 -1
  163. package/realtime-events.d.ts +17 -3
  164. package/realtime-events.d.ts.map +1 -1
  165. package/schemas.d.ts +7 -1
  166. package/schemas.d.ts.map +1 -1
  167. package/support/components/avatar-stack.d.ts +8 -4
  168. package/support/components/avatar-stack.d.ts.map +1 -1
  169. package/support/components/avatar-stack.js +4 -0
  170. package/support/components/avatar-stack.js.map +1 -1
  171. package/support/components/avatar.d.ts +11 -6
  172. package/support/components/avatar.d.ts.map +1 -1
  173. package/support/components/avatar.js +4 -0
  174. package/support/components/avatar.js.map +1 -1
  175. package/support/components/bubble.d.ts.map +1 -1
  176. package/support/components/bubble.js +29 -6
  177. package/support/components/bubble.js.map +1 -1
  178. package/support/components/button.d.ts +8 -5
  179. package/support/components/button.d.ts.map +1 -1
  180. package/support/components/button.js +5 -1
  181. package/support/components/button.js.map +1 -1
  182. package/support/components/container.d.ts +0 -1
  183. package/support/components/container.d.ts.map +1 -1
  184. package/support/components/container.js +2 -8
  185. package/support/components/container.js.map +1 -1
  186. package/support/components/conversation-button-link.d.ts +8 -21
  187. package/support/components/conversation-button-link.d.ts.map +1 -1
  188. package/support/components/conversation-button-link.js +62 -178
  189. package/support/components/conversation-button-link.js.map +1 -1
  190. package/support/components/conversation-event.d.ts.map +1 -1
  191. package/support/components/conversation-event.js +4 -0
  192. package/support/components/conversation-event.js.map +1 -1
  193. package/support/components/conversation-timeline.d.ts +10 -1
  194. package/support/components/conversation-timeline.d.ts.map +1 -1
  195. package/support/components/conversation-timeline.js +63 -57
  196. package/support/components/conversation-timeline.js.map +1 -1
  197. package/support/components/cossistant-branding.d.ts +5 -2
  198. package/support/components/cossistant-branding.d.ts.map +1 -1
  199. package/support/components/cossistant-branding.js +3 -0
  200. package/support/components/cossistant-branding.js.map +1 -1
  201. package/support/components/header.d.ts.map +1 -1
  202. package/support/components/header.js +2 -2
  203. package/support/components/header.js.map +1 -1
  204. package/support/components/icons.d.ts.map +1 -1
  205. package/support/components/multimodal-input.d.ts.map +1 -1
  206. package/support/components/multimodal-input.js +5 -24
  207. package/support/components/multimodal-input.js.map +1 -1
  208. package/support/components/navigation-tab.d.ts +7 -2
  209. package/support/components/navigation-tab.d.ts.map +1 -1
  210. package/support/components/navigation-tab.js +4 -0
  211. package/support/components/navigation-tab.js.map +1 -1
  212. package/support/components/support-content.d.ts +1 -1
  213. package/support/components/support-content.d.ts.map +1 -1
  214. package/support/components/support-content.js +7 -10
  215. package/support/components/support-content.js.map +1 -1
  216. package/support/components/text-effect.d.ts +5 -2
  217. package/support/components/text-effect.d.ts.map +1 -1
  218. package/support/components/text-effect.js +4 -0
  219. package/support/components/text-effect.js.map +1 -1
  220. package/support/components/timeline-identification-tool.d.ts +7 -0
  221. package/support/components/timeline-identification-tool.d.ts.map +1 -0
  222. package/support/components/timeline-identification-tool.js +139 -0
  223. package/support/components/timeline-identification-tool.js.map +1 -0
  224. package/support/components/timeline-message-group.d.ts +2 -1
  225. package/support/components/timeline-message-group.d.ts.map +1 -1
  226. package/support/components/timeline-message-group.js +4 -19
  227. package/support/components/timeline-message-group.js.map +1 -1
  228. package/support/components/timeline-message-item.d.ts +6 -2
  229. package/support/components/timeline-message-item.d.ts.map +1 -1
  230. package/support/components/timeline-message-item.js +8 -4
  231. package/support/components/timeline-message-item.js.map +1 -1
  232. package/support/components/typing-indicator.d.ts +5 -2
  233. package/support/components/typing-indicator.d.ts.map +1 -1
  234. package/support/components/typing-indicator.js +4 -4
  235. package/support/components/typing-indicator.js.map +1 -1
  236. package/support/components/watermark.d.ts.map +1 -1
  237. package/support/context/websocket.d.ts +8 -0
  238. package/support/context/websocket.d.ts.map +1 -1
  239. package/support/context/websocket.js +12 -6
  240. package/support/context/websocket.js.map +1 -1
  241. package/support/index.d.ts +8 -8
  242. package/support/index.d.ts.map +1 -1
  243. package/support/index.js +18 -18
  244. package/support/index.js.map +1 -1
  245. package/support/pages/conversation-history.js +46 -54
  246. package/support/pages/conversation-history.js.map +1 -1
  247. package/support/pages/conversation.d.ts +3 -6
  248. package/support/pages/conversation.d.ts.map +1 -1
  249. package/support/pages/conversation.js +19 -9
  250. package/support/pages/conversation.js.map +1 -1
  251. package/support/pages/home.d.ts +2 -2
  252. package/support/pages/home.d.ts.map +1 -1
  253. package/support/pages/home.js +64 -77
  254. package/support/pages/home.js.map +1 -1
  255. package/support/store/support-store.d.ts +18 -2
  256. package/support/store/support-store.d.ts.map +1 -1
  257. package/support/store/support-store.js +20 -5
  258. package/support/store/support-store.js.map +1 -1
  259. package/support/{support-CMoDLQoC.css → support-Ck4jy29i.css} +1 -2
  260. package/support/support-Ck4jy29i.css.map +1 -0
  261. package/support/text/index.d.ts +15 -2
  262. package/support/text/index.d.ts.map +1 -1
  263. package/support/text/index.js +15 -2
  264. package/support/text/index.js.map +1 -1
  265. package/support/text/locales/en.js +22 -4
  266. package/support/text/locales/en.js.map +1 -1
  267. package/support/text/locales/es.js +18 -0
  268. package/support/text/locales/es.js.map +1 -1
  269. package/support/text/locales/fr.js +18 -0
  270. package/support/text/locales/fr.js.map +1 -1
  271. package/support/text/locales/keys.d.ts +69 -9
  272. package/support/text/locales/keys.d.ts.map +1 -1
  273. package/support/text/locales/keys.js +18 -0
  274. package/support/text/locales/keys.js.map +1 -1
  275. package/support/text/runtime.d.ts +21 -0
  276. package/support/text/runtime.d.ts.map +1 -1
  277. package/support/text/runtime.js +21 -0
  278. package/support/text/runtime.js.map +1 -1
  279. package/support/utils/index.d.ts +4 -0
  280. package/support/utils/index.d.ts.map +1 -1
  281. package/support/utils/index.js +4 -1
  282. package/support/utils/index.js.map +1 -1
  283. package/support/utils/time.d.ts +3 -0
  284. package/support/utils/time.d.ts.map +1 -1
  285. package/support/utils/time.js +3 -0
  286. package/support/utils/time.js.map +1 -1
  287. package/support-config.d.ts +2 -1
  288. package/support-config.d.ts.map +1 -1
  289. package/support-config.js.map +1 -1
  290. package/support.css +2 -2
  291. package/timeline-item.d.ts +10 -0
  292. package/timeline-item.d.ts.map +1 -1
  293. package/utils/conversation.d.ts +7 -0
  294. package/utils/conversation.d.ts.map +1 -0
  295. package/utils/conversation.js +18 -0
  296. package/utils/conversation.js.map +1 -0
  297. package/utils/id.d.ts +3 -0
  298. package/utils/id.d.ts.map +1 -1
  299. package/utils/id.js +3 -0
  300. package/utils/id.js.map +1 -1
  301. package/utils/index.d.ts +2 -1
  302. package/utils/index.js +2 -1
  303. package/utils/metadata-hash.d.ts +12 -0
  304. package/utils/metadata-hash.d.ts.map +1 -0
  305. package/utils/metadata-hash.js +26 -0
  306. package/utils/metadata-hash.js.map +1 -0
  307. package/utils/text.d.ts +3 -0
  308. package/utils/text.d.ts.map +1 -1
  309. package/utils/text.js +3 -0
  310. package/utils/text.js.map +1 -1
  311. package/utils/use-render-element.d.ts +3 -0
  312. package/utils/use-render-element.d.ts.map +1 -1
  313. package/utils/use-render-element.js +3 -0
  314. package/utils/use-render-element.js.map +1 -1
  315. package/support/context/config.d.ts +0 -32
  316. package/support/context/config.d.ts.map +0 -1
  317. package/support/context/config.js +0 -27
  318. package/support/context/config.js.map +0 -1
  319. package/support/support-CMoDLQoC.css.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-conversation-typing.js","names":["excludeOptions: Required<UseConversationTypingOptions>"],"sources":["../../src/hooks/use-conversation-typing.ts"],"sourcesContent":["import type { TypingEntry } from \"@cossistant/core\";\nimport { useMemo } from \"react\";\nimport { useTypingStore } from \"../realtime/typing-store\";\n\nexport type ConversationTypingParticipant = TypingEntry;\n\ntype UseConversationTypingOptions = {\n\texcludeVisitorId?: string | null;\n\texcludeUserId?: string | null;\n\texcludeAiAgentId?: string | null;\n};\n\nfunction shouldExclude(\n\tentry: TypingEntry,\n\toptions: Required<UseConversationTypingOptions>\n) {\n\tif (entry.actorType === \"visitor\" && options.excludeVisitorId) {\n\t\treturn entry.actorId === options.excludeVisitorId;\n\t}\n\n\tif (entry.actorType === \"user\" && options.excludeUserId) {\n\t\treturn entry.actorId === options.excludeUserId;\n\t}\n\n\tif (entry.actorType === \"ai_agent\" && options.excludeAiAgentId) {\n\t\treturn entry.actorId === options.excludeAiAgentId;\n\t}\n\n\treturn false;\n}\n\nexport function useConversationTyping(\n\tconversationId: string | null | undefined,\n\toptions: UseConversationTypingOptions = {}\n): ConversationTypingParticipant[] {\n\tconst conversationTyping = useTypingStore((state) =>\n\t\tconversationId ? (state.conversations[conversationId] ?? null) : null\n\t);\n\n\treturn useMemo(() => {\n\t\tif (!(conversationId && conversationTyping)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst excludeOptions: Required<UseConversationTypingOptions> = {\n\t\t\texcludeVisitorId: options.excludeVisitorId ?? null,\n\t\t\texcludeUserId: options.excludeUserId ?? null,\n\t\t\texcludeAiAgentId: options.excludeAiAgentId ?? null,\n\t\t};\n\n\t\tconst entries = Object.values(conversationTyping).filter(\n\t\t\t(entry) => !shouldExclude(entry, excludeOptions)\n\t\t);\n\n\t\tentries.sort((a, b) => a.updatedAt - b.updatedAt);\n\n\t\treturn entries;\n\t}, [\n\t\tconversationId,\n\t\tconversationTyping,\n\t\toptions.excludeVisitorId,\n\t\toptions.excludeUserId,\n\t\toptions.excludeAiAgentId,\n\t]);\n}\n"],"mappings":";;;;AAYA,SAAS,cACR,OACA,SACC;AACD,KAAI,MAAM,cAAc,aAAa,QAAQ,iBAC5C,QAAO,MAAM,YAAY,QAAQ;AAGlC,KAAI,MAAM,cAAc,UAAU,QAAQ,cACzC,QAAO,MAAM,YAAY,QAAQ;AAGlC,KAAI,MAAM,cAAc,cAAc,QAAQ,iBAC7C,QAAO,MAAM,YAAY,QAAQ;AAGlC,QAAO;;AAGR,SAAgB,sBACf,gBACA,UAAwC,EAAE,EACR;CAClC,MAAM,qBAAqB,gBAAgB,UAC1C,iBAAkB,MAAM,cAAc,mBAAmB,OAAQ,KACjE;AAED,QAAO,cAAc;AACpB,MAAI,EAAE,kBAAkB,oBACvB,QAAO,EAAE;EAGV,MAAMA,iBAAyD;GAC9D,kBAAkB,QAAQ,oBAAoB;GAC9C,eAAe,QAAQ,iBAAiB;GACxC,kBAAkB,QAAQ,oBAAoB;GAC9C;EAED,MAAM,UAAU,OAAO,OAAO,mBAAmB,CAAC,QAChD,UAAU,CAAC,cAAc,OAAO,eAAe,CAChD;AAED,UAAQ,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;AAEjD,SAAO;IACL;EACF;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,CAAC"}
1
+ {"version":3,"file":"use-conversation-typing.js","names":["excludeOptions: Required<UseConversationTypingOptions>"],"sources":["../../src/hooks/use-conversation-typing.ts"],"sourcesContent":["import type { TypingEntry } from \"@cossistant/core\";\nimport { useMemo } from \"react\";\nimport { useTypingStore } from \"../realtime/typing-store\";\n\nexport type ConversationTypingParticipant = TypingEntry;\n\ntype UseConversationTypingOptions = {\n\texcludeVisitorId?: string | null;\n\texcludeUserId?: string | null;\n\texcludeAiAgentId?: string | null;\n};\n\nfunction shouldExclude(\n\tentry: TypingEntry,\n\toptions: Required<UseConversationTypingOptions>\n) {\n\tif (entry.actorType === \"visitor\" && options.excludeVisitorId) {\n\t\treturn entry.actorId === options.excludeVisitorId;\n\t}\n\n\tif (entry.actorType === \"user\" && options.excludeUserId) {\n\t\treturn entry.actorId === options.excludeUserId;\n\t}\n\n\tif (entry.actorType === \"ai_agent\" && options.excludeAiAgentId) {\n\t\treturn entry.actorId === options.excludeAiAgentId;\n\t}\n\n\treturn false;\n}\n\n/**\n * Selects typing participants for a conversation while letting consumers omit\n * their own identities.\n */\nexport function useConversationTyping(\n\tconversationId: string | null | undefined,\n\toptions: UseConversationTypingOptions = {}\n): ConversationTypingParticipant[] {\n\tconst conversationTyping = useTypingStore((state) =>\n\t\tconversationId ? (state.conversations[conversationId] ?? null) : null\n\t);\n\n\treturn useMemo(() => {\n\t\tif (!(conversationId && conversationTyping)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst excludeOptions: Required<UseConversationTypingOptions> = {\n\t\t\texcludeVisitorId: options.excludeVisitorId ?? null,\n\t\t\texcludeUserId: options.excludeUserId ?? null,\n\t\t\texcludeAiAgentId: options.excludeAiAgentId ?? null,\n\t\t};\n\n\t\tconst entries = Object.values(conversationTyping).filter(\n\t\t\t(entry) => !shouldExclude(entry, excludeOptions)\n\t\t);\n\n\t\tentries.sort((a, b) => a.updatedAt - b.updatedAt);\n\n\t\treturn entries;\n\t}, [\n\t\tconversationId,\n\t\tconversationTyping,\n\t\toptions.excludeVisitorId,\n\t\toptions.excludeUserId,\n\t\toptions.excludeAiAgentId,\n\t]);\n}\n"],"mappings":";;;;AAYA,SAAS,cACR,OACA,SACC;AACD,KAAI,MAAM,cAAc,aAAa,QAAQ,iBAC5C,QAAO,MAAM,YAAY,QAAQ;AAGlC,KAAI,MAAM,cAAc,UAAU,QAAQ,cACzC,QAAO,MAAM,YAAY,QAAQ;AAGlC,KAAI,MAAM,cAAc,cAAc,QAAQ,iBAC7C,QAAO,MAAM,YAAY,QAAQ;AAGlC,QAAO;;;;;;AAOR,SAAgB,sBACf,gBACA,UAAwC,EAAE,EACR;CAClC,MAAM,qBAAqB,gBAAgB,UAC1C,iBAAkB,MAAM,cAAc,mBAAmB,OAAQ,KACjE;AAED,QAAO,cAAc;AACpB,MAAI,EAAE,kBAAkB,oBACvB,QAAO,EAAE;EAGV,MAAMA,iBAAyD;GAC9D,kBAAkB,QAAQ,oBAAoB;GAC9C,eAAe,QAAQ,iBAAiB;GACxC,kBAAkB,QAAQ,oBAAoB;GAC9C;EAED,MAAM,UAAU,OAAO,OAAO,mBAAmB,CAAC,QAChD,UAAU,CAAC,cAAc,OAAO,eAAe,CAChD;AAED,UAAQ,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU;AAEjD,SAAO;IACL;EACF;EACA;EACA,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,CAAC"}
@@ -12,6 +12,17 @@ type UseConversationResult = {
12
12
  error: Error | null;
13
13
  refetch: (args?: GetConversationRequest) => Promise<GetConversationResponse | undefined>;
14
14
  };
15
+ /**
16
+ * Loads and caches a single conversation identified by `conversationId`.
17
+ *
18
+ * The hook keeps the conversations store hydrated, exposes a derived loading
19
+ * state that respects cached data and provides a `refetch` helper to manually
20
+ * refresh the thread.
21
+ *
22
+ * @param conversationId The conversation to retrieve; when `null` the hook
23
+ * skips requests and returns `null` data.
24
+ * @param options Additional react-query style controls for the request.
25
+ */
15
26
  declare function useConversation(conversationId: string | null, options?: UseConversationOptions): UseConversationResult;
16
27
  //#endregion
17
28
  export { UseConversationOptions, UseConversationResult, useConversation };
@@ -1 +1 @@
1
- {"version":3,"file":"use-conversation.d.ts","names":[],"sources":["../../src/hooks/use-conversation.ts"],"sourcesContent":[],"mappings":";;;KAQY,sBAAA;;EAAA,eAAA,CAAA,EAAA,MAAA,GAAsB,KAAA;EAMtB,oBAAA,CAAA,EAAA,OAAqB;CAAA;AAClB,KADH,qBAAA,GACG;cAEP,EAFO,uBAEP,CAAA,cAAA,CAAA,GAAA,IAAA;WAEC,EAAA,OAAA;OACK,EAHN,KAGM,GAAA,IAAA;SAAR,EAAA,CAAA,IAAA,CAAA,EADG,sBACH,EAAA,GAAA,OAAA,CAAQ,uBAAR,GAAA,SAAA,CAAA;CAAO;AAGG,iBAAA,eAAA,CAAe,cAAA,EAAA,MAAA,GAAA,IAAA,EAAA,OAAA,CAAA,EAErB,sBAFqB,CAAA,EAG5B,qBAH4B"}
1
+ {"version":3,"file":"use-conversation.d.ts","names":[],"sources":["../../src/hooks/use-conversation.ts"],"sourcesContent":[],"mappings":";;;KAQY,sBAAA;;EAAA,eAAA,CAAA,EAAA,MAAA,GAAsB,KAAA;EAMtB,oBAAA,CAAA,EAAA,OAAqB;CAClB;AAEP,KAHI,qBAAA,GAGJ;EAEC,YAAA,EAJM,uBAIN,CAAA,cAAA,CAAA,GAAA,IAAA;EACK,SAAA,EAAA,OAAA;EAAR,KAAA,EAHE,KAGF,GAAA,IAAA;EAAO,OAAA,EAAA,CAAA,IAAA,CAAA,EADJ,sBACI,EAAA,GAAP,OAAO,CAAC,uBAAD,GAAA,SAAA,CAAA;AAcb,CAAA;;;;;;;;;;;;iBAAgB,eAAA,0CAEN,yBACP"}
@@ -3,6 +3,17 @@ import { useStoreSelector } from "./private/store/use-store-selector.js";
3
3
  import { useSupport } from "../provider.js";
4
4
 
5
5
  //#region src/hooks/use-conversation.ts
6
+ /**
7
+ * Loads and caches a single conversation identified by `conversationId`.
8
+ *
9
+ * The hook keeps the conversations store hydrated, exposes a derived loading
10
+ * state that respects cached data and provides a `refetch` helper to manually
11
+ * refresh the thread.
12
+ *
13
+ * @param conversationId The conversation to retrieve; when `null` the hook
14
+ * skips requests and returns `null` data.
15
+ * @param options Additional react-query style controls for the request.
16
+ */
6
17
  function useConversation(conversationId, options = {}) {
7
18
  const { client } = useSupport();
8
19
  const store = client.conversationsStore;
@@ -1 +1 @@
1
- {"version":3,"file":"use-conversation.js","names":["request: GetConversationRequest | undefined"],"sources":["../../src/hooks/use-conversation.ts"],"sourcesContent":["import type {\n\tGetConversationRequest,\n\tGetConversationResponse,\n} from \"@cossistant/types/api/conversation\";\nimport { useSupport } from \"../provider\";\nimport { useStoreSelector } from \"./private/store/use-store-selector\";\nimport { useClientQuery } from \"./private/use-client-query\";\n\nexport type UseConversationOptions = {\n\tenabled?: boolean;\n\trefetchInterval?: number | false;\n\trefetchOnWindowFocus?: boolean;\n};\n\nexport type UseConversationResult = {\n\tconversation: GetConversationResponse[\"conversation\"] | null;\n\tisLoading: boolean;\n\terror: Error | null;\n\trefetch: (\n\t\targs?: GetConversationRequest\n\t) => Promise<GetConversationResponse | undefined>;\n};\n\nexport function useConversation(\n\tconversationId: string | null,\n\toptions: UseConversationOptions = {}\n): UseConversationResult {\n\tconst { client } = useSupport();\n\tconst store = client.conversationsStore;\n\n\tconst conversation = useStoreSelector(store, (state) => {\n\t\tif (!conversationId) {\n\t\t\treturn null;\n\t\t}\n\t\treturn state.byId[conversationId] ?? null;\n\t});\n\n\tconst request: GetConversationRequest | undefined = conversationId\n\t\t? { conversationId }\n\t\t: undefined;\n\n\tconst {\n\t\trefetch: queryRefetch,\n\t\tisLoading: queryLoading,\n\t\terror,\n\t} = useClientQuery<GetConversationResponse, GetConversationRequest>({\n\t\tclient,\n\t\tqueryFn: (instance) => {\n\t\t\tif (!request) {\n\t\t\t\tthrow new Error(\"Conversation ID is required\");\n\t\t\t}\n\t\t\treturn instance.getConversation(request);\n\t\t},\n\t\tenabled: Boolean(conversationId && (options.enabled ?? true)),\n\t\trefetchInterval: options.refetchInterval ?? false,\n\t\trefetchOnWindowFocus: options.refetchOnWindowFocus ?? true,\n\t\trefetchOnMount: !conversation,\n\t\tinitialArgs: request,\n\t\tdependencies: [conversationId ?? \"null\"],\n\t});\n\n\tconst refetch = (args?: GetConversationRequest) => {\n\t\tif (!conversationId) {\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\n\t\treturn queryRefetch({\n\t\t\tconversationId,\n\t\t\t...args,\n\t\t});\n\t};\n\n\tconst isLoading = conversation ? false : queryLoading;\n\n\treturn {\n\t\tconversation,\n\t\tisLoading,\n\t\terror,\n\t\trefetch,\n\t};\n}\n"],"mappings":";;;;;AAuBA,SAAgB,gBACf,gBACA,UAAkC,EAAE,EACZ;CACxB,MAAM,EAAE,WAAW,YAAY;CAC/B,MAAM,QAAQ,OAAO;CAErB,MAAM,eAAe,iBAAiB,QAAQ,UAAU;AACvD,MAAI,CAAC,eACJ,QAAO;AAER,SAAO,MAAM,KAAK,mBAAmB;GACpC;CAEF,MAAMA,UAA8C,iBACjD,EAAE,gBAAgB,GAClB;CAEH,MAAM,EACL,SAAS,cACT,WAAW,cACX,UACG,eAAgE;EACnE;EACA,UAAU,aAAa;AACtB,OAAI,CAAC,QACJ,OAAM,IAAI,MAAM,8BAA8B;AAE/C,UAAO,SAAS,gBAAgB,QAAQ;;EAEzC,SAAS,QAAQ,mBAAmB,QAAQ,WAAW,MAAM;EAC7D,iBAAiB,QAAQ,mBAAmB;EAC5C,sBAAsB,QAAQ,wBAAwB;EACtD,gBAAgB,CAAC;EACjB,aAAa;EACb,cAAc,CAAC,kBAAkB,OAAO;EACxC,CAAC;CAEF,MAAM,WAAW,SAAkC;AAClD,MAAI,CAAC,eACJ,QAAO,QAAQ,QAAQ,OAAU;AAGlC,SAAO,aAAa;GACnB;GACA,GAAG;GACH,CAAC;;AAKH,QAAO;EACN;EACA,WAJiB,eAAe,QAAQ;EAKxC;EACA;EACA"}
1
+ {"version":3,"file":"use-conversation.js","names":["request: GetConversationRequest | undefined"],"sources":["../../src/hooks/use-conversation.ts"],"sourcesContent":["import type {\n\tGetConversationRequest,\n\tGetConversationResponse,\n} from \"@cossistant/types/api/conversation\";\nimport { useSupport } from \"../provider\";\nimport { useStoreSelector } from \"./private/store/use-store-selector\";\nimport { useClientQuery } from \"./private/use-client-query\";\n\nexport type UseConversationOptions = {\n\tenabled?: boolean;\n\trefetchInterval?: number | false;\n\trefetchOnWindowFocus?: boolean;\n};\n\nexport type UseConversationResult = {\n\tconversation: GetConversationResponse[\"conversation\"] | null;\n\tisLoading: boolean;\n\terror: Error | null;\n\trefetch: (\n\t\targs?: GetConversationRequest\n\t) => Promise<GetConversationResponse | undefined>;\n};\n\n/**\n * Loads and caches a single conversation identified by `conversationId`.\n *\n * The hook keeps the conversations store hydrated, exposes a derived loading\n * state that respects cached data and provides a `refetch` helper to manually\n * refresh the thread.\n *\n * @param conversationId The conversation to retrieve; when `null` the hook\n * skips requests and returns `null` data.\n * @param options Additional react-query style controls for the request.\n */\nexport function useConversation(\n\tconversationId: string | null,\n\toptions: UseConversationOptions = {}\n): UseConversationResult {\n\tconst { client } = useSupport();\n\tconst store = client.conversationsStore;\n\n\tconst conversation = useStoreSelector(store, (state) => {\n\t\tif (!conversationId) {\n\t\t\treturn null;\n\t\t}\n\t\treturn state.byId[conversationId] ?? null;\n\t});\n\n\tconst request: GetConversationRequest | undefined = conversationId\n\t\t? { conversationId }\n\t\t: undefined;\n\n\tconst {\n\t\trefetch: queryRefetch,\n\t\tisLoading: queryLoading,\n\t\terror,\n\t} = useClientQuery<GetConversationResponse, GetConversationRequest>({\n\t\tclient,\n\t\tqueryFn: (instance) => {\n\t\t\tif (!request) {\n\t\t\t\tthrow new Error(\"Conversation ID is required\");\n\t\t\t}\n\t\t\treturn instance.getConversation(request);\n\t\t},\n\t\tenabled: Boolean(conversationId && (options.enabled ?? true)),\n\t\trefetchInterval: options.refetchInterval ?? false,\n\t\trefetchOnWindowFocus: options.refetchOnWindowFocus ?? true,\n\t\trefetchOnMount: !conversation,\n\t\tinitialArgs: request,\n\t\tdependencies: [conversationId ?? \"null\"],\n\t});\n\n\tconst refetch = (args?: GetConversationRequest) => {\n\t\tif (!conversationId) {\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\n\t\treturn queryRefetch({\n\t\t\tconversationId,\n\t\t\t...args,\n\t\t});\n\t};\n\n\tconst isLoading = conversation ? false : queryLoading;\n\n\treturn {\n\t\tconversation,\n\t\tisLoading,\n\t\terror,\n\t\trefetch,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,SAAgB,gBACf,gBACA,UAAkC,EAAE,EACZ;CACxB,MAAM,EAAE,WAAW,YAAY;CAC/B,MAAM,QAAQ,OAAO;CAErB,MAAM,eAAe,iBAAiB,QAAQ,UAAU;AACvD,MAAI,CAAC,eACJ,QAAO;AAER,SAAO,MAAM,KAAK,mBAAmB;GACpC;CAEF,MAAMA,UAA8C,iBACjD,EAAE,gBAAgB,GAClB;CAEH,MAAM,EACL,SAAS,cACT,WAAW,cACX,UACG,eAAgE;EACnE;EACA,UAAU,aAAa;AACtB,OAAI,CAAC,QACJ,OAAM,IAAI,MAAM,8BAA8B;AAE/C,UAAO,SAAS,gBAAgB,QAAQ;;EAEzC,SAAS,QAAQ,mBAAmB,QAAQ,WAAW,MAAM;EAC7D,iBAAiB,QAAQ,mBAAmB;EAC5C,sBAAsB,QAAQ,wBAAwB;EACtD,gBAAgB,CAAC;EACjB,aAAa;EACb,cAAc,CAAC,kBAAkB,OAAO;EACxC,CAAC;CAEF,MAAM,WAAW,SAAkC;AAClD,MAAI,CAAC,eACJ,QAAO,QAAQ,QAAQ,OAAU;AAGlC,SAAO,aAAa;GACnB;GACA,GAAG;GACH,CAAC;;AAKH,QAAO;EACN;EACA,WAJiB,eAAe,QAAQ;EAKxC;EACA;EACA"}
@@ -14,6 +14,18 @@ type UseConversationsResult = {
14
14
  error: Error | null;
15
15
  refetch: (args?: Partial<ListConversationsRequest>) => Promise<ListConversationsResponse | undefined>;
16
16
  };
17
+ /**
18
+ * Fetches and subscribes to the authenticated visitor's conversation list.
19
+ *
20
+ * The hook keeps the store in sync with the REST client and exposes
21
+ * pagination metadata plus a refetch helper for manual refreshes. The
22
+ * `options` mirror the public API filters so the UI can request slices of the
23
+ * inbox without duplicating data-fetching logic.
24
+ *
25
+ * @param options Filtering and lifecycle controls for the query.
26
+ * @returns Conversations, pagination data, loading state, and a refetch
27
+ * helper.
28
+ */
17
29
  declare function useConversations(options?: UseConversationsOptions): UseConversationsResult;
18
30
  //#endregion
19
31
  export { UseConversationsOptions, UseConversationsResult, useConversations };
@@ -1 +1 @@
1
- {"version":3,"file":"use-conversations.d.ts","names":[],"sources":["../../src/hooks/use-conversations.ts"],"sourcesContent":[],"mappings":";;;;KA0CY,uBAAA,GAA0B,QACrC,KAAK;;EADM,eAAA,CAAA,EAAA,MAAA,GAAuB,KAAA;EAAA,oBAAA,CAAA,EAAA,OAAA;;AAClC,KAOW,sBAAA,GAPX;eADqC,EAStB,yBATsB,CAAA,eAAA,CAAA;EAAO,UAAA,EAUhC,sBAVgC,GAAA,IAAA;EAQjC,SAAA,EAAA,OAAA;EAAsB,KAAA,EAI1B,KAJ0B,GAAA,IAAA;SAClB,EAAA,CAAA,IAAA,CAAA,EAKP,OALO,CAKC,wBALD,CAAA,EAAA,GAMV,OANU,CAMF,yBANE,GAAA,SAAA,CAAA;;AAGR,iBAMQ,gBAAA,CANR,OAAA,CAAA,EAOE,uBAPF,CAAA,EAQL,sBARK"}
1
+ {"version":3,"file":"use-conversations.d.ts","names":[],"sources":["../../src/hooks/use-conversations.ts"],"sourcesContent":[],"mappings":";;;;KA0CY,uBAAA,GAA0B,QACrC,KAAK;;EADM,eAAA,CAAA,EAAA,MAAA,GAAuB,KAAA;EAC7B,oBAAA,CAAA,EAAA,OAAA;CAAL;AADqC,KAQ1B,sBAAA,GAR0B;EAAO,aAAA,EAS7B,yBAT6B,CAAA,eAAA,CAAA;EAQjC,UAAA,EAEC,sBAFqB,GAAA,IAAA;EAClB,SAAA,EAAA,OAAA;EACH,KAAA,EAEL,KAFK,GAAA,IAAA;EAEL,OAAA,EAAA,CAAA,IAAA,CAAA,EAEC,OAFD,CAES,wBAFT,CAAA,EAAA,GAGF,OAHE,CAGM,yBAHN,GAAA,SAAA,CAAA;CAES;;;;;AAgBjB;;;;;;;;iBAAgB,gBAAA,WACN,0BACP"}
@@ -9,6 +9,18 @@ function areSelectionsEqual(a, b) {
9
9
  if (a.conversations.length !== b.conversations.length) return false;
10
10
  return a.conversations.every((conversation, index) => conversation === b.conversations[index]);
11
11
  }
12
+ /**
13
+ * Fetches and subscribes to the authenticated visitor's conversation list.
14
+ *
15
+ * The hook keeps the store in sync with the REST client and exposes
16
+ * pagination metadata plus a refetch helper for manual refreshes. The
17
+ * `options` mirror the public API filters so the UI can request slices of the
18
+ * inbox without duplicating data-fetching logic.
19
+ *
20
+ * @param options Filtering and lifecycle controls for the query.
21
+ * @returns Conversations, pagination data, loading state, and a refetch
22
+ * helper.
23
+ */
12
24
  function useConversations(options = {}) {
13
25
  const { client } = useSupport();
14
26
  const { limit, page, order, orderBy, status, enabled = true, refetchInterval = false, refetchOnWindowFocus = true } = options;
@@ -1 +1 @@
1
- {"version":3,"file":"use-conversations.js","names":[],"sources":["../../src/hooks/use-conversations.ts"],"sourcesContent":["import type { ConversationPagination } from \"@cossistant/core\";\nimport type {\n\tListConversationsRequest,\n\tListConversationsResponse,\n} from \"@cossistant/types/api/conversation\";\nimport { useCallback, useMemo } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useStoreSelector } from \"./private/store/use-store-selector\";\nimport { useClientQuery } from \"./private/use-client-query\";\n\ntype ConversationsSelection = {\n\tconversations: ListConversationsResponse[\"conversations\"];\n\tpagination: ConversationPagination | null;\n};\n\nfunction areSelectionsEqual(\n\ta: ConversationsSelection,\n\tb: ConversationsSelection\n): boolean {\n\tconst samePagination =\n\t\ta.pagination === b.pagination ||\n\t\t(Boolean(a.pagination) &&\n\t\t\tBoolean(b.pagination) &&\n\t\t\ta.pagination?.page === b.pagination?.page &&\n\t\t\ta.pagination?.limit === b.pagination?.limit &&\n\t\t\ta.pagination?.total === b.pagination?.total &&\n\t\t\ta.pagination?.totalPages === b.pagination?.totalPages &&\n\t\t\ta.pagination?.hasMore === b.pagination?.hasMore);\n\n\tif (!samePagination) {\n\t\treturn false;\n\t}\n\n\tif (a.conversations.length !== b.conversations.length) {\n\t\treturn false;\n\t}\n\n\treturn a.conversations.every(\n\t\t(conversation, index) => conversation === b.conversations[index]\n\t);\n}\n\nexport type UseConversationsOptions = Partial<\n\tOmit<ListConversationsRequest, \"visitorId\">\n> & {\n\tenabled?: boolean;\n\trefetchInterval?: number | false;\n\trefetchOnWindowFocus?: boolean;\n};\n\nexport type UseConversationsResult = {\n\tconversations: ListConversationsResponse[\"conversations\"];\n\tpagination: ConversationPagination | null;\n\tisLoading: boolean;\n\terror: Error | null;\n\trefetch: (\n\t\targs?: Partial<ListConversationsRequest>\n\t) => Promise<ListConversationsResponse | undefined>;\n};\n\nexport function useConversations(\n\toptions: UseConversationsOptions = {}\n): UseConversationsResult {\n\tconst { client } = useSupport();\n\n\tconst {\n\t\tlimit,\n\t\tpage,\n\t\torder,\n\t\torderBy,\n\t\tstatus,\n\t\tenabled = true,\n\t\trefetchInterval = false,\n\t\trefetchOnWindowFocus = true,\n\t} = options;\n\n\tconst requestDefaults = useMemo(\n\t\t() => ({ limit, page, status, orderBy, order }),\n\t\t[limit, page, status, orderBy, order]\n\t);\n\n\tconst store = client.conversationsStore;\n\n\tconst selection = useStoreSelector(\n\t\tstore,\n\t\t(state): ConversationsSelection => ({\n\t\t\tconversations: state.ids\n\t\t\t\t.map((id) => state.byId[id])\n\t\t\t\t.filter(\n\t\t\t\t\t(\n\t\t\t\t\t\tconversation\n\t\t\t\t\t): conversation is ListConversationsResponse[\"conversations\"][number] =>\n\t\t\t\t\t\tBoolean(conversation)\n\t\t\t\t),\n\t\t\tpagination: state.pagination,\n\t\t}),\n\t\tareSelectionsEqual\n\t);\n\n\tconst {\n\t\trefetch: queryRefetch,\n\t\tisLoading: queryLoading,\n\t\terror,\n\t} = useClientQuery<\n\t\tListConversationsResponse,\n\t\tPartial<ListConversationsRequest>\n\t>({\n\t\tclient,\n\t\tqueryFn: (instance, args) =>\n\t\t\tinstance.listConversations({\n\t\t\t\t...requestDefaults,\n\t\t\t\t...args,\n\t\t\t}),\n\t\tenabled,\n\t\trefetchInterval,\n\t\trefetchOnWindowFocus,\n\t\trefetchOnMount: selection.conversations.length === 0,\n\t\tinitialArgs: requestDefaults,\n\t\tdependencies: [limit, page, status, orderBy, order],\n\t});\n\n\tconst refetch = useCallback(\n\t\t(args?: Partial<ListConversationsRequest>) =>\n\t\t\tqueryRefetch({\n\t\t\t\t...requestDefaults,\n\t\t\t\t...args,\n\t\t\t}),\n\t\t[queryRefetch, requestDefaults]\n\t);\n\n\tconst isInitialLoad = selection.conversations.length === 0;\n\tconst isLoading = isInitialLoad ? queryLoading : false;\n\n\treturn {\n\t\tconversations: selection.conversations,\n\t\tpagination: selection.pagination,\n\t\tisLoading,\n\t\terror,\n\t\trefetch,\n\t};\n}\n"],"mappings":";;;;;;AAeA,SAAS,mBACR,GACA,GACU;AAWV,KAAI,EATH,EAAE,eAAe,EAAE,cAClB,QAAQ,EAAE,WAAW,IACrB,QAAQ,EAAE,WAAW,IACrB,EAAE,YAAY,SAAS,EAAE,YAAY,QACrC,EAAE,YAAY,UAAU,EAAE,YAAY,SACtC,EAAE,YAAY,UAAU,EAAE,YAAY,SACtC,EAAE,YAAY,eAAe,EAAE,YAAY,cAC3C,EAAE,YAAY,YAAY,EAAE,YAAY,SAGzC,QAAO;AAGR,KAAI,EAAE,cAAc,WAAW,EAAE,cAAc,OAC9C,QAAO;AAGR,QAAO,EAAE,cAAc,OACrB,cAAc,UAAU,iBAAiB,EAAE,cAAc,OAC1D;;AAqBF,SAAgB,iBACf,UAAmC,EAAE,EACZ;CACzB,MAAM,EAAE,WAAW,YAAY;CAE/B,MAAM,EACL,OACA,MACA,OACA,SACA,QACA,UAAU,MACV,kBAAkB,OAClB,uBAAuB,SACpB;CAEJ,MAAM,kBAAkB,eAChB;EAAE;EAAO;EAAM;EAAQ;EAAS;EAAO,GAC9C;EAAC;EAAO;EAAM;EAAQ;EAAS;EAAM,CACrC;CAED,MAAM,QAAQ,OAAO;CAErB,MAAM,YAAY,iBACjB,QACC,WAAmC;EACnC,eAAe,MAAM,IACnB,KAAK,OAAO,MAAM,KAAK,IAAI,CAC3B,QAEC,iBAEA,QAAQ,aAAa,CACtB;EACF,YAAY,MAAM;EAClB,GACD,mBACA;CAED,MAAM,EACL,SAAS,cACT,WAAW,cACX,UACG,eAGF;EACD;EACA,UAAU,UAAU,SACnB,SAAS,kBAAkB;GAC1B,GAAG;GACH,GAAG;GACH,CAAC;EACH;EACA;EACA;EACA,gBAAgB,UAAU,cAAc,WAAW;EACnD,aAAa;EACb,cAAc;GAAC;GAAO;GAAM;GAAQ;GAAS;GAAM;EACnD,CAAC;CAEF,MAAM,UAAU,aACd,SACA,aAAa;EACZ,GAAG;EACH,GAAG;EACH,CAAC,EACH,CAAC,cAAc,gBAAgB,CAC/B;CAGD,MAAM,YADgB,UAAU,cAAc,WAAW,IACvB,eAAe;AAEjD,QAAO;EACN,eAAe,UAAU;EACzB,YAAY,UAAU;EACtB;EACA;EACA;EACA"}
1
+ {"version":3,"file":"use-conversations.js","names":[],"sources":["../../src/hooks/use-conversations.ts"],"sourcesContent":["import type { ConversationPagination } from \"@cossistant/core\";\nimport type {\n\tListConversationsRequest,\n\tListConversationsResponse,\n} from \"@cossistant/types/api/conversation\";\nimport { useCallback, useMemo } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useStoreSelector } from \"./private/store/use-store-selector\";\nimport { useClientQuery } from \"./private/use-client-query\";\n\ntype ConversationsSelection = {\n\tconversations: ListConversationsResponse[\"conversations\"];\n\tpagination: ConversationPagination | null;\n};\n\nfunction areSelectionsEqual(\n\ta: ConversationsSelection,\n\tb: ConversationsSelection\n): boolean {\n\tconst samePagination =\n\t\ta.pagination === b.pagination ||\n\t\t(Boolean(a.pagination) &&\n\t\t\tBoolean(b.pagination) &&\n\t\t\ta.pagination?.page === b.pagination?.page &&\n\t\t\ta.pagination?.limit === b.pagination?.limit &&\n\t\t\ta.pagination?.total === b.pagination?.total &&\n\t\t\ta.pagination?.totalPages === b.pagination?.totalPages &&\n\t\t\ta.pagination?.hasMore === b.pagination?.hasMore);\n\n\tif (!samePagination) {\n\t\treturn false;\n\t}\n\n\tif (a.conversations.length !== b.conversations.length) {\n\t\treturn false;\n\t}\n\n\treturn a.conversations.every(\n\t\t(conversation, index) => conversation === b.conversations[index]\n\t);\n}\n\nexport type UseConversationsOptions = Partial<\n\tOmit<ListConversationsRequest, \"visitorId\">\n> & {\n\tenabled?: boolean;\n\trefetchInterval?: number | false;\n\trefetchOnWindowFocus?: boolean;\n};\n\nexport type UseConversationsResult = {\n\tconversations: ListConversationsResponse[\"conversations\"];\n\tpagination: ConversationPagination | null;\n\tisLoading: boolean;\n\terror: Error | null;\n\trefetch: (\n\t\targs?: Partial<ListConversationsRequest>\n\t) => Promise<ListConversationsResponse | undefined>;\n};\n\n/**\n * Fetches and subscribes to the authenticated visitor's conversation list.\n *\n * The hook keeps the store in sync with the REST client and exposes\n * pagination metadata plus a refetch helper for manual refreshes. The\n * `options` mirror the public API filters so the UI can request slices of the\n * inbox without duplicating data-fetching logic.\n *\n * @param options Filtering and lifecycle controls for the query.\n * @returns Conversations, pagination data, loading state, and a refetch\n * helper.\n */\nexport function useConversations(\n\toptions: UseConversationsOptions = {}\n): UseConversationsResult {\n\tconst { client } = useSupport();\n\n\tconst {\n\t\tlimit,\n\t\tpage,\n\t\torder,\n\t\torderBy,\n\t\tstatus,\n\t\tenabled = true,\n\t\trefetchInterval = false,\n\t\trefetchOnWindowFocus = true,\n\t} = options;\n\n\tconst requestDefaults = useMemo(\n\t\t() => ({ limit, page, status, orderBy, order }),\n\t\t[limit, page, status, orderBy, order]\n\t);\n\n\tconst store = client.conversationsStore;\n\n\tconst selection = useStoreSelector(\n\t\tstore,\n\t\t(state): ConversationsSelection => ({\n\t\t\tconversations: state.ids\n\t\t\t\t.map((id) => state.byId[id])\n\t\t\t\t.filter(\n\t\t\t\t\t(\n\t\t\t\t\t\tconversation\n\t\t\t\t\t): conversation is ListConversationsResponse[\"conversations\"][number] =>\n\t\t\t\t\t\tBoolean(conversation)\n\t\t\t\t),\n\t\t\tpagination: state.pagination,\n\t\t}),\n\t\tareSelectionsEqual\n\t);\n\n\tconst {\n\t\trefetch: queryRefetch,\n\t\tisLoading: queryLoading,\n\t\terror,\n\t} = useClientQuery<\n\t\tListConversationsResponse,\n\t\tPartial<ListConversationsRequest>\n\t>({\n\t\tclient,\n\t\tqueryFn: (instance, args) =>\n\t\t\tinstance.listConversations({\n\t\t\t\t...requestDefaults,\n\t\t\t\t...args,\n\t\t\t}),\n\t\tenabled,\n\t\trefetchInterval,\n\t\trefetchOnWindowFocus,\n\t\trefetchOnMount: selection.conversations.length === 0,\n\t\tinitialArgs: requestDefaults,\n\t\tdependencies: [limit, page, status, orderBy, order],\n\t});\n\n\tconst refetch = useCallback(\n\t\t(args?: Partial<ListConversationsRequest>) =>\n\t\t\tqueryRefetch({\n\t\t\t\t...requestDefaults,\n\t\t\t\t...args,\n\t\t\t}),\n\t\t[queryRefetch, requestDefaults]\n\t);\n\n\tconst isInitialLoad = selection.conversations.length === 0;\n\tconst isLoading = isInitialLoad ? queryLoading : false;\n\n\treturn {\n\t\tconversations: selection.conversations,\n\t\tpagination: selection.pagination,\n\t\tisLoading,\n\t\terror,\n\t\trefetch,\n\t};\n}\n"],"mappings":";;;;;;AAeA,SAAS,mBACR,GACA,GACU;AAWV,KAAI,EATH,EAAE,eAAe,EAAE,cAClB,QAAQ,EAAE,WAAW,IACrB,QAAQ,EAAE,WAAW,IACrB,EAAE,YAAY,SAAS,EAAE,YAAY,QACrC,EAAE,YAAY,UAAU,EAAE,YAAY,SACtC,EAAE,YAAY,UAAU,EAAE,YAAY,SACtC,EAAE,YAAY,eAAe,EAAE,YAAY,cAC3C,EAAE,YAAY,YAAY,EAAE,YAAY,SAGzC,QAAO;AAGR,KAAI,EAAE,cAAc,WAAW,EAAE,cAAc,OAC9C,QAAO;AAGR,QAAO,EAAE,cAAc,OACrB,cAAc,UAAU,iBAAiB,EAAE,cAAc,OAC1D;;;;;;;;;;;;;;AAiCF,SAAgB,iBACf,UAAmC,EAAE,EACZ;CACzB,MAAM,EAAE,WAAW,YAAY;CAE/B,MAAM,EACL,OACA,MACA,OACA,SACA,QACA,UAAU,MACV,kBAAkB,OAClB,uBAAuB,SACpB;CAEJ,MAAM,kBAAkB,eAChB;EAAE;EAAO;EAAM;EAAQ;EAAS;EAAO,GAC9C;EAAC;EAAO;EAAM;EAAQ;EAAS;EAAM,CACrC;CAED,MAAM,QAAQ,OAAO;CAErB,MAAM,YAAY,iBACjB,QACC,WAAmC;EACnC,eAAe,MAAM,IACnB,KAAK,OAAO,MAAM,KAAK,IAAI,CAC3B,QAEC,iBAEA,QAAQ,aAAa,CACtB;EACF,YAAY,MAAM;EAClB,GACD,mBACA;CAED,MAAM,EACL,SAAS,cACT,WAAW,cACX,UACG,eAGF;EACD;EACA,UAAU,UAAU,SACnB,SAAS,kBAAkB;GAC1B,GAAG;GACH,GAAG;GACH,CAAC;EACH;EACA;EACA;EACA,gBAAgB,UAAU,cAAc,WAAW;EACnD,aAAa;EACb,cAAc;GAAC;GAAO;GAAM;GAAQ;GAAS;GAAM;EACnD,CAAC;CAEF,MAAM,UAAU,aACd,SACA,aAAa;EACZ,GAAG;EACH,GAAG;EACH,CAAC,EACH,CAAC,cAAc,gBAAgB,CAC/B;CAGD,MAAM,YADgB,UAAU,cAAc,WAAW,IACvB,eAAe;AAEjD,QAAO;EACN,eAAe,UAAU;EACzB,YAAY,UAAU;EACtB;EACA;EACA;EACA"}
@@ -24,6 +24,11 @@ type UseCreateConversationResult = {
24
24
  error: Error | null;
25
25
  reset: () => void;
26
26
  };
27
+ /**
28
+ * Imperative helper for bootstrapping a new conversation locally before the
29
+ * backend persists it. Mirrors react-query's mutate API to simplify
30
+ * integration with forms or buttons.
31
+ */
27
32
  declare function useCreateConversation(options?: UseCreateConversationOptions): UseCreateConversationResult;
28
33
  //#endregion
29
34
  export { CreateConversationVariables, UseCreateConversationOptions, UseCreateConversationResult, useCreateConversation };
@@ -1 +1 @@
1
- {"version":3,"file":"use-create-conversation.d.ts","names":[],"sources":["../../src/hooks/use-create-conversation.ts"],"sourcesContent":[],"mappings":";;;;;;KAOY,4BAAA;WACF;EADE,SAAA,CAAA,EAAA,CAAA,IAAA,EAEQ,8BAFoB,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,CAAA,KAAA,EAGrB,KAHqB,EAAA,GAAA,IAAA;;AAEpB,KAIR,2BAAA,GAJQ;gBACD,CAAA,EAAA,MAAA;EAAK,oBAAA,CAAA,EAKA,YALA,EAAA;EAGZ,SAAA,CAAA,EAAA,MAAA;EAA2B,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;QAEf,CAAA,EAGd,YAHc,CAAA,QAAA,CAAA;OAGd,CAAA,EAAA,MAAA,GAAA,IAAA;CAAY;AAIV,KAAA,2BAAA,GAA2B;EAAA,MAAA,EAAA,CAAA,SAAA,CAAA,EACjB,2BADiB,EAAA,GAAA,IAAA;aACjB,EAAA,CAAA,SAAA,CAAA,EAER,2BAFQ,EAAA,GAGhB,OAHgB,CAGR,8BAHQ,GAAA,IAAA,CAAA;WAER,EAAA,OAAA;OACA,EAEN,KAFM,GAAA,IAAA;OAAR,EAAA,GAAA,GAAA,IAAA;;AAEO,iBAgBG,qBAAA,CAhBH,OAAA,CAAA,EAiBH,4BAjBG,CAAA,EAkBV,2BAlBU"}
1
+ {"version":3,"file":"use-create-conversation.d.ts","names":[],"sources":["../../src/hooks/use-create-conversation.ts"],"sourcesContent":[],"mappings":";;;;;;KAOY,4BAAA;WACF;EADE,SAAA,CAAA,EAAA,CAAA,IAAA,EAEQ,8BAFoB,EAAA,GAAA,IAAA;EAC9B,OAAA,CAAA,EAAA,CAAA,KAAA,EAES,KAFT,EAAA,GAAA,IAAA;CACU;AACD,KAGP,2BAAA,GAHO;EAAK,cAAA,CAAA,EAAA,MAAA;EAGZ,oBAAA,CAAA,EAEY,YAFe,EAAA;EAS3B,SAAA,CAAA,EAAA,MAAA;EACU,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAER,MAAA,CAAA,EAPJ,YAOI,CAAA,QAAA,CAAA;EACA,KAAA,CAAA,EAAA,MAAA,GAAA,IAAA;CAAR;AAEE,KANI,2BAAA,GAMJ;EAAK,MAAA,EAAA,CAAA,SAAA,CAAA,EALS,2BAKT,EAAA,GAAA,IAAA;EAqBG,WAAA,EAAA,CAAA,SACN,CAD2B,EAxBvB,2BAyBJ,EAAA,GAxBJ,OAwBI,CAxBI,8BAyBgB,GAAA,IAAA,CAAA;;SAvBtB;;;;;;;;iBAqBQ,qBAAA,WACN,+BACP"}
@@ -7,6 +7,11 @@ function toError(error) {
7
7
  if (typeof error === "string") return new Error(error);
8
8
  return /* @__PURE__ */ new Error("Unknown error");
9
9
  }
10
+ /**
11
+ * Imperative helper for bootstrapping a new conversation locally before the
12
+ * backend persists it. Mirrors react-query's mutate API to simplify
13
+ * integration with forms or buttons.
14
+ */
10
15
  function useCreateConversation(options = {}) {
11
16
  const { client: contextClient } = useSupport();
12
17
  const { client: overrideClient, onError, onSuccess } = options;
@@ -46,19 +51,17 @@ function useCreateConversation(options = {}) {
46
51
  onError,
47
52
  onSuccess
48
53
  ]);
49
- const mutate = useCallback((variables) => {
50
- mutateAsync(variables).catch(() => {});
51
- }, [mutateAsync]);
52
- const reset = useCallback(() => {
53
- setError(null);
54
- setIsPending(false);
55
- }, []);
56
54
  return {
57
- mutate,
55
+ mutate: useCallback((variables) => {
56
+ mutateAsync(variables).catch(() => {});
57
+ }, [mutateAsync]),
58
58
  mutateAsync,
59
59
  isPending,
60
60
  error,
61
- reset
61
+ reset: useCallback(() => {
62
+ setError(null);
63
+ setIsPending(false);
64
+ }, [])
62
65
  };
63
66
  }
64
67
 
@@ -1 +1 @@
1
- {"version":3,"file":"use-create-conversation.js","names":["response: CreateConversationResponseBody"],"sources":["../../src/hooks/use-create-conversation.ts"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport type { CreateConversationResponseBody } from \"@cossistant/types/api/conversation\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type { Conversation } from \"@cossistant/types/schemas\";\nimport { useCallback, useState } from \"react\";\nimport { useSupport } from \"../provider\";\n\nexport type UseCreateConversationOptions = {\n\tclient?: CossistantClient;\n\tonSuccess?: (data: CreateConversationResponseBody) => void;\n\tonError?: (error: Error) => void;\n};\n\nexport type CreateConversationVariables = {\n\tconversationId?: string;\n\tdefaultTimelineItems?: TimelineItem[];\n\tvisitorId?: string;\n\twebsiteId?: string | null;\n\tstatus?: Conversation[\"status\"];\n\ttitle?: string | null;\n};\n\nexport type UseCreateConversationResult = {\n\tmutate: (variables?: CreateConversationVariables) => void;\n\tmutateAsync: (\n\t\tvariables?: CreateConversationVariables\n\t) => Promise<CreateConversationResponseBody | null>;\n\tisPending: boolean;\n\terror: Error | null;\n\treset: () => void;\n};\n\nfunction toError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn new Error(error);\n\t}\n\n\treturn new Error(\"Unknown error\");\n}\n\nexport function useCreateConversation(\n\toptions: UseCreateConversationOptions = {}\n): UseCreateConversationResult {\n\tconst { client: contextClient } = useSupport();\n\tconst { client: overrideClient, onError, onSuccess } = options;\n\tconst client = overrideClient ?? contextClient;\n\n\tconst [isPending, setIsPending] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst mutateAsync = useCallback(\n\t\tasync (\n\t\t\tvariables: CreateConversationVariables = {}\n\t\t): Promise<CreateConversationResponseBody | null> => {\n\t\t\tsetIsPending(true);\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst {\n\t\t\t\t\twebsiteId,\n\t\t\t\t\tstatus,\n\t\t\t\t\ttitle,\n\t\t\t\t\tconversationId: providedConversationId,\n\t\t\t\t\tdefaultTimelineItems = [],\n\t\t\t\t\tvisitorId,\n\t\t\t\t} = variables;\n\n\t\t\t\tconst initiated = client.initiateConversation({\n\t\t\t\t\tconversationId: providedConversationId ?? undefined,\n\t\t\t\t\tdefaultTimelineItems,\n\t\t\t\t\tvisitorId: visitorId ?? undefined,\n\t\t\t\t\twebsiteId: websiteId ?? undefined,\n\t\t\t\t\tstatus: status ?? undefined,\n\t\t\t\t\ttitle: title ?? undefined,\n\t\t\t\t});\n\n\t\t\t\tconst response: CreateConversationResponseBody = {\n\t\t\t\t\tconversation: initiated.conversation,\n\t\t\t\t\tinitialTimelineItems: initiated.defaultTimelineItems,\n\t\t\t\t};\n\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(null);\n\t\t\t\tonSuccess?.(response);\n\t\t\t\treturn response;\n\t\t\t} catch (raw) {\n\t\t\t\tconst normalised = toError(raw);\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(normalised);\n\t\t\t\tonError?.(normalised);\n\t\t\t\tthrow normalised;\n\t\t\t}\n\t\t},\n\t\t[client, onError, onSuccess]\n\t);\n\n\tconst mutate = useCallback(\n\t\t(variables?: CreateConversationVariables) => {\n\t\t\tvoid mutateAsync(variables).catch(() => {\n\t\t\t\t// Intentionally swallow to match react-query semantics\n\t\t\t});\n\t\t},\n\t\t[mutateAsync]\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tsetError(null);\n\t\tsetIsPending(false);\n\t}, []);\n\n\treturn {\n\t\tmutate,\n\t\tmutateAsync,\n\t\tisPending,\n\t\terror,\n\t\treset,\n\t};\n}\n"],"mappings":";;;;AAgCA,SAAS,QAAQ,OAAuB;AACvC,KAAI,iBAAiB,MACpB,QAAO;AAGR,KAAI,OAAO,UAAU,SACpB,QAAO,IAAI,MAAM,MAAM;AAGxB,wBAAO,IAAI,MAAM,gBAAgB;;AAGlC,SAAgB,sBACf,UAAwC,EAAE,EACZ;CAC9B,MAAM,EAAE,QAAQ,kBAAkB,YAAY;CAC9C,MAAM,EAAE,QAAQ,gBAAgB,SAAS,cAAc;CACvD,MAAM,SAAS,kBAAkB;CAEjC,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAEtD,MAAM,cAAc,YACnB,OACC,YAAyC,EAAE,KACS;AACpD,eAAa,KAAK;AAClB,WAAS,KAAK;AAEd,MAAI;GACH,MAAM,EACL,WACA,QACA,OACA,gBAAgB,wBAChB,uBAAuB,EAAE,EACzB,cACG;GAEJ,MAAM,YAAY,OAAO,qBAAqB;IAC7C,gBAAgB,0BAA0B;IAC1C;IACA,WAAW,aAAa;IACxB,WAAW,aAAa;IACxB,QAAQ,UAAU;IAClB,OAAO,SAAS;IAChB,CAAC;GAEF,MAAMA,WAA2C;IAChD,cAAc,UAAU;IACxB,sBAAsB,UAAU;IAChC;AAED,gBAAa,MAAM;AACnB,YAAS,KAAK;AACd,eAAY,SAAS;AACrB,UAAO;WACC,KAAK;GACb,MAAM,aAAa,QAAQ,IAAI;AAC/B,gBAAa,MAAM;AACnB,YAAS,WAAW;AACpB,aAAU,WAAW;AACrB,SAAM;;IAGR;EAAC;EAAQ;EAAS;EAAU,CAC5B;CAED,MAAM,SAAS,aACb,cAA4C;AAC5C,EAAK,YAAY,UAAU,CAAC,YAAY,GAEtC;IAEH,CAAC,YAAY,CACb;CAED,MAAM,QAAQ,kBAAkB;AAC/B,WAAS,KAAK;AACd,eAAa,MAAM;IACjB,EAAE,CAAC;AAEN,QAAO;EACN;EACA;EACA;EACA;EACA;EACA"}
1
+ {"version":3,"file":"use-create-conversation.js","names":["response: CreateConversationResponseBody"],"sources":["../../src/hooks/use-create-conversation.ts"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport type { CreateConversationResponseBody } from \"@cossistant/types/api/conversation\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type { Conversation } from \"@cossistant/types/schemas\";\nimport { useCallback, useState } from \"react\";\nimport { useSupport } from \"../provider\";\n\nexport type UseCreateConversationOptions = {\n\tclient?: CossistantClient;\n\tonSuccess?: (data: CreateConversationResponseBody) => void;\n\tonError?: (error: Error) => void;\n};\n\nexport type CreateConversationVariables = {\n\tconversationId?: string;\n\tdefaultTimelineItems?: TimelineItem[];\n\tvisitorId?: string;\n\twebsiteId?: string | null;\n\tstatus?: Conversation[\"status\"];\n\ttitle?: string | null;\n};\n\nexport type UseCreateConversationResult = {\n\tmutate: (variables?: CreateConversationVariables) => void;\n\tmutateAsync: (\n\t\tvariables?: CreateConversationVariables\n\t) => Promise<CreateConversationResponseBody | null>;\n\tisPending: boolean;\n\terror: Error | null;\n\treset: () => void;\n};\n\nfunction toError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn new Error(error);\n\t}\n\n\treturn new Error(\"Unknown error\");\n}\n\n/**\n * Imperative helper for bootstrapping a new conversation locally before the\n * backend persists it. Mirrors react-query's mutate API to simplify\n * integration with forms or buttons.\n */\nexport function useCreateConversation(\n\toptions: UseCreateConversationOptions = {}\n): UseCreateConversationResult {\n\tconst { client: contextClient } = useSupport();\n\tconst { client: overrideClient, onError, onSuccess } = options;\n\tconst client = overrideClient ?? contextClient;\n\n\tconst [isPending, setIsPending] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst mutateAsync = useCallback(\n\t\tasync (\n\t\t\tvariables: CreateConversationVariables = {}\n\t\t): Promise<CreateConversationResponseBody | null> => {\n\t\t\tsetIsPending(true);\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst {\n\t\t\t\t\twebsiteId,\n\t\t\t\t\tstatus,\n\t\t\t\t\ttitle,\n\t\t\t\t\tconversationId: providedConversationId,\n\t\t\t\t\tdefaultTimelineItems = [],\n\t\t\t\t\tvisitorId,\n\t\t\t\t} = variables;\n\n\t\t\t\tconst initiated = client.initiateConversation({\n\t\t\t\t\tconversationId: providedConversationId ?? undefined,\n\t\t\t\t\tdefaultTimelineItems,\n\t\t\t\t\tvisitorId: visitorId ?? undefined,\n\t\t\t\t\twebsiteId: websiteId ?? undefined,\n\t\t\t\t\tstatus: status ?? undefined,\n\t\t\t\t\ttitle: title ?? undefined,\n\t\t\t\t});\n\n\t\t\t\tconst response: CreateConversationResponseBody = {\n\t\t\t\t\tconversation: initiated.conversation,\n\t\t\t\t\tinitialTimelineItems: initiated.defaultTimelineItems,\n\t\t\t\t};\n\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(null);\n\t\t\t\tonSuccess?.(response);\n\t\t\t\treturn response;\n\t\t\t} catch (raw) {\n\t\t\t\tconst normalised = toError(raw);\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(normalised);\n\t\t\t\tonError?.(normalised);\n\t\t\t\tthrow normalised;\n\t\t\t}\n\t\t},\n\t\t[client, onError, onSuccess]\n\t);\n\n\tconst mutate = useCallback(\n\t\t(variables?: CreateConversationVariables) => {\n\t\t\tvoid mutateAsync(variables).catch(() => {\n\t\t\t\t// Intentionally swallow to match react-query semantics\n\t\t\t});\n\t\t},\n\t\t[mutateAsync]\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tsetError(null);\n\t\tsetIsPending(false);\n\t}, []);\n\n\treturn {\n\t\tmutate,\n\t\tmutateAsync,\n\t\tisPending,\n\t\terror,\n\t\treset,\n\t};\n}\n"],"mappings":";;;;AAgCA,SAAS,QAAQ,OAAuB;AACvC,KAAI,iBAAiB,MACpB,QAAO;AAGR,KAAI,OAAO,UAAU,SACpB,QAAO,IAAI,MAAM,MAAM;AAGxB,wBAAO,IAAI,MAAM,gBAAgB;;;;;;;AAQlC,SAAgB,sBACf,UAAwC,EAAE,EACZ;CAC9B,MAAM,EAAE,QAAQ,kBAAkB,YAAY;CAC9C,MAAM,EAAE,QAAQ,gBAAgB,SAAS,cAAc;CACvD,MAAM,SAAS,kBAAkB;CAEjC,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAEtD,MAAM,cAAc,YACnB,OACC,YAAyC,EAAE,KACS;AACpD,eAAa,KAAK;AAClB,WAAS,KAAK;AAEd,MAAI;GACH,MAAM,EACL,WACA,QACA,OACA,gBAAgB,wBAChB,uBAAuB,EAAE,EACzB,cACG;GAEJ,MAAM,YAAY,OAAO,qBAAqB;IAC7C,gBAAgB,0BAA0B;IAC1C;IACA,WAAW,aAAa;IACxB,WAAW,aAAa;IACxB,QAAQ,UAAU;IAClB,OAAO,SAAS;IAChB,CAAC;GAEF,MAAMA,WAA2C;IAChD,cAAc,UAAU;IACxB,sBAAsB,UAAU;IAChC;AAED,gBAAa,MAAM;AACnB,YAAS,KAAK;AACd,eAAY,SAAS;AACrB,UAAO;WACC,KAAK;GACb,MAAM,aAAa,QAAQ,IAAI;AAC/B,gBAAa,MAAM;AACnB,YAAS,WAAW;AACpB,aAAU,WAAW;AACrB,SAAM;;IAGR;EAAC;EAAQ;EAAS;EAAU,CAC5B;AAgBD,QAAO;EACN,QAfc,aACb,cAA4C;AAC5C,GAAK,YAAY,UAAU,CAAC,YAAY,GAEtC;KAEH,CAAC,YAAY,CACb;EASA;EACA;EACA;EACA,OAVa,kBAAkB;AAC/B,YAAS,KAAK;AACd,gBAAa,MAAM;KACjB,EAAE,CAAC;EAQL"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-home-page.d.ts","names":[],"sources":["../../src/hooks/use-home-page.ts"],"sourcesContent":[],"mappings":";;;KAKY,kBAAA;;AAAZ;AAuBA;;SAEgB,CAAA,EAAA,OAAA;;;;EA4DA,mBAAW,CAAA,EAAA,CAAA,cAAA,CAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA;;;EAEP,kBAAA,CAAA,EAAA,CAAA,cAAA,EAAA,MAAA,EAAA,GAAA,IAAA;;;;;;KAhER,iBAAA;iBAEI;;SAER;wBAGe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuDP,WAAA,WACN,qBACP"}
1
+ {"version":3,"file":"use-home-page.d.ts","names":[],"sources":["../../src/hooks/use-home-page.ts"],"sourcesContent":[],"mappings":";;;KAKY,kBAAA;;AAAZ;AAuBA;;EAIQ,OAAA,CAAA,EAAA,OAAA;EAGe;;AAuDvB;;;;;;;;;;;KA9DY,iBAAA;iBAEI;;SAER;wBAGe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuDP,WAAA,WACN,qBACP"}
@@ -1,5 +1,7 @@
1
+ import { shouldDisplayConversation } from "../utils/conversation.js";
1
2
  import { useConversations } from "./use-conversations.js";
2
3
  import { useCallback, useMemo } from "react";
4
+ import { ConversationStatus } from "@cossistant/types";
3
5
 
4
6
  //#region src/hooks/use-home-page.ts
5
7
  /**
@@ -49,17 +51,17 @@ import { useCallback, useMemo } from "react";
49
51
  */
50
52
  function useHomePage(options = {}) {
51
53
  const { enabled = true, onStartConversation, onOpenConversation, onOpenConversationHistory } = options;
52
- const { conversations, isLoading, error } = useConversations({
54
+ const { conversations: allConversations, isLoading, error } = useConversations({
53
55
  enabled,
54
56
  orderBy: "updatedAt",
55
57
  order: "desc"
56
58
  });
59
+ const conversations = useMemo(() => allConversations.filter(shouldDisplayConversation), [allConversations]);
57
60
  const { lastOpenConversation, availableConversationsCount } = useMemo(() => {
58
- const openConversation$1 = conversations.find((conv) => conv.status === "open");
59
- const otherCount = Math.max((conversations.length || 0) - 1, 0);
61
+ const openConversation$1 = conversations.find((conv) => conv.status === ConversationStatus.OPEN || conv.status === "open");
60
62
  return {
61
63
  lastOpenConversation: openConversation$1,
62
- availableConversationsCount: otherCount
64
+ availableConversationsCount: Math.max(conversations.length - (openConversation$1 ? 1 : 0), 0)
63
65
  };
64
66
  }, [conversations]);
65
67
  const startConversation = useCallback((initialMessage) => {
@@ -1 +1 @@
1
- {"version":3,"file":"use-home-page.js","names":["openConversation"],"sources":["../../src/hooks/use-home-page.ts"],"sourcesContent":["import type { Conversation } from \"@cossistant/types\";\nimport { useCallback, useMemo } from \"react\";\nimport { PENDING_CONVERSATION_ID } from \"../utils/id\";\nimport { useConversations } from \"./use-conversations\";\n\nexport type UseHomePageOptions = {\n\t/**\n\t * Whether to enable conversations fetching.\n\t * Default: true\n\t */\n\tenabled?: boolean;\n\n\t/**\n\t * Callback when user wants to start a new conversation.\n\t */\n\tonStartConversation?: (initialMessage?: string) => void;\n\n\t/**\n\t * Callback when user wants to open an existing conversation.\n\t */\n\tonOpenConversation?: (conversationId: string) => void;\n\n\t/**\n\t * Callback when user wants to view conversation history.\n\t */\n\tonOpenConversationHistory?: () => void;\n};\n\nexport type UseHomePageReturn = {\n\t// Conversations data\n\tconversations: Conversation[];\n\tisLoading: boolean;\n\terror: Error | null;\n\n\t// Derived state\n\tlastOpenConversation: Conversation | undefined;\n\tavailableConversationsCount: number;\n\thasConversations: boolean;\n\n\t// Actions\n\tstartConversation: (initialMessage?: string) => void;\n\topenConversation: (conversationId: string) => void;\n\topenConversationHistory: () => void;\n};\n\n/**\n * Main hook for the home page of the support widget.\n *\n * This hook:\n * - Fetches and manages conversations list\n * - Derives useful state (last open conversation, conversation counts)\n * - Provides navigation actions for the home page\n *\n * It encapsulates all home page logic, making the component\n * purely presentational.\n *\n * @example\n * ```tsx\n * export function HomePage() {\n * const home = useHomePage({\n * onStartConversation: (msg) => {\n * navigate('conversation', { conversationId: PENDING_CONVERSATION_ID, initialMessage: msg });\n * },\n * onOpenConversation: (id) => {\n * navigate('conversation', { conversationId: id });\n * },\n * onOpenConversationHistory: () => {\n * navigate('conversation-history');\n * },\n * });\n *\n * return (\n * <>\n * <h1>How can we help?</h1>\n *\n * {home.lastOpenConversation && (\n * <ConversationCard\n * conversation={home.lastOpenConversation}\n * onClick={() => home.openConversation(home.lastOpenConversation.id)}\n * />\n * )}\n *\n * <Button onClick={() => home.startConversation()}>\n * Ask a question\n * </Button>\n * </>\n * );\n * }\n * ```\n */\nexport function useHomePage(\n\toptions: UseHomePageOptions = {}\n): UseHomePageReturn {\n\tconst {\n\t\tenabled = true,\n\t\tonStartConversation,\n\t\tonOpenConversation,\n\t\tonOpenConversationHistory,\n\t} = options;\n\n\t// Fetch conversations\n\tconst { conversations, isLoading, error } = useConversations({\n\t\tenabled,\n\t\t// Fetch most recent conversations first\n\t\torderBy: \"updatedAt\",\n\t\torder: \"desc\",\n\t});\n\n\t// Derive useful state from conversations\n\tconst { lastOpenConversation, availableConversationsCount } = useMemo(() => {\n\t\t// Find the most recent open conversation\n\t\tconst openConversation = conversations.find(\n\t\t\t(conv) => conv.status === \"open\"\n\t\t);\n\n\t\t// Count other conversations (excluding the one we're showing)\n\t\tconst otherCount = Math.max((conversations.length || 0) - 1, 0);\n\n\t\treturn {\n\t\t\tlastOpenConversation: openConversation,\n\t\t\tavailableConversationsCount: otherCount,\n\t\t};\n\t}, [conversations]);\n\n\t// Navigation actions\n\tconst startConversation = useCallback(\n\t\t(initialMessage?: string) => {\n\t\t\tonStartConversation?.(initialMessage);\n\t\t},\n\t\t[onStartConversation]\n\t);\n\n\tconst openConversation = useCallback(\n\t\t(conversationId: string) => {\n\t\t\tonOpenConversation?.(conversationId);\n\t\t},\n\t\t[onOpenConversation]\n\t);\n\n\tconst openConversationHistory = useCallback(() => {\n\t\tonOpenConversationHistory?.();\n\t}, [onOpenConversationHistory]);\n\n\treturn {\n\t\tconversations,\n\t\tisLoading,\n\t\terror,\n\t\tlastOpenConversation,\n\t\tavailableConversationsCount,\n\t\thasConversations: conversations.length > 0,\n\t\tstartConversation,\n\t\topenConversation,\n\t\topenConversationHistory,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,SAAgB,YACf,UAA8B,EAAE,EACZ;CACpB,MAAM,EACL,UAAU,MACV,qBACA,oBACA,8BACG;CAGJ,MAAM,EAAE,eAAe,WAAW,UAAU,iBAAiB;EAC5D;EAEA,SAAS;EACT,OAAO;EACP,CAAC;CAGF,MAAM,EAAE,sBAAsB,gCAAgC,cAAc;EAE3E,MAAMA,qBAAmB,cAAc,MACrC,SAAS,KAAK,WAAW,OAC1B;EAGD,MAAM,aAAa,KAAK,KAAK,cAAc,UAAU,KAAK,GAAG,EAAE;AAE/D,SAAO;GACN,sBAAsBA;GACtB,6BAA6B;GAC7B;IACC,CAAC,cAAc,CAAC;CAGnB,MAAM,oBAAoB,aACxB,mBAA4B;AAC5B,wBAAsB,eAAe;IAEtC,CAAC,oBAAoB,CACrB;CAED,MAAM,mBAAmB,aACvB,mBAA2B;AAC3B,uBAAqB,eAAe;IAErC,CAAC,mBAAmB,CACpB;CAED,MAAM,0BAA0B,kBAAkB;AACjD,+BAA6B;IAC3B,CAAC,0BAA0B,CAAC;AAE/B,QAAO;EACN;EACA;EACA;EACA;EACA;EACA,kBAAkB,cAAc,SAAS;EACzC;EACA;EACA;EACA"}
1
+ {"version":3,"file":"use-home-page.js","names":["openConversation"],"sources":["../../src/hooks/use-home-page.ts"],"sourcesContent":["import { type Conversation, ConversationStatus } from \"@cossistant/types\";\nimport { useCallback, useMemo } from \"react\";\nimport { shouldDisplayConversation } from \"../utils/conversation\";\nimport { useConversations } from \"./use-conversations\";\n\nexport type UseHomePageOptions = {\n\t/**\n\t * Whether to enable conversations fetching.\n\t * Default: true\n\t */\n\tenabled?: boolean;\n\n\t/**\n\t * Callback when user wants to start a new conversation.\n\t */\n\tonStartConversation?: (initialMessage?: string) => void;\n\n\t/**\n\t * Callback when user wants to open an existing conversation.\n\t */\n\tonOpenConversation?: (conversationId: string) => void;\n\n\t/**\n\t * Callback when user wants to view conversation history.\n\t */\n\tonOpenConversationHistory?: () => void;\n};\n\nexport type UseHomePageReturn = {\n\t// Conversations data\n\tconversations: Conversation[];\n\tisLoading: boolean;\n\terror: Error | null;\n\n\t// Derived state\n\tlastOpenConversation: Conversation | undefined;\n\tavailableConversationsCount: number;\n\thasConversations: boolean;\n\n\t// Actions\n\tstartConversation: (initialMessage?: string) => void;\n\topenConversation: (conversationId: string) => void;\n\topenConversationHistory: () => void;\n};\n\n/**\n * Main hook for the home page of the support widget.\n *\n * This hook:\n * - Fetches and manages conversations list\n * - Derives useful state (last open conversation, conversation counts)\n * - Provides navigation actions for the home page\n *\n * It encapsulates all home page logic, making the component\n * purely presentational.\n *\n * @example\n * ```tsx\n * export function HomePage() {\n * const home = useHomePage({\n * onStartConversation: (msg) => {\n * navigate('conversation', { conversationId: PENDING_CONVERSATION_ID, initialMessage: msg });\n * },\n * onOpenConversation: (id) => {\n * navigate('conversation', { conversationId: id });\n * },\n * onOpenConversationHistory: () => {\n * navigate('conversation-history');\n * },\n * });\n *\n * return (\n * <>\n * <h1>How can we help?</h1>\n *\n * {home.lastOpenConversation && (\n * <ConversationCard\n * conversation={home.lastOpenConversation}\n * onClick={() => home.openConversation(home.lastOpenConversation.id)}\n * />\n * )}\n *\n * <Button onClick={() => home.startConversation()}>\n * Ask a question\n * </Button>\n * </>\n * );\n * }\n * ```\n */\nexport function useHomePage(\n\toptions: UseHomePageOptions = {}\n): UseHomePageReturn {\n\tconst {\n\t\tenabled = true,\n\t\tonStartConversation,\n\t\tonOpenConversation,\n\t\tonOpenConversationHistory,\n\t} = options;\n\n\t// Fetch conversations\n\tconst {\n\t\tconversations: allConversations,\n\t\tisLoading,\n\t\terror,\n\t} = useConversations({\n\t\tenabled,\n\t\t// Fetch most recent conversations first\n\t\torderBy: \"updatedAt\",\n\t\torder: \"desc\",\n\t});\n\n\tconst conversations = useMemo(\n\t\t() => allConversations.filter(shouldDisplayConversation),\n\t\t[allConversations]\n\t);\n\n\t// Derive useful state from conversations\n\tconst { lastOpenConversation, availableConversationsCount } = useMemo(() => {\n\t\t// Find the most recent open conversation\n\t\tconst openConversation = conversations.find(\n\t\t\t(conv) =>\n\t\t\t\tconv.status === ConversationStatus.OPEN || conv.status === \"open\"\n\t\t);\n\n\t\t// Count other conversations (excluding the one we're showing)\n\t\tconst otherCount = Math.max(\n\t\t\tconversations.length - (openConversation ? 1 : 0),\n\t\t\t0\n\t\t);\n\n\t\treturn {\n\t\t\tlastOpenConversation: openConversation,\n\t\t\tavailableConversationsCount: otherCount,\n\t\t};\n\t}, [conversations]);\n\n\t// Navigation actions\n\tconst startConversation = useCallback(\n\t\t(initialMessage?: string) => {\n\t\t\tonStartConversation?.(initialMessage);\n\t\t},\n\t\t[onStartConversation]\n\t);\n\n\tconst openConversation = useCallback(\n\t\t(conversationId: string) => {\n\t\t\tonOpenConversation?.(conversationId);\n\t\t},\n\t\t[onOpenConversation]\n\t);\n\n\tconst openConversationHistory = useCallback(() => {\n\t\tonOpenConversationHistory?.();\n\t}, [onOpenConversationHistory]);\n\n\treturn {\n\t\tconversations,\n\t\tisLoading,\n\t\terror,\n\t\tlastOpenConversation,\n\t\tavailableConversationsCount,\n\t\thasConversations: conversations.length > 0,\n\t\tstartConversation,\n\t\topenConversation,\n\t\topenConversationHistory,\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,SAAgB,YACf,UAA8B,EAAE,EACZ;CACpB,MAAM,EACL,UAAU,MACV,qBACA,oBACA,8BACG;CAGJ,MAAM,EACL,eAAe,kBACf,WACA,UACG,iBAAiB;EACpB;EAEA,SAAS;EACT,OAAO;EACP,CAAC;CAEF,MAAM,gBAAgB,cACf,iBAAiB,OAAO,0BAA0B,EACxD,CAAC,iBAAiB,CAClB;CAGD,MAAM,EAAE,sBAAsB,gCAAgC,cAAc;EAE3E,MAAMA,qBAAmB,cAAc,MACrC,SACA,KAAK,WAAW,mBAAmB,QAAQ,KAAK,WAAW,OAC5D;AAQD,SAAO;GACN,sBAAsBA;GACtB,6BAPkB,KAAK,IACvB,cAAc,UAAUA,qBAAmB,IAAI,IAC/C,EACA;GAKA;IACC,CAAC,cAAc,CAAC;CAGnB,MAAM,oBAAoB,aACxB,mBAA4B;AAC5B,wBAAsB,eAAe;IAEtC,CAAC,oBAAoB,CACrB;CAED,MAAM,mBAAmB,aACvB,mBAA2B;AAC3B,uBAAqB,eAAe;IAErC,CAAC,mBAAmB,CACpB;CAED,MAAM,0BAA0B,kBAAkB;AACjD,+BAA6B;IAC3B,CAAC,0BAA0B,CAAC;AAE/B,QAAO;EACN;EACA;EACA;EACA;EACA;EACA,kBAAkB,cAAc,SAAS;EACzC;EACA;EACA;EACA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-message-composer.d.ts","names":[],"sources":["../../src/hooks/use-message-composer.ts"],"sourcesContent":[],"mappings":";;;;;KAUY,yBAAA;;AAAZ;;QAIS,EAAA,gBAAA;;;;;EAiCU,cAAA,EAAA,MAAA,GAAA,IAAA;EAMP;;;sBAIJ,CAAA,EAhCgB,YAgChB,EAAA;;;AAgDR;EAAkC,SAAA,CAAA,EAAA,MAAA;;;;;;;;;;oBA/Df;;;;gBAKJ,KACb;;KAKU,wBAAA;;SAGJ;SACA;;;;oBAQW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCH,kBAAA,UACN,4BACP"}
1
+ {"version":3,"file":"use-message-composer.d.ts","names":[],"sources":["../../src/hooks/use-message-composer.ts"],"sourcesContent":[],"mappings":";;;;;KAUY,yBAAA;;AAAZ;;EAewB,MAAA,EAXf,gBAWe;EAiBL;;;;EAWP,cAAA,EAAA,MAAA,GAAA,IAAwB;EAG5B;;;EASe,oBAAA,CAAA,EAxCC,YAwCD,EAAA;EAwCP;;;;;;;;;;;;;oBA/DG;;;;gBAKJ,KACb;;KAKU,wBAAA;;SAGJ;SACA;;;;oBAQW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCH,kBAAA,UACN,4BACP"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-realtime-support.d.ts","names":[],"sources":["../../src/hooks/use-realtime-support.ts"],"sourcesContent":[],"mappings":";;;KAIY,yBAAA;oBACO;AADnB,CAAA;AAIY,KAAA,wBAAA,GAAwB;EAAA,WAAA,EAAA,OAAA;cAG5B,EAAA,OAAA;OACO,EADP,KACO,GAAA,IAAA;MACH,EAAA,CAAA,KAAA,EADG,gBACH,EAAA,GAAA,IAAA;WAEE,EAFF,gBAEE,GAAA,IAAA;;EACgC,WAAA,EADhC,gBACgC,GAAA,IAAA;EAQ9B,SAAA,EAAA,CAAA,OAAA,EAAkB,CAAA,KAAA,EARJ,gBAQI,EAAA,GAAA,IAAA,EAAA,GAAA,GAAA,GAAA,IAAA;CAAA;;;;;;iBAAlB,kBAAA,WACN,4BACP"}
1
+ {"version":3,"file":"use-realtime-support.d.ts","names":[],"sources":["../../src/hooks/use-realtime-support.ts"],"sourcesContent":[],"mappings":";;;KAIY,yBAAA;oBACO;AADnB,CAAA;AAIY,KAAA,wBAAA,GAAwB;EAG5B,WAAA,EAAA,OAAA;EACO,YAAA,EAAA,OAAA;EACH,KAAA,EAFJ,KAEI,GAAA,IAAA;EAEE,IAAA,EAAA,CAAA,KAAA,EAHC,gBAGD,EAAA,GAAA,IAAA;EACgB,SAAA,EAHlB,gBAGkB,GAAA,IAAA;EAAgB;EAQ9B,WAAA,EATF,gBASoB,GAAA,IACxB;+BAToB;;;;;;;iBAQd,kBAAA,WACN,4BACP"}
@@ -9,6 +9,11 @@ type SendMessageOptions = {
9
9
  files?: File[];
10
10
  defaultTimelineItems?: TimelineItem[];
11
11
  visitorId?: string;
12
+ /**
13
+ * Optional message ID to use for the optimistic update and API request.
14
+ * When not provided, a ULID will be generated on the client.
15
+ */
16
+ messageId?: string;
12
17
  onSuccess?: (conversationId: string, messageId: string) => void;
13
18
  onError?: (error: Error) => void;
14
19
  };
@@ -28,6 +33,10 @@ type UseSendMessageResult = {
28
33
  type UseSendMessageOptions = {
29
34
  client?: CossistantClient;
30
35
  };
36
+ /**
37
+ * Sends visitor messages while handling optimistic pending conversations and
38
+ * exposing react-query-like mutation state.
39
+ */
31
40
  declare function useSendMessage(options?: UseSendMessageOptions): UseSendMessageResult;
32
41
  //#endregion
33
42
  export { SendMessageOptions, SendMessageResult, UseSendMessageOptions, UseSendMessageResult, useSendMessage };
@@ -1 +1 @@
1
- {"version":3,"file":"use-send-message.d.ts","names":[],"sources":["../../src/hooks/use-send-message.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,kBAAA;;EAAA,OAAA,EAAA,MAAA;EAAkB,KAAA,CAAA,EAGrB,IAHqB,EAAA;sBAGrB,CAAA,EACe,YADf,EAAA;WACe,CAAA,EAAA,MAAA;WAGL,CAAA,EAAA,CAAA,cAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAK,OAAA,CAAA,EAAA,CAAA,KAAA,EAAL,KAAK,EAAA,GAAA,IAAA;AAGxB,CAAA;AAA6B,KAAjB,iBAAA,GAAiB;gBAGb,EAAA,MAAA;WACQ,EAAA,MAAA;EAA8B,YAAA,CAAA,EADtC,8BACsC,CAAA,cAAA,CAAA;EAG1C,oBAAA,CAAA,EAHY,8BAGQ,CAAA,sBAAA,CAAA;CAAA;AACb,KADP,oBAAA,GACO;QAER,EAAA,CAAA,OAAA,EAFQ,kBAER,EAAA,GAAA,IAAA;aACG,EAAA,CAAA,OAAA,EADH,kBACG,EAAA,GAAR,OAAQ,CAAA,iBAAA,GAAA,IAAA,CAAA;WAAR,EAAA,OAAA;OAEE,EAAA,KAAA,GAAA,IAAA;EAAK,KAAA,EAAA,GAAA,GAAA,IAAA;AAIb,CAAA;AAuCgB,KAvCJ,qBAAA,GAuCkB;EAAA,MAAA,CAAA,EAtCpB,gBAsCoB;;AAE3B,iBAFa,cAAA,CAEb,OAAA,CAAA,EADO,qBACP,CAAA,EAAA,oBAAA"}
1
+ {"version":3,"file":"use-send-message.d.ts","names":[],"sources":["../../src/hooks/use-send-message.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,kBAAA;;EAAA,OAAA,EAAA,MAAA;EAGH,KAAA,CAAA,EAAA,IAAA,EAAA;EACe,oBAAA,CAAA,EAAA,YAAA,EAAA;EAQL,SAAA,CAAA,EAAA,MAAA;EAAK;AAGxB;AAOA;;EAGW,SAAA,CAAA,EAAA,MAAA;EACG,SAAA,CAAA,EAAA,CAAA,cAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAR,OAAA,CAAA,EAAA,CAAA,KAAA,EAda,KAcb,EAAA,GAAA,IAAA;CAEE;AAAK,KAbD,iBAAA,GAaC;EAID,cAAA,EAAA,MAAA;EA6CI,SAAA,EAAA,MAAc;iBA3Dd;yBACQ;;KAGZ,oBAAA;oBACO;yBAER,uBACL,QAAQ;;SAEN;;;KAII,qBAAA;WACF;;;;;;iBA4CM,cAAA,WACN,wBACP"}
@@ -8,10 +8,10 @@ function toError(error) {
8
8
  if (typeof error === "string") return new Error(error);
9
9
  return /* @__PURE__ */ new Error("Unknown error");
10
10
  }
11
- function buildTimelineItemPayload(body, conversationId, visitorId) {
11
+ function buildTimelineItemPayload(body, conversationId, visitorId, messageId) {
12
12
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
13
13
  return {
14
- id: generateMessageId(),
14
+ id: messageId ?? generateMessageId(),
15
15
  conversationId,
16
16
  organizationId: "",
17
17
  type: "message",
@@ -28,13 +28,17 @@ function buildTimelineItemPayload(body, conversationId, visitorId) {
28
28
  deletedAt: null
29
29
  };
30
30
  }
31
+ /**
32
+ * Sends visitor messages while handling optimistic pending conversations and
33
+ * exposing react-query-like mutation state.
34
+ */
31
35
  function useSendMessage(options = {}) {
32
36
  const { client: contextClient } = useSupport();
33
37
  const client = options.client ?? contextClient;
34
38
  const [isPending, setIsPending] = useState(false);
35
39
  const [error, setError] = useState(null);
36
40
  const mutateAsync = useCallback(async (payload) => {
37
- const { conversationId: providedConversationId, message, defaultTimelineItems = [], visitorId, onSuccess, onError } = payload;
41
+ const { conversationId: providedConversationId, message, defaultTimelineItems = [], visitorId, messageId: providedMessageId, onSuccess, onError } = payload;
38
42
  if (!message.trim()) {
39
43
  const emptyMessageError = /* @__PURE__ */ new Error("Message cannot be empty");
40
44
  setError(emptyMessageError);
@@ -56,7 +60,7 @@ function useSendMessage(options = {}) {
56
60
  preparedDefaultTimelineItems = initiated.defaultTimelineItems;
57
61
  initialConversation = initiated.conversation;
58
62
  }
59
- const timelineItemPayload = buildTimelineItemPayload(message, conversationId, visitorId ?? null);
63
+ const timelineItemPayload = buildTimelineItemPayload(message, conversationId, visitorId ?? null, providedMessageId);
60
64
  const response = await client.sendMessage({
61
65
  conversationId,
62
66
  item: {
@@ -97,19 +101,17 @@ function useSendMessage(options = {}) {
97
101
  throw normalised;
98
102
  }
99
103
  }, [client]);
100
- const mutate = useCallback((opts) => {
101
- mutateAsync(opts).catch(() => {});
102
- }, [mutateAsync]);
103
- const reset = useCallback(() => {
104
- setError(null);
105
- setIsPending(false);
106
- }, []);
107
104
  return {
108
- mutate,
105
+ mutate: useCallback((opts) => {
106
+ mutateAsync(opts).catch(() => {});
107
+ }, [mutateAsync]),
109
108
  mutateAsync,
110
109
  isPending,
111
110
  error,
112
- reset
111
+ reset: useCallback(() => {
112
+ setError(null);
113
+ setIsPending(false);
114
+ }, [])
113
115
  };
114
116
  }
115
117
 
@@ -1 +1 @@
1
- {"version":3,"file":"use-send-message.js","names":["initialConversation:\n\t\t\t\t\t| CreateConversationResponseBody[\"conversation\"]\n\t\t\t\t\t| undefined","result: SendMessageResult"],"sources":["../../src/hooks/use-send-message.ts"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport { generateMessageId } from \"@cossistant/core\";\nimport type { CreateConversationResponseBody } from \"@cossistant/types/api/conversation\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { useCallback, useState } from \"react\";\n\nimport { useSupport } from \"../provider\";\n\nexport type SendMessageOptions = {\n\tconversationId?: string | null;\n\tmessage: string;\n\tfiles?: File[];\n\tdefaultTimelineItems?: TimelineItem[];\n\tvisitorId?: string;\n\tonSuccess?: (conversationId: string, messageId: string) => void;\n\tonError?: (error: Error) => void;\n};\n\nexport type SendMessageResult = {\n\tconversationId: string;\n\tmessageId: string;\n\tconversation?: CreateConversationResponseBody[\"conversation\"];\n\tinitialTimelineItems?: CreateConversationResponseBody[\"initialTimelineItems\"];\n};\n\nexport type UseSendMessageResult = {\n\tmutate: (options: SendMessageOptions) => void;\n\tmutateAsync: (\n\t\toptions: SendMessageOptions\n\t) => Promise<SendMessageResult | null>;\n\tisPending: boolean;\n\terror: Error | null;\n\treset: () => void;\n};\n\nexport type UseSendMessageOptions = {\n\tclient?: CossistantClient;\n};\n\nfunction toError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn new Error(error);\n\t}\n\n\treturn new Error(\"Unknown error\");\n}\n\nfunction buildTimelineItemPayload(\n\tbody: string,\n\tconversationId: string,\n\tvisitorId?: string | null\n): TimelineItem {\n\tconst nowIso = new Date().toISOString();\n\n\treturn {\n\t\tid: generateMessageId(),\n\t\tconversationId,\n\t\torganizationId: \"\", // Will be set by backend\n\t\ttype: \"message\" as const,\n\t\ttext: body,\n\t\tparts: [{ type: \"text\" as const, text: body }],\n\t\tvisibility: \"public\" as const,\n\t\tuserId: null,\n\t\taiAgentId: null,\n\t\tvisitorId: visitorId ?? null,\n\t\tcreatedAt: nowIso,\n\t\tdeletedAt: null,\n\t} satisfies TimelineItem;\n}\n\nexport function useSendMessage(\n\toptions: UseSendMessageOptions = {}\n): UseSendMessageResult {\n\tconst { client: contextClient } = useSupport();\n\tconst client = options.client ?? contextClient;\n\n\tconst [isPending, setIsPending] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst mutateAsync = useCallback(\n\t\tasync (payload: SendMessageOptions): Promise<SendMessageResult | null> => {\n\t\t\tconst {\n\t\t\t\tconversationId: providedConversationId,\n\t\t\t\tmessage,\n\t\t\t\tdefaultTimelineItems = [],\n\t\t\t\tvisitorId,\n\t\t\t\tonSuccess,\n\t\t\t\tonError,\n\t\t\t} = payload;\n\n\t\t\tif (!message.trim()) {\n\t\t\t\tconst emptyMessageError = new Error(\"Message cannot be empty\");\n\t\t\t\tsetError(emptyMessageError);\n\t\t\t\tonError?.(emptyMessageError);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tsetIsPending(true);\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tlet conversationId = providedConversationId ?? undefined;\n\t\t\t\tlet preparedDefaultTimelineItems = defaultTimelineItems;\n\t\t\t\tlet initialConversation:\n\t\t\t\t\t| CreateConversationResponseBody[\"conversation\"]\n\t\t\t\t\t| undefined;\n\n\t\t\t\tif (!conversationId) {\n\t\t\t\t\tconst initiated = client.initiateConversation({\n\t\t\t\t\t\tdefaultTimelineItems,\n\t\t\t\t\t\tvisitorId: visitorId ?? undefined,\n\t\t\t\t\t});\n\t\t\t\t\tconversationId = initiated.conversationId;\n\t\t\t\t\tpreparedDefaultTimelineItems = initiated.defaultTimelineItems;\n\t\t\t\t\tinitialConversation = initiated.conversation;\n\t\t\t\t}\n\n\t\t\t\tconst timelineItemPayload = buildTimelineItemPayload(\n\t\t\t\t\tmessage,\n\t\t\t\t\tconversationId,\n\t\t\t\t\tvisitorId ?? null\n\t\t\t\t);\n\n\t\t\t\tconst response = await client.sendMessage({\n\t\t\t\t\tconversationId,\n\t\t\t\t\titem: {\n\t\t\t\t\t\tid: timelineItemPayload.id,\n\t\t\t\t\t\ttext: timelineItemPayload.text ?? \"\",\n\t\t\t\t\t\ttype: timelineItemPayload.type,\n\t\t\t\t\t\tvisibility: timelineItemPayload.visibility,\n\t\t\t\t\t\tuserId: timelineItemPayload.userId,\n\t\t\t\t\t\taiAgentId: timelineItemPayload.aiAgentId,\n\t\t\t\t\t\tvisitorId: timelineItemPayload.visitorId,\n\t\t\t\t\t\tcreatedAt: timelineItemPayload.createdAt,\n\t\t\t\t\t\tparts: timelineItemPayload.parts,\n\t\t\t\t\t},\n\t\t\t\t\tcreateIfPending: true,\n\t\t\t\t});\n\n\t\t\t\tconst messageId = response.item.id;\n\n\t\t\t\tif (!messageId) {\n\t\t\t\t\tthrow new Error(\"SendMessage response missing item.id\");\n\t\t\t\t}\n\n\t\t\t\tconst result: SendMessageResult = {\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessageId,\n\t\t\t\t};\n\n\t\t\t\tif (\"conversation\" in response && response.conversation) {\n\t\t\t\t\tresult.conversation = response.conversation;\n\t\t\t\t\tresult.initialTimelineItems = response.initialTimelineItems;\n\t\t\t\t} else if (initialConversation) {\n\t\t\t\t\tresult.conversation = initialConversation;\n\t\t\t\t\tresult.initialTimelineItems = preparedDefaultTimelineItems;\n\t\t\t\t}\n\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(null);\n\t\t\t\tonSuccess?.(result.conversationId, result.messageId);\n\t\t\t\treturn result;\n\t\t\t} catch (raw) {\n\t\t\t\tconst normalised = toError(raw);\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(normalised);\n\t\t\t\tonError?.(normalised);\n\t\t\t\tthrow normalised;\n\t\t\t}\n\t\t},\n\t\t[client]\n\t);\n\n\tconst mutate = useCallback(\n\t\t(opts: SendMessageOptions) => {\n\t\t\tvoid mutateAsync(opts).catch(() => {\n\t\t\t\t// Swallow errors to mimic react-query behaviour for mutate\n\t\t\t});\n\t\t},\n\t\t[mutateAsync]\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tsetError(null);\n\t\tsetIsPending(false);\n\t}, []);\n\n\treturn {\n\t\tmutate,\n\t\tmutateAsync,\n\t\tisPending,\n\t\terror,\n\t\treset,\n\t};\n}\n"],"mappings":";;;;;AAuCA,SAAS,QAAQ,OAAuB;AACvC,KAAI,iBAAiB,MACpB,QAAO;AAGR,KAAI,OAAO,UAAU,SACpB,QAAO,IAAI,MAAM,MAAM;AAGxB,wBAAO,IAAI,MAAM,gBAAgB;;AAGlC,SAAS,yBACR,MACA,gBACA,WACe;CACf,MAAM,0BAAS,IAAI,MAAM,EAAC,aAAa;AAEvC,QAAO;EACN,IAAI,mBAAmB;EACvB;EACA,gBAAgB;EAChB,MAAM;EACN,MAAM;EACN,OAAO,CAAC;GAAE,MAAM;GAAiB,MAAM;GAAM,CAAC;EAC9C,YAAY;EACZ,QAAQ;EACR,WAAW;EACX,WAAW,aAAa;EACxB,WAAW;EACX,WAAW;EACX;;AAGF,SAAgB,eACf,UAAiC,EAAE,EACZ;CACvB,MAAM,EAAE,QAAQ,kBAAkB,YAAY;CAC9C,MAAM,SAAS,QAAQ,UAAU;CAEjC,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAEtD,MAAM,cAAc,YACnB,OAAO,YAAmE;EACzE,MAAM,EACL,gBAAgB,wBAChB,SACA,uBAAuB,EAAE,EACzB,WACA,WACA,YACG;AAEJ,MAAI,CAAC,QAAQ,MAAM,EAAE;GACpB,MAAM,oCAAoB,IAAI,MAAM,0BAA0B;AAC9D,YAAS,kBAAkB;AAC3B,aAAU,kBAAkB;AAC5B,UAAO;;AAGR,eAAa,KAAK;AAClB,WAAS,KAAK;AAEd,MAAI;GACH,IAAI,iBAAiB,0BAA0B;GAC/C,IAAI,+BAA+B;GACnC,IAAIA;AAIJ,OAAI,CAAC,gBAAgB;IACpB,MAAM,YAAY,OAAO,qBAAqB;KAC7C;KACA,WAAW,aAAa;KACxB,CAAC;AACF,qBAAiB,UAAU;AAC3B,mCAA+B,UAAU;AACzC,0BAAsB,UAAU;;GAGjC,MAAM,sBAAsB,yBAC3B,SACA,gBACA,aAAa,KACb;GAED,MAAM,WAAW,MAAM,OAAO,YAAY;IACzC;IACA,MAAM;KACL,IAAI,oBAAoB;KACxB,MAAM,oBAAoB,QAAQ;KAClC,MAAM,oBAAoB;KAC1B,YAAY,oBAAoB;KAChC,QAAQ,oBAAoB;KAC5B,WAAW,oBAAoB;KAC/B,WAAW,oBAAoB;KAC/B,WAAW,oBAAoB;KAC/B,OAAO,oBAAoB;KAC3B;IACD,iBAAiB;IACjB,CAAC;GAEF,MAAM,YAAY,SAAS,KAAK;AAEhC,OAAI,CAAC,UACJ,OAAM,IAAI,MAAM,uCAAuC;GAGxD,MAAMC,SAA4B;IACjC;IACA;IACA;AAED,OAAI,kBAAkB,YAAY,SAAS,cAAc;AACxD,WAAO,eAAe,SAAS;AAC/B,WAAO,uBAAuB,SAAS;cAC7B,qBAAqB;AAC/B,WAAO,eAAe;AACtB,WAAO,uBAAuB;;AAG/B,gBAAa,MAAM;AACnB,YAAS,KAAK;AACd,eAAY,OAAO,gBAAgB,OAAO,UAAU;AACpD,UAAO;WACC,KAAK;GACb,MAAM,aAAa,QAAQ,IAAI;AAC/B,gBAAa,MAAM;AACnB,YAAS,WAAW;AACpB,aAAU,WAAW;AACrB,SAAM;;IAGR,CAAC,OAAO,CACR;CAED,MAAM,SAAS,aACb,SAA6B;AAC7B,EAAK,YAAY,KAAK,CAAC,YAAY,GAEjC;IAEH,CAAC,YAAY,CACb;CAED,MAAM,QAAQ,kBAAkB;AAC/B,WAAS,KAAK;AACd,eAAa,MAAM;IACjB,EAAE,CAAC;AAEN,QAAO;EACN;EACA;EACA;EACA;EACA;EACA"}
1
+ {"version":3,"file":"use-send-message.js","names":["initialConversation:\n\t\t\t\t\t| CreateConversationResponseBody[\"conversation\"]\n\t\t\t\t\t| undefined","result: SendMessageResult"],"sources":["../../src/hooks/use-send-message.ts"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport { generateMessageId } from \"@cossistant/core\";\nimport type { CreateConversationResponseBody } from \"@cossistant/types/api/conversation\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { useCallback, useState } from \"react\";\n\nimport { useSupport } from \"../provider\";\n\nexport type SendMessageOptions = {\n\tconversationId?: string | null;\n\tmessage: string;\n\tfiles?: File[];\n\tdefaultTimelineItems?: TimelineItem[];\n\tvisitorId?: string;\n\t/**\n\t * Optional message ID to use for the optimistic update and API request.\n\t * When not provided, a ULID will be generated on the client.\n\t */\n\tmessageId?: string;\n\tonSuccess?: (conversationId: string, messageId: string) => void;\n\tonError?: (error: Error) => void;\n};\n\nexport type SendMessageResult = {\n\tconversationId: string;\n\tmessageId: string;\n\tconversation?: CreateConversationResponseBody[\"conversation\"];\n\tinitialTimelineItems?: CreateConversationResponseBody[\"initialTimelineItems\"];\n};\n\nexport type UseSendMessageResult = {\n\tmutate: (options: SendMessageOptions) => void;\n\tmutateAsync: (\n\t\toptions: SendMessageOptions\n\t) => Promise<SendMessageResult | null>;\n\tisPending: boolean;\n\terror: Error | null;\n\treset: () => void;\n};\n\nexport type UseSendMessageOptions = {\n\tclient?: CossistantClient;\n};\n\nfunction toError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn new Error(error);\n\t}\n\n\treturn new Error(\"Unknown error\");\n}\n\nfunction buildTimelineItemPayload(\n\tbody: string,\n\tconversationId: string,\n\tvisitorId: string | null,\n\tmessageId?: string\n): TimelineItem {\n\tconst nowIso = new Date().toISOString();\n\tconst id = messageId ?? generateMessageId();\n\n\treturn {\n\t\tid,\n\t\tconversationId,\n\t\torganizationId: \"\", // Will be set by backend\n\t\ttype: \"message\" as const,\n\t\ttext: body,\n\t\tparts: [{ type: \"text\" as const, text: body }],\n\t\tvisibility: \"public\" as const,\n\t\tuserId: null,\n\t\taiAgentId: null,\n\t\tvisitorId: visitorId ?? null,\n\t\tcreatedAt: nowIso,\n\t\tdeletedAt: null,\n\t} satisfies TimelineItem;\n}\n\n/**\n * Sends visitor messages while handling optimistic pending conversations and\n * exposing react-query-like mutation state.\n */\nexport function useSendMessage(\n\toptions: UseSendMessageOptions = {}\n): UseSendMessageResult {\n\tconst { client: contextClient } = useSupport();\n\tconst client = options.client ?? contextClient;\n\n\tconst [isPending, setIsPending] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst mutateAsync = useCallback(\n\t\tasync (payload: SendMessageOptions): Promise<SendMessageResult | null> => {\n\t\t\tconst {\n\t\t\t\tconversationId: providedConversationId,\n\t\t\t\tmessage,\n\t\t\t\tdefaultTimelineItems = [],\n\t\t\t\tvisitorId,\n\t\t\t\tmessageId: providedMessageId,\n\t\t\t\tonSuccess,\n\t\t\t\tonError,\n\t\t\t} = payload;\n\n\t\t\tif (!message.trim()) {\n\t\t\t\tconst emptyMessageError = new Error(\"Message cannot be empty\");\n\t\t\t\tsetError(emptyMessageError);\n\t\t\t\tonError?.(emptyMessageError);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tsetIsPending(true);\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tlet conversationId = providedConversationId ?? undefined;\n\t\t\t\tlet preparedDefaultTimelineItems = defaultTimelineItems;\n\t\t\t\tlet initialConversation:\n\t\t\t\t\t| CreateConversationResponseBody[\"conversation\"]\n\t\t\t\t\t| undefined;\n\n\t\t\t\tif (!conversationId) {\n\t\t\t\t\tconst initiated = client.initiateConversation({\n\t\t\t\t\t\tdefaultTimelineItems,\n\t\t\t\t\t\tvisitorId: visitorId ?? undefined,\n\t\t\t\t\t});\n\t\t\t\t\tconversationId = initiated.conversationId;\n\t\t\t\t\tpreparedDefaultTimelineItems = initiated.defaultTimelineItems;\n\t\t\t\t\tinitialConversation = initiated.conversation;\n\t\t\t\t}\n\n\t\t\t\tconst timelineItemPayload = buildTimelineItemPayload(\n\t\t\t\t\tmessage,\n\t\t\t\t\tconversationId,\n\t\t\t\t\tvisitorId ?? null,\n\t\t\t\t\tprovidedMessageId\n\t\t\t\t);\n\n\t\t\t\tconst response = await client.sendMessage({\n\t\t\t\t\tconversationId,\n\t\t\t\t\titem: {\n\t\t\t\t\t\tid: timelineItemPayload.id,\n\t\t\t\t\t\ttext: timelineItemPayload.text ?? \"\",\n\t\t\t\t\t\ttype: timelineItemPayload.type,\n\t\t\t\t\t\tvisibility: timelineItemPayload.visibility,\n\t\t\t\t\t\tuserId: timelineItemPayload.userId,\n\t\t\t\t\t\taiAgentId: timelineItemPayload.aiAgentId,\n\t\t\t\t\t\tvisitorId: timelineItemPayload.visitorId,\n\t\t\t\t\t\tcreatedAt: timelineItemPayload.createdAt,\n\t\t\t\t\t\tparts: timelineItemPayload.parts,\n\t\t\t\t\t},\n\t\t\t\t\tcreateIfPending: true,\n\t\t\t\t});\n\n\t\t\t\tconst messageId = response.item.id;\n\n\t\t\t\tif (!messageId) {\n\t\t\t\t\tthrow new Error(\"SendMessage response missing item.id\");\n\t\t\t\t}\n\n\t\t\t\tconst result: SendMessageResult = {\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessageId,\n\t\t\t\t};\n\n\t\t\t\tif (\"conversation\" in response && response.conversation) {\n\t\t\t\t\tresult.conversation = response.conversation;\n\t\t\t\t\tresult.initialTimelineItems = response.initialTimelineItems;\n\t\t\t\t} else if (initialConversation) {\n\t\t\t\t\tresult.conversation = initialConversation;\n\t\t\t\t\tresult.initialTimelineItems = preparedDefaultTimelineItems;\n\t\t\t\t}\n\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(null);\n\t\t\t\tonSuccess?.(result.conversationId, result.messageId);\n\t\t\t\treturn result;\n\t\t\t} catch (raw) {\n\t\t\t\tconst normalised = toError(raw);\n\t\t\t\tsetIsPending(false);\n\t\t\t\tsetError(normalised);\n\t\t\t\tonError?.(normalised);\n\t\t\t\tthrow normalised;\n\t\t\t}\n\t\t},\n\t\t[client]\n\t);\n\n\tconst mutate = useCallback(\n\t\t(opts: SendMessageOptions) => {\n\t\t\tvoid mutateAsync(opts).catch(() => {\n\t\t\t\t// Swallow errors to mimic react-query behaviour for mutate\n\t\t\t});\n\t\t},\n\t\t[mutateAsync]\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tsetError(null);\n\t\tsetIsPending(false);\n\t}, []);\n\n\treturn {\n\t\tmutate,\n\t\tmutateAsync,\n\t\tisPending,\n\t\terror,\n\t\treset,\n\t};\n}\n"],"mappings":";;;;;AA4CA,SAAS,QAAQ,OAAuB;AACvC,KAAI,iBAAiB,MACpB,QAAO;AAGR,KAAI,OAAO,UAAU,SACpB,QAAO,IAAI,MAAM,MAAM;AAGxB,wBAAO,IAAI,MAAM,gBAAgB;;AAGlC,SAAS,yBACR,MACA,gBACA,WACA,WACe;CACf,MAAM,0BAAS,IAAI,MAAM,EAAC,aAAa;AAGvC,QAAO;EACN,IAHU,aAAa,mBAAmB;EAI1C;EACA,gBAAgB;EAChB,MAAM;EACN,MAAM;EACN,OAAO,CAAC;GAAE,MAAM;GAAiB,MAAM;GAAM,CAAC;EAC9C,YAAY;EACZ,QAAQ;EACR,WAAW;EACX,WAAW,aAAa;EACxB,WAAW;EACX,WAAW;EACX;;;;;;AAOF,SAAgB,eACf,UAAiC,EAAE,EACZ;CACvB,MAAM,EAAE,QAAQ,kBAAkB,YAAY;CAC9C,MAAM,SAAS,QAAQ,UAAU;CAEjC,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CAEtD,MAAM,cAAc,YACnB,OAAO,YAAmE;EACzE,MAAM,EACL,gBAAgB,wBAChB,SACA,uBAAuB,EAAE,EACzB,WACA,WAAW,mBACX,WACA,YACG;AAEJ,MAAI,CAAC,QAAQ,MAAM,EAAE;GACpB,MAAM,oCAAoB,IAAI,MAAM,0BAA0B;AAC9D,YAAS,kBAAkB;AAC3B,aAAU,kBAAkB;AAC5B,UAAO;;AAGR,eAAa,KAAK;AAClB,WAAS,KAAK;AAEd,MAAI;GACH,IAAI,iBAAiB,0BAA0B;GAC/C,IAAI,+BAA+B;GACnC,IAAIA;AAIJ,OAAI,CAAC,gBAAgB;IACpB,MAAM,YAAY,OAAO,qBAAqB;KAC7C;KACA,WAAW,aAAa;KACxB,CAAC;AACF,qBAAiB,UAAU;AAC3B,mCAA+B,UAAU;AACzC,0BAAsB,UAAU;;GAGjC,MAAM,sBAAsB,yBAC3B,SACA,gBACA,aAAa,MACb,kBACA;GAED,MAAM,WAAW,MAAM,OAAO,YAAY;IACzC;IACA,MAAM;KACL,IAAI,oBAAoB;KACxB,MAAM,oBAAoB,QAAQ;KAClC,MAAM,oBAAoB;KAC1B,YAAY,oBAAoB;KAChC,QAAQ,oBAAoB;KAC5B,WAAW,oBAAoB;KAC/B,WAAW,oBAAoB;KAC/B,WAAW,oBAAoB;KAC/B,OAAO,oBAAoB;KAC3B;IACD,iBAAiB;IACjB,CAAC;GAEF,MAAM,YAAY,SAAS,KAAK;AAEhC,OAAI,CAAC,UACJ,OAAM,IAAI,MAAM,uCAAuC;GAGxD,MAAMC,SAA4B;IACjC;IACA;IACA;AAED,OAAI,kBAAkB,YAAY,SAAS,cAAc;AACxD,WAAO,eAAe,SAAS;AAC/B,WAAO,uBAAuB,SAAS;cAC7B,qBAAqB;AAC/B,WAAO,eAAe;AACtB,WAAO,uBAAuB;;AAG/B,gBAAa,MAAM;AACnB,YAAS,KAAK;AACd,eAAY,OAAO,gBAAgB,OAAO,UAAU;AACpD,UAAO;WACC,KAAK;GACb,MAAM,aAAa,QAAQ,IAAI;AAC/B,gBAAa,MAAM;AACnB,YAAS,WAAW;AACpB,aAAU,WAAW;AACrB,SAAM;;IAGR,CAAC,OAAO,CACR;AAgBD,QAAO;EACN,QAfc,aACb,SAA6B;AAC7B,GAAK,YAAY,KAAK,CAAC,YAAY,GAEjC;KAEH,CAAC,YAAY,CACb;EASA;EACA;EACA;EACA,OAVa,kBAAkB;AAC/B,YAAS,KAAK;AACd,gBAAa,MAAM;KACjB,EAAE,CAAC;EAQL"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-visitor.d.ts","names":[],"sources":["../../src/hooks/use-visitor.ts"],"sourcesContent":[],"mappings":";;;KAQY,gBAAA;WACF;EADE,kBAAA,EAAgB,CAAA,QAAA,EAGhB,eAHgB,EAAA,GAItB,OAJsB,CAId,eAJc,GAAA,IAAA,CAAA;EAAA,QAAA,EAAA,CAAA,MAAA,EAAA;IAClB,UAAA,CAAA,EAAA,MAAA;IAEE,KAAA,CAAA,EAAA,MAAA;IACE,IAAA,CAAA,EAAA,MAAA;IAAR,KAAA,CAAA,EAAA,MAAA;IAMO,QAAA,CAAA,EAAA,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA;KACN,GAAA,OAAA,CAAA;IAAO,SAAA,EAAA,MAAA;IAsBE,SAAU,EAAA,MAAA;;;;;;;;;;iBAAV,UAAA,CAAA,GAAc"}
1
+ {"version":3,"file":"use-visitor.d.ts","names":[],"sources":["../../src/hooks/use-visitor.ts"],"sourcesContent":[],"mappings":";;;KAQY,gBAAA;WACF;EADE,kBAAA,EAAgB,CAAA,QAAA,EAGhB,eAHgB,EAAA,GAItB,OAJsB,CAId,eAJc,GAAA,IAAA,CAAA;EAClB,QAAA,EAAA,CAAA,MAAA,EAAA;IAEE,UAAA,CAAA,EAAA,MAAA;IACE,KAAA,CAAA,EAAA,MAAA;IAAR,IAAA,CAAA,EAAA,MAAA;IAMO,KAAA,CAAA,EAAA,MAAA;IACN,QAAA,CAAA,EADM,MACN,CAAA,MAAA,EAAA,OAAA,CAAA;EAAO,CAAA,EAAA,GAAP,OAAO,CAAA;IAsBE,SAAU,EAAA,MAAA;;;;;;;;;;;iBAAV,UAAA,CAAA,GAAc"}
@@ -19,38 +19,36 @@ function useVisitor() {
19
19
  const { website, client } = useSupport();
20
20
  const visitor = website?.visitor || null;
21
21
  const visitorId = visitor?.id ?? null;
22
- const setVisitorMetadata = useCallback(async (metadata) => {
23
- if (!visitorId) {
24
- safeWarn("No visitor is associated with this session; metadata update skipped");
25
- return null;
26
- }
27
- try {
28
- return await client.updateVisitorMetadata(metadata);
29
- } catch (error) {
30
- safeError("Failed to update visitor metadata", error);
31
- return null;
32
- }
33
- }, [client, visitorId]);
34
- const identify = useCallback(async (params) => {
35
- if (!visitorId) {
36
- safeWarn("No visitor is associated with this session; identify skipped");
37
- return null;
38
- }
39
- try {
40
- const result = await client.identify(params);
41
- return {
42
- contactId: result.contact.id,
43
- visitorId: result.visitorId
44
- };
45
- } catch (error) {
46
- safeError("Failed to identify visitor", error);
47
- return null;
48
- }
49
- }, [client, visitorId]);
50
22
  return {
51
23
  visitor,
52
- setVisitorMetadata,
53
- identify
24
+ setVisitorMetadata: useCallback(async (metadata) => {
25
+ if (!visitorId) {
26
+ safeWarn("No visitor is associated with this session; metadata update skipped");
27
+ return null;
28
+ }
29
+ try {
30
+ return await client.updateVisitorMetadata(metadata);
31
+ } catch (error) {
32
+ safeError("Failed to update visitor metadata", error);
33
+ return null;
34
+ }
35
+ }, [client, visitorId]),
36
+ identify: useCallback(async (params) => {
37
+ if (!visitorId) {
38
+ safeWarn("No visitor is associated with this session; identify skipped");
39
+ return null;
40
+ }
41
+ try {
42
+ const result = await client.identify(params);
43
+ return {
44
+ contactId: result.contact.id,
45
+ visitorId: result.visitorId
46
+ };
47
+ } catch (error) {
48
+ safeError("Failed to identify visitor", error);
49
+ return null;
50
+ }
51
+ }, [client, visitorId])
54
52
  };
55
53
  }
56
54
 
@@ -1 +1 @@
1
- {"version":3,"file":"use-visitor.js","names":[],"sources":["../../src/hooks/use-visitor.ts"],"sourcesContent":["import type {\n\tPublicVisitor,\n\tVisitorMetadata,\n\tVisitorResponse,\n} from \"@cossistant/types\";\nimport { useCallback } from \"react\";\nimport { useSupport } from \"../provider\";\n\nexport type UseVisitorReturn = {\n\tvisitor: PublicVisitor | null;\n\tsetVisitorMetadata: (\n\t\tmetadata: VisitorMetadata\n\t) => Promise<VisitorResponse | null>;\n\tidentify: (params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) => Promise<{ contactId: string; visitorId: string } | null>;\n};\n\nfunction safeWarn(message: string): void {\n\tif (typeof console !== \"undefined\" && typeof console.warn === \"function\") {\n\t\tconsole.warn(message);\n\t}\n}\n\nfunction safeError(message: string, error: unknown): void {\n\tif (typeof console !== \"undefined\" && typeof console.error === \"function\") {\n\t\tconsole.error(message, error);\n\t}\n}\n\n/**\n * Exposes the current visitor plus helpers to identify and update metadata.\n *\n * Note: Metadata is stored on contacts, not visitors. When you call\n * setVisitorMetadata, it will update the contact metadata if the visitor\n * has been identified. If not, you must call identify() first.\n */\nexport function useVisitor(): UseVisitorReturn {\n\tconst { website, client } = useSupport();\n\tconst visitor = website?.visitor || null;\n\tconst visitorId = visitor?.id ?? null;\n\n\tconst setVisitorMetadata = useCallback<\n\t\t(metadata: VisitorMetadata) => Promise<VisitorResponse | null>\n\t>(\n\t\tasync (metadata) => {\n\t\t\tif (!visitorId) {\n\t\t\t\tsafeWarn(\n\t\t\t\t\t\"No visitor is associated with this session; metadata update skipped\"\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\treturn await client.updateVisitorMetadata(metadata);\n\t\t\t} catch (error) {\n\t\t\t\tsafeError(\"Failed to update visitor metadata\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t[client, visitorId]\n\t);\n\n\tconst identify = useCallback<\n\t\t(params: {\n\t\t\texternalId?: string;\n\t\t\temail?: string;\n\t\t\tname?: string;\n\t\t\timage?: string;\n\t\t\tmetadata?: Record<string, unknown>;\n\t\t}) => Promise<{ contactId: string; visitorId: string } | null>\n\t>(\n\t\tasync (params) => {\n\t\t\tif (!visitorId) {\n\t\t\t\tsafeWarn(\n\t\t\t\t\t\"No visitor is associated with this session; identify skipped\"\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await client.identify(params);\n\n\t\t\t\treturn {\n\t\t\t\t\tcontactId: result.contact.id,\n\t\t\t\t\tvisitorId: result.visitorId,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tsafeError(\"Failed to identify visitor\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t[client, visitorId]\n\t);\n\n\treturn {\n\t\tvisitor,\n\t\tsetVisitorMetadata,\n\t\tidentify,\n\t};\n}\n"],"mappings":";;;;AAsBA,SAAS,SAAS,SAAuB;AACxC,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,SAAS,WAC7D,SAAQ,KAAK,QAAQ;;AAIvB,SAAS,UAAU,SAAiB,OAAsB;AACzD,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,UAAU,WAC9D,SAAQ,MAAM,SAAS,MAAM;;;;;;;;;AAW/B,SAAgB,aAA+B;CAC9C,MAAM,EAAE,SAAS,WAAW,YAAY;CACxC,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,YAAY,SAAS,MAAM;CAEjC,MAAM,qBAAqB,YAG1B,OAAO,aAAa;AACnB,MAAI,CAAC,WAAW;AACf,YACC,sEACA;AACD,UAAO;;AAGR,MAAI;AACH,UAAO,MAAM,OAAO,sBAAsB,SAAS;WAC3C,OAAO;AACf,aAAU,qCAAqC,MAAM;AACrD,UAAO;;IAGT,CAAC,QAAQ,UAAU,CACnB;CAED,MAAM,WAAW,YAShB,OAAO,WAAW;AACjB,MAAI,CAAC,WAAW;AACf,YACC,+DACA;AACD,UAAO;;AAGR,MAAI;GACH,MAAM,SAAS,MAAM,OAAO,SAAS,OAAO;AAE5C,UAAO;IACN,WAAW,OAAO,QAAQ;IAC1B,WAAW,OAAO;IAClB;WACO,OAAO;AACf,aAAU,8BAA8B,MAAM;AAC9C,UAAO;;IAGT,CAAC,QAAQ,UAAU,CACnB;AAED,QAAO;EACN;EACA;EACA;EACA"}
1
+ {"version":3,"file":"use-visitor.js","names":[],"sources":["../../src/hooks/use-visitor.ts"],"sourcesContent":["import type {\n\tPublicVisitor,\n\tVisitorMetadata,\n\tVisitorResponse,\n} from \"@cossistant/types\";\nimport { useCallback } from \"react\";\nimport { useSupport } from \"../provider\";\n\nexport type UseVisitorReturn = {\n\tvisitor: PublicVisitor | null;\n\tsetVisitorMetadata: (\n\t\tmetadata: VisitorMetadata\n\t) => Promise<VisitorResponse | null>;\n\tidentify: (params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) => Promise<{ contactId: string; visitorId: string } | null>;\n};\n\nfunction safeWarn(message: string): void {\n\tif (typeof console !== \"undefined\" && typeof console.warn === \"function\") {\n\t\tconsole.warn(message);\n\t}\n}\n\nfunction safeError(message: string, error: unknown): void {\n\tif (typeof console !== \"undefined\" && typeof console.error === \"function\") {\n\t\tconsole.error(message, error);\n\t}\n}\n\n/**\n * Exposes the current visitor plus helpers to identify and update metadata.\n *\n * Note: Metadata is stored on contacts, not visitors. When you call\n * setVisitorMetadata, it will update the contact metadata if the visitor\n * has been identified. If not, you must call identify() first.\n */\nexport function useVisitor(): UseVisitorReturn {\n\tconst { website, client } = useSupport();\n\tconst visitor = website?.visitor || null;\n\tconst visitorId = visitor?.id ?? null;\n\n\tconst setVisitorMetadata = useCallback<\n\t\t(metadata: VisitorMetadata) => Promise<VisitorResponse | null>\n\t>(\n\t\tasync (metadata) => {\n\t\t\tif (!visitorId) {\n\t\t\t\tsafeWarn(\n\t\t\t\t\t\"No visitor is associated with this session; metadata update skipped\"\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\treturn await client.updateVisitorMetadata(metadata);\n\t\t\t} catch (error) {\n\t\t\t\tsafeError(\"Failed to update visitor metadata\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t[client, visitorId]\n\t);\n\n\tconst identify = useCallback<\n\t\t(params: {\n\t\t\texternalId?: string;\n\t\t\temail?: string;\n\t\t\tname?: string;\n\t\t\timage?: string;\n\t\t\tmetadata?: Record<string, unknown>;\n\t\t}) => Promise<{ contactId: string; visitorId: string } | null>\n\t>(\n\t\tasync (params) => {\n\t\t\tif (!visitorId) {\n\t\t\t\tsafeWarn(\n\t\t\t\t\t\"No visitor is associated with this session; identify skipped\"\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await client.identify(params);\n\n\t\t\t\treturn {\n\t\t\t\t\tcontactId: result.contact.id,\n\t\t\t\t\tvisitorId: result.visitorId,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tsafeError(\"Failed to identify visitor\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t[client, visitorId]\n\t);\n\n\treturn {\n\t\tvisitor,\n\t\tsetVisitorMetadata,\n\t\tidentify,\n\t};\n}\n"],"mappings":";;;;AAsBA,SAAS,SAAS,SAAuB;AACxC,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,SAAS,WAC7D,SAAQ,KAAK,QAAQ;;AAIvB,SAAS,UAAU,SAAiB,OAAsB;AACzD,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,UAAU,WAC9D,SAAQ,MAAM,SAAS,MAAM;;;;;;;;;AAW/B,SAAgB,aAA+B;CAC9C,MAAM,EAAE,SAAS,WAAW,YAAY;CACxC,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,YAAY,SAAS,MAAM;AAuDjC,QAAO;EACN;EACA,oBAvD0B,YAG1B,OAAO,aAAa;AACnB,OAAI,CAAC,WAAW;AACf,aACC,sEACA;AACD,WAAO;;AAGR,OAAI;AACH,WAAO,MAAM,OAAO,sBAAsB,SAAS;YAC3C,OAAO;AACf,cAAU,qCAAqC,MAAM;AACrD,WAAO;;KAGT,CAAC,QAAQ,UAAU,CACnB;EAqCA,UAnCgB,YAShB,OAAO,WAAW;AACjB,OAAI,CAAC,WAAW;AACf,aACC,+DACA;AACD,WAAO;;AAGR,OAAI;IACH,MAAM,SAAS,MAAM,OAAO,SAAS,OAAO;AAE5C,WAAO;KACN,WAAW,OAAO,QAAQ;KAC1B,WAAW,OAAO;KAClB;YACO,OAAO;AACf,cAAU,8BAA8B,MAAM;AAC9C,WAAO;;KAGT,CAAC,QAAQ,UAAU,CACnB;EAMA"}
@@ -3,6 +3,10 @@ type WindowVisibilityFocusState = {
3
3
  isPageVisible: boolean;
4
4
  hasWindowFocus: boolean;
5
5
  };
6
+ /**
7
+ * Tracks document visibility and window focus so hooks can defer updates while
8
+ * the user is away from the page.
9
+ */
6
10
  declare function useWindowVisibilityFocus(): WindowVisibilityFocusState;
7
11
  //#endregion
8
12
  export { WindowVisibilityFocusState, useWindowVisibilityFocus };
@@ -1 +1 @@
1
- {"version":3,"file":"use-window-visibility-focus.d.ts","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":[],"mappings":";KAEY,0BAAA;EAAA,aAAA,EAAA,OAAA;EAkBI,cAAA,EAAA,OAAA;;iBAAA,wBAAA,CAAA,GAA4B"}
1
+ {"version":3,"file":"use-window-visibility-focus.d.ts","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":[],"mappings":";KAEY,0BAAA;EAAA,aAAA,EAAA,OAAA;EAsBI,cAAA,EAAA,OAAA;;;;;;iBAAA,wBAAA,CAAA,GAA4B"}
@@ -7,12 +7,15 @@ const getVisibilityFocusState = () => {
7
7
  hasWindowFocus: true
8
8
  };
9
9
  const isPageVisible = !document.hidden;
10
- const hasWindowFocus = isPageVisible && (typeof document.hasFocus === "function" ? document.hasFocus() : true);
11
10
  return {
12
11
  isPageVisible,
13
- hasWindowFocus
12
+ hasWindowFocus: isPageVisible && (typeof document.hasFocus === "function" ? document.hasFocus() : true)
14
13
  };
15
14
  };
15
+ /**
16
+ * Tracks document visibility and window focus so hooks can defer updates while
17
+ * the user is away from the page.
18
+ */
16
19
  function useWindowVisibilityFocus() {
17
20
  const [state, setState] = useState(() => getVisibilityFocusState());
18
21
  useEffect(() => {