@arbidocs/blocks 0.4.150 → 0.4.152

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 (107) hide show
  1. package/dist/{ConnectedNativeDocxComparison-XQSXVGHR.js → ConnectedNativeDocxComparison-OFPIXNJB.js} +6 -6
  2. package/dist/{ConnectedStreamedWordArtifact-UZVNBKQB.js.map → ConnectedNativeDocxComparison-OFPIXNJB.js.map} +1 -1
  3. package/dist/{ConnectedNativeDocxComparison-3XQSINPQ.cjs → ConnectedNativeDocxComparison-Y5BNLNH6.cjs} +7 -7
  4. package/dist/{ConnectedNativeDocxComparison-3XQSINPQ.cjs.map → ConnectedNativeDocxComparison-Y5BNLNH6.cjs.map} +1 -1
  5. package/dist/{ConnectedNativeDocxEditor-OUWFMIPH.cjs → ConnectedNativeDocxEditor-HTEW5JAH.cjs} +7 -7
  6. package/dist/{ConnectedNativeDocxEditor-OUWFMIPH.cjs.map → ConnectedNativeDocxEditor-HTEW5JAH.cjs.map} +1 -1
  7. package/dist/{ConnectedNativeDocxEditor-IPEZDERL.js → ConnectedNativeDocxEditor-LRYU5HPA.js} +5 -5
  8. package/dist/{ConnectedNativeDocxEditor-IPEZDERL.js.map → ConnectedNativeDocxEditor-LRYU5HPA.js.map} +1 -1
  9. package/dist/{ConnectedStreamedWordArtifact-UZVNBKQB.js → ConnectedStreamedWordArtifact-QAUVUCSX.js} +6 -6
  10. package/dist/{ConnectedNativeDocxComparison-XQSXVGHR.js.map → ConnectedStreamedWordArtifact-QAUVUCSX.js.map} +1 -1
  11. package/dist/{ConnectedStreamedWordArtifact-D5LSMDO4.cjs → ConnectedStreamedWordArtifact-QW74LKHN.cjs} +7 -7
  12. package/dist/ConnectedStreamedWordArtifact-QW74LKHN.cjs.map +1 -0
  13. package/dist/agents/index.cjs +238 -238
  14. package/dist/agents/index.js +4 -4
  15. package/dist/calls/index.cjs +3 -3
  16. package/dist/calls/index.js +2 -2
  17. package/dist/{chunk-IPQ5MJ4Z.cjs → chunk-2FLWPM3B.cjs} +5 -5
  18. package/dist/{chunk-IPQ5MJ4Z.cjs.map → chunk-2FLWPM3B.cjs.map} +1 -1
  19. package/dist/{chunk-CQPFW64W.js → chunk-3PCBYOIZ.js} +3 -3
  20. package/dist/{chunk-CQPFW64W.js.map → chunk-3PCBYOIZ.js.map} +1 -1
  21. package/dist/{chunk-Q6N6MZKO.js → chunk-4236BRZK.js} +3 -3
  22. package/dist/{chunk-Q6N6MZKO.js.map → chunk-4236BRZK.js.map} +1 -1
  23. package/dist/{chunk-KLPRAQCE.cjs → chunk-6I6CVX5G.cjs} +2 -2
  24. package/dist/{chunk-KLPRAQCE.cjs.map → chunk-6I6CVX5G.cjs.map} +1 -1
  25. package/dist/{chunk-TAWPVD6C.cjs → chunk-B3FMUFAW.cjs} +3 -3
  26. package/dist/{chunk-TAWPVD6C.cjs.map → chunk-B3FMUFAW.cjs.map} +1 -1
  27. package/dist/{chunk-3E2F4AHD.js → chunk-CROTH2BS.js} +5 -5
  28. package/dist/{chunk-3E2F4AHD.js.map → chunk-CROTH2BS.js.map} +1 -1
  29. package/dist/{chunk-ILM42LE6.cjs → chunk-CU2O32Z4.cjs} +25 -25
  30. package/dist/{chunk-ILM42LE6.cjs.map → chunk-CU2O32Z4.cjs.map} +1 -1
  31. package/dist/{chunk-TL45OJQE.js → chunk-DB2OXRQC.js} +3 -3
  32. package/dist/{chunk-TL45OJQE.js.map → chunk-DB2OXRQC.js.map} +1 -1
  33. package/dist/{chunk-ZAVEMQ37.cjs → chunk-DWZXSPMB.cjs} +3 -3
  34. package/dist/{chunk-ZAVEMQ37.cjs.map → chunk-DWZXSPMB.cjs.map} +1 -1
  35. package/dist/{chunk-XRWHFMHK.js → chunk-EYJMMGXF.js} +2 -2
  36. package/dist/{chunk-XRWHFMHK.js.map → chunk-EYJMMGXF.js.map} +1 -1
  37. package/dist/{chunk-NWNAYXC7.cjs → chunk-GFOEWPAP.cjs} +3 -3
  38. package/dist/{chunk-NWNAYXC7.cjs.map → chunk-GFOEWPAP.cjs.map} +1 -1
  39. package/dist/{chunk-YIFCLNII.cjs → chunk-HALD6ZB5.cjs} +4 -4
  40. package/dist/{chunk-YIFCLNII.cjs.map → chunk-HALD6ZB5.cjs.map} +1 -1
  41. package/dist/{chunk-TC25LGIM.js → chunk-HUJF2XM2.js} +4 -4
  42. package/dist/chunk-HUJF2XM2.js.map +1 -0
  43. package/dist/{chunk-GGTUMLCT.cjs → chunk-Q4BY2CQQ.cjs} +3 -3
  44. package/dist/{chunk-GGTUMLCT.cjs.map → chunk-Q4BY2CQQ.cjs.map} +1 -1
  45. package/dist/{chunk-AXTDDWMR.js → chunk-QN47Q4N7.js} +3 -3
  46. package/dist/{chunk-AXTDDWMR.js.map → chunk-QN47Q4N7.js.map} +1 -1
  47. package/dist/{chunk-V4YZXGXR.cjs → chunk-T74Q3MCZ.cjs} +4 -4
  48. package/dist/chunk-T74Q3MCZ.cjs.map +1 -0
  49. package/dist/{chunk-3FSXWVHW.cjs → chunk-U6JQ4KMX.cjs} +3 -3
  50. package/dist/{chunk-3FSXWVHW.cjs.map → chunk-U6JQ4KMX.cjs.map} +1 -1
  51. package/dist/{chunk-ECERC6TI.js → chunk-VHJHY7TT.js} +3 -3
  52. package/dist/{chunk-ECERC6TI.js.map → chunk-VHJHY7TT.js.map} +1 -1
  53. package/dist/{chunk-UTVY63DG.js → chunk-WFA2GVZJ.js} +3 -3
  54. package/dist/{chunk-UTVY63DG.js.map → chunk-WFA2GVZJ.js.map} +1 -1
  55. package/dist/{chunk-ZO7PJMCO.js → chunk-WU34CHU5.js} +3 -3
  56. package/dist/{chunk-ZO7PJMCO.js.map → chunk-WU34CHU5.js.map} +1 -1
  57. package/dist/{chunk-HGLC566X.js → chunk-YXNNNP57.js} +3 -3
  58. package/dist/{chunk-HGLC566X.js.map → chunk-YXNNNP57.js.map} +1 -1
  59. package/dist/{chunk-EDV7CYG6.cjs → chunk-ZP6Q3KXU.cjs} +4 -4
  60. package/dist/{chunk-EDV7CYG6.cjs.map → chunk-ZP6Q3KXU.cjs.map} +1 -1
  61. package/dist/collaboration/index.cjs +1 -1
  62. package/dist/collaboration/index.js +1 -1
  63. package/dist/connect/docx.cjs +9 -9
  64. package/dist/connect/docx.js +5 -5
  65. package/dist/connect/index.cjs +292 -292
  66. package/dist/connect/index.d.ts +1 -1
  67. package/dist/connect/index.js +13 -13
  68. package/dist/connect/viewer.cjs +1249 -121
  69. package/dist/connect/viewer.cjs.map +1 -1
  70. package/dist/connect/viewer.js +1145 -21
  71. package/dist/connect/viewer.js.map +1 -1
  72. package/dist/connection/viewer/parsed/ParsedPassage.d.ts +48 -0
  73. package/dist/connection/viewer/parsed/ParsedTextView.d.ts +17 -0
  74. package/dist/connection/viewer/parsed/PassageTagPanel.d.ts +18 -0
  75. package/dist/connection/viewer/parsed/citation-line.d.ts +17 -0
  76. package/dist/connection/viewer/parsed/document-tags.d.ts +8 -0
  77. package/dist/connection/viewer/parsed/useChunkTagging.d.ts +46 -0
  78. package/dist/connection/viewer/parsed/useCitationSelection.d.ts +27 -0
  79. package/dist/connection/viewer/parsed/useDocumentLabels.d.ts +38 -0
  80. package/dist/connection/viewer/parsed/useLazyPages.d.ts +18 -0
  81. package/dist/connection/viewer/parsed/usePageScrollSync.d.ts +17 -0
  82. package/dist/connection/viewer/parsed/usePassageCopy.d.ts +25 -0
  83. package/dist/connection/viewer/support.d.ts +27 -9
  84. package/dist/facts/index.cjs +55 -55
  85. package/dist/facts/index.js +5 -5
  86. package/dist/files/TagPassagePanel.d.ts +2 -1
  87. package/dist/files/index.cjs +169 -169
  88. package/dist/files/index.js +3 -3
  89. package/dist/home/index.cjs +2 -2
  90. package/dist/home/index.js +2 -2
  91. package/dist/index.cjs +355 -355
  92. package/dist/index.js +8 -8
  93. package/dist/retrieval/index.cjs +1 -1
  94. package/dist/retrieval/index.js +1 -1
  95. package/dist/settings/index.cjs +164 -164
  96. package/dist/settings/index.js +3 -3
  97. package/dist/shell/index.cjs +2 -2
  98. package/dist/shell/index.js +2 -2
  99. package/dist/studio/index.cjs +2 -2
  100. package/dist/studio/index.js +2 -2
  101. package/dist/workflow-canvas/index.cjs +16 -16
  102. package/dist/workflow-canvas/index.js +4 -4
  103. package/node_modules/@arbidocs/coedit/package.json +1 -1
  104. package/package.json +5 -5
  105. package/dist/ConnectedStreamedWordArtifact-D5LSMDO4.cjs.map +0 -1
  106. package/dist/chunk-TC25LGIM.js.map +0 -1
  107. package/dist/chunk-V4YZXGXR.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkV4YZXGXR_cjs = require('../chunk-V4YZXGXR.cjs');
5
- var chunkKLPRAQCE_cjs = require('../chunk-KLPRAQCE.cjs');
4
+ var chunkT74Q3MCZ_cjs = require('../chunk-T74Q3MCZ.cjs');
5
+ var chunk6I6CVX5G_cjs = require('../chunk-6I6CVX5G.cjs');
6
6
  require('../chunk-YAEXSCUW.cjs');
7
7
  require('../chunk-223D4727.cjs');
8
8
  var chunkGAYMJWTC_cjs = require('../chunk-GAYMJWTC.cjs');
@@ -16,6 +16,7 @@ require('../chunk-COCGRJLA.cjs');
16
16
  var chunkVLCY46K6_cjs = require('../chunk-VLCY46K6.cjs');
17
17
  require('../chunk-FAXXN7KI.cjs');
18
18
  require('../chunk-V46W7YLI.cjs');
19
+ var chunkLJJJ6CYH_cjs = require('../chunk-LJJJ6CYH.cjs');
19
20
  require('../chunk-SIB6C7P7.cjs');
20
21
  require('../chunk-DVUZTGVL.cjs');
21
22
  require('../chunk-AHDJXIUB.cjs');
@@ -27,8 +28,6 @@ var chunk2YV7FBLO_cjs = require('../chunk-2YV7FBLO.cjs');
27
28
  require('../chunk-VG24E4JJ.cjs');
28
29
  require('../chunk-QVBZESYQ.cjs');
29
30
  var chunk7RGLTF76_cjs = require('../chunk-7RGLTF76.cjs');
30
- var chunkKPZZ5FHE_cjs = require('../chunk-KPZZ5FHE.cjs');
31
- require('../chunk-ULWRNGGE.cjs');
32
31
  require('../chunk-5UHAWSEX.cjs');
33
32
  require('../chunk-B6MVQCXW.cjs');
34
33
  var chunkJKB7WT7L_cjs = require('../chunk-JKB7WT7L.cjs');
@@ -36,11 +35,14 @@ require('../chunk-32HW2Q33.cjs');
36
35
  var chunkFX3K6LNZ_cjs = require('../chunk-FX3K6LNZ.cjs');
37
36
  require('../chunk-PPCATBOY.cjs');
38
37
  require('../chunk-MHVNT4J3.cjs');
38
+ var chunkLXTOOUEN_cjs = require('../chunk-LXTOOUEN.cjs');
39
+ var chunkKPZZ5FHE_cjs = require('../chunk-KPZZ5FHE.cjs');
40
+ require('../chunk-ULWRNGGE.cjs');
39
41
  var chunkKDG6FER6_cjs = require('../chunk-KDG6FER6.cjs');
40
42
  require('../chunk-DES3K4SD.cjs');
41
- var react = require('react');
43
+ var React = require('react');
42
44
  var lucideReact = require('lucide-react');
43
- var react$1 = require('@arbidocs/react');
45
+ var react = require('@arbidocs/react');
44
46
  var artifacts = require('@arbidocs/react/artifacts');
45
47
  var documentTools = require('@arbidocs/react/document-tools');
46
48
  var viewers = require('@arbidocs/react/viewers');
@@ -48,41 +50,45 @@ var ui = require('@arbidocs/react/ui');
48
50
  var reactQuery = require('@tanstack/react-query');
49
51
  var jsxRuntime = require('react/jsx-runtime');
50
52
 
53
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
54
+
55
+ var React__default = /*#__PURE__*/_interopDefault(React);
56
+
51
57
  function ConnectedDocumentToolsProvider({ children }) {
52
58
  const enclosing = documentTools.useOptionalDocumentTools();
53
59
  return enclosing ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : /* @__PURE__ */ jsxRuntime.jsx(OwnDocumentTools, { children });
54
60
  }
55
61
  function OwnDocumentTools({ children }) {
56
- const arbi = react$1.useArbi();
62
+ const arbi = react.useArbi();
57
63
  const queryClient = reactQuery.useQueryClient();
58
64
  const { user, ensureWorkspaceOpen } = chunkGFNELPDP_cjs.useConnectedWorkspace();
59
65
  const { notify: environmentNotify, openDocument: openInHost } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
60
66
  const client = arbi.isLoggedIn ? arbi.getClient().fetch : null;
61
- const signer = react.useMemo(
67
+ const signer = React.useMemo(
62
68
  () => user ? { name: user.name, email: user.email, externalId: user.externalId } : null,
63
69
  [user]
64
70
  );
65
- const notify = react.useCallback(
71
+ const notify = React.useCallback(
66
72
  (message, kind, options) => environmentNotify(message, kind, {
67
73
  description: options?.description,
68
74
  action: options?.action
69
75
  }),
70
76
  [environmentNotify]
71
77
  );
72
- const onDocumentsChanged = react.useCallback(
78
+ const onDocumentsChanged = React.useCallback(
73
79
  async (ids, change) => {
74
- const refresh = [react$1.refreshDocuments(queryClient, arbi, ids)];
80
+ const refresh = [react.refreshDocuments(queryClient, arbi, ids)];
75
81
  if (change === "signed" || change === "version")
76
82
  for (const id of ids)
77
83
  refresh.push(
78
- queryClient.invalidateQueries({ queryKey: react$1.arbiQueryKeys.documentVersions(id) }),
84
+ queryClient.invalidateQueries({ queryKey: react.arbiQueryKeys.documentVersions(id) }),
79
85
  queryClient.invalidateQueries({ queryKey: documentTools.documentBytesKey(id) })
80
86
  );
81
87
  await Promise.all(refresh);
82
88
  },
83
89
  [queryClient, arbi]
84
90
  );
85
- const uploadDocument = react.useCallback(
91
+ const uploadDocument = React.useCallback(
86
92
  async (request) => {
87
93
  if (!client) throw new Error("Sign in to save a copy.");
88
94
  await ensureWorkspaceOpen();
@@ -90,7 +96,7 @@ function OwnDocumentTools({ children }) {
90
96
  },
91
97
  [client, ensureWorkspaceOpen]
92
98
  );
93
- const openDocument = react.useCallback((ref) => openInHost(ref), [openInHost]);
99
+ const openDocument = React.useCallback((ref) => openInHost(ref), [openInHost]);
94
100
  if (!client) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
95
101
  return /* @__PURE__ */ jsxRuntime.jsx(
96
102
  documentTools.DocumentToolsProvider,
@@ -107,17 +113,17 @@ function OwnDocumentTools({ children }) {
107
113
  }
108
114
  var isTranslationDraft = (doc) => !!doc?.derived_from?.some((d) => d.role === "translation") && !doc.derived_from.some((d) => d.role === "final");
109
115
  function FinaliseTranslationButton({
110
- document,
116
+ document: document2,
111
117
  isCompact
112
118
  }) {
113
- const finalise = react$1.useFinaliseTranslation();
119
+ const finalise = react.useFinaliseTranslation();
114
120
  const { openDocument } = documentTools.useDocumentTools();
115
121
  const { notify } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
116
- if (!document || !isTranslationDraft(document)) return null;
122
+ if (!document2 || !isTranslationDraft(document2)) return null;
117
123
  const pending = finalise.isPending;
118
124
  const onClick = async () => {
119
125
  try {
120
- const { document_ext_id: finalId } = await finalise.mutateAsync(document.external_id);
126
+ const { document_ext_id: finalId } = await finalise.mutateAsync(document2.external_id);
121
127
  notify("Saved the final PDF of this translation", "success");
122
128
  openDocument?.(finalId);
123
129
  } catch (error) {
@@ -150,18 +156,18 @@ function FinaliseTranslationButton({
150
156
  function useImageCrop(documentId, fileName, imageBlob) {
151
157
  const { uploadDocument, onDocumentsChanged, openDocument } = documentTools.useDocumentTools();
152
158
  const { notify } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
153
- const [cropImageUrl, setCropImageUrl] = react.useState(null);
154
- const handleOpenCrop = react.useCallback(() => {
159
+ const [cropImageUrl, setCropImageUrl] = React.useState(null);
160
+ const handleOpenCrop = React.useCallback(() => {
155
161
  if (!imageBlob) return;
156
162
  setCropImageUrl(URL.createObjectURL(imageBlob));
157
163
  }, [imageBlob]);
158
- const closeCrop = react.useCallback(() => {
164
+ const closeCrop = React.useCallback(() => {
159
165
  setCropImageUrl((url) => {
160
166
  if (url) URL.revokeObjectURL(url);
161
167
  return null;
162
168
  });
163
169
  }, []);
164
- const handleCropComplete = react.useCallback(
170
+ const handleCropComplete = React.useCallback(
165
171
  async (result) => {
166
172
  const baseName = (fileName || "image").replace(/\.[^.]+$/, "");
167
173
  const file = new File([result.blob], `${baseName} (cropped).png`, { type: "image/png" });
@@ -194,9 +200,9 @@ function fileExtension(fileName) {
194
200
  return fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
195
201
  }
196
202
  function useViewedDocument(documentId) {
197
- const support = chunkKLPRAQCE_cjs.useDocumentViewerSupport();
198
- const [webmHasVideoTrack, setWebmHasVideoTrack] = react.useState(null);
199
- react.useEffect(() => setWebmHasVideoTrack(null), [documentId]);
203
+ const support = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
204
+ const [webmHasVideoTrack, setWebmHasVideoTrack] = React.useState(null);
205
+ React.useEffect(() => setWebmHasVideoTrack(null), [documentId]);
200
206
  const streamingDoc = support.streamingDocuments?.[documentId];
201
207
  const isStreaming = !!streamingDoc && !streamingDoc.isComplete;
202
208
  const draftDoc = support.draftDocuments?.[documentId];
@@ -204,7 +210,7 @@ function useViewedDocument(documentId) {
204
210
  const isCaptureDraft = draftDoc?.kind === "audio" || draftDoc?.kind === "photo" || draftDoc?.kind === "video";
205
211
  const isTextDraft = draftDoc?.kind === "text";
206
212
  const { workspaceId, live } = chunkGFNELPDP_cjs.useConnectedWorkspace();
207
- const { data: record } = react$1.useDocument(documentId, {
213
+ const { data: record } = react.useDocument(documentId, {
208
214
  enabled: live && !!workspaceId && !isStreaming && !isDraft,
209
215
  // A new version (Save version, a signed copy) is processed before its PDF exists: keep
210
216
  // re-reading until it is done, so the PDF tab and the signing tools come back on their own.
@@ -212,8 +218,8 @@ function useViewedDocument(documentId) {
212
218
  });
213
219
  const documentData = record?.external_id === documentId ? record : void 0;
214
220
  const { data: tags } = chunkGAYMJWTC_cjs.useConnectedTags();
215
- const labelSummaries = react.useMemo(
216
- () => chunkV4YZXGXR_cjs.summariseDocTags(documentData?.doctags ?? [], tags.filter(chunkV4YZXGXR_cjs.isDocumentLabel)),
221
+ const labelSummaries = React.useMemo(
222
+ () => chunkT74Q3MCZ_cjs.summariseDocTags(documentData?.doctags ?? [], tags.filter(chunkT74Q3MCZ_cjs.isDocumentLabel)),
217
223
  [documentData, tags]
218
224
  );
219
225
  const fileName = documentData?.file_name;
@@ -238,7 +244,7 @@ function useViewedDocument(documentId) {
238
244
  );
239
245
  const liveSource = streamingDoc ? streamingDoc.content : liveSourceFetched ?? "";
240
246
  const hasParsedDocStatus = documentData?.status === "completed" || documentData?.status === "low-content";
241
- const { data: parsedDoc, isLoading: isParsedDocLoading } = react$1.useParsedDocument(
247
+ const { data: parsedDoc, isLoading: isParsedDocLoading } = react.useParsedDocument(
242
248
  documentId,
243
249
  "final",
244
250
  {
@@ -280,7 +286,7 @@ function useViewerBlobs(documentId, doc) {
280
286
  const { setWebmHasVideoTrack } = doc;
281
287
  const { client, saveFile } = documentTools.useDocumentTools();
282
288
  const { notify } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
283
- const { loadOfflineCopy } = chunkKLPRAQCE_cjs.useDocumentViewerSupport();
289
+ const { loadOfflineCopy } = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
284
290
  const currentVersion = documentData?.current_version ?? 1;
285
291
  const name = documentData?.file_name;
286
292
  const original = ui.isImageFile(name) || ui.isVideoFile(name) || ui.isAudioFile(name);
@@ -291,15 +297,15 @@ function useViewerBlobs(documentId, doc) {
291
297
  enabled: !isArtifact && !!documentData && !isDownloadOnly && (!isDocx || documentData.status === "completed" || documentData.status === "low-content"),
292
298
  fallback
293
299
  });
294
- const [pdfBlob, setPdfBlob] = react.useState(null);
295
- react.useEffect(() => setPdfBlob(null), [documentId]);
296
- react.useEffect(() => {
300
+ const [pdfBlob, setPdfBlob] = React.useState(null);
301
+ React.useEffect(() => setPdfBlob(null), [documentId]);
302
+ React.useEffect(() => {
297
303
  if (pdf.data) setPdfBlob(pdf.data);
298
304
  }, [pdf.data]);
299
- react.useEffect(() => {
305
+ React.useEffect(() => {
300
306
  if (!isWebmFile || !pdfBlob) return;
301
307
  let cancelled = false;
302
- void react$1.hasVideoTrack(pdfBlob).then((result) => {
308
+ void react.hasVideoTrack(pdfBlob).then((result) => {
303
309
  if (!cancelled) setWebmHasVideoTrack(result);
304
310
  });
305
311
  return () => {
@@ -311,7 +317,7 @@ function useViewerBlobs(documentId, doc) {
311
317
  kind: "original",
312
318
  enabled: !isArtifact && !!documentData && isXlsx
313
319
  });
314
- const handleDirectDownload = react.useCallback(async () => {
320
+ const handleDirectDownload = React.useCallback(async () => {
315
321
  try {
316
322
  saveFile(await documentTools.fetchDocumentFile(client, documentId), documentData?.file_name || "download");
317
323
  } catch {
@@ -341,20 +347,20 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
341
347
  hasParsedContent,
342
348
  isParsedDocLoading
343
349
  } = doc;
344
- const session = react$1.useArbiSessionStore();
350
+ const session = react.useArbiSessionStore();
345
351
  const {
346
352
  tab: activeTab,
347
353
  compareId,
348
354
  tabRequest,
349
355
  phonePdfChosen
350
- } = react$1.useArbiSessionState((s) => s.documentViewer);
356
+ } = react.useArbiSessionState((s) => s.documentViewer);
351
357
  const setActiveTab = (tab) => session.setDocumentViewer({ tab });
352
358
  const isTextFile = ui.friendlyFileType(documentData?.file_type, documentData?.file_name) === "Text";
353
359
  const isPhone = chunkFX3K6LNZ_cjs.useIsPhone();
354
- const phoneDefaultDecidedFor = react.useRef(null);
360
+ const phoneDefaultDecidedFor = React.useRef(null);
355
361
  const hasDocumentData = !!documentData;
356
362
  const documentKey = documentData?.external_id;
357
- react.useEffect(() => {
363
+ React.useEffect(() => {
358
364
  if (isArtifact && (activeTab === "pdf" || !liveKind && activeTab === "docx")) {
359
365
  setActiveTab(liveKind ? "preview" : "edit");
360
366
  } else if (isDocx && activeTab === "pdf") {
@@ -367,18 +373,18 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
367
373
  setActiveTab("pdf");
368
374
  }
369
375
  }, [hasDocumentData, documentKey, isArtifact, isDocx, isXlsx, liveKind]);
370
- react.useEffect(() => {
376
+ React.useEffect(() => {
371
377
  if (!tabRequest || !documentKey || tabRequest.documentId !== documentKey) return;
372
378
  phoneDefaultDecidedFor.current = documentKey;
373
379
  session.setDocumentViewer({ tabRequest: null, tab: tabRequest.tab });
374
380
  }, [documentKey, tabRequest]);
375
381
  const hasVersionsTab = isArtifact || isDocx || hasHistory;
376
- react.useEffect(() => {
382
+ React.useEffect(() => {
377
383
  if (activeTab === "versions" && documentData && !hasVersionsTab) {
378
384
  setActiveTab(isXlsx ? "xlsx" : "pdf");
379
385
  }
380
386
  }, [activeTab, documentData, hasVersionsTab]);
381
- react.useEffect(() => {
387
+ React.useEffect(() => {
382
388
  if (activeTab === "html" && documentData !== void 0 && !isParsedDocLoading && !hasParsedContent && !compareId) {
383
389
  setActiveTab(isArtifact ? "edit" : isDocx ? "docx" : isXlsx ? "xlsx" : "pdf");
384
390
  }
@@ -392,7 +398,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
392
398
  isDocx,
393
399
  isXlsx
394
400
  ]);
395
- react.useEffect(() => {
401
+ React.useEffect(() => {
396
402
  if (!isPhone || !documentKey || isParsedDocLoading) return;
397
403
  if (phoneDefaultDecidedFor.current === documentKey) return;
398
404
  phoneDefaultDecidedFor.current = documentKey;
@@ -407,7 +413,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
407
413
  if (isPhone && (tabId === "pdf" || tabId === "html")) change.phonePdfChosen = tabId === "pdf";
408
414
  session.setDocumentViewer(change);
409
415
  };
410
- const mediaTab = isVideo ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.VidIcon, { size: 20 }), tooltip: "Video" } : isAudio ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.AudIcon, { size: 20 }), tooltip: "Audio" } : isImage ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.ImgIcon, { size: 20 }), tooltip: "Image" } : isEmail ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.EmlIcon, { size: 20 }), tooltip: "Email" } : isTextFile ? { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-5" }), tooltip: "Text" } : documentData ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.PdfIcon, { size: 20 }), tooltip: "PDF" } : (
416
+ const mediaTab = isVideo ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react.VidIcon, { size: 20 }), tooltip: "Video" } : isAudio ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react.AudIcon, { size: 20 }), tooltip: "Audio" } : isImage ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react.ImgIcon, { size: 20 }), tooltip: "Image" } : isEmail ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react.EmlIcon, { size: 20 }), tooltip: "Email" } : isTextFile ? { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-5" }), tooltip: "Text" } : documentData ? { icon: /* @__PURE__ */ jsxRuntime.jsx(react.PdfIcon, { size: 20 }), tooltip: "PDF" } : (
411
417
  // The file type is unknown until the record loads: name no guess (a text file
412
418
  // would flip from PDF to Text once it arrives).
413
419
  { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-5" }), tooltip: "Document" }
@@ -440,7 +446,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
440
446
  ...isDocx ? [
441
447
  {
442
448
  id: "docx",
443
- icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.DocIcon, { size: 20 }),
449
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.DocIcon, { size: 20 }),
444
450
  tooltip: "DOCX (with track changes & comments)",
445
451
  label: tabLabel("docx", "DOCX")
446
452
  }
@@ -448,7 +454,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
448
454
  ...isXlsx ? [
449
455
  {
450
456
  id: "xlsx",
451
- icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.XlsIcon, { size: 20 }),
457
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.XlsIcon, { size: 20 }),
452
458
  tooltip: "Spreadsheet",
453
459
  label: tabLabel("xlsx", "Sheet")
454
460
  }
@@ -459,7 +465,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
459
465
  ...(hasParsedContent || compareId) && !liveKind ? [
460
466
  {
461
467
  id: "html",
462
- icon: compareId ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-5" }) : /* @__PURE__ */ jsxRuntime.jsx(react$1.HtmlIcon, { size: 20 }),
468
+ icon: compareId ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-5" }) : /* @__PURE__ */ jsxRuntime.jsx(react.HtmlIcon, { size: 20 }),
463
469
  tooltip: compareId ? "Word redline" : "HTML",
464
470
  label: tabLabel("html", compareId ? "Compare" : "HTML")
465
471
  }
@@ -470,16 +476,16 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
470
476
  function useViewerVersions(docId) {
471
477
  const plainId = docId ? artifacts.parseVersionRef(docId).docId : "";
472
478
  const { data: documents } = chunkGAYMJWTC_cjs.useConnectedDocuments();
473
- const listed = react.useMemo(
479
+ const listed = React.useMemo(
474
480
  () => plainId ? documents.find((d) => d.external_id === plainId) : void 0,
475
481
  [documents, plainId]
476
482
  );
477
- const { data: history } = react$1.useDocumentVersionList(plainId, { enabled: !!plainId && !listed });
478
- const versions = react.useMemo(
483
+ const { data: history } = react.useDocumentVersionList(plainId, { enabled: !!plainId && !listed });
484
+ const versions = React.useMemo(
479
485
  () => listed ? artifacts.documentVersions(listed) : artifacts.toArtifactVersions(plainId || null, history),
480
486
  [listed, history, plainId]
481
487
  );
482
- const translations = react.useMemo(() => {
488
+ const translations = React.useMemo(() => {
483
489
  if (!plainId) return [];
484
490
  return documents.flatMap((doc) => {
485
491
  const link = doc.derived_from?.find(
@@ -498,23 +504,1142 @@ function useViewerVersions(docId) {
498
504
  }, [documents, plainId]);
499
505
  return { versions, translations };
500
506
  }
501
- var AnnotatedPdfViewer = react.lazy(
507
+
508
+ // src/connection/viewer/parsed/document-tags.ts
509
+ function isDocumentTag(tag) {
510
+ if (tag.kind === "search") return false;
511
+ const onDocs = (tag.doctag_count ?? 0) > 0;
512
+ const onFacts = (tag.facttag_count ?? 0) > 0;
513
+ return onDocs || !onFacts;
514
+ }
515
+ function hasChunkInCitations(citations, chunkExtId) {
516
+ return (citations ?? []).some((d) => d.chunks?.some((c) => c.chunk_id === chunkExtId));
517
+ }
518
+ function removeChunkFromCitations(citations, chunkExtId) {
519
+ if (!citations) return null;
520
+ const next = citations.map((d) => ({ ...d, chunks: (d.chunks ?? []).filter((c) => c.chunk_id !== chunkExtId) })).filter((d) => d.chunks.length > 0);
521
+ return next.length ? next : null;
522
+ }
523
+ function addChunkToCitations(citations, documentId, chunkExtId) {
524
+ const chunk = { chunk_id: chunkExtId, page: null };
525
+ const list = citations ?? [];
526
+ const idx = list.findIndex((d) => d.doc_ext_id === documentId);
527
+ if (idx === -1) return [...list, { doc_ext_id: documentId, chunks: [chunk] }];
528
+ const doc = list[idx];
529
+ if ((doc.chunks ?? []).some((c) => c.chunk_id === chunkExtId)) return list;
530
+ const next = [...list];
531
+ next[idx] = { ...doc, chunks: [...doc.chunks ?? [], chunk] };
532
+ return next;
533
+ }
534
+ function useChunkTagging({ documentId, documentDoctags }) {
535
+ const createDocTag = react.useAssignDocTags();
536
+ const updateDocTag = react.useUpdateDocTag();
537
+ const deleteDocTag = react.useRemoveDocTags();
538
+ const getChunkTagState = React.useCallback(
539
+ (chunkExtId) => {
540
+ const appliedTags = documentDoctags.filter(
541
+ (dt) => hasChunkInCitations(dt.citations, chunkExtId)
542
+ );
543
+ const isTagApplied = (tagExtId) => {
544
+ return appliedTags.some((dt) => dt.tag_ext_id === tagExtId);
545
+ };
546
+ const getDoctagForChunk = (tagExtId) => {
547
+ return appliedTags.find((dt) => dt.tag_ext_id === tagExtId);
548
+ };
549
+ return {
550
+ appliedTags,
551
+ isTagApplied,
552
+ getDoctagForChunk
553
+ };
554
+ },
555
+ [documentDoctags]
556
+ );
557
+ const toggleChunkTag = React.useCallback(
558
+ async (chunkExtId, tag, note) => {
559
+ const existingDoctag = documentDoctags.find((dt) => dt.tag_ext_id === tag.external_id);
560
+ const isChunkTagged = hasChunkInCitations(existingDoctag?.citations, chunkExtId);
561
+ if (isChunkTagged) {
562
+ const updatedCitations = removeChunkFromCitations(existingDoctag.citations, chunkExtId);
563
+ if (!updatedCitations) {
564
+ await deleteDocTag.mutateAsync({
565
+ tagId: tag.external_id,
566
+ docIds: [documentId]
567
+ });
568
+ } else {
569
+ await updateDocTag.mutateAsync({
570
+ tagId: tag.external_id,
571
+ docId: documentId,
572
+ citations: updatedCitations,
573
+ note: existingDoctag.note
574
+ });
575
+ }
576
+ } else {
577
+ if (existingDoctag) {
578
+ const updatedCitations = addChunkToCitations(
579
+ existingDoctag.citations,
580
+ documentId,
581
+ chunkExtId
582
+ );
583
+ await updateDocTag.mutateAsync({
584
+ tagId: tag.external_id,
585
+ docId: documentId,
586
+ citations: updatedCitations,
587
+ note: note ?? existingDoctag.note
588
+ });
589
+ } else {
590
+ const newCitations = addChunkToCitations(null, documentId, chunkExtId);
591
+ await createDocTag.mutateAsync({
592
+ tagId: tag.external_id,
593
+ docIds: [documentId],
594
+ citations: newCitations,
595
+ note
596
+ });
597
+ }
598
+ }
599
+ },
600
+ [documentId, documentDoctags, createDocTag, updateDocTag, deleteDocTag]
601
+ );
602
+ const updateChunkTagNote = React.useCallback(
603
+ async (_chunkExtId, tag, note) => {
604
+ const existingDoctag = documentDoctags.find((dt) => dt.tag_ext_id === tag.external_id);
605
+ if (!existingDoctag) return;
606
+ await updateDocTag.mutateAsync({
607
+ tagId: tag.external_id,
608
+ docId: documentId,
609
+ citations: existingDoctag.citations,
610
+ note
611
+ });
612
+ },
613
+ [documentId, documentDoctags, updateDocTag]
614
+ );
615
+ const getChunkTagColors = React.useCallback(
616
+ (chunkExtId, workspaceTags) => {
617
+ const { appliedTags } = getChunkTagState(chunkExtId);
618
+ return appliedTags.map((dt) => {
619
+ const tag = workspaceTags.find((t) => t.external_id === dt.tag_ext_id);
620
+ return tag?.external_id;
621
+ }).filter((id) => !!id);
622
+ },
623
+ [getChunkTagState]
624
+ );
625
+ const isLoading = createDocTag.isPending || updateDocTag.isPending || deleteDocTag.isPending;
626
+ return {
627
+ getChunkTagState,
628
+ toggleChunkTag,
629
+ updateChunkTagNote,
630
+ getChunkTagColors,
631
+ isLoading
632
+ };
633
+ }
634
+ var GROUP_TITLES = {
635
+ checkbox: "Label",
636
+ select: "Choice",
637
+ text: "Text",
638
+ number: "Number"
639
+ };
640
+ function PassageTagPanel({
641
+ documentId,
642
+ chunkExtId,
643
+ chunkContent,
644
+ pageNumber,
645
+ documentDoctags,
646
+ onClose,
647
+ onViewTaggedChunks
648
+ }) {
649
+ const { createTag } = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
650
+ const [editingNoteTagId, setEditingNoteTagId] = React.useState(null);
651
+ const [noteValue, setNoteValue] = React.useState("");
652
+ const { data: allTags } = chunkGAYMJWTC_cjs.useConnectedTags();
653
+ const workspaceTags = React.useMemo(() => allTags.filter(isDocumentTag), [allTags]);
654
+ const { getChunkTagState, toggleChunkTag, updateChunkTagNote, isLoading } = useChunkTagging({
655
+ documentId,
656
+ documentDoctags
657
+ });
658
+ const chunkState = React.useMemo(() => getChunkTagState(chunkExtId), [getChunkTagState, chunkExtId]);
659
+ const groupedTags = React.useMemo(() => {
660
+ const groups2 = {
661
+ checkbox: [],
662
+ select: [],
663
+ text: [],
664
+ number: []
665
+ };
666
+ workspaceTags.forEach((tag) => {
667
+ const group = tag.kind === "label" ? "checkbox" : tag.kind === "annotation" ? tag.tag_type.type : null;
668
+ if (group && groups2[group]) {
669
+ groups2[group].push(tag);
670
+ }
671
+ });
672
+ return groups2;
673
+ }, [workspaceTags]);
674
+ const handleToggleTag = React.useCallback(
675
+ async (tag) => {
676
+ try {
677
+ await toggleChunkTag(chunkExtId, tag);
678
+ } catch (error) {
679
+ console.error("Failed to toggle chunk tag:", error);
680
+ }
681
+ },
682
+ [chunkExtId, toggleChunkTag]
683
+ );
684
+ const handleStartEditNote = React.useCallback(
685
+ (tagExtId) => {
686
+ const doctag = chunkState.getDoctagForChunk(tagExtId);
687
+ setNoteValue(doctag?.note || "");
688
+ setEditingNoteTagId(tagExtId);
689
+ },
690
+ [chunkState]
691
+ );
692
+ const handleSaveNote = React.useCallback(
693
+ async (tag) => {
694
+ try {
695
+ await updateChunkTagNote(chunkExtId, tag, noteValue || null);
696
+ } catch (error) {
697
+ console.error("Failed to save note:", error);
698
+ }
699
+ setEditingNoteTagId(null);
700
+ setNoteValue("");
701
+ },
702
+ [chunkExtId, noteValue, updateChunkTagNote]
703
+ );
704
+ const preview = React.useMemo(() => {
705
+ const maxLength = 200;
706
+ if (chunkContent.length <= maxLength) return chunkContent;
707
+ return chunkContent.slice(0, maxLength) + "...";
708
+ }, [chunkContent]);
709
+ const groups = React.useMemo(
710
+ () => Object.entries(groupedTags).filter(([, tags]) => tags.length > 0).map(([type, tags]) => ({
711
+ id: type,
712
+ title: GROUP_TITLES[type] ?? type,
713
+ tags: tags.map((tag) => ({
714
+ id: tag.external_id,
715
+ color: ui.getEntityColor(tag.external_id, "medium"),
716
+ isApplied: chunkState.isTagApplied(tag.external_id),
717
+ note: chunkState.getDoctagForChunk(tag.external_id)?.note,
718
+ badge: /* @__PURE__ */ jsxRuntime.jsx(ui.TagEntity, { tag, size: "sm", showTooltip: false })
719
+ }))
720
+ })),
721
+ [groupedTags, chunkState]
722
+ );
723
+ const tagById = React.useMemo(
724
+ () => new Map(workspaceTags.map((tag) => [tag.external_id, tag])),
725
+ [workspaceTags]
726
+ );
727
+ return /* @__PURE__ */ jsxRuntime.jsx(
728
+ chunkT74Q3MCZ_cjs.TagPassagePanel,
729
+ {
730
+ pageNumber,
731
+ preview,
732
+ groups,
733
+ isEmpty: workspaceTags.length === 0,
734
+ isBusy: isLoading,
735
+ editingNoteTagId,
736
+ noteValue,
737
+ onNoteChange: setNoteValue,
738
+ onToggle: (id) => {
739
+ const tag = tagById.get(id);
740
+ if (tag) void handleToggleTag(tag);
741
+ },
742
+ onViewTagged: onViewTaggedChunks,
743
+ onStartNote: handleStartEditNote,
744
+ onSaveNote: (id) => {
745
+ const tag = tagById.get(id);
746
+ if (tag) void handleSaveNote(tag);
747
+ },
748
+ onCancelNote: () => {
749
+ setEditingNoteTagId(null);
750
+ setNoteValue("");
751
+ },
752
+ onCreate: createTag,
753
+ onClose
754
+ }
755
+ );
756
+ }
757
+ var ParsedPassage = React.memo(function ParsedPassage2({
758
+ chunk,
759
+ pageNumber,
760
+ isHighlighted,
761
+ isSelected,
762
+ isCitationHighlight,
763
+ isActiveCitation,
764
+ factCitationActive,
765
+ isCitationMode,
766
+ runIsStart,
767
+ runIsEnd,
768
+ runEndIndex,
769
+ labels,
770
+ activeTagColor,
771
+ onTagPassage,
772
+ onShowLabel,
773
+ onRemoveLabel,
774
+ onChunkClick,
775
+ formatChunkWithCitation,
776
+ getPassageDeepLink,
777
+ copyToClipboard,
778
+ onOpenNavigator
779
+ }) {
780
+ const chunkId = chunk.chunkExtId;
781
+ const formattedContent = chunkId ? formatChunkWithCitation(chunk.content, pageNumber || void 0, chunkId) : "";
782
+ const isStrong = isActiveCitation || !factCitationActive && isSelected;
783
+ const isLight = isCitationHighlight || !factCitationActive && isHighlighted;
784
+ const ownIndex = chunk.chunkIndex !== void 0 ? chunk.chunkIndex + 1 : void 0;
785
+ const runLabel = runEndIndex !== void 0 && ownIndex !== void 0 && runEndIndex > ownIndex ? `\xB6${ownIndex}\u2013${runEndIndex}` : `\xB6${ownIndex ?? ""}`;
786
+ const showLabel = !!chunkId && (!isSelected || runIsStart);
787
+ const copyPassage = (type, text, href) => copyToClipboard(text, {
788
+ type,
789
+ documentTitle: chunk.docTitle || "Document",
790
+ pageNumber: pageNumber || void 0,
791
+ passageIndex: chunk.chunkIndex,
792
+ passageContent: formattedContent,
793
+ href
794
+ });
795
+ const passageItems = chunkId ? [
796
+ {
797
+ id: "copy-passage",
798
+ label: "Copy passage with citation",
799
+ primary: true,
800
+ testId: "passage-copy",
801
+ onSelect: () => copyPassage("passage", formattedContent, getPassageDeepLink(chunkId) || void 0)
802
+ },
803
+ {
804
+ id: "copy-link",
805
+ label: "Copy passage link",
806
+ testId: "passage-copy-link",
807
+ onSelect: () => {
808
+ const link = getPassageDeepLink(chunkId);
809
+ if (link) copyPassage("link", link, link);
810
+ }
811
+ },
812
+ ...onTagPassage ? [
813
+ {
814
+ id: "label",
815
+ label: "Label this passage",
816
+ testId: "passage-label",
817
+ onSelect: () => onTagPassage(chunkId)
818
+ }
819
+ ] : [],
820
+ ...onOpenNavigator ? [
821
+ {
822
+ id: "navigator",
823
+ label: "Open in navigator",
824
+ testId: "passage-navigator",
825
+ onSelect: onOpenNavigator
826
+ }
827
+ ] : []
828
+ ] : [];
829
+ const labelItems = chunkId ? labels.flatMap((l, i) => {
830
+ const suffix = labels.length > 1 ? ` \u201C${l.name}\u201D` : " label";
831
+ return [
832
+ ...onShowLabel ? [
833
+ {
834
+ id: `show-${l.tagExtId}`,
835
+ label: `Show${suffix}`,
836
+ primary: i === 0,
837
+ testId: "label-show",
838
+ onSelect: () => onShowLabel(l.tagExtId)
839
+ }
840
+ ] : [],
841
+ ...onRemoveLabel ? [
842
+ {
843
+ id: `remove-${l.tagExtId}`,
844
+ label: `Remove${suffix}`,
845
+ destructive: true,
846
+ testId: "label-remove",
847
+ onSelect: () => onRemoveLabel(chunkId, l.tagExtId)
848
+ }
849
+ ] : []
850
+ ];
851
+ }) : [];
852
+ return /* @__PURE__ */ jsxRuntime.jsx(
853
+ chunkT74Q3MCZ_cjs.HtmlPassage,
854
+ {
855
+ chunkId,
856
+ highlight: isStrong ? "strong" : isLight ? "light" : void 0,
857
+ isHit: isHighlighted,
858
+ isSelected,
859
+ runIsStart,
860
+ runIsEnd,
861
+ isClickable: isCitationMode,
862
+ onSelect: onChunkClick && chunkId ? (extend) => onChunkClick(chunkId, extend) : void 0,
863
+ isTagged: labels.length > 0,
864
+ activeTagColor,
865
+ tagMark: labels.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
866
+ chunkLXTOOUEN_cjs.LabelMark,
867
+ {
868
+ colors: labels.map((l) => l.color),
869
+ name: `Labels: ${labels.map((l) => l.name).join(", ")}`,
870
+ menuLabel: "Label actions",
871
+ testId: `passage-tag-dots-${chunkId}`,
872
+ preview: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block font-medium", children: labels.map((l) => l.name).join(", ") }),
873
+ items: labelItems
874
+ }
875
+ ) : void 0,
876
+ runMarker: isSelected && runIsStart ? /* @__PURE__ */ jsxRuntime.jsx(
877
+ chunkLXTOOUEN_cjs.NoteMark,
878
+ {
879
+ label: runLabel,
880
+ title: "Cited by this note \u2014 click a passage to add, shift-click for a range",
881
+ testId: `note-marker-${chunkId}`
882
+ }
883
+ ) : void 0,
884
+ mark: showLabel && chunkId ? /* @__PURE__ */ jsxRuntime.jsx(
885
+ chunkLXTOOUEN_cjs.PassageMark,
886
+ {
887
+ label: runLabel,
888
+ menuLabel: "Passage actions",
889
+ testId: `passage-mark-${chunkId}`,
890
+ items: passageItems
891
+ }
892
+ ) : void 0,
893
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.MarkdownRenderer, { children: chunk.content })
894
+ }
895
+ );
896
+ });
897
+
898
+ // src/connection/viewer/parsed/citation-line.ts
899
+ function formatCitation(data) {
900
+ const { documentTitle, documentDate, pageNumber } = data;
901
+ let citation = "";
902
+ if (documentTitle) {
903
+ citation += `${documentTitle}`;
904
+ }
905
+ if (documentDate) {
906
+ citation += documentTitle ? `, ${documentDate}` : documentDate;
907
+ }
908
+ if (pageNumber) {
909
+ citation += citation ? `, p. ${pageNumber}` : `p. ${pageNumber}`;
910
+ }
911
+ return citation;
912
+ }
913
+
914
+ // src/connection/viewer/parsed/usePassageCopy.ts
915
+ function usePassageCopy({
916
+ documentId,
917
+ documentData,
918
+ selectedWorkspaceId
919
+ }) {
920
+ const { notify, runtimeConfig } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
921
+ const deploymentDomain = runtimeConfig.deploymentDomain;
922
+ const formatChunkWithCitation = React.useCallback(
923
+ (chunkContent, pageNumber, chunkExtId) => {
924
+ const docDate = documentData?.doc_metadata?.doc_date;
925
+ const citation = formatCitation({
926
+ documentTitle: documentData?.doc_metadata?.title || documentData?.file_name || "",
927
+ documentDate: docDate ? new Date(docDate).toISOString().split("T")[0] : void 0,
928
+ pageNumber
929
+ });
930
+ const deepLinkUrl = selectedWorkspaceId && documentId && chunkExtId ? chunkLJJJ6CYH_cjs.buildDeepLinkUrl(
931
+ { workspaceId: selectedWorkspaceId, documentId, chunkId: chunkExtId },
932
+ deploymentDomain
933
+ ) : "";
934
+ let result = `"${chunkContent.trim()}"`;
935
+ if (citation) {
936
+ result += `
937
+
938
+ \u2014 ${citation}`;
939
+ }
940
+ if (deepLinkUrl) {
941
+ result += `
942
+ [ARBI Docs link](${deepLinkUrl})`;
943
+ }
944
+ return result;
945
+ },
946
+ [documentData, selectedWorkspaceId, documentId, deploymentDomain]
947
+ );
948
+ const getPassageDeepLink = React.useCallback(
949
+ (chunkExtId) => {
950
+ if (!selectedWorkspaceId || !documentId || !chunkExtId) {
951
+ return "";
952
+ }
953
+ return chunkLJJJ6CYH_cjs.buildDeepLinkUrl(
954
+ { workspaceId: selectedWorkspaceId, documentId, chunkId: chunkExtId },
955
+ deploymentDomain
956
+ );
957
+ },
958
+ [selectedWorkspaceId, documentId, deploymentDomain]
959
+ );
960
+ const copyToClipboard = React.useCallback(
961
+ async (text, passageInfo) => {
962
+ try {
963
+ if (passageInfo?.href) {
964
+ const isLink = passageInfo.type === "link";
965
+ const { documentTitle, pageNumber, passageIndex, href } = passageInfo;
966
+ const pageNotation = pageNumber ? `p.${pageNumber}` : "";
967
+ const passageNotation = passageIndex !== void 0 ? `(${passageIndex})` : "";
968
+ const citation = `${documentTitle}${pageNotation ? `, ${pageNotation}${passageNotation}` : ""}`;
969
+ let html;
970
+ let plainText;
971
+ if (isLink) {
972
+ html = `<a href="${href}" target="_blank" rel="noopener noreferrer">${citation}</a>`;
973
+ plainText = href;
974
+ } else {
975
+ const linkHtml = `<p><a href="${href}" target="_blank" rel="noopener noreferrer">${citation}</a></p>`;
976
+ html = `${linkHtml}<blockquote style="margin: 8px 0; padding-left: 12px; border-left: 3px solid #ccc;">${text}</blockquote>`;
977
+ plainText = `${href}
978
+
979
+ ${text}
980
+
981
+ \u2014 ${citation}`;
982
+ }
983
+ const clipboardItem = new ClipboardItem({
984
+ "text/html": new Blob([html], { type: "text/html" }),
985
+ "text/plain": new Blob([plainText], { type: "text/plain" })
986
+ });
987
+ await navigator.clipboard.write([clipboardItem]);
988
+ const prefix = isLink ? "Link copied:" : "Passage copied:";
989
+ const notificationElement = React__default.default.createElement(
990
+ "span",
991
+ { className: "inline-flex items-center gap-2" },
992
+ prefix,
993
+ React__default.default.createElement(chunkLXTOOUEN_cjs.PassagePill, {
994
+ icon: React__default.default.createElement(react.HtmlIcon, { size: 16, className: "flex-shrink-0" }),
995
+ documentTitle: passageInfo.documentTitle,
996
+ pageNumber: passageInfo.pageNumber,
997
+ passageIndex: passageInfo.passageIndex,
998
+ href: passageInfo.href,
999
+ onClick: (e) => e.stopPropagation(),
1000
+ showTooltip: false
1001
+ })
1002
+ );
1003
+ notify(notificationElement, "success", {
1004
+ workspaceId: selectedWorkspaceId || void 0,
1005
+ // The bell entry deep-links back to the copied passage.
1006
+ href: passageInfo.href
1007
+ });
1008
+ } else {
1009
+ await navigator.clipboard.writeText(text);
1010
+ notify("Copied to clipboard", "success");
1011
+ }
1012
+ } catch (err) {
1013
+ console.error("Clipboard copy failed:", err);
1014
+ notify("Failed to copy to clipboard.", "error");
1015
+ }
1016
+ },
1017
+ [selectedWorkspaceId, notify]
1018
+ );
1019
+ return {
1020
+ formatChunkWithCitation,
1021
+ getPassageDeepLink,
1022
+ copyToClipboard
1023
+ };
1024
+ }
1025
+ function useDocumentLabels(documentId, doctags, orderedChunkIds) {
1026
+ const { data: allTags } = chunkGAYMJWTC_cjs.useConnectedTags();
1027
+ const workspaceTags = React.useMemo(() => allTags.filter(isDocumentTag), [allTags]);
1028
+ const documentDoctags = React.useMemo(() => doctags ?? [], [doctags]);
1029
+ const tagSummaries = React.useMemo(
1030
+ () => chunkT74Q3MCZ_cjs.summariseDocTags(documentDoctags, workspaceTags),
1031
+ [documentDoctags, workspaceTags]
1032
+ );
1033
+ const labelSummaries = React.useMemo(
1034
+ () => chunkT74Q3MCZ_cjs.summariseDocTags(documentDoctags, workspaceTags.filter(chunkT74Q3MCZ_cjs.isDocumentLabel)),
1035
+ [documentDoctags, workspaceTags]
1036
+ );
1037
+ const labelsByChunk = React.useMemo(() => {
1038
+ const map = /* @__PURE__ */ new Map();
1039
+ for (const s of tagSummaries) {
1040
+ const label = {
1041
+ tagExtId: s.tagExtId,
1042
+ name: s.name,
1043
+ color: ui.getEntityColor(s.tagExtId, "medium")
1044
+ };
1045
+ for (const id of s.chunkIds) {
1046
+ const list = map.get(id);
1047
+ if (list) list.push(label);
1048
+ else map.set(id, [label]);
1049
+ }
1050
+ }
1051
+ return map;
1052
+ }, [tagSummaries]);
1053
+ const { toggleChunkTag } = useChunkTagging({ documentId, documentDoctags });
1054
+ const removeLabel = React.useCallback(
1055
+ async (chunkExtId, tagExtId) => {
1056
+ const tag = workspaceTags.find((t) => t.external_id === tagExtId);
1057
+ if (!tag) return;
1058
+ try {
1059
+ await toggleChunkTag(chunkExtId, tag);
1060
+ } catch (error) {
1061
+ console.error("Failed to remove passage label", error);
1062
+ }
1063
+ },
1064
+ [workspaceTags, toggleChunkTag]
1065
+ );
1066
+ const [activeTagExtId, setActiveTagExtId] = React.useState(null);
1067
+ const [tagCursor, setTagCursor] = React.useState(0);
1068
+ const [taggingChunkId, setTaggingChunkId] = React.useState(null);
1069
+ const activeTagSummary = tagSummaries.find((t) => t.tagExtId === activeTagExtId);
1070
+ const activeTagColor = activeTagExtId ? ui.getEntityColor(activeTagExtId, "medium") : void 0;
1071
+ const activeChunkIds = React.useMemo(
1072
+ () => new Set(activeTagSummary?.chunkIds ?? []),
1073
+ [activeTagSummary]
1074
+ );
1075
+ const orderedActiveIds = React.useMemo(
1076
+ () => orderedChunkIds.filter((id) => activeChunkIds.has(id)),
1077
+ [orderedChunkIds, activeChunkIds]
1078
+ );
1079
+ const gotoTagged = React.useCallback(
1080
+ (delta) => {
1081
+ if (orderedActiveIds.length === 0) return;
1082
+ const next = (tagCursor + delta + orderedActiveIds.length) % orderedActiveIds.length;
1083
+ setTagCursor(next);
1084
+ document.getElementById(orderedActiveIds[next])?.scrollIntoView({ behavior: "smooth", block: "center" });
1085
+ },
1086
+ [tagCursor, orderedActiveIds]
1087
+ );
1088
+ const selectTag = React.useCallback((tagExtId) => {
1089
+ setActiveTagExtId(tagExtId);
1090
+ setTagCursor(0);
1091
+ }, []);
1092
+ React.useEffect(() => {
1093
+ if (!activeTagExtId || orderedActiveIds.length === 0) return;
1094
+ document.getElementById(orderedActiveIds[0])?.scrollIntoView({ behavior: "smooth", block: "center" });
1095
+ }, [activeTagExtId]);
1096
+ return {
1097
+ documentDoctags,
1098
+ labelSummaries,
1099
+ labelsByChunk,
1100
+ removeLabel,
1101
+ activeTagExtId,
1102
+ activeTagColor,
1103
+ activeChunkIds,
1104
+ tagCursor,
1105
+ gotoTagged,
1106
+ selectTag,
1107
+ taggingChunkId,
1108
+ setTaggingChunkId
1109
+ };
1110
+ }
1111
+ var NONE = [];
1112
+ var noop = () => {
1113
+ };
1114
+ function useCitationSelection({
1115
+ documentId,
1116
+ containerRef,
1117
+ processedChunks,
1118
+ orderedChunkIds,
1119
+ pageOf
1120
+ }) {
1121
+ const { passageCitation } = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
1122
+ const activeCitationContext = passageCitation?.active ?? null;
1123
+ const setPendingPassagesForCitation = passageCitation?.pick ?? noop;
1124
+ const setUnselectedPassagesForCitation = passageCitation?.unpick ?? noop;
1125
+ const viewingPassageId = react.useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
1126
+ const [selectedChunks, setSelectedChunks] = React.useState(/* @__PURE__ */ new Set());
1127
+ const selectedChunksRef = React.useRef(selectedChunks);
1128
+ selectedChunksRef.current = selectedChunks;
1129
+ const selectionAnchorRef = React.useRef(null);
1130
+ const factCitationChunkIds = passageCitation?.highlighted ?? NONE;
1131
+ const factCitationSet = React.useMemo(() => new Set(factCitationChunkIds), [factCitationChunkIds]);
1132
+ const factCitationActive = factCitationSet.size > 0;
1133
+ const factCitationSetRef = React.useRef(factCitationSet);
1134
+ factCitationSetRef.current = factCitationSet;
1135
+ const isCitationMode = !!activeCitationContext && activeCitationContext.documentId === documentId;
1136
+ const selectionRuns = React.useMemo(
1137
+ () => viewers.computeSelectionRuns(processedChunks, selectedChunks),
1138
+ [processedChunks, selectedChunks]
1139
+ );
1140
+ const runStartIds = React.useMemo(
1141
+ () => orderedChunkIds.filter((id) => selectionRuns.get(id)?.isStart),
1142
+ [orderedChunkIds, selectionRuns]
1143
+ );
1144
+ const [runCursor, setRunCursor] = React.useState(0);
1145
+ const gotoRun = React.useCallback(
1146
+ (delta) => {
1147
+ if (runStartIds.length === 0) return;
1148
+ const next = (runCursor + delta + runStartIds.length) % runStartIds.length;
1149
+ setRunCursor(next);
1150
+ document.getElementById(runStartIds[next])?.scrollIntoView({ behavior: "smooth", block: "center" });
1151
+ },
1152
+ [runCursor, runStartIds]
1153
+ );
1154
+ React.useEffect(() => {
1155
+ if (runCursor >= runStartIds.length) setRunCursor(0);
1156
+ }, [runStartIds.length, runCursor]);
1157
+ React.useEffect(() => {
1158
+ setSelectedChunks(/* @__PURE__ */ new Set());
1159
+ }, [activeCitationContext?.key, activeCitationContext?.documentId]);
1160
+ const handleSelectionEnd = React.useCallback(() => {
1161
+ if (!activeCitationContext || activeCitationContext.documentId !== documentId) return;
1162
+ const selection = window.getSelection();
1163
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) return;
1164
+ const container = containerRef.current;
1165
+ if (!container) return;
1166
+ const newSelectedChunks = /* @__PURE__ */ new Set();
1167
+ container.querySelectorAll("[data-chunk-id]").forEach((el) => {
1168
+ const chunkId = el.getAttribute("data-chunk-id");
1169
+ if (!chunkId) return;
1170
+ if (selection.containsNode(el, true)) newSelectedChunks.add(chunkId);
1171
+ });
1172
+ if (newSelectedChunks.size > 0) {
1173
+ setSelectedChunks((prev) => /* @__PURE__ */ new Set([...prev, ...newSelectedChunks]));
1174
+ setPendingPassagesForCitation(
1175
+ Array.from(newSelectedChunks).map((id) => ({ chunk_id: id, page: pageOf(id) }))
1176
+ );
1177
+ }
1178
+ selection.removeAllRanges();
1179
+ }, [activeCitationContext, documentId, containerRef, setPendingPassagesForCitation, pageOf]);
1180
+ const handleChunkClick = React.useCallback(
1181
+ (chunkId, extendFromAnchor) => {
1182
+ if (!activeCitationContext || activeCitationContext.documentId !== documentId) return;
1183
+ const anchorId = selectionAnchorRef.current;
1184
+ const anchorIdx = anchorId ? orderedChunkIds.indexOf(anchorId) : -1;
1185
+ const targetIdx = orderedChunkIds.indexOf(chunkId);
1186
+ if (extendFromAnchor && anchorIdx !== -1 && targetIdx !== -1) {
1187
+ const [from, to] = anchorIdx <= targetIdx ? [anchorIdx, targetIdx] : [targetIdx, anchorIdx];
1188
+ const range = orderedChunkIds.slice(from, to + 1);
1189
+ setSelectedChunks((prev) => /* @__PURE__ */ new Set([...prev, ...range]));
1190
+ setPendingPassagesForCitation(range.map((id) => ({ chunk_id: id, page: pageOf(id) })));
1191
+ return;
1192
+ }
1193
+ selectionAnchorRef.current = chunkId;
1194
+ const wasSelected = factCitationSetRef.current.size ? factCitationSetRef.current.has(chunkId) : selectedChunksRef.current.has(chunkId);
1195
+ setSelectedChunks((prev) => {
1196
+ const next = new Set(prev);
1197
+ if (wasSelected) next.delete(chunkId);
1198
+ else next.add(chunkId);
1199
+ return next;
1200
+ });
1201
+ if (wasSelected) setUnselectedPassagesForCitation([chunkId]);
1202
+ else setPendingPassagesForCitation([{ chunk_id: chunkId, page: pageOf(chunkId) }]);
1203
+ },
1204
+ [
1205
+ activeCitationContext,
1206
+ documentId,
1207
+ orderedChunkIds,
1208
+ setPendingPassagesForCitation,
1209
+ setUnselectedPassagesForCitation,
1210
+ pageOf
1211
+ ]
1212
+ );
1213
+ return {
1214
+ isCitationMode,
1215
+ selectedChunks,
1216
+ selectionRuns,
1217
+ runStartIds,
1218
+ runCursor,
1219
+ gotoRun,
1220
+ handleSelectionEnd,
1221
+ handleChunkClick,
1222
+ factCitationSet,
1223
+ factCitationActive,
1224
+ viewingPassageId
1225
+ };
1226
+ }
1227
+ function scrollToChunk(chunkId) {
1228
+ requestAnimationFrame(() => {
1229
+ const element = document.getElementById(chunkId);
1230
+ if (element) {
1231
+ element.scrollIntoView({ behavior: "auto", block: "center" });
1232
+ return;
1233
+ }
1234
+ setTimeout(() => {
1235
+ document.getElementById(chunkId)?.scrollIntoView({ behavior: "auto", block: "center" });
1236
+ }, 100);
1237
+ });
1238
+ }
1239
+ function usePageScrollSync({
1240
+ containerRef,
1241
+ processedChunksLength,
1242
+ scrollTrigger,
1243
+ onVisibilityUpdate
1244
+ }) {
1245
+ const session = react.useArbiSessionStore();
1246
+ const viewingId = react.useArbiSessionState((s) => s.viewingDocument?.id);
1247
+ const viewingDocumentPage = react.useArbiSessionState((s) => s.viewingDocument?.page ?? null);
1248
+ const viewingPassageId = react.useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
1249
+ const activeTab = react.useArbiSessionState((s) => s.documentViewer.tab);
1250
+ const setViewingDocumentPage = React.useCallback(
1251
+ (page) => {
1252
+ if (viewingId) session.setViewingDocument({ id: viewingId, page });
1253
+ },
1254
+ [session, viewingId]
1255
+ );
1256
+ const [highlighted, setHighlighted] = React.useState(null);
1257
+ const isChunkHighlighted = React.useCallback(
1258
+ (chunkId) => chunkId === highlighted,
1259
+ [highlighted]
1260
+ );
1261
+ const scrollCompleteRef = React.useRef(false);
1262
+ const viewingPassageIdRef = React.useRef(viewingPassageId);
1263
+ viewingPassageIdRef.current = viewingPassageId;
1264
+ React.useEffect(() => {
1265
+ if (activeTab !== "html") {
1266
+ scrollCompleteRef.current = false;
1267
+ }
1268
+ }, [activeTab]);
1269
+ React.useEffect(() => {
1270
+ if (activeTab !== "html" || processedChunksLength === 0) return;
1271
+ if (scrollCompleteRef.current) return;
1272
+ if (viewingPassageIdRef.current) {
1273
+ scrollCompleteRef.current = true;
1274
+ return;
1275
+ }
1276
+ requestAnimationFrame(() => {
1277
+ if (viewingDocumentPage) {
1278
+ const pageElement = document.getElementById(`page-${viewingDocumentPage}`);
1279
+ if (pageElement) {
1280
+ pageElement.scrollIntoView({ behavior: "auto", block: "start" });
1281
+ setTimeout(() => {
1282
+ scrollCompleteRef.current = true;
1283
+ }, 100);
1284
+ }
1285
+ } else {
1286
+ scrollCompleteRef.current = true;
1287
+ }
1288
+ });
1289
+ }, [activeTab, processedChunksLength]);
1290
+ const lastScrolledPassageRef = React.useRef(null);
1291
+ React.useEffect(() => {
1292
+ if (!viewingPassageId) {
1293
+ lastScrolledPassageRef.current = null;
1294
+ setHighlighted(null);
1295
+ }
1296
+ }, [viewingPassageId]);
1297
+ React.useEffect(() => {
1298
+ if (!viewingPassageId || activeTab !== "html" || processedChunksLength === 0) return;
1299
+ if (lastScrolledPassageRef.current === viewingPassageId) return;
1300
+ lastScrolledPassageRef.current = viewingPassageId;
1301
+ setHighlighted(viewingPassageId);
1302
+ scrollToChunk(viewingPassageId);
1303
+ }, [viewingPassageId, activeTab, processedChunksLength]);
1304
+ const viewingPageRef = React.useRef(viewingDocumentPage);
1305
+ viewingPageRef.current = viewingDocumentPage;
1306
+ React.useEffect(() => {
1307
+ const viewingDocumentPage2 = viewingPageRef.current;
1308
+ if (!scrollTrigger || processedChunksLength === 0 || !viewingDocumentPage2) return;
1309
+ scrollCompleteRef.current = false;
1310
+ requestAnimationFrame(() => {
1311
+ const pageElement = document.getElementById(`page-${viewingDocumentPage2}`);
1312
+ if (pageElement) {
1313
+ pageElement.scrollIntoView({ behavior: "smooth", block: "start" });
1314
+ }
1315
+ setTimeout(() => {
1316
+ scrollCompleteRef.current = true;
1317
+ }, 500);
1318
+ });
1319
+ }, [scrollTrigger, processedChunksLength]);
1320
+ const getPageElements = React.useCallback(
1321
+ () => Array.from(document.querySelectorAll('[id^="page-"]')),
1322
+ []
1323
+ );
1324
+ const getPageNumber = React.useCallback((element) => {
1325
+ const pageMatch = element.id.match(/page-(\d+)/);
1326
+ return pageMatch ? parseInt(pageMatch[1], 10) : 0;
1327
+ }, []);
1328
+ viewers.usePageIntersectionObserver({
1329
+ containerRef,
1330
+ scrollCompleteRef,
1331
+ isEnabled: activeTab === "html" && processedChunksLength > 0,
1332
+ getPageElements,
1333
+ getPageNumber,
1334
+ onPageChange: setViewingDocumentPage,
1335
+ onVisibilityUpdate,
1336
+ observeKey: processedChunksLength
1337
+ });
1338
+ return {
1339
+ isChunkHighlighted
1340
+ };
1341
+ }
1342
+
1343
+ // src/connection/viewer/parsed/useLazyPages.ts
1344
+ var LAZY_LOAD_BUFFER_BEFORE = 2;
1345
+ var LAZY_LOAD_BUFFER_AFTER = 5;
1346
+ var INITIAL_PAGES_TO_RENDER = 3;
1347
+ var PAGE_ASPECT_RATIO = 1.3;
1348
+ function useLazyPages({ containerRef, processedChunks, scrollTrigger }) {
1349
+ const [containerWidth, setContainerWidth] = React.useState(0);
1350
+ React.useEffect(() => {
1351
+ const el = containerRef.current;
1352
+ if (!el) return;
1353
+ const observer = new ResizeObserver((entries) => {
1354
+ setContainerWidth(entries[0]?.contentRect.width ?? 0);
1355
+ });
1356
+ observer.observe(el);
1357
+ return () => observer.disconnect();
1358
+ }, [containerRef]);
1359
+ const [renderedPages, setRenderedPages] = React.useState(
1360
+ () => new Set(Array.from({ length: INITIAL_PAGES_TO_RENDER }, (_, i) => i))
1361
+ );
1362
+ React.useEffect(() => {
1363
+ if (processedChunks.length === 0) return;
1364
+ const renderAll = () => {
1365
+ setRenderedPages((prev) => {
1366
+ if (prev.size === processedChunks.length) return prev;
1367
+ return new Set(Array.from({ length: processedChunks.length }, (_, i) => i));
1368
+ });
1369
+ };
1370
+ if (typeof window.requestIdleCallback !== "function") {
1371
+ const timer = setTimeout(renderAll, 200);
1372
+ return () => clearTimeout(timer);
1373
+ }
1374
+ const id = window.requestIdleCallback(renderAll);
1375
+ return () => window.cancelIdleCallback(id);
1376
+ }, [processedChunks.length]);
1377
+ const handleVisibilityUpdate = React.useCallback(
1378
+ (visibilityMap) => {
1379
+ const visiblePageNumbers = Array.from(visibilityMap.entries()).filter(([, ratio]) => ratio > 0).map(([pageNum]) => pageNum);
1380
+ if (visiblePageNumbers.length === 0) return;
1381
+ const visibleIndices = [];
1382
+ processedChunks.forEach((page, index) => {
1383
+ if (page.pageNumber !== null && visiblePageNumbers.includes(page.pageNumber)) {
1384
+ visibleIndices.push(index);
1385
+ }
1386
+ });
1387
+ if (visibleIndices.length === 0) return;
1388
+ const minIndex = Math.min(...visibleIndices);
1389
+ const maxIndex = Math.max(...visibleIndices);
1390
+ const pagesToRender = /* @__PURE__ */ new Set();
1391
+ for (let i = Math.max(0, minIndex - LAZY_LOAD_BUFFER_BEFORE); i <= Math.min(processedChunks.length - 1, maxIndex + LAZY_LOAD_BUFFER_AFTER); i++) {
1392
+ pagesToRender.add(i);
1393
+ }
1394
+ setRenderedPages((prev) => {
1395
+ for (const i of pagesToRender) if (!prev.has(i)) return /* @__PURE__ */ new Set([...prev, ...pagesToRender]);
1396
+ return prev;
1397
+ });
1398
+ },
1399
+ [processedChunks]
1400
+ );
1401
+ const viewingDocumentPage = react.useArbiSessionState((s) => s.viewingDocument?.page ?? null);
1402
+ const viewingPassageId = react.useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
1403
+ const activeTab = react.useArbiSessionState((s) => s.documentViewer.tab);
1404
+ React.useEffect(() => {
1405
+ if (!viewingDocumentPage || processedChunks.length === 0) return;
1406
+ if (!viewingPassageId && activeTab !== "html") return;
1407
+ const targetIndex = processedChunks.findIndex((p) => p.pageNumber === viewingDocumentPage);
1408
+ if (targetIndex === -1) return;
1409
+ setRenderedPages((prev) => {
1410
+ if (prev.has(targetIndex)) return prev;
1411
+ const next = new Set(prev);
1412
+ for (let i = Math.max(0, targetIndex - LAZY_LOAD_BUFFER_BEFORE); i <= Math.min(processedChunks.length - 1, targetIndex + LAZY_LOAD_BUFFER_AFTER); i++) {
1413
+ next.add(i);
1414
+ }
1415
+ return next;
1416
+ });
1417
+ }, [viewingPassageId, viewingDocumentPage, processedChunks, activeTab]);
1418
+ const tabSwitchScrolledRef = React.useRef(false);
1419
+ const passageScrolledRef = React.useRef(null);
1420
+ React.useEffect(() => {
1421
+ if (activeTab !== "html") tabSwitchScrolledRef.current = false;
1422
+ }, [activeTab]);
1423
+ React.useEffect(() => {
1424
+ if (!viewingPassageId) passageScrolledRef.current = null;
1425
+ }, [viewingPassageId]);
1426
+ React.useEffect(() => {
1427
+ if (activeTab !== "html" || !viewingDocumentPage) return;
1428
+ if (viewingPassageId && passageScrolledRef.current !== viewingPassageId) {
1429
+ const target = viewingPassageId;
1430
+ const deadline = performance.now() + 3e3;
1431
+ let raf = 0;
1432
+ const tick = () => {
1433
+ const el = document.getElementById(target);
1434
+ if (el) {
1435
+ passageScrolledRef.current = target;
1436
+ tabSwitchScrolledRef.current = true;
1437
+ el.scrollIntoView({ behavior: "auto", block: "center" });
1438
+ raf = requestAnimationFrame(
1439
+ () => el.scrollIntoView({ behavior: "auto", block: "center" })
1440
+ );
1441
+ return;
1442
+ }
1443
+ if (performance.now() < deadline) raf = requestAnimationFrame(tick);
1444
+ };
1445
+ raf = requestAnimationFrame(tick);
1446
+ return () => cancelAnimationFrame(raf);
1447
+ }
1448
+ if (tabSwitchScrolledRef.current) return;
1449
+ const pageElement = document.getElementById(`page-${viewingDocumentPage}`);
1450
+ if (!pageElement) return;
1451
+ tabSwitchScrolledRef.current = true;
1452
+ requestAnimationFrame(() => {
1453
+ pageElement.scrollIntoView({ behavior: "auto", block: "start" });
1454
+ });
1455
+ }, [renderedPages, activeTab, viewingDocumentPage, viewingPassageId]);
1456
+ const { isChunkHighlighted } = usePageScrollSync({
1457
+ containerRef,
1458
+ processedChunksLength: processedChunks.length,
1459
+ scrollTrigger,
1460
+ onVisibilityUpdate: handleVisibilityUpdate
1461
+ });
1462
+ return {
1463
+ renderedPages,
1464
+ isChunkHighlighted,
1465
+ placeholderHeight: containerWidth ? containerWidth * PAGE_ASPECT_RATIO : 500
1466
+ };
1467
+ }
1468
+ var EMPTY_LABELS = [];
1469
+ function ParsedTextView({
1470
+ documentId,
1471
+ stage = "final",
1472
+ onLoadSuccess,
1473
+ scrollTrigger,
1474
+ zoom = 1,
1475
+ onZoomChange
1476
+ }) {
1477
+ const { workspaceId } = chunkGFNELPDP_cjs.useConnectedWorkspace();
1478
+ const { openInNavigator } = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
1479
+ const containerRef = React.useRef(null);
1480
+ const { data: documentRecord } = react.useDocument(artifacts.parseVersionRef(documentId).docId, {
1481
+ enabled: !!documentId && !!workspaceId
1482
+ });
1483
+ const documentData = documentRecord ?? void 0;
1484
+ const { data: parsedDoc, isLoading, error } = react.useParsedDocument(documentId, stage);
1485
+ const { processedChunks, maxPageNumber } = viewers.useProcessedChunks(
1486
+ parsedDoc?.chunks,
1487
+ parsedDoc?.footnotes || {}
1488
+ );
1489
+ const pageByChunk = React.useMemo(() => {
1490
+ const map = /* @__PURE__ */ new Map();
1491
+ for (const page of processedChunks) {
1492
+ for (const chunk of page.chunks) {
1493
+ if (chunk.chunkExtId) map.set(chunk.chunkExtId, page.pageNumber ?? void 0);
1494
+ }
1495
+ }
1496
+ return map;
1497
+ }, [processedChunks]);
1498
+ const pageOf = React.useCallback((id) => pageByChunk.get(id), [pageByChunk]);
1499
+ const orderedChunkIds = React.useMemo(
1500
+ () => processedChunks.flatMap(
1501
+ (page) => page.chunks.map((c) => c.chunkExtId).filter((id) => !!id)
1502
+ ),
1503
+ [processedChunks]
1504
+ );
1505
+ const totalPages = React.useMemo(
1506
+ () => processedChunks.filter((p) => p.pageNumber !== null).length,
1507
+ [processedChunks]
1508
+ );
1509
+ const labels = useDocumentLabels(documentId, documentData?.doctags, orderedChunkIds);
1510
+ const citation = useCitationSelection({
1511
+ documentId,
1512
+ containerRef,
1513
+ processedChunks,
1514
+ orderedChunkIds,
1515
+ pageOf
1516
+ });
1517
+ const { renderedPages, isChunkHighlighted, placeholderHeight } = useLazyPages({
1518
+ containerRef,
1519
+ processedChunks,
1520
+ scrollTrigger
1521
+ });
1522
+ viewers.useScrollAnchor(containerRef, processedChunks.length);
1523
+ viewers.usePinchZoom({ containerRef, zoom, onZoomChange });
1524
+ const { formatChunkWithCitation, getPassageDeepLink, copyToClipboard } = usePassageCopy({
1525
+ documentId,
1526
+ documentData,
1527
+ selectedWorkspaceId: workspaceId
1528
+ });
1529
+ const handleOpenNavigator = React.useMemo(
1530
+ () => openInNavigator ? () => openInNavigator(documentId) : void 0,
1531
+ [openInNavigator, documentId]
1532
+ );
1533
+ React.useEffect(() => {
1534
+ if (maxPageNumber > 0 && onLoadSuccess) {
1535
+ try {
1536
+ onLoadSuccess(maxPageNumber);
1537
+ } catch (err) {
1538
+ console.error("Error in onLoadSuccess callback:", err);
1539
+ }
1540
+ }
1541
+ }, [maxPageNumber, onLoadSuccess]);
1542
+ if (isLoading) return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading parsed document..." });
1543
+ if (error) {
1544
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-text", children: "Failed to load parsed document" }) });
1545
+ }
1546
+ const taggingChunk = labels.taggingChunkId ? processedChunks.flatMap((page) => page.chunks).find((c) => c.chunkExtId === labels.taggingChunkId) : void 0;
1547
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkT74Q3MCZ_cjs.HtmlViewerRoot, { children: [
1548
+ /* @__PURE__ */ jsxRuntime.jsx(
1549
+ chunkT74Q3MCZ_cjs.DocumentLabelBar,
1550
+ {
1551
+ summaries: labels.labelSummaries,
1552
+ activeTagExtId: labels.activeTagExtId,
1553
+ cursor: labels.tagCursor,
1554
+ onSelect: labels.selectTag,
1555
+ onStep: labels.gotoTagged
1556
+ }
1557
+ ),
1558
+ labels.taggingChunkId && /* @__PURE__ */ jsxRuntime.jsx(
1559
+ PassageTagPanel,
1560
+ {
1561
+ documentId,
1562
+ chunkExtId: labels.taggingChunkId,
1563
+ chunkContent: taggingChunk?.content ?? "",
1564
+ pageNumber: pageOf(labels.taggingChunkId),
1565
+ documentDoctags: labels.documentDoctags,
1566
+ onClose: () => labels.setTaggingChunkId(null),
1567
+ onViewTaggedChunks: (tagExtId) => {
1568
+ labels.selectTag(tagExtId);
1569
+ labels.setTaggingChunkId(null);
1570
+ }
1571
+ }
1572
+ ),
1573
+ !citation.factCitationActive && citation.runStartIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1574
+ chunkT74Q3MCZ_cjs.CitedRunNav,
1575
+ {
1576
+ position: citation.runCursor + 1,
1577
+ total: citation.runStartIds.length,
1578
+ onStep: citation.gotoRun
1579
+ }
1580
+ ),
1581
+ /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.HtmlViewerSurface, { surfaceRef: containerRef, onMouseUp: citation.handleSelectionEnd, children: processedChunks.length > 0 ? processedChunks.map((page, pageIndex) => /* @__PURE__ */ jsxRuntime.jsx(
1582
+ chunkT74Q3MCZ_cjs.HtmlPage,
1583
+ {
1584
+ pageNumber: page.pageNumber,
1585
+ totalPages,
1586
+ isRendered: renderedPages.has(pageIndex),
1587
+ placeholderHeight,
1588
+ zoom,
1589
+ children: page.chunks.map((chunk, chunkIndex) => {
1590
+ const id = chunk.chunkExtId;
1591
+ const run = id ? citation.selectionRuns.get(id) : void 0;
1592
+ return /* @__PURE__ */ jsxRuntime.jsx(
1593
+ ParsedPassage,
1594
+ {
1595
+ chunk,
1596
+ pageNumber: page.pageNumber,
1597
+ isHighlighted: !!(id && isChunkHighlighted(id)),
1598
+ isSelected: !!(id && citation.selectedChunks.has(id)),
1599
+ isCitationHighlight: !!(id && citation.factCitationSet.has(id)),
1600
+ isActiveCitation: !!(id && citation.factCitationActive && citation.viewingPassageId === id && // Only while it is STILL cited: clicking it off must clear it.
1601
+ citation.factCitationSet.has(id)),
1602
+ factCitationActive: citation.factCitationActive,
1603
+ isCitationMode: citation.isCitationMode,
1604
+ runIsStart: !!run?.isStart,
1605
+ runIsEnd: !!run?.isEnd,
1606
+ runEndIndex: run?.endIndex,
1607
+ onChunkClick: citation.isCitationMode ? citation.handleChunkClick : void 0,
1608
+ formatChunkWithCitation,
1609
+ getPassageDeepLink,
1610
+ copyToClipboard,
1611
+ onOpenNavigator: handleOpenNavigator,
1612
+ labels: id ? labels.labelsByChunk.get(id) ?? EMPTY_LABELS : EMPTY_LABELS,
1613
+ activeTagColor: id && labels.activeChunkIds.has(id) ? labels.activeTagColor : void 0,
1614
+ onTagPassage: labels.setTaggingChunkId,
1615
+ onShowLabel: labels.selectTag,
1616
+ onRemoveLabel: labels.removeLabel
1617
+ },
1618
+ chunkIndex
1619
+ );
1620
+ })
1621
+ },
1622
+ pageIndex
1623
+ )) : /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.HtmlViewerEmpty, {}) })
1624
+ ] });
1625
+ }
1626
+ var AnnotatedPdfViewer = React.lazy(
502
1627
  () => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.AnnotatedPdfViewer }))
503
1628
  );
504
- var SignaturePlacementViewer = react.lazy(
1629
+ var SignaturePlacementViewer = React.lazy(
505
1630
  () => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.SignaturePlacementViewer }))
506
1631
  );
507
- var SignatureRequestEditor = react.lazy(
1632
+ var SignatureRequestEditor = React.lazy(
508
1633
  () => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.SignatureRequestEditor }))
509
1634
  );
510
- var GuidedSigningViewer = react.lazy(
1635
+ var GuidedSigningViewer = React.lazy(
511
1636
  () => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.GuidedSigningViewer }))
512
1637
  );
513
1638
  function SessionPdfViewer(props) {
514
- const session = react$1.useArbiSessionStore();
515
- const viewingId = react$1.useArbiSessionState((s) => s.viewingDocument?.id);
516
- const { isDetached } = chunkKLPRAQCE_cjs.useDocumentViewerSupport();
517
- const onPageChange = react.useCallback(
1639
+ const session = react.useArbiSessionStore();
1640
+ const viewingId = react.useArbiSessionState((s) => s.viewingDocument?.id);
1641
+ const { isDetached } = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
1642
+ const onPageChange = React.useCallback(
518
1643
  (page) => {
519
1644
  if (viewingId) session.setViewingDocument({ id: viewingId, page });
520
1645
  },
@@ -544,7 +1669,7 @@ function ViewerPdfPane({
544
1669
  const showMarkup = markup.hasMarkup && !markup.showOriginal;
545
1670
  if (isDownloadOnly) {
546
1671
  return /* @__PURE__ */ jsxRuntime.jsx(
547
- chunkV4YZXGXR_cjs.ViewerPreviewUnavailable,
1672
+ chunkT74Q3MCZ_cjs.ViewerPreviewUnavailable,
548
1673
  {
549
1674
  extension: fileExtension(documentData?.file_name),
550
1675
  onDownload
@@ -554,26 +1679,26 @@ function ViewerPdfPane({
554
1679
  const loadingLabel = isVideo ? "Loading video..." : isAudio ? "Loading audio..." : isImage ? "Loading image..." : !documentData ? "Loading document..." : ui.friendlyFileType(documentData.file_type, documentData.file_name) === "Text" ? "Loading text..." : "Loading PDF...";
555
1680
  const errorLabel = isVideo ? "Failed to load video" : isAudio ? "Failed to load audio" : isImage ? "Failed to load image" : "Failed to load PDF";
556
1681
  if (isDocx && documentData && !["completed", "low-content", "failed"].includes(documentData.status || "")) {
557
- return /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "PDF and search indexing are processing. Open the DOCX tab to edit now." });
1682
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "PDF and search indexing are processing. Open the DOCX tab to edit now." });
558
1683
  }
559
- if (isPdfLoading) return /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: loadingLabel });
1684
+ if (isPdfLoading) return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: loadingLabel });
560
1685
  if (pdfError) {
561
1686
  return /* @__PURE__ */ jsxRuntime.jsx(
562
- chunkV4YZXGXR_cjs.ViewerLoadError,
1687
+ chunkT74Q3MCZ_cjs.ViewerLoadError,
563
1688
  {
564
1689
  message: isVideo || isAudio || isImage ? `${errorLabel} \u2014 download it instead.` : "Couldn't display the PDF \u2014 download it instead.",
565
1690
  onDownload
566
1691
  }
567
1692
  );
568
1693
  }
569
- if (!pdfBlob) return /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: loadingLabel });
1694
+ if (!pdfBlob) return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: loadingLabel });
570
1695
  if (isVideo) return /* @__PURE__ */ jsxRuntime.jsx(viewers.VideoViewer, { blob: pdfBlob, title: documentData?.file_name || "Video" });
571
1696
  if (isAudio) return /* @__PURE__ */ jsxRuntime.jsx(viewers.AudioViewer, { blob: pdfBlob, title: documentData?.file_name || "Audio" });
572
1697
  if (isImage) {
573
1698
  return /* @__PURE__ */ jsxRuntime.jsx(viewers.ImageViewer, { blob: pdfBlob, alt: documentData?.file_name || "Document image" });
574
1699
  }
575
1700
  if (signatureFlow?.kind === "prepare") {
576
- return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
1701
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
577
1702
  SignatureRequestEditor,
578
1703
  {
579
1704
  ...viewerProps,
@@ -589,7 +1714,7 @@ function ViewerPdfPane({
589
1714
  }
590
1715
  if (signatureFlow?.kind === "sign" && currentUserId) {
591
1716
  const { currentPage: _page, scrollTrigger: _trigger, ...guidedProps } = viewerProps;
592
- return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
1717
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
593
1718
  GuidedSigningViewer,
594
1719
  {
595
1720
  ...guidedProps,
@@ -603,7 +1728,7 @@ function ViewerPdfPane({
603
1728
  ) });
604
1729
  }
605
1730
  if (placingSignature) {
606
- return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
1731
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
607
1732
  SignaturePlacementViewer,
608
1733
  {
609
1734
  ...viewerProps,
@@ -617,9 +1742,9 @@ function ViewerPdfPane({
617
1742
  }
618
1743
  if (annotating || showMarkup) {
619
1744
  return /* @__PURE__ */ jsxRuntime.jsx(
620
- react.Suspense,
1745
+ React.Suspense,
621
1746
  {
622
- fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: annotating ? "Loading annotation tools\u2026" : "Loading markup\u2026" }),
1747
+ fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: annotating ? "Loading annotation tools\u2026" : "Loading markup\u2026" }),
623
1748
  children: /* @__PURE__ */ jsxRuntime.jsx(
624
1749
  AnnotatedPdfViewer,
625
1750
  {
@@ -642,18 +1767,18 @@ function ViewerPdfPane({
642
1767
  }
643
1768
  return /* @__PURE__ */ jsxRuntime.jsx(SessionPdfViewer, { ...viewerProps, file: pdfBlob });
644
1769
  }
645
- var NativeDocxEditor = react.lazy(
646
- () => import('../ConnectedNativeDocxEditor-OUWFMIPH.cjs').then((m) => ({
1770
+ var NativeDocxEditor = React.lazy(
1771
+ () => import('../ConnectedNativeDocxEditor-HTEW5JAH.cjs').then((m) => ({
647
1772
  default: m.ConnectedNativeDocxEditor
648
1773
  }))
649
1774
  );
650
- var StreamedWordArtifact = react.lazy(
651
- () => import('../ConnectedStreamedWordArtifact-D5LSMDO4.cjs').then((m) => ({
1775
+ var StreamedWordArtifact = React.lazy(
1776
+ () => import('../ConnectedStreamedWordArtifact-QW74LKHN.cjs').then((m) => ({
652
1777
  default: m.ConnectedStreamedWordArtifact
653
1778
  }))
654
1779
  );
655
- var NativeDocxComparison = react.lazy(
656
- () => import('../ConnectedNativeDocxComparison-3XQSINPQ.cjs').then((m) => ({
1780
+ var NativeDocxComparison = React.lazy(
1781
+ () => import('../ConnectedNativeDocxComparison-Y5BNLNH6.cjs').then((m) => ({
657
1782
  default: m.ConnectedNativeDocxComparison
658
1783
  }))
659
1784
  );
@@ -663,7 +1788,7 @@ function canChangeVisibility(doc, userId) {
663
1788
  return userId.startsWith("agt-") || (doc.created_by_ext_id?.startsWith("agt-") ?? false) || doc.created_by_ext_id === userId;
664
1789
  }
665
1790
  function ConnectedDocumentViewer(props) {
666
- const viewing = react$1.useArbiSessionState((s) => s.viewingDocument?.id);
1791
+ const viewing = react.useArbiSessionState((s) => s.viewingDocument?.id);
667
1792
  const openedId = props.documentId ?? viewing;
668
1793
  if (!openedId) return null;
669
1794
  return /* @__PURE__ */ jsxRuntime.jsx(ConnectedDocumentToolsProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentViewerContent, { ...props, openedId }) });
@@ -673,24 +1798,24 @@ function DocumentViewerContent({
673
1798
  headerActions,
674
1799
  artifactRuntimeUrl = "/artifact-runtime/"
675
1800
  }) {
676
- const arbi = react$1.useArbi();
677
- const session = react$1.useArbiSessionStore();
678
- const support = chunkKLPRAQCE_cjs.useDocumentViewerSupport();
1801
+ const arbi = react.useArbi();
1802
+ const session = react.useArbiSessionStore();
1803
+ const support = chunk6I6CVX5G_cjs.useDocumentViewerSupport();
679
1804
  const formatDate = support.formatDate ?? chunkKDG6FER6_cjs.fmtDate;
680
1805
  const tools = documentTools.useDocumentTools();
681
1806
  const { openConversation, notify } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
682
1807
  const { userId: currentUserId } = chunkGFNELPDP_cjs.useConnectedWorkspace();
683
1808
  const documentId = artifacts.parseVersionRef(openedId).docId;
684
- const [totalPages, setTotalPages] = react.useState(0);
685
- const [isCompact, setIsCompact] = react.useState(false);
686
- const [pdfZoom, setPdfZoom] = react.useState(1);
1809
+ const [totalPages, setTotalPages] = React.useState(0);
1810
+ const [isCompact, setIsCompact] = React.useState(false);
1811
+ const [pdfZoom, setPdfZoom] = React.useState(1);
687
1812
  const {
688
1813
  tab: zoomTab,
689
1814
  textScale,
690
1815
  compareId: compareDocumentId
691
- } = react$1.useArbiSessionState((s) => s.documentViewer);
1816
+ } = react.useArbiSessionState((s) => s.documentViewer);
692
1817
  const zoom = zoomTab === "html" ? textScale : pdfZoom;
693
- const setZoom = react.useCallback(
1818
+ const setZoom = React.useCallback(
694
1819
  (next) => {
695
1820
  const value = typeof next === "function" ? next(zoom) : next;
696
1821
  if (zoomTab === "html") session.setDocumentViewer({ textScale: value });
@@ -698,9 +1823,9 @@ function DocumentViewerContent({
698
1823
  },
699
1824
  [zoomTab, session, zoom]
700
1825
  );
701
- const [scrollTrigger, setScrollTrigger] = react.useState(0);
702
- const containerRef = react.useRef(null);
703
- const viewingDocumentPage = react$1.useArbiSessionState((s) => s.viewingDocument?.page ?? null);
1826
+ const [scrollTrigger, setScrollTrigger] = React.useState(0);
1827
+ const containerRef = React.useRef(null);
1828
+ const viewingDocumentPage = react.useArbiSessionState((s) => s.viewingDocument?.page ?? null);
704
1829
  const setViewingDocumentPage = (page) => session.setViewingDocument({ id: openedId, page });
705
1830
  const setViewingDocumentId = (id) => session.setViewingDocument({ id });
706
1831
  const setActiveTab = (tab) => session.setDocumentViewer({ tab });
@@ -744,17 +1869,17 @@ function DocumentViewerContent({
744
1869
  const shownDocumentId = pdfSnapshotId || documentId;
745
1870
  const blobs = useViewerBlobs(shownDocumentId, doc);
746
1871
  const { pdfBlob, xlsxBlob, xlsxError, handleDirectDownload } = blobs;
747
- const [annotating, setAnnotating] = react.useState(false);
748
- react.useEffect(() => setAnnotating(false), [documentId]);
1872
+ const [annotating, setAnnotating] = React.useState(false);
1873
+ React.useEffect(() => setAnnotating(false), [documentId]);
749
1874
  const hasHistory = versions.length > 1 || (documentData?.current_version ?? 1) > 1 || translations.length > 0;
750
1875
  const { activeTab, handleTabChange, viewerTabs } = useViewerTabs(doc, isCompact, hasHistory);
751
1876
  const crop = useImageCrop(documentId, documentData?.file_name, pdfBlob);
752
- const [placingSignature, setPlacingSignature] = react.useState(false);
753
- const [signAppearance, setSignAppearance] = react.useState();
754
- const [isSignOpen, setIsSignOpen] = react.useState(false);
755
- react.useEffect(() => setPlacingSignature(false), [documentId, snapshotDocumentId]);
756
- const [signatureFlow, setSignatureFlow] = react.useState(null);
757
- react.useEffect(() => setSignatureFlow(null), [documentId, snapshotDocumentId]);
1877
+ const [placingSignature, setPlacingSignature] = React.useState(false);
1878
+ const [signAppearance, setSignAppearance] = React.useState();
1879
+ const [isSignOpen, setIsSignOpen] = React.useState(false);
1880
+ React.useEffect(() => setPlacingSignature(false), [documentId, snapshotDocumentId]);
1881
+ const [signatureFlow, setSignatureFlow] = React.useState(null);
1882
+ React.useEffect(() => setSignatureFlow(null), [documentId, snapshotDocumentId]);
758
1883
  const { data: signatureStatus } = documentTools.useDocumentSignatures(shownDocumentId, !isDraft && !liveKind);
759
1884
  const isCoEditing = !snapshotDocumentId && !compareDocumentId && !isDraft && (activeTab === "docx" && isDocx || activeTab === "edit" && isArtifact && !liveKind && !isStreaming);
760
1885
  const currentVersionLabel = isCoEditing ? void 0 : !snapshotDocumentId && !compareDocumentId && (isDocx || isArtifact && !liveKind) ? "Live" : artifacts.versionLabel(versions, snapshotDocumentId || documentId);
@@ -763,7 +1888,7 @@ function DocumentViewerContent({
763
1888
  const pdfSnapshotNumber = pdfSnapshotId ? snapshotNumber : void 0;
764
1889
  const isSigned = !!signatureStatus?.signed;
765
1890
  const markup = documentTools.useDocumentMarkup(documentData, pdfSnapshotNumber, isSigned);
766
- react.useEffect(() => {
1891
+ React.useEffect(() => {
767
1892
  const container = containerRef.current;
768
1893
  if (!container) return;
769
1894
  const resizeObserver = new ResizeObserver((entries) => {
@@ -772,7 +1897,7 @@ function DocumentViewerContent({
772
1897
  resizeObserver.observe(container);
773
1898
  return () => resizeObserver.disconnect();
774
1899
  }, []);
775
- const handleLoadSuccess = react.useCallback((numPages) => setTotalPages(numPages), []);
1900
+ const handleLoadSuccess = React.useCallback((numPages) => setTotalPages(numPages), []);
776
1901
  const goToPage = (page) => {
777
1902
  setViewingDocumentPage(page);
778
1903
  setScrollTrigger((prev) => prev + 1);
@@ -783,15 +1908,15 @@ function DocumentViewerContent({
783
1908
  };
784
1909
  const documentTitle = streamingDoc?.title || draftDoc?.title || documentData?.doc_metadata?.title || documentData?.file_name || "Document";
785
1910
  const pageNav = totalPages > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
786
- /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerZoomControl, { zoom, onCycle: () => setZoom(viewers.cycleZoom(zoom)) }),
1911
+ /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerZoomControl, { zoom, onCycle: () => setZoom(viewers.cycleZoom(zoom)) }),
787
1912
  /* @__PURE__ */ jsxRuntime.jsx(
788
- chunkV4YZXGXR_cjs.PdfPageNav,
1913
+ chunkT74Q3MCZ_cjs.PdfPageNav,
789
1914
  {
790
1915
  canPrev: (viewingDocumentPage || 1) > 1,
791
1916
  canNext: (viewingDocumentPage || 1) < totalPages,
792
1917
  onPrev: () => stepPage(-1),
793
1918
  onNext: () => stepPage(1),
794
- counter: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerPageCounter, { page: viewingDocumentPage || 1, total: totalPages, onGoTo: goToPage })
1919
+ counter: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerPageCounter, { page: viewingDocumentPage || 1, total: totalPages, onGoTo: goToPage })
795
1920
  }
796
1921
  )
797
1922
  ] });
@@ -815,7 +1940,7 @@ function DocumentViewerContent({
815
1940
  );
816
1941
  const titleBlock = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
817
1942
  isDraft ? support.renderDraftTitle?.(documentId) : /* @__PURE__ */ jsxRuntime.jsx(
818
- chunkV4YZXGXR_cjs.ViewerTitle,
1943
+ chunkT74Q3MCZ_cjs.ViewerTitle,
819
1944
  {
820
1945
  title: documentTitle,
821
1946
  versionLabel: currentVersionLabel,
@@ -840,7 +1965,7 @@ function DocumentViewerContent({
840
1965
  // A draft's kind replaces the tabs: neither Versions nor the text view means anything
841
1966
  // before the first save.
842
1967
  support.renderDraftKind?.(documentId)
843
- ) : /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerTabBar, { tabs: viewerTabs, activeId: activeTab, onChange: handleTabChange }),
1968
+ ) : /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerTabBar, { tabs: viewerTabs, activeId: activeTab, onChange: handleTabChange }),
844
1969
  !isCompact && titleBlock
845
1970
  ] });
846
1971
  const annotatable = documentTools.canAnnotate({
@@ -913,7 +2038,7 @@ function DocumentViewerContent({
913
2038
  }
914
2039
  ),
915
2040
  activeTab === "pdf" && isImage && pdfBlob && /* @__PURE__ */ jsxRuntime.jsx(
916
- chunkV4YZXGXR_cjs.ViewerImageActions,
2041
+ chunkT74Q3MCZ_cjs.ViewerImageActions,
917
2042
  {
918
2043
  compact: isCompact,
919
2044
  onUseAsReference: support.useImageAsReference ? () => support.useImageAsReference(documentId) : void 0,
@@ -1041,7 +2166,7 @@ function DocumentViewerContent({
1041
2166
  onZoomChange: setZoom
1042
2167
  };
1043
2168
  return /* @__PURE__ */ jsxRuntime.jsxs(
1044
- chunkV4YZXGXR_cjs.ViewerFrame,
2169
+ chunkT74Q3MCZ_cjs.ViewerFrame,
1045
2170
  {
1046
2171
  frameRef: containerRef,
1047
2172
  contentId: documentId,
@@ -1072,13 +2197,13 @@ function DocumentViewerContent({
1072
2197
  footer: (
1073
2198
  // Crop to a new document. Full resolution (no maxSize): a crop frames, it never downscales.
1074
2199
  /* @__PURE__ */ jsxRuntime.jsx(
1075
- react$1.ImageCropModal,
2200
+ react.ImageCropModal,
1076
2201
  {
1077
2202
  open: crop.cropImageUrl !== null,
1078
2203
  image: crop.cropImageUrl,
1079
2204
  title: "Crop image",
1080
2205
  saveLabel: "Save as a copy",
1081
- aspectOptions: react$1.DEFAULT_ASPECT_OPTIONS,
2206
+ aspectOptions: react.DEFAULT_ASPECT_OPTIONS,
1082
2207
  output: { mimeType: "image/png" },
1083
2208
  onComplete: crop.handleCropComplete,
1084
2209
  onCancel: crop.closeCrop
@@ -1086,7 +2211,7 @@ function DocumentViewerContent({
1086
2211
  )
1087
2212
  ),
1088
2213
  children: [
1089
- isComparing && /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading comparison\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
2214
+ isComparing && /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading comparison\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
1090
2215
  NativeDocxComparison,
1091
2216
  {
1092
2217
  baseId: compareDocumentId,
@@ -1096,7 +2221,7 @@ function DocumentViewerContent({
1096
2221
  ) }),
1097
2222
  isCaptureDraft && support.renderCaptureDraft?.(documentId),
1098
2223
  !isCaptureDraft && (activeTab === "pdf" || isMedia && activeTab === "html") && !isArtifact && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(chunkUWIILWDI_cjs.ViewerPane, { hidden: activeTab !== "pdf", children: [
1099
- /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.DocumentLabelBar, { summaries: labelSummaries }),
2224
+ /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.DocumentLabelBar, { summaries: labelSummaries }),
1100
2225
  !isMedia && !isImage && signatureBanner,
1101
2226
  activeTab === "pdf" && !isMedia && !isImage && /* @__PURE__ */ jsxRuntime.jsx(
1102
2227
  chunkD3WFIFRY_cjs.MarkupNotices,
@@ -1106,7 +2231,7 @@ function DocumentViewerContent({
1106
2231
  onOpenVersion: (n) => setSnapshotDocumentId(`${documentId}@v${n}`)
1107
2232
  }
1108
2233
  ),
1109
- /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerControlBar, { controls: activeTab === "pdf" && pageNav, children: /* @__PURE__ */ jsxRuntime.jsx(
2234
+ /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerControlBar, { controls: activeTab === "pdf" && pageNav, children: /* @__PURE__ */ jsxRuntime.jsx(
1110
2235
  ViewerPdfPane,
1111
2236
  {
1112
2237
  documentId,
@@ -1144,7 +2269,7 @@ function DocumentViewerContent({
1144
2269
  }
1145
2270
  ),
1146
2271
  activeTab === "edit" && isArtifact && liveKind && /* @__PURE__ */ jsxRuntime.jsx(chunk2YV7FBLO_cjs.ArtifactCodeView, { source: liveSource, fileName: documentData?.file_name ?? void 0 }),
1147
- activeTab === "edit" && isArtifact && !liveKind && !isStreaming && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading editor\u2026" }), children: [
2272
+ activeTab === "edit" && isArtifact && !liveKind && !isStreaming && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading editor\u2026" }), children: [
1148
2273
  isSigned && !snapshotDocumentId && /* @__PURE__ */ jsxRuntime.jsx(chunkD3WFIFRY_cjs.SignedEditNote, {}),
1149
2274
  /* @__PURE__ */ jsxRuntime.jsx(
1150
2275
  NativeDocxEditor,
@@ -1187,8 +2312,8 @@ function DocumentViewerContent({
1187
2312
  onOpenTranslation: (id) => setViewingDocumentId(id)
1188
2313
  }
1189
2314
  ),
1190
- activeTab === "xlsx" && isXlsx && (xlsxBlob ? /* @__PURE__ */ jsxRuntime.jsx(viewers.XlsxViewer, { blob: xlsxBlob }) : /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: xlsxError ? "Failed to load spreadsheet" : "Loading spreadsheet..." })),
1191
- activeTab === "docx" && isDocx && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Loading editor\u2026" }), children: [
2315
+ activeTab === "xlsx" && isXlsx && (xlsxBlob ? /* @__PURE__ */ jsxRuntime.jsx(viewers.XlsxViewer, { blob: xlsxBlob }) : /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: xlsxError ? "Failed to load spreadsheet" : "Loading spreadsheet..." })),
2316
+ activeTab === "docx" && isDocx && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Loading editor\u2026" }), children: [
1192
2317
  signatureBanner,
1193
2318
  isSigned && !snapshotDocumentId && /* @__PURE__ */ jsxRuntime.jsx(chunkD3WFIFRY_cjs.SignedEditNote, {}),
1194
2319
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1201,7 +2326,7 @@ function DocumentViewerContent({
1201
2326
  `${snapshotDocumentId || documentId}-${snapshotDocumentId ? "snapshot" : "live"}`
1202
2327
  )
1203
2328
  ] }),
1204
- streamingDoc && isStreaming && isArtifact && !liveKind && !isComparing && (activeTab === "html" || activeTab === "edit") && /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerMessage, { children: "Opening draft\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
2329
+ streamingDoc && isStreaming && isArtifact && !liveKind && !isComparing && (activeTab === "html" || activeTab === "edit") && /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: "Opening draft\u2026" }), children: /* @__PURE__ */ jsxRuntime.jsx(
1205
2330
  StreamedWordArtifact,
1206
2331
  {
1207
2332
  documentId: documentId.startsWith("doc-") ? documentId : void 0,
@@ -1211,13 +2336,16 @@ function DocumentViewerContent({
1211
2336
  },
1212
2337
  documentId
1213
2338
  ) }),
1214
- !isCaptureDraft && !isComparing && activeTab === "html" && !(isStreaming && isArtifact && !liveKind) && support.renderParsedView && /* @__PURE__ */ jsxRuntime.jsx(chunkUWIILWDI_cjs.ViewerPane, { children: /* @__PURE__ */ jsxRuntime.jsx(chunkV4YZXGXR_cjs.ViewerControlBar, { controls: pageNav, children: support.renderParsedView({
1215
- documentId: pdfSnapshotId || documentId,
1216
- onLoadSuccess: handleLoadSuccess,
1217
- scrollTrigger,
1218
- zoom,
1219
- onZoomChange: setZoom
1220
- }) }) })
2339
+ !isCaptureDraft && !isComparing && activeTab === "html" && !(isStreaming && isArtifact && !liveKind) && /* @__PURE__ */ jsxRuntime.jsx(chunkUWIILWDI_cjs.ViewerPane, { children: /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerControlBar, { controls: pageNav, children: /* @__PURE__ */ jsxRuntime.jsx(
2340
+ ParsedTextView,
2341
+ {
2342
+ documentId: pdfSnapshotId || documentId,
2343
+ onLoadSuccess: handleLoadSuccess,
2344
+ scrollTrigger,
2345
+ zoom,
2346
+ onZoomChange: setZoom
2347
+ }
2348
+ ) }) })
1221
2349
  ]
1222
2350
  }
1223
2351
  );