@cossistant/react 0.0.26 → 0.0.29

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 (247) hide show
  1. package/README.md +1 -1
  2. package/api.d.ts +1 -1
  3. package/api.d.ts.map +1 -1
  4. package/checks.d.ts +1 -1
  5. package/checks.d.ts.map +1 -1
  6. package/coerce.d.ts +1 -1
  7. package/coerce.d.ts.map +1 -1
  8. package/conversation.d.ts +6 -3
  9. package/conversation.d.ts.map +1 -1
  10. package/core.d.ts +1 -1
  11. package/core.d.ts.map +1 -1
  12. package/errors.d.ts +12 -3
  13. package/errors.d.ts.map +1 -1
  14. package/errors2.d.ts +1 -1
  15. package/errors2.d.ts.map +1 -1
  16. package/hooks/index.d.ts +3 -2
  17. package/hooks/index.js +6 -5
  18. package/hooks/private/store/use-website-store.js +2 -1
  19. package/hooks/private/store/use-website-store.js.map +1 -1
  20. package/hooks/private/use-client-query.d.ts +6 -0
  21. package/hooks/private/use-client-query.d.ts.map +1 -1
  22. package/hooks/private/use-client-query.js +26 -3
  23. package/hooks/private/use-client-query.js.map +1 -1
  24. package/hooks/private/use-grouped-messages.d.ts +8 -5
  25. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  26. package/hooks/private/use-grouped-messages.js +44 -11
  27. package/hooks/private/use-grouped-messages.js.map +1 -1
  28. package/hooks/private/use-multimodal-input.d.ts.map +1 -1
  29. package/hooks/private/use-multimodal-input.js +7 -5
  30. package/hooks/private/use-multimodal-input.js.map +1 -1
  31. package/hooks/private/use-visitor-typing-reporter.d.ts +18 -1
  32. package/hooks/private/use-visitor-typing-reporter.d.ts.map +1 -1
  33. package/hooks/private/use-visitor-typing-reporter.js +34 -4
  34. package/hooks/private/use-visitor-typing-reporter.js.map +1 -1
  35. package/hooks/use-conversation-page.d.ts +1 -0
  36. package/hooks/use-conversation-page.d.ts.map +1 -1
  37. package/hooks/use-conversation-page.js +6 -1
  38. package/hooks/use-conversation-page.js.map +1 -1
  39. package/hooks/use-conversation-preview.d.ts +2 -1
  40. package/hooks/use-conversation-preview.d.ts.map +1 -1
  41. package/hooks/use-conversation-preview.js +1 -1
  42. package/hooks/use-conversation-preview.js.map +1 -1
  43. package/hooks/use-conversation-seen.js +1 -1
  44. package/hooks/use-conversation-seen.js.map +1 -1
  45. package/hooks/use-conversation-timeline-items.js +2 -1
  46. package/hooks/use-conversation-timeline-items.js.map +1 -1
  47. package/hooks/use-conversation-timeline.d.ts.map +1 -1
  48. package/hooks/use-conversation-timeline.js +1 -3
  49. package/hooks/use-conversation-timeline.js.map +1 -1
  50. package/hooks/use-conversation.js +2 -1
  51. package/hooks/use-conversation.js.map +1 -1
  52. package/hooks/use-conversations.js +1 -0
  53. package/hooks/use-conversations.js.map +1 -1
  54. package/hooks/use-create-conversation.d.ts.map +1 -1
  55. package/hooks/use-file-upload.d.ts +55 -0
  56. package/hooks/use-file-upload.d.ts.map +1 -0
  57. package/hooks/use-file-upload.js +100 -0
  58. package/hooks/use-file-upload.js.map +1 -0
  59. package/hooks/use-message-composer.d.ts +11 -0
  60. package/hooks/use-message-composer.d.ts.map +1 -1
  61. package/hooks/use-message-composer.js +7 -3
  62. package/hooks/use-message-composer.js.map +1 -1
  63. package/hooks/use-send-message.d.ts +1 -0
  64. package/hooks/use-send-message.d.ts.map +1 -1
  65. package/hooks/use-send-message.js +63 -11
  66. package/hooks/use-send-message.js.map +1 -1
  67. package/index.d.ts +7 -4
  68. package/index.js +13 -10
  69. package/json-schema.d.ts +70 -0
  70. package/json-schema.d.ts.map +1 -0
  71. package/package.json +4 -3
  72. package/parse.d.ts +1 -1
  73. package/parse.d.ts.map +1 -1
  74. package/primitives/avatar/fallback.d.ts.map +1 -1
  75. package/primitives/avatar/fallback.js +1 -1
  76. package/primitives/avatar/fallback.js.map +1 -1
  77. package/primitives/conversation-timeline.d.ts.map +1 -1
  78. package/primitives/conversation-timeline.js +10 -5
  79. package/primitives/conversation-timeline.js.map +1 -1
  80. package/primitives/day-separator.d.ts +76 -0
  81. package/primitives/day-separator.d.ts.map +1 -0
  82. package/primitives/day-separator.js +111 -0
  83. package/primitives/day-separator.js.map +1 -0
  84. package/primitives/index.d.ts +5 -3
  85. package/primitives/index.js +17 -5
  86. package/primitives/index.parts.d.ts +4 -2
  87. package/primitives/index.parts.js +5 -3
  88. package/primitives/timeline-item-attachments.d.ts +100 -0
  89. package/primitives/timeline-item-attachments.d.ts.map +1 -0
  90. package/primitives/timeline-item-attachments.js +151 -0
  91. package/primitives/timeline-item-attachments.js.map +1 -0
  92. package/primitives/timeline-item-group.d.ts.map +1 -1
  93. package/primitives/timeline-item-group.js +1 -1
  94. package/primitives/timeline-item-group.js.map +1 -1
  95. package/primitives/timeline-item.js +1 -1
  96. package/primitives/timeline-item.js.map +1 -1
  97. package/primitives/trigger.d.ts +91 -0
  98. package/primitives/trigger.d.ts.map +1 -0
  99. package/primitives/trigger.js +74 -0
  100. package/primitives/trigger.js.map +1 -0
  101. package/primitives/window.d.ts +22 -1
  102. package/primitives/window.d.ts.map +1 -1
  103. package/primitives/window.js +91 -5
  104. package/primitives/window.js.map +1 -1
  105. package/provider.d.ts.map +1 -1
  106. package/provider.js +8 -3
  107. package/provider.js.map +1 -1
  108. package/realtime/index.js +1 -1
  109. package/realtime/provider.js +1 -1
  110. package/realtime/support-provider.js +5 -1
  111. package/realtime/support-provider.js.map +1 -1
  112. package/realtime-events.d.ts +165 -2
  113. package/realtime-events.d.ts.map +1 -1
  114. package/registries.d.ts +1 -1
  115. package/registries.d.ts.map +1 -1
  116. package/schemas.d.ts +305 -7
  117. package/schemas.d.ts.map +1 -1
  118. package/schemas2.d.ts +29 -4
  119. package/schemas2.d.ts.map +1 -1
  120. package/schemas3.d.ts +2 -1
  121. package/schemas3.d.ts.map +1 -1
  122. package/standard-schema.d.ts +83 -21
  123. package/standard-schema.d.ts.map +1 -1
  124. package/support/components/button.d.ts +1 -1
  125. package/support/components/content.d.ts +30 -0
  126. package/support/components/content.d.ts.map +1 -0
  127. package/support/components/content.js +282 -0
  128. package/support/components/content.js.map +1 -0
  129. package/support/components/conversation-button-link.js +1 -1
  130. package/support/components/conversation-timeline.d.ts +5 -0
  131. package/support/components/conversation-timeline.d.ts.map +1 -1
  132. package/support/components/conversation-timeline.js +25 -5
  133. package/support/components/conversation-timeline.js.map +1 -1
  134. package/support/components/header.js +1 -1
  135. package/support/components/image-lightbox.d.ts +49 -0
  136. package/support/components/image-lightbox.d.ts.map +1 -0
  137. package/support/components/image-lightbox.js +142 -0
  138. package/support/components/image-lightbox.js.map +1 -0
  139. package/support/components/index.d.ts +5 -4
  140. package/support/components/index.js +4 -4
  141. package/support/components/multimodal-input.d.ts +4 -1
  142. package/support/components/multimodal-input.d.ts.map +1 -1
  143. package/support/components/multimodal-input.js +71 -45
  144. package/support/components/multimodal-input.js.map +1 -1
  145. package/support/components/navigation-tab.js +1 -1
  146. package/support/components/root.d.ts +23 -0
  147. package/support/components/root.d.ts.map +1 -0
  148. package/support/components/root.js +36 -0
  149. package/support/components/root.js.map +1 -0
  150. package/support/components/timeline-message-item.d.ts.map +1 -1
  151. package/support/components/timeline-message-item.js +82 -18
  152. package/support/components/timeline-message-item.js.map +1 -1
  153. package/support/components/trigger.d.ts +14 -0
  154. package/support/components/trigger.d.ts.map +1 -0
  155. package/support/components/{bubble.js → trigger.js} +16 -12
  156. package/support/components/trigger.js.map +1 -0
  157. package/support/components/typing-indicator.d.ts.map +1 -1
  158. package/support/components/typing-indicator.js +1 -0
  159. package/support/components/typing-indicator.js.map +1 -1
  160. package/support/context/controlled-state.d.ts +46 -0
  161. package/support/context/controlled-state.d.ts.map +1 -0
  162. package/support/context/controlled-state.js +34 -0
  163. package/support/context/controlled-state.js.map +1 -0
  164. package/support/context/events.d.ts +103 -0
  165. package/support/context/events.d.ts.map +1 -0
  166. package/support/context/events.js +139 -0
  167. package/support/context/events.js.map +1 -0
  168. package/support/context/handle.d.ts +90 -0
  169. package/support/context/handle.d.ts.map +1 -0
  170. package/support/context/handle.js +79 -0
  171. package/support/context/handle.js.map +1 -0
  172. package/support/context/positioning.d.ts +17 -0
  173. package/support/context/positioning.d.ts.map +1 -0
  174. package/support/context/positioning.js +26 -0
  175. package/support/context/positioning.js.map +1 -0
  176. package/support/context/slots.d.ts +85 -0
  177. package/support/context/slots.d.ts.map +1 -0
  178. package/support/context/slots.js +115 -0
  179. package/support/context/slots.js.map +1 -0
  180. package/support/context/websocket.d.ts +8 -1
  181. package/support/context/websocket.d.ts.map +1 -1
  182. package/support/context/websocket.js +8 -1
  183. package/support/context/websocket.js.map +1 -1
  184. package/support/index.d.ts +239 -54
  185. package/support/index.d.ts.map +1 -1
  186. package/support/index.js +254 -33
  187. package/support/index.js.map +1 -1
  188. package/support/pages/articles.d.ts.map +1 -1
  189. package/support/pages/articles.js +3 -4
  190. package/support/pages/articles.js.map +1 -1
  191. package/support/pages/conversation-history.js +2 -2
  192. package/support/pages/conversation.js +6 -5
  193. package/support/pages/conversation.js.map +1 -1
  194. package/support/pages/home.js +2 -2
  195. package/support/router.d.ts +52 -12
  196. package/support/router.d.ts.map +1 -1
  197. package/support/router.js +78 -30
  198. package/support/router.js.map +1 -1
  199. package/support/store/index.d.ts +2 -2
  200. package/support/store/support-store.d.ts +26 -20
  201. package/support/store/support-store.d.ts.map +1 -1
  202. package/support/store/support-store.js +47 -6
  203. package/support/store/support-store.js.map +1 -1
  204. package/support/{support-D2EgfIts.css → support-C7Xaw-N6.css} +1 -2
  205. package/support/support-C7Xaw-N6.css.map +1 -0
  206. package/support/text/index.d.ts +1 -1
  207. package/support/text/index.d.ts.map +1 -1
  208. package/support/text/index.js.map +1 -1
  209. package/support/types.d.ts +75 -12
  210. package/support/types.d.ts.map +1 -1
  211. package/support.css +2 -2
  212. package/tailwind.css +0 -1
  213. package/timeline-item.d.ts +68 -2
  214. package/timeline-item.d.ts.map +1 -1
  215. package/to-json-schema.d.ts +96 -0
  216. package/to-json-schema.d.ts.map +1 -0
  217. package/util.d.ts +6 -2
  218. package/util.d.ts.map +1 -1
  219. package/utils/index.d.ts +2 -1
  220. package/utils/index.js +2 -1
  221. package/utils/merge-refs.d.ts +30 -0
  222. package/utils/merge-refs.d.ts.map +1 -0
  223. package/utils/merge-refs.js +46 -0
  224. package/utils/merge-refs.js.map +1 -0
  225. package/utils/use-render-element.d.ts.map +1 -1
  226. package/utils/use-render-element.js +36 -8
  227. package/utils/use-render-element.js.map +1 -1
  228. package/versions.d.ts +2 -2
  229. package/versions.d.ts.map +1 -1
  230. package/zod-extensions.d.ts +1 -1
  231. package/zod-extensions.d.ts.map +1 -1
  232. package/primitives/bubble.d.ts +0 -38
  233. package/primitives/bubble.d.ts.map +0 -1
  234. package/primitives/bubble.js +0 -57
  235. package/primitives/bubble.js.map +0 -1
  236. package/support/components/bubble.d.ts +0 -10
  237. package/support/components/bubble.d.ts.map +0 -1
  238. package/support/components/bubble.js.map +0 -1
  239. package/support/components/container.d.ts +0 -13
  240. package/support/components/container.d.ts.map +0 -1
  241. package/support/components/container.js +0 -109
  242. package/support/components/container.js.map +0 -1
  243. package/support/components/support-content.d.ts +0 -22
  244. package/support/components/support-content.d.ts.map +0 -1
  245. package/support/components/support-content.js +0 -48
  246. package/support/components/support-content.js.map +0 -1
  247. package/support/support-D2EgfIts.css.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.js","names":["WebSocketBridge: React.FC<WebSocketBridgeProps>","intervalId: number | null","WebSocketProvider: React.FC<WebSocketProviderProps>"],"sources":["../../../src/support/context/websocket.tsx"],"sourcesContent":["\"use client\";\n\nimport { PRESENCE_PING_INTERVAL_MS } from \"@cossistant/types\";\nimport type React from \"react\";\nimport { createContext, useContext, useEffect, useMemo } from \"react\";\nimport {\n\ttype RealtimeAuthConfig,\n\ttype RealtimeContextValue,\n\tRealtimeProvider,\n\tuseRealtimeConnection,\n} from \"../../realtime\";\n\ntype WebSocketContextValue = RealtimeContextValue;\n\ntype WebSocketProviderProps = {\n\tchildren: React.ReactNode;\n\tpublicKey?: string;\n\twebsiteId?: string;\n\tvisitorId?: string;\n\twsUrl?: string;\n\tautoConnect?: boolean;\n\tonConnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketContext = createContext<WebSocketContextValue | null>(null);\n\nfunction createVisitorAuthConfig({\n\tvisitorId,\n\twebsiteId,\n\tpublicKey,\n}: Pick<\n\tWebSocketProviderProps,\n\t\"visitorId\" | \"websiteId\" | \"publicKey\"\n>): RealtimeAuthConfig | null {\n\tconst normalizedVisitorId = visitorId?.trim();\n\tif (!normalizedVisitorId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: \"visitor\",\n\t\tvisitorId: normalizedVisitorId,\n\t\twebsiteId: websiteId?.trim() || null,\n\t\tpublicKey: publicKey?.trim() || null,\n\t} satisfies RealtimeAuthConfig;\n}\n\ntype WebSocketBridgeProps = {\n\tchildren: React.ReactNode;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketBridge: React.FC<WebSocketBridgeProps> = ({\n\tchildren,\n\tonError,\n}) => {\n\tconst connection = useRealtimeConnection();\n\tconst { visitorId, sendRaw, isConnected } = connection;\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!(visitorId && sendRaw)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst pingMessage = \"presence:ping\";\n\n\t\tconst sendPresencePing = () => {\n\t\t\tif (!isConnected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsendRaw(pingMessage);\n\t\t\t} catch (error) {\n\t\t\t\tif (!onError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst normalizedError =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new Error(\n\t\t\t\t\t\t\t\ttypeof error === \"string\"\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: \"Unknown presence ping error\"\n\t\t\t\t\t\t\t);\n\n\t\t\t\tif (!normalizedError.message.includes(\"Failed to send presence ping\")) {\n\t\t\t\t\tnormalizedError.message = `Failed to send presence ping: ${normalizedError.message}`;\n\t\t\t\t}\n\n\t\t\t\tonError(normalizedError);\n\t\t\t}\n\t\t};\n\n\t\tlet intervalId: number | null = null;\n\n\t\tconst clearPresenceInterval = () => {\n\t\t\tif (intervalId !== null) {\n\t\t\t\twindow.clearInterval(intervalId);\n\t\t\t\tintervalId = null;\n\t\t\t}\n\t\t};\n\n\t\tconst startPresenceInterval = () => {\n\t\t\tclearPresenceInterval();\n\n\t\t\tif (!isConnected || document.visibilityState === \"hidden\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tintervalId = window.setInterval(\n\t\t\t\tsendPresencePing,\n\t\t\t\tPRESENCE_PING_INTERVAL_MS\n\t\t\t);\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\tclearPresenceInterval();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\tif (isConnected && document.visibilityState !== \"hidden\") {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t\tclearPresenceInterval();\n\t\t};\n\t}, [isConnected, onError, sendRaw, visitorId]);\n\tconst value = useMemo(() => connection, [connection]);\n\treturn (\n\t\t<WebSocketContext.Provider value={value}>\n\t\t\t{children}\n\t\t</WebSocketContext.Provider>\n\t);\n};\n\n/**\n * Support-specific realtime provider that authenticates visitors and keeps the\n * connection alive with presence pings.\n */\nexport const WebSocketProvider: React.FC<WebSocketProviderProps> = ({\n\tchildren,\n\tpublicKey,\n\twebsiteId,\n\tvisitorId,\n\twsUrl,\n\tautoConnect = true,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst auth = createVisitorAuthConfig({ publicKey, websiteId, visitorId });\n\n\treturn (\n\t\t<RealtimeProvider\n\t\t\tauth={auth}\n\t\t\tautoConnect={autoConnect}\n\t\t\tonConnect={onConnect}\n\t\t\tonDisconnect={onDisconnect}\n\t\t\tonError={onError}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t<WebSocketBridge onError={onError}>{children}</WebSocketBridge>\n\t\t</RealtimeProvider>\n\t);\n};\n\n/**\n * Accessor for the support websocket context.\n */\nexport const useWebSocket = (): WebSocketContextValue => {\n\tconst context = useContext(WebSocketContext);\n\tif (!context) {\n\t\tthrow new Error(\"useWebSocket must be used within WebSocketProvider\");\n\t}\n\treturn context;\n};\n\nexport type { WebSocketContextValue, WebSocketProviderProps };\nexport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\n"],"mappings":";;;;;;;;;AA0BA,MAAM,mBAAmB,cAA4C,KAAK;AAE1E,SAAS,wBAAwB,EAChC,WACA,WACA,aAI6B;CAC7B,MAAM,sBAAsB,WAAW,MAAM;AAC7C,KAAI,CAAC,oBACJ,QAAO;AAGR,QAAO;EACN,MAAM;EACN,WAAW;EACX,WAAW,WAAW,MAAM,IAAI;EAChC,WAAW,WAAW,MAAM,IAAI;EAChC;;AAQF,MAAMA,mBAAmD,EACxD,UACA,cACK;CACL,MAAM,aAAa,uBAAuB;CAC1C,MAAM,EAAE,WAAW,SAAS,gBAAgB;AAE5C,iBAAgB;AACf,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,YACxD;AAGD,MAAI,EAAE,aAAa,SAClB;EAGD,MAAM,cAAc;EAEpB,MAAM,yBAAyB;AAC9B,OAAI,CAAC,YACJ;AAGD,OAAI;AACH,YAAQ,YAAY;YACZ,OAAO;AACf,QAAI,CAAC,QACJ;IAGD,MAAM,kBACL,iBAAiB,QACd,QACA,IAAI,MACJ,OAAO,UAAU,WACd,QACA,8BACH;AAEJ,QAAI,CAAC,gBAAgB,QAAQ,SAAS,+BAA+B,CACpE,iBAAgB,UAAU,iCAAiC,gBAAgB;AAG5E,YAAQ,gBAAgB;;;EAI1B,IAAIC,aAA4B;EAEhC,MAAM,8BAA8B;AACnC,OAAI,eAAe,MAAM;AACxB,WAAO,cAAc,WAAW;AAChC,iBAAa;;;EAIf,MAAM,8BAA8B;AACnC,0BAAuB;AAEvB,OAAI,CAAC,eAAe,SAAS,oBAAoB,SAChD;AAGD,gBAAa,OAAO,YACnB,kBACA,0BACA;;EAGF,MAAM,oBAAoB;AACzB,qBAAkB;AAClB,0BAAuB;;EAGxB,MAAM,+BAA+B;AACpC,OAAI,SAAS,oBAAoB,UAAU;AAC1C,2BAAuB;AACvB;;AAGD,qBAAkB;AAClB,0BAAuB;;AAGxB,SAAO,iBAAiB,SAAS,YAAY;AAC7C,WAAS,iBAAiB,oBAAoB,uBAAuB;AAErE,MAAI,eAAe,SAAS,oBAAoB,UAAU;AACzD,qBAAkB;AAClB,0BAAuB;;AAGxB,eAAa;AACZ,UAAO,oBAAoB,SAAS,YAAY;AAChD,YAAS,oBAAoB,oBAAoB,uBAAuB;AACxE,0BAAuB;;IAEtB;EAAC;EAAa;EAAS;EAAS;EAAU,CAAC;CAC9C,MAAM,QAAQ,cAAc,YAAY,CAAC,WAAW,CAAC;AACrD,QACC,oBAAC,iBAAiB;EAAgB;EAChC;GAC0B;;;;;;AAQ9B,MAAaC,qBAAuD,EACnE,UACA,WACA,WACA,WACA,OACA,cAAc,MACd,WACA,cACA,cACK;AAGL,QACC,oBAAC;EACA,MAJW,wBAAwB;GAAE;GAAW;GAAW;GAAW,CAAC;EAK1D;EACF;EACG;EACL;EACF;YAEP,oBAAC;GAAyB;GAAU;IAA2B;GAC7C;;;;;AAOrB,MAAa,qBAA4C;CACxD,MAAM,UAAU,WAAW,iBAAiB;AAC5C,KAAI,CAAC,QACJ,OAAM,IAAI,MAAM,qDAAqD;AAEtE,QAAO"}
1
+ {"version":3,"file":"websocket.js","names":["WebSocketBridge: React.FC<WebSocketBridgeProps>","intervalId: number | null","WebSocketProvider: React.FC<WebSocketProviderProps>"],"sources":["../../../src/support/context/websocket.tsx"],"sourcesContent":["\"use client\";\n\nimport { PRESENCE_PING_INTERVAL_MS } from \"@cossistant/types\";\nimport type React from \"react\";\nimport { createContext, useContext, useEffect, useMemo } from \"react\";\nimport {\n\ttype RealtimeAuthConfig,\n\ttype RealtimeContextValue,\n\tRealtimeProvider,\n\tuseRealtimeConnection,\n} from \"../../realtime\";\n\ntype WebSocketContextValue = RealtimeContextValue;\n\ntype WebSocketProviderProps = {\n\tchildren: React.ReactNode;\n\tpublicKey?: string;\n\twebsiteId?: string;\n\tvisitorId?: string;\n\twsUrl?: string;\n\tautoConnect?: boolean;\n\tonConnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketContext = createContext<WebSocketContextValue | null>(null);\n\nfunction createVisitorAuthConfig({\n\tvisitorId,\n\twebsiteId,\n\tpublicKey,\n}: Pick<\n\tWebSocketProviderProps,\n\t\"visitorId\" | \"websiteId\" | \"publicKey\"\n>): RealtimeAuthConfig | null {\n\tconst normalizedVisitorId = visitorId?.trim();\n\tif (!normalizedVisitorId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: \"visitor\",\n\t\tvisitorId: normalizedVisitorId,\n\t\twebsiteId: websiteId?.trim() || null,\n\t\tpublicKey: publicKey?.trim() || null,\n\t} satisfies RealtimeAuthConfig;\n}\n\ntype WebSocketBridgeProps = {\n\tchildren: React.ReactNode;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketBridge: React.FC<WebSocketBridgeProps> = ({\n\tchildren,\n\tonError,\n}) => {\n\tconst connection = useRealtimeConnection();\n\tconst { visitorId, sendRaw, isConnected } = connection;\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!(visitorId && sendRaw)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst pingMessage = \"presence:ping\";\n\n\t\tconst sendPresencePing = () => {\n\t\t\tif (!isConnected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsendRaw(pingMessage);\n\t\t\t} catch (error) {\n\t\t\t\tif (!onError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst normalizedError =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new Error(\n\t\t\t\t\t\t\t\ttypeof error === \"string\"\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: \"Unknown presence ping error\"\n\t\t\t\t\t\t\t);\n\n\t\t\t\tif (!normalizedError.message.includes(\"Failed to send presence ping\")) {\n\t\t\t\t\tnormalizedError.message = `Failed to send presence ping: ${normalizedError.message}`;\n\t\t\t\t}\n\n\t\t\t\tonError(normalizedError);\n\t\t\t}\n\t\t};\n\n\t\tlet intervalId: number | null = null;\n\n\t\tconst clearPresenceInterval = () => {\n\t\t\tif (intervalId !== null) {\n\t\t\t\twindow.clearInterval(intervalId);\n\t\t\t\tintervalId = null;\n\t\t\t}\n\t\t};\n\n\t\tconst startPresenceInterval = () => {\n\t\t\tclearPresenceInterval();\n\n\t\t\tif (!isConnected || document.visibilityState === \"hidden\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tintervalId = window.setInterval(\n\t\t\t\tsendPresencePing,\n\t\t\t\tPRESENCE_PING_INTERVAL_MS\n\t\t\t);\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\tclearPresenceInterval();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\tif (isConnected && document.visibilityState !== \"hidden\") {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t\tclearPresenceInterval();\n\t\t};\n\t}, [isConnected, onError, sendRaw, visitorId]);\n\tconst value = useMemo(() => connection, [connection]);\n\treturn (\n\t\t<WebSocketContext.Provider value={value}>\n\t\t\t{children}\n\t\t</WebSocketContext.Provider>\n\t);\n};\n\n/**\n * Support-specific realtime provider that authenticates visitors and keeps the\n * connection alive with presence pings.\n */\nexport const WebSocketProvider: React.FC<WebSocketProviderProps> = ({\n\tchildren,\n\tpublicKey,\n\twebsiteId,\n\tvisitorId,\n\twsUrl,\n\tautoConnect = true,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst auth = createVisitorAuthConfig({ publicKey, websiteId, visitorId });\n\n\treturn (\n\t\t<RealtimeProvider\n\t\t\tauth={auth}\n\t\t\tautoConnect={autoConnect}\n\t\t\tonConnect={onConnect}\n\t\t\tonDisconnect={onDisconnect}\n\t\t\tonError={onError}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t<WebSocketBridge onError={onError}>{children}</WebSocketBridge>\n\t\t</RealtimeProvider>\n\t);\n};\n\n/**\n * Accessor for the support websocket context.\n * Throws if used outside WebSocketProvider.\n */\nexport const useWebSocket = (): WebSocketContextValue => {\n\tconst context = useContext(WebSocketContext);\n\tif (!context) {\n\t\tthrow new Error(\"useWebSocket must be used within WebSocketProvider\");\n\t}\n\treturn context;\n};\n\n/**\n * Safe accessor for the support websocket context.\n * Returns null if used outside WebSocketProvider instead of throwing.\n * Useful for optional WebSocket usage in hooks that may or may not have the provider.\n */\nexport const useWebSocketSafe = (): WebSocketContextValue | null =>\n\tuseContext(WebSocketContext);\n\nexport type { WebSocketContextValue, WebSocketProviderProps };\nexport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\n"],"mappings":";;;;;;;;;AA0BA,MAAM,mBAAmB,cAA4C,KAAK;AAE1E,SAAS,wBAAwB,EAChC,WACA,WACA,aAI6B;CAC7B,MAAM,sBAAsB,WAAW,MAAM;AAC7C,KAAI,CAAC,oBACJ,QAAO;AAGR,QAAO;EACN,MAAM;EACN,WAAW;EACX,WAAW,WAAW,MAAM,IAAI;EAChC,WAAW,WAAW,MAAM,IAAI;EAChC;;AAQF,MAAMA,mBAAmD,EACxD,UACA,cACK;CACL,MAAM,aAAa,uBAAuB;CAC1C,MAAM,EAAE,WAAW,SAAS,gBAAgB;AAE5C,iBAAgB;AACf,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,YACxD;AAGD,MAAI,EAAE,aAAa,SAClB;EAGD,MAAM,cAAc;EAEpB,MAAM,yBAAyB;AAC9B,OAAI,CAAC,YACJ;AAGD,OAAI;AACH,YAAQ,YAAY;YACZ,OAAO;AACf,QAAI,CAAC,QACJ;IAGD,MAAM,kBACL,iBAAiB,QACd,QACA,IAAI,MACJ,OAAO,UAAU,WACd,QACA,8BACH;AAEJ,QAAI,CAAC,gBAAgB,QAAQ,SAAS,+BAA+B,CACpE,iBAAgB,UAAU,iCAAiC,gBAAgB;AAG5E,YAAQ,gBAAgB;;;EAI1B,IAAIC,aAA4B;EAEhC,MAAM,8BAA8B;AACnC,OAAI,eAAe,MAAM;AACxB,WAAO,cAAc,WAAW;AAChC,iBAAa;;;EAIf,MAAM,8BAA8B;AACnC,0BAAuB;AAEvB,OAAI,CAAC,eAAe,SAAS,oBAAoB,SAChD;AAGD,gBAAa,OAAO,YACnB,kBACA,0BACA;;EAGF,MAAM,oBAAoB;AACzB,qBAAkB;AAClB,0BAAuB;;EAGxB,MAAM,+BAA+B;AACpC,OAAI,SAAS,oBAAoB,UAAU;AAC1C,2BAAuB;AACvB;;AAGD,qBAAkB;AAClB,0BAAuB;;AAGxB,SAAO,iBAAiB,SAAS,YAAY;AAC7C,WAAS,iBAAiB,oBAAoB,uBAAuB;AAErE,MAAI,eAAe,SAAS,oBAAoB,UAAU;AACzD,qBAAkB;AAClB,0BAAuB;;AAGxB,eAAa;AACZ,UAAO,oBAAoB,SAAS,YAAY;AAChD,YAAS,oBAAoB,oBAAoB,uBAAuB;AACxE,0BAAuB;;IAEtB;EAAC;EAAa;EAAS;EAAS;EAAU,CAAC;CAC9C,MAAM,QAAQ,cAAc,YAAY,CAAC,WAAW,CAAC;AACrD,QACC,oBAAC,iBAAiB;EAAgB;EAChC;GAC0B;;;;;;AAQ9B,MAAaC,qBAAuD,EACnE,UACA,WACA,WACA,WACA,OACA,cAAc,MACd,WACA,cACA,cACK;AAGL,QACC,oBAAC;EACA,MAJW,wBAAwB;GAAE;GAAW;GAAW;GAAW,CAAC;EAK1D;EACF;EACG;EACL;EACF;YAEP,oBAAC;GAAyB;GAAU;IAA2B;GAC7C;;;;;;AAQrB,MAAa,qBAA4C;CACxD,MAAM,UAAU,WAAW,iBAAiB;AAC5C,KAAI,CAAC,QACJ,OAAM,IAAI,MAAM,qDAAqD;AAEtE,QAAO;;;;;;;AAQR,MAAa,yBACZ,WAAW,iBAAiB"}
@@ -1,74 +1,259 @@
1
1
  import { SupportLocale, SupportTextContentOverrides } from "./text/locales/keys.js";
2
- import { CustomPage } from "./router.js";
2
+ import { CustomPage, PageProps } from "./router.js";
3
+ import { SlotProps } from "./context/slots.js";
4
+ import { ConversationEndEvent, ConversationStartEvent, ErrorEvent, MessageReceivedEvent, MessageSentEvent, SupportEvent, SupportEventCallbacks, SupportEventType, useSupportEventEmitter, useSupportEvents } from "./context/events.js";
5
+ import { SupportHandle, useSupportHandle } from "./context/handle.js";
3
6
  import { Text, useSupportText } from "./text/index.js";
4
- import { BubbleSlotProps, ContainerSlotProps, RouterSlotProps } from "./types.js";
7
+ import { Align, CollisionPadding, ContentProps, RootProps, Side, TriggerRenderProps } from "./types.js";
5
8
  import { CoButton } from "./components/button.js";
6
9
  import { Header } from "./components/header.js";
7
10
  import { WebSocketContextValue, WebSocketProvider, useWebSocket } from "./context/websocket.js";
8
11
  import { useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
9
12
  import "./store/index.js";
10
- import React, { ReactElement } from "react";
11
- import { DefaultRoutes, NavigationState, RouteRegistry, SupportPage } from "@cossistant/core";
13
+ import * as React$1 from "react";
14
+ import * as _cossistant_core0 from "@cossistant/core";
15
+ import { DefaultRoutes, NavigationState, RouteRegistry, SupportPage as SupportPageType } from "@cossistant/core";
12
16
  import { DefaultMessage } from "@cossistant/types";
13
17
 
14
18
  //#region src/support/index.d.ts
15
19
  type SupportProps<Locale extends string = SupportLocale> = {
20
+ /**
21
+ * Additional CSS classes for the root wrapper.
22
+ */
16
23
  className?: string;
17
- position?: "top" | "bottom";
18
- align?: "right" | "left";
19
- positioning?: "fixed" | "absolute";
24
+ /**
25
+ * Which side of the trigger to place the content.
26
+ * @default "top"
27
+ */
28
+ side?: Side;
29
+ /**
30
+ * Alignment along the side axis.
31
+ * @default "end"
32
+ */
33
+ align?: Align;
34
+ /**
35
+ * Distance (in pixels) between the trigger and the content.
36
+ * @default 16
37
+ */
38
+ sideOffset?: number;
39
+ /**
40
+ * Enable automatic collision avoidance.
41
+ * When true, the content repositions to stay within the viewport.
42
+ * @default true
43
+ */
44
+ avoidCollisions?: boolean;
45
+ /**
46
+ * Padding from viewport edges when avoiding collisions.
47
+ * @default 8
48
+ */
49
+ collisionPadding?: CollisionPadding;
50
+ /**
51
+ * Granular className overrides for specific parts.
52
+ */
53
+ classNames?: {
54
+ trigger?: string;
55
+ content?: string;
56
+ };
57
+ /**
58
+ * Force a specific theme. Omit for automatic detection.
59
+ */
60
+ theme?: "light" | "dark";
61
+ /**
62
+ * Controlled open state.
63
+ * When provided, the widget operates in controlled mode.
64
+ * Use with `onOpenChange` to manage state externally.
65
+ */
66
+ open?: boolean;
67
+ /**
68
+ * Callback fired when the open state should change.
69
+ * Use with `open` prop for controlled mode.
70
+ *
71
+ * @example
72
+ * const [isOpen, setIsOpen] = useState(false);
73
+ * <Support open={isOpen} onOpenChange={setIsOpen} />
74
+ */
75
+ onOpenChange?: (open: boolean) => void;
76
+ /**
77
+ * Whether the widget should open automatically on mount (uncontrolled mode).
78
+ * Ignored when `open` prop is provided (controlled mode).
79
+ * @default false
80
+ */
81
+ defaultOpen?: boolean;
82
+ /**
83
+ * Quick reply options displayed to users.
84
+ */
20
85
  quickOptions?: string[];
86
+ /**
87
+ * Custom welcome messages shown before a conversation starts.
88
+ */
21
89
  defaultMessages?: DefaultMessage[];
22
- defaultOpen?: boolean;
90
+ /**
91
+ * Locale string for widget translations.
92
+ */
23
93
  locale?: Locale;
94
+ /**
95
+ * Custom text content overrides for internationalization.
96
+ */
24
97
  content?: SupportTextContentOverrides<Locale>;
25
- theme?: "light" | "dark";
26
- slots?: {
27
- bubble?: React.ComponentType<BubbleSlotProps>;
28
- container?: React.ComponentType<ContainerSlotProps>;
29
- router?: React.ComponentType<RouterSlotProps>;
30
- };
31
- classNames?: {
32
- root?: string;
33
- bubble?: string;
34
- container?: string;
35
- };
98
+ /**
99
+ * Custom pages to add to the router.
100
+ */
36
101
  customPages?: CustomPage[];
37
- children?: React.ReactNode;
102
+ /**
103
+ * Called when a new conversation is started.
104
+ */
105
+ onConversationStart?: (event: ConversationStartEvent) => void;
106
+ /**
107
+ * Called when a conversation ends (resolved, closed, etc.).
108
+ */
109
+ onConversationEnd?: (event: ConversationEndEvent) => void;
110
+ /**
111
+ * Called when the visitor sends a message.
112
+ */
113
+ onMessageSent?: (event: MessageSentEvent) => void;
114
+ /**
115
+ * Called when a message is received from an agent (human or AI).
116
+ */
117
+ onMessageReceived?: (event: MessageReceivedEvent) => void;
118
+ /**
119
+ * Called when an error occurs within the widget.
120
+ */
121
+ onError?: (event: ErrorEvent) => void;
122
+ /**
123
+ * Children for composition. Can include:
124
+ * - <Support.Trigger> for custom trigger
125
+ * - <Support.Content> for custom content positioning
126
+ * - <Support.Page> components for custom routes
127
+ */
128
+ children?: React$1.ReactNode;
129
+ };
130
+ type SupportTriggerProps = Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
131
+ /**
132
+ * Content to render inside the trigger.
133
+ * Can be static content or a function receiving render props.
134
+ */
135
+ children?: React$1.ReactNode | ((props: TriggerRenderProps) => React$1.ReactNode);
136
+ /**
137
+ * When true, renders children directly with all props passed through.
138
+ */
139
+ asChild?: boolean;
140
+ className?: string;
141
+ };
142
+ type SupportContentProps = {
143
+ className?: string;
144
+ /**
145
+ * Which side of the trigger to place the content.
146
+ * @default "top"
147
+ */
148
+ side?: Side;
149
+ /**
150
+ * Alignment along the side axis.
151
+ * @default "end"
152
+ */
153
+ align?: Align;
154
+ /**
155
+ * Distance (in pixels) between the trigger and the content.
156
+ * @default 16
157
+ */
158
+ sideOffset?: number;
159
+ /**
160
+ * Enable automatic collision avoidance.
161
+ * When true, the content repositions to stay within the viewport.
162
+ * @default true
163
+ */
164
+ avoidCollisions?: boolean;
165
+ /**
166
+ * Padding from viewport edges when avoiding collisions.
167
+ * @default 8
168
+ */
169
+ collisionPadding?: CollisionPadding;
170
+ children?: React$1.ReactNode;
171
+ };
172
+ type SupportRouterProps = {
173
+ /**
174
+ * Custom pages to add alongside built-in pages.
175
+ */
176
+ customPages?: CustomPage[];
177
+ /**
178
+ * Page components to register.
179
+ */
180
+ children?: React$1.ReactNode;
181
+ };
182
+ type SupportPageProps<K extends keyof _cossistant_core0.RouteRegistry = keyof _cossistant_core0.RouteRegistry> = {
183
+ name: K;
184
+ component: React$1.ComponentType<{
185
+ params?: _cossistant_core0.RouteRegistry[K];
186
+ }>;
187
+ };
188
+ type SupportRootProps = {
189
+ /**
190
+ * Controlled open state.
191
+ * When provided, the widget operates in controlled mode.
192
+ */
193
+ open?: boolean;
194
+ /**
195
+ * Callback fired when the open state should change.
196
+ * Use with `open` prop for controlled mode.
197
+ */
198
+ onOpenChange?: (open: boolean) => void;
199
+ /**
200
+ * Whether the widget should open automatically (uncontrolled mode).
201
+ * Ignored when `open` prop is provided.
202
+ * @default false
203
+ */
204
+ defaultOpen?: boolean;
205
+ /**
206
+ * Force a specific theme.
207
+ */
208
+ theme?: "light" | "dark";
209
+ /**
210
+ * Additional CSS classes.
211
+ */
212
+ className?: string;
213
+ /**
214
+ * Called when a new conversation is started.
215
+ */
216
+ onConversationStart?: (event: ConversationStartEvent) => void;
217
+ /**
218
+ * Called when a conversation ends.
219
+ */
220
+ onConversationEnd?: (event: ConversationEndEvent) => void;
221
+ /**
222
+ * Called when the visitor sends a message.
223
+ */
224
+ onMessageSent?: (event: MessageSentEvent) => void;
225
+ /**
226
+ * Called when a message is received from an agent.
227
+ */
228
+ onMessageReceived?: (event: MessageReceivedEvent) => void;
229
+ /**
230
+ * Called when an error occurs.
231
+ */
232
+ onError?: (event: ErrorEvent) => void;
233
+ children: React$1.ReactNode;
234
+ };
235
+ declare const Support: (<Locale extends string = SupportLocale>(props: SupportProps<Locale> & {
236
+ ref?: React$1.Ref<SupportHandle>;
237
+ }) => React$1.ReactElement | null) & {
238
+ Root: React$1.ForwardRefExoticComponent<SupportRootProps & React$1.RefAttributes<SupportHandle>>;
239
+ Trigger: React$1.ForwardRefExoticComponent<Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
240
+ /**
241
+ * Content to render inside the trigger.
242
+ * Can be static content or a function receiving render props.
243
+ */
244
+ children?: React$1.ReactNode | ((props: TriggerRenderProps) => React$1.ReactNode);
245
+ /**
246
+ * When true, renders children directly with all props passed through.
247
+ */
248
+ asChild?: boolean;
249
+ className?: string;
250
+ } & React$1.RefAttributes<HTMLButtonElement>>;
251
+ Content: React$1.FC<SupportContentProps>;
252
+ Router: React$1.FC<SupportRouterProps>;
253
+ Page: <K extends keyof _cossistant_core0.RouteRegistry>(_props: PageProps<K>) => null;
254
+ Header: React$1.FC<SlotProps>;
255
+ Footer: React$1.FC<SlotProps>;
38
256
  };
39
- /**
40
- * Complete support widget with chat, routing, and real-time features.
41
- *
42
- * @example
43
- * // Zero config
44
- * <Support />
45
- *
46
- * @example
47
- * // With customization and custom pages
48
- * <Support
49
- * theme="dark"
50
- * classNames={{ bubble: "bg-purple-600" }}
51
- * customPages={[
52
- * { name: "FAQ", component: FAQPage }
53
- * ]}
54
- * />
55
- */
56
- declare function Support<Locale extends string = SupportLocale>({
57
- className,
58
- position,
59
- align,
60
- positioning,
61
- quickOptions,
62
- defaultMessages,
63
- defaultOpen,
64
- locale,
65
- content,
66
- theme,
67
- slots,
68
- classNames,
69
- customPages,
70
- children
71
- }: SupportProps<Locale>): ReactElement | null;
72
257
  //#endregion
73
- export { type BubbleSlotProps, CoButton as Button, type ContainerSlotProps, type CustomPage, type DefaultRoutes, Header, type NavigationState, type RouteRegistry, type RouterSlotProps, Support, Support as default, type SupportLocale, type SupportPage, SupportProps, type SupportTextContentOverrides, Text, type WebSocketContextValue, WebSocketProvider, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
258
+ export { type Align, CoButton as Button, type CollisionPadding, type ContentProps, type ConversationEndEvent, type ConversationStartEvent, type CustomPage, type DefaultRoutes, type ErrorEvent, Header, type MessageReceivedEvent, type MessageSentEvent, type NavigationState, type RootProps, type RouteRegistry, type Side, Support, Support as default, SupportContentProps, type SupportEvent, type SupportEventCallbacks, type SupportEventType, type SupportHandle, type SupportLocale, SupportPageProps, type SupportPageType, SupportProps, SupportRootProps, SupportRouterProps, type SupportTextContentOverrides, SupportTriggerProps, Text, type TriggerRenderProps, type WebSocketContextValue, WebSocketProvider, useSupportConfig, useSupportEventEmitter, useSupportEvents, useSupportHandle, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
74
259
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;KAmBY,qCAAqC;;;;;;oBAO9B;;EAPP,MAAA,CAAA,EASF,MATc;EAAyB,OAAA,CAAA,EAUtC,2BAVsC,CAUV,MAVU,CAAA;EAO9B,KAAA,CAAA,EAAA,OAAA,GAAA,MAAA;EAET,KAAA,CAAA,EAAA;IAC6B,MAAA,CAAA,EAO5B,KAAA,CAAM,aAPsB,CAOR,eAPQ,CAAA;IAA5B,SAAA,CAAA,EAQG,KAAA,CAAM,aART,CAQuB,kBARvB,CAAA;IAOoB,MAAA,CAAA,EAEpB,KAAA,CAAM,aAFc,CAEA,eAFA,CAAA;EAApB,CAAA;EACuB,UAAA,CAAA,EAAA;IAAd,IAAA,CAAA,EAAA,MAAA;IACW,MAAA,CAAA,EAAA,MAAA;IAAd,SAAA,CAAA,EAAA,MAAA;EAWF,CAAA;EAEH,WAAM,CAAA,EAFH,UAEG,EAAA;EAAS,QAAA,CAAA,EAAf,KAAA,CAAM,SAAS;AAoB3B,CAAA;;;;;;;;;;;;;;;;;;AAe0B,iBAfV,OAeU,CAAA,eAAA,MAAA,GAfsB,aAetB,CAAA,CAAA;EAAA,SAAA;EAAA,QAAA;EAAA,KAAA;EAAA,WAAA;EAAA,YAAA;EAAA,eAAA;EAAA,WAAA;EAAA,MAAA;EAAA,OAAA;EAAA,KAAA;EAAA,KAAA;EAAA,UAAA;EAAA,WAAA;EAAA;AAAA,CAAA,EAAvB,YAAuB,CAAV,MAAU,CAAA,CAAA,EAAA,YAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;KAsCY,qCAAqC;;;;;;;;;SAUzC;EAVI;;;;EAmCQ,KAAA,CAAA,EAnBX,KAmBW;EA+CD;;;;EAeJ,UAAA,CAAA,EAAA,MAAA;EASgB;;;;;EA4BnB,eAAM,CAAA,EAAA,OAAA;EAAS;AA6M3B;;;EAAkC,gBAAA,CAAA,EAhTd,gBAgTc;EAQtB;;;EAAiE,UAAA,CAAA,EAAA;IAsCjE,OAAA,CAAA,EAAA,MAAA;IAMJ,OAAA,CAAA,EAAA,MAAA;EAKC,CAAA;EAgBW;;;EA4CR,KAAA,CAAA,EAAA,OAAA,GAAA,MAAkB;EAsClB;;;;;EAMwC,IAAA,CAAA,EAAA,OAAA;EADxC;;AAuBZ;;;;;;EA6CW,YAAM,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAS;AA2F1B;;;;EAtUiD,WAAA,CAAA,EAAA,OAAA;EAAV;;;;;;;oBA1PpB;;;;EAyQ2C,MAAM,CAAA,EApQ1D,MAoQ0D;;;;YA/PzD,4BAA4B;;;;gBAKxB;;;;gCASgB;;;;8BAKF;;;;0BAKJ;;;;8BAKI;;;;oBAKV;;;;;;;aAQP,OAAA,CAAM;;KA6MN,mBAAA,GAAsB,KACjC,OAAA,CAAM,qBAAqB;;;;;aAOhB,OAAA,CAAM,qBAAqB,uBAAuB,OAAA,CAAM;;;;;;;KAsCxD,mBAAA;;;;;;SAMJ;;;;;UAKC;;;;;;;;;;;;;;;;qBAgBW;aACR,OAAA,CAAM;;KA2CN,kBAAA;;;;gBAIG;;;;aAIH,OAAA,CAAM;;KA8BN,iCAAgB,iBAAA,CAEO,sBAAa,iBAAA,CAAoC;QAE7E;aACK,OAAA,CAAM;aADV,iBAAA,CAE8B,aAAA,CAAc;;;KAsBxC,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA4BmB;;;;8BAIF;;;;0BAIJ;;;;8BAII;;;;oBAIV;YACR,OAAA,CAAM;;cA2FJ,mCAxUS,sBAEd,aAAa;QAAkB,OAAA,CAAM,IAAI;MAC5C,OAAA,CAAM;;;;;;;eAcC,OAAA,CAAM,qBAAqB,uBAAuB,OAAA,CAAM"}
package/support/index.js CHANGED
@@ -1,65 +1,286 @@
1
1
  import "./support.js";
2
- import { SupportRealtimeProvider } from "../realtime/support-provider.js";
3
2
  import { SupportConfig } from "../support-config.js";
3
+ import { SupportTrigger as SupportTrigger$1 } from "../primitives/trigger.js";
4
+ import { ControlledStateProvider } from "./context/controlled-state.js";
4
5
  import { initializeSupportStore, useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
6
+ import { SupportRealtimeProvider } from "../realtime/support-provider.js";
7
+ import { FooterSlot, HeaderSlot } from "./context/slots.js";
8
+ import { Content } from "./components/content.js";
9
+ import { Root } from "./components/root.js";
10
+ import { ThemeWrapper } from "./components/theme-wrapper.js";
11
+ import { DefaultTrigger } from "./components/trigger.js";
12
+ import { SupportEventsProvider, useSupportEventEmitter, useSupportEvents } from "./context/events.js";
13
+ import { SupportHandleProvider, useSupportHandle } from "./context/handle.js";
5
14
  import { CoButton } from "./components/button.js";
6
15
  import { Header } from "./components/header.js";
7
16
  import { SupportTextProvider, Text, useSupportText } from "./text/index.js";
8
- import { SupportContent } from "./components/support-content.js";
9
- import { ThemeWrapper } from "./components/theme-wrapper.js";
10
17
  import { WebSocketProvider, useWebSocket } from "./context/websocket.js";
18
+ import { Page, Router } from "./router.js";
11
19
  import { useSupport } from "../provider.js";
12
- import React from "react";
20
+ import * as React$1 from "react";
13
21
  import { jsx, jsxs } from "react/jsx-runtime";
14
22
 
15
23
  //#region src/support/index.tsx
24
+ function parseChildren(children) {
25
+ const result = {
26
+ trigger: null,
27
+ content: null,
28
+ pages: [],
29
+ other: []
30
+ };
31
+ React$1.Children.forEach(children, (child) => {
32
+ if (!React$1.isValidElement(child)) {
33
+ result.other.push(child);
34
+ return;
35
+ }
36
+ const displayName = child.type?.displayName ?? "";
37
+ if (displayName === "Support.Trigger" || child.type === SupportTrigger) result.trigger = child;
38
+ else if (displayName === "Support.Content" || child.type === SupportContent) result.content = child;
39
+ else if (displayName === "Support.Page" || child.type === Page) result.pages.push(child);
40
+ else result.other.push(child);
41
+ });
42
+ return result;
43
+ }
16
44
  /**
17
45
  * Complete support widget with chat, routing, and real-time features.
18
46
  *
19
47
  * @example
20
- * // Zero config
48
+ * // Zero config - works instantly
21
49
  * <Support />
22
50
  *
23
51
  * @example
24
- * // With customization and custom pages
52
+ * // With styling
25
53
  * <Support
26
54
  * theme="dark"
27
- * classNames={{ bubble: "bg-purple-600" }}
28
- * customPages={[
29
- * { name: "FAQ", component: FAQPage }
30
- * ]}
55
+ * classNames={{
56
+ * trigger: "bg-purple-600",
57
+ * content: "border-purple-200",
58
+ * }}
31
59
  * />
60
+ *
61
+ * @example
62
+ * // With custom positioning
63
+ * <Support side="bottom" align="end" sideOffset={8} />
64
+ *
65
+ * @example
66
+ * // Controlled mode - external state management
67
+ * const [isOpen, setIsOpen] = useState(false);
68
+ * <Support open={isOpen} onOpenChange={setIsOpen} />
69
+ *
70
+ * @example
71
+ * // With imperative ref
72
+ * const supportRef = useRef<SupportHandle>(null);
73
+ * supportRef.current?.open();
74
+ * supportRef.current?.startConversation("Hello!");
75
+ * <Support ref={supportRef} />
76
+ *
77
+ * @example
78
+ * // With custom trigger
79
+ * <Support side="bottom" align="end">
80
+ * <Support.Trigger className="px-4 py-2">
81
+ * {({ isOpen, unreadCount }) => (
82
+ * <span>{isOpen ? "Close" : `Help (${unreadCount})`}</span>
83
+ * )}
84
+ * </Support.Trigger>
85
+ * </Support>
86
+ *
87
+ * @example
88
+ * // With custom pages
89
+ * <Support>
90
+ * <Support.Page name="FAQ" component={FAQPage} />
91
+ * </Support>
32
92
  */
33
- function Support({ className, position = "bottom", align = "right", positioning = "fixed", quickOptions, defaultMessages, defaultOpen, locale, content, theme, slots, classNames, customPages, children }) {
93
+ function SupportComponentInner({ className, side = "top", align = "end", sideOffset = 16, avoidCollisions = true, collisionPadding = 8, classNames = {}, theme, open, onOpenChange, defaultOpen, quickOptions, defaultMessages, locale, content, customPages, onConversationStart, onConversationEnd, onMessageSent, onMessageReceived, onError, children }, ref) {
34
94
  const { website } = useSupport();
35
95
  const isVisitorBlocked = website?.visitor?.isBlocked ?? false;
36
- React.useEffect(() => {
37
- if (defaultOpen !== void 0) initializeSupportStore({ defaultOpen });
38
- }, [defaultOpen]);
96
+ React$1.useEffect(() => {
97
+ if (open === void 0 && defaultOpen !== void 0) initializeSupportStore({ defaultOpen });
98
+ }, [open, defaultOpen]);
39
99
  if (!website || isVisitorBlocked) return null;
40
- return /* @__PURE__ */ jsxs(ThemeWrapper, {
41
- theme,
42
- children: [/* @__PURE__ */ jsx(SupportRealtimeProvider, { children: /* @__PURE__ */ jsx(SupportTextProvider, {
43
- content,
44
- locale,
45
- children: /* @__PURE__ */ jsx(SupportContent, {
46
- align,
47
- className,
48
- classNames,
49
- customPages,
50
- position,
51
- positioning,
52
- slots,
53
- children
100
+ const parsed = parseChildren(children);
101
+ return /* @__PURE__ */ jsx(ControlledStateProvider, {
102
+ onOpenChange,
103
+ open,
104
+ children: /* @__PURE__ */ jsx(SupportEventsProvider, {
105
+ onConversationEnd,
106
+ onConversationStart,
107
+ onError,
108
+ onMessageReceived,
109
+ onMessageSent,
110
+ children: /* @__PURE__ */ jsx(SupportHandleProvider, {
111
+ forwardedRef: ref,
112
+ children: /* @__PURE__ */ jsxs(ThemeWrapper, {
113
+ theme,
114
+ children: [/* @__PURE__ */ jsx(SupportRealtimeProvider, { children: /* @__PURE__ */ jsx(SupportTextProvider, {
115
+ content,
116
+ locale,
117
+ children: /* @__PURE__ */ jsxs(Root, {
118
+ className,
119
+ children: [parsed.trigger ?? /* @__PURE__ */ jsx(DefaultTrigger, { className: classNames.trigger }), parsed.content ?? /* @__PURE__ */ jsx(Content, {
120
+ align,
121
+ avoidCollisions,
122
+ className: classNames.content,
123
+ collisionPadding,
124
+ side,
125
+ sideOffset,
126
+ children: /* @__PURE__ */ jsx(Router, {
127
+ customPages,
128
+ children: parsed.pages
129
+ })
130
+ })]
131
+ })
132
+ }) }), /* @__PURE__ */ jsx(SupportConfig, {
133
+ defaultMessages,
134
+ quickOptions
135
+ })]
136
+ })
54
137
  })
55
- }) }), /* @__PURE__ */ jsx(SupportConfig, {
56
- defaultMessages,
57
- quickOptions
58
- })]
138
+ })
59
139
  });
60
140
  }
141
+ const SupportComponent = React$1.forwardRef(SupportComponentInner);
142
+ /**
143
+ * Custom trigger component for the support widget.
144
+ * Use this inside <Support> to replace the default floating button.
145
+ *
146
+ * @example
147
+ * <Support.Trigger className="my-button">
148
+ * {({ isOpen, unreadCount }) => (
149
+ * <span>{isOpen ? "Close" : `Help (${unreadCount})`}</span>
150
+ * )}
151
+ * </Support.Trigger>
152
+ */
153
+ const SupportTrigger = React$1.forwardRef(({ children, className, asChild = false,...props }, ref) => /* @__PURE__ */ jsx(SupportTrigger$1, {
154
+ asChild,
155
+ className,
156
+ ref,
157
+ ...props,
158
+ children
159
+ }));
160
+ SupportTrigger.displayName = "Support.Trigger";
161
+ /**
162
+ * Custom content wrapper for the support widget.
163
+ * Use this inside <Support> for custom positioning or styling.
164
+ *
165
+ * @example
166
+ * <Support>
167
+ * <Support.Trigger>Help</Support.Trigger>
168
+ * <Support.Content side="bottom" align="end" className="my-content">
169
+ * <Support.Router />
170
+ * </Support.Content>
171
+ * </Support>
172
+ */
173
+ const SupportContent = ({ className, side = "top", align = "end", sideOffset = 16, avoidCollisions = true, collisionPadding = 8, children }) => /* @__PURE__ */ jsx(Content, {
174
+ align,
175
+ avoidCollisions,
176
+ className,
177
+ collisionPadding,
178
+ side,
179
+ sideOffset,
180
+ children: children ?? /* @__PURE__ */ jsx(Router, {})
181
+ });
182
+ SupportContent.displayName = "Support.Content";
183
+ /**
184
+ * Router with all default pages (Home, Conversation, etc.).
185
+ * Use inside <Support.Content> for full control.
186
+ *
187
+ * @example
188
+ * <Support.Content>
189
+ * <Support.Router />
190
+ * </Support.Content>
191
+ *
192
+ * @example
193
+ * // With custom pages
194
+ * <Support.Router>
195
+ * <Support.Page name="FAQ" component={FAQPage} />
196
+ * </Support.Router>
197
+ */
198
+ const SupportRouter = ({ customPages, children }) => /* @__PURE__ */ jsx(Router, {
199
+ customPages,
200
+ children
201
+ });
202
+ SupportRouter.displayName = "Support.Router";
203
+ /**
204
+ * Declarative page registration for custom routes.
205
+ *
206
+ * @example
207
+ * <Support>
208
+ * <Support.Page name="FAQ" component={FAQPage} />
209
+ * <Support.Page name="SETTINGS" component={SettingsPage} />
210
+ * </Support>
211
+ */
212
+ const SupportPage = Page;
213
+ SupportPage.displayName = "Support.Page";
214
+ /**
215
+ * Root component for full composition mode.
216
+ * Use when you need complete control over the widget structure.
217
+ *
218
+ * @example
219
+ * // Uncontrolled
220
+ * <Support.Root defaultOpen={false}>
221
+ * <Support.Trigger asChild>
222
+ * <button>Help</button>
223
+ * </Support.Trigger>
224
+ * <Support.Content side="bottom" align="end">
225
+ * <Support.Router />
226
+ * </Support.Content>
227
+ * </Support.Root>
228
+ *
229
+ * @example
230
+ * // Controlled
231
+ * const [isOpen, setIsOpen] = useState(false);
232
+ * <Support.Root open={isOpen} onOpenChange={setIsOpen}>
233
+ * ...
234
+ * </Support.Root>
235
+ *
236
+ * @example
237
+ * // With imperative ref
238
+ * const supportRef = useRef<SupportHandle>(null);
239
+ * <Support.Root ref={supportRef}>
240
+ * ...
241
+ * </Support.Root>
242
+ */
243
+ const SupportRoot = React$1.forwardRef(({ open, onOpenChange, defaultOpen, theme, className, onConversationStart, onConversationEnd, onMessageSent, onMessageReceived, onError, children }, ref) => {
244
+ const { website } = useSupport();
245
+ const isVisitorBlocked = website?.visitor?.isBlocked ?? false;
246
+ React$1.useEffect(() => {
247
+ if (open === void 0 && defaultOpen !== void 0) initializeSupportStore({ defaultOpen });
248
+ }, [open, defaultOpen]);
249
+ if (!website || isVisitorBlocked) return null;
250
+ return /* @__PURE__ */ jsx(ControlledStateProvider, {
251
+ onOpenChange,
252
+ open,
253
+ children: /* @__PURE__ */ jsx(SupportEventsProvider, {
254
+ onConversationEnd,
255
+ onConversationStart,
256
+ onError,
257
+ onMessageReceived,
258
+ onMessageSent,
259
+ children: /* @__PURE__ */ jsx(SupportHandleProvider, {
260
+ forwardedRef: ref,
261
+ children: /* @__PURE__ */ jsx(ThemeWrapper, {
262
+ theme,
263
+ children: /* @__PURE__ */ jsx(SupportRealtimeProvider, { children: /* @__PURE__ */ jsx(Root, {
264
+ className,
265
+ children
266
+ }) })
267
+ })
268
+ })
269
+ })
270
+ });
271
+ });
272
+ SupportRoot.displayName = "Support.Root";
273
+ const Support = Object.assign(SupportComponent, {
274
+ Root: SupportRoot,
275
+ Trigger: SupportTrigger,
276
+ Content: SupportContent,
277
+ Router: SupportRouter,
278
+ Page: SupportPage,
279
+ Header: HeaderSlot,
280
+ Footer: FooterSlot
281
+ });
61
282
  var support_default = Support;
62
283
 
63
284
  //#endregion
64
- export { CoButton as Button, Header, Support, Text, WebSocketProvider, support_default as default, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
285
+ export { CoButton as Button, Header, Support, Text, WebSocketProvider, support_default as default, useSupportConfig, useSupportEventEmitter, useSupportEvents, useSupportHandle, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
65
286
  //# sourceMappingURL=index.js.map