@arbidocs/react 0.5.110 → 0.5.112

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 (1011) hide show
  1. package/dist/PdfViewerImpl-QUSDLNNM.cjs +380 -0
  2. package/dist/PdfViewerImpl-QUSDLNNM.cjs.map +1 -0
  3. package/dist/{PdfViewer.d-bQH9yxFg.d.cts → PdfViewerImpl.d-B28hLEuj.d.ts} +8 -1
  4. package/dist/account/client.js +96 -0
  5. package/dist/account/client.js.map +7 -0
  6. package/dist/account/delete.js +70 -0
  7. package/dist/account/delete.js.map +7 -0
  8. package/dist/account/didit.js +34 -0
  9. package/dist/account/didit.js.map +7 -0
  10. package/dist/account/dismissed-tips.js +33 -0
  11. package/dist/account/dismissed-tips.js.map +7 -0
  12. package/dist/account/email.js +84 -0
  13. package/dist/account/email.js.map +7 -0
  14. package/dist/account/entitlements.js +47 -0
  15. package/dist/account/entitlements.js.map +7 -0
  16. package/dist/account/identity.js +270 -0
  17. package/dist/account/identity.js.map +7 -0
  18. package/dist/account/index.js +93 -0
  19. package/dist/account/index.js.map +7 -0
  20. package/dist/account/notifications.js +59 -0
  21. package/dist/account/notifications.js.map +7 -0
  22. package/dist/account/password.js +103 -0
  23. package/dist/account/password.js.map +7 -0
  24. package/dist/account/profile.js +116 -0
  25. package/dist/account/profile.js.map +7 -0
  26. package/dist/account/recovery.js +13 -0
  27. package/dist/account/recovery.js.map +7 -0
  28. package/dist/account/relevance.js +82 -0
  29. package/dist/account/relevance.js.map +7 -0
  30. package/dist/account/sessions.js +37 -0
  31. package/dist/account/sessions.js.map +7 -0
  32. package/dist/account/settings.js +39 -0
  33. package/dist/account/settings.js.map +7 -0
  34. package/dist/account/table-views.js +16 -0
  35. package/dist/account/table-views.js.map +7 -0
  36. package/dist/ai/AiAnswer.js +83 -0
  37. package/dist/ai/AiAnswer.js.map +7 -0
  38. package/dist/ai/AiMarkdown.js +40 -0
  39. package/dist/ai/AiMarkdown.js.map +7 -0
  40. package/dist/ai/ArtifactCanvas.js +193 -0
  41. package/dist/ai/ArtifactCanvas.js.map +7 -0
  42. package/dist/ai/CitationRenderer.js +413 -0
  43. package/dist/ai/CitationRenderer.js.map +7 -0
  44. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  45. package/dist/ai/MarkdownRenderer.js.map +7 -0
  46. package/dist/ai/MessageArtifactCard.js +75 -0
  47. package/dist/ai/MessageArtifactCard.js.map +7 -0
  48. package/dist/ai/PassageCard.js +79 -0
  49. package/dist/ai/PassageCard.js.map +7 -0
  50. package/dist/ai/engine.js +110 -0
  51. package/dist/ai/engine.js.map +7 -0
  52. package/dist/ai/index.js +63 -0
  53. package/dist/ai/index.js.map +7 -0
  54. package/dist/ai/markdown-base-components.js +37 -0
  55. package/dist/ai/markdown-base-components.js.map +7 -0
  56. package/dist/ai/markdown-streaming-context.js +6 -0
  57. package/dist/ai/markdown-streaming-context.js.map +7 -0
  58. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  59. package/dist/ai/normalize-citations.js.map +7 -0
  60. package/dist/ai/redline.js +41 -0
  61. package/dist/ai/redline.js.map +7 -0
  62. package/dist/ai/split-markdown-blocks.js +40 -0
  63. package/dist/ai/split-markdown-blocks.js.map +7 -0
  64. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  65. package/dist/ai/stored-markdown.js.map +7 -0
  66. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  67. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  68. package/dist/annotations/AnnotationToolbar.js +398 -0
  69. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  70. package/dist/annotations/FreezeDialog.js +170 -0
  71. package/dist/annotations/FreezeDialog.js.map +7 -0
  72. package/dist/annotations/ProductionDialog.js +354 -0
  73. package/dist/annotations/ProductionDialog.js.map +7 -0
  74. package/dist/annotations/controller.js +49 -0
  75. package/dist/annotations/controller.js.map +7 -0
  76. package/dist/annotations/freeze/browser.js +21 -0
  77. package/dist/annotations/freeze/browser.js.map +7 -0
  78. package/dist/annotations/freeze/bundle.js +201 -0
  79. package/dist/annotations/freeze/bundle.js.map +7 -0
  80. package/dist/annotations/freeze/coords.js +37 -0
  81. package/dist/annotations/freeze/coords.js.map +7 -0
  82. package/dist/annotations/freeze/freeze.js +261 -0
  83. package/dist/annotations/freeze/freeze.js.map +7 -0
  84. package/dist/annotations/freeze/hash.js +28 -0
  85. package/dist/annotations/freeze/hash.js.map +7 -0
  86. package/dist/annotations/freeze/index-page.js +78 -0
  87. package/dist/annotations/freeze/index-page.js.map +7 -0
  88. package/dist/annotations/freeze/index.d.ts +1 -1
  89. package/dist/annotations/freeze/index.js +28 -22
  90. package/dist/annotations/freeze/index.js.map +7 -1
  91. package/dist/annotations/freeze/raster.js +208 -0
  92. package/dist/annotations/freeze/raster.js.map +7 -0
  93. package/dist/annotations/freeze/stamp.js +117 -0
  94. package/dist/annotations/freeze/stamp.js.map +7 -0
  95. package/dist/annotations/freeze/types.js +14 -0
  96. package/dist/annotations/freeze/types.js.map +7 -0
  97. package/dist/annotations/freeze/vector.js +283 -0
  98. package/dist/annotations/freeze/vector.js.map +7 -0
  99. package/dist/annotations/geometry.js +81 -0
  100. package/dist/annotations/geometry.js.map +7 -0
  101. package/dist/annotations/index.js +125 -6
  102. package/dist/annotations/index.js.map +7 -1
  103. package/dist/annotations/merge.js +53 -0
  104. package/dist/annotations/merge.js.map +7 -0
  105. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  106. package/dist/annotations/model.js.map +7 -0
  107. package/dist/annotations/overlay-geometry.js +41 -0
  108. package/dist/annotations/overlay-geometry.js.map +7 -0
  109. package/dist/annotations/redaction-log.js +33 -0
  110. package/dist/annotations/redaction-log.js.map +7 -0
  111. package/dist/annotations/selection-marks.js +122 -0
  112. package/dist/annotations/selection-marks.js.map +7 -0
  113. package/dist/annotations/state.js +140 -0
  114. package/dist/annotations/state.js.map +7 -0
  115. package/dist/annotations/store.js +49 -0
  116. package/dist/annotations/store.js.map +7 -0
  117. package/dist/annotations/useAnnotationLayer.js +306 -0
  118. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  119. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  120. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  121. package/dist/annotations/useTextSelectionMarks.js +100 -0
  122. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  123. package/dist/artifacts/artifact-kind.js +19 -0
  124. package/dist/artifacts/artifact-kind.js.map +7 -0
  125. package/dist/artifacts/index.cjs +13 -13
  126. package/dist/artifacts/index.js +89 -571
  127. package/dist/artifacts/index.js.map +7 -1
  128. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  129. package/dist/artifacts/normalize-markdown.js.map +7 -0
  130. package/dist/artifacts/redline-core.js +12 -3
  131. package/dist/artifacts/redline-core.js.map +7 -1
  132. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  133. package/dist/artifacts/redline-diff.js.map +7 -0
  134. package/dist/artifacts/redline-engine.js +14 -0
  135. package/dist/artifacts/redline-engine.js.map +7 -0
  136. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  137. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  138. package/dist/artifacts/useArtifactEditSession.js +183 -0
  139. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  140. package/dist/artifacts/useArtifactSession.js +173 -0
  141. package/dist/artifacts/useArtifactSession.js.map +7 -0
  142. package/dist/artifacts/useArtifactSource.js +16 -0
  143. package/dist/artifacts/useArtifactSource.js.map +7 -0
  144. package/dist/artifacts/useArtifactText.js +78 -0
  145. package/dist/artifacts/useArtifactText.js.map +7 -0
  146. package/dist/artifacts/useRedline.js +65 -0
  147. package/dist/artifacts/useRedline.js.map +7 -0
  148. package/dist/artifacts/useStreamedArtifact.js +74 -0
  149. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  150. package/dist/artifacts/versions.js +68 -0
  151. package/dist/artifacts/versions.js.map +7 -0
  152. package/dist/billing.js +200 -0
  153. package/dist/billing.js.map +7 -0
  154. package/dist/boot-timeout.js +19 -0
  155. package/dist/boot-timeout.js.map +7 -0
  156. package/dist/calendar/accounts.js +213 -0
  157. package/dist/calendar/accounts.js.map +7 -0
  158. package/dist/calendar/hooks.js +409 -0
  159. package/dist/calendar/hooks.js.map +7 -0
  160. package/dist/calendar/index.js +31 -0
  161. package/dist/calendar/index.js.map +7 -0
  162. package/dist/calendar/keys.js +5 -0
  163. package/dist/calendar/keys.js.map +7 -0
  164. package/dist/calendar/offline/outbox.js +231 -0
  165. package/dist/calendar/offline/outbox.js.map +7 -0
  166. package/dist/calendar/offline/runtime.js +109 -0
  167. package/dist/calendar/offline/runtime.js.map +7 -0
  168. package/dist/calendar/offline/support.js +41 -0
  169. package/dist/calendar/offline/support.js.map +7 -0
  170. package/dist/calendar/support.js +34 -0
  171. package/dist/calendar/support.js.map +7 -0
  172. package/dist/calls/actions.js +226 -0
  173. package/dist/calls/actions.js.map +7 -0
  174. package/dist/calls/events.js +138 -0
  175. package/dist/calls/events.js.map +7 -0
  176. package/dist/calls/gate.js +19 -0
  177. package/dist/calls/gate.js.map +7 -0
  178. package/dist/calls/hooks.js +115 -0
  179. package/dist/calls/hooks.js.map +7 -0
  180. package/dist/calls/in-call-chat.js +132 -0
  181. package/dist/calls/in-call-chat.js.map +7 -0
  182. package/dist/calls/index.js +24 -0
  183. package/dist/calls/index.js.map +7 -0
  184. package/dist/calls/keys.js +17 -0
  185. package/dist/calls/keys.js.map +7 -0
  186. package/dist/calls/livekit/index.cjs +48 -48
  187. package/dist/calls/livekit/index.js +6 -958
  188. package/dist/calls/livekit/index.js.map +7 -1
  189. package/dist/calls/livekit/room.js +98 -0
  190. package/dist/calls/livekit/room.js.map +7 -0
  191. package/dist/calls/livekit/useCallRecorder.js +219 -0
  192. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  193. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  194. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  195. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  196. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  197. package/dist/calls/livekit/useInCallChat.js +161 -0
  198. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  199. package/dist/calls/livekit/useWebinar.js +239 -0
  200. package/dist/calls/livekit/useWebinar.js.map +7 -0
  201. package/dist/calls/meeting-chat.js +149 -0
  202. package/dist/calls/meeting-chat.js.map +7 -0
  203. package/dist/calls/moderation.js +50 -0
  204. package/dist/calls/moderation.js.map +7 -0
  205. package/dist/calls/open-meeting-chat.js +29 -0
  206. package/dist/calls/open-meeting-chat.js.map +7 -0
  207. package/dist/calls/read-only.js +24 -0
  208. package/dist/calls/read-only.js.map +7 -0
  209. package/dist/calls/recording-media.js +218 -0
  210. package/dist/calls/recording-media.js.map +7 -0
  211. package/dist/calls/recording-playback.js +260 -0
  212. package/dist/calls/recording-playback.js.map +7 -0
  213. package/dist/calls/recording.js +268 -0
  214. package/dist/calls/recording.js.map +7 -0
  215. package/dist/calls/save-to-thread.js +80 -0
  216. package/dist/calls/save-to-thread.js.map +7 -0
  217. package/dist/calls/session.js +134 -0
  218. package/dist/calls/session.js.map +7 -0
  219. package/dist/calls/transcript-format.js +147 -0
  220. package/dist/calls/transcript-format.js.map +7 -0
  221. package/dist/calls/transcription.js +101 -0
  222. package/dist/calls/transcription.js.map +7 -0
  223. package/dist/calls/webinar.js +71 -0
  224. package/dist/calls/webinar.js.map +7 -0
  225. package/dist/charge-watch.js +71 -0
  226. package/dist/charge-watch.js.map +7 -0
  227. package/dist/chat/ChatBubble.js +146 -0
  228. package/dist/chat/ChatBubble.js.map +7 -0
  229. package/dist/chat/ConversationScope.js +30 -0
  230. package/dist/chat/ConversationScope.js.map +7 -0
  231. package/dist/chat/active-config.js +20 -0
  232. package/dist/chat/active-config.js.map +7 -0
  233. package/dist/chat/agent-chat-owner.js +25 -0
  234. package/dist/chat/agent-chat-owner.js.map +7 -0
  235. package/dist/chat/chat-artifacts.js +64 -0
  236. package/dist/chat/chat-artifacts.js.map +7 -0
  237. package/dist/chat/citations.js +32 -0
  238. package/dist/chat/citations.js.map +7 -0
  239. package/dist/chat/config-model.js +10 -0
  240. package/dist/chat/config-model.js.map +7 -0
  241. package/dist/chat/conversation-cache.js +676 -0
  242. package/dist/chat/conversation-cache.js.map +7 -0
  243. package/dist/chat/conversation-events.js +57 -0
  244. package/dist/chat/conversation-events.js.map +7 -0
  245. package/dist/chat/conversation-mentions.js +58 -0
  246. package/dist/chat/conversation-mentions.js.map +7 -0
  247. package/dist/chat/conversation-workspace.js +58 -0
  248. package/dist/chat/conversation-workspace.js.map +7 -0
  249. package/dist/chat/mentions.js +116 -0
  250. package/dist/chat/mentions.js.map +7 -0
  251. package/dist/chat/open-document.js +106 -0
  252. package/dist/chat/open-document.js.map +7 -0
  253. package/dist/chat/orphaned.js +44 -0
  254. package/dist/chat/orphaned.js.map +7 -0
  255. package/dist/chat/pendingFirstTurn.js +30 -0
  256. package/dist/chat/pendingFirstTurn.js.map +7 -0
  257. package/dist/chat/reply-target.js +12 -0
  258. package/dist/chat/reply-target.js.map +7 -0
  259. package/dist/chat/run-finished.js +28 -0
  260. package/dist/chat/run-finished.js.map +7 -0
  261. package/dist/chat/run-state.js +91 -0
  262. package/dist/chat/run-state.js.map +7 -0
  263. package/dist/chat/stream-handlers.js +419 -0
  264. package/dist/chat/stream-handlers.js.map +7 -0
  265. package/dist/chat/thread-binding.js +76 -0
  266. package/dist/chat/thread-binding.js.map +7 -0
  267. package/dist/chat/thread-document.js +53 -0
  268. package/dist/chat/thread-document.js.map +7 -0
  269. package/dist/chat/turn-control.js +79 -0
  270. package/dist/chat/turn-control.js.map +7 -0
  271. package/dist/chat/useAgentRunControl.js +36 -0
  272. package/dist/chat/useAgentRunControl.js.map +7 -0
  273. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  274. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  275. package/dist/chat/useAskAgain.js +32 -0
  276. package/dist/chat/useAskAgain.js.map +7 -0
  277. package/dist/chat/useAutoSendDraft.js +17 -0
  278. package/dist/chat/useAutoSendDraft.js.map +7 -0
  279. package/dist/chat/useBranchNavigation.js +97 -0
  280. package/dist/chat/useBranchNavigation.js.map +7 -0
  281. package/dist/chat/useConnectRunStream.js +169 -0
  282. package/dist/chat/useConnectRunStream.js.map +7 -0
  283. package/dist/chat/useConversation.js +431 -0
  284. package/dist/chat/useConversation.js.map +7 -0
  285. package/dist/chat/useConversationActions.js +662 -0
  286. package/dist/chat/useConversationActions.js.map +7 -0
  287. package/dist/chat/useConversationData.js +143 -0
  288. package/dist/chat/useConversationData.js.map +7 -0
  289. package/dist/chat/useConversationDocuments.js +41 -0
  290. package/dist/chat/useConversationDocuments.js.map +7 -0
  291. package/dist/chat/useConversationSettings.js +78 -0
  292. package/dist/chat/useConversationSettings.js.map +7 -0
  293. package/dist/chat/useConversationTurn.js +31 -0
  294. package/dist/chat/useConversationTurn.js.map +7 -0
  295. package/dist/chat/useConversationWorkspace.js +12 -0
  296. package/dist/chat/useConversationWorkspace.js.map +7 -0
  297. package/dist/chat/useDeleteMessage.js +15 -0
  298. package/dist/chat/useDeleteMessage.js.map +7 -0
  299. package/dist/chat/useDocumentAutoAdd.js +73 -0
  300. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  301. package/dist/chat/useMessageTimer.js +39 -0
  302. package/dist/chat/useMessageTimer.js.map +7 -0
  303. package/dist/chat/useThinkingContent.js +67 -0
  304. package/dist/chat/useThinkingContent.js.map +7 -0
  305. package/dist/chat/useThreadDocument.js +61 -0
  306. package/dist/chat/useThreadDocument.js.map +7 -0
  307. package/dist/chat/workflow-run-titles.js +50 -0
  308. package/dist/chat/workflow-run-titles.js.map +7 -0
  309. package/dist/{chunk-W2FATOTX.cjs → chunk-3JAEX57E.cjs} +4 -4
  310. package/dist/{chunk-W2FATOTX.cjs.map → chunk-3JAEX57E.cjs.map} +1 -1
  311. package/dist/{chunk-HD5H2PPP.cjs → chunk-5TRUFWKT.cjs} +66 -66
  312. package/dist/{chunk-HD5H2PPP.cjs.map → chunk-5TRUFWKT.cjs.map} +1 -1
  313. package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
  314. package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
  315. package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
  316. package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
  317. package/dist/{chunk-RVUGSM65.cjs → chunk-GKGAPU6T.cjs} +44 -44
  318. package/dist/{chunk-RVUGSM65.cjs.map → chunk-GKGAPU6T.cjs.map} +1 -1
  319. package/dist/{chunk-7LIMHY56.cjs → chunk-O32T7XRD.cjs} +3 -3
  320. package/dist/{chunk-7LIMHY56.cjs.map → chunk-O32T7XRD.cjs.map} +1 -1
  321. package/dist/chunk-PWGSIM3F.cjs +291 -0
  322. package/dist/chunk-PWGSIM3F.cjs.map +1 -0
  323. package/dist/chunk-QP3WQSAA.cjs +23 -0
  324. package/dist/chunk-QP3WQSAA.cjs.map +1 -0
  325. package/dist/chunk-T5FZICXN.cjs +50 -0
  326. package/dist/chunk-T5FZICXN.cjs.map +1 -0
  327. package/dist/{chunk-QF2BW6HZ.cjs → chunk-UDDJIUHJ.cjs} +38 -38
  328. package/dist/{chunk-QF2BW6HZ.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
  329. package/dist/{chunk-5HDKL6XB.cjs → chunk-YMB6XUR2.cjs} +57 -57
  330. package/dist/{chunk-5HDKL6XB.cjs.map → chunk-YMB6XUR2.cjs.map} +1 -1
  331. package/dist/config/config-hooks.js +209 -0
  332. package/dist/config/config-hooks.js.map +7 -0
  333. package/dist/connectivity.js +72 -0
  334. package/dist/connectivity.js.map +7 -0
  335. package/dist/connectors/hooks.js +263 -0
  336. package/dist/connectors/hooks.js.map +7 -0
  337. package/dist/connectors/index.js +28 -0
  338. package/dist/connectors/index.js.map +7 -0
  339. package/dist/contacts.js +100 -0
  340. package/dist/contacts.js.map +7 -0
  341. package/dist/conversation-list.js +65 -0
  342. package/dist/conversation-list.js.map +7 -0
  343. package/dist/databases.js +195 -0
  344. package/dist/databases.js.map +7 -0
  345. package/dist/datasets/aggregate.js +281 -0
  346. package/dist/datasets/aggregate.js.map +7 -0
  347. package/dist/datasets/index.js +122 -0
  348. package/dist/datasets/index.js.map +7 -0
  349. package/dist/datasets/members.js +27 -0
  350. package/dist/datasets/members.js.map +7 -0
  351. package/dist/datasets/panel.js +44 -0
  352. package/dist/datasets/panel.js.map +7 -0
  353. package/dist/datasets/registry.js +47 -0
  354. package/dist/datasets/registry.js.map +7 -0
  355. package/dist/datasets/rows-source.js +44 -0
  356. package/dist/datasets/rows-source.js.map +7 -0
  357. package/dist/datasets/sources/activity.js +83 -0
  358. package/dist/datasets/sources/activity.js.map +7 -0
  359. package/dist/datasets/sources/conversations.js +74 -0
  360. package/dist/datasets/sources/conversations.js.map +7 -0
  361. package/dist/datasets/sources/database.js +209 -0
  362. package/dist/datasets/sources/database.js.map +7 -0
  363. package/dist/datasets/sources/documents.js +93 -0
  364. package/dist/datasets/sources/documents.js.map +7 -0
  365. package/dist/datasets/sources/facts.js +56 -0
  366. package/dist/datasets/sources/facts.js.map +7 -0
  367. package/dist/datasets/sources/projects.js +117 -0
  368. package/dist/datasets/sources/projects.js.map +7 -0
  369. package/dist/datasets/sources/tags.js +67 -0
  370. package/dist/datasets/sources/tags.js.map +7 -0
  371. package/dist/datasets/sources/usage.js +268 -0
  372. package/dist/datasets/sources/usage.js.map +7 -0
  373. package/dist/datasets/sources/workflows.js +91 -0
  374. package/dist/datasets/sources/workflows.js.map +7 -0
  375. package/dist/datasets/sources/workspaces.js +67 -0
  376. package/dist/datasets/sources/workspaces.js.map +7 -0
  377. package/dist/datasets/store.js +194 -0
  378. package/dist/datasets/store.js.map +7 -0
  379. package/dist/datasets/types.js +14 -0
  380. package/dist/datasets/types.js.map +7 -0
  381. package/dist/directmessages/ConversationList.js +148 -0
  382. package/dist/directmessages/ConversationList.js.map +7 -0
  383. package/dist/directmessages/DateSeparator.js +8 -0
  384. package/dist/directmessages/DateSeparator.js.map +7 -0
  385. package/dist/directmessages/DmAvatar.js +29 -0
  386. package/dist/directmessages/DmAvatar.js.map +7 -0
  387. package/dist/directmessages/DmComposer.js +201 -0
  388. package/dist/directmessages/DmComposer.js.map +7 -0
  389. package/dist/directmessages/arrivals.js +29 -0
  390. package/dist/directmessages/arrivals.js.map +7 -0
  391. package/dist/directmessages/chat-cache.js +192 -0
  392. package/dist/directmessages/chat-cache.js.map +7 -0
  393. package/dist/directmessages/grouping.js +26 -0
  394. package/dist/directmessages/grouping.js.map +7 -0
  395. package/dist/directmessages/index.js +81 -0
  396. package/dist/directmessages/index.js.map +7 -0
  397. package/dist/directmessages/useChats.js +266 -0
  398. package/dist/directmessages/useChats.js.map +7 -0
  399. package/dist/directmessages/utils.js +23 -0
  400. package/dist/directmessages/utils.js.map +7 -0
  401. package/dist/document-tools/can-annotate.js +7 -0
  402. package/dist/document-tools/can-annotate.js.map +7 -0
  403. package/dist/document-tools/core.cjs +99 -99
  404. package/dist/document-tools/core.d.ts +2 -2
  405. package/dist/document-tools/core.js +218 -12
  406. package/dist/document-tools/core.js.map +7 -1
  407. package/dist/document-tools/document-pdf.js +76 -0
  408. package/dist/document-tools/document-pdf.js.map +7 -0
  409. package/dist/document-tools/environment.js +136 -0
  410. package/dist/document-tools/environment.js.map +7 -0
  411. package/dist/document-tools/file-shares.js +112 -0
  412. package/dist/document-tools/file-shares.js.map +7 -0
  413. package/dist/document-tools/frozen-copy.js +27 -0
  414. package/dist/document-tools/frozen-copy.js.map +7 -0
  415. package/dist/document-tools/index.cjs +101 -101
  416. package/dist/document-tools/index.d.ts +1 -1
  417. package/dist/document-tools/index.js +26 -148
  418. package/dist/document-tools/index.js.map +7 -1
  419. package/dist/document-tools/markup-download.js +51 -0
  420. package/dist/document-tools/markup-download.js.map +7 -0
  421. package/dist/document-tools/markup-store.js +138 -0
  422. package/dist/document-tools/markup-store.js.map +7 -0
  423. package/dist/document-tools/markup-transfer.js +88 -0
  424. package/dist/document-tools/markup-transfer.js.map +7 -0
  425. package/dist/document-tools/production.js +147 -0
  426. package/dist/document-tools/production.js.map +7 -0
  427. package/dist/document-tools/saved-signature.js +90 -0
  428. package/dist/document-tools/saved-signature.js.map +7 -0
  429. package/dist/document-tools/signature-requests.js +310 -0
  430. package/dist/document-tools/signature-requests.js.map +7 -0
  431. package/dist/document-tools/signing.js +127 -0
  432. package/dist/document-tools/signing.js.map +7 -0
  433. package/dist/document-tools/useDocumentBytes.js +38 -0
  434. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  435. package/dist/document-tools/useDocumentMarkup.js +154 -0
  436. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  437. package/dist/document-tools/useIsOnline.js +13 -0
  438. package/dist/document-tools/useIsOnline.js.map +7 -0
  439. package/dist/document-tools/verification.js +60 -0
  440. package/dist/document-tools/verification.js.map +7 -0
  441. package/dist/documents/DocumentReview.js +220 -0
  442. package/dist/documents/DocumentReview.js.map +7 -0
  443. package/dist/documents/DraftTitleControls.js +41 -0
  444. package/dist/documents/DraftTitleControls.js.map +7 -0
  445. package/dist/documents/InlineMicButton.js +90 -0
  446. package/dist/documents/InlineMicButton.js.map +7 -0
  447. package/dist/documents/MicRecordingOverlay.js +29 -0
  448. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  449. package/dist/documents/MicWaveformIndicator.js +68 -0
  450. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  451. package/dist/documents/PhotoCapture.js +120 -0
  452. package/dist/documents/PhotoCapture.js.map +7 -0
  453. package/dist/documents/VideoCapture.js +129 -0
  454. package/dist/documents/VideoCapture.js.map +7 -0
  455. package/dist/documents/VoiceNoteRecorder.js +166 -0
  456. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  457. package/dist/documents/audio-segmenter.js +63 -0
  458. package/dist/documents/audio-segmenter.js.map +7 -0
  459. package/dist/documents/capture-frame.js +21 -0
  460. package/dist/documents/capture-frame.js.map +7 -0
  461. package/dist/documents/chunked-recorder.js +190 -0
  462. package/dist/documents/chunked-recorder.js.map +7 -0
  463. package/dist/documents/document-download.js +53 -0
  464. package/dist/documents/document-download.js.map +7 -0
  465. package/dist/documents/document-fields.js +109 -0
  466. package/dist/documents/document-fields.js.map +7 -0
  467. package/dist/documents/documents-cache.js +110 -0
  468. package/dist/documents/documents-cache.js.map +7 -0
  469. package/dist/documents/documents-data.js +128 -0
  470. package/dist/documents/documents-data.js.map +7 -0
  471. package/dist/documents/documents-loader.js +113 -0
  472. package/dist/documents/documents-loader.js.map +7 -0
  473. package/dist/documents/documents-writes.js +448 -0
  474. package/dist/documents/documents-writes.js.map +7 -0
  475. package/dist/documents/format-elapsed.js +10 -0
  476. package/dist/documents/format-elapsed.js.map +7 -0
  477. package/dist/documents/has-video-track.js +26 -0
  478. package/dist/documents/has-video-track.js.map +7 -0
  479. package/dist/documents/index.js +266 -0
  480. package/dist/documents/index.js.map +7 -0
  481. package/dist/documents/media-error.js +18 -0
  482. package/dist/documents/media-error.js.map +7 -0
  483. package/dist/documents/offline-documents.js +160 -0
  484. package/dist/documents/offline-documents.js.map +7 -0
  485. package/dist/documents/pending-sync.js +210 -0
  486. package/dist/documents/pending-sync.js.map +7 -0
  487. package/dist/documents/processing-live.js +122 -0
  488. package/dist/documents/processing-live.js.map +7 -0
  489. package/dist/documents/processing-order.js +59 -0
  490. package/dist/documents/processing-order.js.map +7 -0
  491. package/dist/documents/processing-settle.js +21 -0
  492. package/dist/documents/processing-settle.js.map +7 -0
  493. package/dist/documents/related-documents.js +133 -0
  494. package/dist/documents/related-documents.js.map +7 -0
  495. package/dist/documents/support.js +29 -0
  496. package/dist/documents/support.js.map +7 -0
  497. package/dist/documents/upload-files.js +169 -0
  498. package/dist/documents/upload-files.js.map +7 -0
  499. package/dist/documents/useAudioRecorder.js +315 -0
  500. package/dist/documents/useAudioRecorder.js.map +7 -0
  501. package/dist/documents/useCameraStream.js +35 -0
  502. package/dist/documents/useCameraStream.js.map +7 -0
  503. package/dist/documents/useDocumentThumbnails.js +71 -0
  504. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  505. package/dist/documents/useDownloadDocuments.js +90 -0
  506. package/dist/documents/useDownloadDocuments.js.map +7 -0
  507. package/dist/documents/usePassageQuotes.js +37 -0
  508. package/dist/documents/usePassageQuotes.js.map +7 -0
  509. package/dist/documents/useUploadFiles.js +165 -0
  510. package/dist/documents/useUploadFiles.js.map +7 -0
  511. package/dist/documents/useUploadFromUrls.js +63 -0
  512. package/dist/documents/useUploadFromUrls.js.map +7 -0
  513. package/dist/documents/useVideoRecorder.js +62 -0
  514. package/dist/documents/useVideoRecorder.js.map +7 -0
  515. package/dist/entities/AgentMarkers.js +61 -0
  516. package/dist/entities/AgentMarkers.js.map +7 -0
  517. package/dist/entities/DocumentEntity.js +125 -0
  518. package/dist/entities/DocumentEntity.js.map +7 -0
  519. package/dist/entities/EntityPill.js +250 -0
  520. package/dist/entities/EntityPill.js.map +7 -0
  521. package/dist/entities/ProjectEntity.js +61 -0
  522. package/dist/entities/ProjectEntity.js.map +7 -0
  523. package/dist/entities/ShieldIcon.js +49 -0
  524. package/dist/entities/ShieldIcon.js.map +7 -0
  525. package/dist/entities/TagEntity.js +79 -0
  526. package/dist/entities/TagEntity.js.map +7 -0
  527. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  528. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  529. package/dist/entities/UserEntity.js +211 -0
  530. package/dist/entities/UserEntity.js.map +7 -0
  531. package/dist/entities/VerifiedBadge.js +19 -0
  532. package/dist/entities/VerifiedBadge.js.map +7 -0
  533. package/dist/entities/agent-avatar-colors.js +26 -0
  534. package/dist/entities/agent-avatar-colors.js.map +7 -0
  535. package/dist/entities/colors.js +64 -0
  536. package/dist/entities/colors.js.map +7 -0
  537. package/dist/entities/file-type.js +151 -0
  538. package/dist/entities/file-type.js.map +7 -0
  539. package/dist/entities/index.js +100 -0
  540. package/dist/entities/index.js.map +7 -0
  541. package/dist/entities/media-type.js +61 -0
  542. package/dist/entities/media-type.js.map +7 -0
  543. package/dist/entities/registry.js +385 -0
  544. package/dist/entities/registry.js.map +7 -0
  545. package/dist/entities/status.js +43 -0
  546. package/dist/entities/status.js.map +7 -0
  547. package/dist/entities/tag-kinds.js +23 -0
  548. package/dist/entities/tag-kinds.js.map +7 -0
  549. package/dist/entities/tag-types.js +44 -0
  550. package/dist/entities/tag-types.js.map +7 -0
  551. package/dist/entities/vocabulary.js +12 -0
  552. package/dist/entities/vocabulary.js.map +7 -0
  553. package/dist/entity-extraction.js +25 -0
  554. package/dist/entity-extraction.js.map +7 -0
  555. package/dist/facts-search.js +57 -0
  556. package/dist/facts-search.js.map +7 -0
  557. package/dist/facts.js +69 -0
  558. package/dist/facts.js.map +7 -0
  559. package/dist/hooks.js +320 -0
  560. package/dist/hooks.js.map +7 -0
  561. package/dist/host/ArbiHost.js +24 -0
  562. package/dist/host/ArbiHost.js.map +7 -0
  563. package/dist/host/assistant-copy.js +54 -0
  564. package/dist/host/assistant-copy.js.map +7 -0
  565. package/dist/host/config.js +9 -0
  566. package/dist/host/config.js.map +7 -0
  567. package/dist/host/context.js +10 -0
  568. package/dist/host/context.js.map +7 -0
  569. package/dist/host/features.js +144 -0
  570. package/dist/host/features.js.map +7 -0
  571. package/dist/host/index.js +12 -0
  572. package/dist/host/index.js.map +7 -0
  573. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  574. package/dist/host/merge.js.map +7 -0
  575. package/dist/house-template.js +40 -0
  576. package/dist/house-template.js.map +7 -0
  577. package/dist/icons/AppleIcon.js +25 -0
  578. package/dist/icons/AppleIcon.js.map +7 -0
  579. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  580. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  581. package/dist/icons/ArbiIcon.js +24 -0
  582. package/dist/icons/ArbiIcon.js.map +7 -0
  583. package/dist/icons/AudIcon.js +56 -0
  584. package/dist/icons/AudIcon.js.map +7 -0
  585. package/dist/icons/ClaudeIcon.js +28 -0
  586. package/dist/icons/ClaudeIcon.js.map +7 -0
  587. package/dist/icons/DocIcon.js +56 -0
  588. package/dist/icons/DocIcon.js.map +7 -0
  589. package/dist/icons/EmlIcon.js +57 -0
  590. package/dist/icons/EmlIcon.js.map +7 -0
  591. package/dist/icons/FireworksIcon.js +47 -0
  592. package/dist/icons/FireworksIcon.js.map +7 -0
  593. package/dist/icons/GeminiIcon.js +37 -0
  594. package/dist/icons/GeminiIcon.js.map +7 -0
  595. package/dist/icons/GitHubIcon.js +32 -0
  596. package/dist/icons/GitHubIcon.js.map +7 -0
  597. package/dist/icons/GoogleIcon.js +53 -0
  598. package/dist/icons/GoogleIcon.js.map +7 -0
  599. package/dist/icons/HtmlIcon.js +56 -0
  600. package/dist/icons/HtmlIcon.js.map +7 -0
  601. package/dist/icons/ImgIcon.js +56 -0
  602. package/dist/icons/ImgIcon.js.map +7 -0
  603. package/dist/icons/LinkedInIcon.js +25 -0
  604. package/dist/icons/LinkedInIcon.js.map +7 -0
  605. package/dist/icons/OpenAIIcon.js +28 -0
  606. package/dist/icons/OpenAIIcon.js.map +7 -0
  607. package/dist/icons/PdfIcon.js +56 -0
  608. package/dist/icons/PdfIcon.js.map +7 -0
  609. package/dist/icons/ProviderIcon.js +42 -0
  610. package/dist/icons/ProviderIcon.js.map +7 -0
  611. package/dist/icons/TxtIcon.js +56 -0
  612. package/dist/icons/TxtIcon.js.map +7 -0
  613. package/dist/icons/VidIcon.js +56 -0
  614. package/dist/icons/VidIcon.js.map +7 -0
  615. package/dist/icons/XlsIcon.js +56 -0
  616. package/dist/icons/XlsIcon.js.map +7 -0
  617. package/dist/icons/arbi-mark.js +5 -0
  618. package/dist/icons/arbi-mark.js.map +7 -0
  619. package/dist/icons/colors.js +31 -0
  620. package/dist/icons/colors.js.map +7 -0
  621. package/dist/icons/file-type.js +105 -0
  622. package/dist/icons/file-type.js.map +7 -0
  623. package/dist/icons/index.js +55 -0
  624. package/dist/icons/index.js.map +7 -0
  625. package/dist/imagecrop/ImageCropModal.js +56 -0
  626. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  627. package/dist/imagecrop/ImageCropper.js +100 -0
  628. package/dist/imagecrop/ImageCropper.js.map +7 -0
  629. package/dist/imagecrop/cropImage.js +43 -0
  630. package/dist/imagecrop/cropImage.js.map +7 -0
  631. package/dist/imagecrop/index.js +13 -0
  632. package/dist/imagecrop/index.js.map +7 -0
  633. package/dist/index.cjs +1689 -1619
  634. package/dist/index.cjs.map +1 -1
  635. package/dist/{index.d-BMhTH98a.d.ts → index.d-CYXcTKYt.d.ts} +1 -0
  636. package/dist/index.d.ts +38 -8
  637. package/dist/index.js +702 -17060
  638. package/dist/index.js.map +7 -1
  639. package/dist/lazy-chunk.d-B6YDLMKI.d.ts +31 -0
  640. package/dist/lazy-chunk.js +46 -0
  641. package/dist/lazy-chunk.js.map +7 -0
  642. package/dist/lib/collision-padding.js +13 -0
  643. package/dist/lib/collision-padding.js.map +7 -0
  644. package/dist/lib/format-friendly-date.js +55 -0
  645. package/dist/lib/format-friendly-date.js.map +7 -0
  646. package/dist/lib/format-relative-time.js +52 -0
  647. package/dist/lib/format-relative-time.js.map +7 -0
  648. package/dist/lib/markdown-to-text.js +35 -0
  649. package/dist/lib/markdown-to-text.js.map +7 -0
  650. package/dist/lib/toast-interaction.js +9 -0
  651. package/dist/lib/toast-interaction.js.map +7 -0
  652. package/dist/lib/utils.js +9 -0
  653. package/dist/lib/utils.js.map +7 -0
  654. package/dist/mail/client.js +103 -0
  655. package/dist/mail/client.js.map +7 -0
  656. package/dist/mail/document-attachment.js +38 -0
  657. package/dist/mail/document-attachment.js.map +7 -0
  658. package/dist/mail/filing.js +132 -0
  659. package/dist/mail/filing.js.map +7 -0
  660. package/dist/mail/hooks.js +393 -0
  661. package/dist/mail/hooks.js.map +7 -0
  662. package/dist/mail/index.js +120 -0
  663. package/dist/mail/index.js.map +7 -0
  664. package/dist/mail/offline/changes.js +258 -0
  665. package/dist/mail/offline/changes.js.map +7 -0
  666. package/dist/mail/offline/confirm-sign-out.js +37 -0
  667. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  668. package/dist/mail/offline/crypto.js +26 -0
  669. package/dist/mail/offline/crypto.js.map +7 -0
  670. package/dist/mail/offline/drafts.js +69 -0
  671. package/dist/mail/offline/drafts.js.map +7 -0
  672. package/dist/mail/offline/hooks.js +104 -0
  673. package/dist/mail/offline/hooks.js.map +7 -0
  674. package/dist/mail/offline/index.js +48 -0
  675. package/dist/mail/offline/index.js.map +7 -0
  676. package/dist/mail/offline/live.js +233 -0
  677. package/dist/mail/offline/live.js.map +7 -0
  678. package/dist/mail/offline/mailbox.js +191 -0
  679. package/dist/mail/offline/mailbox.js.map +7 -0
  680. package/dist/mail/offline/outbox.js +167 -0
  681. package/dist/mail/offline/outbox.js.map +7 -0
  682. package/dist/mail/offline/reads.js +159 -0
  683. package/dist/mail/offline/reads.js.map +7 -0
  684. package/dist/mail/offline/runtime.js +100 -0
  685. package/dist/mail/offline/runtime.js.map +7 -0
  686. package/dist/mail/offline/settings.js +84 -0
  687. package/dist/mail/offline/settings.js.map +7 -0
  688. package/dist/mail/offline/store.js +29 -0
  689. package/dist/mail/offline/store.js.map +7 -0
  690. package/dist/mail/offline/sync.js +251 -0
  691. package/dist/mail/offline/sync.js.map +7 -0
  692. package/dist/mail/offline/wipe.js +19 -0
  693. package/dist/mail/offline/wipe.js.map +7 -0
  694. package/dist/mail/thread-keys.js +53 -0
  695. package/dist/mail/thread-keys.js.map +7 -0
  696. package/dist/mail/threads.js +71 -0
  697. package/dist/mail/threads.js.map +7 -0
  698. package/dist/mail/useMailClient.js +42 -0
  699. package/dist/mail/useMailClient.js.map +7 -0
  700. package/dist/model-connections.js +58 -0
  701. package/dist/model-connections.js.map +7 -0
  702. package/dist/notifications/ActivityFeed.js +70 -0
  703. package/dist/notifications/ActivityFeed.js.map +7 -0
  704. package/dist/notifications/NotificationBell.js +200 -0
  705. package/dist/notifications/NotificationBell.js.map +7 -0
  706. package/dist/notifications/Toaster.js +24 -0
  707. package/dist/notifications/Toaster.js.map +7 -0
  708. package/dist/notifications/activity-types.js +65 -0
  709. package/dist/notifications/activity-types.js.map +7 -0
  710. package/dist/notifications/bell.js +24 -0
  711. package/dist/notifications/bell.js.map +7 -0
  712. package/dist/notifications/calendar-notifications.js +79 -0
  713. package/dist/notifications/calendar-notifications.js.map +7 -0
  714. package/dist/notifications/index.js +108 -0
  715. package/dist/notifications/index.js.map +7 -0
  716. package/dist/notifications/live.js +28 -0
  717. package/dist/notifications/live.js.map +7 -0
  718. package/dist/notifications/notification-types.js +127 -0
  719. package/dist/notifications/notification-types.js.map +7 -0
  720. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  721. package/dist/notifications/notify-store.js.map +7 -0
  722. package/dist/notifications/server-notifications.js +452 -0
  723. package/dist/notifications/server-notifications.js.map +7 -0
  724. package/dist/notifications/useNotifications.js +34 -0
  725. package/dist/notifications/useNotifications.js.map +7 -0
  726. package/dist/offline-store/network.js +11 -0
  727. package/dist/offline-store/network.js.map +7 -0
  728. package/dist/offline-store/store.js +136 -0
  729. package/dist/offline-store/store.js.map +7 -0
  730. package/dist/offline-store/wipe.js +8 -0
  731. package/dist/offline-store/wipe.js.map +7 -0
  732. package/dist/offline.js +58 -0
  733. package/dist/offline.js.map +7 -0
  734. package/dist/people.js +122 -0
  735. package/dist/people.js.map +7 -0
  736. package/dist/projects.js +30 -0
  737. package/dist/projects.js.map +7 -0
  738. package/dist/query-client.js +63 -0
  739. package/dist/query-client.js.map +7 -0
  740. package/dist/{query-keys.d-ChgpJLPF.d.ts → query-keys.d-B1Am9tIF.d.ts} +1 -1
  741. package/dist/{chunk-6H3O63TQ.js → query-keys.js} +19 -32
  742. package/dist/query-keys.js.map +7 -0
  743. package/dist/query-persist.js +66 -0
  744. package/dist/query-persist.js.map +7 -0
  745. package/dist/queued-writes.js +59 -0
  746. package/dist/queued-writes.js.map +7 -0
  747. package/dist/remote-control.js +67 -0
  748. package/dist/remote-control.js.map +7 -0
  749. package/dist/search/index.js +23 -0
  750. package/dist/search/index.js.map +7 -0
  751. package/dist/search/session.js +58 -0
  752. package/dist/search/session.js.map +7 -0
  753. package/dist/search/useSemanticSearch.js +82 -0
  754. package/dist/search/useSemanticSearch.js.map +7 -0
  755. package/dist/session/chat.js +512 -0
  756. package/dist/session/chat.js.map +7 -0
  757. package/dist/session/documents.js +196 -0
  758. package/dist/session/documents.js.map +7 -0
  759. package/dist/session/drafts.js +103 -0
  760. package/dist/session/drafts.js.map +7 -0
  761. package/dist/session/index.js +123 -0
  762. package/dist/session/index.js.map +7 -0
  763. package/dist/session/layout.js +339 -0
  764. package/dist/session/layout.js.map +7 -0
  765. package/dist/session/persist.js +106 -0
  766. package/dist/session/persist.js.map +7 -0
  767. package/dist/session/session-hooks.js +53 -0
  768. package/dist/session/session-hooks.js.map +7 -0
  769. package/dist/session/signed-in.js +36 -0
  770. package/dist/session/signed-in.js.map +7 -0
  771. package/dist/session/store.js +166 -0
  772. package/dist/session/store.js.map +7 -0
  773. package/dist/session/thread-tabs.js +121 -0
  774. package/dist/session/thread-tabs.js.map +7 -0
  775. package/dist/session/ui-state-storage.js +76 -0
  776. package/dist/session/ui-state-storage.js.map +7 -0
  777. package/dist/session/workspace.js +77 -0
  778. package/dist/session/workspace.js.map +7 -0
  779. package/dist/shell/index.cjs +37 -37
  780. package/dist/shell/index.js +43 -10
  781. package/dist/shell/index.js.map +7 -1
  782. package/dist/skill-pack.js +111 -0
  783. package/dist/skill-pack.js.map +7 -0
  784. package/dist/storage.js +186 -0
  785. package/dist/storage.js.map +7 -0
  786. package/dist/support/index.js +35 -0
  787. package/dist/support/index.js.map +7 -0
  788. package/dist/tags.js +204 -0
  789. package/dist/tags.js.map +7 -0
  790. package/dist/ui/DebouncedInput.js +109 -0
  791. package/dist/ui/DebouncedInput.js.map +7 -0
  792. package/dist/ui/DictateContext.js +8 -0
  793. package/dist/ui/DictateContext.js.map +7 -0
  794. package/dist/ui/IconToggle.js +79 -0
  795. package/dist/ui/IconToggle.js.map +7 -0
  796. package/dist/ui/VerifiedToggle.js +38 -0
  797. package/dist/ui/VerifiedToggle.js.map +7 -0
  798. package/dist/ui/VisibilityToggle.js +103 -0
  799. package/dist/ui/VisibilityToggle.js.map +7 -0
  800. package/dist/ui/avatar.js +40 -0
  801. package/dist/ui/avatar.js.map +7 -0
  802. package/dist/ui/badge.js +28 -0
  803. package/dist/ui/badge.js.map +7 -0
  804. package/dist/ui/button.js +48 -0
  805. package/dist/ui/button.js.map +7 -0
  806. package/dist/ui/card.js +90 -0
  807. package/dist/ui/card.js.map +7 -0
  808. package/dist/ui/checkbox.js +22 -0
  809. package/dist/ui/checkbox.js.map +7 -0
  810. package/dist/ui/collapsible.js +10 -0
  811. package/dist/ui/collapsible.js.map +7 -0
  812. package/dist/ui/command.js +103 -0
  813. package/dist/ui/command.js.map +7 -0
  814. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  815. package/dist/ui/dialog.js.map +7 -0
  816. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  817. package/dist/ui/dropdown-menu.js.map +7 -0
  818. package/dist/ui/hover-card.js +36 -0
  819. package/dist/ui/hover-card.js.map +7 -0
  820. package/dist/ui/index.cjs +167 -154
  821. package/dist/ui/index.d.ts +2 -1
  822. package/dist/ui/index.js +290 -9
  823. package/dist/ui/index.js.map +7 -1
  824. package/dist/ui/input.js +65 -0
  825. package/dist/ui/input.js.map +7 -0
  826. package/dist/ui/label.js +16 -0
  827. package/dist/ui/label.js.map +7 -0
  828. package/dist/ui/mark-menu.js +300 -0
  829. package/dist/ui/mark-menu.js.map +7 -0
  830. package/dist/ui/popover.js +40 -0
  831. package/dist/ui/popover.js.map +7 -0
  832. package/dist/ui/portal-container.js +17 -0
  833. package/dist/ui/portal-container.js.map +7 -0
  834. package/dist/ui/progress.js +24 -0
  835. package/dist/ui/progress.js.map +7 -0
  836. package/dist/ui/radio-group.js +29 -0
  837. package/dist/ui/radio-group.js.map +7 -0
  838. package/dist/ui/scroll-area.js +39 -0
  839. package/dist/ui/scroll-area.js.map +7 -0
  840. package/dist/ui/select.js +130 -0
  841. package/dist/ui/select.js.map +7 -0
  842. package/dist/ui/separator.js +23 -0
  843. package/dist/ui/separator.js.map +7 -0
  844. package/dist/ui/slider.js +23 -0
  845. package/dist/ui/slider.js.map +7 -0
  846. package/dist/ui/switch.js +28 -0
  847. package/dist/ui/switch.js.map +7 -0
  848. package/dist/ui/table.js +75 -0
  849. package/dist/ui/table.js.map +7 -0
  850. package/dist/ui/tabs.js +48 -0
  851. package/dist/ui/tabs.js.map +7 -0
  852. package/dist/ui/textarea.js +63 -0
  853. package/dist/ui/textarea.js.map +7 -0
  854. package/dist/ui/toggle-group.js +43 -0
  855. package/dist/ui/toggle-group.js.map +7 -0
  856. package/dist/ui/toggle.js +40 -0
  857. package/dist/ui/toggle.js.map +7 -0
  858. package/dist/ui/tooltip.js +215 -0
  859. package/dist/ui/tooltip.js.map +7 -0
  860. package/dist/usage-metered.js +8 -0
  861. package/dist/usage-metered.js.map +7 -0
  862. package/dist/useArbi.js +16 -0
  863. package/dist/useArbi.js.map +7 -0
  864. package/dist/useInstallSkillPack.js +81 -0
  865. package/dist/useInstallSkillPack.js.map +7 -0
  866. package/dist/usermenu/UserMenu.js +188 -0
  867. package/dist/usermenu/UserMenu.js.map +7 -0
  868. package/dist/usermenu/index.js +5 -0
  869. package/dist/usermenu/index.js.map +7 -0
  870. package/dist/users/index.js +15 -0
  871. package/dist/users/index.js.map +7 -0
  872. package/dist/users/user-display.js +60 -0
  873. package/dist/users/user-display.js.map +7 -0
  874. package/dist/viewers/AudioViewer.js +23 -0
  875. package/dist/viewers/AudioViewer.js.map +7 -0
  876. package/dist/viewers/DocxViewer.js +81 -0
  877. package/dist/viewers/DocxViewer.js.map +7 -0
  878. package/dist/viewers/ImageViewer.js +31 -0
  879. package/dist/viewers/ImageViewer.js.map +7 -0
  880. package/dist/viewers/PdfViewer.cjs +17 -0
  881. package/dist/viewers/PdfViewer.cjs.map +1 -0
  882. package/dist/viewers/PdfViewer.d.ts +9 -0
  883. package/dist/viewers/PdfViewer.js +20 -0
  884. package/dist/viewers/PdfViewer.js.map +7 -0
  885. package/dist/viewers/PdfViewerImpl.js +384 -0
  886. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  887. package/dist/viewers/VideoViewer.js +31 -0
  888. package/dist/viewers/VideoViewer.js.map +7 -0
  889. package/dist/viewers/XlsxViewer.js +102 -0
  890. package/dist/viewers/XlsxViewer.js.map +7 -0
  891. package/dist/viewers/index.cjs +79 -653
  892. package/dist/viewers/index.cjs.map +1 -1
  893. package/dist/viewers/index.d.ts +3 -1
  894. package/dist/viewers/index.js +60 -903
  895. package/dist/viewers/index.js.map +7 -1
  896. package/dist/viewers/page-scroll.js +59 -0
  897. package/dist/viewers/page-scroll.js.map +7 -0
  898. package/dist/viewers/pdf-viewer-constants.js +9 -0
  899. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  900. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  901. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  902. package/dist/viewers/selection-runs.js +38 -0
  903. package/dist/viewers/selection-runs.js.map +7 -0
  904. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  905. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  906. package/dist/viewers/useProcessedChunks.js +58 -0
  907. package/dist/viewers/useProcessedChunks.js.map +7 -0
  908. package/dist/viewers/viewer-zoom.js +163 -0
  909. package/dist/viewers/viewer-zoom.js.map +7 -0
  910. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  911. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  912. package/dist/websocket/context.js +14 -0
  913. package/dist/websocket/context.js.map +7 -0
  914. package/dist/websocket/hooks.js +30 -0
  915. package/dist/websocket/hooks.js.map +7 -0
  916. package/dist/websocket/index.js +22 -0
  917. package/dist/websocket/index.js.map +7 -0
  918. package/dist/websocket/live-updates.js +38 -0
  919. package/dist/websocket/live-updates.js.map +7 -0
  920. package/dist/websocket/reconnect.js +13 -0
  921. package/dist/websocket/reconnect.js.map +7 -0
  922. package/dist/websocket/store.js +58 -0
  923. package/dist/websocket/store.js.map +7 -0
  924. package/dist/workforce.js +607 -0
  925. package/dist/workforce.js.map +7 -0
  926. package/dist/workspaces/access-request.js +35 -0
  927. package/dist/workspaces/access-request.js.map +7 -0
  928. package/dist/workspaces/archive.js +59 -0
  929. package/dist/workspaces/archive.js.map +7 -0
  930. package/dist/workspaces/current.js +20 -0
  931. package/dist/workspaces/current.js.map +7 -0
  932. package/dist/workspaces/delete-workspaces.js +15 -0
  933. package/dist/workspaces/delete-workspaces.js.map +7 -0
  934. package/dist/workspaces/export-archive.js +40 -0
  935. package/dist/workspaces/export-archive.js.map +7 -0
  936. package/dist/workspaces/index.js +99 -0
  937. package/dist/workspaces/index.js.map +7 -0
  938. package/dist/workspaces/settings.js +45 -0
  939. package/dist/workspaces/settings.js.map +7 -0
  940. package/dist/workspaces/shell-workspaces.js +49 -0
  941. package/dist/workspaces/shell-workspaces.js.map +7 -0
  942. package/dist/workspaces/switch.js +234 -0
  943. package/dist/workspaces/switch.js.map +7 -0
  944. package/dist/workspaces/transfer.js +170 -0
  945. package/dist/workspaces/transfer.js.map +7 -0
  946. package/dist/workspaces/useShellWorkspaces.js +86 -0
  947. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  948. package/dist/workspaces/workspace-users.js +65 -0
  949. package/dist/workspaces/workspace-users.js.map +7 -0
  950. package/package.json +12 -4
  951. package/dist/PdfViewer.d-bQH9yxFg.d.ts +0 -55
  952. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  953. package/dist/annotations/freeze/index.d.cts +0 -205
  954. package/dist/annotations/index.d.cts +0 -360
  955. package/dist/artifacts/index.d.cts +0 -476
  956. package/dist/artifacts/redline-core.d.cts +0 -39
  957. package/dist/bundle-YNOX7VIL.js +0 -5
  958. package/dist/bundle-YNOX7VIL.js.map +0 -1
  959. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  960. package/dist/calls/livekit/index.d.cts +0 -280
  961. package/dist/chunk-47CCGUWR.js.map +0 -1
  962. package/dist/chunk-6H3O63TQ.js.map +0 -1
  963. package/dist/chunk-74N436VK.js.map +0 -1
  964. package/dist/chunk-APZZQZ6P.js +0 -147
  965. package/dist/chunk-APZZQZ6P.js.map +0 -1
  966. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  967. package/dist/chunk-CPQ3CU4B.js +0 -246
  968. package/dist/chunk-CPQ3CU4B.js.map +0 -1
  969. package/dist/chunk-DPYBZDJB.js.map +0 -1
  970. package/dist/chunk-DQALOQPI.js +0 -2766
  971. package/dist/chunk-DQALOQPI.js.map +0 -1
  972. package/dist/chunk-FZJMA32S.js +0 -1011
  973. package/dist/chunk-FZJMA32S.js.map +0 -1
  974. package/dist/chunk-H5M7FXLB.js +0 -2057
  975. package/dist/chunk-H5M7FXLB.js.map +0 -1
  976. package/dist/chunk-HDCRPPBW.js +0 -75
  977. package/dist/chunk-HDCRPPBW.js.map +0 -1
  978. package/dist/chunk-NIKPG4PW.js +0 -1128
  979. package/dist/chunk-NIKPG4PW.js.map +0 -1
  980. package/dist/chunk-NNAJLY6B.js +0 -4974
  981. package/dist/chunk-NNAJLY6B.js.map +0 -1
  982. package/dist/chunk-OYPKKHXY.js +0 -559
  983. package/dist/chunk-OYPKKHXY.js.map +0 -1
  984. package/dist/chunk-P6WLV5UY.js +0 -644
  985. package/dist/chunk-P6WLV5UY.js.map +0 -1
  986. package/dist/chunk-PTOP7OHG.js.map +0 -1
  987. package/dist/chunk-SN5YV6FF.js +0 -11
  988. package/dist/chunk-SN5YV6FF.js.map +0 -1
  989. package/dist/chunk-T3USOSVN.js.map +0 -1
  990. package/dist/chunk-T4CLW3DN.js +0 -2560
  991. package/dist/chunk-T4CLW3DN.js.map +0 -1
  992. package/dist/chunk-UW2SGTI5.js.map +0 -1
  993. package/dist/chunk-VSCU7K4V.js.map +0 -1
  994. package/dist/chunk-WL2Y2T47.js.map +0 -1
  995. package/dist/chunk-WUTL62MC.js.map +0 -1
  996. package/dist/chunk-Y3MTRA7D.js +0 -97
  997. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  998. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  999. package/dist/document-tools/core.d.cts +0 -883
  1000. package/dist/document-tools/index.d.cts +0 -90
  1001. package/dist/index.d-BMhTH98a.d.cts +0 -2035
  1002. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  1003. package/dist/index.d.cts +0 -15893
  1004. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  1005. package/dist/query-keys.d-ChgpJLPF.d.cts +0 -337
  1006. package/dist/shell/index.d.cts +0 -6
  1007. package/dist/store.d-GADDvC7w.d.cts +0 -35
  1008. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  1009. package/dist/ui/index.d.cts +0 -25
  1010. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  1011. package/dist/viewers/index.d.cts +0 -260
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/signature-requests.ts"],
4
+ "sourcesContent": ["/**\n * Signature requests: an author places fields (signature, initials, date, name) on the PDF of one\n * exact document version and assigns each to a signer: a workspace member (a guest too), or anyone\n * by email, who is invited to the workspace and signs once they join. A Word document's own\n * signature fields (Insert \u203A Signature field) come back from `suggest` placed exactly, with their\n * signer (`source: 'anchor'`). Each signer is then walked\n * through their fields, adopts a signature once and applies it at each. They sign ONCE for all of\n * their fields: the server's statement binds the PDF they were shown, every field they applied and\n * what they adopted. The last signature draws every field and seals the signed copy as the\n * document's next version (see `src/core/signature_requests.py` in ARBI).\n */\n\nimport { signMessage, unlockIdentityWithPassword, type components } from '@arbidocs/client'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { workspaces } from '@arbidocs/sdk/browser'\nimport { useDocumentTools, type DocumentToolsClient } from './environment'\nimport { intentText, sha256Hex, SigningError } from './signing'\nimport { arbiQueryKeys } from '../query-keys'\nimport { useArbiHost } from '../host/config'\n\n/**\n * The open workspace, when the host has an `Arbi` with one, and a guard that keeps a read made for\n * it only if that workspace stayed open on the server meanwhile (these lists are the open\n * workspace's there): a read that crosses a switch is dropped, never cached as another's.\n */\nfunction useOpenWorkspaceRead() {\n const arbi = useArbiHost().arbi\n const workspaceId = arbi?.hasWorkspace ? arbi.getWorkspaceId() : undefined\n const read = <T>(run: () => Promise<T>): Promise<T> =>\n arbi && workspaceId ? arbi.readInWorkspace(workspaceId, run) : run()\n return { workspaceId, read }\n}\n\nexport type SignatureField = components['schemas']['SignatureField']\nexport type SignatureFieldType = SignatureField['type']\nexport type SignatureRequest = components['schemas']['SignatureRequestResponse']\nexport type SignatureRequestSigner = components['schemas']['SignatureRequestSigner']\nexport type SignerProgress = components['schemas']['SignerProgress']\nexport type SuggestedSignatureField = components['schemas']['SuggestedSignatureField']\nexport type AdoptedSignature = components['schemas']['AdoptedSignature']\nexport type SignRequestSignResponse = components['schemas']['SignRequestSignResponse']\n\n/** Field types in the order the editor offers them. */\nexport const SIGNATURE_FIELD_TYPES: readonly SignatureFieldType[] = [\n 'signature',\n 'initials',\n 'date',\n 'name',\n]\n\nexport const FIELD_TYPE_LABELS: Record<SignatureFieldType, string> = {\n signature: 'Signature',\n initials: 'Initials',\n date: 'Date signed',\n name: 'Name',\n}\n\n/**\n * Default size of a new field, as fractions of the page (the backend draws to fit the box). The\n * same sizes the server's suggester places fields in (`esign_suggest._SIZE`).\n */\nexport const DEFAULT_FIELD_SIZE: Record<SignatureFieldType, { width: number; height: number }> = {\n signature: { width: 0.28, height: 0.05 },\n initials: { width: 0.1, height: 0.04 },\n date: { width: 0.22, height: 0.028 },\n name: { width: 0.28, height: 0.028 },\n}\n\n/** How far each signer has got, as the request's sender sees it. */\nexport const SIGNER_PROGRESS_LABELS: Record<SignerProgress, string> = {\n invited: 'Invited',\n registered: 'Not opened yet',\n viewed: 'Viewed',\n signed: 'Signed',\n declined: 'Declined',\n}\n\nconst EMAIL = /^[^@\\s<>,;]{1,64}@[^@\\s<>,;]{1,255}\\.[^@\\s<>,;]{1,63}$/\n\n/** Whether a field's signer is an email (someone to invite) rather than a member or request signer. */\nexport const isEmailSigner = (signer: string) => EMAIL.test(signer.trim())\n\n/** The fields carrying a signer's mark: every signer needs at least one to be sent the request. */\nexport const MARK_FIELD_TYPES: readonly SignatureFieldType[] = ['signature', 'initials']\n\nfunction detail(error: unknown, fallback: string): string {\n const d = (error as { detail?: unknown } | undefined)?.detail\n if (typeof d === 'string') return d\n if (Array.isArray(d) && d[0] && typeof d[0] === 'object' && 'msg' in d[0]) {\n return String((d[0] as { msg: unknown }).msg)\n }\n return fallback\n}\n\n/** A short unique id for a new field (the server only needs it unique within the request). */\nexport function newFieldId(): string {\n return `f${Math.random().toString(36).slice(2, 10)}`\n}\n\n/** Initials from a name: \"Olive M. Owner\" -> \"OMO\". */\nexport function initialsOf(name: string): string {\n return name\n .split(/\\s+/)\n .filter(Boolean)\n .map((part) => part[0]!.toUpperCase())\n .join('')\n .slice(0, 4)\n}\n\n/** The fields a signer completes, in the order they are walked through: page, then top to bottom. */\nexport function fieldsInSigningOrder(fields: SignatureField[], signer: string): SignatureField[] {\n return fields\n .filter((f) => f.signer === signer)\n .sort((a, b) => a.page - b.page || a.y - b.y || a.x - b.x)\n}\n\n/** Why a draft cannot be sent yet, or null when it can. Mirrors the server's checks. */\nexport function sendBlocker(fields: SignatureField[]): string | null {\n if (fields.length === 0) return 'Place at least one field.'\n const signers = [...new Set(fields.map((f) => f.signer))]\n for (const signer of signers) {\n if (!fields.some((f) => f.signer === signer && MARK_FIELD_TYPES.includes(f.type))) {\n return 'Every signer needs a signature or initials field.'\n }\n }\n return null\n}\n\n/**\n * Suggested fields grouped by signature block; `assign` maps a block (`group`) to the signer its\n * fields go to. A field placed in the Word document that names its signer goes to them: the\n * member with that email (`members`, by lowercased email), else the email itself (an invitee).\n * Unassigned blocks are left out.\n */\nexport function fieldsFromSuggestions(\n suggestions: SuggestedSignatureField[],\n assign: Record<number, string | undefined>,\n members: ReadonlyMap<string, string> = new Map()\n): SignatureField[] {\n return suggestions.flatMap((s) => {\n const email = s.signer_email?.toLowerCase()\n const signer = email ? (members.get(email) ?? email) : assign[s.group]\n if (!signer) return []\n return [\n {\n id: newFieldId(),\n type: s.type,\n page: s.page,\n x: s.x,\n y: s.y,\n width: s.width,\n height: s.height,\n signer,\n required: s.required ?? true,\n },\n ]\n })\n}\n\n/** The Word document's own fields (found by their anchors) and the optional layout suggestions. */\nexport function splitSuggestions(suggestions: SuggestedSignatureField[]) {\n return {\n placed: suggestions.filter((s) => s.source === 'anchor'),\n extras: suggestions.filter((s) => s.source !== 'anchor'),\n }\n}\n\n// \u2500\u2500 Reads \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function fetchDocumentSignatureRequests(\n client: DocumentToolsClient,\n documentId: string\n): Promise<SignatureRequest[]> {\n const { data, error } = await client.GET('/v1/document/{document_ext_id}/signature-requests', {\n params: { path: { document_ext_id: documentId } },\n })\n if (!data) throw new Error(detail(error, 'The signature requests could not be read'))\n return data\n}\n\n/** A document's signature requests, newest first. */\nexport function useDocumentSignatureRequests(\n documentId: string | null | undefined,\n enabled = true\n) {\n const { client } = useDocumentTools()\n return useQuery({\n queryKey: arbiQueryKeys.signatureRequestsForDocument(documentId ?? ''),\n queryFn: () => fetchDocumentSignatureRequests(client, documentId!),\n enabled: enabled && !!documentId,\n staleTime: 15_000,\n })\n}\n\n/** A signer the Word document's placed fields name, with the name they give. */\nexport interface NamedSigner {\n email: string\n name: string\n}\n\n/** What a document asks to be signed: the fields found, and the signers its Word fields name. */\nexport interface SignatureFieldSuggestions {\n fields: SuggestedSignatureField[]\n /**\n * Named even when the PDF shows none of the Word fields' anchors (the fields are then placed by\n * hand): who each email belongs to. Empty from a server that does not report them.\n */\n signers: NamedSigner[]\n}\n\nexport async function signatureFieldSuggestions(\n client: DocumentToolsClient,\n documentId: string,\n version?: number\n): Promise<SignatureFieldSuggestions> {\n const { data, error } = await client.GET(\n '/v1/document/{document_ext_id}/signature-fields/suggest',\n {\n params: { path: { document_ext_id: documentId }, ...(version ? { query: { version } } : {}) },\n }\n )\n if (!data) throw new Error(detail(error, 'Signature blocks could not be read'))\n return { fields: data.fields, signers: (data as { signers?: NamedSigner[] }).signers ?? [] }\n}\n\nexport async function suggestSignatureFields(\n client: DocumentToolsClient,\n documentId: string,\n version?: number\n): Promise<SuggestedSignatureField[]> {\n return (await signatureFieldSuggestions(client, documentId, version)).fields\n}\n\n// \u2500\u2500 Prepare \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SaveSignatureRequestVars {\n documentId: string\n /** The version the fields were placed on (the PDF shown). Omitted = current. */\n version?: number\n fields: SignatureField[]\n message?: string\n /** Existing draft to update instead of creating a new request. */\n requestId?: string\n /** Send it to the signers (else it is saved as a draft). */\n send: boolean\n}\n\nexport async function saveSignatureRequest(\n client: DocumentToolsClient,\n { documentId, version, fields, message, requestId, send }: SaveSignatureRequestVars\n): Promise<SignatureRequest> {\n if (!requestId) {\n const { data, error } = await client.POST('/v1/document/{document_ext_id}/signature-requests', {\n params: { path: { document_ext_id: documentId } },\n body: { fields, message: message || null, send, ...(version ? { version } : {}) },\n })\n if (!data) throw new Error(detail(error, 'The signature request could not be saved'))\n return data\n }\n const path = { request_ext_id: requestId }\n const updated = await client.PATCH('/v1/signature-requests/{request_ext_id}', {\n params: { path },\n body: { fields, message: message ?? null },\n })\n if (!updated.data) throw new Error(detail(updated.error, 'The draft could not be saved'))\n if (!send) return updated.data\n const sent = await client.POST('/v1/signature-requests/{request_ext_id}/send', {\n params: { path },\n })\n if (!sent.data) throw new Error(detail(sent.error, 'The request could not be sent'))\n return sent.data\n}\n\nfunction useInvalidateRequests() {\n const queryClient = useQueryClient()\n return () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.signatureRequests() })\n}\n\nexport function useSaveSignatureRequest() {\n const { client } = useDocumentTools()\n const invalidate = useInvalidateRequests()\n return useMutation({\n mutationFn: (vars: SaveSignatureRequestVars) => saveSignatureRequest(client, vars),\n onSuccess: invalidate,\n })\n}\n\nexport function useVoidSignatureRequest() {\n const { client } = useDocumentTools()\n const invalidate = useInvalidateRequests()\n return useMutation({\n mutationFn: async (requestId: string) => {\n const { data, error } = await client.POST('/v1/signature-requests/{request_ext_id}/void', {\n params: { path: { request_ext_id: requestId } },\n })\n if (!data) throw new Error(detail(error, 'The request could not be voided'))\n return data\n },\n onSuccess: invalidate,\n })\n}\n\nexport function useDeclineSignatureRequest() {\n const { client } = useDocumentTools()\n const invalidate = useInvalidateRequests()\n return useMutation({\n mutationFn: async ({ requestId, reason }: { requestId: string; reason?: string }) => {\n const { data, error } = await client.POST('/v1/signature-requests/{request_ext_id}/decline', {\n params: { path: { request_ext_id: requestId } },\n body: { reason: reason || null },\n })\n if (!data) throw new Error(detail(error, 'Could not decline'))\n return data\n },\n onSuccess: invalidate,\n })\n}\n\n// \u2500\u2500 Sign \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SignRequestVars {\n request: SignatureRequest\n /** The PDF the signer was walked through (`GET /view?version=` of the request's version). */\n pdfBlob: Blob\n email: string\n password: string\n adopted: AdoptedSignature\n /** The ids of the fields the signer applied: every required one of theirs. */\n fields: string[]\n}\n\n/**\n * Sign all of the signer's fields at once: the server prepares the statement, the browser checks\n * it covers the PDF on screen under the wording the signer read, re-derives the Ed25519 key from\n * the password and signs. Resolves with `completed` when this was the last signature.\n */\nexport async function signSignatureRequest(\n client: DocumentToolsClient,\n deploymentDomain: string,\n { request, pdfBlob, email, password, adopted, fields }: SignRequestVars\n): Promise<SignRequestSignResponse> {\n const path = { request_ext_id: request.external_id }\n const body = { adopted, fields }\n const prepared = await client.POST('/v1/signature-requests/{request_ext_id}/sign/prepare', {\n params: { path },\n body,\n })\n if (!prepared.data) {\n throw new SigningError(detail(prepared.error, 'Could not prepare signing'), 'failed')\n }\n const { statement, intent, source_sha256, timestamp } = prepared.data\n if (source_sha256 !== request.source_sha256 || (await sha256Hex(pdfBlob)) !== source_sha256) {\n throw new SigningError('The document changed since it was sent. Ask for it again.', 'stale')\n }\n if (intent !== intentText({ name: adopted.name })) {\n throw new Error('Signing statement mismatch; not signed.')\n }\n const identity = await unlockIdentityWithPassword(email, password, deploymentDomain)\n const signed = await client.POST('/v1/signature-requests/{request_ext_id}/sign', {\n params: { path },\n body: { ...body, timestamp, signature: signMessage(statement, identity) },\n })\n if (!signed.data) throw new SigningError(detail(signed.error, 'Signing failed'), 'failed')\n return signed.data\n}\n\nexport function useSignSignatureRequest() {\n const env = useDocumentTools()\n const invalidate = useInvalidateRequests()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (vars: SignRequestVars) => {\n if (!env.deploymentDomain) throw new Error('Signing is not set up: no deployment domain')\n return signSignatureRequest(env.client, env.deploymentDomain, vars)\n },\n onSuccess: async (result) => {\n await invalidate()\n if (result.completed && result.request.doc_ext_id) {\n await env.onDocumentsChanged?.([result.request.doc_ext_id], 'signed')\n await queryClient.invalidateQueries({ queryKey: arbiQueryKeys.documentSignatures() })\n }\n },\n })\n}\n\n// \u2500\u2500 Who can sign \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SignerCandidate {\n externalId: string\n name: string\n email: string\n role: string\n}\n\n/**\n * The people in the active workspace who may sign: owners, collaborators and guests (an agent never\n * does). The first one listed is the current user when they are a member.\n */\nexport function useSignerCandidates(enabled = true) {\n const { client, user } = useDocumentTools()\n const { workspaceId, read } = useOpenWorkspaceRead()\n return useQuery({\n queryKey: arbiQueryKeys.signatureCandidates(workspaceId ?? ''),\n queryFn: async (): Promise<SignerCandidate[]> => {\n const { data, error } = await read(() => client.GET('/v1/workspace/users'))\n if (!data) throw new Error(detail(error, 'The workspace members could not be read'))\n const people = data\n .filter((m) => m.user.external_id.startsWith('usr-'))\n .map((m) => ({\n externalId: m.user.external_id,\n name: [m.user.given_name, m.user.family_name].filter(Boolean).join(' ') || m.user.email,\n email: m.user.email,\n role: String(m.role),\n }))\n const me = user?.email?.toLowerCase()\n return [...people].sort(\n (a, b) => Number(b.email.toLowerCase() === me) - Number(a.email.toLowerCase() === me)\n )\n },\n enabled,\n staleTime: 60_000,\n })\n}\n\n// \u2500\u2500 Invite \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Invite signers who are not in the workspace yet, as guests, through the workspace's own invite\n * (`POST /v1/workspace/users` with `confirm_invite`): a registered person is added at once, anyone\n * else is emailed an invitation that lands on the document. Each is asked to sign when they join.\n * Only a workspace owner can invite.\n */\nexport async function inviteSigners(\n client: DocumentToolsClient,\n documentId: string,\n emails: string[]\n): Promise<void> {\n if (!emails.length) return\n const { error, response } = await client.POST('/v1/workspace/users', {\n body: workspaces.addWorkspaceMembersBody({\n emails,\n role: 'guest',\n confirm_invite: true,\n resource_type: 'document',\n resource_ext_id: documentId,\n }),\n })\n if (response.status === 409) {\n throw new Error('Share the document with the workspace before asking others to sign it.')\n }\n // 404 \"No users found to add\": everyone is a member already (nothing to do).\n if (error && response.status !== 404) {\n throw new Error(detail(error, 'The signers could not be invited'))\n }\n}\n\nexport function useInviteSigners() {\n const { client } = useDocumentTools()\n const invalidate = useInvalidateRequests()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: ({ documentId, emails }: { documentId: string; emails: string[] }) =>\n inviteSigners(client, documentId, emails),\n onSuccess: async () => {\n await invalidate()\n await queryClient.invalidateQueries({ queryKey: arbiQueryKeys.signatureCandidates() })\n },\n })\n}\n"],
5
+ "mappings": "AAYA,SAAS,aAAa,kCAAmD;AACzE,SAAS,aAAa,UAAU,sBAAsB;AACtD,SAAS,kBAAkB;AAC3B,SAAS,wBAAkD;AAC3D,SAAS,YAAY,WAAW,oBAAoB;AACpD,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAO5B,SAAS,uBAAuB;AAC9B,QAAM,OAAO,YAAY,EAAE;AAC3B,QAAM,cAAc,MAAM,eAAe,KAAK,eAAe,IAAI;AACjE,QAAM,OAAO,CAAI,QACf,QAAQ,cAAc,KAAK,gBAAgB,aAAa,GAAG,IAAI,IAAI;AACrE,SAAO,EAAE,aAAa,KAAK;AAC7B;AAYO,MAAM,wBAAuD;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,oBAAwD;AAAA,EACnE,WAAW;AAAA,EACX,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AACR;AAMO,MAAM,qBAAoF;AAAA,EAC/F,WAAW,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EACvC,UAAU,EAAE,OAAO,KAAK,QAAQ,KAAK;AAAA,EACrC,MAAM,EAAE,OAAO,MAAM,QAAQ,MAAM;AAAA,EACnC,MAAM,EAAE,OAAO,MAAM,QAAQ,MAAM;AACrC;AAGO,MAAM,yBAAyD;AAAA,EACpE,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AACZ;AAEA,MAAM,QAAQ;AAGP,MAAM,gBAAgB,CAAC,WAAmB,MAAM,KAAK,OAAO,KAAK,CAAC;AAGlE,MAAM,mBAAkD,CAAC,aAAa,UAAU;AAEvF,SAAS,OAAO,OAAgB,UAA0B;AACxD,QAAM,IAAK,OAA4C;AACvD,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC,MAAM,YAAY,SAAS,EAAE,CAAC,GAAG;AACzE,WAAO,OAAQ,EAAE,CAAC,EAAuB,GAAG;AAAA,EAC9C;AACA,SAAO;AACT;AAGO,SAAS,aAAqB;AACnC,SAAO,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACpD;AAGO,SAAS,WAAW,MAAsB;AAC/C,SAAO,KACJ,MAAM,KAAK,EACX,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,CAAC,EAAG,YAAY,CAAC,EACpC,KAAK,EAAE,EACP,MAAM,GAAG,CAAC;AACf;AAGO,SAAS,qBAAqB,QAA0B,QAAkC;AAC/F,SAAO,OACJ,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EACjC,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D;AAGO,SAAS,YAAY,QAAyC;AACnE,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,UAAU,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxD,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,OAAO,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,iBAAiB,SAAS,EAAE,IAAI,CAAC,GAAG;AACjF,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,sBACd,aACA,QACA,UAAuC,oBAAI,IAAI,GAC7B;AAClB,SAAO,YAAY,QAAQ,CAAC,MAAM;AAChC,UAAM,QAAQ,EAAE,cAAc,YAAY;AAC1C,UAAM,SAAS,QAAS,QAAQ,IAAI,KAAK,KAAK,QAAS,OAAO,EAAE,KAAK;AACrE,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,WAAO;AAAA,MACL;AAAA,QACE,IAAI,WAAW;AAAA,QACf,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,GAAG,EAAE;AAAA,QACL,GAAG,EAAE;AAAA,QACL,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV;AAAA,QACA,UAAU,EAAE,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAGO,SAAS,iBAAiB,aAAwC;AACvE,SAAO;AAAA,IACL,QAAQ,YAAY,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ;AAAA,IACvD,QAAQ,YAAY,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ;AAAA,EACzD;AACF;AAIA,eAAsB,+BACpB,QACA,YAC6B;AAC7B,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,IAAI,qDAAqD;AAAA,IAC5F,QAAQ,EAAE,MAAM,EAAE,iBAAiB,WAAW,EAAE;AAAA,EAClD,CAAC;AACD,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,0CAA0C,CAAC;AACpF,SAAO;AACT;AAGO,SAAS,6BACd,YACA,UAAU,MACV;AACA,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,SAAO,SAAS;AAAA,IACd,UAAU,cAAc,6BAA6B,cAAc,EAAE;AAAA,IACrE,SAAS,MAAM,+BAA+B,QAAQ,UAAW;AAAA,IACjE,SAAS,WAAW,CAAC,CAAC;AAAA,IACtB,WAAW;AAAA,EACb,CAAC;AACH;AAkBA,eAAsB,0BACpB,QACA,YACA,SACoC;AACpC,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO;AAAA,IACnC;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,WAAW,GAAG,GAAI,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAG;AAAA,IAC9F;AAAA,EACF;AACA,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,oCAAoC,CAAC;AAC9E,SAAO,EAAE,QAAQ,KAAK,QAAQ,SAAU,KAAqC,WAAW,CAAC,EAAE;AAC7F;AAEA,eAAsB,uBACpB,QACA,YACA,SACoC;AACpC,UAAQ,MAAM,0BAA0B,QAAQ,YAAY,OAAO,GAAG;AACxE;AAgBA,eAAsB,qBACpB,QACA,EAAE,YAAY,SAAS,QAAQ,SAAS,WAAW,KAAK,GAC7B;AAC3B,MAAI,CAAC,WAAW;AACd,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,qDAAqD;AAAA,MAC7F,QAAQ,EAAE,MAAM,EAAE,iBAAiB,WAAW,EAAE;AAAA,MAChD,MAAM,EAAE,QAAQ,SAAS,WAAW,MAAM,MAAM,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAAA,IAClF,CAAC;AACD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,0CAA0C,CAAC;AACpF,WAAO;AAAA,EACT;AACA,QAAM,OAAO,EAAE,gBAAgB,UAAU;AACzC,QAAM,UAAU,MAAM,OAAO,MAAM,2CAA2C;AAAA,IAC5E,QAAQ,EAAE,KAAK;AAAA,IACf,MAAM,EAAE,QAAQ,SAAS,WAAW,KAAK;AAAA,EAC3C,CAAC;AACD,MAAI,CAAC,QAAQ,KAAM,OAAM,IAAI,MAAM,OAAO,QAAQ,OAAO,8BAA8B,CAAC;AACxF,MAAI,CAAC,KAAM,QAAO,QAAQ;AAC1B,QAAM,OAAO,MAAM,OAAO,KAAK,gDAAgD;AAAA,IAC7E,QAAQ,EAAE,KAAK;AAAA,EACjB,CAAC;AACD,MAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,OAAO,KAAK,OAAO,+BAA+B,CAAC;AACnF,SAAO,KAAK;AACd;AAEA,SAAS,wBAAwB;AAC/B,QAAM,cAAc,eAAe;AACnC,SAAO,MAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,kBAAkB,EAAE,CAAC;AAC5F;AAEO,SAAS,0BAA0B;AACxC,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,aAAa,sBAAsB;AACzC,SAAO,YAAY;AAAA,IACjB,YAAY,CAAC,SAAmC,qBAAqB,QAAQ,IAAI;AAAA,IACjF,WAAW;AAAA,EACb,CAAC;AACH;AAEO,SAAS,0BAA0B;AACxC,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,aAAa,sBAAsB;AACzC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,cAAsB;AACvC,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,gDAAgD;AAAA,QACxF,QAAQ,EAAE,MAAM,EAAE,gBAAgB,UAAU,EAAE;AAAA,MAChD,CAAC;AACD,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,iCAAiC,CAAC;AAC3E,aAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,EACb,CAAC;AACH;AAEO,SAAS,6BAA6B;AAC3C,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,aAAa,sBAAsB;AACzC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,EAAE,WAAW,OAAO,MAA8C;AACnF,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,mDAAmD;AAAA,QAC3F,QAAQ,EAAE,MAAM,EAAE,gBAAgB,UAAU,EAAE;AAAA,QAC9C,MAAM,EAAE,QAAQ,UAAU,KAAK;AAAA,MACjC,CAAC;AACD,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,mBAAmB,CAAC;AAC7D,aAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,EACb,CAAC;AACH;AAoBA,eAAsB,qBACpB,QACA,kBACA,EAAE,SAAS,SAAS,OAAO,UAAU,SAAS,OAAO,GACnB;AAClC,QAAM,OAAO,EAAE,gBAAgB,QAAQ,YAAY;AACnD,QAAM,OAAO,EAAE,SAAS,OAAO;AAC/B,QAAM,WAAW,MAAM,OAAO,KAAK,wDAAwD;AAAA,IACzF,QAAQ,EAAE,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACD,MAAI,CAAC,SAAS,MAAM;AAClB,UAAM,IAAI,aAAa,OAAO,SAAS,OAAO,2BAA2B,GAAG,QAAQ;AAAA,EACtF;AACA,QAAM,EAAE,WAAW,QAAQ,eAAe,UAAU,IAAI,SAAS;AACjE,MAAI,kBAAkB,QAAQ,iBAAkB,MAAM,UAAU,OAAO,MAAO,eAAe;AAC3F,UAAM,IAAI,aAAa,6DAA6D,OAAO;AAAA,EAC7F;AACA,MAAI,WAAW,WAAW,EAAE,MAAM,QAAQ,KAAK,CAAC,GAAG;AACjD,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,QAAM,WAAW,MAAM,2BAA2B,OAAO,UAAU,gBAAgB;AACnF,QAAM,SAAS,MAAM,OAAO,KAAK,gDAAgD;AAAA,IAC/E,QAAQ,EAAE,KAAK;AAAA,IACf,MAAM,EAAE,GAAG,MAAM,WAAW,WAAW,YAAY,WAAW,QAAQ,EAAE;AAAA,EAC1E,CAAC;AACD,MAAI,CAAC,OAAO,KAAM,OAAM,IAAI,aAAa,OAAO,OAAO,OAAO,gBAAgB,GAAG,QAAQ;AACzF,SAAO,OAAO;AAChB;AAEO,SAAS,0BAA0B;AACxC,QAAM,MAAM,iBAAiB;AAC7B,QAAM,aAAa,sBAAsB;AACzC,QAAM,cAAc,eAAe;AACnC,SAAO,YAAY;AAAA,IACjB,YAAY,CAAC,SAA0B;AACrC,UAAI,CAAC,IAAI,iBAAkB,OAAM,IAAI,MAAM,6CAA6C;AACxF,aAAO,qBAAqB,IAAI,QAAQ,IAAI,kBAAkB,IAAI;AAAA,IACpE;AAAA,IACA,WAAW,OAAO,WAAW;AAC3B,YAAM,WAAW;AACjB,UAAI,OAAO,aAAa,OAAO,QAAQ,YAAY;AACjD,cAAM,IAAI,qBAAqB,CAAC,OAAO,QAAQ,UAAU,GAAG,QAAQ;AACpE,cAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,mBAAmB,EAAE,CAAC;AAAA,MACtF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAeO,SAAS,oBAAoB,UAAU,MAAM;AAClD,QAAM,EAAE,QAAQ,KAAK,IAAI,iBAAiB;AAC1C,QAAM,EAAE,aAAa,KAAK,IAAI,qBAAqB;AACnD,SAAO,SAAS;AAAA,IACd,UAAU,cAAc,oBAAoB,eAAe,EAAE;AAAA,IAC7D,SAAS,YAAwC;AAC/C,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,OAAO,IAAI,qBAAqB,CAAC;AAC1E,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,OAAO,OAAO,yCAAyC,CAAC;AACnF,YAAM,SAAS,KACZ,OAAO,CAAC,MAAM,EAAE,KAAK,YAAY,WAAW,MAAM,CAAC,EACnD,IAAI,CAAC,OAAO;AAAA,QACX,YAAY,EAAE,KAAK;AAAA,QACnB,MAAM,CAAC,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK;AAAA,QAClF,OAAO,EAAE,KAAK;AAAA,QACd,MAAM,OAAO,EAAE,IAAI;AAAA,MACrB,EAAE;AACJ,YAAM,KAAK,MAAM,OAAO,YAAY;AACpC,aAAO,CAAC,GAAG,MAAM,EAAE;AAAA,QACjB,CAAC,GAAG,MAAM,OAAO,EAAE,MAAM,YAAY,MAAM,EAAE,IAAI,OAAO,EAAE,MAAM,YAAY,MAAM,EAAE;AAAA,MACtF;AAAA,IACF;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb,CAAC;AACH;AAUA,eAAsB,cACpB,QACA,YACA,QACe;AACf,MAAI,CAAC,OAAO,OAAQ;AACpB,QAAM,EAAE,OAAO,SAAS,IAAI,MAAM,OAAO,KAAK,uBAAuB;AAAA,IACnE,MAAM,WAAW,wBAAwB;AAAA,MACvC;AAAA,MACA,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACD,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AAEA,MAAI,SAAS,SAAS,WAAW,KAAK;AACpC,UAAM,IAAI,MAAM,OAAO,OAAO,kCAAkC,CAAC;AAAA,EACnE;AACF;AAEO,SAAS,mBAAmB;AACjC,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,aAAa,sBAAsB;AACzC,QAAM,cAAc,eAAe;AACnC,SAAO,YAAY;AAAA,IACjB,YAAY,CAAC,EAAE,YAAY,OAAO,MAChC,cAAc,QAAQ,YAAY,MAAM;AAAA,IAC1C,WAAW,YAAY;AACrB,YAAM,WAAW;AACjB,YAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,oBAAoB,EAAE,CAAC;AAAA,IACvF;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,127 @@
1
+ import { signMessage, unlockIdentityWithPassword } from "@arbidocs/client";
2
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { parseVersionRef } from "../artifacts/versions.js";
4
+ import { useDocumentTools } from "./environment.js";
5
+ import { arbiQueryKeys } from "../query-keys.js";
6
+ function intentText(signer) {
7
+ return `I, ${signer.name.trim()}, sign this document electronically. I intend this electronic signature to have the same effect as my handwritten signature.`;
8
+ }
9
+ async function sha256Hex(blob) {
10
+ const digest = await crypto.subtle.digest("SHA-256", new Uint8Array(await blob.arrayBuffer()));
11
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
12
+ }
13
+ function toAppearance(box) {
14
+ return { page: box.page - 1, x: box.rect.x, y: box.rect.y, width: box.rect.w, height: box.rect.h };
15
+ }
16
+ const MIN_SIGNATURE_BOX = { width: 0.3, height: 0.07 };
17
+ function isLegibleSignatureBox(rect) {
18
+ return rect.w >= MIN_SIGNATURE_BOX.width && rect.h >= MIN_SIGNATURE_BOX.height;
19
+ }
20
+ const SIGNATURES_PATH = "/v1/document/{document_ext_id}/signatures";
21
+ function errorDetail(error, fallback) {
22
+ const detail = error?.detail;
23
+ return typeof detail === "string" ? detail : fallback;
24
+ }
25
+ async function fetchDocumentSignatures(client, documentRef) {
26
+ const { docId, version } = parseVersionRef(documentRef);
27
+ const { data, error } = await client.GET(SIGNATURES_PATH, {
28
+ params: { path: { document_ext_id: docId }, ...version ? { query: { version } } : {} }
29
+ });
30
+ if (!data) throw new Error(errorDetail(error, "The signatures could not be read"));
31
+ return data;
32
+ }
33
+ function useDocumentSignatures(documentId, enabled = true) {
34
+ const { client } = useDocumentTools();
35
+ const { docId, version } = parseVersionRef(documentId);
36
+ return useQuery({
37
+ queryKey: arbiQueryKeys.documentSignatures(docId ?? "", version),
38
+ queryFn: () => fetchDocumentSignatures(client, documentId),
39
+ enabled: enabled && !!docId,
40
+ staleTime: 6e4
41
+ });
42
+ }
43
+ class SigningError extends Error {
44
+ reason;
45
+ constructor(message, reason) {
46
+ super(message);
47
+ this.name = "SigningError";
48
+ this.reason = reason;
49
+ }
50
+ }
51
+ function signingErrorReason(detail) {
52
+ if (/still being prepared/i.test(detail)) return "preparing";
53
+ if (/no longer the current version/i.test(detail)) return "stale";
54
+ return "failed";
55
+ }
56
+ function signingError(error, fallback) {
57
+ const detail = errorDetail(error, fallback);
58
+ return new SigningError(detail, signingErrorReason(detail));
59
+ }
60
+ const PREPARE_RETRIES = 3;
61
+ const PREPARE_RETRY_DELAY_MS = 1500;
62
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
63
+ async function signDocument(client, deploymentDomain, {
64
+ documentId,
65
+ pdfBlob,
66
+ email,
67
+ password,
68
+ signer,
69
+ appearance,
70
+ includeDate = false,
71
+ version
72
+ }) {
73
+ const path = { document_ext_id: documentId };
74
+ const body = {
75
+ signer: { name: signer.name },
76
+ ...appearance ? { appearance } : {},
77
+ include_date: includeDate,
78
+ ...version ? { version } : {}
79
+ };
80
+ const prepare = () => client.POST("/v1/document/{document_ext_id}/sign/prepare", { params: { path }, body });
81
+ let prepared = await prepare();
82
+ for (let attempt = 0; !prepared.data && attempt < PREPARE_RETRIES; attempt++) {
83
+ if (signingError(prepared.error, "").reason !== "preparing") break;
84
+ await wait(PREPARE_RETRY_DELAY_MS);
85
+ prepared = await prepare();
86
+ }
87
+ if (!prepared.data) throw signingError(prepared.error, "Could not prepare signing");
88
+ const { statement, intent, source_sha256, timestamp } = prepared.data;
89
+ if (await sha256Hex(pdfBlob) !== source_sha256) {
90
+ throw new Error("The document changed since it was opened. Reopen it and sign again.");
91
+ }
92
+ if (intent !== intentText(signer)) throw new Error("Signing statement mismatch; not signed.");
93
+ const identity = await unlockIdentityWithPassword(email, password, deploymentDomain);
94
+ const signed = await client.POST("/v1/document/{document_ext_id}/sign", {
95
+ params: { path },
96
+ body: { ...body, timestamp, signature: signMessage(statement, identity) }
97
+ });
98
+ if (!signed.data) throw signingError(signed.error, "Signing failed");
99
+ return signed.data;
100
+ }
101
+ function useSignDocument() {
102
+ const env = useDocumentTools();
103
+ const queryClient = useQueryClient();
104
+ return useMutation({
105
+ mutationFn: (vars) => {
106
+ if (!env.deploymentDomain) throw new Error("Signing is not set up: no deployment domain");
107
+ return signDocument(env.client, env.deploymentDomain, vars);
108
+ },
109
+ onSuccess: async (result) => {
110
+ await env.onDocumentsChanged?.([result.doc_ext_id], "signed");
111
+ await queryClient.invalidateQueries({ queryKey: arbiQueryKeys.documentSignatures() });
112
+ }
113
+ });
114
+ }
115
+ export {
116
+ PREPARE_RETRIES,
117
+ SigningError,
118
+ fetchDocumentSignatures,
119
+ intentText,
120
+ isLegibleSignatureBox,
121
+ sha256Hex,
122
+ signDocument,
123
+ toAppearance,
124
+ useDocumentSignatures,
125
+ useSignDocument
126
+ };
127
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/signing.ts"],
4
+ "sourcesContent": ["/**\n * Electronic signing. The backend (`src/core/esign.py` in ARBI) defines what a signature binds;\n * the helpers mirror the two pieces the browser must reproduce exactly: the statement of intent\n * shown to the signer, and the SHA-256 of the PDF the viewer displayed.\n */\n\nimport { signMessage, unlockIdentityWithPassword, type components } from '@arbidocs/client'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { parseVersionRef } from '../artifacts/versions'\nimport { useDocumentTools, type DocumentToolsClient } from './environment'\nimport { arbiQueryKeys } from '../query-keys'\n\n/**\n * Who signs: the name only. A role, a firm or a place go on the page as ordinary annotation text,\n * which is not part of the signature.\n */\nexport type SignerDetails = components['schemas']['SignerDetails']\n\n/** Same sentence as `esign.intent_text`; the dialog refuses to sign if the server's differs. */\nexport function intentText(signer: SignerDetails): string {\n return `I, ${signer.name.trim()}, sign this document electronically. I intend this electronic signature to have the same effect as my handwritten signature.`\n}\n\nexport async function sha256Hex(blob: Blob): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new Uint8Array(await blob.arrayBuffer()))\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/** A signature box drawn on the annotation overlay, as the signing API's placement. */\nexport function toAppearance(box: {\n page: number\n rect: { x: number; y: number; w: number; h: number }\n}): { page: number; x: number; y: number; width: number; height: number } {\n // The layer counts pages from 1, the signing API from 0. Both use fractions of the page as\n // displayed, origin top-left.\n return { page: box.page - 1, x: box.rect.x, y: box.rect.y, width: box.rect.w, height: box.rect.h }\n}\n\n/**\n * The smallest box the backend can draw a legible signature in: the signer's name and the\n * details line shrink to fit, so a box under these fractions of the page is shrunk to near\n * unreadable size. The backend's own default box is 0.40 x 0.10.\n */\nconst MIN_SIGNATURE_BOX = { width: 0.3, height: 0.07 }\n\nexport function isLegibleSignatureBox(rect: { w: number; h: number }): boolean {\n return rect.w >= MIN_SIGNATURE_BOX.width && rect.h >= MIN_SIGNATURE_BOX.height\n}\n\n// \u2500\u2500 Signing through the API \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\u2500\n\nexport type SignatureAppearance = components['schemas']['SignatureAppearance']\nexport type SignatureStatusResponse = components['schemas']['SignatureStatusResponse']\nexport type SignatureRecord = components['schemas']['SignatureRecord']\nexport type SignDocumentResponse = components['schemas']['SignDocumentResponse']\n\nconst SIGNATURES_PATH = '/v1/document/{document_ext_id}/signatures'\n/**\n * The same key openapi-react-query gives this request (`['get', path, init]`), so a host that\n * reads or persists the API cache by path treats it like its own queries.\n */\n\nfunction errorDetail(error: unknown, fallback: string): string {\n const detail = (error as { detail?: unknown } | undefined)?.detail\n return typeof detail === 'string' ? detail : fallback\n}\n\n/** Whether a document version is a signed copy, and its signatures. */\nexport async function fetchDocumentSignatures(\n client: DocumentToolsClient,\n documentRef: string\n): Promise<SignatureStatusResponse> {\n const { docId, version } = parseVersionRef(documentRef)\n const { data, error } = await client.GET(SIGNATURES_PATH, {\n params: { path: { document_ext_id: docId }, ...(version ? { query: { version } } : {}) },\n })\n if (!data) throw new Error(errorDetail(error, 'The signatures could not be read'))\n return data\n}\n\n/**\n * Is a document version a signed copy? `documentId` is a document id (its current version) or a\n * version reference `doc-\u2026@v{n}`. Needs a React Query `QueryClientProvider`.\n */\nexport function useDocumentSignatures(documentId: string | null | undefined, enabled = true) {\n const { client } = useDocumentTools()\n const { docId, version } = parseVersionRef(documentId)\n return useQuery({\n queryKey: arbiQueryKeys.documentSignatures(docId ?? '', version),\n queryFn: () => fetchDocumentSignatures(client, documentId!),\n enabled: enabled && !!docId,\n staleTime: 60_000,\n })\n}\n\n/**\n * Why the server would not sign: the PDF of a Word or text document is still being rendered\n * (`preparing`, worth another try in a moment), or the version on screen is no longer the current\n * one (`stale`: only the current version can be signed, so the signer reopens it).\n */\nexport type SigningErrorReason = 'preparing' | 'stale' | 'failed'\n\nexport class SigningError extends Error {\n readonly reason: SigningErrorReason\n constructor(message: string, reason: SigningErrorReason) {\n super(message)\n this.name = 'SigningError'\n this.reason = reason\n }\n}\n\n/** The 409s the backend's signing router raises, told apart by their wording. */\nfunction signingErrorReason(detail: string): SigningErrorReason {\n if (/still being prepared/i.test(detail)) return 'preparing'\n if (/no longer the current version/i.test(detail)) return 'stale'\n return 'failed'\n}\n\nfunction signingError(error: unknown, fallback: string): SigningError {\n const detail = errorDetail(error, fallback)\n return new SigningError(detail, signingErrorReason(detail))\n}\n\n/** How often, and how long apart, a prepare is retried while the PDF is still being rendered. */\nexport const PREPARE_RETRIES = 3\nconst PREPARE_RETRY_DELAY_MS = 1500\n\nconst wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))\n\nexport interface SignDocumentVars {\n documentId: string\n /**\n * The PDF bytes the viewer is showing (`GET /view?version=`, never the original's download): the\n * signer signs exactly these.\n */\n pdfBlob: Blob\n /**\n * The version `pdfBlob` is of. The server signs only the current version and refuses\n * (`SigningError` `stale`) when this one has been superseded. Omitted = the current version.\n */\n version?: number\n email: string\n password: string\n signer: SignerDetails\n /** Where the signature goes; omitted = the backend default (bottom of the last page). */\n appearance?: SignatureAppearance\n /** Draw the signing date under the signature. Default off: only the signature is drawn. */\n includeDate?: boolean\n}\n\n/**\n * Sign a document: the server prepares the statement, the browser checks that it covers the PDF\n * on screen under the wording the signer read, re-derives the user's Ed25519 key from their\n * password and signs it, and the server seals the signed copy as a new version.\n *\n * What is drawn on the page is only the signature (the signer's name as the signature mark) and,\n * with `includeDate`, the date; anyone can click it to open its certificate. A role, a firm or a\n * place go on the page as ordinary annotation text, which is not part of the signature.\n */\nexport async function signDocument(\n client: DocumentToolsClient,\n deploymentDomain: string,\n {\n documentId,\n pdfBlob,\n email,\n password,\n signer,\n appearance,\n includeDate = false,\n version,\n }: SignDocumentVars\n): Promise<SignDocumentResponse> {\n const path = { document_ext_id: documentId }\n // One body for both calls: the server refuses a /sign whose include_date (or placement) differs\n // from what was prepared, since what the signature shows is part of what is signed.\n const body = {\n signer: { name: signer.name },\n ...(appearance ? { appearance } : {}),\n include_date: includeDate,\n ...(version ? { version } : {}),\n }\n\n // A Word or text document's PDF is rendered after upload: while it is, prepare says so, and a\n // short wait usually sees it ready.\n const prepare = () =>\n client.POST('/v1/document/{document_ext_id}/sign/prepare', { params: { path }, body })\n let prepared = await prepare()\n for (let attempt = 0; !prepared.data && attempt < PREPARE_RETRIES; attempt++) {\n if (signingError(prepared.error, '').reason !== 'preparing') break\n await wait(PREPARE_RETRY_DELAY_MS)\n prepared = await prepare()\n }\n if (!prepared.data) throw signingError(prepared.error, 'Could not prepare signing')\n const { statement, intent, source_sha256, timestamp } = prepared.data\n // Sign only what was on screen, under the wording the signer read.\n if ((await sha256Hex(pdfBlob)) !== source_sha256) {\n throw new Error('The document changed since it was opened. Reopen it and sign again.')\n }\n if (intent !== intentText(signer)) throw new Error('Signing statement mismatch; not signed.')\n\n // The re-typed password must open the session's identity, which is the key the server verifies.\n const identity = await unlockIdentityWithPassword(email, password, deploymentDomain)\n const signed = await client.POST('/v1/document/{document_ext_id}/sign', {\n params: { path },\n body: { ...body, timestamp, signature: signMessage(statement, identity) },\n })\n if (!signed.data) throw signingError(signed.error, 'Signing failed')\n return signed.data\n}\n\n/** The signing mutation. On success the host hears the document changed (`'signed'`). */\nexport function useSignDocument() {\n const env = useDocumentTools()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (vars: SignDocumentVars) => {\n if (!env.deploymentDomain) throw new Error('Signing is not set up: no deployment domain')\n return signDocument(env.client, env.deploymentDomain, vars)\n },\n onSuccess: async (result) => {\n // The signed copy is the document's new current version: the host refreshes its row,\n // versions and rendered PDF, and the signature badge reads again.\n await env.onDocumentsChanged?.([result.doc_ext_id], 'signed')\n await queryClient.invalidateQueries({ queryKey: arbiQueryKeys.documentSignatures() })\n },\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,38 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useDocumentTools } from "./environment.js";
3
+ import { fetchDocumentFile, fetchDocumentPdf } from "./document-pdf.js";
4
+ import { documentBytesKey } from "../query-keys.js";
5
+ import { documentBytesKey as documentBytesKey2 } from "../query-keys.js";
6
+ function useDocumentBytes(documentRef, options) {
7
+ const { client } = useDocumentTools();
8
+ const { version, kind, enabled = true, fallback } = options;
9
+ return useQuery({
10
+ queryKey: documentBytesKey2(documentRef, version ?? null, kind),
11
+ queryFn: async ({ signal }) => {
12
+ if (fallback && typeof navigator !== "undefined" && navigator.onLine === false) {
13
+ const offline = await fallback();
14
+ if (offline) return offline;
15
+ }
16
+ try {
17
+ return await (kind === "original" ? fetchDocumentFile : fetchDocumentPdf)(
18
+ client,
19
+ documentRef,
20
+ { signal }
21
+ );
22
+ } catch (error) {
23
+ const offline = await fallback?.();
24
+ if (offline) return offline;
25
+ throw error;
26
+ }
27
+ },
28
+ enabled: enabled && !!documentRef,
29
+ // 'always' so it still runs offline: the fallback serves a copy kept on this device.
30
+ networkMode: "always",
31
+ staleTime: Infinity
32
+ });
33
+ }
34
+ export {
35
+ documentBytesKey,
36
+ useDocumentBytes
37
+ };
38
+ //# sourceMappingURL=useDocumentBytes.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/useDocumentBytes.ts"],
4
+ "sourcesContent": ["/**\n * The bytes a document viewer shows: the PDF of a document version (`/view`), or for media the\n * stored file itself (`/download`), through the host's API client. Keyed on the version, since a\n * document keeps its id across versions: a new version (a save, a signed copy) must never show the\n * previous one's file.\n */\nimport { useQuery } from '@tanstack/react-query'\nimport { useDocumentTools } from './environment'\nimport { fetchDocumentFile, fetchDocumentPdf } from './document-pdf'\n\nimport type { DocumentBytesKind } from '../query-keys'\nexport type { DocumentBytesKind }\n\nexport { documentBytesKey } from '../query-keys'\nimport { documentBytesKey } from '../query-keys'\n\nexport interface UseDocumentBytesOptions {\n /** The document's current version, so a new one reads afresh. */\n version: number | null | undefined\n kind: DocumentBytesKind\n enabled?: boolean\n /**\n * Bytes to use when the network cannot give them (a copy kept on this device): asked first when\n * offline, and again when the request fails.\n */\n fallback?: () => Promise<Blob | undefined>\n}\n\n/** A document's (or version reference's) bytes; see {@link UseDocumentBytesOptions}. */\nexport function useDocumentBytes(documentRef: string, options: UseDocumentBytesOptions) {\n const { client } = useDocumentTools()\n const { version, kind, enabled = true, fallback } = options\n return useQuery({\n queryKey: documentBytesKey(documentRef, version ?? null, kind),\n queryFn: async ({ signal }) => {\n if (fallback && typeof navigator !== 'undefined' && navigator.onLine === false) {\n const offline = await fallback()\n if (offline) return offline\n }\n try {\n return await (kind === 'original' ? fetchDocumentFile : fetchDocumentPdf)(\n client,\n documentRef,\n { signal }\n )\n } catch (error) {\n const offline = await fallback?.()\n if (offline) return offline\n throw error\n }\n },\n enabled: enabled && !!documentRef,\n // 'always' so it still runs offline: the fallback serves a copy kept on this device.\n networkMode: 'always',\n staleTime: Infinity,\n })\n}\n"],
5
+ "mappings": "AAMA,SAAS,gBAAgB;AACzB,SAAS,wBAAwB;AACjC,SAAS,mBAAmB,wBAAwB;AAKpD,SAAS,wBAAwB;AACjC,SAAS,oBAAAA,yBAAwB;AAe1B,SAAS,iBAAiB,aAAqB,SAAkC;AACtF,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,EAAE,SAAS,MAAM,UAAU,MAAM,SAAS,IAAI;AACpD,SAAO,SAAS;AAAA,IACd,UAAUA,kBAAiB,aAAa,WAAW,MAAM,IAAI;AAAA,IAC7D,SAAS,OAAO,EAAE,OAAO,MAAM;AAC7B,UAAI,YAAY,OAAO,cAAc,eAAe,UAAU,WAAW,OAAO;AAC9E,cAAM,UAAU,MAAM,SAAS;AAC/B,YAAI,QAAS,QAAO;AAAA,MACtB;AACA,UAAI;AACF,eAAO,OAAO,SAAS,aAAa,oBAAoB;AAAA,UACtD;AAAA,UACA;AAAA,UACA,EAAE,OAAO;AAAA,QACX;AAAA,MACF,SAAS,OAAO;AACd,cAAM,UAAU,MAAM,WAAW;AACjC,YAAI,QAAS,QAAO;AACpB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS,WAAW,CAAC,CAAC;AAAA;AAAA,IAEtB,aAAa;AAAA,IACb,WAAW;AAAA,EACb,CAAC;AACH;",
6
+ "names": ["documentBytesKey"]
7
+ }
@@ -0,0 +1,154 @@
1
+ import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { useDocumentTools } from "./environment.js";
3
+ import { SIGNED_LOCKED_REASON, fetchMarkupPdf } from "./markup-download.js";
4
+ import {
5
+ copyOpenThreads,
6
+ forgetLegacyLayer,
7
+ migrateLegacyLayer,
8
+ readLegacyLayer,
9
+ versionsWithMarkup
10
+ } from "./markup-transfer.js";
11
+ const SIGNED_UNCHANGED = "The signed PDF is unchanged: the comments are kept beside it as markup.";
12
+ function useDocumentMarkup(documentData, snapshotVersion, currentSigned = false) {
13
+ const { client, notify, saveFile, onDocumentsChanged } = useDocumentTools();
14
+ const documentId = documentData?.external_id;
15
+ const currentVersion = documentData?.current_version ?? 1;
16
+ const shownVersion = snapshotVersion ?? currentVersion;
17
+ const versions = useMemo(() => documentData?.versions ?? [], [documentData?.versions]);
18
+ const [localCounts, setLocalCounts] = useState({});
19
+ const countOf = useCallback(
20
+ (n) => localCounts[`${documentId}@${n}`] ?? versions.find((v) => v.n === n)?.markup_count ?? 0,
21
+ [localCounts, documentId, versions]
22
+ );
23
+ const hasMarkup = countOf(shownVersion) > 0;
24
+ const [showOriginal, setShowOriginal] = useState(false);
25
+ useEffect(() => setShowOriginal(false), [documentId, snapshotVersion]);
26
+ const refresh = useCallback(() => {
27
+ if (!documentId || !onDocumentsChanged) return;
28
+ Promise.resolve(onDocumentsChanged([documentId], "markup")).catch(
29
+ (e) => console.warn("Could not refresh the document after a markup change", e)
30
+ );
31
+ }, [documentId, onDocumentsChanged]);
32
+ const onMarkupChange = useCallback(
33
+ (snapshot) => {
34
+ if (!documentId) return;
35
+ const key = `${documentId}@${shownVersion}`;
36
+ if (countOf(shownVersion) > 0 !== snapshot.count > 0) refresh();
37
+ setLocalCounts((counts) => ({ ...counts, [key]: snapshot.count }));
38
+ },
39
+ [documentId, shownVersion, countOf, refresh]
40
+ );
41
+ const downloadMarkup = useCallback(async () => {
42
+ if (!documentId) return;
43
+ if (currentSigned) {
44
+ notify(SIGNED_LOCKED_REASON, "info");
45
+ return;
46
+ }
47
+ try {
48
+ const { blob, fileName } = await fetchMarkupPdf(
49
+ client,
50
+ documentId,
51
+ snapshotVersion ? snapshotVersion : void 0
52
+ );
53
+ saveFile(blob, fileName);
54
+ } catch (e) {
55
+ notify(e instanceof Error ? e.message : "The markup could not be downloaded", "error");
56
+ }
57
+ }, [client, documentId, snapshotVersion, saveFile, notify, currentSigned]);
58
+ const [legacyCount, setLegacyCount] = useState(0);
59
+ const [migrating, setMigrating] = useState(false);
60
+ const shared = documentData?.shared;
61
+ const loaded = !!documentData;
62
+ const migrate = useCallback(async () => {
63
+ if (!documentId) return;
64
+ const layer = readLegacyLayer(documentId);
65
+ if (!layer) return;
66
+ setMigrating(true);
67
+ try {
68
+ const added = await migrateLegacyLayer(documentId, layer, versions, currentVersion, client);
69
+ setLegacyCount(0);
70
+ setLocalCounts({});
71
+ refresh();
72
+ if (added > 0) {
73
+ notify(
74
+ `${added} annotation${added === 1 ? "" : "s"} from this browser saved to the document`,
75
+ "success",
76
+ {
77
+ description: shared ? "They are now part of the shared markup." : "They are saved with the document, visible only to you."
78
+ }
79
+ );
80
+ }
81
+ } catch (e) {
82
+ notify(
83
+ e instanceof Error ? e.message : "The annotations from this browser could not be saved",
84
+ "error",
85
+ { description: "They are still kept in this browser; open the document again to retry." }
86
+ );
87
+ } finally {
88
+ setMigrating(false);
89
+ }
90
+ }, [client, documentId, versions, currentVersion, refresh, shared, notify]);
91
+ useEffect(() => {
92
+ if (!documentId || !loaded) return;
93
+ const layer = readLegacyLayer(documentId);
94
+ if (!layer) {
95
+ setLegacyCount(0);
96
+ return;
97
+ }
98
+ if (layer.annotations.length === 0) {
99
+ forgetLegacyLayer(documentId);
100
+ setLegacyCount(0);
101
+ return;
102
+ }
103
+ if (shared) setLegacyCount(layer.annotations.length);
104
+ else void migrate();
105
+ }, [documentId, loaded, shared]);
106
+ const legacyPrompt = legacyCount > 0 && !snapshotVersion ? {
107
+ count: legacyCount,
108
+ busy: migrating,
109
+ add: () => void migrate(),
110
+ discard: () => {
111
+ if (documentId) forgetLegacyLayer(documentId);
112
+ setLegacyCount(0);
113
+ }
114
+ } : null;
115
+ const [copying, setCopying] = useState(false);
116
+ const olderWithMarkup = versionsWithMarkup(versions).filter((v) => v.n !== currentVersion).sort((a, b) => b.n - a.n)[0];
117
+ const olderNote = !snapshotVersion && !hasMarkup && olderWithMarkup ? {
118
+ version: olderWithMarkup.n,
119
+ busy: copying,
120
+ signed: currentSigned,
121
+ copy: () => {
122
+ if (!documentId) return;
123
+ setCopying(true);
124
+ copyOpenThreads(documentId, olderWithMarkup.n, client).then((n) => {
125
+ if (n > 0) {
126
+ setLocalCounts((c) => ({ ...c, [`${documentId}@${currentVersion}`]: n }));
127
+ refresh();
128
+ }
129
+ notify(
130
+ n > 0 ? `${n} open comment thread${n === 1 ? "" : "s"} copied to version ${currentVersion}` : `Version ${olderWithMarkup.n} has no open comments`,
131
+ n > 0 ? "success" : "info",
132
+ // The markup is stored beside the version, so the sealed bytes do not change.
133
+ n > 0 && currentSigned ? { description: SIGNED_UNCHANGED } : void 0
134
+ );
135
+ }).catch(
136
+ (e) => notify(e instanceof Error ? e.message : "The comments could not be copied", "error")
137
+ ).finally(() => setCopying(false));
138
+ }
139
+ } : null;
140
+ return {
141
+ hasMarkup,
142
+ showOriginal,
143
+ setShowOriginal,
144
+ onMarkupChange,
145
+ downloadMarkup,
146
+ legacyPrompt,
147
+ olderNote
148
+ };
149
+ }
150
+ export {
151
+ SIGNED_UNCHANGED,
152
+ useDocumentMarkup
153
+ };
154
+ //# sourceMappingURL=useDocumentMarkup.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/useDocumentMarkup.ts"],
4
+ "sourcesContent": ["/**\n * Markup state for the document page: whether the version on screen has markup (so the viewer\n * opens on it, the default view), the \"Show original\" toggle, \"Download with markup\", the one-time\n * migration of this browser's old annotation layer, and the note shown when the markup is on an\n * older version (with \"copy open comments\").\n *\n * Whether a version has markup comes from the document's version entries (`markup_count`), kept\n * current by the viewer's own saves (`onMarkupChange`) until the document is refetched.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useDocumentTools } from './environment'\nimport type { MarkupSnapshot } from './markup-store'\nimport { SIGNED_LOCKED_REASON, fetchMarkupPdf } from './markup-download'\nimport {\n copyOpenThreads,\n forgetLegacyLayer,\n migrateLegacyLayer,\n readLegacyLayer,\n versionsWithMarkup,\n type VersionInfo,\n} from './markup-transfer'\n\nexport const SIGNED_UNCHANGED =\n 'The signed PDF is unchanged: the comments are kept beside it as markup.'\n\nexport interface MarkupDocument {\n external_id: string\n shared?: boolean | null\n current_version?: number | null\n versions?: VersionInfo[] | null\n}\n\nexport interface LegacyPrompt {\n count: number\n busy: boolean\n add: () => void\n discard: () => void\n}\n\nexport interface OlderMarkupNote {\n version: number\n busy: boolean\n /** The current version is a signed copy: say that copying leaves its signed PDF as it is. */\n signed: boolean\n copy: () => void\n}\n\nexport function useDocumentMarkup(\n documentData: MarkupDocument | null | undefined,\n /** The version on screen when it is an older one (a read-only snapshot). */\n snapshotVersion: number | undefined,\n /**\n * Whether the version on screen is a signed, sealed copy: locked, so no \"Download with markup\"\n * (and, for the current version, copied comments leave its signed PDF as it is).\n */\n currentSigned = false\n) {\n const { client, notify, saveFile, onDocumentsChanged } = useDocumentTools()\n const documentId = documentData?.external_id\n const currentVersion = documentData?.current_version ?? 1\n const shownVersion = snapshotVersion ?? currentVersion\n const versions = useMemo(() => documentData?.versions ?? [], [documentData?.versions])\n\n // Counts from this session's saves win over the (possibly stale) document record.\n const [localCounts, setLocalCounts] = useState<Record<string, number>>({})\n const countOf = useCallback(\n (n: number) =>\n localCounts[`${documentId}@${n}`] ?? versions.find((v) => v.n === n)?.markup_count ?? 0,\n [localCounts, documentId, versions]\n )\n const hasMarkup = countOf(shownVersion) > 0\n\n const [showOriginal, setShowOriginal] = useState(false)\n useEffect(() => setShowOriginal(false), [documentId, snapshotVersion])\n\n const refresh = useCallback(() => {\n if (!documentId || !onDocumentsChanged) return\n Promise.resolve(onDocumentsChanged([documentId], 'markup')).catch((e: unknown) =>\n console.warn('Could not refresh the document after a markup change', e)\n )\n }, [documentId, onDocumentsChanged])\n\n const onMarkupChange = useCallback(\n (snapshot: MarkupSnapshot) => {\n if (!documentId) return\n const key = `${documentId}@${shownVersion}`\n // The list's \"Download with markup\" and the version entries follow the first/last mark.\n if (countOf(shownVersion) > 0 !== snapshot.count > 0) refresh()\n setLocalCounts((counts) => ({ ...counts, [key]: snapshot.count }))\n },\n [documentId, shownVersion, countOf, refresh]\n )\n\n const downloadMarkup = useCallback(async () => {\n if (!documentId) return\n // A signed version is locked: its markup is never written into its PDF.\n if (currentSigned) {\n notify(SIGNED_LOCKED_REASON, 'info')\n return\n }\n try {\n const { blob, fileName } = await fetchMarkupPdf(\n client,\n documentId,\n snapshotVersion ? snapshotVersion : undefined\n )\n saveFile(blob, fileName)\n } catch (e) {\n notify(e instanceof Error ? e.message : 'The markup could not be downloaded', 'error')\n }\n }, [client, documentId, snapshotVersion, saveFile, notify, currentSigned])\n\n // --- Migration of this browser's layer (arbi:annotations:<docId>) ---\n const [legacyCount, setLegacyCount] = useState(0)\n const [migrating, setMigrating] = useState(false)\n const shared = documentData?.shared\n const loaded = !!documentData\n\n const migrate = useCallback(async () => {\n if (!documentId) return\n const layer = readLegacyLayer(documentId)\n if (!layer) return\n setMigrating(true)\n try {\n const added = await migrateLegacyLayer(documentId, layer, versions, currentVersion, client)\n setLegacyCount(0)\n setLocalCounts({})\n refresh()\n if (added > 0) {\n notify(\n `${added} annotation${added === 1 ? '' : 's'} from this browser saved to the document`,\n 'success',\n {\n description: shared\n ? 'They are now part of the shared markup.'\n : 'They are saved with the document, visible only to you.',\n }\n )\n }\n } catch (e) {\n notify(\n e instanceof Error ? e.message : 'The annotations from this browser could not be saved',\n 'error',\n { description: 'They are still kept in this browser; open the document again to retry.' }\n )\n } finally {\n setMigrating(false)\n }\n }, [client, documentId, versions, currentVersion, refresh, shared, notify])\n\n useEffect(() => {\n if (!documentId || !loaded) return\n const layer = readLegacyLayer(documentId)\n if (!layer) {\n setLegacyCount(0)\n return\n }\n if (layer.annotations.length === 0) {\n forgetLegacyLayer(documentId)\n setLegacyCount(0)\n return\n }\n // A private document is the user's own: its old layer simply becomes its markup. A shared one\n // would show the marks to everyone, so the user decides.\n if (shared) setLegacyCount(layer.annotations.length)\n else void migrate()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [documentId, loaded, shared])\n\n const legacyPrompt: LegacyPrompt | null =\n legacyCount > 0 && !snapshotVersion\n ? {\n count: legacyCount,\n busy: migrating,\n add: () => void migrate(),\n discard: () => {\n if (documentId) forgetLegacyLayer(documentId)\n setLegacyCount(0)\n },\n }\n : null\n\n // --- Markup on an older version (a newer version starts with none) ---\n const [copying, setCopying] = useState(false)\n const olderWithMarkup = versionsWithMarkup(versions)\n .filter((v) => v.n !== currentVersion)\n .sort((a, b) => b.n - a.n)[0]\n const olderNote: OlderMarkupNote | null =\n !snapshotVersion && !hasMarkup && olderWithMarkup\n ? {\n version: olderWithMarkup.n,\n busy: copying,\n signed: currentSigned,\n copy: () => {\n if (!documentId) return\n setCopying(true)\n copyOpenThreads(documentId, olderWithMarkup.n, client)\n .then((n) => {\n if (n > 0) {\n setLocalCounts((c) => ({ ...c, [`${documentId}@${currentVersion}`]: n }))\n refresh()\n }\n notify(\n n > 0\n ? `${n} open comment thread${n === 1 ? '' : 's'} copied to version ${currentVersion}`\n : `Version ${olderWithMarkup.n} has no open comments`,\n n > 0 ? 'success' : 'info',\n // The markup is stored beside the version, so the sealed bytes do not change.\n n > 0 && currentSigned ? { description: SIGNED_UNCHANGED } : undefined\n )\n })\n .catch((e: unknown) =>\n notify(e instanceof Error ? e.message : 'The comments could not be copied', 'error')\n )\n .finally(() => setCopying(false))\n },\n }\n : null\n\n return {\n hasMarkup,\n showOriginal,\n setShowOriginal,\n onMarkupChange,\n downloadMarkup,\n legacyPrompt,\n olderNote,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { onlineManager } from "@tanstack/react-query";
3
+ function useIsOnline() {
4
+ return useSyncExternalStore(
5
+ (onChange) => onlineManager.subscribe(onChange),
6
+ () => onlineManager.isOnline(),
7
+ () => true
8
+ );
9
+ }
10
+ export {
11
+ useIsOnline
12
+ };
13
+ //# sourceMappingURL=useIsOnline.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/useIsOnline.ts"],
4
+ "sourcesContent": ["/**\n * Reactive connectivity from React Query's `onlineManager` (the browser's online events, plus\n * whatever the host feeds it, e.g. a WebSocket). The markup autosave waits while it is false.\n */\n\nimport { useSyncExternalStore } from 'react'\nimport { onlineManager } from '@tanstack/react-query'\n\nexport function useIsOnline(): boolean {\n return useSyncExternalStore(\n (onChange) => onlineManager.subscribe(onChange),\n () => onlineManager.isOnline(),\n () => true\n )\n}\n"],
5
+ "mappings": "AAKA,SAAS,4BAA4B;AACrC,SAAS,qBAAqB;AAEvB,SAAS,cAAuB;AACrC,SAAO;AAAA,IACL,CAAC,aAAa,cAAc,UAAU,QAAQ;AAAA,IAC9C,MAAM,cAAc,SAAS;AAAA,IAC7B,MAAM;AAAA,EACR;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,60 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useDocumentTools } from "./environment.js";
3
+ import { sha256Hex } from "./signing.js";
4
+ import { arbiQueryKeys } from "../query-keys.js";
5
+ const VERIFY_PATH = "/v1/sign/verify/{reference}";
6
+ const REFERENCE = /^sig-[0-9a-f]{32}$/;
7
+ function isSignatureReference(reference) {
8
+ return !!reference && REFERENCE.test(reference);
9
+ }
10
+ class SignatureVerificationError extends Error {
11
+ constructor(message, status) {
12
+ super(message);
13
+ this.status = status;
14
+ this.name = "SignatureVerificationError";
15
+ }
16
+ status;
17
+ }
18
+ const VERIFY_ERRORS = {
19
+ 404: "No signature has this reference.",
20
+ 429: "Too many checks, try again in a minute."
21
+ };
22
+ async function fetchSignatureVerification(client, reference) {
23
+ if (!isSignatureReference(reference)) {
24
+ throw new SignatureVerificationError("This is not a signature reference.");
25
+ }
26
+ const { data, response } = await client.GET(VERIFY_PATH, {
27
+ params: { path: { reference } }
28
+ });
29
+ if (!response.ok || !data) {
30
+ throw new SignatureVerificationError(
31
+ VERIFY_ERRORS[response.status] ?? "The signature could not be checked right now.",
32
+ response.status
33
+ );
34
+ }
35
+ return data;
36
+ }
37
+ function useSignatureVerification(reference) {
38
+ const { client } = useDocumentTools();
39
+ return useQuery({
40
+ queryKey: arbiQueryKeys.signatureVerification(reference ?? ""),
41
+ queryFn: () => fetchSignatureVerification(client, reference),
42
+ enabled: !!reference,
43
+ retry: false
44
+ });
45
+ }
46
+ async function matchSignedCopy(file, verification) {
47
+ const hash = await sha256Hex(file);
48
+ if (hash === verification.document_sha256.toLowerCase()) return { kind: "current" };
49
+ const signature = verification.signatures.find((s) => s.sha256.toLowerCase() === hash);
50
+ return signature ? { kind: "earlier", signature } : { kind: "none" };
51
+ }
52
+ export {
53
+ SignatureVerificationError,
54
+ VERIFY_PATH,
55
+ fetchSignatureVerification,
56
+ isSignatureReference,
57
+ matchSignedCopy,
58
+ useSignatureVerification
59
+ };
60
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/verification.ts"],
4
+ "sourcesContent": ["/**\n * Checking a signature from its reference, without signing in: the public certificate behind the\n * link on a signed PDF's signature (`GET /v1/sign/verify/{reference}`). It names who signed and\n * when, says whether the signed document is unchanged since, and carries the SHA-256 of the signed\n * PDF and of each signed revision, so anyone can check their own copy in the browser (the file is\n * never uploaded). No email addresses and no document content.\n */\n\nimport type { components } from '@arbidocs/client'\nimport { useQuery } from '@tanstack/react-query'\nimport { useDocumentTools, type DocumentToolsClient } from './environment'\nimport { sha256Hex } from './signing'\nimport { arbiQueryKeys } from '../query-keys'\n\nexport const VERIFY_PATH = '/v1/sign/verify/{reference}'\n\nexport type SignatureVerification = components['schemas']['SignatureVerification']\nexport type VerifiedSignature = components['schemas']['VerifiedSignature']\n\n/** A signature reference as the backend issues them: `sig-` and 128 random bits in hex. */\nconst REFERENCE = /^sig-[0-9a-f]{32}$/\n\nexport function isSignatureReference(reference: string | null | undefined): boolean {\n return !!reference && REFERENCE.test(reference)\n}\n\nexport class SignatureVerificationError extends Error {\n constructor(\n message: string,\n readonly status?: number\n ) {\n super(message)\n this.name = 'SignatureVerificationError'\n }\n}\n\nconst VERIFY_ERRORS: Record<number, string> = {\n 404: 'No signature has this reference.',\n 429: 'Too many checks, try again in a minute.',\n}\n\nexport async function fetchSignatureVerification(\n client: DocumentToolsClient,\n reference: string\n): Promise<SignatureVerification> {\n if (!isSignatureReference(reference)) {\n throw new SignatureVerificationError('This is not a signature reference.')\n }\n const { data, response } = await client.GET(VERIFY_PATH, {\n params: { path: { reference } },\n })\n if (!response.ok || !data) {\n throw new SignatureVerificationError(\n VERIFY_ERRORS[response.status] ?? 'The signature could not be checked right now.',\n response.status\n )\n }\n return data\n}\n\n/** The certificate of a signature reference. Needs a `<DocumentToolsProvider>` (no user). */\nexport function useSignatureVerification(reference: string | null | undefined) {\n const { client } = useDocumentTools()\n return useQuery({\n queryKey: arbiQueryKeys.signatureVerification(reference ?? ''),\n queryFn: () => fetchSignatureVerification(client, reference!),\n enabled: !!reference,\n retry: false,\n })\n}\n\n/**\n * What a copy is: the signed document as it stands (`current`), the document as it was when an\n * earlier signer signed it (`earlier`, a counter-signed PDF's earlier revision), or neither.\n */\nexport type CopyMatch =\n { kind: 'current' } | { kind: 'earlier'; signature: VerifiedSignature } | { kind: 'none' }\n\n/** Compare a file with the signed PDF and its signed revisions. Hashed here; nothing is uploaded. */\nexport async function matchSignedCopy(\n file: Blob,\n verification: Pick<SignatureVerification, 'document_sha256' | 'signatures'>\n): Promise<CopyMatch> {\n const hash = await sha256Hex(file)\n if (hash === verification.document_sha256.toLowerCase()) return { kind: 'current' }\n const signature = verification.signatures.find((s) => s.sha256.toLowerCase() === hash)\n return signature ? { kind: 'earlier', signature } : { kind: 'none' }\n}\n"],
5
+ "mappings": "AASA,SAAS,gBAAgB;AACzB,SAAS,wBAAkD;AAC3D,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAEvB,MAAM,cAAc;AAM3B,MAAM,YAAY;AAEX,SAAS,qBAAqB,WAA+C;AAClF,SAAO,CAAC,CAAC,aAAa,UAAU,KAAK,SAAS;AAChD;AAEO,MAAM,mCAAmC,MAAM;AAAA,EACpD,YACE,SACS,QACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAJW;AAKb;AAEA,MAAM,gBAAwC;AAAA,EAC5C,KAAK;AAAA,EACL,KAAK;AACP;AAEA,eAAsB,2BACpB,QACA,WACgC;AAChC,MAAI,CAAC,qBAAqB,SAAS,GAAG;AACpC,UAAM,IAAI,2BAA2B,oCAAoC;AAAA,EAC3E;AACA,QAAM,EAAE,MAAM,SAAS,IAAI,MAAM,OAAO,IAAI,aAAa;AAAA,IACvD,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE;AAAA,EAChC,CAAC;AACD,MAAI,CAAC,SAAS,MAAM,CAAC,MAAM;AACzB,UAAM,IAAI;AAAA,MACR,cAAc,SAAS,MAAM,KAAK;AAAA,MAClC,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,yBAAyB,WAAsC;AAC7E,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,SAAO,SAAS;AAAA,IACd,UAAU,cAAc,sBAAsB,aAAa,EAAE;AAAA,IAC7D,SAAS,MAAM,2BAA2B,QAAQ,SAAU;AAAA,IAC5D,SAAS,CAAC,CAAC;AAAA,IACX,OAAO;AAAA,EACT,CAAC;AACH;AAUA,eAAsB,gBACpB,MACA,cACoB;AACpB,QAAM,OAAO,MAAM,UAAU,IAAI;AACjC,MAAI,SAAS,aAAa,gBAAgB,YAAY,EAAG,QAAO,EAAE,MAAM,UAAU;AAClF,QAAM,YAAY,aAAa,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,MAAM,IAAI;AACrF,SAAO,YAAY,EAAE,MAAM,WAAW,UAAU,IAAI,EAAE,MAAM,OAAO;AACrE;",
6
+ "names": []
7
+ }