@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-window-visibility-focus.js","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type WindowVisibilityFocusState = {\n isPageVisible: boolean;\n hasWindowFocus: boolean;\n};\n\nconst getVisibilityFocusState = (): WindowVisibilityFocusState => {\n if (typeof document === \"undefined\") {\n return { isPageVisible: true, hasWindowFocus: true };\n }\n\n const isPageVisible = !document.hidden;\n const hasWindowFocus =\n isPageVisible &&\n (typeof document.hasFocus === \"function\" ? document.hasFocus() : true);\n\n return { isPageVisible, hasWindowFocus };\n};\n\nexport function useWindowVisibilityFocus(): WindowVisibilityFocusState {\n const [state, setState] = useState<WindowVisibilityFocusState>(\n () => getVisibilityFocusState()\n );\n\n useEffect(() => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const handleVisibilityChange = () => {\n setState(getVisibilityFocusState());\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n handleVisibilityChange();\n return () => {\n document.removeEventListener(\n \"visibilitychange\",\n handleVisibilityChange\n );\n };\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const syncVisibilityFocus = () => {\n setState(getVisibilityFocusState());\n };\n\n const handleFocus = () => {\n syncVisibilityFocus();\n };\n const handleBlur = () => {\n syncVisibilityFocus();\n };\n\n window.addEventListener(\"focus\", handleFocus);\n window.addEventListener(\"blur\", handleBlur);\n\n syncVisibilityFocus();\n\n return () => {\n window.removeEventListener(\"focus\", handleFocus);\n window.removeEventListener(\"blur\", handleBlur);\n };\n }, []);\n\n return state;\n}\n"],"mappings":";;;AAOA,MAAM,gCAA4D;AAC1D,KAAI,OAAO,aAAa,YAChB,QAAO;EAAE,eAAe;EAAM,gBAAgB;EAAM;CAG5D,MAAM,gBAAgB,CAAC,SAAS;CAChC,MAAM,iBACE,kBACC,OAAO,SAAS,aAAa,aAAa,SAAS,UAAU,GAAG;AAEzE,QAAO;EAAE;EAAe;EAAgB;;AAGhD,SAAgB,2BAAuD;CAC/D,MAAM,CAAC,OAAO,YAAY,eACZ,yBAAyB,CACtC;AAED,iBAAgB;AACR,MAAI,OAAO,aAAa,YAChB;EAGR,MAAM,+BAA+B;AAC7B,YAAS,yBAAyB,CAAC;;AAG3C,WAAS,iBAAiB,oBAAoB,uBAAuB;AACrE,0BAAwB;AACxB,eAAa;AACL,YAAS,oBACD,oBACA,uBACP;;IAEd,EAAE,CAAC;AAEN,iBAAgB;AACR,MAAI,OAAO,WAAW,YACd;EAGR,MAAM,4BAA4B;AAC1B,YAAS,yBAAyB,CAAC;;EAG3C,MAAM,oBAAoB;AAClB,wBAAqB;;EAE7B,MAAM,mBAAmB;AACjB,wBAAqB;;AAG7B,SAAO,iBAAiB,SAAS,YAAY;AAC7C,SAAO,iBAAiB,QAAQ,WAAW;AAE3C,uBAAqB;AAErB,eAAa;AACL,UAAO,oBAAoB,SAAS,YAAY;AAChD,UAAO,oBAAoB,QAAQ,WAAW;;IAE3D,EAAE,CAAC;AAEN,QAAO"}
1
+ {"version":3,"file":"use-window-visibility-focus.js","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type WindowVisibilityFocusState = {\n\tisPageVisible: boolean;\n\thasWindowFocus: boolean;\n};\n\nconst getVisibilityFocusState = (): WindowVisibilityFocusState => {\n\tif (typeof document === \"undefined\") {\n\t\treturn { isPageVisible: true, hasWindowFocus: true };\n\t}\n\n\tconst isPageVisible = !document.hidden;\n\tconst hasWindowFocus =\n\t\tisPageVisible &&\n\t\t(typeof document.hasFocus === \"function\" ? document.hasFocus() : true);\n\n\treturn { isPageVisible, hasWindowFocus };\n};\n\n/**\n * Tracks document visibility and window focus so hooks can defer updates while\n * the user is away from the page.\n */\nexport function useWindowVisibilityFocus(): WindowVisibilityFocusState {\n\tconst [state, setState] = useState<WindowVisibilityFocusState>(() =>\n\t\tgetVisibilityFocusState()\n\t);\n\n\tuseEffect(() => {\n\t\tif (typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tsetState(getVisibilityFocusState());\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\thandleVisibilityChange();\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst syncVisibilityFocus = () => {\n\t\t\tsetState(getVisibilityFocusState());\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsyncVisibilityFocus();\n\t\t};\n\t\tconst handleBlur = () => {\n\t\t\tsyncVisibilityFocus();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\twindow.addEventListener(\"blur\", handleBlur);\n\n\t\tsyncVisibilityFocus();\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\twindow.removeEventListener(\"blur\", handleBlur);\n\t\t};\n\t}, []);\n\n\treturn state;\n}\n"],"mappings":";;;AAOA,MAAM,gCAA4D;AACjE,KAAI,OAAO,aAAa,YACvB,QAAO;EAAE,eAAe;EAAM,gBAAgB;EAAM;CAGrD,MAAM,gBAAgB,CAAC,SAAS;AAKhC,QAAO;EAAE;EAAe,gBAHvB,kBACC,OAAO,SAAS,aAAa,aAAa,SAAS,UAAU,GAAG;EAE1B;;;;;;AAOzC,SAAgB,2BAAuD;CACtE,MAAM,CAAC,OAAO,YAAY,eACzB,yBAAyB,CACzB;AAED,iBAAgB;AACf,MAAI,OAAO,aAAa,YACvB;EAGD,MAAM,+BAA+B;AACpC,YAAS,yBAAyB,CAAC;;AAGpC,WAAS,iBAAiB,oBAAoB,uBAAuB;AACrE,0BAAwB;AACxB,eAAa;AACZ,YAAS,oBAAoB,oBAAoB,uBAAuB;;IAEvE,EAAE,CAAC;AAEN,iBAAgB;AACf,MAAI,OAAO,WAAW,YACrB;EAGD,MAAM,4BAA4B;AACjC,YAAS,yBAAyB,CAAC;;EAGpC,MAAM,oBAAoB;AACzB,wBAAqB;;EAEtB,MAAM,mBAAmB;AACxB,wBAAqB;;AAGtB,SAAO,iBAAiB,SAAS,YAAY;AAC7C,SAAO,iBAAiB,QAAQ,WAAW;AAE3C,uBAAqB;AAErB,eAAa;AACZ,UAAO,oBAAoB,SAAS,YAAY;AAChD,UAAO,oBAAoB,QAAQ,WAAW;;IAE7C,EAAE,CAAC;AAEN,QAAO"}
@@ -1,16 +1,25 @@
1
+ import { ReactElement } from "react";
2
+ import { VisitorMetadata } from "@cossistant/types";
3
+
1
4
  //#region src/identify-visitor.d.ts
2
5
  type IdentifySupportVisitorProps = {
3
6
  externalId?: string;
4
7
  email?: string;
8
+ name?: string | null;
9
+ image?: string | null;
10
+ metadata?: VisitorMetadata | null;
5
11
  };
6
12
  /**
7
- * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`.
13
+ * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.
8
14
  */
9
15
  declare const IdentifySupportVisitor: {
10
16
  ({
11
17
  externalId,
12
- email
13
- }: IdentifySupportVisitorProps): null;
18
+ email,
19
+ name,
20
+ image,
21
+ metadata: _newMetadata
22
+ }: IdentifySupportVisitorProps): ReactElement | null;
14
23
  displayName: string;
15
24
  };
16
25
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"identify-visitor.d.ts","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":[],"mappings":";KAIY,2BAAA;EAAA,UAAA,CAAA,EAAA,MAAA;EAQC,KAAA,CAAA,EAAA,MAAA;CAcZ;;;;AAX6B,cAHjB,sBAGiB,EAAA;;;;KAA3B"}
1
+ {"version":3,"file":"identify-visitor.d.ts","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":[],"mappings":";;;;KAOY,2BAAA;EAAA,UAAA,CAAA,EAAA,MAAA;EAWC,KAAA,CAAA,EAAA,MAAA;;;aAND;;;;;AAYiC,cANhC,sBAMgC,EAAA;;;;;;;KAA1C,8BAA8B"}
@@ -1,21 +1,70 @@
1
1
  import { useVisitor } from "./hooks/use-visitor.js";
2
- import { useEffect } from "react";
2
+ import { computeMetadataHash } from "./utils/metadata-hash.js";
3
+ import { useEffect, useState } from "react";
3
4
 
4
5
  //#region src/identify-visitor.tsx
5
6
  /**
6
- * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`.
7
+ * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.
7
8
  */
8
- const IdentifySupportVisitor = ({ externalId, email }) => {
9
- const { visitor, identify } = useVisitor();
9
+ const IdentifySupportVisitor = ({ externalId, email, name, image, metadata: _newMetadata }) => {
10
+ const { visitor, identify, setVisitorMetadata } = useVisitor();
11
+ const [hasIdentified, setHasIdentified] = useState(false);
12
+ const [lastMetadataHash, setLastMetadataHash] = useState(null);
10
13
  useEffect(() => {
11
- if (!visitor?.contact && (externalId || email)) identify({
12
- externalId,
13
- email
14
- });
14
+ const shouldIdentify = async () => {
15
+ if (!Boolean(externalId || email)) return;
16
+ if (!visitor?.contact) {
17
+ if (!hasIdentified) {
18
+ await identify({
19
+ externalId,
20
+ email,
21
+ name: name ?? void 0,
22
+ image: image ?? void 0
23
+ });
24
+ setHasIdentified(true);
25
+ }
26
+ return;
27
+ }
28
+ const contact = visitor.contact;
29
+ const nameChanged = name !== void 0 && name !== contact.name;
30
+ const emailChanged = email !== void 0 && email !== contact.email;
31
+ const imageChanged = image !== void 0 && image !== contact.image;
32
+ if (nameChanged || emailChanged || imageChanged) await identify({
33
+ externalId,
34
+ email,
35
+ name: name ?? void 0,
36
+ image: image ?? void 0
37
+ });
38
+ };
39
+ shouldIdentify();
15
40
  }, [
16
41
  visitor?.contact,
17
42
  externalId,
18
- email
43
+ email,
44
+ name,
45
+ image,
46
+ identify,
47
+ hasIdentified
48
+ ]);
49
+ useEffect(() => {
50
+ const updateMetadata = async () => {
51
+ if (!_newMetadata) return;
52
+ if (!visitor?.contact) return;
53
+ const newMetadataHash = await computeMetadataHash(_newMetadata);
54
+ const hashChanged = newMetadataHash !== (visitor.contact.metadataHash || "");
55
+ const notAlreadyUpdated = newMetadataHash !== lastMetadataHash;
56
+ if (Boolean(newMetadataHash && hashChanged && notAlreadyUpdated)) {
57
+ await setVisitorMetadata(_newMetadata);
58
+ setLastMetadataHash(newMetadataHash);
59
+ }
60
+ };
61
+ updateMetadata();
62
+ }, [
63
+ _newMetadata,
64
+ visitor?.contact?.metadataHash,
65
+ visitor?.contact,
66
+ setVisitorMetadata,
67
+ lastMetadataHash
19
68
  ]);
20
69
  return null;
21
70
  };
@@ -1 +1 @@
1
- {"version":3,"file":"identify-visitor.js","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":["/** biome-ignore-all lint/correctness/useExhaustiveDependencies: wanted here */\nimport { useEffect } from \"react\";\nimport { useVisitor } from \"./hooks\";\n\nexport type IdentifySupportVisitorProps = {\n\texternalId?: string;\n\temail?: string;\n};\n\n/**\n * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`.\n */\nexport const IdentifySupportVisitor = ({\n\texternalId,\n\temail,\n}: IdentifySupportVisitorProps) => {\n\tconst { visitor, identify } = useVisitor();\n\n\t// Only update when the arrays actually change content\n\tuseEffect(() => {\n\t\tif (!visitor?.contact && (externalId || email)) {\n\t\t\tidentify({ externalId, email });\n\t\t}\n\t}, [visitor?.contact, externalId, email]);\n\n\treturn null;\n};\n\nIdentifySupportVisitor.displayName = \"IdentifySupportVisitor\";\n"],"mappings":";;;;;;;AAYA,MAAa,0BAA0B,EACtC,YACA,YACkC;CAClC,MAAM,EAAE,SAAS,aAAa,YAAY;AAG1C,iBAAgB;AACf,MAAI,CAAC,SAAS,YAAY,cAAc,OACvC,UAAS;GAAE;GAAY;GAAO,CAAC;IAE9B;EAAC,SAAS;EAAS;EAAY;EAAM,CAAC;AAEzC,QAAO;;AAGR,uBAAuB,cAAc"}
1
+ {"version":3,"file":"identify-visitor.js","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":["/** biome-ignore-all lint/correctness/useExhaustiveDependencies: wanted here */\n\nimport type { VisitorMetadata } from \"@cossistant/types\";\nimport { type ReactElement, useEffect, useState } from \"react\";\nimport { useVisitor } from \"./hooks\";\nimport { computeMetadataHash } from \"./utils/metadata-hash\";\n\nexport type IdentifySupportVisitorProps = {\n\texternalId?: string;\n\temail?: string;\n\tname?: string | null;\n\timage?: string | null;\n\tmetadata?: VisitorMetadata | null;\n};\n\n/**\n * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.\n */\nexport const IdentifySupportVisitor = ({\n\texternalId,\n\temail,\n\tname,\n\timage,\n\tmetadata: _newMetadata,\n}: IdentifySupportVisitorProps): ReactElement | null => {\n\tconst { visitor, identify, setVisitorMetadata } = useVisitor();\n\tconst [hasIdentified, setHasIdentified] = useState(false);\n\tconst [lastMetadataHash, setLastMetadataHash] = useState<string | null>(null);\n\n\t// Only call identify if:\n\t// 1. Visitor hasn't been identified yet (no contact)\n\t// 2. Name, email, or image changed compared to current contact\n\tuseEffect(() => {\n\t\tconst shouldIdentify = async () => {\n\t\t\tconst hasIdentificationData = Boolean(externalId || email);\n\n\t\t\t// Need at least externalId or email to identify\n\t\t\tif (!hasIdentificationData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Case 1: No contact exists yet\n\t\t\tif (!visitor?.contact) {\n\t\t\t\tif (!hasIdentified) {\n\t\t\t\t\tawait identify({\n\t\t\t\t\t\texternalId,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tname: name ?? undefined,\n\t\t\t\t\t\timage: image ?? undefined,\n\t\t\t\t\t});\n\t\t\t\t\tsetHasIdentified(true);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Case 2: Contact exists but name/email/image changed\n\t\t\tconst contact = visitor.contact;\n\t\t\tconst nameChanged = name !== undefined && name !== contact.name;\n\t\t\tconst emailChanged = email !== undefined && email !== contact.email;\n\t\t\tconst imageChanged = image !== undefined && image !== contact.image;\n\t\t\tconst hasChanges = nameChanged || emailChanged || imageChanged;\n\n\t\t\tif (hasChanges) {\n\t\t\t\tawait identify({\n\t\t\t\t\texternalId,\n\t\t\t\t\temail,\n\t\t\t\t\tname: name ?? undefined,\n\t\t\t\t\timage: image ?? undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tshouldIdentify();\n\t}, [\n\t\tvisitor?.contact,\n\t\texternalId,\n\t\temail,\n\t\tname,\n\t\timage,\n\t\tidentify,\n\t\thasIdentified,\n\t]);\n\n\t// Compute metadata hash, compare to previous hash and only update if it has changed\n\tuseEffect(() => {\n\t\tconst updateMetadata = async () => {\n\t\t\t// Skip if no metadata provided or visitor doesn't have a contact\n\t\t\tif (!_newMetadata) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!visitor?.contact) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Compute new metadata hash\n\t\t\tconst newMetadataHash = await computeMetadataHash(_newMetadata);\n\n\t\t\t// Get the existing hash from the contact\n\t\t\tconst existingHash = visitor.contact.metadataHash || \"\";\n\n\t\t\t// Only update if hashes don't match and we haven't already updated with this hash\n\t\t\tconst hashChanged = newMetadataHash !== existingHash;\n\t\t\tconst notAlreadyUpdated = newMetadataHash !== lastMetadataHash;\n\t\t\tconst shouldUpdate = Boolean(\n\t\t\t\tnewMetadataHash && hashChanged && notAlreadyUpdated\n\t\t\t);\n\n\t\t\tif (shouldUpdate) {\n\t\t\t\tawait setVisitorMetadata(_newMetadata);\n\t\t\t\tsetLastMetadataHash(newMetadataHash);\n\t\t\t}\n\t\t};\n\n\t\tupdateMetadata();\n\t}, [\n\t\t_newMetadata,\n\t\tvisitor?.contact?.metadataHash,\n\t\tvisitor?.contact,\n\t\tsetVisitorMetadata,\n\t\tlastMetadataHash,\n\t]);\n\n\treturn null;\n};\n\nIdentifySupportVisitor.displayName = \"IdentifySupportVisitor\";\n"],"mappings":";;;;;;;;AAkBA,MAAa,0BAA0B,EACtC,YACA,OACA,MACA,OACA,UAAU,mBAC6C;CACvD,MAAM,EAAE,SAAS,UAAU,uBAAuB,YAAY;CAC9D,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,kBAAkB,uBAAuB,SAAwB,KAAK;AAK7E,iBAAgB;EACf,MAAM,iBAAiB,YAAY;AAIlC,OAAI,CAH0B,QAAQ,cAAc,MAAM,CAIzD;AAID,OAAI,CAAC,SAAS,SAAS;AACtB,QAAI,CAAC,eAAe;AACnB,WAAM,SAAS;MACd;MACA;MACA,MAAM,QAAQ;MACd,OAAO,SAAS;MAChB,CAAC;AACF,sBAAiB,KAAK;;AAEvB;;GAID,MAAM,UAAU,QAAQ;GACxB,MAAM,cAAc,SAAS,UAAa,SAAS,QAAQ;GAC3D,MAAM,eAAe,UAAU,UAAa,UAAU,QAAQ;GAC9D,MAAM,eAAe,UAAU,UAAa,UAAU,QAAQ;AAG9D,OAFmB,eAAe,gBAAgB,aAGjD,OAAM,SAAS;IACd;IACA;IACA,MAAM,QAAQ;IACd,OAAO,SAAS;IAChB,CAAC;;AAIJ,kBAAgB;IACd;EACF,SAAS;EACT;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;AAGF,iBAAgB;EACf,MAAM,iBAAiB,YAAY;AAElC,OAAI,CAAC,aACJ;AAGD,OAAI,CAAC,SAAS,QACb;GAID,MAAM,kBAAkB,MAAM,oBAAoB,aAAa;GAM/D,MAAM,cAAc,qBAHC,QAAQ,QAAQ,gBAAgB;GAIrD,MAAM,oBAAoB,oBAAoB;AAK9C,OAJqB,QACpB,mBAAmB,eAAe,kBAClC,EAEiB;AACjB,UAAM,mBAAmB,aAAa;AACtC,wBAAoB,gBAAgB;;;AAItC,kBAAgB;IACd;EACF;EACA,SAAS,SAAS;EAClB,SAAS;EACT;EACA;EACA,CAAC;AAEF,QAAO;;AAGR,uBAAuB,cAAc"}
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useClientQuery } from "./hooks/private/use-client-query.js";
2
2
  import { useDefaultMessages } from "./hooks/private/use-default-messages.js";
3
- import { ConversationItem, GroupedMessage, TimelineEventItem, UseGroupedMessagesOptions, UseGroupedMessagesProps, useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
3
+ import { ConversationItem, GroupedMessage, TimelineEventItem, TimelineToolItem, UseGroupedMessagesOptions, UseGroupedMessagesProps, useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
4
4
  import { UseMultimodalInputOptions, UseMultimodalInputReturn, useMultimodalInput } from "./hooks/private/use-multimodal-input.js";
5
5
  import { UseClientResult, useClient } from "./hooks/private/use-rest-client.js";
6
6
  import { UseComposerRefocusOptions, UseComposerRefocusReturn, useComposerRefocus } from "./hooks/use-composer-refocus.js";
@@ -9,9 +9,12 @@ import { CONVERSATION_AUTO_SEEN_DELAY_MS, UseConversationAutoSeenOptions, useCon
9
9
  import { UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, useConversationHistoryPage } from "./hooks/use-conversation-history-page.js";
10
10
  import { ConversationLifecycleState, UseConversationLifecycleOptions, UseConversationLifecycleReturn, useConversationLifecycle } from "./hooks/use-conversation-lifecycle.js";
11
11
  import { UseConversationPageOptions, UseConversationPageReturn, useConversationPage } from "./hooks/use-conversation-page.js";
12
- import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
12
+ import { SupportLocale, SupportTextContentOverrides } from "./support/text/locales/keys.js";
13
13
  import { UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, useConversationTimelineItems } from "./hooks/use-conversation-timeline-items.js";
14
+ import { ConversationPreviewAssignedAgent, ConversationPreviewLastMessage, ConversationPreviewTypingParticipant, ConversationPreviewTypingState, UseConversationPreviewOptions, UseConversationPreviewReturn, useConversationPreview } from "./hooks/use-conversation-preview.js";
15
+ import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
14
16
  import { ConversationTypingParticipant, useConversationTyping } from "./hooks/use-conversation-typing.js";
17
+ import { ConversationTimelineTypingParticipant, UseConversationTimelineOptions, UseConversationTimelineReturn, useConversationTimeline } from "./hooks/use-conversation-timeline.js";
15
18
  import { UseConversationsOptions, UseConversationsResult, useConversations } from "./hooks/use-conversations.js";
16
19
  import { CreateConversationVariables, UseCreateConversationOptions, UseCreateConversationResult, useCreateConversation } from "./hooks/use-create-conversation.js";
17
20
  import { UseHomePageOptions, UseHomePageReturn, useHomePage } from "./hooks/use-home-page.js";
@@ -20,19 +23,19 @@ import { UseRealtimeSupportOptions, UseRealtimeSupportResult, useRealtimeSupport
20
23
  import { SendMessageOptions, SendMessageResult, UseSendMessageOptions, UseSendMessageResult, useSendMessage } from "./hooks/use-send-message.js";
21
24
  import { UseVisitorReturn, useVisitor } from "./hooks/use-visitor.js";
22
25
  import { WindowVisibilityFocusState, useWindowVisibilityFocus } from "./hooks/use-window-visibility-focus.js";
26
+ import "./hooks/index.js";
23
27
  import { IdentifySupportVisitor, IdentifySupportVisitorProps } from "./identify-visitor.js";
24
28
  import { SupportConfig, SupportConfigProps } from "./support-config.js";
25
29
  import { index_d_exports } from "./primitives/index.js";
26
- import { CossistantContextValue, CossistantProviderProps, SupportProvider, SupportProviderProps, useSupport } from "./provider.js";
30
+ import { CossistantContextValue, CossistantProviderProps, SupportContext, SupportProvider, SupportProviderProps, UseSupportValue, useSupport } from "./provider.js";
27
31
  import { RealtimeAuthConfig, RealtimeContextValue, RealtimeProvider, RealtimeProviderProps, useRealtimeConnection } from "./realtime/provider.js";
28
32
  import { applyConversationSeenEvent, hydrateConversationSeen, upsertConversationSeen } from "./realtime/seen-store.js";
29
33
  import { SupportRealtimeProvider } from "./realtime/support-provider.js";
30
34
  import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, setTypingState } from "./realtime/typing-store.js";
31
35
  import { RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, useRealtime } from "./realtime/use-realtime.js";
32
- import { SupportLocale, SupportTextContentOverrides } from "./support/text/locales/keys.js";
36
+ import "./realtime/index.js";
33
37
  import { Text, useSupportText } from "./support/text/index.js";
34
- import { useSupportConfig } from "./support/context/config.js";
35
38
  import { WebSocketContextValue, WebSocketProvider, useWebSocket } from "./support/context/websocket.js";
36
- import { useSupportStore } from "./support/store/support-store.js";
39
+ import { useSupportConfig, useSupportNavigation, useSupportStore } from "./support/store/support-store.js";
37
40
  import { Support, SupportProps } from "./support/index.js";
38
- export { CONVERSATION_AUTO_SEEN_DELAY_MS, ConversationItem, ConversationLifecycleState, ConversationTypingParticipant, CossistantContextValue, CossistantProviderProps, CreateConversationVariables, GroupedMessage, IdentifySupportVisitor, IdentifySupportVisitorProps, index_d_exports as Primitives, RealtimeAuthConfig, RealtimeContextValue, RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, RealtimeProvider, RealtimeProviderProps, SendMessageOptions, SendMessageResult, Support, SupportConfig, SupportConfigProps, SupportLocale, SupportProps, SupportProvider, SupportProviderProps, SupportRealtimeProvider, SupportTextContentOverrides, Text, TimelineEventItem, UseClientResult, UseComposerRefocusOptions, UseComposerRefocusReturn, UseConversationAutoSeenOptions, UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, UseConversationLifecycleOptions, UseConversationLifecycleReturn, UseConversationOptions, UseConversationPageOptions, UseConversationPageReturn, UseConversationResult, UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, UseConversationsOptions, UseConversationsResult, UseCreateConversationOptions, UseCreateConversationResult, UseGroupedMessagesOptions, UseGroupedMessagesProps, UseHomePageOptions, UseHomePageReturn, UseMessageComposerOptions, UseMessageComposerReturn, UseMultimodalInputOptions, UseMultimodalInputReturn, UseRealtimeSupportOptions, UseRealtimeSupportResult, UseSendMessageOptions, UseSendMessageResult, UseVisitorReturn, WebSocketContextValue, WebSocketProvider, WindowVisibilityFocusState, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationSeen, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
41
+ export { CONVERSATION_AUTO_SEEN_DELAY_MS, ConversationItem, ConversationLifecycleState, ConversationPreviewAssignedAgent, ConversationPreviewLastMessage, ConversationPreviewTypingParticipant, ConversationPreviewTypingState, ConversationTimelineTypingParticipant, ConversationTypingParticipant, CossistantContextValue, CossistantProviderProps, CreateConversationVariables, GroupedMessage, IdentifySupportVisitor, IdentifySupportVisitorProps, index_d_exports as Primitives, RealtimeAuthConfig, RealtimeContextValue, RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, RealtimeProvider, RealtimeProviderProps, SendMessageOptions, SendMessageResult, Support, SupportConfig, SupportConfigProps, SupportContext, SupportLocale, SupportProps, SupportProvider, SupportProviderProps, SupportRealtimeProvider, SupportTextContentOverrides, Text, TimelineEventItem, TimelineToolItem, UseClientResult, UseComposerRefocusOptions, UseComposerRefocusReturn, UseConversationAutoSeenOptions, UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, UseConversationLifecycleOptions, UseConversationLifecycleReturn, UseConversationOptions, UseConversationPageOptions, UseConversationPageReturn, UseConversationPreviewOptions, UseConversationPreviewReturn, UseConversationResult, UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, UseConversationTimelineOptions, UseConversationTimelineReturn, UseConversationsOptions, UseConversationsResult, UseCreateConversationOptions, UseCreateConversationResult, UseGroupedMessagesOptions, UseGroupedMessagesProps, UseHomePageOptions, UseHomePageReturn, UseMessageComposerOptions, UseMessageComposerReturn, UseMultimodalInputOptions, UseMultimodalInputReturn, UseRealtimeSupportOptions, UseRealtimeSupportResult, UseSendMessageOptions, UseSendMessageResult, UseSupportValue, UseVisitorReturn, WebSocketContextValue, WebSocketProvider, WindowVisibilityFocusState, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationPreview, useConversationSeen, useConversationTimeline, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
package/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { useClientQuery } from "./hooks/private/use-client-query.js";
2
2
  import { useClient } from "./hooks/private/use-rest-client.js";
3
- import { RealtimeProvider, useRealtimeConnection } from "./realtime/provider.js";
4
3
  import { applyConversationSeenEvent, hydrateConversationSeen, upsertConversationSeen } from "./realtime/seen-store.js";
4
+ import { RealtimeProvider, useRealtimeConnection } from "./realtime/provider.js";
5
5
  import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, setTypingState } from "./realtime/typing-store.js";
6
6
  import { useRealtime } from "./realtime/use-realtime.js";
7
7
  import { SupportRealtimeProvider } from "./realtime/support-provider.js";
8
8
  import { SupportConfig } from "./support-config.js";
9
- import { useSupportStore } from "./support/store/support-store.js";
10
- import { useSupportConfig } from "./support/context/config.js";
9
+ import { useSupportConfig, useSupportNavigation, useSupportStore } from "./support/store/support-store.js";
11
10
  import { primitives_exports } from "./primitives/index.js";
12
11
  import { Text, useSupportText } from "./support/text/index.js";
12
+ import { useConversation } from "./hooks/use-conversation.js";
13
13
  import { useWindowVisibilityFocus } from "./hooks/use-window-visibility-focus.js";
14
14
  import { CONVERSATION_AUTO_SEEN_DELAY_MS, useConversationAutoSeen } from "./hooks/use-conversation-auto-seen.js";
15
15
  import { useConversationLifecycle } from "./hooks/use-conversation-lifecycle.js";
@@ -19,20 +19,21 @@ import { useSendMessage } from "./hooks/use-send-message.js";
19
19
  import { useMessageComposer } from "./hooks/use-message-composer.js";
20
20
  import { useConversationPage } from "./hooks/use-conversation-page.js";
21
21
  import { useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
22
+ import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
23
+ import { useConversationTyping } from "./hooks/use-conversation-typing.js";
24
+ import { useConversationTimeline } from "./hooks/use-conversation-timeline.js";
22
25
  import { useComposerRefocus } from "./hooks/use-composer-refocus.js";
26
+ import { useVisitor } from "./hooks/use-visitor.js";
23
27
  import { useConversations } from "./hooks/use-conversations.js";
24
28
  import { useConversationHistoryPage } from "./hooks/use-conversation-history-page.js";
29
+ import { useConversationPreview } from "./hooks/use-conversation-preview.js";
25
30
  import { useHomePage } from "./hooks/use-home-page.js";
26
31
  import { WebSocketProvider, useWebSocket } from "./support/context/websocket.js";
27
32
  import { Support } from "./support/index.js";
28
- import { SupportProvider, useSupport } from "./provider.js";
33
+ import { SupportContext, SupportProvider, useSupport } from "./provider.js";
29
34
  import { useDefaultMessages } from "./hooks/private/use-default-messages.js";
30
- import { useConversation } from "./hooks/use-conversation.js";
31
- import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
32
- import { useConversationTyping } from "./hooks/use-conversation-typing.js";
33
35
  import { useCreateConversation } from "./hooks/use-create-conversation.js";
34
36
  import { useRealtimeSupport } from "./hooks/use-realtime-support.js";
35
- import { useVisitor } from "./hooks/use-visitor.js";
36
37
  import { IdentifySupportVisitor } from "./identify-visitor.js";
37
38
 
38
- export { CONVERSATION_AUTO_SEEN_DELAY_MS, IdentifySupportVisitor, primitives_exports as Primitives, RealtimeProvider, Support, SupportConfig, SupportProvider, SupportRealtimeProvider, Text, WebSocketProvider, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationSeen, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
39
+ export { CONVERSATION_AUTO_SEEN_DELAY_MS, IdentifySupportVisitor, primitives_exports as Primitives, RealtimeProvider, Support, SupportConfig, SupportContext, SupportProvider, SupportRealtimeProvider, Text, WebSocketProvider, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationPreview, useConversationSeen, useConversationTimeline, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
package/package.json CHANGED
@@ -1,27 +1,22 @@
1
1
  {
2
2
  "name": "@cossistant/react",
3
- "version": "0.0.4",
3
+ "type": "module",
4
+ "version": "0.0.5",
4
5
  "private": false,
5
6
  "author": "Cossistant team",
6
7
  "description": "Headless React SDK for building AI-powered support/chat widgets. Hooks + primitives, WS-driven, TypeScript-first. Next.js-ready, Tailwind optional.",
7
8
  "keywords": [
8
9
  "react",
9
- "headless",
10
10
  "headless-ui",
11
- "support",
12
- "customer support",
11
+ "support-widget",
12
+ "chat-widget",
13
+ "customer-support",
13
14
  "helpdesk",
14
- "support widget",
15
- "chat widget",
16
- "live chat",
17
- "ai",
18
- "ai support",
19
- "ai-agent",
20
- "support agent",
15
+ "live-chat",
16
+ "ai-support",
17
+ "websocket",
21
18
  "typescript",
22
- "nextjs",
23
19
  "tailwind",
24
- "shadcn",
25
20
  "accessibility"
26
21
  ],
27
22
  "bugs": {
@@ -56,10 +51,10 @@
56
51
  "import": "./hooks/index.js"
57
52
  },
58
53
  "./hooks/*": {
59
- "types": "./hooks/*d.ts",
60
- "import": "./hooks/*js"
54
+ "types": "./hooks/*.d.ts",
55
+ "import": "./hooks/*.js"
61
56
  },
62
- "./support.css": "./support/support.css",
57
+ "./support.css": "./support.css",
63
58
  "./realtime": {
64
59
  "types": "./realtime/index.d.ts",
65
60
  "import": "./realtime/index.js"
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/primitives/avatar/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAGK,WAAA;;AAH0B,CAAA;AAOnB,KAAA,WAAA,GAAc,IAAH,CACtB,OAAA,CAAM,cADgB,CACD,eADC,CAAA,EAAA,UAAA,CAAA,GAAA;EAAA,QAAA,CAAA,EAIX,OAAA,CAAM,SAJK;SACD,CAAA,EAAA,OAAA;WAArB,CAAA,EAAM,MAAA;;AAGK,UAKK,kBAAA,SAA2B,WAL1B,CAAA;EAAS,0BAAA,EAAA,CAAA,MAAA,EAOjB,WAPiB,CAAA,oBAAA,CAAA,EAAA,GAAA,IAAA;AAK3B;;;;;AAYa,cAAA,gBAAgB,EAAA,GAAA,GAAA,kBAQ5B;AAMD;;;;AAAmB,cAAN,MAAM,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,eAAA,CAAA,EAAA,UAAA,CAAA,GAAA;UA/BP,CAAA,EAAA,OAAA,CAAM,SAAA;;;yBA+BC,gBAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/primitives/avatar/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAGK,WAAA;;AAH0B,CAAA;AAOnB,KAAA,WAAA,GAAc,IAAH,CACtB,OAAA,CAAM,cADgB,CACD,eADC,CAAA,EAAA,UAAA,CAAA,GAAA;EACD,QAAA,CAAA,EAGV,OAAA,CAAM,SAHI;EAArB,OAAM,CAAA,EAAA,OAAA;EADmB,SAAA,CAAA,EAAA,MAAA;CAId;AAAe,UAKV,kBAAA,SAA2B,WALjB,CAAA;EAKV,0BAAmB,EAAA,CAAA,MAE1B,EAAA,WAFkC,CAAA,oBAAW,CAAA,EAAA,GAAA,IAAA;AAYvD;AAcA;;;;AA/BY,cAiBC,gBAjBK,EAAA,GAAA,GAiBW,kBAjBX;;;;;cA+BL,QAAM,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aA/BP,OAAA,CAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"fallback.d.ts","names":[],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":[],"mappings":";;;KASY,mBAAA,GAAsB,KACjC,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EAJN,IAAA,CAAA,EAAA,MAAA;EAAmB,OAAA,CAAA,EAAA,MAAA;SACT,CAAA,EAAA,OAAA;WAArB,CAAA,EAAM,MAAA;;;;AA+BP;;AAA2B,cAAd,cAAc,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,eAAA,CAAA,EAAA,UAAA,CAAA,GAAA;UAAA,CAAA,EA5Bf,OAAA,CAAM,SA4BS;MAAA,CAAA,EAAA,MAAA;SA5Bf,CAAA,EAAA,MAAM;;;yBA4BS,gBAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"fallback.d.ts","names":[],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":[],"mappings":";;;KASY,mBAAA,GAAsB,KACjC,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EAJN,IAAA,CAAA,EAAA,MAAA;EACU,OAAA,CAAA,EAAA,MAAA;EAArB,OAAM,CAAA,EAAA,OAAA;EAD2B,SAAA,CAAA,EAAA,MAAA;CAItB;;AA4BZ;;;AAA2B,cAAd,cAAc,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,eAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EA5Bf,QAAM,CAAA,EAAN,OAAA,CAAM,SAAA;;;EA4BS,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA"}
@@ -7,9 +7,7 @@ const getInitials = (name) => {
7
7
  const names = name.trim().split(" ");
8
8
  if (names.length === 0) return "";
9
9
  if (names.length === 1) return names[0]?.charAt(0).toUpperCase() || "";
10
- const firstInitial = names[0]?.charAt(0) || "";
11
- const lastInitial = names[names.length - 1]?.charAt(0) || "";
12
- return (firstInitial + lastInitial).toUpperCase();
10
+ return ((names[0]?.charAt(0) || "") + (names[names.length - 1]?.charAt(0) || "")).toUpperCase();
13
11
  };
14
12
  /**
15
13
  * Displays initials or custom content while the avatar image loads or fails.
@@ -1 +1 @@
1
- {"version":3,"file":"fallback.js","names":["React","state: FallbackState"],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { useAvatarContext } from \"./avatar\";\n\ntype FallbackState = {\n\timageLoadingStatus: \"idle\" | \"loading\" | \"loaded\" | \"error\";\n\tinitials?: string;\n};\n\nexport type AvatarFallbackProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tname?: string;\n\tdelayMs?: number;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\nconst getInitials = (name: string): string => {\n\tconst names = name.trim().split(\" \");\n\tif (names.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tif (names.length === 1) {\n\t\treturn names[0]?.charAt(0).toUpperCase() || \"\";\n\t}\n\n\tconst firstInitial = names[0]?.charAt(0) || \"\";\n\t// biome-ignore lint/style/useAtIndex: ok here\n\tconst lastInitial = names[names.length - 1]?.charAt(0) || \"\";\n\n\treturn (firstInitial + lastInitial).toUpperCase();\n};\n\n/**\n * Displays initials or custom content while the avatar image loads or fails.\n * Optional delay avoids flashes when images load instantly.\n */\nexport const AvatarFallback = (() => {\n\tconst Component = React.forwardRef<HTMLSpanElement, AvatarFallbackProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tname = \"\",\n\t\t\t\tdelayMs = 0,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { imageLoadingStatus } = useAvatarContext();\n\t\t\tconst [canRender, setCanRender] = React.useState(delayMs === 0);\n\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (delayMs > 0) {\n\t\t\t\t\tconst timerId = window.setTimeout(() => setCanRender(true), delayMs);\n\t\t\t\t\treturn () => window.clearTimeout(timerId);\n\t\t\t\t}\n\t\t\t}, [delayMs]);\n\n\t\t\tconst initials = React.useMemo(() => {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn getInitials(name);\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}, [name]);\n\n\t\t\tconst state: FallbackState = {\n\t\t\t\timageLoadingStatus,\n\t\t\t\tinitials,\n\t\t\t};\n\n\t\t\tconst shouldRender =\n\t\t\t\tcanRender &&\n\t\t\t\timageLoadingStatus !== \"loaded\" &&\n\t\t\t\timageLoadingStatus !== \"loading\";\n\n\t\t\tconst content = children || initials;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate,\n\t\t\t\t\tenabled: shouldRender,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"AvatarFallback\";\n\treturn Component;\n})();\n"],"mappings":";;;;;AAoBA,MAAM,eAAe,SAAyB;CAC7C,MAAM,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI;AACpC,KAAI,MAAM,WAAW,EACpB,QAAO;AAGR,KAAI,MAAM,WAAW,EACpB,QAAO,MAAM,IAAI,OAAO,EAAE,CAAC,aAAa,IAAI;CAG7C,MAAM,eAAe,MAAM,IAAI,OAAO,EAAE,IAAI;CAE5C,MAAM,cAAc,MAAM,MAAM,SAAS,IAAI,OAAO,EAAE,IAAI;AAE1D,SAAQ,eAAe,aAAa,aAAa;;;;;;AAOlD,MAAa,wBAAwB;CACpC,MAAM,YAAYA,QAAM,YAEtB,EACC,UACA,OAAO,IACP,UAAU,GACV,WACA,UAAU,MACV,GAAG,SAEJ,QACI;EACJ,MAAM,EAAE,uBAAuB,kBAAkB;EACjD,MAAM,CAAC,WAAW,gBAAgBA,QAAM,SAAS,YAAY,EAAE;AAE/D,UAAM,gBAAgB;AACrB,OAAI,UAAU,GAAG;IAChB,MAAM,UAAU,OAAO,iBAAiB,aAAa,KAAK,EAAE,QAAQ;AACpE,iBAAa,OAAO,aAAa,QAAQ;;KAExC,CAAC,QAAQ,CAAC;EAEb,MAAM,WAAWA,QAAM,cAAc;AACpC,OAAI,KACH,QAAO,YAAY,KAAK;AAEzB,UAAO;KACL,CAAC,KAAK,CAAC;EAEV,MAAMC,QAAuB;GAC5B;GACA;GACA;EAED,MAAM,eACL,aACA,uBAAuB,YACvB,uBAAuB;EAExB,MAAM,UAAU,YAAY;AAE5B,SAAO,iBACN,QACA;GACC;GACA;GACA,EACD;GACC;GACA;GACA,SAAS;GACT,OAAO;IACN,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
1
+ {"version":3,"file":"fallback.js","names":["React","state: FallbackState"],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { useAvatarContext } from \"./avatar\";\n\ntype FallbackState = {\n\timageLoadingStatus: \"idle\" | \"loading\" | \"loaded\" | \"error\";\n\tinitials?: string;\n};\n\nexport type AvatarFallbackProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tname?: string;\n\tdelayMs?: number;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\nconst getInitials = (name: string): string => {\n\tconst names = name.trim().split(\" \");\n\tif (names.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tif (names.length === 1) {\n\t\treturn names[0]?.charAt(0).toUpperCase() || \"\";\n\t}\n\n\tconst firstInitial = names[0]?.charAt(0) || \"\";\n\t// biome-ignore lint/style/useAtIndex: ok here\n\tconst lastInitial = names[names.length - 1]?.charAt(0) || \"\";\n\n\treturn (firstInitial + lastInitial).toUpperCase();\n};\n\n/**\n * Displays initials or custom content while the avatar image loads or fails.\n * Optional delay avoids flashes when images load instantly.\n */\nexport const AvatarFallback = (() => {\n\tconst Component = React.forwardRef<HTMLSpanElement, AvatarFallbackProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tname = \"\",\n\t\t\t\tdelayMs = 0,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { imageLoadingStatus } = useAvatarContext();\n\t\t\tconst [canRender, setCanRender] = React.useState(delayMs === 0);\n\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (delayMs > 0) {\n\t\t\t\t\tconst timerId = window.setTimeout(() => setCanRender(true), delayMs);\n\t\t\t\t\treturn () => window.clearTimeout(timerId);\n\t\t\t\t}\n\t\t\t}, [delayMs]);\n\n\t\t\tconst initials = React.useMemo(() => {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn getInitials(name);\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}, [name]);\n\n\t\t\tconst state: FallbackState = {\n\t\t\t\timageLoadingStatus,\n\t\t\t\tinitials,\n\t\t\t};\n\n\t\t\tconst shouldRender =\n\t\t\t\tcanRender &&\n\t\t\t\timageLoadingStatus !== \"loaded\" &&\n\t\t\t\timageLoadingStatus !== \"loading\";\n\n\t\t\tconst content = children || initials;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate,\n\t\t\t\t\tenabled: shouldRender,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"AvatarFallback\";\n\treturn Component;\n})();\n"],"mappings":";;;;;AAoBA,MAAM,eAAe,SAAyB;CAC7C,MAAM,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI;AACpC,KAAI,MAAM,WAAW,EACpB,QAAO;AAGR,KAAI,MAAM,WAAW,EACpB,QAAO,MAAM,IAAI,OAAO,EAAE,CAAC,aAAa,IAAI;AAO7C,UAJqB,MAAM,IAAI,OAAO,EAAE,IAAI,OAExB,MAAM,MAAM,SAAS,IAAI,OAAO,EAAE,IAAI,KAEtB,aAAa;;;;;;AAOlD,MAAa,wBAAwB;CACpC,MAAM,YAAYA,QAAM,YAEtB,EACC,UACA,OAAO,IACP,UAAU,GACV,WACA,UAAU,MACV,GAAG,SAEJ,QACI;EACJ,MAAM,EAAE,uBAAuB,kBAAkB;EACjD,MAAM,CAAC,WAAW,gBAAgBA,QAAM,SAAS,YAAY,EAAE;AAE/D,UAAM,gBAAgB;AACrB,OAAI,UAAU,GAAG;IAChB,MAAM,UAAU,OAAO,iBAAiB,aAAa,KAAK,EAAE,QAAQ;AACpE,iBAAa,OAAO,aAAa,QAAQ;;KAExC,CAAC,QAAQ,CAAC;EAEb,MAAM,WAAWA,QAAM,cAAc;AACpC,OAAI,KACH,QAAO,YAAY,KAAK;AAEzB,UAAO;KACL,CAAC,KAAK,CAAC;EAEV,MAAMC,QAAuB;GAC5B;GACA;GACA;EAED,MAAM,eACL,aACA,uBAAuB,YACvB,uBAAuB;EAExB,MAAM,UAAU,YAAY;AAE5B,SAAO,iBACN,QACA;GACC;GACA;GACA,EACD;GACC;GACA;GACA,SAAS;GACT,OAAO;IACN,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","names":[],"sources":["../../../src/primitives/avatar/image.tsx"],"sourcesContent":[],"mappings":";;;KAIK,UAAA;;AAJ0B,CAAA;AAQnB,KAAA,gBAAA,GAAmB,IAAH,CAC3B,OAAA,CAAM,iBADqB,CACH,gBADG,CAAA,EAAA,KAAA,GAAA,KAAA,CAAA,GAAA;EAAA,GAAA,EAAA,MAAA;KACH,CAAA,EAAA,MAAA;SAAxB,CAAA,EAAA,OAAM;WADwB,CAAA,EAAA,MAAA;uBAQG,CAAA,EAAA,CAAA,MAAA,EAAA,UAAA,CAAA,oBAAA,CAAA,EAAA,GAAA,IAAA;CAAU;AAO5C;;;;AAAwB,cAAX,WAAW,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,gBAAA,CAAA,EAAA,KAAA,GAAA,KAAA,CAAA,GAAA;KAPU,EAAA,MAAA;;;WAOV,CAAA,EAAA,MAAA;EAAA,qBAAA,CAAA,EAAA,CAAA,MAAA,EAPU,UAOV,CAAA,oBAAA,CAAA,EAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"image.d.ts","names":[],"sources":["../../../src/primitives/avatar/image.tsx"],"sourcesContent":[],"mappings":";;;KAIK,UAAA;;AAJ0B,CAAA;AAQnB,KAAA,gBAAA,GAAmB,IAAH,CAC3B,OAAA,CAAM,iBADqB,CACH,gBADG,CAAA,EAAA,KAAA,GAAA,KAAA,CAAA,GAAA;EACH,GAAA,EAAA,MAAA;EAAxB,GAAA,CAAA,EAAM,MAAA;EADwB,OAAA,CAAA,EAAA,OAAA;EAQG,SAAA,CAAA,EAAA,MAAA;EAAU,qBAAA,CAAA,EAAA,CAAA,MAAA,EAAV,UAAU,CAAA,oBAAA,CAAA,EAAA,GAAA,IAAA;AAO5C,CAAA;;;;;cAAa,aAAW,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,kBAAA;;EAAA,GAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,OAAA;;mCAPU"}
@@ -1,4 +1,5 @@
1
1
  import { Avatar, AvatarProps } from "./avatar.js";
2
2
  import { AvatarFallback, AvatarFallbackProps } from "./fallback.js";
3
3
  import { AvatarImage, AvatarImageProps } from "./image.js";
4
+ import "./index.parts.js";
4
5
  export { Avatar, AvatarFallback, AvatarFallbackProps, AvatarImage, AvatarImageProps, AvatarProps };
@@ -5,6 +5,7 @@ type SupportBubbleProps = Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>,
5
5
  children?: React$1.ReactNode | ((props: {
6
6
  isOpen: boolean;
7
7
  unreadCount: number;
8
+ isTyping: boolean;
8
9
  toggle: () => void;
9
10
  }) => React$1.ReactNode);
10
11
  asChild?: boolean;
@@ -18,6 +19,7 @@ declare const SupportBubble: React$1.ForwardRefExoticComponent<Omit<React$1.Butt
18
19
  children?: React$1.ReactNode | ((props: {
19
20
  isOpen: boolean;
20
21
  unreadCount: number;
22
+ isTyping: boolean;
21
23
  toggle: () => void;
22
24
  }) => React$1.ReactNode);
23
25
  asChild?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"bubble.d.ts","names":[],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":[],"mappings":";;;KAKY,kBAAA,GAAqB,KAChC,OAAA,CAAM,qBAAqB;aAIxB,OAAA,CAAM;IALE,MAAA,EAAA,OAAA;IAAkB,WAAA,EAAA,MAAA;IACF,MAAA,EAAA,GAAA,GAAA,IAAA;KAA3B,GASS,OAAA,CAAM,SATT,CAAA;SAD0B,CAAA,EAAA,OAAA;WAK7B,CAAA,EAAM,MAAA;;;AAcV;;;AAA0B,cAAb,aAAa,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,iBAAA,CAAA,EAAA,UAAA,CAAA,GAAA;UAAA,CAAA,EAdtB,OAAA,CAAM,SAcgB,GAAA,CAAA,CAAA,KAAA,EAAA;IAdtB,MAAA,EAAM,OAAA;IAKA,WAAM,EAAA,MAAA;;QAAN,OAAA,CAAM;SASU,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA"}
1
+ {"version":3,"file":"bubble.d.ts","names":[],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":[],"mappings":";;;KAMY,kBAAA,GAAqB,KAChC,OAAA,CAAM,qBAAqB;aAIxB,OAAA,CAAM;IALE,MAAA,EAAA,OAAA;IACgB,WAAA,EAAA,MAAA;IAA3B,QAAM,EAAA,OAAA;IAD0B,MAAA,EAAA,GAAA,GAAA,IAAA;EAK7B,CAAA,EAAA,GAMM,OAAA,CAAM,SANN,CAAA;EAMA,OAAM,CAAA,EAAA,OAAA;EAAS,SAAA,CAAA,EAAA,MAAA;AASzB,CAAA;;;;;AATU,cASG,aATG,EASU,OAAA,CAAA,yBATV,CASU,IATV,CASU,OAAA,CAAA,oBATV,CASU,iBATV,CAAA,EAAA,UAAA,CAAA,GAAA;aANZ,OAAA,CAAM;;IAegB,WAAA,EAAA,MAAA;IAAA,QAAA,EAAA,OAAA;;QAThB,OAAA,CAAM"}
@@ -1,5 +1,6 @@
1
+ import { useTypingStore } from "../realtime/typing-store.js";
1
2
  import { useRenderElement } from "../utils/use-render-element.js";
2
- import { useSupportConfig } from "../support/context/config.js";
3
+ import { useSupportConfig } from "../support/store/support-store.js";
3
4
  import { useSupport } from "../provider.js";
4
5
  import * as React$1 from "react";
5
6
 
@@ -11,10 +12,15 @@ import * as React$1 from "react";
11
12
  const SupportBubble = (() => {
12
13
  const Component = React$1.forwardRef(({ children, className, asChild = false,...props }, ref) => {
13
14
  const { isOpen, toggle } = useSupportConfig();
14
- const { unreadCount } = useSupport();
15
+ const { unreadCount, visitor } = useSupport();
16
+ const visitorId = visitor?.id ?? null;
15
17
  const renderProps = {
16
18
  isOpen,
17
19
  unreadCount,
20
+ isTyping: useTypingStore(React$1.useCallback((state) => Object.values(state.conversations).some((entries) => Object.values(entries).some((entry) => {
21
+ if (visitorId && entry.actorType === "visitor" && entry.actorId === visitorId) return false;
22
+ return true;
23
+ })), [visitorId])),
18
24
  toggle
19
25
  };
20
26
  const content = typeof children === "function" ? children(renderProps) : children;
@@ -1 +1 @@
1
- {"version":3,"file":"bubble.js","names":["React"],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useSupportConfig } from \"../support\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type SupportBubbleProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: {\n\t\t\t\tisOpen: boolean;\n\t\t\t\tunreadCount: number;\n\t\t\t\ttoggle: () => void;\n\t\t }) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Floating action button that toggles the support window. Exposes widget state\n * and unread counts to render-prop children for fully custom UI shells.\n */\nexport const SupportBubble = (() => {\n\tconst Component = React.forwardRef<HTMLButtonElement, SupportBubbleProps>(\n\t\t({ children, className, asChild = false, ...props }, ref) => {\n\t\t\tconst { isOpen, toggle } = useSupportConfig();\n\t\t\tconst { unreadCount } = useSupport();\n\n\t\t\tconst renderProps = { isOpen, unreadCount, toggle };\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"button\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\ttype: \"button\",\n\t\t\t\t\t\t\"aria-haspopup\": \"dialog\",\n\t\t\t\t\t\t\"aria-expanded\": isOpen,\n\t\t\t\t\t\tonClick: toggle,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"SupportBubble\";\n\treturn Component;\n})();\n"],"mappings":";;;;;;;;;;AAwBA,MAAa,uBAAuB;CACnC,MAAM,YAAYA,QAAM,YACtB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QAAQ;EAC5D,MAAM,EAAE,QAAQ,WAAW,kBAAkB;EAC7C,MAAM,EAAE,gBAAgB,YAAY;EAEpC,MAAM,cAAc;GAAE;GAAQ;GAAa;GAAQ;EAEnD,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;AAE1D,SAAO,iBACN,UACA;GACC;GACA;GACA,EACD;GACC;GACA,OAAO;GACP,OAAO;IACN,MAAM;IACN,iBAAiB;IACjB,iBAAiB;IACjB,SAAS;IACT,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
1
+ {"version":3,"file":"bubble.js","names":["React"],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useTypingStore } from \"../realtime/typing-store\";\nimport { useSupportConfig } from \"../support\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type SupportBubbleProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: {\n\t\t\t\tisOpen: boolean;\n\t\t\t\tunreadCount: number;\n\t\t\t\tisTyping: boolean;\n\t\t\t\ttoggle: () => void;\n\t\t }) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Floating action button that toggles the support window. Exposes widget state\n * and unread counts to render-prop children for fully custom UI shells.\n */\nexport const SupportBubble = (() => {\n\tconst Component = React.forwardRef<HTMLButtonElement, SupportBubbleProps>(\n\t\t({ children, className, asChild = false, ...props }, ref) => {\n\t\t\tconst { isOpen, toggle } = useSupportConfig();\n\t\t\tconst { unreadCount, visitor } = useSupport();\n\t\t\tconst visitorId = visitor?.id ?? null;\n\n\t\t\tconst hasTyping = useTypingStore(\n\t\t\t\tReact.useCallback(\n\t\t\t\t\t(state) =>\n\t\t\t\t\t\tObject.values(state.conversations).some((entries) =>\n\t\t\t\t\t\t\tObject.values(entries).some((entry) => {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tvisitorId &&\n\t\t\t\t\t\t\t\t\tentry.actorType === \"visitor\" &&\n\t\t\t\t\t\t\t\t\tentry.actorId === visitorId\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t\t[visitorId]\n\t\t\t\t)\n\t\t\t);\n\n\t\t\tconst renderProps = {\n\t\t\t\tisOpen,\n\t\t\t\tunreadCount,\n\t\t\t\tisTyping: hasTyping,\n\t\t\t\ttoggle,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"button\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\ttype: \"button\",\n\t\t\t\t\t\t\"aria-haspopup\": \"dialog\",\n\t\t\t\t\t\t\"aria-expanded\": isOpen,\n\t\t\t\t\t\tonClick: toggle,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"SupportBubble\";\n\treturn Component;\n})();\n"],"mappings":";;;;;;;;;;;AA0BA,MAAa,uBAAuB;CACnC,MAAM,YAAYA,QAAM,YACtB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QAAQ;EAC5D,MAAM,EAAE,QAAQ,WAAW,kBAAkB;EAC7C,MAAM,EAAE,aAAa,YAAY,YAAY;EAC7C,MAAM,YAAY,SAAS,MAAM;EAsBjC,MAAM,cAAc;GACnB;GACA;GACA,UAvBiB,eACjBA,QAAM,aACJ,UACA,OAAO,OAAO,MAAM,cAAc,CAAC,MAAM,YACxC,OAAO,OAAO,QAAQ,CAAC,MAAM,UAAU;AACtC,QACC,aACA,MAAM,cAAc,aACpB,MAAM,YAAY,UAElB,QAAO;AAGR,WAAO;KACN,CACF,EACF,CAAC,UAAU,CACX,CACD;GAMA;GACA;EAED,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;AAE1D,SAAO,iBACN,UACA;GACC;GACA;GACA,EACD;GACC;GACA,OAAO;GACP,OAAO;IACN,MAAM;IACN,iBAAiB;IACjB,iBAAiB;IACjB,SAAS;IACT,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","names":[],"sources":["../../src/primitives/button.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA,GAAc,OAAA,CAAM,qBAAqB;;EAAzC,SAAA,CAAA,EAAA,MAAW;CAAA;;;;AAUvB;;AAAmB,cAAN,MAAM,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,iBAAA,CAAA,GAAA;SAAA,CAAA,EAAA,OAAA"}
1
+ {"version":3,"file":"button.d.ts","names":[],"sources":["../../src/primitives/button.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA,GAAc,OAAA,CAAM,qBAAqB;;EAAzC,SAAA,CAAA,EAAA,MAAW;AAUvB,CAAA;;;;;;AAAmB,cAAN,MAAM,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,iBAAA,CAAA,GAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAOA;AAAqC,KAPzB,+BAAA,GAOyB;WACf,EAAA,MAAA;WAArB,CAAA,EAAM,OAAA;SADiC,CAAA,EAAA,OAAA;SAKpC,EAAA,OAAM;;AACuC,KANrC,yBAAA,GAA4B,IAMe,CALtD,OAAA,CAAM,cAKgD,CALjC,cAKiC,CAAA,EAAA,UAAA,CAAA,GAAA;UAG9C,CAAA,EAJL,OAAA,CAAM,SAID,GAAA,CAAA,CAAA,KAAA,EAHI,+BAGJ,EAAA,GAHwC,OAAA,CAAM,SAG9C,CAAA;EAAgB,OAAA,CAAA,EAAA,OAAA;EAYZ,SAAA,CAAA,EAAA,MAAA;EAwGT,KAAA,CAAA,EApHK,YAoHL,EAAA;WAxG6B,CAAA,EAAA,OAAA;SAAA,CAAA,EAAA,OAAA;YAAA,CAAA,EAAA,OAAA;aAhBvB,CAAA,EAAA,GAAA,GAAA,IAAA;eACG,CAAA,EAAA,GAAA,GAAA,IAAA;;;;;;AAeoB,cAApB,oBAAoB,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EA0GrB,QAAA,CAAA,EA1HR,OAAA,CAAM,SA0HE,GAAA,CAAA,CAAA,KAAA,EAzHC,+BAyHiC,EAAA,GAzHG,OAAA,CAAM,SAyHT,CAAA;EAAA,OAAA,CAAA,EAAA,OAAA;WACxB,CAAA,EAAA,MAAA;OAArB,CAAA,EAvHQ,YAuHF,EAAA;WAD0C,CAAA,EAAA,OAAA;SAIrC,CAAA,EAAA,OAAM;EAAS,UAAA,CAAA,EAAA,OAAA;EASd,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAuBT,aAAA,CAAA,EAAA,GAAA,GAAA,IAAA;yBAvBsC,eAAA,CAAA,CAAA;AAAA,KAb9B,kCAAA,GAAqC,IAaP,CAZzC,OAAA,CAAM,cAYmC,CAZpB,cAYoB,CAAA,EAAA,UAAA,CAAA,GAAA;UAAA,CAAA,EAT9B,OAAA,CAAM,SASwB;SAT9B,CAAA,EAAA,OAAM;;;;;AAkClB;;AACsB,cA1BT,6BA0BS,EA1BoB,OAAA,CAAA,yBA0BpB,CA1BoB,IA0BpB,CA1BoB,OAAA,CAAA,cA0BpB,CA1BoB,cA0BpB,CAAA,EAAA,UAAA,CAAA,GAAA;UAArB,CAAA,EAnCW,OAAA,CAAM,SAmCX;SADwC,CAAA,EAAA,OAAA;WAInC,CAAA,EAAM,MAAA;CAAS,wBAAA,eAAA,CAAA,CAAA;AASd,KAbD,gCAAA,GAAmC,IAsC3C,CArCH,OAAA,CAAM,cAqCH,CArCkB,cAqClB,CAAA,EAAA,UAAA,CAAA,GAAA;EAAA,QAAA,CAAA,EAlCQ,OAAA,CAAM,SAkCd;SAzBoC,CAAA,EAAA,OAAA;WAAA,CAAA,EAAA,MAAA;;;;;;AAAA,cAA3B,2BAA2B,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EA2B5B,QAAA,CAAA,EApCA,OAAA,CAAM,SAoCN;EAA8B,OAAA,CAAA,EAAA,OAAA;WACpB,CAAA,EAAA,MAAA;yBAAf,eAAA,CAAA,CAAA;AADsC,KAAjC,8BAAA,GAAiC,IAAA,CAC5C,OAAA,CAAM,cADsC,CACvB,cADuB,CAAA,EAAA,UAAA,CAAA,GAAA;UAIjC,CAAA,EAAA,OAAA,CAAM,SAAA;EAAS,OAAA,CAAA,EAAA,OAAA;EASd,SAAA,CAAA,EAAA,MAAA;CAyBT;;;;;cAzBS,2BAAyB,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aAT1B,OAAA,CAAM;SASoB,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA"}
1
+ {"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAOA;AACsB,KARV,+BAAA,GAQU;EAArB,SAAM,EAAA,MAAA;EADiC,SAAA,CAAA,EAAA,OAAA;EAKpC,OAAM,CAAA,EAAA,OAAA;EACG,OAAA,EAAA,OAAA;CAAoC;AAGxC,KATG,yBAAA,GAA4B,IAS/B,CARR,OAAA,CAAM,cAQE,CARa,cAQb,CAAA,EAAA,UAAA,CAAA,GAAA;EAAgB,QAAA,CAAA,EAJrB,OAAA,CAAM,SAIe,GAAA,CAAA,CAAA,KAAA,EAHZ,+BAGY,EAAA,GAHwB,OAAA,CAAM,SAG9B,CAAA;EA6BZ,OAAA,CAAA,EAAA,OAAA;EAAoB,SAAA,CAAA,EAAA,MAAA;EAAA,KAAA,CAAA,EA7BxB,YA6BwB,EAAA;EAAA,SAAA,CAAA,EAAA,OAAA;EAjC7B,OAAM,CAAA,EAAA,OAAA;EACG,UAAA,CAAA,EAAA,OAAA;EAAoC,WAAM,CAAA,EAAA,GAAA,GAAA,IAAA;EAG9C,aAAA,CAAA,EAAA,GAAA,GAAA,IAAA;;;;;AA+LT;AACsB,cAnKT,oBAmKS,EAnKW,OAAA,CAAA,yBAmKX,CAnKW,IAmKX,CAnKW,OAAA,CAAA,cAmKX,CAnKW,cAmKX,CAAA,EAAA,UAAA,CAAA,GAAA;EAArB,QAAM,CAAA,EApMH,OAAA,CAAM,SAoMH,GAAA,CAAA,CAAA,KAAA,EAnMM,+BAmMN,EAAA,GAnM0C,OAAA,CAAM,SAmMhD,CAAA;EAD0C,OAAA,CAAA,EAAA,OAAA;EAIrC,SAAM,CAAA,EAAA,MAAA;EAAS,KAAA,CAAA,EAnMlB,YAmMkB,EAAA;EASd,SAAA,CAAA,EAAA,OAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAAA,UAAA,CAAA,EAAA,OAAA;EAAA,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAT9B,aAAM,CAAA,EAAA,GAAA,GAAA,IAAA;;KAJN,kCAAA,GAAqC,KAChD,OAAA,CAAM,eAAe;EAYoB,QAAA,CAAA,EAT9B,OAAA,CAAM,SASwB;EAAA,OAAA,CAAA,EAAA,OAAA;EAyB9B,SAAA,CAAA,EAAA,MAAA;CACU;;;;;AAYT,cAtCA,6BA+DT,EA/DsC,OAAA,CAAA,yBA+DtC,CA/DsC,IA+DtC,CA/DsC,OAAA,CAAA,cA+DtC,CA/DsC,cA+DtC,CAAA,EAAA,UAAA,CAAA,GAAA;EAzBoC,QAAA,CAAA,EA/C5B,OAAA,CAAM,SA+CsB;EAAA,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;CAT5B,wBAAM,eAAA,CAAA,CAAA;KAJN,gCAAA,GAAmC,KAC9C,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EASsB,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;AA2BxC,CAAA;;;;;AAI2B,cA/Bd,2BA+Bc,EA/Ba,OAAA,CAAA,yBA+Bb,CA/Ba,IA+Bb,CA/Ba,OAAA,CAAA,cA+Bb,CA/Ba,cA+Bb,CAAA,EAAA,UAAA,CAAA,GAAA;EASd,QAAA,CAAA,EAjDD,OAAA,CAAM,SAiDL;EAAyB,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;CAAA,wBAAA,eAAA,CAAA,CAAA;AAT1B,KAJA,8BAAA,GAAiC,IAI3B,CAHjB,OAAA,CAAM,cAGW,CAHI,cAGJ,CAAA,EAAA,UAAA,CAAA,GAAA;aAAN,OAAA,CAAM;;EASoB,SAAA,CAAA,EAAA,MAAA;CAAA;;;;;cAAzB,2BAAyB,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aAT1B,OAAA,CAAM"}
@@ -2,6 +2,14 @@ import { useRenderElement } from "../utils/use-render-element.js";
2
2
  import * as React$1 from "react";
3
3
 
4
4
  //#region src/primitives/conversation-timeline.tsx
5
+ const BOTTOM_THRESHOLD_PX = 12;
6
+ const TOP_THRESHOLD_PX = 2;
7
+ function getLastItemKey(items) {
8
+ if (items.length === 0) return null;
9
+ const lastItem = items.at(-1);
10
+ if (lastItem?.id) return lastItem.id;
11
+ return lastItem?.createdAt ?? null;
12
+ }
5
13
  /**
6
14
  * Scrollable conversation timeline that wires auto-scroll behaviour, live-region semantics and
7
15
  * pagination callbacks for displaying timeline items (messages, events, etc.).
@@ -16,6 +24,9 @@ const ConversationTimeline = (() => {
16
24
  }, [ref]);
17
25
  const isInitialRender = React$1.useRef(true);
18
26
  const previousItemCount = React$1.useRef(items.length);
27
+ const previousLastItemKey = React$1.useRef(getLastItemKey(items));
28
+ const isPinnedToBottom = React$1.useRef(true);
29
+ const isAtTop = React$1.useRef(true);
19
30
  const renderProps = {
20
31
  itemCount: items.length,
21
32
  isLoading,
@@ -23,18 +34,59 @@ const ConversationTimeline = (() => {
23
34
  isEmpty: items.length === 0
24
35
  };
25
36
  const content = typeof children === "function" ? children(renderProps) : children;
37
+ const lastItemKey = getLastItemKey(items);
26
38
  React$1.useEffect(() => {
27
- if (autoScroll && internalRef.current) {
28
- if (items.length > previousItemCount.current || isInitialRender.current) internalRef.current.scrollTop = internalRef.current.scrollHeight;
39
+ const element = internalRef.current;
40
+ if (!(element && autoScroll)) {
29
41
  previousItemCount.current = items.length;
42
+ previousLastItemKey.current = lastItemKey;
30
43
  isInitialRender.current = false;
44
+ return;
31
45
  }
32
- }, [items.length, autoScroll]);
46
+ const hasNewItems = items.length > previousItemCount.current;
47
+ const itemsRemoved = items.length < previousItemCount.current;
48
+ const appendedNewItem = hasNewItems && lastItemKey !== null && lastItemKey !== previousLastItemKey.current;
49
+ const replacedLastItem = !hasNewItems && lastItemKey !== null && lastItemKey !== previousLastItemKey.current;
50
+ if (isInitialRender.current || itemsRemoved && isPinnedToBottom.current || appendedNewItem && isPinnedToBottom.current || replacedLastItem && isPinnedToBottom.current) {
51
+ element.scrollTop = element.scrollHeight;
52
+ isPinnedToBottom.current = true;
53
+ isAtTop.current = false;
54
+ }
55
+ previousItemCount.current = items.length;
56
+ previousLastItemKey.current = lastItemKey;
57
+ isInitialRender.current = false;
58
+ }, [
59
+ autoScroll,
60
+ items.length,
61
+ lastItemKey
62
+ ]);
33
63
  const handleScroll = React$1.useCallback((e) => {
34
64
  const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
35
- if (scrollTop === 0 && onScrollStart) onScrollStart();
36
- if (scrollTop + clientHeight >= scrollHeight - 10 && onScrollEnd) onScrollEnd();
65
+ const pinnedNow = scrollHeight - scrollTop - clientHeight <= BOTTOM_THRESHOLD_PX;
66
+ if (pinnedNow && !isPinnedToBottom.current) onScrollEnd?.();
67
+ isPinnedToBottom.current = pinnedNow;
68
+ const atTop = scrollTop <= TOP_THRESHOLD_PX;
69
+ if (atTop && !isAtTop.current) onScrollStart?.();
70
+ isAtTop.current = atTop;
37
71
  }, [onScrollStart, onScrollEnd]);
72
+ const fadeStyle = React$1.useMemo(() => {
73
+ const maskHeight = "90px";
74
+ const scrollbarWidth = "8px";
75
+ const maskImage = `linear-gradient(to bottom, transparent, black ${maskHeight}, black calc(100% - ${maskHeight}), transparent), linear-gradient(black, black)`;
76
+ const maskSize = `calc(100% - ${scrollbarWidth}) 100%, ${scrollbarWidth} 100%`;
77
+ const maskPosition = "0 0, 100% 0";
78
+ const maskRepeat = "no-repeat, no-repeat";
79
+ return {
80
+ maskImage,
81
+ maskSize,
82
+ maskPosition,
83
+ maskRepeat,
84
+ WebkitMaskImage: maskImage,
85
+ WebkitMaskSize: maskSize,
86
+ WebkitMaskPosition: maskPosition,
87
+ WebkitMaskRepeat: maskRepeat
88
+ };
89
+ }, []);
38
90
  return useRenderElement("div", {
39
91
  className,
40
92
  asChild
@@ -47,6 +99,7 @@ const ConversationTimeline = (() => {
47
99
  "aria-live": "polite",
48
100
  "aria-relevant": "additions",
49
101
  onScroll: handleScroll,
102
+ style: fadeStyle,
50
103
  ...props,
51
104
  children: content
52
105
  }