@arbidocs/react 0.5.111 → 0.5.113

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 (972) hide show
  1. package/dist/account/client.js +96 -0
  2. package/dist/account/client.js.map +7 -0
  3. package/dist/account/delete.js +70 -0
  4. package/dist/account/delete.js.map +7 -0
  5. package/dist/account/didit.js +34 -0
  6. package/dist/account/didit.js.map +7 -0
  7. package/dist/account/dismissed-tips.js +33 -0
  8. package/dist/account/dismissed-tips.js.map +7 -0
  9. package/dist/account/email.js +84 -0
  10. package/dist/account/email.js.map +7 -0
  11. package/dist/account/entitlements.js +47 -0
  12. package/dist/account/entitlements.js.map +7 -0
  13. package/dist/account/identity.js +270 -0
  14. package/dist/account/identity.js.map +7 -0
  15. package/dist/account/index.js +93 -0
  16. package/dist/account/index.js.map +7 -0
  17. package/dist/account/notifications.js +59 -0
  18. package/dist/account/notifications.js.map +7 -0
  19. package/dist/account/password.js +103 -0
  20. package/dist/account/password.js.map +7 -0
  21. package/dist/account/profile.js +116 -0
  22. package/dist/account/profile.js.map +7 -0
  23. package/dist/account/recovery.js +13 -0
  24. package/dist/account/recovery.js.map +7 -0
  25. package/dist/account/relevance.js +82 -0
  26. package/dist/account/relevance.js.map +7 -0
  27. package/dist/account/sessions.js +37 -0
  28. package/dist/account/sessions.js.map +7 -0
  29. package/dist/account/settings.js +39 -0
  30. package/dist/account/settings.js.map +7 -0
  31. package/dist/account/table-views.js +16 -0
  32. package/dist/account/table-views.js.map +7 -0
  33. package/dist/ai/AiAnswer.js +83 -0
  34. package/dist/ai/AiAnswer.js.map +7 -0
  35. package/dist/ai/AiMarkdown.js +40 -0
  36. package/dist/ai/AiMarkdown.js.map +7 -0
  37. package/dist/ai/ArtifactCanvas.js +193 -0
  38. package/dist/ai/ArtifactCanvas.js.map +7 -0
  39. package/dist/ai/CitationRenderer.js +413 -0
  40. package/dist/ai/CitationRenderer.js.map +7 -0
  41. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  42. package/dist/ai/MarkdownRenderer.js.map +7 -0
  43. package/dist/ai/MessageArtifactCard.js +75 -0
  44. package/dist/ai/MessageArtifactCard.js.map +7 -0
  45. package/dist/ai/PassageCard.js +79 -0
  46. package/dist/ai/PassageCard.js.map +7 -0
  47. package/dist/ai/engine.js +110 -0
  48. package/dist/ai/engine.js.map +7 -0
  49. package/dist/ai/index.js +63 -0
  50. package/dist/ai/index.js.map +7 -0
  51. package/dist/ai/markdown-base-components.js +37 -0
  52. package/dist/ai/markdown-base-components.js.map +7 -0
  53. package/dist/ai/markdown-streaming-context.js +6 -0
  54. package/dist/ai/markdown-streaming-context.js.map +7 -0
  55. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  56. package/dist/ai/normalize-citations.js.map +7 -0
  57. package/dist/ai/redline.js +41 -0
  58. package/dist/ai/redline.js.map +7 -0
  59. package/dist/ai/split-markdown-blocks.js +40 -0
  60. package/dist/ai/split-markdown-blocks.js.map +7 -0
  61. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  62. package/dist/ai/stored-markdown.js.map +7 -0
  63. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  64. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  65. package/dist/annotations/AnnotationToolbar.js +398 -0
  66. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  67. package/dist/annotations/FreezeDialog.js +170 -0
  68. package/dist/annotations/FreezeDialog.js.map +7 -0
  69. package/dist/annotations/ProductionDialog.js +354 -0
  70. package/dist/annotations/ProductionDialog.js.map +7 -0
  71. package/dist/annotations/controller.js +49 -0
  72. package/dist/annotations/controller.js.map +7 -0
  73. package/dist/annotations/freeze/browser.js +21 -0
  74. package/dist/annotations/freeze/browser.js.map +7 -0
  75. package/dist/annotations/freeze/bundle.js +201 -0
  76. package/dist/annotations/freeze/bundle.js.map +7 -0
  77. package/dist/annotations/freeze/coords.js +37 -0
  78. package/dist/annotations/freeze/coords.js.map +7 -0
  79. package/dist/annotations/freeze/freeze.js +261 -0
  80. package/dist/annotations/freeze/freeze.js.map +7 -0
  81. package/dist/annotations/freeze/hash.js +28 -0
  82. package/dist/annotations/freeze/hash.js.map +7 -0
  83. package/dist/annotations/freeze/index-page.js +78 -0
  84. package/dist/annotations/freeze/index-page.js.map +7 -0
  85. package/dist/annotations/freeze/index.js +28 -22
  86. package/dist/annotations/freeze/index.js.map +7 -1
  87. package/dist/annotations/freeze/raster.js +208 -0
  88. package/dist/annotations/freeze/raster.js.map +7 -0
  89. package/dist/annotations/freeze/stamp.js +117 -0
  90. package/dist/annotations/freeze/stamp.js.map +7 -0
  91. package/dist/annotations/freeze/types.js +14 -0
  92. package/dist/annotations/freeze/types.js.map +7 -0
  93. package/dist/annotations/freeze/vector.js +283 -0
  94. package/dist/annotations/freeze/vector.js.map +7 -0
  95. package/dist/annotations/geometry.js +81 -0
  96. package/dist/annotations/geometry.js.map +7 -0
  97. package/dist/annotations/index.js +125 -6
  98. package/dist/annotations/index.js.map +7 -1
  99. package/dist/annotations/merge.js +53 -0
  100. package/dist/annotations/merge.js.map +7 -0
  101. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  102. package/dist/annotations/model.js.map +7 -0
  103. package/dist/annotations/overlay-geometry.js +41 -0
  104. package/dist/annotations/overlay-geometry.js.map +7 -0
  105. package/dist/annotations/redaction-log.js +33 -0
  106. package/dist/annotations/redaction-log.js.map +7 -0
  107. package/dist/annotations/selection-marks.js +122 -0
  108. package/dist/annotations/selection-marks.js.map +7 -0
  109. package/dist/annotations/state.js +140 -0
  110. package/dist/annotations/state.js.map +7 -0
  111. package/dist/annotations/store.js +49 -0
  112. package/dist/annotations/store.js.map +7 -0
  113. package/dist/annotations/useAnnotationLayer.js +306 -0
  114. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  115. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  116. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  117. package/dist/annotations/useTextSelectionMarks.js +100 -0
  118. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  119. package/dist/artifacts/artifact-kind.js +19 -0
  120. package/dist/artifacts/artifact-kind.js.map +7 -0
  121. package/dist/artifacts/index.js +89 -571
  122. package/dist/artifacts/index.js.map +7 -1
  123. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  124. package/dist/artifacts/normalize-markdown.js.map +7 -0
  125. package/dist/artifacts/redline-core.js +12 -3
  126. package/dist/artifacts/redline-core.js.map +7 -1
  127. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  128. package/dist/artifacts/redline-diff.js.map +7 -0
  129. package/dist/artifacts/redline-engine.js +14 -0
  130. package/dist/artifacts/redline-engine.js.map +7 -0
  131. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  132. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  133. package/dist/artifacts/useArtifactEditSession.js +183 -0
  134. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  135. package/dist/artifacts/useArtifactSession.js +173 -0
  136. package/dist/artifacts/useArtifactSession.js.map +7 -0
  137. package/dist/artifacts/useArtifactSource.js +16 -0
  138. package/dist/artifacts/useArtifactSource.js.map +7 -0
  139. package/dist/artifacts/useArtifactText.js +78 -0
  140. package/dist/artifacts/useArtifactText.js.map +7 -0
  141. package/dist/artifacts/useRedline.js +65 -0
  142. package/dist/artifacts/useRedline.js.map +7 -0
  143. package/dist/artifacts/useStreamedArtifact.js +74 -0
  144. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  145. package/dist/artifacts/versions.js +68 -0
  146. package/dist/artifacts/versions.js.map +7 -0
  147. package/dist/billing.js +200 -0
  148. package/dist/billing.js.map +7 -0
  149. package/dist/boot-timeout.js +19 -0
  150. package/dist/boot-timeout.js.map +7 -0
  151. package/dist/calendar/accounts.js +213 -0
  152. package/dist/calendar/accounts.js.map +7 -0
  153. package/dist/calendar/hooks.js +409 -0
  154. package/dist/calendar/hooks.js.map +7 -0
  155. package/dist/calendar/index.js +31 -0
  156. package/dist/calendar/index.js.map +7 -0
  157. package/dist/calendar/keys.js +5 -0
  158. package/dist/calendar/keys.js.map +7 -0
  159. package/dist/calendar/offline/outbox.js +231 -0
  160. package/dist/calendar/offline/outbox.js.map +7 -0
  161. package/dist/calendar/offline/runtime.js +109 -0
  162. package/dist/calendar/offline/runtime.js.map +7 -0
  163. package/dist/calendar/offline/support.js +41 -0
  164. package/dist/calendar/offline/support.js.map +7 -0
  165. package/dist/calendar/support.js +34 -0
  166. package/dist/calendar/support.js.map +7 -0
  167. package/dist/calls/actions.js +226 -0
  168. package/dist/calls/actions.js.map +7 -0
  169. package/dist/calls/events.js +138 -0
  170. package/dist/calls/events.js.map +7 -0
  171. package/dist/calls/gate.js +19 -0
  172. package/dist/calls/gate.js.map +7 -0
  173. package/dist/calls/hooks.js +115 -0
  174. package/dist/calls/hooks.js.map +7 -0
  175. package/dist/calls/in-call-chat.js +132 -0
  176. package/dist/calls/in-call-chat.js.map +7 -0
  177. package/dist/calls/index.js +24 -0
  178. package/dist/calls/index.js.map +7 -0
  179. package/dist/calls/keys.js +17 -0
  180. package/dist/calls/keys.js.map +7 -0
  181. package/dist/calls/livekit/index.js +6 -958
  182. package/dist/calls/livekit/index.js.map +7 -1
  183. package/dist/calls/livekit/room.js +98 -0
  184. package/dist/calls/livekit/room.js.map +7 -0
  185. package/dist/calls/livekit/useCallRecorder.js +219 -0
  186. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  187. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  188. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  189. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  190. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  191. package/dist/calls/livekit/useInCallChat.js +161 -0
  192. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  193. package/dist/calls/livekit/useWebinar.js +239 -0
  194. package/dist/calls/livekit/useWebinar.js.map +7 -0
  195. package/dist/calls/meeting-chat.js +149 -0
  196. package/dist/calls/meeting-chat.js.map +7 -0
  197. package/dist/calls/moderation.js +50 -0
  198. package/dist/calls/moderation.js.map +7 -0
  199. package/dist/calls/open-meeting-chat.js +29 -0
  200. package/dist/calls/open-meeting-chat.js.map +7 -0
  201. package/dist/calls/read-only.js +24 -0
  202. package/dist/calls/read-only.js.map +7 -0
  203. package/dist/calls/recording-media.js +218 -0
  204. package/dist/calls/recording-media.js.map +7 -0
  205. package/dist/calls/recording-playback.js +260 -0
  206. package/dist/calls/recording-playback.js.map +7 -0
  207. package/dist/calls/recording.js +268 -0
  208. package/dist/calls/recording.js.map +7 -0
  209. package/dist/calls/save-to-thread.js +80 -0
  210. package/dist/calls/save-to-thread.js.map +7 -0
  211. package/dist/calls/session.js +134 -0
  212. package/dist/calls/session.js.map +7 -0
  213. package/dist/calls/transcript-format.js +147 -0
  214. package/dist/calls/transcript-format.js.map +7 -0
  215. package/dist/calls/transcription.js +101 -0
  216. package/dist/calls/transcription.js.map +7 -0
  217. package/dist/calls/webinar.js +71 -0
  218. package/dist/calls/webinar.js.map +7 -0
  219. package/dist/charge-watch.js +71 -0
  220. package/dist/charge-watch.js.map +7 -0
  221. package/dist/chat/ChatBubble.js +146 -0
  222. package/dist/chat/ChatBubble.js.map +7 -0
  223. package/dist/chat/ConversationScope.js +30 -0
  224. package/dist/chat/ConversationScope.js.map +7 -0
  225. package/dist/chat/active-config.js +20 -0
  226. package/dist/chat/active-config.js.map +7 -0
  227. package/dist/chat/agent-chat-owner.js +25 -0
  228. package/dist/chat/agent-chat-owner.js.map +7 -0
  229. package/dist/chat/chat-artifacts.js +64 -0
  230. package/dist/chat/chat-artifacts.js.map +7 -0
  231. package/dist/chat/citations.js +32 -0
  232. package/dist/chat/citations.js.map +7 -0
  233. package/dist/chat/config-model.js +10 -0
  234. package/dist/chat/config-model.js.map +7 -0
  235. package/dist/chat/conversation-cache.js +676 -0
  236. package/dist/chat/conversation-cache.js.map +7 -0
  237. package/dist/chat/conversation-events.js +57 -0
  238. package/dist/chat/conversation-events.js.map +7 -0
  239. package/dist/chat/conversation-mentions.js +58 -0
  240. package/dist/chat/conversation-mentions.js.map +7 -0
  241. package/dist/chat/conversation-workspace.js +58 -0
  242. package/dist/chat/conversation-workspace.js.map +7 -0
  243. package/dist/chat/mentions.js +116 -0
  244. package/dist/chat/mentions.js.map +7 -0
  245. package/dist/chat/open-document.js +106 -0
  246. package/dist/chat/open-document.js.map +7 -0
  247. package/dist/chat/orphaned.js +44 -0
  248. package/dist/chat/orphaned.js.map +7 -0
  249. package/dist/chat/pendingFirstTurn.js +30 -0
  250. package/dist/chat/pendingFirstTurn.js.map +7 -0
  251. package/dist/chat/reply-target.js +12 -0
  252. package/dist/chat/reply-target.js.map +7 -0
  253. package/dist/chat/run-finished.js +28 -0
  254. package/dist/chat/run-finished.js.map +7 -0
  255. package/dist/chat/run-state.js +91 -0
  256. package/dist/chat/run-state.js.map +7 -0
  257. package/dist/chat/stream-handlers.js +419 -0
  258. package/dist/chat/stream-handlers.js.map +7 -0
  259. package/dist/chat/thread-binding.js +76 -0
  260. package/dist/chat/thread-binding.js.map +7 -0
  261. package/dist/chat/thread-document.js +53 -0
  262. package/dist/chat/thread-document.js.map +7 -0
  263. package/dist/chat/turn-control.js +79 -0
  264. package/dist/chat/turn-control.js.map +7 -0
  265. package/dist/chat/useAgentRunControl.js +36 -0
  266. package/dist/chat/useAgentRunControl.js.map +7 -0
  267. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  268. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  269. package/dist/chat/useAskAgain.js +32 -0
  270. package/dist/chat/useAskAgain.js.map +7 -0
  271. package/dist/chat/useAutoSendDraft.js +17 -0
  272. package/dist/chat/useAutoSendDraft.js.map +7 -0
  273. package/dist/chat/useBranchNavigation.js +97 -0
  274. package/dist/chat/useBranchNavigation.js.map +7 -0
  275. package/dist/chat/useConnectRunStream.js +169 -0
  276. package/dist/chat/useConnectRunStream.js.map +7 -0
  277. package/dist/chat/useConversation.js +431 -0
  278. package/dist/chat/useConversation.js.map +7 -0
  279. package/dist/chat/useConversationActions.js +662 -0
  280. package/dist/chat/useConversationActions.js.map +7 -0
  281. package/dist/chat/useConversationData.js +143 -0
  282. package/dist/chat/useConversationData.js.map +7 -0
  283. package/dist/chat/useConversationDocuments.js +41 -0
  284. package/dist/chat/useConversationDocuments.js.map +7 -0
  285. package/dist/chat/useConversationSettings.js +78 -0
  286. package/dist/chat/useConversationSettings.js.map +7 -0
  287. package/dist/chat/useConversationTurn.js +31 -0
  288. package/dist/chat/useConversationTurn.js.map +7 -0
  289. package/dist/chat/useConversationWorkspace.js +12 -0
  290. package/dist/chat/useConversationWorkspace.js.map +7 -0
  291. package/dist/chat/useDeleteMessage.js +15 -0
  292. package/dist/chat/useDeleteMessage.js.map +7 -0
  293. package/dist/chat/useDocumentAutoAdd.js +73 -0
  294. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  295. package/dist/chat/useMessageTimer.js +39 -0
  296. package/dist/chat/useMessageTimer.js.map +7 -0
  297. package/dist/chat/useThinkingContent.js +67 -0
  298. package/dist/chat/useThinkingContent.js.map +7 -0
  299. package/dist/chat/useThreadDocument.js +61 -0
  300. package/dist/chat/useThreadDocument.js.map +7 -0
  301. package/dist/chat/workflow-run-titles.js +50 -0
  302. package/dist/chat/workflow-run-titles.js.map +7 -0
  303. package/dist/config/config-hooks.js +209 -0
  304. package/dist/config/config-hooks.js.map +7 -0
  305. package/dist/connectivity.js +72 -0
  306. package/dist/connectivity.js.map +7 -0
  307. package/dist/connectors/hooks.js +263 -0
  308. package/dist/connectors/hooks.js.map +7 -0
  309. package/dist/connectors/index.js +28 -0
  310. package/dist/connectors/index.js.map +7 -0
  311. package/dist/contacts.js +100 -0
  312. package/dist/contacts.js.map +7 -0
  313. package/dist/conversation-list.js +65 -0
  314. package/dist/conversation-list.js.map +7 -0
  315. package/dist/databases.js +195 -0
  316. package/dist/databases.js.map +7 -0
  317. package/dist/datasets/aggregate.js +281 -0
  318. package/dist/datasets/aggregate.js.map +7 -0
  319. package/dist/datasets/index.js +122 -0
  320. package/dist/datasets/index.js.map +7 -0
  321. package/dist/datasets/members.js +27 -0
  322. package/dist/datasets/members.js.map +7 -0
  323. package/dist/datasets/panel.js +44 -0
  324. package/dist/datasets/panel.js.map +7 -0
  325. package/dist/datasets/registry.js +47 -0
  326. package/dist/datasets/registry.js.map +7 -0
  327. package/dist/datasets/rows-source.js +44 -0
  328. package/dist/datasets/rows-source.js.map +7 -0
  329. package/dist/datasets/sources/activity.js +83 -0
  330. package/dist/datasets/sources/activity.js.map +7 -0
  331. package/dist/datasets/sources/conversations.js +74 -0
  332. package/dist/datasets/sources/conversations.js.map +7 -0
  333. package/dist/datasets/sources/database.js +209 -0
  334. package/dist/datasets/sources/database.js.map +7 -0
  335. package/dist/datasets/sources/documents.js +93 -0
  336. package/dist/datasets/sources/documents.js.map +7 -0
  337. package/dist/datasets/sources/facts.js +56 -0
  338. package/dist/datasets/sources/facts.js.map +7 -0
  339. package/dist/datasets/sources/projects.js +117 -0
  340. package/dist/datasets/sources/projects.js.map +7 -0
  341. package/dist/datasets/sources/tags.js +67 -0
  342. package/dist/datasets/sources/tags.js.map +7 -0
  343. package/dist/datasets/sources/usage.js +268 -0
  344. package/dist/datasets/sources/usage.js.map +7 -0
  345. package/dist/datasets/sources/workflows.js +91 -0
  346. package/dist/datasets/sources/workflows.js.map +7 -0
  347. package/dist/datasets/sources/workspaces.js +67 -0
  348. package/dist/datasets/sources/workspaces.js.map +7 -0
  349. package/dist/datasets/store.js +194 -0
  350. package/dist/datasets/store.js.map +7 -0
  351. package/dist/datasets/types.js +14 -0
  352. package/dist/datasets/types.js.map +7 -0
  353. package/dist/directmessages/ConversationList.js +148 -0
  354. package/dist/directmessages/ConversationList.js.map +7 -0
  355. package/dist/directmessages/DateSeparator.js +8 -0
  356. package/dist/directmessages/DateSeparator.js.map +7 -0
  357. package/dist/directmessages/DmAvatar.js +29 -0
  358. package/dist/directmessages/DmAvatar.js.map +7 -0
  359. package/dist/directmessages/DmComposer.js +201 -0
  360. package/dist/directmessages/DmComposer.js.map +7 -0
  361. package/dist/directmessages/arrivals.js +29 -0
  362. package/dist/directmessages/arrivals.js.map +7 -0
  363. package/dist/directmessages/chat-cache.js +192 -0
  364. package/dist/directmessages/chat-cache.js.map +7 -0
  365. package/dist/directmessages/grouping.js +26 -0
  366. package/dist/directmessages/grouping.js.map +7 -0
  367. package/dist/directmessages/index.js +81 -0
  368. package/dist/directmessages/index.js.map +7 -0
  369. package/dist/directmessages/useChats.js +266 -0
  370. package/dist/directmessages/useChats.js.map +7 -0
  371. package/dist/directmessages/utils.js +23 -0
  372. package/dist/directmessages/utils.js.map +7 -0
  373. package/dist/document-tools/can-annotate.js +7 -0
  374. package/dist/document-tools/can-annotate.js.map +7 -0
  375. package/dist/document-tools/core.js +218 -12
  376. package/dist/document-tools/core.js.map +7 -1
  377. package/dist/document-tools/document-pdf.js +76 -0
  378. package/dist/document-tools/document-pdf.js.map +7 -0
  379. package/dist/document-tools/environment.js +136 -0
  380. package/dist/document-tools/environment.js.map +7 -0
  381. package/dist/document-tools/file-shares.js +112 -0
  382. package/dist/document-tools/file-shares.js.map +7 -0
  383. package/dist/document-tools/frozen-copy.js +27 -0
  384. package/dist/document-tools/frozen-copy.js.map +7 -0
  385. package/dist/document-tools/index.js +26 -148
  386. package/dist/document-tools/index.js.map +7 -1
  387. package/dist/document-tools/markup-download.js +51 -0
  388. package/dist/document-tools/markup-download.js.map +7 -0
  389. package/dist/document-tools/markup-store.js +138 -0
  390. package/dist/document-tools/markup-store.js.map +7 -0
  391. package/dist/document-tools/markup-transfer.js +88 -0
  392. package/dist/document-tools/markup-transfer.js.map +7 -0
  393. package/dist/document-tools/production.js +147 -0
  394. package/dist/document-tools/production.js.map +7 -0
  395. package/dist/document-tools/saved-signature.js +90 -0
  396. package/dist/document-tools/saved-signature.js.map +7 -0
  397. package/dist/document-tools/signature-requests.js +310 -0
  398. package/dist/document-tools/signature-requests.js.map +7 -0
  399. package/dist/document-tools/signing.js +127 -0
  400. package/dist/document-tools/signing.js.map +7 -0
  401. package/dist/document-tools/useDocumentBytes.js +38 -0
  402. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  403. package/dist/document-tools/useDocumentMarkup.js +154 -0
  404. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  405. package/dist/document-tools/useIsOnline.js +13 -0
  406. package/dist/document-tools/useIsOnline.js.map +7 -0
  407. package/dist/document-tools/verification.js +60 -0
  408. package/dist/document-tools/verification.js.map +7 -0
  409. package/dist/documents/DocumentReview.js +220 -0
  410. package/dist/documents/DocumentReview.js.map +7 -0
  411. package/dist/documents/DraftTitleControls.js +41 -0
  412. package/dist/documents/DraftTitleControls.js.map +7 -0
  413. package/dist/documents/InlineMicButton.js +90 -0
  414. package/dist/documents/InlineMicButton.js.map +7 -0
  415. package/dist/documents/MicRecordingOverlay.js +29 -0
  416. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  417. package/dist/documents/MicWaveformIndicator.js +68 -0
  418. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  419. package/dist/documents/PhotoCapture.js +120 -0
  420. package/dist/documents/PhotoCapture.js.map +7 -0
  421. package/dist/documents/VideoCapture.js +129 -0
  422. package/dist/documents/VideoCapture.js.map +7 -0
  423. package/dist/documents/VoiceNoteRecorder.js +166 -0
  424. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  425. package/dist/documents/audio-segmenter.js +63 -0
  426. package/dist/documents/audio-segmenter.js.map +7 -0
  427. package/dist/documents/capture-frame.js +21 -0
  428. package/dist/documents/capture-frame.js.map +7 -0
  429. package/dist/documents/chunked-recorder.js +190 -0
  430. package/dist/documents/chunked-recorder.js.map +7 -0
  431. package/dist/documents/document-download.js +53 -0
  432. package/dist/documents/document-download.js.map +7 -0
  433. package/dist/documents/document-fields.js +109 -0
  434. package/dist/documents/document-fields.js.map +7 -0
  435. package/dist/documents/documents-cache.js +110 -0
  436. package/dist/documents/documents-cache.js.map +7 -0
  437. package/dist/documents/documents-data.js +128 -0
  438. package/dist/documents/documents-data.js.map +7 -0
  439. package/dist/documents/documents-loader.js +113 -0
  440. package/dist/documents/documents-loader.js.map +7 -0
  441. package/dist/documents/documents-writes.js +448 -0
  442. package/dist/documents/documents-writes.js.map +7 -0
  443. package/dist/documents/format-elapsed.js +10 -0
  444. package/dist/documents/format-elapsed.js.map +7 -0
  445. package/dist/documents/has-video-track.js +26 -0
  446. package/dist/documents/has-video-track.js.map +7 -0
  447. package/dist/documents/index.js +266 -0
  448. package/dist/documents/index.js.map +7 -0
  449. package/dist/documents/media-error.js +18 -0
  450. package/dist/documents/media-error.js.map +7 -0
  451. package/dist/documents/offline-documents.js +160 -0
  452. package/dist/documents/offline-documents.js.map +7 -0
  453. package/dist/documents/pending-sync.js +210 -0
  454. package/dist/documents/pending-sync.js.map +7 -0
  455. package/dist/documents/processing-live.js +122 -0
  456. package/dist/documents/processing-live.js.map +7 -0
  457. package/dist/documents/processing-order.js +59 -0
  458. package/dist/documents/processing-order.js.map +7 -0
  459. package/dist/documents/processing-settle.js +21 -0
  460. package/dist/documents/processing-settle.js.map +7 -0
  461. package/dist/documents/related-documents.js +133 -0
  462. package/dist/documents/related-documents.js.map +7 -0
  463. package/dist/documents/support.js +29 -0
  464. package/dist/documents/support.js.map +7 -0
  465. package/dist/documents/upload-files.js +169 -0
  466. package/dist/documents/upload-files.js.map +7 -0
  467. package/dist/documents/useAudioRecorder.js +315 -0
  468. package/dist/documents/useAudioRecorder.js.map +7 -0
  469. package/dist/documents/useCameraStream.js +35 -0
  470. package/dist/documents/useCameraStream.js.map +7 -0
  471. package/dist/documents/useDocumentThumbnails.js +71 -0
  472. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  473. package/dist/documents/useDownloadDocuments.js +90 -0
  474. package/dist/documents/useDownloadDocuments.js.map +7 -0
  475. package/dist/documents/usePassageQuotes.js +37 -0
  476. package/dist/documents/usePassageQuotes.js.map +7 -0
  477. package/dist/documents/useUploadFiles.js +165 -0
  478. package/dist/documents/useUploadFiles.js.map +7 -0
  479. package/dist/documents/useUploadFromUrls.js +63 -0
  480. package/dist/documents/useUploadFromUrls.js.map +7 -0
  481. package/dist/documents/useVideoRecorder.js +62 -0
  482. package/dist/documents/useVideoRecorder.js.map +7 -0
  483. package/dist/entities/AgentMarkers.js +61 -0
  484. package/dist/entities/AgentMarkers.js.map +7 -0
  485. package/dist/entities/DocumentEntity.js +125 -0
  486. package/dist/entities/DocumentEntity.js.map +7 -0
  487. package/dist/entities/EntityPill.js +250 -0
  488. package/dist/entities/EntityPill.js.map +7 -0
  489. package/dist/entities/ProjectEntity.js +61 -0
  490. package/dist/entities/ProjectEntity.js.map +7 -0
  491. package/dist/entities/ShieldIcon.js +49 -0
  492. package/dist/entities/ShieldIcon.js.map +7 -0
  493. package/dist/entities/TagEntity.js +79 -0
  494. package/dist/entities/TagEntity.js.map +7 -0
  495. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  496. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  497. package/dist/entities/UserEntity.js +211 -0
  498. package/dist/entities/UserEntity.js.map +7 -0
  499. package/dist/entities/VerifiedBadge.js +19 -0
  500. package/dist/entities/VerifiedBadge.js.map +7 -0
  501. package/dist/entities/agent-avatar-colors.js +26 -0
  502. package/dist/entities/agent-avatar-colors.js.map +7 -0
  503. package/dist/entities/colors.js +64 -0
  504. package/dist/entities/colors.js.map +7 -0
  505. package/dist/entities/file-type.js +151 -0
  506. package/dist/entities/file-type.js.map +7 -0
  507. package/dist/entities/index.js +100 -0
  508. package/dist/entities/index.js.map +7 -0
  509. package/dist/entities/media-type.js +61 -0
  510. package/dist/entities/media-type.js.map +7 -0
  511. package/dist/entities/registry.js +385 -0
  512. package/dist/entities/registry.js.map +7 -0
  513. package/dist/entities/status.js +43 -0
  514. package/dist/entities/status.js.map +7 -0
  515. package/dist/entities/tag-kinds.js +23 -0
  516. package/dist/entities/tag-kinds.js.map +7 -0
  517. package/dist/entities/tag-types.js +44 -0
  518. package/dist/entities/tag-types.js.map +7 -0
  519. package/dist/entities/vocabulary.js +12 -0
  520. package/dist/entities/vocabulary.js.map +7 -0
  521. package/dist/entity-extraction.js +25 -0
  522. package/dist/entity-extraction.js.map +7 -0
  523. package/dist/facts-search.js +57 -0
  524. package/dist/facts-search.js.map +7 -0
  525. package/dist/facts.js +69 -0
  526. package/dist/facts.js.map +7 -0
  527. package/dist/hooks.js +320 -0
  528. package/dist/hooks.js.map +7 -0
  529. package/dist/host/ArbiHost.js +24 -0
  530. package/dist/host/ArbiHost.js.map +7 -0
  531. package/dist/host/assistant-copy.js +54 -0
  532. package/dist/host/assistant-copy.js.map +7 -0
  533. package/dist/host/config.js +9 -0
  534. package/dist/host/config.js.map +7 -0
  535. package/dist/host/context.js +10 -0
  536. package/dist/host/context.js.map +7 -0
  537. package/dist/host/features.js +144 -0
  538. package/dist/host/features.js.map +7 -0
  539. package/dist/host/index.js +12 -0
  540. package/dist/host/index.js.map +7 -0
  541. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  542. package/dist/host/merge.js.map +7 -0
  543. package/dist/house-template.js +40 -0
  544. package/dist/house-template.js.map +7 -0
  545. package/dist/icons/AppleIcon.js +25 -0
  546. package/dist/icons/AppleIcon.js.map +7 -0
  547. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  548. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  549. package/dist/icons/ArbiIcon.js +24 -0
  550. package/dist/icons/ArbiIcon.js.map +7 -0
  551. package/dist/icons/AudIcon.js +56 -0
  552. package/dist/icons/AudIcon.js.map +7 -0
  553. package/dist/icons/ClaudeIcon.js +28 -0
  554. package/dist/icons/ClaudeIcon.js.map +7 -0
  555. package/dist/icons/DocIcon.js +56 -0
  556. package/dist/icons/DocIcon.js.map +7 -0
  557. package/dist/icons/EmlIcon.js +57 -0
  558. package/dist/icons/EmlIcon.js.map +7 -0
  559. package/dist/icons/FireworksIcon.js +47 -0
  560. package/dist/icons/FireworksIcon.js.map +7 -0
  561. package/dist/icons/GeminiIcon.js +37 -0
  562. package/dist/icons/GeminiIcon.js.map +7 -0
  563. package/dist/icons/GitHubIcon.js +32 -0
  564. package/dist/icons/GitHubIcon.js.map +7 -0
  565. package/dist/icons/GoogleIcon.js +53 -0
  566. package/dist/icons/GoogleIcon.js.map +7 -0
  567. package/dist/icons/HtmlIcon.js +56 -0
  568. package/dist/icons/HtmlIcon.js.map +7 -0
  569. package/dist/icons/ImgIcon.js +56 -0
  570. package/dist/icons/ImgIcon.js.map +7 -0
  571. package/dist/icons/LinkedInIcon.js +25 -0
  572. package/dist/icons/LinkedInIcon.js.map +7 -0
  573. package/dist/icons/OpenAIIcon.js +28 -0
  574. package/dist/icons/OpenAIIcon.js.map +7 -0
  575. package/dist/icons/PdfIcon.js +56 -0
  576. package/dist/icons/PdfIcon.js.map +7 -0
  577. package/dist/icons/ProviderIcon.js +42 -0
  578. package/dist/icons/ProviderIcon.js.map +7 -0
  579. package/dist/icons/TxtIcon.js +56 -0
  580. package/dist/icons/TxtIcon.js.map +7 -0
  581. package/dist/icons/VidIcon.js +56 -0
  582. package/dist/icons/VidIcon.js.map +7 -0
  583. package/dist/icons/XlsIcon.js +56 -0
  584. package/dist/icons/XlsIcon.js.map +7 -0
  585. package/dist/icons/arbi-mark.js +5 -0
  586. package/dist/icons/arbi-mark.js.map +7 -0
  587. package/dist/icons/colors.js +31 -0
  588. package/dist/icons/colors.js.map +7 -0
  589. package/dist/icons/file-type.js +105 -0
  590. package/dist/icons/file-type.js.map +7 -0
  591. package/dist/icons/index.js +55 -0
  592. package/dist/icons/index.js.map +7 -0
  593. package/dist/imagecrop/ImageCropModal.js +56 -0
  594. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  595. package/dist/imagecrop/ImageCropper.js +100 -0
  596. package/dist/imagecrop/ImageCropper.js.map +7 -0
  597. package/dist/imagecrop/cropImage.js +43 -0
  598. package/dist/imagecrop/cropImage.js.map +7 -0
  599. package/dist/imagecrop/index.js +13 -0
  600. package/dist/imagecrop/index.js.map +7 -0
  601. package/dist/index.js +702 -17116
  602. package/dist/index.js.map +7 -1
  603. package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
  604. package/dist/lazy-chunk.js.map +7 -0
  605. package/dist/lib/collision-padding.js +13 -0
  606. package/dist/lib/collision-padding.js.map +7 -0
  607. package/dist/lib/format-friendly-date.js +55 -0
  608. package/dist/lib/format-friendly-date.js.map +7 -0
  609. package/dist/lib/format-relative-time.js +52 -0
  610. package/dist/lib/format-relative-time.js.map +7 -0
  611. package/dist/lib/markdown-to-text.js +35 -0
  612. package/dist/lib/markdown-to-text.js.map +7 -0
  613. package/dist/lib/toast-interaction.js +9 -0
  614. package/dist/lib/toast-interaction.js.map +7 -0
  615. package/dist/lib/utils.js +9 -0
  616. package/dist/lib/utils.js.map +7 -0
  617. package/dist/mail/client.js +103 -0
  618. package/dist/mail/client.js.map +7 -0
  619. package/dist/mail/document-attachment.js +38 -0
  620. package/dist/mail/document-attachment.js.map +7 -0
  621. package/dist/mail/filing.js +132 -0
  622. package/dist/mail/filing.js.map +7 -0
  623. package/dist/mail/hooks.js +393 -0
  624. package/dist/mail/hooks.js.map +7 -0
  625. package/dist/mail/index.js +120 -0
  626. package/dist/mail/index.js.map +7 -0
  627. package/dist/mail/offline/changes.js +258 -0
  628. package/dist/mail/offline/changes.js.map +7 -0
  629. package/dist/mail/offline/confirm-sign-out.js +37 -0
  630. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  631. package/dist/mail/offline/crypto.js +26 -0
  632. package/dist/mail/offline/crypto.js.map +7 -0
  633. package/dist/mail/offline/drafts.js +69 -0
  634. package/dist/mail/offline/drafts.js.map +7 -0
  635. package/dist/mail/offline/hooks.js +104 -0
  636. package/dist/mail/offline/hooks.js.map +7 -0
  637. package/dist/mail/offline/index.js +48 -0
  638. package/dist/mail/offline/index.js.map +7 -0
  639. package/dist/mail/offline/live.js +233 -0
  640. package/dist/mail/offline/live.js.map +7 -0
  641. package/dist/mail/offline/mailbox.js +191 -0
  642. package/dist/mail/offline/mailbox.js.map +7 -0
  643. package/dist/mail/offline/outbox.js +167 -0
  644. package/dist/mail/offline/outbox.js.map +7 -0
  645. package/dist/mail/offline/reads.js +159 -0
  646. package/dist/mail/offline/reads.js.map +7 -0
  647. package/dist/mail/offline/runtime.js +100 -0
  648. package/dist/mail/offline/runtime.js.map +7 -0
  649. package/dist/mail/offline/settings.js +84 -0
  650. package/dist/mail/offline/settings.js.map +7 -0
  651. package/dist/mail/offline/store.js +29 -0
  652. package/dist/mail/offline/store.js.map +7 -0
  653. package/dist/mail/offline/sync.js +251 -0
  654. package/dist/mail/offline/sync.js.map +7 -0
  655. package/dist/mail/offline/wipe.js +19 -0
  656. package/dist/mail/offline/wipe.js.map +7 -0
  657. package/dist/mail/thread-keys.js +53 -0
  658. package/dist/mail/thread-keys.js.map +7 -0
  659. package/dist/mail/threads.js +71 -0
  660. package/dist/mail/threads.js.map +7 -0
  661. package/dist/mail/useMailClient.js +42 -0
  662. package/dist/mail/useMailClient.js.map +7 -0
  663. package/dist/model-connections.js +58 -0
  664. package/dist/model-connections.js.map +7 -0
  665. package/dist/notifications/ActivityFeed.js +70 -0
  666. package/dist/notifications/ActivityFeed.js.map +7 -0
  667. package/dist/notifications/NotificationBell.js +200 -0
  668. package/dist/notifications/NotificationBell.js.map +7 -0
  669. package/dist/notifications/Toaster.js +24 -0
  670. package/dist/notifications/Toaster.js.map +7 -0
  671. package/dist/notifications/activity-types.js +65 -0
  672. package/dist/notifications/activity-types.js.map +7 -0
  673. package/dist/notifications/bell.js +24 -0
  674. package/dist/notifications/bell.js.map +7 -0
  675. package/dist/notifications/calendar-notifications.js +79 -0
  676. package/dist/notifications/calendar-notifications.js.map +7 -0
  677. package/dist/notifications/index.js +108 -0
  678. package/dist/notifications/index.js.map +7 -0
  679. package/dist/notifications/live.js +28 -0
  680. package/dist/notifications/live.js.map +7 -0
  681. package/dist/notifications/notification-types.js +127 -0
  682. package/dist/notifications/notification-types.js.map +7 -0
  683. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  684. package/dist/notifications/notify-store.js.map +7 -0
  685. package/dist/notifications/server-notifications.js +452 -0
  686. package/dist/notifications/server-notifications.js.map +7 -0
  687. package/dist/notifications/useNotifications.js +34 -0
  688. package/dist/notifications/useNotifications.js.map +7 -0
  689. package/dist/offline-store/network.js +11 -0
  690. package/dist/offline-store/network.js.map +7 -0
  691. package/dist/offline-store/store.js +136 -0
  692. package/dist/offline-store/store.js.map +7 -0
  693. package/dist/offline-store/wipe.js +8 -0
  694. package/dist/offline-store/wipe.js.map +7 -0
  695. package/dist/offline.js +58 -0
  696. package/dist/offline.js.map +7 -0
  697. package/dist/people.js +122 -0
  698. package/dist/people.js.map +7 -0
  699. package/dist/projects.js +30 -0
  700. package/dist/projects.js.map +7 -0
  701. package/dist/query-client.js +63 -0
  702. package/dist/query-client.js.map +7 -0
  703. package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
  704. package/dist/query-keys.js.map +7 -0
  705. package/dist/query-persist.js +66 -0
  706. package/dist/query-persist.js.map +7 -0
  707. package/dist/queued-writes.js +59 -0
  708. package/dist/queued-writes.js.map +7 -0
  709. package/dist/remote-control.js +67 -0
  710. package/dist/remote-control.js.map +7 -0
  711. package/dist/search/index.js +23 -0
  712. package/dist/search/index.js.map +7 -0
  713. package/dist/search/session.js +58 -0
  714. package/dist/search/session.js.map +7 -0
  715. package/dist/search/useSemanticSearch.js +82 -0
  716. package/dist/search/useSemanticSearch.js.map +7 -0
  717. package/dist/session/chat.js +512 -0
  718. package/dist/session/chat.js.map +7 -0
  719. package/dist/session/documents.js +196 -0
  720. package/dist/session/documents.js.map +7 -0
  721. package/dist/session/drafts.js +103 -0
  722. package/dist/session/drafts.js.map +7 -0
  723. package/dist/session/index.js +123 -0
  724. package/dist/session/index.js.map +7 -0
  725. package/dist/session/layout.js +339 -0
  726. package/dist/session/layout.js.map +7 -0
  727. package/dist/session/persist.js +106 -0
  728. package/dist/session/persist.js.map +7 -0
  729. package/dist/session/session-hooks.js +53 -0
  730. package/dist/session/session-hooks.js.map +7 -0
  731. package/dist/session/signed-in.js +36 -0
  732. package/dist/session/signed-in.js.map +7 -0
  733. package/dist/session/store.js +166 -0
  734. package/dist/session/store.js.map +7 -0
  735. package/dist/session/thread-tabs.js +121 -0
  736. package/dist/session/thread-tabs.js.map +7 -0
  737. package/dist/session/ui-state-storage.js +76 -0
  738. package/dist/session/ui-state-storage.js.map +7 -0
  739. package/dist/session/workspace.js +77 -0
  740. package/dist/session/workspace.js.map +7 -0
  741. package/dist/shell/index.js +43 -10
  742. package/dist/shell/index.js.map +7 -1
  743. package/dist/skill-pack.js +111 -0
  744. package/dist/skill-pack.js.map +7 -0
  745. package/dist/storage.js +186 -0
  746. package/dist/storage.js.map +7 -0
  747. package/dist/support/index.js +35 -0
  748. package/dist/support/index.js.map +7 -0
  749. package/dist/tags.js +204 -0
  750. package/dist/tags.js.map +7 -0
  751. package/dist/ui/DebouncedInput.js +109 -0
  752. package/dist/ui/DebouncedInput.js.map +7 -0
  753. package/dist/ui/DictateContext.js +8 -0
  754. package/dist/ui/DictateContext.js.map +7 -0
  755. package/dist/ui/IconToggle.js +79 -0
  756. package/dist/ui/IconToggle.js.map +7 -0
  757. package/dist/ui/VerifiedToggle.js +38 -0
  758. package/dist/ui/VerifiedToggle.js.map +7 -0
  759. package/dist/ui/VisibilityToggle.js +103 -0
  760. package/dist/ui/VisibilityToggle.js.map +7 -0
  761. package/dist/ui/avatar.js +40 -0
  762. package/dist/ui/avatar.js.map +7 -0
  763. package/dist/ui/badge.js +28 -0
  764. package/dist/ui/badge.js.map +7 -0
  765. package/dist/ui/button.js +48 -0
  766. package/dist/ui/button.js.map +7 -0
  767. package/dist/ui/card.js +90 -0
  768. package/dist/ui/card.js.map +7 -0
  769. package/dist/ui/checkbox.js +22 -0
  770. package/dist/ui/checkbox.js.map +7 -0
  771. package/dist/ui/collapsible.js +10 -0
  772. package/dist/ui/collapsible.js.map +7 -0
  773. package/dist/ui/command.js +103 -0
  774. package/dist/ui/command.js.map +7 -0
  775. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  776. package/dist/ui/dialog.js.map +7 -0
  777. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  778. package/dist/ui/dropdown-menu.js.map +7 -0
  779. package/dist/ui/hover-card.js +36 -0
  780. package/dist/ui/hover-card.js.map +7 -0
  781. package/dist/ui/index.js +290 -10
  782. package/dist/ui/index.js.map +7 -1
  783. package/dist/ui/input.js +65 -0
  784. package/dist/ui/input.js.map +7 -0
  785. package/dist/ui/label.js +16 -0
  786. package/dist/ui/label.js.map +7 -0
  787. package/dist/ui/mark-menu.js +300 -0
  788. package/dist/ui/mark-menu.js.map +7 -0
  789. package/dist/ui/popover.js +40 -0
  790. package/dist/ui/popover.js.map +7 -0
  791. package/dist/ui/portal-container.js +17 -0
  792. package/dist/ui/portal-container.js.map +7 -0
  793. package/dist/ui/progress.js +24 -0
  794. package/dist/ui/progress.js.map +7 -0
  795. package/dist/ui/radio-group.js +29 -0
  796. package/dist/ui/radio-group.js.map +7 -0
  797. package/dist/ui/scroll-area.js +39 -0
  798. package/dist/ui/scroll-area.js.map +7 -0
  799. package/dist/ui/select.js +130 -0
  800. package/dist/ui/select.js.map +7 -0
  801. package/dist/ui/separator.js +23 -0
  802. package/dist/ui/separator.js.map +7 -0
  803. package/dist/ui/slider.js +23 -0
  804. package/dist/ui/slider.js.map +7 -0
  805. package/dist/ui/switch.js +28 -0
  806. package/dist/ui/switch.js.map +7 -0
  807. package/dist/ui/table.js +75 -0
  808. package/dist/ui/table.js.map +7 -0
  809. package/dist/ui/tabs.js +48 -0
  810. package/dist/ui/tabs.js.map +7 -0
  811. package/dist/ui/textarea.js +63 -0
  812. package/dist/ui/textarea.js.map +7 -0
  813. package/dist/ui/toggle-group.js +43 -0
  814. package/dist/ui/toggle-group.js.map +7 -0
  815. package/dist/ui/toggle.js +40 -0
  816. package/dist/ui/toggle.js.map +7 -0
  817. package/dist/ui/tooltip.js +215 -0
  818. package/dist/ui/tooltip.js.map +7 -0
  819. package/dist/usage-metered.js +8 -0
  820. package/dist/usage-metered.js.map +7 -0
  821. package/dist/useArbi.js +16 -0
  822. package/dist/useArbi.js.map +7 -0
  823. package/dist/useInstallSkillPack.js +81 -0
  824. package/dist/useInstallSkillPack.js.map +7 -0
  825. package/dist/usermenu/UserMenu.js +188 -0
  826. package/dist/usermenu/UserMenu.js.map +7 -0
  827. package/dist/usermenu/index.js +5 -0
  828. package/dist/usermenu/index.js.map +7 -0
  829. package/dist/users/index.js +15 -0
  830. package/dist/users/index.js.map +7 -0
  831. package/dist/users/user-display.js +60 -0
  832. package/dist/users/user-display.js.map +7 -0
  833. package/dist/viewers/AudioViewer.js +23 -0
  834. package/dist/viewers/AudioViewer.js.map +7 -0
  835. package/dist/viewers/DocxViewer.js +81 -0
  836. package/dist/viewers/DocxViewer.js.map +7 -0
  837. package/dist/viewers/ImageViewer.js +31 -0
  838. package/dist/viewers/ImageViewer.js.map +7 -0
  839. package/dist/viewers/PdfViewer.js +19 -3
  840. package/dist/viewers/PdfViewer.js.map +7 -1
  841. package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
  842. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  843. package/dist/viewers/VideoViewer.js +31 -0
  844. package/dist/viewers/VideoViewer.js.map +7 -0
  845. package/dist/viewers/XlsxViewer.js +102 -0
  846. package/dist/viewers/XlsxViewer.js.map +7 -0
  847. package/dist/viewers/index.js +61 -271
  848. package/dist/viewers/index.js.map +7 -1
  849. package/dist/viewers/page-scroll.js +59 -0
  850. package/dist/viewers/page-scroll.js.map +7 -0
  851. package/dist/viewers/pdf-viewer-constants.js +9 -0
  852. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  853. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  854. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  855. package/dist/viewers/selection-runs.js +38 -0
  856. package/dist/viewers/selection-runs.js.map +7 -0
  857. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  858. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  859. package/dist/viewers/useProcessedChunks.js +58 -0
  860. package/dist/viewers/useProcessedChunks.js.map +7 -0
  861. package/dist/viewers/viewer-zoom.js +163 -0
  862. package/dist/viewers/viewer-zoom.js.map +7 -0
  863. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  864. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  865. package/dist/websocket/context.js +14 -0
  866. package/dist/websocket/context.js.map +7 -0
  867. package/dist/websocket/hooks.js +30 -0
  868. package/dist/websocket/hooks.js.map +7 -0
  869. package/dist/websocket/index.js +22 -0
  870. package/dist/websocket/index.js.map +7 -0
  871. package/dist/websocket/live-updates.js +38 -0
  872. package/dist/websocket/live-updates.js.map +7 -0
  873. package/dist/websocket/reconnect.js +13 -0
  874. package/dist/websocket/reconnect.js.map +7 -0
  875. package/dist/websocket/store.js +58 -0
  876. package/dist/websocket/store.js.map +7 -0
  877. package/dist/workforce.js +607 -0
  878. package/dist/workforce.js.map +7 -0
  879. package/dist/workspaces/access-request.js +35 -0
  880. package/dist/workspaces/access-request.js.map +7 -0
  881. package/dist/workspaces/archive.js +59 -0
  882. package/dist/workspaces/archive.js.map +7 -0
  883. package/dist/workspaces/current.js +20 -0
  884. package/dist/workspaces/current.js.map +7 -0
  885. package/dist/workspaces/delete-workspaces.js +15 -0
  886. package/dist/workspaces/delete-workspaces.js.map +7 -0
  887. package/dist/workspaces/export-archive.js +40 -0
  888. package/dist/workspaces/export-archive.js.map +7 -0
  889. package/dist/workspaces/index.js +99 -0
  890. package/dist/workspaces/index.js.map +7 -0
  891. package/dist/workspaces/settings.js +45 -0
  892. package/dist/workspaces/settings.js.map +7 -0
  893. package/dist/workspaces/shell-workspaces.js +49 -0
  894. package/dist/workspaces/shell-workspaces.js.map +7 -0
  895. package/dist/workspaces/switch.js +234 -0
  896. package/dist/workspaces/switch.js.map +7 -0
  897. package/dist/workspaces/transfer.js +170 -0
  898. package/dist/workspaces/transfer.js.map +7 -0
  899. package/dist/workspaces/useShellWorkspaces.js +86 -0
  900. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  901. package/dist/workspaces/workspace-users.js +65 -0
  902. package/dist/workspaces/workspace-users.js.map +7 -0
  903. package/package.json +4 -4
  904. package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
  905. package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
  906. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  907. package/dist/annotations/freeze/index.d.cts +0 -205
  908. package/dist/annotations/index.d.cts +0 -360
  909. package/dist/artifacts/index.d.cts +0 -476
  910. package/dist/artifacts/redline-core.d.cts +0 -39
  911. package/dist/bundle-YNOX7VIL.js +0 -5
  912. package/dist/bundle-YNOX7VIL.js.map +0 -1
  913. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  914. package/dist/calls/livekit/index.d.cts +0 -280
  915. package/dist/chunk-47CCGUWR.js.map +0 -1
  916. package/dist/chunk-4FL3X3LA.js +0 -2057
  917. package/dist/chunk-4FL3X3LA.js.map +0 -1
  918. package/dist/chunk-6QNBSXCE.js +0 -271
  919. package/dist/chunk-6QNBSXCE.js.map +0 -1
  920. package/dist/chunk-74N436VK.js.map +0 -1
  921. package/dist/chunk-APZZQZ6P.js +0 -147
  922. package/dist/chunk-APZZQZ6P.js.map +0 -1
  923. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  924. package/dist/chunk-DPYBZDJB.js.map +0 -1
  925. package/dist/chunk-DZKRL5H3.js +0 -2766
  926. package/dist/chunk-DZKRL5H3.js.map +0 -1
  927. package/dist/chunk-HDCRPPBW.js +0 -75
  928. package/dist/chunk-HDCRPPBW.js.map +0 -1
  929. package/dist/chunk-L2IPPTVC.js +0 -20
  930. package/dist/chunk-L2IPPTVC.js.map +0 -1
  931. package/dist/chunk-LSU4UPS5.js +0 -1011
  932. package/dist/chunk-LSU4UPS5.js.map +0 -1
  933. package/dist/chunk-NIKPG4PW.js +0 -1128
  934. package/dist/chunk-NIKPG4PW.js.map +0 -1
  935. package/dist/chunk-NNAJLY6B.js +0 -4974
  936. package/dist/chunk-NNAJLY6B.js.map +0 -1
  937. package/dist/chunk-OYPKKHXY.js +0 -559
  938. package/dist/chunk-OYPKKHXY.js.map +0 -1
  939. package/dist/chunk-PTOP7OHG.js.map +0 -1
  940. package/dist/chunk-QMY2JKBI.js +0 -246
  941. package/dist/chunk-QMY2JKBI.js.map +0 -1
  942. package/dist/chunk-SN5YV6FF.js +0 -11
  943. package/dist/chunk-SN5YV6FF.js.map +0 -1
  944. package/dist/chunk-SSXFVWCT.js.map +0 -1
  945. package/dist/chunk-T3USOSVN.js.map +0 -1
  946. package/dist/chunk-T4CLW3DN.js +0 -2560
  947. package/dist/chunk-T4CLW3DN.js.map +0 -1
  948. package/dist/chunk-UW2SGTI5.js.map +0 -1
  949. package/dist/chunk-VSCU7K4V.js.map +0 -1
  950. package/dist/chunk-WL2Y2T47.js.map +0 -1
  951. package/dist/chunk-WUTL62MC.js.map +0 -1
  952. package/dist/chunk-XWPLOFDN.js +0 -644
  953. package/dist/chunk-XWPLOFDN.js.map +0 -1
  954. package/dist/chunk-Y3MTRA7D.js +0 -97
  955. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  956. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  957. package/dist/chunk-ZM6N7YZH.js.map +0 -1
  958. package/dist/document-tools/core.d.cts +0 -883
  959. package/dist/document-tools/index.d.cts +0 -90
  960. package/dist/index.d-LArLnpI8.d.cts +0 -2036
  961. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  962. package/dist/index.d.cts +0 -15923
  963. package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
  964. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  965. package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
  966. package/dist/shell/index.d.cts +0 -6
  967. package/dist/store.d-GADDvC7w.d.cts +0 -35
  968. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  969. package/dist/ui/index.d.cts +0 -26
  970. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  971. package/dist/viewers/PdfViewer.d.cts +0 -9
  972. package/dist/viewers/index.d.cts +0 -262
@@ -0,0 +1,147 @@
1
+ import { chats } from "@arbidocs/sdk/browser";
2
+ function sortTranscriptMessages(messages) {
3
+ const spokenAt = (m) => {
4
+ const parsed = m.decryptFailed ? null : chats.parseTranscriptContent(m.content);
5
+ const at = Date.parse(parsed?.started_at ?? m.created_at);
6
+ return Number.isNaN(at) ? 0 : at;
7
+ };
8
+ return messages.map((m, i) => ({ m, i, at: spokenAt(m) })).sort((a, b) => a.at - b.at || a.i - b.i).map(({ m }) => m);
9
+ }
10
+ function transcriptSegmentOf(tools) {
11
+ if (!tools || typeof tools !== "object") return void 0;
12
+ const record = tools;
13
+ const byKey = record.transcript_segment;
14
+ const candidates = byKey ? [byKey] : Object.values(record);
15
+ for (const c of candidates) {
16
+ if (!c || typeof c !== "object") continue;
17
+ const t = c;
18
+ if (c !== byKey && t.name !== "transcript_segment") continue;
19
+ if (typeof t.segment_id !== "string" || typeof t.speaker_ext_id !== "string") continue;
20
+ return {
21
+ segment_id: t.segment_id,
22
+ speaker_ext_id: t.speaker_ext_id,
23
+ started_at: typeof t.started_at === "string" ? t.started_at : null
24
+ };
25
+ }
26
+ return void 0;
27
+ }
28
+ const pad = (n) => String(n).padStart(2, "0");
29
+ function clockTime(iso) {
30
+ if (!iso) return "";
31
+ const d = new Date(iso);
32
+ if (Number.isNaN(d.getTime())) return "";
33
+ return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
34
+ }
35
+ function formatTranscriptMarkdown(opts) {
36
+ const lines = [...opts.lines].filter((l) => l.text.trim()).sort((a, b) => (Date.parse(a.at ?? "") || 0) - (Date.parse(b.at ?? "") || 0));
37
+ const first = lines.find((l) => l.at)?.at;
38
+ const date = opts.date ?? (first ? new Date(first) : null);
39
+ const heading = `## Transcript: ${opts.title?.trim() || "Meeting"}`;
40
+ const dateLine = date ? `_${date.toLocaleDateString(void 0, { year: "numeric", month: "long", day: "numeric" })}_` : null;
41
+ const body = lines.map((l) => {
42
+ const time = clockTime(l.at);
43
+ return `**${l.speaker}**${time ? ` [${time}]` : ""}: ${l.text.trim().replace(/\s*\n\s*/g, " ")}`;
44
+ });
45
+ return [heading, ...dateLine ? [dateLine] : [], ...body].join("\n\n");
46
+ }
47
+ function threadTranscriptLines(messages, nameOf) {
48
+ const seen = /* @__PURE__ */ new Set();
49
+ const lines = [];
50
+ for (const m of messages) {
51
+ const marker = transcriptSegmentOf(m.tools);
52
+ if (!marker || seen.has(marker.segment_id)) continue;
53
+ seen.add(marker.segment_id);
54
+ const name = nameOf(marker.speaker_ext_id);
55
+ lines.push({
56
+ speaker: name || "Former member",
57
+ at: marker.started_at ?? m.created_at ?? null,
58
+ text: stripSpeakerPrefix(m.content ?? "", name)
59
+ });
60
+ }
61
+ return lines;
62
+ }
63
+ function stripSpeakerPrefix(content, speakerName) {
64
+ if (speakerName && content.startsWith(`${speakerName}: `)) {
65
+ return content.slice(speakerName.length + 2);
66
+ }
67
+ return content;
68
+ }
69
+ function isRecordingSegmentId(segmentId) {
70
+ return typeof segmentId === "string" && segmentId.startsWith("rec-");
71
+ }
72
+ function recordingWindowsOf(recordings) {
73
+ return recordings.map((r) => ({
74
+ trackExtIds: (r.tracks ?? []).map((t) => t.external_id),
75
+ startedAt: r.started_at,
76
+ stoppedAt: r.stopped_at ?? null
77
+ }));
78
+ }
79
+ function chatTranscriptRef(message) {
80
+ if (!chats.isTranscriptMessage(message)) return null;
81
+ const parsed = message.decryptFailed ? null : chats.parseTranscriptContent(message.content);
82
+ return { segmentId: message.dedupe_key, startedAt: parsed?.started_at ?? message.created_at };
83
+ }
84
+ function threadTranscriptRef(message) {
85
+ const marker = transcriptSegmentOf(message.tools ?? message.meta?.tools);
86
+ if (!marker) return null;
87
+ return { segmentId: marker.segment_id, startedAt: marker.started_at ?? message.created_at };
88
+ }
89
+ function supersededTranscriptLines(lines, refOf, recordings = []) {
90
+ const superseded = /* @__PURE__ */ new Set();
91
+ const recLines = [];
92
+ for (const line of lines) {
93
+ const ref = refOf(line);
94
+ if (ref && isRecordingSegmentId(ref.segmentId)) {
95
+ recLines.push({ segmentId: ref.segmentId, at: Date.parse(ref.startedAt ?? "") });
96
+ }
97
+ }
98
+ if (!recLines.length) return superseded;
99
+ const windows = [];
100
+ const claimed = /* @__PURE__ */ new Set();
101
+ for (const r of recordings) {
102
+ const prefixes = r.trackExtIds.map((t) => `rec-${t}-`);
103
+ const mine = recLines.filter((l) => prefixes.some((p) => l.segmentId.startsWith(p)));
104
+ if (!mine.length) continue;
105
+ for (const l of mine) claimed.add(l.segmentId);
106
+ const start = Date.parse(r.startedAt);
107
+ const stop = r.stoppedAt ? Date.parse(r.stoppedAt) : Number.POSITIVE_INFINITY;
108
+ if (!Number.isNaN(start)) windows.push([start, Number.isNaN(stop) ? Infinity : stop]);
109
+ }
110
+ const unclaimed = recLines.filter((l) => !claimed.has(l.segmentId) && !Number.isNaN(l.at));
111
+ if (unclaimed.length) {
112
+ const times = unclaimed.map((l) => l.at);
113
+ windows.push([Math.min(...times), Math.max(...times)]);
114
+ }
115
+ if (!windows.length) return superseded;
116
+ for (const line of lines) {
117
+ const ref = refOf(line);
118
+ if (!ref || isRecordingSegmentId(ref.segmentId)) continue;
119
+ const at = Date.parse(ref.startedAt ?? "");
120
+ if (Number.isNaN(at)) continue;
121
+ if (windows.some(([start, stop]) => at >= start && at <= stop)) superseded.add(line);
122
+ }
123
+ return superseded;
124
+ }
125
+ function supersedeLiveTranscript(lines, refOf, recordings = []) {
126
+ const superseded = supersededTranscriptLines(lines, refOf, recordings);
127
+ return superseded.size ? lines.filter((l) => !superseded.has(l)) : [...lines];
128
+ }
129
+ function hasRecordingTranscript(lines, refOf) {
130
+ return lines.some((l) => isRecordingSegmentId(refOf(l)?.segmentId));
131
+ }
132
+ export {
133
+ chatTranscriptRef,
134
+ clockTime,
135
+ formatTranscriptMarkdown,
136
+ hasRecordingTranscript,
137
+ isRecordingSegmentId,
138
+ recordingWindowsOf,
139
+ sortTranscriptMessages,
140
+ stripSpeakerPrefix,
141
+ supersedeLiveTranscript,
142
+ supersededTranscriptLines,
143
+ threadTranscriptLines,
144
+ threadTranscriptRef,
145
+ transcriptSegmentOf
146
+ };
147
+ //# sourceMappingURL=transcript-format.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/calls/transcript-format.ts"],
4
+ "sourcesContent": ["/**\n * Reading stored call transcripts (light, so lists and message views can import it cheaply). A\n * transcript chat message's own format (`isTranscriptMessage`, `parseTranscriptContent`) is the\n * SDK's (`chats`). See `./transcription.ts` for how they are written.\n */\n\nimport { chats } from '@arbidocs/sdk/browser'\n\n/** The `transcript_segment` marker of a workspace thread message. */\nexport interface TranscriptSegmentMarker {\n segment_id: string\n speaker_ext_id: string\n started_at?: string | null\n}\n\n/**\n * Transcript messages in spoken order: by each line's `started_at` (when it was said), falling back to when it was\n * stored. Live lines are stored as they are spoken, but a recording's Transcribe stores one speaker track after\n * another, so storage order would list every line of one speaker before the next speaker's.\n */\nexport function sortTranscriptMessages<\n T extends { content?: string | null; created_at: string; decryptFailed?: boolean },\n>(messages: readonly T[]): T[] {\n const spokenAt = (m: T) => {\n const parsed = m.decryptFailed ? null : chats.parseTranscriptContent(m.content)\n const at = Date.parse(parsed?.started_at ?? m.created_at)\n return Number.isNaN(at) ? 0 : at\n }\n return messages\n .map((m, i) => ({ m, i, at: spokenAt(m) }))\n .sort((a, b) => a.at - b.at || a.i - b.i)\n .map(({ m }) => m)\n}\n\n/**\n * The `transcript_segment` marker of a thread message's `tools` (keyed by tool name, like\n * `workflow_step`), if it carries one.\n */\nexport function transcriptSegmentOf(tools: unknown): TranscriptSegmentMarker | undefined {\n if (!tools || typeof tools !== 'object') return undefined\n const record = tools as Record<string, unknown>\n const byKey = record.transcript_segment\n const candidates = byKey ? [byKey] : Object.values(record)\n for (const c of candidates) {\n if (!c || typeof c !== 'object') continue\n const t = c as Partial<TranscriptSegmentMarker> & { name?: unknown }\n if (c !== byKey && t.name !== 'transcript_segment') continue\n if (typeof t.segment_id !== 'string' || typeof t.speaker_ext_id !== 'string') continue\n return {\n segment_id: t.segment_id,\n speaker_ext_id: t.speaker_ext_id,\n started_at: typeof t.started_at === 'string' ? t.started_at : null,\n }\n }\n return undefined\n}\n\n/** One line of an exported transcript. */\nexport interface TranscriptExportLine {\n speaker: string\n /** ISO time the segment started; null when unknown. */\n at: string | null\n text: string\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0')\n\n/** `hh:mm:ss` in local time, or '' for a missing/invalid time. */\nexport function clockTime(iso: string | null | undefined): string {\n if (!iso) return ''\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return ''\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n}\n\n/**\n * A meeting transcript as ONE markdown comment: title, date, then `Speaker [hh:mm:ss]: text`\n * lines in time order (the host's \"Save transcript to thread\").\n */\nexport function formatTranscriptMarkdown(opts: {\n title: string | null | undefined\n /** The meeting's date (first line's time when omitted). */\n date?: Date | null\n lines: TranscriptExportLine[]\n}): string {\n const lines = [...opts.lines]\n .filter((l) => l.text.trim())\n .sort((a, b) => (Date.parse(a.at ?? '') || 0) - (Date.parse(b.at ?? '') || 0))\n const first = lines.find((l) => l.at)?.at\n const date = opts.date ?? (first ? new Date(first) : null)\n const heading = `## Transcript: ${opts.title?.trim() || 'Meeting'}`\n const dateLine = date\n ? `_${date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}_`\n : null\n const body = lines.map((l) => {\n const time = clockTime(l.at)\n // One paragraph per line; collapse inner newlines so a line never breaks the layout.\n return `**${l.speaker}**${time ? ` [${time}]` : ''}: ${l.text.trim().replace(/\\s*\\n\\s*/g, ' ')}`\n })\n return [heading, ...(dateLine ? [dateLine] : []), ...body].join('\\n\\n')\n}\n\n/**\n * A workspace meeting thread's transcript: its `transcript_segment` comments as export lines (the\n * speaker from the members list, the text without its \"Name: \" prefix), deduped by segment id.\n */\nexport function threadTranscriptLines(\n messages: { content?: string | null; created_at?: string | null; tools?: unknown }[],\n nameOf: (speakerExtId: string) => string | null\n): TranscriptExportLine[] {\n const seen = new Set<string>()\n const lines: TranscriptExportLine[] = []\n for (const m of messages) {\n const marker = transcriptSegmentOf(m.tools)\n if (!marker || seen.has(marker.segment_id)) continue\n seen.add(marker.segment_id)\n const name = nameOf(marker.speaker_ext_id)\n lines.push({\n speaker: name || 'Former member',\n at: marker.started_at ?? m.created_at ?? null,\n text: stripSpeakerPrefix(m.content ?? '', name),\n })\n }\n return lines\n}\n\n/** A thread comment's text (\"Name: text\") without its speaker prefix. */\nexport function stripSpeakerPrefix(content: string, speakerName: string | null): string {\n if (speakerName && content.startsWith(`${speakerName}: `)) {\n return content.slice(speakerName.length + 2)\n }\n return content\n}\n\n// \u2500\u2500 A recording's transcript supersedes the live one \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** The segment id of a line transcribed from a recording (`rec-<track>-\u2026`), not live. */\nexport function isRecordingSegmentId(segmentId: string | null | undefined): boolean {\n return typeof segmentId === 'string' && segmentId.startsWith('rec-')\n}\n\n/** A recording's time window and its tracks (from `GET /v1/calls/{id}/recordings`). */\nexport interface RecordingWindow {\n trackExtIds: readonly string[]\n /** ISO start of the recording. */\n startedAt: string\n /** ISO stop of the recording; null while it records (open-ended). */\n stoppedAt: string | null\n}\n\n/** The recordings of a call as windows. */\nexport function recordingWindowsOf(\n recordings: readonly {\n started_at: string\n stopped_at?: string | null\n tracks?: readonly { external_id: string }[] | null\n }[]\n): RecordingWindow[] {\n return recordings.map((r) => ({\n trackExtIds: (r.tracks ?? []).map((t) => t.external_id),\n startedAt: r.started_at,\n stoppedAt: r.stopped_at ?? null,\n }))\n}\n\n/** What the supersede rule needs of a transcript line; null for a message that is not one. */\nexport interface TranscriptLineRef {\n segmentId: string | null | undefined\n /** ISO time the line was spoken (or stored). */\n startedAt: string | null | undefined\n}\n\n/** A transcript chat message (E2E meeting chat): its `dedupe_key` is the segment id. */\nexport function chatTranscriptRef(message: {\n kind?: string | null\n content?: string | null\n created_at: string\n dedupe_key?: string | null\n decryptFailed?: boolean\n}): TranscriptLineRef | null {\n if (!chats.isTranscriptMessage(message)) return null\n const parsed = message.decryptFailed ? null : chats.parseTranscriptContent(message.content)\n return { segmentId: message.dedupe_key, startedAt: parsed?.started_at ?? message.created_at }\n}\n\n/** A workspace meeting thread message with a `transcript_segment` marker. */\nexport function threadTranscriptRef(message: {\n created_at?: string | null\n tools?: unknown\n meta?: { tools?: unknown } | null\n}): TranscriptLineRef | null {\n const marker = transcriptSegmentOf(message.tools ?? message.meta?.tools)\n if (!marker) return null\n return { segmentId: marker.segment_id, startedAt: marker.started_at ?? message.created_at }\n}\n\n/**\n * The LIVE transcript lines a recording's transcript supersedes. Transcribing a recording stores its\n * lines (`rec-\u2026` segment ids) beside the live ones of the same speech, so both would show. For each\n * recording that has transcript lines, the live lines spoken inside its [started_at, stopped_at]\n * window are superseded; without a recording transcript, the live lines stand.\n *\n * A `rec-` line of a recording not in `recordings` (the list did not load) still supersedes: its\n * window is then the span of those lines' own times.\n *\n * `refOf` returns null for a message that is not a transcript line (never superseded).\n */\nexport function supersededTranscriptLines<T>(\n lines: readonly T[],\n refOf: (line: T) => TranscriptLineRef | null,\n recordings: readonly RecordingWindow[] = []\n): Set<T> {\n const superseded = new Set<T>()\n const recLines: { segmentId: string; at: number }[] = []\n for (const line of lines) {\n const ref = refOf(line)\n if (ref && isRecordingSegmentId(ref.segmentId)) {\n recLines.push({ segmentId: ref.segmentId as string, at: Date.parse(ref.startedAt ?? '') })\n }\n }\n if (!recLines.length) return superseded\n\n const windows: [number, number][] = []\n const claimed = new Set<string>()\n for (const r of recordings) {\n const prefixes = r.trackExtIds.map((t) => `rec-${t}-`)\n const mine = recLines.filter((l) => prefixes.some((p) => l.segmentId.startsWith(p)))\n if (!mine.length) continue\n for (const l of mine) claimed.add(l.segmentId)\n const start = Date.parse(r.startedAt)\n const stop = r.stoppedAt ? Date.parse(r.stoppedAt) : Number.POSITIVE_INFINITY\n if (!Number.isNaN(start)) windows.push([start, Number.isNaN(stop) ? Infinity : stop])\n }\n const unclaimed = recLines.filter((l) => !claimed.has(l.segmentId) && !Number.isNaN(l.at))\n if (unclaimed.length) {\n const times = unclaimed.map((l) => l.at)\n windows.push([Math.min(...times), Math.max(...times)])\n }\n if (!windows.length) return superseded\n\n for (const line of lines) {\n const ref = refOf(line)\n if (!ref || isRecordingSegmentId(ref.segmentId)) continue\n const at = Date.parse(ref.startedAt ?? '')\n if (Number.isNaN(at)) continue\n if (windows.some(([start, stop]) => at >= start && at <= stop)) superseded.add(line)\n }\n return superseded\n}\n\n/** `lines` without the live lines a recording's transcript supersedes (see above). */\nexport function supersedeLiveTranscript<T>(\n lines: readonly T[],\n refOf: (line: T) => TranscriptLineRef | null,\n recordings: readonly RecordingWindow[] = []\n): T[] {\n const superseded = supersededTranscriptLines(lines, refOf, recordings)\n return superseded.size ? lines.filter((l) => !superseded.has(l)) : [...lines]\n}\n\n/** Whether any of these messages is a line transcribed from a recording. */\nexport function hasRecordingTranscript<T>(\n lines: readonly T[],\n refOf: (line: T) => TranscriptLineRef | null\n): boolean {\n return lines.some((l) => isRecordingSegmentId(refOf(l)?.segmentId))\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,101 @@
1
+ import { decryptWithChatKey, encryptWithChatKey } from "@arbidocs/client";
2
+ import { chatByExtId } from "./in-call-chat.js";
3
+ import { ensureMeetingChat } from "./meeting-chat.js";
4
+ const CALL_CAPTION_TOPIC = "arbi.caption";
5
+ const CALL_TRANSCRIPTION_TOPIC = "arbi.transcription";
6
+ const CAPTION_MAX_CHARS = 2e3;
7
+ const LIVE_SEGMENTER = { minVoiceMs: 400, holdShortMs: 1e3 };
8
+ const encoder = new TextEncoder();
9
+ const decoder = new TextDecoder();
10
+ const SEGMENT_ID_PATTERN = /^[A-Za-z0-9_-]{8,64}$/;
11
+ function newSegmentId() {
12
+ const bytes = new Uint8Array(12);
13
+ globalThis.crypto.getRandomValues(bytes);
14
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
15
+ }
16
+ async function encodeCaptionPacket(packet, callKey) {
17
+ return encoder.encode(await encryptWithChatKey(JSON.stringify(packet), callKey));
18
+ }
19
+ async function decodeCaptionPacket(payload, callKey) {
20
+ try {
21
+ const parsed = JSON.parse(await decryptWithChatKey(decoder.decode(payload), callKey));
22
+ if (!parsed || typeof parsed !== "object") return null;
23
+ const p = parsed;
24
+ if (p.v !== 1 || typeof p.segment_id !== "string" || !SEGMENT_ID_PATTERN.test(p.segment_id) || typeof p.text !== "string" || typeof p.identity !== "string") {
25
+ return null;
26
+ }
27
+ const text = p.text.trim().slice(0, CAPTION_MAX_CHARS);
28
+ if (!text) return null;
29
+ return {
30
+ v: 1,
31
+ segment_id: p.segment_id,
32
+ text,
33
+ identity: p.identity,
34
+ name: typeof p.name === "string" ? p.name : p.identity,
35
+ t: typeof p.t === "number" ? p.t : Date.now(),
36
+ ...p.proxy === true ? { proxy: true } : {}
37
+ };
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ function transcriptPersistRole(params) {
43
+ if (!params.canPost || !params.hasCallKey) return null;
44
+ if (params.speakerIdentity === params.myIdentity) return "own";
45
+ if (params.speakerNeedsProxy) return "proxy";
46
+ return null;
47
+ }
48
+ function threadTranscriptText(segment) {
49
+ return `${segment.speakerName}: ${segment.text}`;
50
+ }
51
+ async function persistTranscriptSegment(arbi, queryClient, callExtId, callKey, segment) {
52
+ const ref = await ensureMeetingChat(arbi, queryClient, callExtId, callKey);
53
+ await storeTranscriptSegment(arbi, queryClient, ref, segment);
54
+ return ref;
55
+ }
56
+ async function storeTranscriptSegment(arbi, queryClient, ref, segment) {
57
+ if (ref.kind === "chat") {
58
+ const chat = await arbi.chats.ready(await chatByExtId(arbi, queryClient, ref.chatExtId));
59
+ const ring = await arbi.chats.ring(chat);
60
+ const key = ring.keys.get(ring.currentVersion);
61
+ if (!key) throw new Error("No key for the meeting chat");
62
+ const content = {
63
+ text: segment.text,
64
+ speaker_identity: segment.speakerIdentity,
65
+ speaker_name: segment.speakerName,
66
+ started_at: segment.startedAt
67
+ };
68
+ await arbi.calls.transcription.postChatLine(ref.chatExtId, {
69
+ content: await encryptWithChatKey(JSON.stringify(content), key),
70
+ key_version: ring.currentVersion,
71
+ dedupe_key: segment.segmentId
72
+ });
73
+ return;
74
+ }
75
+ const transcript = {
76
+ segment_id: segment.segmentId,
77
+ speaker_ext_id: segment.speakerIdentity,
78
+ started_at: segment.startedAt
79
+ };
80
+ await arbi.conversations.postMessage({
81
+ content: threadTranscriptText(segment),
82
+ conversation_ext_id: ref.conversationExtId,
83
+ assistant_mode: "mentioned",
84
+ transcript
85
+ });
86
+ }
87
+ export {
88
+ CALL_CAPTION_TOPIC,
89
+ CALL_TRANSCRIPTION_TOPIC,
90
+ CAPTION_MAX_CHARS,
91
+ LIVE_SEGMENTER,
92
+ SEGMENT_ID_PATTERN,
93
+ decodeCaptionPacket,
94
+ encodeCaptionPacket,
95
+ newSegmentId,
96
+ persistTranscriptSegment,
97
+ storeTranscriptSegment,
98
+ threadTranscriptText,
99
+ transcriptPersistRole
100
+ };
101
+ //# sourceMappingURL=transcription.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/calls/transcription.ts"],
4
+ "sourcesContent": ["/**\n * Live call transcription (ARBI `docs/meeting-chats-plan.md` \u00A75): captions over the data channel\n * and transcript persistence into the call's meeting chat.\n *\n * Attribution is by origin: a participant's browser transcribes only its own microphone, so the\n * speaker is whoever sent the audio \u2014 there is no diarization.\n *\n * Captions: the speaker's client broadcasts `{segment_id, text, identity, name, t}` on topic\n * {@link CALL_CAPTION_TOPIC}, sealed under the call key K exactly like an in-call chat packet, so\n * the SFU only forwards ciphertext. The transcription state itself is announced by the SERVER on\n * {@link CALL_TRANSCRIPTION_TOPIC} (plaintext; it carries no content).\n *\n * Persistence: the speaker stores its own segments. A speaker who cannot post to the meeting chat (a\n * workspace guest on a thread call: read-only) marks its captions `proxy`, and every member that can\n * post stores them instead \u2014 idempotent by the segment id (`dedupe_key` in a chat, the `transcript`\n * marker in a thread), so each is stored once whichever member wins.\n */\n\nimport { decryptWithChatKey, encryptWithChatKey } from '@arbidocs/client'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi, calls, chats } from '@arbidocs/sdk/browser'\nimport { chatByExtId } from './in-call-chat'\nimport { ensureMeetingChat, type MeetingChatRef } from './meeting-chat'\n\nexport const CALL_CAPTION_TOPIC = 'arbi.caption'\n/** Server-sent: `{on, by_identity, by_name}`. */\nexport const CALL_TRANSCRIPTION_TOPIC = 'arbi.transcription'\nexport const CAPTION_MAX_CHARS = 2000\n/**\n * Voice-activity tuning for live call speech: the shared 700 ms pause rule, but a segment needs only\n * 400 ms of voice, and a segment still too short waits 1 s more for the rest of a short phrase\n * (\"Perfect.\" \u2026 \"Thank you both.\") so a closing line is not dropped as two blips.\n */\nexport const LIVE_SEGMENTER = { minVoiceMs: 400, holdShortMs: 1_000 } as const\n\n/** One caption over the data channel, encrypted under K. */\nexport interface CaptionPacket {\n v: 1\n segment_id: string\n text: string\n /** The speaker's LiveKit identity (checked against the packet's sender on receipt). */\n identity: string\n name: string\n /** When the segment started, ms since epoch. */\n t: number\n /** The speaker cannot post to the meeting chat: members store this segment for them. */\n proxy?: boolean\n}\n\n/** A caption on screen. */\nexport interface CaptionLine {\n segmentId: string\n identity: string\n name: string\n text: string\n /** Segment start, ms since epoch. */\n t: number\n mine: boolean\n /** Local receipt time (drives the fade). */\n receivedAt: number\n}\n\n/** A transcript segment to store. */\nexport interface TranscriptSegment {\n segmentId: string\n text: string\n speakerIdentity: string\n speakerName: string\n /** ISO start of the segment. */\n startedAt: string | null\n}\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\nexport const SEGMENT_ID_PATTERN = /^[A-Za-z0-9_-]{8,64}$/\n\n/** A fresh segment id (`^[A-Za-z0-9_-]{8,64}$`). */\nexport function newSegmentId(): string {\n const bytes = new Uint8Array(12)\n globalThis.crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n// \u2500\u2500 Captions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function encodeCaptionPacket(\n packet: CaptionPacket,\n callKey: Uint8Array\n): Promise<Uint8Array<ArrayBuffer>> {\n return encoder.encode(await encryptWithChatKey(JSON.stringify(packet), callKey))\n}\n\n/** Open a received caption; null when it is not under K or malformed. */\nexport async function decodeCaptionPacket(\n payload: Uint8Array,\n callKey: Uint8Array\n): Promise<CaptionPacket | null> {\n try {\n const parsed: unknown = JSON.parse(await decryptWithChatKey(decoder.decode(payload), callKey))\n if (!parsed || typeof parsed !== 'object') return null\n const p = parsed as Partial<CaptionPacket>\n if (\n p.v !== 1 ||\n typeof p.segment_id !== 'string' ||\n !SEGMENT_ID_PATTERN.test(p.segment_id) ||\n typeof p.text !== 'string' ||\n typeof p.identity !== 'string'\n ) {\n return null\n }\n const text = p.text.trim().slice(0, CAPTION_MAX_CHARS)\n if (!text) return null\n return {\n v: 1,\n segment_id: p.segment_id,\n text,\n identity: p.identity,\n name: typeof p.name === 'string' ? p.name : p.identity,\n t: typeof p.t === 'number' ? p.t : Date.now(),\n ...(p.proxy === true ? { proxy: true } : {}),\n }\n } catch {\n return null\n }\n}\n\n// \u2500\u2500 Persistence routing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Who stores a segment:\n * - `own`: my own segment, and I can post to the meeting chat;\n * - `proxy`: someone else's segment marked `proxy` (they cannot post: a workspace guest), and I\n * can post \u2014 every such member stores it, the server dedupes by segment id;\n * - null: the speaker stores it themselves, or I cannot post (read-only, or no call key to open\n * the meeting chat with). My own segment then goes out marked `proxy` for members to store.\n */\nexport function transcriptPersistRole(params: {\n myIdentity: string\n /** I can post to the meeting chat (not a workspace guest of a thread call). */\n canPost: boolean\n hasCallKey: boolean\n speakerIdentity: string\n /** The caption was marked `proxy` by its speaker. */\n speakerNeedsProxy: boolean\n}): 'own' | 'proxy' | null {\n if (!params.canPost || !params.hasCallKey) return null\n if (params.speakerIdentity === params.myIdentity) return 'own'\n if (params.speakerNeedsProxy) return 'proxy'\n return null\n}\n\n/** The thread comment text of a segment (\"Name: text\"). */\nexport function threadTranscriptText(segment: TranscriptSegment): string {\n return `${segment.speakerName}: ${segment.text}`\n}\n\n/**\n * Store one segment in the call's meeting chat (made on first use): an E2E chat message of kind\n * `transcript` under the chat key, or a comment with a transcript marker in a workspace meeting\n * thread. Idempotent per segment id. Returns the chat it went to.\n *\n * In a thread the marker's `speaker_ext_id` is the speaker: the server accepts it from the speaker,\n * or from a member when the speaker is a guest of the workspace (422 `speaker_mismatch` otherwise).\n */\nexport async function persistTranscriptSegment(\n arbi: Arbi,\n queryClient: QueryClient,\n callExtId: string,\n callKey: Uint8Array,\n segment: TranscriptSegment\n): Promise<MeetingChatRef> {\n const ref = await ensureMeetingChat(arbi, queryClient, callExtId, callKey)\n await storeTranscriptSegment(arbi, queryClient, ref, segment)\n return ref\n}\n\n/**\n * Store one segment in a known meeting chat (see {@link persistTranscriptSegment}); also used for\n * the lines transcribed from a recording (segment ids `rec-<track>-<seq>`).\n */\nexport async function storeTranscriptSegment(\n arbi: Arbi,\n queryClient: QueryClient,\n ref: MeetingChatRef,\n segment: TranscriptSegment\n): Promise<void> {\n if (ref.kind === 'chat') {\n const chat = await arbi.chats.ready(await chatByExtId(arbi, queryClient, ref.chatExtId))\n const ring = await arbi.chats.ring(chat)\n const key = ring.keys.get(ring.currentVersion)\n if (!key) throw new Error('No key for the meeting chat')\n const content: chats.TranscriptContent = {\n text: segment.text,\n speaker_identity: segment.speakerIdentity,\n speaker_name: segment.speakerName,\n started_at: segment.startedAt,\n }\n await arbi.calls.transcription.postChatLine(ref.chatExtId, {\n content: await encryptWithChatKey(JSON.stringify(content), key),\n key_version: ring.currentVersion,\n dedupe_key: segment.segmentId,\n })\n return\n }\n const transcript: calls.TranscriptSegmentRef = {\n segment_id: segment.segmentId,\n speaker_ext_id: segment.speakerIdentity,\n started_at: segment.startedAt,\n }\n // A comment in the workspace meeting thread, idempotent per segment. The server takes it from its\n // speaker, or from a member for a speaker with the workspace guest role.\n await arbi.conversations.postMessage({\n content: threadTranscriptText(segment),\n conversation_ext_id: ref.conversationExtId,\n assistant_mode: 'mentioned',\n transcript,\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ import { decryptCallTitle, encryptCallTitle } from "@arbidocs/client";
2
+ import { joinFromPreJoin } from "./actions.js";
3
+ import { callSession } from "./session.js";
4
+ const CALL_WEBINAR_TOPIC = "arbi.webinar";
5
+ const AUDIENCE_CHOICES = { audioEnabled: false, videoEnabled: false };
6
+ const isHand = (h) => !!h && typeof h === "object" && typeof h.identity === "string" && typeof h.raised_at === "string";
7
+ function parseWebinarPacket(payload, fromParticipant) {
8
+ if (fromParticipant) return null;
9
+ let raw;
10
+ try {
11
+ raw = JSON.parse(new TextDecoder().decode(payload));
12
+ } catch {
13
+ return null;
14
+ }
15
+ if (!raw || typeof raw !== "object") return null;
16
+ const p = raw;
17
+ switch (p.type) {
18
+ case "state":
19
+ if (typeof p.live !== "boolean") return null;
20
+ return {
21
+ type: "state",
22
+ live: p.live,
23
+ live_at: typeof p.live_at === "string" ? p.live_at : null,
24
+ chat: p.chat === "everyone" ? "everyone" : "panelists"
25
+ };
26
+ case "hands":
27
+ return {
28
+ type: "hands",
29
+ hands: Array.isArray(p.hands) ? p.hands.filter(isHand).map((h) => ({ ...h, name: String(h.name ?? "") })) : []
30
+ };
31
+ case "questions":
32
+ case "promoted":
33
+ case "demoted":
34
+ return { type: p.type };
35
+ default:
36
+ return null;
37
+ }
38
+ }
39
+ const UNREADABLE = "(This question could not be decrypted.)";
40
+ function sealQuestionText(text, key) {
41
+ return encryptCallTitle(text, key);
42
+ }
43
+ async function openQuestion(q, key) {
44
+ const [text, answerText] = await Promise.all([
45
+ decryptCallTitle(q.body, key),
46
+ q.answer ? decryptCallTitle(q.answer, key) : Promise.resolve(null)
47
+ ]);
48
+ return { ...q, text: text ?? UNREADABLE, answerText };
49
+ }
50
+ function markRejoining(callExtId, on = true) {
51
+ callSession.updateActiveCall(callExtId, { rejoining: on });
52
+ }
53
+ async function rejoinAsAudience(arbi, callExtId) {
54
+ if (callSession.getState().active?.callExtId !== callExtId) return;
55
+ markRejoining(callExtId);
56
+ try {
57
+ await joinFromPreJoin(arbi, AUDIENCE_CHOICES);
58
+ } finally {
59
+ markRejoining(callExtId, false);
60
+ }
61
+ }
62
+ export {
63
+ AUDIENCE_CHOICES,
64
+ CALL_WEBINAR_TOPIC,
65
+ markRejoining,
66
+ openQuestion,
67
+ parseWebinarPacket,
68
+ rejoinAsAudience,
69
+ sealQuestionText
70
+ };
71
+ //# sourceMappingURL=webinar.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/calls/webinar.ts"],
4
+ "sourcesContent": ["/**\n * The webinar's wire formats on the client: the server's LiveKit data messages (topic\n * `arbi.webinar`, trusted only when server-sent) and the Q&A text, end-to-end under the call key K\n * in the same secretbox format as the call title (`encryptCallTitle` / `decryptCallTitle`), and\n * joining a webinar again without leaving it.\n */\n\nimport type { Arbi, calls } from '@arbidocs/sdk/browser'\nimport { decryptCallTitle, encryptCallTitle } from '@arbidocs/client'\nimport { joinFromPreJoin } from './actions'\nimport { callSession, type JoinChoices } from './session'\n\nexport const CALL_WEBINAR_TOPIC = 'arbi.webinar'\n\n/** The audience cannot publish: no microphone, no camera, no device check. */\nexport const AUDIENCE_CHOICES: JoinChoices = { audioEnabled: false, videoEnabled: false }\n\ntype Hand = NonNullable<calls.WebinarState['hands']>[number]\n\nexport type WebinarPacket =\n | { type: 'state'; live: boolean; live_at: string | null; chat: calls.WebinarChat }\n | { type: 'hands'; hands: Hand[] }\n | { type: 'questions' }\n | { type: 'promoted' }\n | { type: 'demoted' }\n\nconst isHand = (h: unknown): h is Hand =>\n !!h &&\n typeof h === 'object' &&\n typeof (h as Hand).identity === 'string' &&\n typeof (h as Hand).raised_at === 'string'\n\n/**\n * A data packet on {@link CALL_WEBINAR_TOPIC}, or null. `fromParticipant` is whether a participant\n * sent it: only the server speaks on this topic, so anything from a participant is dropped.\n */\nexport function parseWebinarPacket(\n payload: Uint8Array,\n fromParticipant: boolean\n): WebinarPacket | null {\n if (fromParticipant) return null\n let raw: unknown\n try {\n raw = JSON.parse(new TextDecoder().decode(payload))\n } catch {\n return null\n }\n if (!raw || typeof raw !== 'object') return null\n const p = raw as Record<string, unknown>\n switch (p.type) {\n case 'state':\n if (typeof p.live !== 'boolean') return null\n return {\n type: 'state',\n live: p.live,\n live_at: typeof p.live_at === 'string' ? p.live_at : null,\n chat: p.chat === 'everyone' ? 'everyone' : 'panelists',\n }\n case 'hands':\n return {\n type: 'hands',\n hands: Array.isArray(p.hands)\n ? p.hands.filter(isHand).map((h) => ({ ...h, name: String(h.name ?? '') }))\n : [],\n }\n case 'questions':\n case 'promoted':\n case 'demoted':\n return { type: p.type }\n default:\n return null\n }\n}\n\n/** A question with its text opened under K (`null` when it does not open: shown as such). */\nexport interface OpenQuestion extends calls.CallQuestion {\n text: string\n answerText: string | null\n}\n\nconst UNREADABLE = '(This question could not be decrypted.)'\n\nexport function sealQuestionText(text: string, key: Uint8Array): Promise<string> {\n return encryptCallTitle(text, key)\n}\n\nexport async function openQuestion(q: calls.CallQuestion, key: Uint8Array): Promise<OpenQuestion> {\n const [text, answerText] = await Promise.all([\n decryptCallTitle(q.body, key),\n q.answer ? decryptCallTitle(q.answer, key) : Promise.resolve(null),\n ])\n return { ...q, text: text ?? UNREADABLE, answerText }\n}\n\n// \u2500\u2500 Joining again \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// After a moderator moved me to the audience (or I stepped down, or declined the stage) the server\n// removes me from the room, and I come straight back with a new token \u2014 hidden and listen-only,\n// because the session's stage state says so. No pre-join and no error screen: the same join path\n// as the pre-join's, with the audience's choices.\n\n/** The room I am in is about to drop me for a rejoin: its disconnect is not a leave. */\nexport function markRejoining(callExtId: string, on = true): void {\n callSession.updateActiveCall(callExtId, { rejoining: on })\n}\n\n/** Join again as the audience (the room that dropped me has already gone). */\nexport async function rejoinAsAudience(arbi: Arbi, callExtId: string): Promise<void> {\n if (callSession.getState().active?.callExtId !== callExtId) return\n markRejoining(callExtId)\n try {\n await joinFromPreJoin(arbi, AUDIENCE_CHOICES)\n } finally {\n markRejoining(callExtId, false)\n }\n}\n"],
5
+ "mappings": "AAQA,SAAS,kBAAkB,wBAAwB;AACnD,SAAS,uBAAuB;AAChC,SAAS,mBAAqC;AAEvC,MAAM,qBAAqB;AAG3B,MAAM,mBAAgC,EAAE,cAAc,OAAO,cAAc,MAAM;AAWxF,MAAM,SAAS,CAAC,MACd,CAAC,CAAC,KACF,OAAO,MAAM,YACb,OAAQ,EAAW,aAAa,YAChC,OAAQ,EAAW,cAAc;AAM5B,SAAS,mBACd,SACA,iBACsB;AACtB,MAAI,gBAAiB,QAAO;AAC5B,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,UAAQ,EAAE,MAAM;AAAA,IACd,KAAK;AACH,UAAI,OAAO,EAAE,SAAS,UAAW,QAAO;AACxC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,EAAE;AAAA,QACR,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAAA,QACrD,MAAM,EAAE,SAAS,aAAa,aAAa;AAAA,MAC7C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,MAAM,QAAQ,EAAE,KAAK,IACxB,EAAE,MAAM,OAAO,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IACxE,CAAC;AAAA,MACP;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,MAAM,EAAE,KAAK;AAAA,IACxB;AACE,aAAO;AAAA,EACX;AACF;AAQA,MAAM,aAAa;AAEZ,SAAS,iBAAiB,MAAc,KAAkC;AAC/E,SAAO,iBAAiB,MAAM,GAAG;AACnC;AAEA,eAAsB,aAAa,GAAuB,KAAwC;AAChG,QAAM,CAAC,MAAM,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,iBAAiB,EAAE,MAAM,GAAG;AAAA,IAC5B,EAAE,SAAS,iBAAiB,EAAE,QAAQ,GAAG,IAAI,QAAQ,QAAQ,IAAI;AAAA,EACnE,CAAC;AACD,SAAO,EAAE,GAAG,GAAG,MAAM,QAAQ,YAAY,WAAW;AACtD;AAUO,SAAS,cAAc,WAAmB,KAAK,MAAY;AAChE,cAAY,iBAAiB,WAAW,EAAE,WAAW,GAAG,CAAC;AAC3D;AAGA,eAAsB,iBAAiB,MAAY,WAAkC;AACnF,MAAI,YAAY,SAAS,EAAE,QAAQ,cAAc,UAAW;AAC5D,gBAAc,SAAS;AACvB,MAAI;AACF,UAAM,gBAAgB,MAAM,gBAAgB;AAAA,EAC9C,UAAE;AACA,kBAAc,WAAW,KAAK;AAAA,EAChC;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import { arbiQueryKeys } from "./hooks.js";
4
+ const SLOW_AFTER_MS = 5e3;
5
+ const POLL_EVERY_MS = 3e3;
6
+ const STILL_WORKING = "Still working \u2014 confirm in your bank's tab if it opened. We'll update here.";
7
+ function useIsSlow(isPending, ms = SLOW_AFTER_MS) {
8
+ const [isSlow, setIsSlow] = useState(false);
9
+ useEffect(() => {
10
+ if (!isPending) {
11
+ setIsSlow(false);
12
+ return;
13
+ }
14
+ const timer = setTimeout(() => setIsSlow(true), ms);
15
+ return () => clearTimeout(timer);
16
+ }, [isPending, ms]);
17
+ return isSlow;
18
+ }
19
+ function useChargeWatch(project, isPending) {
20
+ const queryClient = useQueryClient();
21
+ const isSlow = useIsSlow(isPending);
22
+ const watchRef = useRef(null);
23
+ useEffect(() => {
24
+ if (!isSlow) return;
25
+ const timer = setInterval(
26
+ () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.projects(), exact: true }),
27
+ POLL_EVERY_MS
28
+ );
29
+ return () => clearInterval(timer);
30
+ }, [isSlow, queryClient]);
31
+ const settle = useCallback((ok, onNotLanded) => {
32
+ const watch2 = watchRef.current;
33
+ if (!watch2 || watch2.settled) return;
34
+ watch2.settled = true;
35
+ if (ok) watch2.onLanded();
36
+ else onNotLanded?.();
37
+ }, []);
38
+ useEffect(() => {
39
+ const watch2 = watchRef.current;
40
+ if (watch2 && !watch2.settled && watch2.landed(project)) settle(true);
41
+ }, [project, settle]);
42
+ const watch = useCallback((landed, onLanded) => {
43
+ watchRef.current = { landed, onLanded, settled: false };
44
+ }, []);
45
+ const succeeded = useCallback(() => settle(true), [settle]);
46
+ const refused = useCallback(() => settle(false), [settle]);
47
+ const settleFailure = useCallback(
48
+ async (onNotLanded) => {
49
+ const watch2 = watchRef.current;
50
+ if (!watch2 || watch2.settled) return;
51
+ let fresh;
52
+ try {
53
+ await queryClient.refetchQueries({ queryKey: arbiQueryKeys.projects(), exact: true });
54
+ fresh = queryClient.getQueryData(arbiQueryKeys.projects())?.find((p) => p.external_id === project.external_id);
55
+ } catch {
56
+ fresh = void 0;
57
+ }
58
+ settle(!!fresh && watch2.landed(fresh), onNotLanded);
59
+ },
60
+ [queryClient, project.external_id, settle]
61
+ );
62
+ return { isSlow, watch, succeeded, refused, settleFailure };
63
+ }
64
+ export {
65
+ POLL_EVERY_MS,
66
+ SLOW_AFTER_MS,
67
+ STILL_WORKING,
68
+ useChargeWatch,
69
+ useIsSlow
70
+ };
71
+ //# sourceMappingURL=charge-watch.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/charge-watch.ts"],
4
+ "sourcesContent": ["/**\n * useChargeWatch \u2014 feedback for a money action that can take a while (\"Paying\u2026\", \"Upgrading\u2026\").\n *\n * - After 5 s pending, `isSlow` turns on (show STILL_WORKING) and the projects list is refetched\n * every 3 s, so a change that lands while the request is still open shows up here.\n * - `watch(landed, onLanded)` at press time: `landed(project)` says whether the change shows on\n * the project. The first time it does, `onLanded` runs once (from a poll, the request's success,\n * or a check after a failure), so success is never reported twice.\n * - `settleFailure(onNotLanded)` after an error that doesn't say what happened (timeout, 5xx):\n * refetch, and report success if the change landed after all; otherwise `onNotLanded`.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { ProjectResponse } from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from './hooks'\n\nexport const SLOW_AFTER_MS = 5000\nexport const POLL_EVERY_MS = 3000\nexport const STILL_WORKING =\n \"Still working \u2014 confirm in your bank's tab if it opened. We'll update here.\"\n\n/** True once `isPending` has lasted `ms`. */\nexport function useIsSlow(isPending: boolean, ms = SLOW_AFTER_MS): boolean {\n const [isSlow, setIsSlow] = useState(false)\n useEffect(() => {\n if (!isPending) {\n setIsSlow(false)\n return\n }\n const timer = setTimeout(() => setIsSlow(true), ms)\n return () => clearTimeout(timer)\n }, [isPending, ms])\n return isSlow\n}\n\ninterface Watch {\n landed: (project: ProjectResponse) => boolean\n onLanded: () => void\n settled: boolean\n}\n\nexport function useChargeWatch(project: ProjectResponse, isPending: boolean) {\n const queryClient = useQueryClient()\n const isSlow = useIsSlow(isPending)\n const watchRef = useRef<Watch | null>(null)\n\n useEffect(() => {\n if (!isSlow) return\n const timer = setInterval(\n () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.projects(), exact: true }),\n POLL_EVERY_MS\n )\n return () => clearInterval(timer)\n }, [isSlow, queryClient])\n\n const settle = useCallback((ok: boolean, onNotLanded?: () => void) => {\n const watch = watchRef.current\n if (!watch || watch.settled) return\n watch.settled = true\n if (ok) watch.onLanded()\n else onNotLanded?.()\n }, [])\n\n // A refetched project that shows the change settles the action, request or no request.\n useEffect(() => {\n const watch = watchRef.current\n if (watch && !watch.settled && watch.landed(project)) settle(true)\n }, [project, settle])\n\n const watch = useCallback((landed: Watch['landed'], onLanded: Watch['onLanded']) => {\n watchRef.current = { landed, onLanded, settled: false }\n }, [])\n\n /** The request succeeded. */\n const succeeded = useCallback(() => settle(true), [settle])\n\n /** The request failed with a known refusal: nothing changed. */\n const refused = useCallback(() => settle(false), [settle])\n\n const settleFailure = useCallback(\n async (onNotLanded: () => void) => {\n const watch = watchRef.current\n if (!watch || watch.settled) return\n let fresh: ProjectResponse | undefined\n try {\n await queryClient.refetchQueries({ queryKey: arbiQueryKeys.projects(), exact: true })\n fresh = queryClient\n .getQueryData<ProjectResponse[]>(arbiQueryKeys.projects())\n ?.find((p) => p.external_id === project.external_id)\n } catch {\n fresh = undefined\n }\n settle(!!fresh && watch.landed(fresh), onNotLanded)\n },\n [queryClient, project.external_id, settle]\n )\n\n return { isSlow, watch, succeeded, refused, settleFailure }\n}\n"],
5
+ "mappings": "AAYA,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AACzD,SAAS,sBAAsB;AAE/B,SAAS,qBAAqB;AAEvB,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,gBACX;AAGK,SAAS,UAAU,WAAoB,KAAK,eAAwB;AACzE,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,YAAU,MAAM;AACd,QAAI,CAAC,WAAW;AACd,gBAAU,KAAK;AACf;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,MAAM,UAAU,IAAI,GAAG,EAAE;AAClD,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,WAAW,EAAE,CAAC;AAClB,SAAO;AACT;AAQO,SAAS,eAAe,SAA0B,WAAoB;AAC3E,QAAM,cAAc,eAAe;AACnC,QAAM,SAAS,UAAU,SAAS;AAClC,QAAM,WAAW,OAAqB,IAAI;AAE1C,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ;AAAA,MACZ,MAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,SAAS,GAAG,OAAO,KAAK,CAAC;AAAA,MACvF;AAAA,IACF;AACA,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,QAAQ,WAAW,CAAC;AAExB,QAAM,SAAS,YAAY,CAAC,IAAa,gBAA6B;AACpE,UAAMA,SAAQ,SAAS;AACvB,QAAI,CAACA,UAASA,OAAM,QAAS;AAC7B,IAAAA,OAAM,UAAU;AAChB,QAAI,GAAI,CAAAA,OAAM,SAAS;AAAA,QAClB,eAAc;AAAA,EACrB,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,UAAMA,SAAQ,SAAS;AACvB,QAAIA,UAAS,CAACA,OAAM,WAAWA,OAAM,OAAO,OAAO,EAAG,QAAO,IAAI;AAAA,EACnE,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,QAAM,QAAQ,YAAY,CAAC,QAAyB,aAAgC;AAClF,aAAS,UAAU,EAAE,QAAQ,UAAU,SAAS,MAAM;AAAA,EACxD,GAAG,CAAC,CAAC;AAGL,QAAM,YAAY,YAAY,MAAM,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;AAG1D,QAAM,UAAU,YAAY,MAAM,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC;AAEzD,QAAM,gBAAgB;AAAA,IACpB,OAAO,gBAA4B;AACjC,YAAMA,SAAQ,SAAS;AACvB,UAAI,CAACA,UAASA,OAAM,QAAS;AAC7B,UAAI;AACJ,UAAI;AACF,cAAM,YAAY,eAAe,EAAE,UAAU,cAAc,SAAS,GAAG,OAAO,KAAK,CAAC;AACpF,gBAAQ,YACL,aAAgC,cAAc,SAAS,CAAC,GACvD,KAAK,CAAC,MAAM,EAAE,gBAAgB,QAAQ,WAAW;AAAA,MACvD,QAAQ;AACN,gBAAQ;AAAA,MACV;AACA,aAAO,CAAC,CAAC,SAASA,OAAM,OAAO,KAAK,GAAG,WAAW;AAAA,IACpD;AAAA,IACA,CAAC,aAAa,QAAQ,aAAa,MAAM;AAAA,EAC3C;AAEA,SAAO,EAAE,QAAQ,OAAO,WAAW,SAAS,cAAc;AAC5D;",
6
+ "names": ["watch"]
7
+ }
@@ -0,0 +1,146 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { memo, useState } from "react";
3
+ import { Trash2, Check, CheckCheck, Link } from "lucide-react";
4
+ import { cn } from "../lib/utils.js";
5
+ const TypingIndicator = memo(function TypingIndicator2() {
6
+ return /* @__PURE__ */ jsx("div", { className: "flex w-full justify-start mb-2", "data-testid": "dm-typing-indicator", children: /* @__PURE__ */ jsx("div", { className: "bg-card border border-primary rounded-2xl rounded-bl-md px-4 py-2.5", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-1 items-center", children: [
7
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:0ms]" }),
8
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:150ms]" }),
9
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:300ms]" })
10
+ ] }) }) });
11
+ });
12
+ const ChatBubble = memo(function ChatBubble2({
13
+ message,
14
+ timestamp,
15
+ isSent,
16
+ deleted,
17
+ read,
18
+ onDelete,
19
+ onCopyLink,
20
+ id,
21
+ isLastOfRun = true,
22
+ senderName,
23
+ classNames,
24
+ renderMessage = (m) => m,
25
+ formatTimestamp = (t) => t,
26
+ attachments,
27
+ "data-testid": testId
28
+ }) {
29
+ const [isHovered, setIsHovered] = useState(false);
30
+ const [isFocused, setIsFocused] = useState(false);
31
+ const showActions = isHovered || isFocused;
32
+ if (deleted) {
33
+ return /* @__PURE__ */ jsx(
34
+ "div",
35
+ {
36
+ id,
37
+ "data-testid": testId,
38
+ className: `flex w-full ${isSent ? "justify-end" : "justify-start"} mb-2`,
39
+ children: /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground italic px-3 py-1", children: "Message deleted" })
40
+ }
41
+ );
42
+ }
43
+ const bubbleRadius = cn(
44
+ "rounded-2xl",
45
+ isSent && isLastOfRun && "rounded-br-sm",
46
+ !isSent && isLastOfRun && "rounded-bl-sm"
47
+ );
48
+ const bubbleSurface = isSent ? cn("bg-ai-accent-soft text-foreground chat-bubble-sent", classNames?.ownBubble) : cn("border border-border bg-card text-card-foreground", classNames?.peerBubble);
49
+ const copyLinkButton = onCopyLink && /* @__PURE__ */ jsx(
50
+ "button",
51
+ {
52
+ onClick: onCopyLink,
53
+ onFocus: () => setIsFocused(true),
54
+ onBlur: () => setIsFocused(false),
55
+ className: cn(
56
+ "self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded",
57
+ showActions ? "opacity-100 text-foreground" : "opacity-0 text-muted-foreground"
58
+ ),
59
+ "aria-label": "Copy link to this message",
60
+ children: /* @__PURE__ */ jsx(Link, { className: "w-3.5 h-3.5" })
61
+ }
62
+ );
63
+ return /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ id,
67
+ "data-testid": testId,
68
+ className: cn(
69
+ "flex w-full items-end",
70
+ isLastOfRun ? "mb-2" : "mb-0.5",
71
+ isSent ? "justify-end" : "justify-start"
72
+ ),
73
+ onMouseEnter: () => setIsHovered(true),
74
+ onMouseLeave: () => setIsHovered(false),
75
+ children: [
76
+ isSent && (copyLinkButton || onDelete) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 mr-1", children: [
77
+ copyLinkButton,
78
+ onDelete && /* @__PURE__ */ jsx(
79
+ "button",
80
+ {
81
+ onClick: onDelete,
82
+ onFocus: () => setIsFocused(true),
83
+ onBlur: () => setIsFocused(false),
84
+ className: cn(
85
+ "self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded",
86
+ showActions ? "opacity-100 text-destructive" : "opacity-0 text-muted-foreground"
87
+ ),
88
+ "aria-label": "Delete message",
89
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
90
+ }
91
+ )
92
+ ] }),
93
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col max-w-[80%] md:max-w-[60%]", children: /* @__PURE__ */ jsxs(
94
+ "div",
95
+ {
96
+ className: cn(
97
+ "px-3.5 py-2 break-words shadow-sm transition-shadow",
98
+ bubbleRadius,
99
+ bubbleSurface
100
+ ),
101
+ children: [
102
+ (message || !attachments) && /* @__PURE__ */ jsx("div", { className: "text-sm [&_.markdown-content]:space-y-1.5 [&_pre]:max-w-full [&_pre]:overflow-x-auto", children: renderMessage(message) }),
103
+ attachments && /* @__PURE__ */ jsx("div", { className: cn(message && "mt-1.5"), children: attachments }),
104
+ isLastOfRun && /* @__PURE__ */ jsxs(
105
+ "div",
106
+ {
107
+ className: cn(
108
+ "flex items-center gap-1.5 mt-0.5",
109
+ isSent ? "justify-end" : "justify-start"
110
+ ),
111
+ children: [
112
+ senderName && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium leading-none opacity-90", children: senderName }),
113
+ /* @__PURE__ */ jsx("span", { className: "text-xs leading-none opacity-70", children: formatTimestamp(timestamp) }),
114
+ isSent && (read ? /* @__PURE__ */ jsx(CheckCheck, { className: "w-3.5 h-3.5 flex-shrink-0 opacity-80" }) : /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 flex-shrink-0 opacity-60" }))
115
+ ]
116
+ }
117
+ )
118
+ ]
119
+ }
120
+ ) }),
121
+ !isSent && (onDelete || copyLinkButton) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 ml-1", children: [
122
+ onDelete && /* @__PURE__ */ jsx(
123
+ "button",
124
+ {
125
+ onClick: onDelete,
126
+ onFocus: () => setIsFocused(true),
127
+ onBlur: () => setIsFocused(false),
128
+ className: cn(
129
+ "self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded",
130
+ showActions ? "opacity-100 text-destructive" : "opacity-0 text-muted-foreground"
131
+ ),
132
+ "aria-label": "Delete message",
133
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
134
+ }
135
+ ),
136
+ copyLinkButton
137
+ ] })
138
+ ]
139
+ }
140
+ );
141
+ });
142
+ export {
143
+ ChatBubble,
144
+ TypingIndicator
145
+ };
146
+ //# sourceMappingURL=ChatBubble.js.map