@arbidocs/react 0.5.111 → 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 (983) hide show
  1. package/dist/account/client.js +96 -0
  2. package/dist/account/client.js.map +7 -0
  3. package/dist/account/delete.js +70 -0
  4. package/dist/account/delete.js.map +7 -0
  5. package/dist/account/didit.js +34 -0
  6. package/dist/account/didit.js.map +7 -0
  7. package/dist/account/dismissed-tips.js +33 -0
  8. package/dist/account/dismissed-tips.js.map +7 -0
  9. package/dist/account/email.js +84 -0
  10. package/dist/account/email.js.map +7 -0
  11. package/dist/account/entitlements.js +47 -0
  12. package/dist/account/entitlements.js.map +7 -0
  13. package/dist/account/identity.js +270 -0
  14. package/dist/account/identity.js.map +7 -0
  15. package/dist/account/index.js +93 -0
  16. package/dist/account/index.js.map +7 -0
  17. package/dist/account/notifications.js +59 -0
  18. package/dist/account/notifications.js.map +7 -0
  19. package/dist/account/password.js +103 -0
  20. package/dist/account/password.js.map +7 -0
  21. package/dist/account/profile.js +116 -0
  22. package/dist/account/profile.js.map +7 -0
  23. package/dist/account/recovery.js +13 -0
  24. package/dist/account/recovery.js.map +7 -0
  25. package/dist/account/relevance.js +82 -0
  26. package/dist/account/relevance.js.map +7 -0
  27. package/dist/account/sessions.js +37 -0
  28. package/dist/account/sessions.js.map +7 -0
  29. package/dist/account/settings.js +39 -0
  30. package/dist/account/settings.js.map +7 -0
  31. package/dist/account/table-views.js +16 -0
  32. package/dist/account/table-views.js.map +7 -0
  33. package/dist/ai/AiAnswer.js +83 -0
  34. package/dist/ai/AiAnswer.js.map +7 -0
  35. package/dist/ai/AiMarkdown.js +40 -0
  36. package/dist/ai/AiMarkdown.js.map +7 -0
  37. package/dist/ai/ArtifactCanvas.js +193 -0
  38. package/dist/ai/ArtifactCanvas.js.map +7 -0
  39. package/dist/ai/CitationRenderer.js +413 -0
  40. package/dist/ai/CitationRenderer.js.map +7 -0
  41. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  42. package/dist/ai/MarkdownRenderer.js.map +7 -0
  43. package/dist/ai/MessageArtifactCard.js +75 -0
  44. package/dist/ai/MessageArtifactCard.js.map +7 -0
  45. package/dist/ai/PassageCard.js +79 -0
  46. package/dist/ai/PassageCard.js.map +7 -0
  47. package/dist/ai/engine.js +110 -0
  48. package/dist/ai/engine.js.map +7 -0
  49. package/dist/ai/index.js +63 -0
  50. package/dist/ai/index.js.map +7 -0
  51. package/dist/ai/markdown-base-components.js +37 -0
  52. package/dist/ai/markdown-base-components.js.map +7 -0
  53. package/dist/ai/markdown-streaming-context.js +6 -0
  54. package/dist/ai/markdown-streaming-context.js.map +7 -0
  55. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  56. package/dist/ai/normalize-citations.js.map +7 -0
  57. package/dist/ai/redline.js +41 -0
  58. package/dist/ai/redline.js.map +7 -0
  59. package/dist/ai/split-markdown-blocks.js +40 -0
  60. package/dist/ai/split-markdown-blocks.js.map +7 -0
  61. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  62. package/dist/ai/stored-markdown.js.map +7 -0
  63. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  64. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  65. package/dist/annotations/AnnotationToolbar.js +398 -0
  66. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  67. package/dist/annotations/FreezeDialog.js +170 -0
  68. package/dist/annotations/FreezeDialog.js.map +7 -0
  69. package/dist/annotations/ProductionDialog.js +354 -0
  70. package/dist/annotations/ProductionDialog.js.map +7 -0
  71. package/dist/annotations/controller.js +49 -0
  72. package/dist/annotations/controller.js.map +7 -0
  73. package/dist/annotations/freeze/browser.js +21 -0
  74. package/dist/annotations/freeze/browser.js.map +7 -0
  75. package/dist/annotations/freeze/bundle.js +201 -0
  76. package/dist/annotations/freeze/bundle.js.map +7 -0
  77. package/dist/annotations/freeze/coords.js +37 -0
  78. package/dist/annotations/freeze/coords.js.map +7 -0
  79. package/dist/annotations/freeze/freeze.js +261 -0
  80. package/dist/annotations/freeze/freeze.js.map +7 -0
  81. package/dist/annotations/freeze/hash.js +28 -0
  82. package/dist/annotations/freeze/hash.js.map +7 -0
  83. package/dist/annotations/freeze/index-page.js +78 -0
  84. package/dist/annotations/freeze/index-page.js.map +7 -0
  85. package/dist/annotations/freeze/index.js +28 -22
  86. package/dist/annotations/freeze/index.js.map +7 -1
  87. package/dist/annotations/freeze/raster.js +208 -0
  88. package/dist/annotations/freeze/raster.js.map +7 -0
  89. package/dist/annotations/freeze/stamp.js +117 -0
  90. package/dist/annotations/freeze/stamp.js.map +7 -0
  91. package/dist/annotations/freeze/types.js +14 -0
  92. package/dist/annotations/freeze/types.js.map +7 -0
  93. package/dist/annotations/freeze/vector.js +283 -0
  94. package/dist/annotations/freeze/vector.js.map +7 -0
  95. package/dist/annotations/geometry.js +81 -0
  96. package/dist/annotations/geometry.js.map +7 -0
  97. package/dist/annotations/index.js +125 -6
  98. package/dist/annotations/index.js.map +7 -1
  99. package/dist/annotations/merge.js +53 -0
  100. package/dist/annotations/merge.js.map +7 -0
  101. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  102. package/dist/annotations/model.js.map +7 -0
  103. package/dist/annotations/overlay-geometry.js +41 -0
  104. package/dist/annotations/overlay-geometry.js.map +7 -0
  105. package/dist/annotations/redaction-log.js +33 -0
  106. package/dist/annotations/redaction-log.js.map +7 -0
  107. package/dist/annotations/selection-marks.js +122 -0
  108. package/dist/annotations/selection-marks.js.map +7 -0
  109. package/dist/annotations/state.js +140 -0
  110. package/dist/annotations/state.js.map +7 -0
  111. package/dist/annotations/store.js +49 -0
  112. package/dist/annotations/store.js.map +7 -0
  113. package/dist/annotations/useAnnotationLayer.js +306 -0
  114. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  115. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  116. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  117. package/dist/annotations/useTextSelectionMarks.js +100 -0
  118. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  119. package/dist/artifacts/artifact-kind.js +19 -0
  120. package/dist/artifacts/artifact-kind.js.map +7 -0
  121. package/dist/artifacts/index.js +89 -571
  122. package/dist/artifacts/index.js.map +7 -1
  123. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  124. package/dist/artifacts/normalize-markdown.js.map +7 -0
  125. package/dist/artifacts/redline-core.js +12 -3
  126. package/dist/artifacts/redline-core.js.map +7 -1
  127. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  128. package/dist/artifacts/redline-diff.js.map +7 -0
  129. package/dist/artifacts/redline-engine.js +14 -0
  130. package/dist/artifacts/redline-engine.js.map +7 -0
  131. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  132. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  133. package/dist/artifacts/useArtifactEditSession.js +183 -0
  134. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  135. package/dist/artifacts/useArtifactSession.js +173 -0
  136. package/dist/artifacts/useArtifactSession.js.map +7 -0
  137. package/dist/artifacts/useArtifactSource.js +16 -0
  138. package/dist/artifacts/useArtifactSource.js.map +7 -0
  139. package/dist/artifacts/useArtifactText.js +78 -0
  140. package/dist/artifacts/useArtifactText.js.map +7 -0
  141. package/dist/artifacts/useRedline.js +65 -0
  142. package/dist/artifacts/useRedline.js.map +7 -0
  143. package/dist/artifacts/useStreamedArtifact.js +74 -0
  144. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  145. package/dist/artifacts/versions.js +68 -0
  146. package/dist/artifacts/versions.js.map +7 -0
  147. package/dist/billing.js +200 -0
  148. package/dist/billing.js.map +7 -0
  149. package/dist/boot-timeout.js +19 -0
  150. package/dist/boot-timeout.js.map +7 -0
  151. package/dist/calendar/accounts.js +213 -0
  152. package/dist/calendar/accounts.js.map +7 -0
  153. package/dist/calendar/hooks.js +409 -0
  154. package/dist/calendar/hooks.js.map +7 -0
  155. package/dist/calendar/index.js +31 -0
  156. package/dist/calendar/index.js.map +7 -0
  157. package/dist/calendar/keys.js +5 -0
  158. package/dist/calendar/keys.js.map +7 -0
  159. package/dist/calendar/offline/outbox.js +231 -0
  160. package/dist/calendar/offline/outbox.js.map +7 -0
  161. package/dist/calendar/offline/runtime.js +109 -0
  162. package/dist/calendar/offline/runtime.js.map +7 -0
  163. package/dist/calendar/offline/support.js +41 -0
  164. package/dist/calendar/offline/support.js.map +7 -0
  165. package/dist/calendar/support.js +34 -0
  166. package/dist/calendar/support.js.map +7 -0
  167. package/dist/calls/actions.js +226 -0
  168. package/dist/calls/actions.js.map +7 -0
  169. package/dist/calls/events.js +138 -0
  170. package/dist/calls/events.js.map +7 -0
  171. package/dist/calls/gate.js +19 -0
  172. package/dist/calls/gate.js.map +7 -0
  173. package/dist/calls/hooks.js +115 -0
  174. package/dist/calls/hooks.js.map +7 -0
  175. package/dist/calls/in-call-chat.js +132 -0
  176. package/dist/calls/in-call-chat.js.map +7 -0
  177. package/dist/calls/index.js +24 -0
  178. package/dist/calls/index.js.map +7 -0
  179. package/dist/calls/keys.js +17 -0
  180. package/dist/calls/keys.js.map +7 -0
  181. package/dist/calls/livekit/index.js +6 -958
  182. package/dist/calls/livekit/index.js.map +7 -1
  183. package/dist/calls/livekit/room.js +98 -0
  184. package/dist/calls/livekit/room.js.map +7 -0
  185. package/dist/calls/livekit/useCallRecorder.js +219 -0
  186. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  187. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  188. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  189. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  190. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  191. package/dist/calls/livekit/useInCallChat.js +161 -0
  192. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  193. package/dist/calls/livekit/useWebinar.js +239 -0
  194. package/dist/calls/livekit/useWebinar.js.map +7 -0
  195. package/dist/calls/meeting-chat.js +149 -0
  196. package/dist/calls/meeting-chat.js.map +7 -0
  197. package/dist/calls/moderation.js +50 -0
  198. package/dist/calls/moderation.js.map +7 -0
  199. package/dist/calls/open-meeting-chat.js +29 -0
  200. package/dist/calls/open-meeting-chat.js.map +7 -0
  201. package/dist/calls/read-only.js +24 -0
  202. package/dist/calls/read-only.js.map +7 -0
  203. package/dist/calls/recording-media.js +218 -0
  204. package/dist/calls/recording-media.js.map +7 -0
  205. package/dist/calls/recording-playback.js +260 -0
  206. package/dist/calls/recording-playback.js.map +7 -0
  207. package/dist/calls/recording.js +268 -0
  208. package/dist/calls/recording.js.map +7 -0
  209. package/dist/calls/save-to-thread.js +80 -0
  210. package/dist/calls/save-to-thread.js.map +7 -0
  211. package/dist/calls/session.js +134 -0
  212. package/dist/calls/session.js.map +7 -0
  213. package/dist/calls/transcript-format.js +147 -0
  214. package/dist/calls/transcript-format.js.map +7 -0
  215. package/dist/calls/transcription.js +101 -0
  216. package/dist/calls/transcription.js.map +7 -0
  217. package/dist/calls/webinar.js +71 -0
  218. package/dist/calls/webinar.js.map +7 -0
  219. package/dist/charge-watch.js +71 -0
  220. package/dist/charge-watch.js.map +7 -0
  221. package/dist/chat/ChatBubble.js +146 -0
  222. package/dist/chat/ChatBubble.js.map +7 -0
  223. package/dist/chat/ConversationScope.js +30 -0
  224. package/dist/chat/ConversationScope.js.map +7 -0
  225. package/dist/chat/active-config.js +20 -0
  226. package/dist/chat/active-config.js.map +7 -0
  227. package/dist/chat/agent-chat-owner.js +25 -0
  228. package/dist/chat/agent-chat-owner.js.map +7 -0
  229. package/dist/chat/chat-artifacts.js +64 -0
  230. package/dist/chat/chat-artifacts.js.map +7 -0
  231. package/dist/chat/citations.js +32 -0
  232. package/dist/chat/citations.js.map +7 -0
  233. package/dist/chat/config-model.js +10 -0
  234. package/dist/chat/config-model.js.map +7 -0
  235. package/dist/chat/conversation-cache.js +676 -0
  236. package/dist/chat/conversation-cache.js.map +7 -0
  237. package/dist/chat/conversation-events.js +57 -0
  238. package/dist/chat/conversation-events.js.map +7 -0
  239. package/dist/chat/conversation-mentions.js +58 -0
  240. package/dist/chat/conversation-mentions.js.map +7 -0
  241. package/dist/chat/conversation-workspace.js +58 -0
  242. package/dist/chat/conversation-workspace.js.map +7 -0
  243. package/dist/chat/mentions.js +116 -0
  244. package/dist/chat/mentions.js.map +7 -0
  245. package/dist/chat/open-document.js +106 -0
  246. package/dist/chat/open-document.js.map +7 -0
  247. package/dist/chat/orphaned.js +44 -0
  248. package/dist/chat/orphaned.js.map +7 -0
  249. package/dist/chat/pendingFirstTurn.js +30 -0
  250. package/dist/chat/pendingFirstTurn.js.map +7 -0
  251. package/dist/chat/reply-target.js +12 -0
  252. package/dist/chat/reply-target.js.map +7 -0
  253. package/dist/chat/run-finished.js +28 -0
  254. package/dist/chat/run-finished.js.map +7 -0
  255. package/dist/chat/run-state.js +91 -0
  256. package/dist/chat/run-state.js.map +7 -0
  257. package/dist/chat/stream-handlers.js +419 -0
  258. package/dist/chat/stream-handlers.js.map +7 -0
  259. package/dist/chat/thread-binding.js +76 -0
  260. package/dist/chat/thread-binding.js.map +7 -0
  261. package/dist/chat/thread-document.js +53 -0
  262. package/dist/chat/thread-document.js.map +7 -0
  263. package/dist/chat/turn-control.js +79 -0
  264. package/dist/chat/turn-control.js.map +7 -0
  265. package/dist/chat/useAgentRunControl.js +36 -0
  266. package/dist/chat/useAgentRunControl.js.map +7 -0
  267. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  268. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  269. package/dist/chat/useAskAgain.js +32 -0
  270. package/dist/chat/useAskAgain.js.map +7 -0
  271. package/dist/chat/useAutoSendDraft.js +17 -0
  272. package/dist/chat/useAutoSendDraft.js.map +7 -0
  273. package/dist/chat/useBranchNavigation.js +97 -0
  274. package/dist/chat/useBranchNavigation.js.map +7 -0
  275. package/dist/chat/useConnectRunStream.js +169 -0
  276. package/dist/chat/useConnectRunStream.js.map +7 -0
  277. package/dist/chat/useConversation.js +431 -0
  278. package/dist/chat/useConversation.js.map +7 -0
  279. package/dist/chat/useConversationActions.js +662 -0
  280. package/dist/chat/useConversationActions.js.map +7 -0
  281. package/dist/chat/useConversationData.js +143 -0
  282. package/dist/chat/useConversationData.js.map +7 -0
  283. package/dist/chat/useConversationDocuments.js +41 -0
  284. package/dist/chat/useConversationDocuments.js.map +7 -0
  285. package/dist/chat/useConversationSettings.js +78 -0
  286. package/dist/chat/useConversationSettings.js.map +7 -0
  287. package/dist/chat/useConversationTurn.js +31 -0
  288. package/dist/chat/useConversationTurn.js.map +7 -0
  289. package/dist/chat/useConversationWorkspace.js +12 -0
  290. package/dist/chat/useConversationWorkspace.js.map +7 -0
  291. package/dist/chat/useDeleteMessage.js +15 -0
  292. package/dist/chat/useDeleteMessage.js.map +7 -0
  293. package/dist/chat/useDocumentAutoAdd.js +73 -0
  294. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  295. package/dist/chat/useMessageTimer.js +39 -0
  296. package/dist/chat/useMessageTimer.js.map +7 -0
  297. package/dist/chat/useThinkingContent.js +67 -0
  298. package/dist/chat/useThinkingContent.js.map +7 -0
  299. package/dist/chat/useThreadDocument.js +61 -0
  300. package/dist/chat/useThreadDocument.js.map +7 -0
  301. package/dist/chat/workflow-run-titles.js +50 -0
  302. package/dist/chat/workflow-run-titles.js.map +7 -0
  303. package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
  304. package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
  305. package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
  306. package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
  307. package/dist/{chunk-DI5KSVKY.cjs → chunk-UDDJIUHJ.cjs} +3 -3
  308. package/dist/{chunk-DI5KSVKY.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
  309. package/dist/config/config-hooks.js +209 -0
  310. package/dist/config/config-hooks.js.map +7 -0
  311. package/dist/connectivity.js +72 -0
  312. package/dist/connectivity.js.map +7 -0
  313. package/dist/connectors/hooks.js +263 -0
  314. package/dist/connectors/hooks.js.map +7 -0
  315. package/dist/connectors/index.js +28 -0
  316. package/dist/connectors/index.js.map +7 -0
  317. package/dist/contacts.js +100 -0
  318. package/dist/contacts.js.map +7 -0
  319. package/dist/conversation-list.js +65 -0
  320. package/dist/conversation-list.js.map +7 -0
  321. package/dist/databases.js +195 -0
  322. package/dist/databases.js.map +7 -0
  323. package/dist/datasets/aggregate.js +281 -0
  324. package/dist/datasets/aggregate.js.map +7 -0
  325. package/dist/datasets/index.js +122 -0
  326. package/dist/datasets/index.js.map +7 -0
  327. package/dist/datasets/members.js +27 -0
  328. package/dist/datasets/members.js.map +7 -0
  329. package/dist/datasets/panel.js +44 -0
  330. package/dist/datasets/panel.js.map +7 -0
  331. package/dist/datasets/registry.js +47 -0
  332. package/dist/datasets/registry.js.map +7 -0
  333. package/dist/datasets/rows-source.js +44 -0
  334. package/dist/datasets/rows-source.js.map +7 -0
  335. package/dist/datasets/sources/activity.js +83 -0
  336. package/dist/datasets/sources/activity.js.map +7 -0
  337. package/dist/datasets/sources/conversations.js +74 -0
  338. package/dist/datasets/sources/conversations.js.map +7 -0
  339. package/dist/datasets/sources/database.js +209 -0
  340. package/dist/datasets/sources/database.js.map +7 -0
  341. package/dist/datasets/sources/documents.js +93 -0
  342. package/dist/datasets/sources/documents.js.map +7 -0
  343. package/dist/datasets/sources/facts.js +56 -0
  344. package/dist/datasets/sources/facts.js.map +7 -0
  345. package/dist/datasets/sources/projects.js +117 -0
  346. package/dist/datasets/sources/projects.js.map +7 -0
  347. package/dist/datasets/sources/tags.js +67 -0
  348. package/dist/datasets/sources/tags.js.map +7 -0
  349. package/dist/datasets/sources/usage.js +268 -0
  350. package/dist/datasets/sources/usage.js.map +7 -0
  351. package/dist/datasets/sources/workflows.js +91 -0
  352. package/dist/datasets/sources/workflows.js.map +7 -0
  353. package/dist/datasets/sources/workspaces.js +67 -0
  354. package/dist/datasets/sources/workspaces.js.map +7 -0
  355. package/dist/datasets/store.js +194 -0
  356. package/dist/datasets/store.js.map +7 -0
  357. package/dist/datasets/types.js +14 -0
  358. package/dist/datasets/types.js.map +7 -0
  359. package/dist/directmessages/ConversationList.js +148 -0
  360. package/dist/directmessages/ConversationList.js.map +7 -0
  361. package/dist/directmessages/DateSeparator.js +8 -0
  362. package/dist/directmessages/DateSeparator.js.map +7 -0
  363. package/dist/directmessages/DmAvatar.js +29 -0
  364. package/dist/directmessages/DmAvatar.js.map +7 -0
  365. package/dist/directmessages/DmComposer.js +201 -0
  366. package/dist/directmessages/DmComposer.js.map +7 -0
  367. package/dist/directmessages/arrivals.js +29 -0
  368. package/dist/directmessages/arrivals.js.map +7 -0
  369. package/dist/directmessages/chat-cache.js +192 -0
  370. package/dist/directmessages/chat-cache.js.map +7 -0
  371. package/dist/directmessages/grouping.js +26 -0
  372. package/dist/directmessages/grouping.js.map +7 -0
  373. package/dist/directmessages/index.js +81 -0
  374. package/dist/directmessages/index.js.map +7 -0
  375. package/dist/directmessages/useChats.js +266 -0
  376. package/dist/directmessages/useChats.js.map +7 -0
  377. package/dist/directmessages/utils.js +23 -0
  378. package/dist/directmessages/utils.js.map +7 -0
  379. package/dist/document-tools/can-annotate.js +7 -0
  380. package/dist/document-tools/can-annotate.js.map +7 -0
  381. package/dist/document-tools/core.cjs +80 -80
  382. package/dist/document-tools/core.js +218 -12
  383. package/dist/document-tools/core.js.map +7 -1
  384. package/dist/document-tools/document-pdf.js +76 -0
  385. package/dist/document-tools/document-pdf.js.map +7 -0
  386. package/dist/document-tools/environment.js +136 -0
  387. package/dist/document-tools/environment.js.map +7 -0
  388. package/dist/document-tools/file-shares.js +112 -0
  389. package/dist/document-tools/file-shares.js.map +7 -0
  390. package/dist/document-tools/frozen-copy.js +27 -0
  391. package/dist/document-tools/frozen-copy.js.map +7 -0
  392. package/dist/document-tools/index.cjs +80 -80
  393. package/dist/document-tools/index.js +26 -148
  394. package/dist/document-tools/index.js.map +7 -1
  395. package/dist/document-tools/markup-download.js +51 -0
  396. package/dist/document-tools/markup-download.js.map +7 -0
  397. package/dist/document-tools/markup-store.js +138 -0
  398. package/dist/document-tools/markup-store.js.map +7 -0
  399. package/dist/document-tools/markup-transfer.js +88 -0
  400. package/dist/document-tools/markup-transfer.js.map +7 -0
  401. package/dist/document-tools/production.js +147 -0
  402. package/dist/document-tools/production.js.map +7 -0
  403. package/dist/document-tools/saved-signature.js +90 -0
  404. package/dist/document-tools/saved-signature.js.map +7 -0
  405. package/dist/document-tools/signature-requests.js +310 -0
  406. package/dist/document-tools/signature-requests.js.map +7 -0
  407. package/dist/document-tools/signing.js +127 -0
  408. package/dist/document-tools/signing.js.map +7 -0
  409. package/dist/document-tools/useDocumentBytes.js +38 -0
  410. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  411. package/dist/document-tools/useDocumentMarkup.js +154 -0
  412. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  413. package/dist/document-tools/useIsOnline.js +13 -0
  414. package/dist/document-tools/useIsOnline.js.map +7 -0
  415. package/dist/document-tools/verification.js +60 -0
  416. package/dist/document-tools/verification.js.map +7 -0
  417. package/dist/documents/DocumentReview.js +220 -0
  418. package/dist/documents/DocumentReview.js.map +7 -0
  419. package/dist/documents/DraftTitleControls.js +41 -0
  420. package/dist/documents/DraftTitleControls.js.map +7 -0
  421. package/dist/documents/InlineMicButton.js +90 -0
  422. package/dist/documents/InlineMicButton.js.map +7 -0
  423. package/dist/documents/MicRecordingOverlay.js +29 -0
  424. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  425. package/dist/documents/MicWaveformIndicator.js +68 -0
  426. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  427. package/dist/documents/PhotoCapture.js +120 -0
  428. package/dist/documents/PhotoCapture.js.map +7 -0
  429. package/dist/documents/VideoCapture.js +129 -0
  430. package/dist/documents/VideoCapture.js.map +7 -0
  431. package/dist/documents/VoiceNoteRecorder.js +166 -0
  432. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  433. package/dist/documents/audio-segmenter.js +63 -0
  434. package/dist/documents/audio-segmenter.js.map +7 -0
  435. package/dist/documents/capture-frame.js +21 -0
  436. package/dist/documents/capture-frame.js.map +7 -0
  437. package/dist/documents/chunked-recorder.js +190 -0
  438. package/dist/documents/chunked-recorder.js.map +7 -0
  439. package/dist/documents/document-download.js +53 -0
  440. package/dist/documents/document-download.js.map +7 -0
  441. package/dist/documents/document-fields.js +109 -0
  442. package/dist/documents/document-fields.js.map +7 -0
  443. package/dist/documents/documents-cache.js +110 -0
  444. package/dist/documents/documents-cache.js.map +7 -0
  445. package/dist/documents/documents-data.js +128 -0
  446. package/dist/documents/documents-data.js.map +7 -0
  447. package/dist/documents/documents-loader.js +113 -0
  448. package/dist/documents/documents-loader.js.map +7 -0
  449. package/dist/documents/documents-writes.js +448 -0
  450. package/dist/documents/documents-writes.js.map +7 -0
  451. package/dist/documents/format-elapsed.js +10 -0
  452. package/dist/documents/format-elapsed.js.map +7 -0
  453. package/dist/documents/has-video-track.js +26 -0
  454. package/dist/documents/has-video-track.js.map +7 -0
  455. package/dist/documents/index.js +266 -0
  456. package/dist/documents/index.js.map +7 -0
  457. package/dist/documents/media-error.js +18 -0
  458. package/dist/documents/media-error.js.map +7 -0
  459. package/dist/documents/offline-documents.js +160 -0
  460. package/dist/documents/offline-documents.js.map +7 -0
  461. package/dist/documents/pending-sync.js +210 -0
  462. package/dist/documents/pending-sync.js.map +7 -0
  463. package/dist/documents/processing-live.js +122 -0
  464. package/dist/documents/processing-live.js.map +7 -0
  465. package/dist/documents/processing-order.js +59 -0
  466. package/dist/documents/processing-order.js.map +7 -0
  467. package/dist/documents/processing-settle.js +21 -0
  468. package/dist/documents/processing-settle.js.map +7 -0
  469. package/dist/documents/related-documents.js +133 -0
  470. package/dist/documents/related-documents.js.map +7 -0
  471. package/dist/documents/support.js +29 -0
  472. package/dist/documents/support.js.map +7 -0
  473. package/dist/documents/upload-files.js +169 -0
  474. package/dist/documents/upload-files.js.map +7 -0
  475. package/dist/documents/useAudioRecorder.js +315 -0
  476. package/dist/documents/useAudioRecorder.js.map +7 -0
  477. package/dist/documents/useCameraStream.js +35 -0
  478. package/dist/documents/useCameraStream.js.map +7 -0
  479. package/dist/documents/useDocumentThumbnails.js +71 -0
  480. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  481. package/dist/documents/useDownloadDocuments.js +90 -0
  482. package/dist/documents/useDownloadDocuments.js.map +7 -0
  483. package/dist/documents/usePassageQuotes.js +37 -0
  484. package/dist/documents/usePassageQuotes.js.map +7 -0
  485. package/dist/documents/useUploadFiles.js +165 -0
  486. package/dist/documents/useUploadFiles.js.map +7 -0
  487. package/dist/documents/useUploadFromUrls.js +63 -0
  488. package/dist/documents/useUploadFromUrls.js.map +7 -0
  489. package/dist/documents/useVideoRecorder.js +62 -0
  490. package/dist/documents/useVideoRecorder.js.map +7 -0
  491. package/dist/entities/AgentMarkers.js +61 -0
  492. package/dist/entities/AgentMarkers.js.map +7 -0
  493. package/dist/entities/DocumentEntity.js +125 -0
  494. package/dist/entities/DocumentEntity.js.map +7 -0
  495. package/dist/entities/EntityPill.js +250 -0
  496. package/dist/entities/EntityPill.js.map +7 -0
  497. package/dist/entities/ProjectEntity.js +61 -0
  498. package/dist/entities/ProjectEntity.js.map +7 -0
  499. package/dist/entities/ShieldIcon.js +49 -0
  500. package/dist/entities/ShieldIcon.js.map +7 -0
  501. package/dist/entities/TagEntity.js +79 -0
  502. package/dist/entities/TagEntity.js.map +7 -0
  503. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  504. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  505. package/dist/entities/UserEntity.js +211 -0
  506. package/dist/entities/UserEntity.js.map +7 -0
  507. package/dist/entities/VerifiedBadge.js +19 -0
  508. package/dist/entities/VerifiedBadge.js.map +7 -0
  509. package/dist/entities/agent-avatar-colors.js +26 -0
  510. package/dist/entities/agent-avatar-colors.js.map +7 -0
  511. package/dist/entities/colors.js +64 -0
  512. package/dist/entities/colors.js.map +7 -0
  513. package/dist/entities/file-type.js +151 -0
  514. package/dist/entities/file-type.js.map +7 -0
  515. package/dist/entities/index.js +100 -0
  516. package/dist/entities/index.js.map +7 -0
  517. package/dist/entities/media-type.js +61 -0
  518. package/dist/entities/media-type.js.map +7 -0
  519. package/dist/entities/registry.js +385 -0
  520. package/dist/entities/registry.js.map +7 -0
  521. package/dist/entities/status.js +43 -0
  522. package/dist/entities/status.js.map +7 -0
  523. package/dist/entities/tag-kinds.js +23 -0
  524. package/dist/entities/tag-kinds.js.map +7 -0
  525. package/dist/entities/tag-types.js +44 -0
  526. package/dist/entities/tag-types.js.map +7 -0
  527. package/dist/entities/vocabulary.js +12 -0
  528. package/dist/entities/vocabulary.js.map +7 -0
  529. package/dist/entity-extraction.js +25 -0
  530. package/dist/entity-extraction.js.map +7 -0
  531. package/dist/facts-search.js +57 -0
  532. package/dist/facts-search.js.map +7 -0
  533. package/dist/facts.js +69 -0
  534. package/dist/facts.js.map +7 -0
  535. package/dist/hooks.js +320 -0
  536. package/dist/hooks.js.map +7 -0
  537. package/dist/host/ArbiHost.js +24 -0
  538. package/dist/host/ArbiHost.js.map +7 -0
  539. package/dist/host/assistant-copy.js +54 -0
  540. package/dist/host/assistant-copy.js.map +7 -0
  541. package/dist/host/config.js +9 -0
  542. package/dist/host/config.js.map +7 -0
  543. package/dist/host/context.js +10 -0
  544. package/dist/host/context.js.map +7 -0
  545. package/dist/host/features.js +144 -0
  546. package/dist/host/features.js.map +7 -0
  547. package/dist/host/index.js +12 -0
  548. package/dist/host/index.js.map +7 -0
  549. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  550. package/dist/host/merge.js.map +7 -0
  551. package/dist/house-template.js +40 -0
  552. package/dist/house-template.js.map +7 -0
  553. package/dist/icons/AppleIcon.js +25 -0
  554. package/dist/icons/AppleIcon.js.map +7 -0
  555. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  556. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  557. package/dist/icons/ArbiIcon.js +24 -0
  558. package/dist/icons/ArbiIcon.js.map +7 -0
  559. package/dist/icons/AudIcon.js +56 -0
  560. package/dist/icons/AudIcon.js.map +7 -0
  561. package/dist/icons/ClaudeIcon.js +28 -0
  562. package/dist/icons/ClaudeIcon.js.map +7 -0
  563. package/dist/icons/DocIcon.js +56 -0
  564. package/dist/icons/DocIcon.js.map +7 -0
  565. package/dist/icons/EmlIcon.js +57 -0
  566. package/dist/icons/EmlIcon.js.map +7 -0
  567. package/dist/icons/FireworksIcon.js +47 -0
  568. package/dist/icons/FireworksIcon.js.map +7 -0
  569. package/dist/icons/GeminiIcon.js +37 -0
  570. package/dist/icons/GeminiIcon.js.map +7 -0
  571. package/dist/icons/GitHubIcon.js +32 -0
  572. package/dist/icons/GitHubIcon.js.map +7 -0
  573. package/dist/icons/GoogleIcon.js +53 -0
  574. package/dist/icons/GoogleIcon.js.map +7 -0
  575. package/dist/icons/HtmlIcon.js +56 -0
  576. package/dist/icons/HtmlIcon.js.map +7 -0
  577. package/dist/icons/ImgIcon.js +56 -0
  578. package/dist/icons/ImgIcon.js.map +7 -0
  579. package/dist/icons/LinkedInIcon.js +25 -0
  580. package/dist/icons/LinkedInIcon.js.map +7 -0
  581. package/dist/icons/OpenAIIcon.js +28 -0
  582. package/dist/icons/OpenAIIcon.js.map +7 -0
  583. package/dist/icons/PdfIcon.js +56 -0
  584. package/dist/icons/PdfIcon.js.map +7 -0
  585. package/dist/icons/ProviderIcon.js +42 -0
  586. package/dist/icons/ProviderIcon.js.map +7 -0
  587. package/dist/icons/TxtIcon.js +56 -0
  588. package/dist/icons/TxtIcon.js.map +7 -0
  589. package/dist/icons/VidIcon.js +56 -0
  590. package/dist/icons/VidIcon.js.map +7 -0
  591. package/dist/icons/XlsIcon.js +56 -0
  592. package/dist/icons/XlsIcon.js.map +7 -0
  593. package/dist/icons/arbi-mark.js +5 -0
  594. package/dist/icons/arbi-mark.js.map +7 -0
  595. package/dist/icons/colors.js +31 -0
  596. package/dist/icons/colors.js.map +7 -0
  597. package/dist/icons/file-type.js +105 -0
  598. package/dist/icons/file-type.js.map +7 -0
  599. package/dist/icons/index.js +55 -0
  600. package/dist/icons/index.js.map +7 -0
  601. package/dist/imagecrop/ImageCropModal.js +56 -0
  602. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  603. package/dist/imagecrop/ImageCropper.js +100 -0
  604. package/dist/imagecrop/ImageCropper.js.map +7 -0
  605. package/dist/imagecrop/cropImage.js +43 -0
  606. package/dist/imagecrop/cropImage.js.map +7 -0
  607. package/dist/imagecrop/index.js +13 -0
  608. package/dist/imagecrop/index.js.map +7 -0
  609. package/dist/index.cjs +282 -282
  610. package/dist/index.js +702 -17116
  611. package/dist/index.js.map +7 -1
  612. package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
  613. package/dist/lazy-chunk.js.map +7 -0
  614. package/dist/lib/collision-padding.js +13 -0
  615. package/dist/lib/collision-padding.js.map +7 -0
  616. package/dist/lib/format-friendly-date.js +55 -0
  617. package/dist/lib/format-friendly-date.js.map +7 -0
  618. package/dist/lib/format-relative-time.js +52 -0
  619. package/dist/lib/format-relative-time.js.map +7 -0
  620. package/dist/lib/markdown-to-text.js +35 -0
  621. package/dist/lib/markdown-to-text.js.map +7 -0
  622. package/dist/lib/toast-interaction.js +9 -0
  623. package/dist/lib/toast-interaction.js.map +7 -0
  624. package/dist/lib/utils.js +9 -0
  625. package/dist/lib/utils.js.map +7 -0
  626. package/dist/mail/client.js +103 -0
  627. package/dist/mail/client.js.map +7 -0
  628. package/dist/mail/document-attachment.js +38 -0
  629. package/dist/mail/document-attachment.js.map +7 -0
  630. package/dist/mail/filing.js +132 -0
  631. package/dist/mail/filing.js.map +7 -0
  632. package/dist/mail/hooks.js +393 -0
  633. package/dist/mail/hooks.js.map +7 -0
  634. package/dist/mail/index.js +120 -0
  635. package/dist/mail/index.js.map +7 -0
  636. package/dist/mail/offline/changes.js +258 -0
  637. package/dist/mail/offline/changes.js.map +7 -0
  638. package/dist/mail/offline/confirm-sign-out.js +37 -0
  639. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  640. package/dist/mail/offline/crypto.js +26 -0
  641. package/dist/mail/offline/crypto.js.map +7 -0
  642. package/dist/mail/offline/drafts.js +69 -0
  643. package/dist/mail/offline/drafts.js.map +7 -0
  644. package/dist/mail/offline/hooks.js +104 -0
  645. package/dist/mail/offline/hooks.js.map +7 -0
  646. package/dist/mail/offline/index.js +48 -0
  647. package/dist/mail/offline/index.js.map +7 -0
  648. package/dist/mail/offline/live.js +233 -0
  649. package/dist/mail/offline/live.js.map +7 -0
  650. package/dist/mail/offline/mailbox.js +191 -0
  651. package/dist/mail/offline/mailbox.js.map +7 -0
  652. package/dist/mail/offline/outbox.js +167 -0
  653. package/dist/mail/offline/outbox.js.map +7 -0
  654. package/dist/mail/offline/reads.js +159 -0
  655. package/dist/mail/offline/reads.js.map +7 -0
  656. package/dist/mail/offline/runtime.js +100 -0
  657. package/dist/mail/offline/runtime.js.map +7 -0
  658. package/dist/mail/offline/settings.js +84 -0
  659. package/dist/mail/offline/settings.js.map +7 -0
  660. package/dist/mail/offline/store.js +29 -0
  661. package/dist/mail/offline/store.js.map +7 -0
  662. package/dist/mail/offline/sync.js +251 -0
  663. package/dist/mail/offline/sync.js.map +7 -0
  664. package/dist/mail/offline/wipe.js +19 -0
  665. package/dist/mail/offline/wipe.js.map +7 -0
  666. package/dist/mail/thread-keys.js +53 -0
  667. package/dist/mail/thread-keys.js.map +7 -0
  668. package/dist/mail/threads.js +71 -0
  669. package/dist/mail/threads.js.map +7 -0
  670. package/dist/mail/useMailClient.js +42 -0
  671. package/dist/mail/useMailClient.js.map +7 -0
  672. package/dist/model-connections.js +58 -0
  673. package/dist/model-connections.js.map +7 -0
  674. package/dist/notifications/ActivityFeed.js +70 -0
  675. package/dist/notifications/ActivityFeed.js.map +7 -0
  676. package/dist/notifications/NotificationBell.js +200 -0
  677. package/dist/notifications/NotificationBell.js.map +7 -0
  678. package/dist/notifications/Toaster.js +24 -0
  679. package/dist/notifications/Toaster.js.map +7 -0
  680. package/dist/notifications/activity-types.js +65 -0
  681. package/dist/notifications/activity-types.js.map +7 -0
  682. package/dist/notifications/bell.js +24 -0
  683. package/dist/notifications/bell.js.map +7 -0
  684. package/dist/notifications/calendar-notifications.js +79 -0
  685. package/dist/notifications/calendar-notifications.js.map +7 -0
  686. package/dist/notifications/index.js +108 -0
  687. package/dist/notifications/index.js.map +7 -0
  688. package/dist/notifications/live.js +28 -0
  689. package/dist/notifications/live.js.map +7 -0
  690. package/dist/notifications/notification-types.js +127 -0
  691. package/dist/notifications/notification-types.js.map +7 -0
  692. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  693. package/dist/notifications/notify-store.js.map +7 -0
  694. package/dist/notifications/server-notifications.js +452 -0
  695. package/dist/notifications/server-notifications.js.map +7 -0
  696. package/dist/notifications/useNotifications.js +34 -0
  697. package/dist/notifications/useNotifications.js.map +7 -0
  698. package/dist/offline-store/network.js +11 -0
  699. package/dist/offline-store/network.js.map +7 -0
  700. package/dist/offline-store/store.js +136 -0
  701. package/dist/offline-store/store.js.map +7 -0
  702. package/dist/offline-store/wipe.js +8 -0
  703. package/dist/offline-store/wipe.js.map +7 -0
  704. package/dist/offline.js +58 -0
  705. package/dist/offline.js.map +7 -0
  706. package/dist/people.js +122 -0
  707. package/dist/people.js.map +7 -0
  708. package/dist/projects.js +30 -0
  709. package/dist/projects.js.map +7 -0
  710. package/dist/query-client.js +63 -0
  711. package/dist/query-client.js.map +7 -0
  712. package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
  713. package/dist/query-keys.js.map +7 -0
  714. package/dist/query-persist.js +66 -0
  715. package/dist/query-persist.js.map +7 -0
  716. package/dist/queued-writes.js +59 -0
  717. package/dist/queued-writes.js.map +7 -0
  718. package/dist/remote-control.js +67 -0
  719. package/dist/remote-control.js.map +7 -0
  720. package/dist/search/index.js +23 -0
  721. package/dist/search/index.js.map +7 -0
  722. package/dist/search/session.js +58 -0
  723. package/dist/search/session.js.map +7 -0
  724. package/dist/search/useSemanticSearch.js +82 -0
  725. package/dist/search/useSemanticSearch.js.map +7 -0
  726. package/dist/session/chat.js +512 -0
  727. package/dist/session/chat.js.map +7 -0
  728. package/dist/session/documents.js +196 -0
  729. package/dist/session/documents.js.map +7 -0
  730. package/dist/session/drafts.js +103 -0
  731. package/dist/session/drafts.js.map +7 -0
  732. package/dist/session/index.js +123 -0
  733. package/dist/session/index.js.map +7 -0
  734. package/dist/session/layout.js +339 -0
  735. package/dist/session/layout.js.map +7 -0
  736. package/dist/session/persist.js +106 -0
  737. package/dist/session/persist.js.map +7 -0
  738. package/dist/session/session-hooks.js +53 -0
  739. package/dist/session/session-hooks.js.map +7 -0
  740. package/dist/session/signed-in.js +36 -0
  741. package/dist/session/signed-in.js.map +7 -0
  742. package/dist/session/store.js +166 -0
  743. package/dist/session/store.js.map +7 -0
  744. package/dist/session/thread-tabs.js +121 -0
  745. package/dist/session/thread-tabs.js.map +7 -0
  746. package/dist/session/ui-state-storage.js +76 -0
  747. package/dist/session/ui-state-storage.js.map +7 -0
  748. package/dist/session/workspace.js +77 -0
  749. package/dist/session/workspace.js.map +7 -0
  750. package/dist/shell/index.cjs +37 -37
  751. package/dist/shell/index.js +43 -10
  752. package/dist/shell/index.js.map +7 -1
  753. package/dist/skill-pack.js +111 -0
  754. package/dist/skill-pack.js.map +7 -0
  755. package/dist/storage.js +186 -0
  756. package/dist/storage.js.map +7 -0
  757. package/dist/support/index.js +35 -0
  758. package/dist/support/index.js.map +7 -0
  759. package/dist/tags.js +204 -0
  760. package/dist/tags.js.map +7 -0
  761. package/dist/ui/DebouncedInput.js +109 -0
  762. package/dist/ui/DebouncedInput.js.map +7 -0
  763. package/dist/ui/DictateContext.js +8 -0
  764. package/dist/ui/DictateContext.js.map +7 -0
  765. package/dist/ui/IconToggle.js +79 -0
  766. package/dist/ui/IconToggle.js.map +7 -0
  767. package/dist/ui/VerifiedToggle.js +38 -0
  768. package/dist/ui/VerifiedToggle.js.map +7 -0
  769. package/dist/ui/VisibilityToggle.js +103 -0
  770. package/dist/ui/VisibilityToggle.js.map +7 -0
  771. package/dist/ui/avatar.js +40 -0
  772. package/dist/ui/avatar.js.map +7 -0
  773. package/dist/ui/badge.js +28 -0
  774. package/dist/ui/badge.js.map +7 -0
  775. package/dist/ui/button.js +48 -0
  776. package/dist/ui/button.js.map +7 -0
  777. package/dist/ui/card.js +90 -0
  778. package/dist/ui/card.js.map +7 -0
  779. package/dist/ui/checkbox.js +22 -0
  780. package/dist/ui/checkbox.js.map +7 -0
  781. package/dist/ui/collapsible.js +10 -0
  782. package/dist/ui/collapsible.js.map +7 -0
  783. package/dist/ui/command.js +103 -0
  784. package/dist/ui/command.js.map +7 -0
  785. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  786. package/dist/ui/dialog.js.map +7 -0
  787. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  788. package/dist/ui/dropdown-menu.js.map +7 -0
  789. package/dist/ui/hover-card.js +36 -0
  790. package/dist/ui/hover-card.js.map +7 -0
  791. package/dist/ui/index.cjs +154 -154
  792. package/dist/ui/index.js +290 -10
  793. package/dist/ui/index.js.map +7 -1
  794. package/dist/ui/input.js +65 -0
  795. package/dist/ui/input.js.map +7 -0
  796. package/dist/ui/label.js +16 -0
  797. package/dist/ui/label.js.map +7 -0
  798. package/dist/ui/mark-menu.js +300 -0
  799. package/dist/ui/mark-menu.js.map +7 -0
  800. package/dist/ui/popover.js +40 -0
  801. package/dist/ui/popover.js.map +7 -0
  802. package/dist/ui/portal-container.js +17 -0
  803. package/dist/ui/portal-container.js.map +7 -0
  804. package/dist/ui/progress.js +24 -0
  805. package/dist/ui/progress.js.map +7 -0
  806. package/dist/ui/radio-group.js +29 -0
  807. package/dist/ui/radio-group.js.map +7 -0
  808. package/dist/ui/scroll-area.js +39 -0
  809. package/dist/ui/scroll-area.js.map +7 -0
  810. package/dist/ui/select.js +130 -0
  811. package/dist/ui/select.js.map +7 -0
  812. package/dist/ui/separator.js +23 -0
  813. package/dist/ui/separator.js.map +7 -0
  814. package/dist/ui/slider.js +23 -0
  815. package/dist/ui/slider.js.map +7 -0
  816. package/dist/ui/switch.js +28 -0
  817. package/dist/ui/switch.js.map +7 -0
  818. package/dist/ui/table.js +75 -0
  819. package/dist/ui/table.js.map +7 -0
  820. package/dist/ui/tabs.js +48 -0
  821. package/dist/ui/tabs.js.map +7 -0
  822. package/dist/ui/textarea.js +63 -0
  823. package/dist/ui/textarea.js.map +7 -0
  824. package/dist/ui/toggle-group.js +43 -0
  825. package/dist/ui/toggle-group.js.map +7 -0
  826. package/dist/ui/toggle.js +40 -0
  827. package/dist/ui/toggle.js.map +7 -0
  828. package/dist/ui/tooltip.js +215 -0
  829. package/dist/ui/tooltip.js.map +7 -0
  830. package/dist/usage-metered.js +8 -0
  831. package/dist/usage-metered.js.map +7 -0
  832. package/dist/useArbi.js +16 -0
  833. package/dist/useArbi.js.map +7 -0
  834. package/dist/useInstallSkillPack.js +81 -0
  835. package/dist/useInstallSkillPack.js.map +7 -0
  836. package/dist/usermenu/UserMenu.js +188 -0
  837. package/dist/usermenu/UserMenu.js.map +7 -0
  838. package/dist/usermenu/index.js +5 -0
  839. package/dist/usermenu/index.js.map +7 -0
  840. package/dist/users/index.js +15 -0
  841. package/dist/users/index.js.map +7 -0
  842. package/dist/users/user-display.js +60 -0
  843. package/dist/users/user-display.js.map +7 -0
  844. package/dist/viewers/AudioViewer.js +23 -0
  845. package/dist/viewers/AudioViewer.js.map +7 -0
  846. package/dist/viewers/DocxViewer.js +81 -0
  847. package/dist/viewers/DocxViewer.js.map +7 -0
  848. package/dist/viewers/ImageViewer.js +31 -0
  849. package/dist/viewers/ImageViewer.js.map +7 -0
  850. package/dist/viewers/PdfViewer.js +19 -3
  851. package/dist/viewers/PdfViewer.js.map +7 -1
  852. package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
  853. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  854. package/dist/viewers/VideoViewer.js +31 -0
  855. package/dist/viewers/VideoViewer.js.map +7 -0
  856. package/dist/viewers/XlsxViewer.js +102 -0
  857. package/dist/viewers/XlsxViewer.js.map +7 -0
  858. package/dist/viewers/index.js +61 -271
  859. package/dist/viewers/index.js.map +7 -1
  860. package/dist/viewers/page-scroll.js +59 -0
  861. package/dist/viewers/page-scroll.js.map +7 -0
  862. package/dist/viewers/pdf-viewer-constants.js +9 -0
  863. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  864. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  865. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  866. package/dist/viewers/selection-runs.js +38 -0
  867. package/dist/viewers/selection-runs.js.map +7 -0
  868. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  869. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  870. package/dist/viewers/useProcessedChunks.js +58 -0
  871. package/dist/viewers/useProcessedChunks.js.map +7 -0
  872. package/dist/viewers/viewer-zoom.js +163 -0
  873. package/dist/viewers/viewer-zoom.js.map +7 -0
  874. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  875. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  876. package/dist/websocket/context.js +14 -0
  877. package/dist/websocket/context.js.map +7 -0
  878. package/dist/websocket/hooks.js +30 -0
  879. package/dist/websocket/hooks.js.map +7 -0
  880. package/dist/websocket/index.js +22 -0
  881. package/dist/websocket/index.js.map +7 -0
  882. package/dist/websocket/live-updates.js +38 -0
  883. package/dist/websocket/live-updates.js.map +7 -0
  884. package/dist/websocket/reconnect.js +13 -0
  885. package/dist/websocket/reconnect.js.map +7 -0
  886. package/dist/websocket/store.js +58 -0
  887. package/dist/websocket/store.js.map +7 -0
  888. package/dist/workforce.js +607 -0
  889. package/dist/workforce.js.map +7 -0
  890. package/dist/workspaces/access-request.js +35 -0
  891. package/dist/workspaces/access-request.js.map +7 -0
  892. package/dist/workspaces/archive.js +59 -0
  893. package/dist/workspaces/archive.js.map +7 -0
  894. package/dist/workspaces/current.js +20 -0
  895. package/dist/workspaces/current.js.map +7 -0
  896. package/dist/workspaces/delete-workspaces.js +15 -0
  897. package/dist/workspaces/delete-workspaces.js.map +7 -0
  898. package/dist/workspaces/export-archive.js +40 -0
  899. package/dist/workspaces/export-archive.js.map +7 -0
  900. package/dist/workspaces/index.js +99 -0
  901. package/dist/workspaces/index.js.map +7 -0
  902. package/dist/workspaces/settings.js +45 -0
  903. package/dist/workspaces/settings.js.map +7 -0
  904. package/dist/workspaces/shell-workspaces.js +49 -0
  905. package/dist/workspaces/shell-workspaces.js.map +7 -0
  906. package/dist/workspaces/switch.js +234 -0
  907. package/dist/workspaces/switch.js.map +7 -0
  908. package/dist/workspaces/transfer.js +170 -0
  909. package/dist/workspaces/transfer.js.map +7 -0
  910. package/dist/workspaces/useShellWorkspaces.js +86 -0
  911. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  912. package/dist/workspaces/workspace-users.js +65 -0
  913. package/dist/workspaces/workspace-users.js.map +7 -0
  914. package/package.json +4 -4
  915. package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
  916. package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
  917. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  918. package/dist/annotations/freeze/index.d.cts +0 -205
  919. package/dist/annotations/index.d.cts +0 -360
  920. package/dist/artifacts/index.d.cts +0 -476
  921. package/dist/artifacts/redline-core.d.cts +0 -39
  922. package/dist/bundle-YNOX7VIL.js +0 -5
  923. package/dist/bundle-YNOX7VIL.js.map +0 -1
  924. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  925. package/dist/calls/livekit/index.d.cts +0 -280
  926. package/dist/chunk-47CCGUWR.js.map +0 -1
  927. package/dist/chunk-4FL3X3LA.js +0 -2057
  928. package/dist/chunk-4FL3X3LA.js.map +0 -1
  929. package/dist/chunk-6QNBSXCE.js +0 -271
  930. package/dist/chunk-6QNBSXCE.js.map +0 -1
  931. package/dist/chunk-74N436VK.js.map +0 -1
  932. package/dist/chunk-APZZQZ6P.js +0 -147
  933. package/dist/chunk-APZZQZ6P.js.map +0 -1
  934. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  935. package/dist/chunk-DPYBZDJB.js.map +0 -1
  936. package/dist/chunk-DZKRL5H3.js +0 -2766
  937. package/dist/chunk-DZKRL5H3.js.map +0 -1
  938. package/dist/chunk-HDCRPPBW.js +0 -75
  939. package/dist/chunk-HDCRPPBW.js.map +0 -1
  940. package/dist/chunk-L2IPPTVC.js +0 -20
  941. package/dist/chunk-L2IPPTVC.js.map +0 -1
  942. package/dist/chunk-LSU4UPS5.js +0 -1011
  943. package/dist/chunk-LSU4UPS5.js.map +0 -1
  944. package/dist/chunk-NIKPG4PW.js +0 -1128
  945. package/dist/chunk-NIKPG4PW.js.map +0 -1
  946. package/dist/chunk-NNAJLY6B.js +0 -4974
  947. package/dist/chunk-NNAJLY6B.js.map +0 -1
  948. package/dist/chunk-OYPKKHXY.js +0 -559
  949. package/dist/chunk-OYPKKHXY.js.map +0 -1
  950. package/dist/chunk-PTOP7OHG.js.map +0 -1
  951. package/dist/chunk-QMY2JKBI.js +0 -246
  952. package/dist/chunk-QMY2JKBI.js.map +0 -1
  953. package/dist/chunk-SN5YV6FF.js +0 -11
  954. package/dist/chunk-SN5YV6FF.js.map +0 -1
  955. package/dist/chunk-SSXFVWCT.js.map +0 -1
  956. package/dist/chunk-T3USOSVN.js.map +0 -1
  957. package/dist/chunk-T4CLW3DN.js +0 -2560
  958. package/dist/chunk-T4CLW3DN.js.map +0 -1
  959. package/dist/chunk-UW2SGTI5.js.map +0 -1
  960. package/dist/chunk-VSCU7K4V.js.map +0 -1
  961. package/dist/chunk-WL2Y2T47.js.map +0 -1
  962. package/dist/chunk-WUTL62MC.js.map +0 -1
  963. package/dist/chunk-XWPLOFDN.js +0 -644
  964. package/dist/chunk-XWPLOFDN.js.map +0 -1
  965. package/dist/chunk-Y3MTRA7D.js +0 -97
  966. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  967. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  968. package/dist/chunk-ZM6N7YZH.js.map +0 -1
  969. package/dist/document-tools/core.d.cts +0 -883
  970. package/dist/document-tools/index.d.cts +0 -90
  971. package/dist/index.d-LArLnpI8.d.cts +0 -2036
  972. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  973. package/dist/index.d.cts +0 -15923
  974. package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
  975. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  976. package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
  977. package/dist/shell/index.d.cts +0 -6
  978. package/dist/store.d-GADDvC7w.d.cts +0 -35
  979. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  980. package/dist/ui/index.d.cts +0 -26
  981. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  982. package/dist/viewers/PdfViewer.d.cts +0 -9
  983. package/dist/viewers/index.d.cts +0 -262
@@ -0,0 +1,51 @@
1
+ const SIGNED_LOCKED_REASON = "Signed documents can't be changed \u2014 download the signed file instead";
2
+ function isSignedVersion(doc, version) {
3
+ const n = version ?? doc.current_version ?? 1;
4
+ return (doc.versions ?? []).some((v) => v.n === n && v.reason === "signed");
5
+ }
6
+ class MarkupDownloadError extends Error {
7
+ constructor(message, status) {
8
+ super(message);
9
+ this.status = status;
10
+ this.name = "MarkupDownloadError";
11
+ }
12
+ status;
13
+ }
14
+ function currentHasMarkup(doc) {
15
+ const n = doc.current_version ?? 1;
16
+ return (doc.versions ?? []).some((v) => v.n === n && (v.markup_count ?? 0) > 0);
17
+ }
18
+ async function fetchMarkupPdf(client, documentId, version, workspaceExtId) {
19
+ const { data, response } = await client.GET("/v1/document/{document_ext_id}/markup/pdf", {
20
+ params: {
21
+ path: { document_ext_id: documentId },
22
+ query: {
23
+ ...version ? { version } : {},
24
+ ...workspaceExtId ? { workspace_ext_id: workspaceExtId } : {}
25
+ }
26
+ },
27
+ parseAs: "blob"
28
+ });
29
+ if (!response.ok || !data) {
30
+ throw new MarkupDownloadError(
31
+ response.status === 404 ? "This document has no markup yet" : (
32
+ // The server refuses a signed version: its PDF takes no more changes.
33
+ response.status === 409 ? SIGNED_LOCKED_REASON : "The markup could not be downloaded"
34
+ ),
35
+ response.status
36
+ );
37
+ }
38
+ const disposition = response.headers.get("content-disposition") ?? "";
39
+ const utf8 = /filename\*=UTF-8''([^;]+)/i.exec(disposition)?.[1];
40
+ const plain = /filename="([^"]+)"/i.exec(disposition)?.[1];
41
+ const fileName = utf8 ? decodeURIComponent(utf8) : plain ?? "markup.pdf";
42
+ return { blob: data, fileName };
43
+ }
44
+ export {
45
+ MarkupDownloadError,
46
+ SIGNED_LOCKED_REASON,
47
+ currentHasMarkup,
48
+ fetchMarkupPdf,
49
+ isSignedVersion
50
+ };
51
+ //# sourceMappingURL=markup-download.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/markup-download.ts"],
4
+ "sourcesContent": ["/**\n * \"Download with markup\": a document version's markup PDF, the PDF with its annotations as native\n * PDF annotations (comments, highlights, stamps, unapplied redactions), which Acrobat and Preview\n * show. The plain Download serves the original. Kept apart from the annotation layer code so a\n * documents list can offer it without loading the annotation tools.\n *\n * A SIGNED version is locked: nothing but a further signature changes it. Its markup stays in the\n * separate markup layer (a title beside the signature, say) and is never written into its PDF, so\n * it has no \"Download with markup\"; the plain Download is the signed file as it is.\n */\n\nimport type { DocumentToolsClient } from './environment'\n\ninterface DocumentVersions {\n current_version?: number | null\n versions?: Array<{ n: number; markup_count?: number | null; reason?: string | null }> | null\n}\n\n/** Why \"Download with markup\" is off for a signed version. */\nexport const SIGNED_LOCKED_REASON =\n \"Signed documents can't be changed \u2014 download the signed file instead\"\n\n/** Whether a version (default: the current one) is a signed copy, per its version entry. */\nexport function isSignedVersion(doc: DocumentVersions, version?: number): boolean {\n const n = version ?? doc.current_version ?? 1\n return (doc.versions ?? []).some((v) => v.n === n && v.reason === 'signed')\n}\n\nexport class MarkupDownloadError extends Error {\n constructor(\n message: string,\n readonly status?: number\n ) {\n super(message)\n this.name = 'MarkupDownloadError'\n }\n}\n\n/** Whether a document's current version has markup (per its version entries). */\nexport function currentHasMarkup(doc: DocumentVersions): boolean {\n const n = doc.current_version ?? 1\n return (doc.versions ?? []).some((v) => v.n === n && (v.markup_count ?? 0) > 0)\n}\n\n/** Fetch a version's markup PDF (default: the current version's). */\nexport async function fetchMarkupPdf(\n client: DocumentToolsClient,\n documentId: string,\n version?: number,\n workspaceExtId?: string\n): Promise<{ blob: Blob; fileName: string }> {\n const { data, response } = await client.GET('/v1/document/{document_ext_id}/markup/pdf', {\n params: {\n path: { document_ext_id: documentId },\n query: {\n ...(version ? { version } : {}),\n ...(workspaceExtId ? { workspace_ext_id: workspaceExtId } : {}),\n },\n },\n parseAs: 'blob',\n })\n if (!response.ok || !data) {\n throw new MarkupDownloadError(\n response.status === 404\n ? 'This document has no markup yet'\n : // The server refuses a signed version: its PDF takes no more changes.\n response.status === 409\n ? SIGNED_LOCKED_REASON\n : 'The markup could not be downloaded',\n response.status\n )\n }\n const disposition = response.headers.get('content-disposition') ?? ''\n const utf8 = /filename\\*=UTF-8''([^;]+)/i.exec(disposition)?.[1]\n const plain = /filename=\"([^\"]+)\"/i.exec(disposition)?.[1]\n const fileName = utf8 ? decodeURIComponent(utf8) : (plain ?? 'markup.pdf')\n return { blob: data as Blob, fileName }\n}\n"],
5
+ "mappings": "AAmBO,MAAM,uBACX;AAGK,SAAS,gBAAgB,KAAuB,SAA2B;AAChF,QAAM,IAAI,WAAW,IAAI,mBAAmB;AAC5C,UAAQ,IAAI,YAAY,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,KAAK,EAAE,WAAW,QAAQ;AAC5E;AAEO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YACE,SACS,QACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAJW;AAKb;AAGO,SAAS,iBAAiB,KAAgC;AAC/D,QAAM,IAAI,IAAI,mBAAmB;AACjC,UAAQ,IAAI,YAAY,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,MAAM,EAAE,gBAAgB,KAAK,CAAC;AAChF;AAGA,eAAsB,eACpB,QACA,YACA,SACA,gBAC2C;AAC3C,QAAM,EAAE,MAAM,SAAS,IAAI,MAAM,OAAO,IAAI,6CAA6C;AAAA,IACvF,QAAQ;AAAA,MACN,MAAM,EAAE,iBAAiB,WAAW;AAAA,MACpC,OAAO;AAAA,QACL,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,QAC7B,GAAI,iBAAiB,EAAE,kBAAkB,eAAe,IAAI,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AACD,MAAI,CAAC,SAAS,MAAM,CAAC,MAAM;AACzB,UAAM,IAAI;AAAA,MACR,SAAS,WAAW,MAChB;AAAA;AAAA,QAEA,SAAS,WAAW,MAClB,uBACA;AAAA;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AACA,QAAM,cAAc,SAAS,QAAQ,IAAI,qBAAqB,KAAK;AACnE,QAAM,OAAO,6BAA6B,KAAK,WAAW,IAAI,CAAC;AAC/D,QAAM,QAAQ,sBAAsB,KAAK,WAAW,IAAI,CAAC;AACzD,QAAM,WAAW,OAAO,mBAAmB,IAAI,IAAK,SAAS;AAC7D,SAAO,EAAE,MAAM,MAAc,SAAS;AACxC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,138 @@
1
+ import {
2
+ AnnotationStoreOfflineError,
3
+ LAYER_SCHEMA_VERSION,
4
+ mergeLayers,
5
+ parseLayer
6
+ } from "../annotations/index.js";
7
+ const MAX_MERGE_ATTEMPTS = 5;
8
+ const KEEPALIVE_LIMIT = 6e4;
9
+ class MarkupStoreError extends Error {
10
+ constructor(message, status) {
11
+ super(message);
12
+ this.status = status;
13
+ this.name = "MarkupStoreError";
14
+ }
15
+ status;
16
+ }
17
+ const detailOf = (error, fallback) => {
18
+ const detail = error?.detail;
19
+ return typeof detail === "string" ? detail : fallback;
20
+ };
21
+ async function call(request) {
22
+ try {
23
+ return await request();
24
+ } catch (e) {
25
+ if (e instanceof TypeError || typeof navigator !== "undefined" && !navigator.onLine) {
26
+ throw new AnnotationStoreOfflineError();
27
+ }
28
+ throw e;
29
+ }
30
+ }
31
+ function createMarkupStore({ version, client, onSaved }) {
32
+ let revision = 0;
33
+ let count = 0;
34
+ let canEdit = false;
35
+ let base = null;
36
+ const seen = /* @__PURE__ */ new Set();
37
+ const remember = (layer) => {
38
+ for (const a of layer.annotations) seen.add(a.id);
39
+ };
40
+ const query = version ? { version } : {};
41
+ async function read(documentId, ifNoneMatch) {
42
+ const { data, error, response } = await call(
43
+ () => client.GET("/v1/document/{document_ext_id}/markup", {
44
+ params: { path: { document_ext_id: documentId }, query },
45
+ headers: ifNoneMatch === void 0 ? void 0 : { "If-None-Match": `"${ifNoneMatch}"` }
46
+ })
47
+ );
48
+ if (response.status === 304) return null;
49
+ if (error || !data) {
50
+ throw new MarkupStoreError(
51
+ detailOf(error, `The markup could not be loaded (${response.status})`),
52
+ response.status
53
+ );
54
+ }
55
+ const layer = parseLayer({
56
+ schema: LAYER_SCHEMA_VERSION,
57
+ documentId,
58
+ annotations: data.annotations ?? [],
59
+ updatedAt: data.updated_at ?? (/* @__PURE__ */ new Date()).toISOString()
60
+ });
61
+ return { revision: data.revision ?? 0, layer, canEdit: !!data.can_edit };
62
+ }
63
+ function adopt(server) {
64
+ revision = server.revision;
65
+ canEdit = server.canEdit;
66
+ base = server.layer;
67
+ count = server.layer.annotations.length;
68
+ remember(server.layer);
69
+ }
70
+ async function put(layer, from) {
71
+ return call(
72
+ () => client.PUT("/v1/document/{document_ext_id}/markup", {
73
+ params: { path: { document_ext_id: layer.documentId }, query },
74
+ headers: { "If-Match": `"${from}"` },
75
+ body: { annotations: layer.annotations, base_revision: from },
76
+ // A save started as the page closes must outlive it; browsers cap such bodies at 64 KB.
77
+ keepalive: JSON.stringify(layer.annotations).length < KEEPALIVE_LIMIT
78
+ })
79
+ );
80
+ }
81
+ return {
82
+ snapshot: () => ({ revision, count, canEdit }),
83
+ canEdit: () => canEdit,
84
+ async load(documentId) {
85
+ const server = await read(documentId);
86
+ if (!server) throw new MarkupStoreError("The markup could not be loaded");
87
+ adopt(server);
88
+ return server.layer;
89
+ },
90
+ async save(layer) {
91
+ remember(layer);
92
+ let mine = layer;
93
+ for (let attempt = 0; attempt < MAX_MERGE_ATTEMPTS; attempt++) {
94
+ const { data, error, response } = await put(mine, revision);
95
+ if (response.ok && data) {
96
+ revision = data.revision;
97
+ count = data.count;
98
+ base = mine;
99
+ remember(mine);
100
+ onSaved?.({ revision, count, canEdit });
101
+ return mine;
102
+ }
103
+ if (response.status === 409) {
104
+ const latest = await read(layer.documentId);
105
+ if (!latest) throw new MarkupStoreError("The markup could not be re-read");
106
+ const deleted = new Set(
107
+ [...seen].filter((id) => !mine.annotations.some((a) => a.id === id))
108
+ );
109
+ const merged = mergeLayers({ base, mine, theirs: latest.layer, deleted });
110
+ revision = latest.revision;
111
+ canEdit = latest.canEdit;
112
+ base = latest.layer;
113
+ remember(latest.layer);
114
+ mine = merged;
115
+ continue;
116
+ }
117
+ if (response.status === 403) canEdit = false;
118
+ throw new MarkupStoreError(
119
+ detailOf(error, `The markup could not be saved (${response.status})`),
120
+ response.status
121
+ );
122
+ }
123
+ throw new MarkupStoreError("The markup keeps changing; it will be saved on the next edit");
124
+ },
125
+ async pull(documentId) {
126
+ const server = await read(documentId, revision);
127
+ if (!server || server.revision === revision) return null;
128
+ adopt(server);
129
+ return server.layer;
130
+ }
131
+ };
132
+ }
133
+ export {
134
+ MAX_MERGE_ATTEMPTS,
135
+ MarkupStoreError,
136
+ createMarkupStore
137
+ };
138
+ //# sourceMappingURL=markup-store.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/markup-store.ts"],
4
+ "sourcesContent": ["/**\n * The annotation store for a document version's MARKUP on the server: `GET`/`PUT\n * /v1/document/{id}/markup`. The server keeps the marks as native PDF annotations in an encrypted\n * `{doc}-markup.pdf` next to the version (same document id, the document's own privacy); this store\n * only moves the layer and its revision.\n *\n * Optimistic concurrency: every save names the revision it started from. When someone else saved\n * first the server answers 409; the store then re-reads the latest layer, merges it with ours by\n * annotation id (`mergeLayers`: union, last edit wins per mark, replies unioned, our deletions\n * stay deleted) and saves again. The merged layer is returned so the viewer shows their marks too.\n *\n * Deletions are tracked as tombstones for the session: an id this session has seen that is no\n * longer in the layer it saves was deleted here, and a concurrent edit elsewhere cannot bring it\n * back.\n */\n\nimport {\n AnnotationStoreOfflineError,\n LAYER_SCHEMA_VERSION,\n mergeLayers,\n parseLayer,\n type AnnotationLayer,\n type AnnotationStore,\n} from '../annotations'\nimport type { DocumentToolsClient } from './environment'\n\n/** How many times a save re-reads and merges after a 409 before giving up (each is a real race). */\nexport const MAX_MERGE_ATTEMPTS = 5\n/** Below this many bytes a save uses `keepalive`, so it completes even if the page unloads. */\nconst KEEPALIVE_LIMIT = 60_000\n\nexport interface MarkupSnapshot {\n revision: number\n count: number\n canEdit: boolean\n}\n\nexport interface MarkupStoreOptions {\n /** The version the markup belongs to; omitted = the document's current version. */\n version?: number\n /** The ARBI API client (see `DocumentToolsEnvironment.client`). */\n client: DocumentToolsClient\n /** After every successful save: the new revision and how many marks the markup holds. */\n onSaved?: (snapshot: MarkupSnapshot) => void\n}\n\nexport interface MarkupStore extends AnnotationStore {\n snapshot(): MarkupSnapshot\n}\n\ninterface ServerLayer {\n revision: number\n layer: AnnotationLayer\n canEdit: boolean\n}\n\nexport class MarkupStoreError extends Error {\n constructor(\n message: string,\n readonly status?: number\n ) {\n super(message)\n this.name = 'MarkupStoreError'\n }\n}\n\nconst detailOf = (error: unknown, fallback: string) => {\n const detail = (error as { detail?: unknown } | undefined)?.detail\n return typeof detail === 'string' ? detail : fallback\n}\n\n/** A request that never reached the server (no network, DNS, CORS) is \"offline\", not a failure. */\nasync function call<T>(request: () => Promise<T>): Promise<T> {\n try {\n return await request()\n } catch (e) {\n if (e instanceof TypeError || (typeof navigator !== 'undefined' && !navigator.onLine)) {\n throw new AnnotationStoreOfflineError()\n }\n throw e\n }\n}\n\nexport function createMarkupStore({ version, client, onSaved }: MarkupStoreOptions): MarkupStore {\n let revision = 0\n let count = 0\n let canEdit = false\n /** The layer as last read from or written to the server: the base of a merge. */\n let base: AnnotationLayer | null = null\n /** Every mark id this session has held: one missing from a save was deleted here. */\n const seen = new Set<string>()\n const remember = (layer: AnnotationLayer) => {\n for (const a of layer.annotations) seen.add(a.id)\n }\n const query = version ? { version } : {}\n\n async function read(documentId: string, ifNoneMatch?: number): Promise<ServerLayer | null> {\n const { data, error, response } = await call(() =>\n client.GET('/v1/document/{document_ext_id}/markup', {\n params: { path: { document_ext_id: documentId }, query },\n headers: ifNoneMatch === undefined ? undefined : { 'If-None-Match': `\"${ifNoneMatch}\"` },\n })\n )\n if (response.status === 304) return null\n if (error || !data) {\n throw new MarkupStoreError(\n detailOf(error, `The markup could not be loaded (${response.status})`),\n response.status\n )\n }\n const layer = parseLayer({\n schema: LAYER_SCHEMA_VERSION,\n documentId,\n annotations: data.annotations ?? [],\n updatedAt: data.updated_at ?? new Date().toISOString(),\n })\n return { revision: data.revision ?? 0, layer, canEdit: !!data.can_edit }\n }\n\n function adopt(server: ServerLayer) {\n revision = server.revision\n canEdit = server.canEdit\n base = server.layer\n count = server.layer.annotations.length\n remember(server.layer)\n }\n\n async function put(layer: AnnotationLayer, from: number) {\n return call(() =>\n client.PUT('/v1/document/{document_ext_id}/markup', {\n params: { path: { document_ext_id: layer.documentId }, query },\n headers: { 'If-Match': `\"${from}\"` },\n body: { annotations: layer.annotations as never, base_revision: from },\n // A save started as the page closes must outlive it; browsers cap such bodies at 64 KB.\n keepalive: JSON.stringify(layer.annotations).length < KEEPALIVE_LIMIT,\n })\n )\n }\n\n return {\n snapshot: () => ({ revision, count, canEdit }),\n canEdit: () => canEdit,\n\n async load(documentId) {\n const server = await read(documentId)\n if (!server) throw new MarkupStoreError('The markup could not be loaded')\n adopt(server)\n return server.layer\n },\n\n async save(layer) {\n remember(layer)\n let mine = layer\n for (let attempt = 0; attempt < MAX_MERGE_ATTEMPTS; attempt++) {\n const { data, error, response } = await put(mine, revision)\n if (response.ok && data) {\n revision = data.revision\n count = data.count\n base = mine\n remember(mine)\n onSaved?.({ revision, count, canEdit })\n return mine\n }\n if (response.status === 409) {\n // Someone saved first: their layer, merged with ours, is what we save next.\n const latest = await read(layer.documentId)\n if (!latest) throw new MarkupStoreError('The markup could not be re-read')\n const deleted = new Set(\n [...seen].filter((id) => !mine.annotations.some((a) => a.id === id))\n )\n const merged = mergeLayers({ base, mine, theirs: latest.layer, deleted })\n revision = latest.revision\n canEdit = latest.canEdit\n base = latest.layer\n remember(latest.layer)\n mine = merged\n continue\n }\n if (response.status === 403) canEdit = false\n throw new MarkupStoreError(\n detailOf(error, `The markup could not be saved (${response.status})`),\n response.status\n )\n }\n throw new MarkupStoreError('The markup keeps changing; it will be saved on the next edit')\n },\n\n async pull(documentId) {\n const server = await read(documentId, revision)\n if (!server || server.revision === revision) return null\n adopt(server)\n return server.layer\n },\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,88 @@
1
+ import {
2
+ LAYER_SCHEMA_VERSION,
3
+ emptyLayer,
4
+ mergeLayers,
5
+ parseLayer
6
+ } from "../annotations/index.js";
7
+ import { createMarkupStore } from "./markup-store.js";
8
+ const LEGACY_LAYER_PREFIX = "arbi:annotations:";
9
+ function storage() {
10
+ try {
11
+ return typeof localStorage === "undefined" ? void 0 : localStorage;
12
+ } catch {
13
+ return void 0;
14
+ }
15
+ }
16
+ function readLegacyLayer(documentId) {
17
+ try {
18
+ const raw = storage()?.getItem(LEGACY_LAYER_PREFIX + documentId);
19
+ if (!raw) return null;
20
+ return parseLayer(JSON.parse(raw));
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+ function forgetLegacyLayer(documentId) {
26
+ try {
27
+ storage()?.removeItem(LEGACY_LAYER_PREFIX + documentId);
28
+ } catch {
29
+ }
30
+ }
31
+ function marksByVersion(layer, versions) {
32
+ const sorted = [...versions].sort((a, b) => a.n - b.n);
33
+ const out = /* @__PURE__ */ new Map();
34
+ for (const mark of layer.annotations) {
35
+ const at = Date.parse(mark.createdAt);
36
+ let target = sorted[0]?.n ?? 1;
37
+ for (const v of sorted) {
38
+ const created = v.created_at ? Date.parse(v.created_at) : Number.NaN;
39
+ if (!Number.isNaN(created) && !Number.isNaN(at) && created <= at) target = v.n;
40
+ }
41
+ out.set(target, [...out.get(target) ?? [], mark]);
42
+ }
43
+ return out;
44
+ }
45
+ async function addToMarkup(documentId, version, marks, client) {
46
+ const store = createMarkupStore({ version, client });
47
+ const current = await store.load(documentId);
48
+ const incoming = {
49
+ ...emptyLayer(documentId, (/* @__PURE__ */ new Date()).toISOString()),
50
+ annotations: marks
51
+ };
52
+ const merged = mergeLayers({ base: null, mine: current, theirs: incoming });
53
+ const added = merged.annotations.length - current.annotations.length;
54
+ if (added > 0) await store.save(parseLayer({ ...merged, schema: LAYER_SCHEMA_VERSION }));
55
+ return added;
56
+ }
57
+ async function migrateLegacyLayer(documentId, layer, versions, currentVersion, client) {
58
+ let added = 0;
59
+ for (const [n, marks] of marksByVersion(layer, versions.length ? versions : [{ n: 1 }])) {
60
+ added += await addToMarkup(documentId, n === currentVersion ? void 0 : n, marks, client);
61
+ }
62
+ forgetLegacyLayer(documentId);
63
+ return added;
64
+ }
65
+ async function openThreadsOf(documentId, version, client) {
66
+ const layer = await createMarkupStore({ version, client }).load(documentId);
67
+ return layer.annotations.filter((a) => a.kind === "comment" && !a.resolved);
68
+ }
69
+ async function copyOpenThreads(documentId, fromVersion, client) {
70
+ const threads = await openThreadsOf(documentId, fromVersion, client);
71
+ if (!threads.length) return 0;
72
+ return addToMarkup(documentId, void 0, threads, client);
73
+ }
74
+ function versionsWithMarkup(versions) {
75
+ return (versions ?? []).filter((v) => (v.markup_count ?? 0) > 0);
76
+ }
77
+ export {
78
+ LEGACY_LAYER_PREFIX,
79
+ addToMarkup,
80
+ copyOpenThreads,
81
+ forgetLegacyLayer,
82
+ marksByVersion,
83
+ migrateLegacyLayer,
84
+ openThreadsOf,
85
+ readLegacyLayer,
86
+ versionsWithMarkup
87
+ };
88
+ //# sourceMappingURL=markup-transfer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/markup-transfer.ts"],
4
+ "sourcesContent": ["/**\n * Moving marks INTO a version's markup without the viewer: the one-time migration of layers kept in\n * this browser before markup lived on the server, and \"copy open comments\" from an older version's\n * markup onto the current one (a new version \u2014 signed, synced from Drive, saved from Word \u2014 starts\n * with an empty markup; redactions never carry over).\n *\n * Both are unions by annotation id, so running them twice adds nothing twice.\n */\n\nimport {\n LAYER_SCHEMA_VERSION,\n emptyLayer,\n mergeLayers,\n parseLayer,\n type Annotation,\n type AnnotationLayer,\n} from '../annotations'\nimport type { DocumentToolsClient } from './environment'\nimport { createMarkupStore } from './markup-store'\n\nexport const LEGACY_LAYER_PREFIX = 'arbi:annotations:'\n\nexport interface VersionInfo {\n n: number\n created_at?: string | null\n markup_count?: number | null\n}\n\nfunction storage(): Storage | undefined {\n try {\n return typeof localStorage === 'undefined' ? undefined : localStorage\n } catch {\n return undefined\n }\n}\n\n/** The layer this browser kept for a document before markup moved to the server, if any. */\nexport function readLegacyLayer(documentId: string): AnnotationLayer | null {\n try {\n const raw = storage()?.getItem(LEGACY_LAYER_PREFIX + documentId)\n if (!raw) return null\n return parseLayer(JSON.parse(raw))\n } catch {\n return null // unreadable: nothing worth migrating\n }\n}\n\nexport function forgetLegacyLayer(documentId: string): void {\n try {\n storage()?.removeItem(LEGACY_LAYER_PREFIX + documentId)\n } catch {\n // storage blocked: nothing to forget\n }\n}\n\n/**\n * Which version each legacy mark belongs to: the version that was current when it was made. A\n * document's id is the id of its first version (older layers were made on it); a layer made after\n * the versions moved inside the document was made on whatever version was then current.\n */\nexport function marksByVersion(\n layer: AnnotationLayer,\n versions: VersionInfo[]\n): Map<number, Annotation[]> {\n const sorted = [...versions].sort((a, b) => a.n - b.n)\n const out = new Map<number, Annotation[]>()\n for (const mark of layer.annotations) {\n const at = Date.parse(mark.createdAt)\n let target = sorted[0]?.n ?? 1\n for (const v of sorted) {\n const created = v.created_at ? Date.parse(v.created_at) : Number.NaN\n if (!Number.isNaN(created) && !Number.isNaN(at) && created <= at) target = v.n\n }\n out.set(target, [...(out.get(target) ?? []), mark])\n }\n return out\n}\n\n/** Add marks to one version's markup (union by id); returns how many were new. */\nexport async function addToMarkup(\n documentId: string,\n version: number | undefined,\n marks: Annotation[],\n client: DocumentToolsClient\n): Promise<number> {\n const store = createMarkupStore({ version, client })\n const current = await store.load(documentId)\n const incoming: AnnotationLayer = {\n ...emptyLayer(documentId, new Date().toISOString()),\n annotations: marks,\n }\n // Theirs (the server) wins any tie: a mark already in the markup is never overwritten by an\n // older browser copy of it.\n const merged = mergeLayers({ base: null, mine: current, theirs: incoming })\n const added = merged.annotations.length - current.annotations.length\n if (added > 0) await store.save(parseLayer({ ...merged, schema: LAYER_SCHEMA_VERSION }))\n return added\n}\n\n/**\n * Migrate this browser's layer for a document into its markup, version by version, then forget\n * the browser copy. Throws (and keeps the browser copy) if any version could not be saved.\n */\nexport async function migrateLegacyLayer(\n documentId: string,\n layer: AnnotationLayer,\n versions: VersionInfo[],\n currentVersion: number,\n client: DocumentToolsClient\n): Promise<number> {\n let added = 0\n for (const [n, marks] of marksByVersion(layer, versions.length ? versions : [{ n: 1 }])) {\n added += await addToMarkup(documentId, n === currentVersion ? undefined : n, marks, client)\n }\n forgetLegacyLayer(documentId)\n return added\n}\n\n/** The unresolved comment threads (with replies) of a version's markup. */\nexport async function openThreadsOf(\n documentId: string,\n version: number,\n client: DocumentToolsClient\n): Promise<Annotation[]> {\n const layer = await createMarkupStore({ version, client }).load(documentId)\n return layer.annotations.filter((a) => a.kind === 'comment' && !a.resolved)\n}\n\n/** Copy the open comment threads of an older version onto the current version's markup. */\nexport async function copyOpenThreads(\n documentId: string,\n fromVersion: number,\n client: DocumentToolsClient\n): Promise<number> {\n const threads = await openThreadsOf(documentId, fromVersion, client)\n if (!threads.length) return 0\n return addToMarkup(documentId, undefined, threads, client)\n}\n\n/** Version entries of a document as the API returns them (`DocResponse.versions`). */\nexport function versionsWithMarkup(versions: VersionInfo[] | null | undefined): VersionInfo[] {\n return (versions ?? []).filter((v) => (v.markup_count ?? 0) > 0)\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,147 @@
1
+ import { DocumentFetchError, fetchDocumentFile, fetchDocumentPdf } from "./document-pdf.js";
2
+ const PRODUCTIONS_FOLDER = "Productions";
3
+ const extensionOf = (fileName) => {
4
+ const name = (fileName ?? "").toLowerCase();
5
+ const dot = name.lastIndexOf(".");
6
+ return dot < 0 ? "" : name.slice(dot + 1);
7
+ };
8
+ const NO_RENDITION_EXTENSIONS = new Set(
9
+ [
10
+ // images
11
+ "jpg jpeg png gif bmp tiff tif webp heic",
12
+ // video and audio
13
+ "mp4 mpeg mpg webm mov avi mkv mp3 wav m4a aac ogg flac",
14
+ // archives, binaries, design files
15
+ "zip rar 7z tar gz exe bin dmg iso apk msi dll so psd ai sketch"
16
+ ].join(" ").split(" ")
17
+ );
18
+ const isPdfDocument = (doc) => /pdf/i.test(doc.file_type ?? "") || extensionOf(doc.file_name) === "pdf";
19
+ const hasNoRendition = (doc) => !isPdfDocument(doc) && NO_RENDITION_EXTENSIONS.has(extensionOf(doc.file_name));
20
+ const productionDocumentName = (doc) => doc.doc_metadata?.title || doc.file_name || doc.external_id;
21
+ const isPdfBytes = (bytes) => bytes.length > 4 && String.fromCharCode(...bytes.subarray(0, 5)) === "%PDF-";
22
+ async function fetchProductionPdf(client, doc) {
23
+ const pdf = isPdfDocument(doc);
24
+ let blob;
25
+ try {
26
+ blob = await (pdf ? fetchDocumentFile : fetchDocumentPdf)(client, doc.external_id);
27
+ } catch (e) {
28
+ if (!pdf && e instanceof DocumentFetchError) return null;
29
+ throw e;
30
+ }
31
+ const bytes = new Uint8Array(await blob.arrayBuffer());
32
+ return pdf || isPdfBytes(bytes) ? bytes : null;
33
+ }
34
+ const safeName = (name) => name.replace(/[\\/:*?"<>|]+/g, "_").trim();
35
+ function productionTitle(firstLabel, lastLabel) {
36
+ return safeName(`Production ${firstLabel}-${lastLabel}`);
37
+ }
38
+ function productionFolder(title, merged) {
39
+ return merged ? PRODUCTIONS_FOLDER : `${PRODUCTIONS_FOLDER}/${title}`;
40
+ }
41
+ function productionFileName(file, title) {
42
+ if (!file.firstLabel) return `${title} index.pdf`;
43
+ return `${file.name.replace(/\.pdf$/i, "")} (${file.firstLabel}-${file.lastLabel}).pdf`;
44
+ }
45
+ const csvCell = (value) => `"${String(value).replace(/"/g, '""')}"`;
46
+ function productionIndexCsv(index) {
47
+ const rows = index.map(
48
+ (e) => [e.documentId, e.name, e.file, e.pages, e.firstLabel, e.lastLabel].map(csvCell).join(",")
49
+ );
50
+ return ["document_id,name,file,pages,first_label,last_label", ...rows].join("\n");
51
+ }
52
+ async function saveProductionFiles(upload, files, folder) {
53
+ const ids = [];
54
+ for (const file of files) {
55
+ const query = {
56
+ derived_from: file.sources.map((doc) => doc.external_id),
57
+ derived_role: "production",
58
+ shared: file.sources.every((doc) => doc.shared),
59
+ folder
60
+ };
61
+ const workspaces = new Set(file.sources.map((doc) => doc.workspace_ext_id).filter(Boolean));
62
+ if (workspaces.size === 1) query.workspace_ext_id = [...workspaces][0];
63
+ const response = await upload({
64
+ file: new File([file.bytes], file.name, { type: "application/pdf" }),
65
+ query
66
+ });
67
+ ids.push(...response?.doc_ext_ids ?? []);
68
+ }
69
+ return ids;
70
+ }
71
+ async function buildProduction(client, documents, choices, options) {
72
+ const byId = new Map(documents.map((doc) => [doc.external_id, doc]));
73
+ const included = [];
74
+ const noRendition = [];
75
+ const items = [];
76
+ for (const doc of choices.order.flatMap((id) => byId.get(id) ?? [])) {
77
+ const bytes = await fetchProductionPdf(client, doc);
78
+ if (!bytes) {
79
+ noRendition.push(doc);
80
+ continue;
81
+ }
82
+ included.push(doc);
83
+ items.push({
84
+ name: productionDocumentName(doc),
85
+ documentId: doc.external_id,
86
+ bytes,
87
+ qrUrl: options.documentUrl(doc.external_id)
88
+ });
89
+ }
90
+ if (items.length === 0) {
91
+ throw new Error("None of these documents has a PDF version to number yet.");
92
+ }
93
+ const { buildBundle } = await import("../annotations/freeze/bundle.js");
94
+ const result = await buildBundle(items, {
95
+ layout: choices.layout,
96
+ bates: {
97
+ prefix: choices.prefix,
98
+ start: choices.start,
99
+ digits: choices.digits,
100
+ corner: choices.corner
101
+ },
102
+ qr: choices.qr,
103
+ // The QR code sits in the bottom corner the label is not in.
104
+ qrCorner: choices.corner.endsWith("left") ? "bottom-right" : "bottom-left",
105
+ indexPage: choices.indexPage,
106
+ author: options.author,
107
+ onProgress: options.onProgress
108
+ });
109
+ const title = productionTitle(
110
+ result.index[0].firstLabel,
111
+ result.index[result.index.length - 1].lastLabel
112
+ );
113
+ const merged = choices.layout === "merged";
114
+ const files = merged ? [{ ...result.files[0], name: `${title}.pdf` }] : result.files;
115
+ const sourceOf = new Map(result.index.map((e) => [e.file, byId.get(e.documentId)]));
116
+ const uploads = files.map((file) => ({
117
+ name: merged ? file.name : productionFileName(file, title),
118
+ bytes: file.bytes,
119
+ // The merged file (and a separate index) is made from every document; each per-document
120
+ // file from its own.
121
+ sources: merged || !sourceOf.has(file.name) ? included : [sourceOf.get(file.name)]
122
+ }));
123
+ return {
124
+ title,
125
+ merged,
126
+ files,
127
+ index: result.index,
128
+ included,
129
+ noRendition,
130
+ uploads,
131
+ folder: productionFolder(title, merged)
132
+ };
133
+ }
134
+ export {
135
+ PRODUCTIONS_FOLDER,
136
+ buildProduction,
137
+ fetchProductionPdf,
138
+ hasNoRendition,
139
+ isPdfDocument,
140
+ productionDocumentName,
141
+ productionFileName,
142
+ productionFolder,
143
+ productionIndexCsv,
144
+ productionTitle,
145
+ saveProductionFiles
146
+ };
147
+ //# sourceMappingURL=production.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/production.ts"],
4
+ "sourcesContent": ["/**\n * Production sets: number the selected documents with Bates labels (optionally a QR code back to\n * each document and an index page) and save the result back to the workspace. The dialog is\n * `ProductionSetDialog` in `@arbidocs/blocks/document-tools`; this is its data side.\n *\n * A PDF is numbered as stored (`/download`). Any other document is numbered through its PDF\n * rendition (`/view`, what the viewer shows for a Word or text file); one without a rendition is\n * left out. Saved results are new documents derived from their sources (role `production`) in a\n * Productions folder, shared with the workspace only if every source is. The originals never\n * change.\n *\n * pdf-lib (the numbering) is loaded only when a production is built, so importing this module\n * stays as light as the rest of the document tools.\n */\n\nimport type { components } from '@arbidocs/client'\nimport type { ProductionChoices } from '../annotations/ProductionDialog'\nimport type { BundleFile, BundleIndexEntry, BundleItem } from '../annotations/freeze/bundle'\nimport { DocumentFetchError, fetchDocumentFile, fetchDocumentPdf } from './document-pdf'\nimport type {\n DocumentToolsClient,\n DocumentToolsEnvironment,\n DocumentUploadQuery,\n} from './environment'\n\n/** The fields of a document record (`DocResponse`) a production uses. */\nexport type ProductionSource = Pick<\n components['schemas']['DocResponse'],\n 'external_id' | 'file_name' | 'file_type' | 'shared'\n> & {\n doc_metadata?: { title?: string | null } | null\n /** The document's workspace: the produced files are saved there, named on the upload. */\n workspace_ext_id?: string | null\n}\n\nexport const PRODUCTIONS_FOLDER = 'Productions'\n\nconst extensionOf = (fileName: string | null | undefined) => {\n const name = (fileName ?? '').toLowerCase()\n const dot = name.lastIndexOf('.')\n return dot < 0 ? '' : name.slice(dot + 1)\n}\n\n/** Media, archives and design files: no PDF version to number. */\nconst NO_RENDITION_EXTENSIONS = new Set(\n [\n // images\n 'jpg jpeg png gif bmp tiff tif webp heic',\n // video and audio\n 'mp4 mpeg mpg webm mov avi mkv mp3 wav m4a aac ogg flac',\n // archives, binaries, design files\n 'zip rar 7z tar gz exe bin dmg iso apk msi dll so psd ai sketch',\n ]\n .join(' ')\n .split(' ')\n)\n\nexport const isPdfDocument = (doc: ProductionSource) =>\n /pdf/i.test(doc.file_type ?? '') || extensionOf(doc.file_name) === 'pdf'\n\n/** True for a document with no PDF version to number (media, archives and the like). */\nexport const hasNoRendition = (doc: ProductionSource) =>\n !isPdfDocument(doc) && NO_RENDITION_EXTENSIONS.has(extensionOf(doc.file_name))\n\n/** The name a document goes by in the dialog and the index: its title, else its file name. */\nexport const productionDocumentName = (doc: ProductionSource) =>\n doc.doc_metadata?.title || doc.file_name || doc.external_id\n\nconst isPdfBytes = (bytes: Uint8Array) =>\n bytes.length > 4 && String.fromCharCode(...bytes.subarray(0, 5)) === '%PDF-'\n\n/**\n * The PDF to number for `doc`: the file itself, or the PDF version of anything else. `null` when a\n * non-PDF has no PDF version (yet), so it is left out; a PDF that cannot be downloaded throws.\n */\nexport async function fetchProductionPdf(\n client: DocumentToolsClient,\n doc: ProductionSource\n): Promise<Uint8Array | null> {\n const pdf = isPdfDocument(doc)\n let blob: Blob\n try {\n blob = await (pdf ? fetchDocumentFile : fetchDocumentPdf)(client, doc.external_id)\n } catch (e) {\n if (!pdf && e instanceof DocumentFetchError) return null\n throw e\n }\n const bytes = new Uint8Array(await blob.arrayBuffer())\n return pdf || isPdfBytes(bytes) ? bytes : null\n}\n\nconst safeName = (name: string) => name.replace(/[\\\\/:*?\"<>|]+/g, '_').trim()\n\n/** \"Production ACME-000001-ACME-000042\": names the files and folder of one production. */\nexport function productionTitle(firstLabel: string, lastLabel: string): string {\n return safeName(`Production ${firstLabel}-${lastLabel}`)\n}\n\n/** Where a production is saved: the Productions folder, or a folder of its own per document. */\nexport function productionFolder(title: string, merged: boolean): string {\n return merged ? PRODUCTIONS_FOLDER : `${PRODUCTIONS_FOLDER}/${title}`\n}\n\n/** In the workspace a per-document file says which range it holds, beside its original. */\nexport function productionFileName(file: BundleFile, title: string): string {\n if (!file.firstLabel) return `${title} index.pdf`\n return `${file.name.replace(/\\.pdf$/i, '')} (${file.firstLabel}-${file.lastLabel}).pdf`\n}\n\nconst csvCell = (value: string | number) => `\"${String(value).replace(/\"/g, '\"\"')}\"`\n\n/** The `index.csv` of a per-document production: every document with its file and range. */\nexport function productionIndexCsv(index: readonly BundleIndexEntry[]): string {\n const rows = index.map((e) =>\n [e.documentId, e.name, e.file, e.pages, e.firstLabel, e.lastLabel].map(csvCell).join(',')\n )\n return ['document_id,name,file,pages,first_label,last_label', ...rows].join('\\n')\n}\n\nexport interface ProductionUpload {\n name: string\n bytes: Uint8Array\n /** The documents this file was made from. */\n sources: ProductionSource[]\n}\n\n/** Save each file as a new workspace document derived from its sources; returns the new ids. */\nexport async function saveProductionFiles(\n upload: NonNullable<DocumentToolsEnvironment['uploadDocument']>,\n files: readonly ProductionUpload[],\n folder: string\n): Promise<string[]> {\n const ids: string[] = []\n for (const file of files) {\n const query: DocumentUploadQuery = {\n derived_from: file.sources.map((doc) => doc.external_id),\n derived_role: 'production',\n shared: file.sources.every((doc) => doc.shared),\n folder,\n }\n // Saved in the sources' workspace, named on the upload (never whichever one is open now).\n const workspaces = new Set(file.sources.map((doc) => doc.workspace_ext_id).filter(Boolean))\n if (workspaces.size === 1) query.workspace_ext_id = [...workspaces][0]\n const response = await upload({\n file: new File([file.bytes as BlobPart], file.name, { type: 'application/pdf' }),\n query,\n })\n ids.push(...(response?.doc_ext_ids ?? []))\n }\n return ids\n}\n\nexport interface BuildProductionOptions {\n /** The link a document's QR code opens (the document in the host app). */\n documentUrl: (documentId: string) => string\n /** Who produced the set; recorded in a merged file's metadata. */\n author?: string\n onProgress?: (done: number, total: number) => void\n}\n\nexport interface BuiltProduction {\n title: string\n merged: boolean\n /** The numbered files: one merged PDF (named after its range), or one per document (+ index). */\n files: BundleFile[]\n index: BundleIndexEntry[]\n /** The documents numbered, in order. */\n included: ProductionSource[]\n /** Documents left out because they have no PDF version yet. */\n noRendition: ProductionSource[]\n /** The files as they are saved to the workspace, each with the documents it was made from. */\n uploads: ProductionUpload[]\n folder: string\n}\n\n/**\n * Fetch each document's PDF (in `choices.order`) and number the set. Throws when none of the\n * documents has a PDF version, or when a PDF cannot be fetched.\n */\nexport async function buildProduction(\n client: DocumentToolsClient,\n documents: readonly ProductionSource[],\n choices: ProductionChoices,\n options: BuildProductionOptions\n): Promise<BuiltProduction> {\n const byId = new Map(documents.map((doc) => [doc.external_id, doc]))\n const included: ProductionSource[] = []\n const noRendition: ProductionSource[] = []\n const items: BundleItem[] = []\n for (const doc of choices.order.flatMap((id) => byId.get(id) ?? [])) {\n const bytes = await fetchProductionPdf(client, doc)\n if (!bytes) {\n noRendition.push(doc)\n continue\n }\n included.push(doc)\n items.push({\n name: productionDocumentName(doc),\n documentId: doc.external_id,\n bytes,\n qrUrl: options.documentUrl(doc.external_id),\n })\n }\n if (items.length === 0) {\n throw new Error('None of these documents has a PDF version to number yet.')\n }\n\n const { buildBundle } = await import('../annotations/freeze/bundle')\n const result = await buildBundle(items, {\n layout: choices.layout,\n bates: {\n prefix: choices.prefix,\n start: choices.start,\n digits: choices.digits,\n corner: choices.corner,\n },\n qr: choices.qr,\n // The QR code sits in the bottom corner the label is not in.\n qrCorner: choices.corner.endsWith('left') ? 'bottom-right' : 'bottom-left',\n indexPage: choices.indexPage,\n author: options.author,\n onProgress: options.onProgress,\n })\n\n const title = productionTitle(\n result.index[0].firstLabel,\n result.index[result.index.length - 1].lastLabel\n )\n const merged = choices.layout === 'merged'\n // A merged file is named after its range; per-document files keep their document names.\n const files = merged ? [{ ...result.files[0], name: `${title}.pdf` }] : result.files\n const sourceOf = new Map(result.index.map((e) => [e.file, byId.get(e.documentId)!]))\n const uploads = files.map((file) => ({\n name: merged ? file.name : productionFileName(file, title),\n bytes: file.bytes,\n // The merged file (and a separate index) is made from every document; each per-document\n // file from its own.\n sources: merged || !sourceOf.has(file.name) ? included : [sourceOf.get(file.name)!],\n }))\n return {\n title,\n merged,\n files,\n index: result.index,\n included,\n noRendition,\n uploads,\n folder: productionFolder(title, merged),\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,90 @@
1
+ import {
2
+ getUserEncryptionKeypair,
3
+ initSodium,
4
+ sealedBoxDecrypt,
5
+ sealedBoxEncrypt
6
+ } from "@arbidocs/client";
7
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
8
+ import { useDocumentTools } from "./environment.js";
9
+ import { arbiQueryKeys } from "../query-keys.js";
10
+ const INFORMAL_SIGNATURE_NOTE = "Your saved signature or initials are placed as an image on the document.";
11
+ async function keypair(source = getUserEncryptionKeypair) {
12
+ await initSodium();
13
+ const pair = await source();
14
+ if (!pair) throw new Error("Sign in again to use your saved signature.");
15
+ return pair;
16
+ }
17
+ function detail(error, fallback) {
18
+ const d = error?.detail;
19
+ return typeof d === "string" ? d : fallback;
20
+ }
21
+ async function fetchSavedSignature(client, source) {
22
+ const { data, error } = await client.GET("/v1/user/signature");
23
+ if (!data) throw new Error(detail(error, "Your saved signature could not be read"));
24
+ if (!data.sealed) return null;
25
+ const pair = await keypair(source);
26
+ const json = new TextDecoder().decode(sealedBoxDecrypt(data.sealed, pair.secretKey));
27
+ return JSON.parse(json);
28
+ }
29
+ async function storeSavedSignature(client, signature, source) {
30
+ const pair = await keypair(source);
31
+ const sealed = sealedBoxEncrypt(
32
+ Uint8Array.from(new TextEncoder().encode(JSON.stringify(signature))),
33
+ pair.publicKey
34
+ );
35
+ const { error, response } = await client.PUT("/v1/user/signature", { body: { sealed } });
36
+ if (!response.ok) throw new Error(detail(error, "Your signature could not be saved"));
37
+ }
38
+ async function deleteSavedSignature(client) {
39
+ const { error, response } = await client.DELETE("/v1/user/signature");
40
+ if (!response.ok) throw new Error(detail(error, "Your saved signature could not be deleted"));
41
+ }
42
+ function useSavedSignature(enabled = true) {
43
+ const { client } = useDocumentTools();
44
+ return useQuery({
45
+ queryKey: arbiQueryKeys.savedSignature(),
46
+ queryFn: () => fetchSavedSignature(client),
47
+ enabled,
48
+ staleTime: 6e4,
49
+ retry: false
50
+ });
51
+ }
52
+ function useStoreSavedSignature() {
53
+ const { client } = useDocumentTools();
54
+ const queryClient = useQueryClient();
55
+ return useMutation({
56
+ mutationFn: (signature) => storeSavedSignature(client, signature),
57
+ onSuccess: (_, signature) => queryClient.setQueryData(arbiQueryKeys.savedSignature(), signature)
58
+ });
59
+ }
60
+ function useDeleteSavedSignature() {
61
+ const { client } = useDocumentTools();
62
+ const queryClient = useQueryClient();
63
+ return useMutation({
64
+ mutationFn: () => deleteSavedSignature(client),
65
+ onSuccess: () => queryClient.setQueryData(arbiQueryKeys.savedSignature(), null)
66
+ });
67
+ }
68
+ function pngBytes(base64) {
69
+ const raw = atob(base64);
70
+ const out = new Uint8Array(raw.length);
71
+ for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
72
+ return out;
73
+ }
74
+ function pngSize(base64) {
75
+ const bytes = pngBytes(base64.slice(0, 64));
76
+ const view = new DataView(bytes.buffer);
77
+ return { width: view.getUint32(16), height: view.getUint32(20) };
78
+ }
79
+ export {
80
+ INFORMAL_SIGNATURE_NOTE,
81
+ deleteSavedSignature,
82
+ fetchSavedSignature,
83
+ pngBytes,
84
+ pngSize,
85
+ storeSavedSignature,
86
+ useDeleteSavedSignature,
87
+ useSavedSignature,
88
+ useStoreSavedSignature
89
+ };
90
+ //# sourceMappingURL=saved-signature.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/document-tools/saved-signature.ts"],
4
+ "sourcesContent": ["/**\n * A signature saved to one's account, for informal use: inserted into a Word document as a picture,\n * or placed on a PDF as a stamp, and offered again the next time one adopts a signature to sign.\n *\n * It is sealed HERE, in the browser, to the user's own X25519 key (a SealedBox to the public half of\n * the keypair their signing key derives): the server keeps the sealed bytes (`/v1/user/signature`)\n * and can never read them. Only with the user's explicit consent (\"Save to my account for future\n * use\"); Delete removes it from the account completely. A typed mark is saved as its picture too,\n * so every use has an image to place.\n */\n\nimport {\n getUserEncryptionKeypair,\n initSodium,\n sealedBoxDecrypt,\n sealedBoxEncrypt,\n type KeyPair,\n} from '@arbidocs/client'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useDocumentTools, type DocumentToolsClient } from './environment'\nimport { arbiQueryKeys } from '../query-keys'\n\nexport interface SavedSignature {\n name: string\n initials: string\n /** How the signature was adopted (a typed one is saved as its picture as well). */\n style: 'typed' | 'drawn' | 'uploaded'\n initials_style: 'typed' | 'drawn'\n /** Base64 PNGs, transparent around the ink. */\n signature_png: string\n initials_png: string\n}\n\n/** The one line shown wherever a saved signature is placed by hand. */\nexport const INFORMAL_SIGNATURE_NOTE =\n 'Your saved signature or initials are placed as an image on the document.'\n\n/** The user's own keypair (the session's); a host or a test may pass another. */\nexport type KeypairSource = () => Promise<KeyPair | null>\n\nasync function keypair(source: KeypairSource = getUserEncryptionKeypair): Promise<KeyPair> {\n await initSodium()\n const pair = await source()\n if (!pair) throw new Error('Sign in again to use your saved signature.')\n return pair\n}\n\nfunction detail(error: unknown, fallback: string): string {\n const d = (error as { detail?: unknown } | undefined)?.detail\n return typeof d === 'string' ? d : fallback\n}\n\n/** The saved signature, opened with the user's own key; null when none is saved. */\nexport async function fetchSavedSignature(\n client: DocumentToolsClient,\n source?: KeypairSource\n): Promise<SavedSignature | null> {\n const { data, error } = await client.GET('/v1/user/signature')\n if (!data) throw new Error(detail(error, 'Your saved signature could not be read'))\n if (!data.sealed) return null\n const pair = await keypair(source)\n const json = new TextDecoder().decode(sealedBoxDecrypt(data.sealed, pair.secretKey))\n return JSON.parse(json) as SavedSignature\n}\n\n/** Seal it to the user's own key and save it (replacing any saved before). */\nexport async function storeSavedSignature(\n client: DocumentToolsClient,\n signature: SavedSignature,\n source?: KeypairSource\n): Promise<void> {\n const pair = await keypair(source)\n const sealed = sealedBoxEncrypt(\n Uint8Array.from(new TextEncoder().encode(JSON.stringify(signature))),\n pair.publicKey\n )\n const { error, response } = await client.PUT('/v1/user/signature', { body: { sealed } })\n if (!response.ok) throw new Error(detail(error, 'Your signature could not be saved'))\n}\n\n/** Remove it from the account completely. */\nexport async function deleteSavedSignature(client: DocumentToolsClient): Promise<void> {\n const { error, response } = await client.DELETE('/v1/user/signature')\n if (!response.ok) throw new Error(detail(error, 'Your saved signature could not be deleted'))\n}\n\nexport function useSavedSignature(enabled = true) {\n const { client } = useDocumentTools()\n return useQuery({\n queryKey: arbiQueryKeys.savedSignature(),\n queryFn: () => fetchSavedSignature(client),\n enabled,\n staleTime: 60_000,\n retry: false,\n })\n}\n\nexport function useStoreSavedSignature() {\n const { client } = useDocumentTools()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (signature: SavedSignature) => storeSavedSignature(client, signature),\n onSuccess: (_, signature) =>\n queryClient.setQueryData(arbiQueryKeys.savedSignature(), signature),\n })\n}\n\nexport function useDeleteSavedSignature() {\n const { client } = useDocumentTools()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: () => deleteSavedSignature(client),\n onSuccess: () => queryClient.setQueryData(arbiQueryKeys.savedSignature(), null),\n })\n}\n\n/** Base64 PNG bytes, decoded (for an inline picture or an upload). */\nexport function pngBytes(base64: string): Uint8Array {\n const raw = atob(base64)\n const out = new Uint8Array(raw.length)\n for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i)\n return out\n}\n\n/** A PNG's pixel size, read from its header (IHDR). */\nexport function pngSize(base64: string): { width: number; height: number } {\n const bytes = pngBytes(base64.slice(0, 64))\n const view = new DataView(bytes.buffer)\n return { width: view.getUint32(16), height: view.getUint32(20) }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }