@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.
- package/dist/{ConnectedNativeDocxComparison-XQSXVGHR.js → ConnectedNativeDocxComparison-OFPIXNJB.js} +6 -6
- package/dist/{ConnectedStreamedWordArtifact-UZVNBKQB.js.map → ConnectedNativeDocxComparison-OFPIXNJB.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-3XQSINPQ.cjs → ConnectedNativeDocxComparison-Y5BNLNH6.cjs} +7 -7
- package/dist/{ConnectedNativeDocxComparison-3XQSINPQ.cjs.map → ConnectedNativeDocxComparison-Y5BNLNH6.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-OUWFMIPH.cjs → ConnectedNativeDocxEditor-HTEW5JAH.cjs} +7 -7
- package/dist/{ConnectedNativeDocxEditor-OUWFMIPH.cjs.map → ConnectedNativeDocxEditor-HTEW5JAH.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-IPEZDERL.js → ConnectedNativeDocxEditor-LRYU5HPA.js} +5 -5
- package/dist/{ConnectedNativeDocxEditor-IPEZDERL.js.map → ConnectedNativeDocxEditor-LRYU5HPA.js.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-UZVNBKQB.js → ConnectedStreamedWordArtifact-QAUVUCSX.js} +6 -6
- package/dist/{ConnectedNativeDocxComparison-XQSXVGHR.js.map → ConnectedStreamedWordArtifact-QAUVUCSX.js.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-D5LSMDO4.cjs → ConnectedStreamedWordArtifact-QW74LKHN.cjs} +7 -7
- package/dist/ConnectedStreamedWordArtifact-QW74LKHN.cjs.map +1 -0
- package/dist/agents/index.cjs +238 -238
- package/dist/agents/index.js +4 -4
- package/dist/calls/index.cjs +3 -3
- package/dist/calls/index.js +2 -2
- package/dist/{chunk-IPQ5MJ4Z.cjs → chunk-2FLWPM3B.cjs} +5 -5
- package/dist/{chunk-IPQ5MJ4Z.cjs.map → chunk-2FLWPM3B.cjs.map} +1 -1
- package/dist/{chunk-CQPFW64W.js → chunk-3PCBYOIZ.js} +3 -3
- package/dist/{chunk-CQPFW64W.js.map → chunk-3PCBYOIZ.js.map} +1 -1
- package/dist/{chunk-Q6N6MZKO.js → chunk-4236BRZK.js} +3 -3
- package/dist/{chunk-Q6N6MZKO.js.map → chunk-4236BRZK.js.map} +1 -1
- package/dist/{chunk-KLPRAQCE.cjs → chunk-6I6CVX5G.cjs} +2 -2
- package/dist/{chunk-KLPRAQCE.cjs.map → chunk-6I6CVX5G.cjs.map} +1 -1
- package/dist/{chunk-TAWPVD6C.cjs → chunk-B3FMUFAW.cjs} +3 -3
- package/dist/{chunk-TAWPVD6C.cjs.map → chunk-B3FMUFAW.cjs.map} +1 -1
- package/dist/{chunk-3E2F4AHD.js → chunk-CROTH2BS.js} +5 -5
- package/dist/{chunk-3E2F4AHD.js.map → chunk-CROTH2BS.js.map} +1 -1
- package/dist/{chunk-ILM42LE6.cjs → chunk-CU2O32Z4.cjs} +25 -25
- package/dist/{chunk-ILM42LE6.cjs.map → chunk-CU2O32Z4.cjs.map} +1 -1
- package/dist/{chunk-TL45OJQE.js → chunk-DB2OXRQC.js} +3 -3
- package/dist/{chunk-TL45OJQE.js.map → chunk-DB2OXRQC.js.map} +1 -1
- package/dist/{chunk-ZAVEMQ37.cjs → chunk-DWZXSPMB.cjs} +3 -3
- package/dist/{chunk-ZAVEMQ37.cjs.map → chunk-DWZXSPMB.cjs.map} +1 -1
- package/dist/{chunk-XRWHFMHK.js → chunk-EYJMMGXF.js} +2 -2
- package/dist/{chunk-XRWHFMHK.js.map → chunk-EYJMMGXF.js.map} +1 -1
- package/dist/{chunk-NWNAYXC7.cjs → chunk-GFOEWPAP.cjs} +3 -3
- package/dist/{chunk-NWNAYXC7.cjs.map → chunk-GFOEWPAP.cjs.map} +1 -1
- package/dist/{chunk-YIFCLNII.cjs → chunk-HALD6ZB5.cjs} +4 -4
- package/dist/{chunk-YIFCLNII.cjs.map → chunk-HALD6ZB5.cjs.map} +1 -1
- package/dist/{chunk-TC25LGIM.js → chunk-HUJF2XM2.js} +4 -4
- package/dist/chunk-HUJF2XM2.js.map +1 -0
- package/dist/{chunk-GGTUMLCT.cjs → chunk-Q4BY2CQQ.cjs} +3 -3
- package/dist/{chunk-GGTUMLCT.cjs.map → chunk-Q4BY2CQQ.cjs.map} +1 -1
- package/dist/{chunk-AXTDDWMR.js → chunk-QN47Q4N7.js} +3 -3
- package/dist/{chunk-AXTDDWMR.js.map → chunk-QN47Q4N7.js.map} +1 -1
- package/dist/{chunk-V4YZXGXR.cjs → chunk-T74Q3MCZ.cjs} +4 -4
- package/dist/chunk-T74Q3MCZ.cjs.map +1 -0
- package/dist/{chunk-3FSXWVHW.cjs → chunk-U6JQ4KMX.cjs} +3 -3
- package/dist/{chunk-3FSXWVHW.cjs.map → chunk-U6JQ4KMX.cjs.map} +1 -1
- package/dist/{chunk-ECERC6TI.js → chunk-VHJHY7TT.js} +3 -3
- package/dist/{chunk-ECERC6TI.js.map → chunk-VHJHY7TT.js.map} +1 -1
- package/dist/{chunk-UTVY63DG.js → chunk-WFA2GVZJ.js} +3 -3
- package/dist/{chunk-UTVY63DG.js.map → chunk-WFA2GVZJ.js.map} +1 -1
- package/dist/{chunk-ZO7PJMCO.js → chunk-WU34CHU5.js} +3 -3
- package/dist/{chunk-ZO7PJMCO.js.map → chunk-WU34CHU5.js.map} +1 -1
- package/dist/{chunk-HGLC566X.js → chunk-YXNNNP57.js} +3 -3
- package/dist/{chunk-HGLC566X.js.map → chunk-YXNNNP57.js.map} +1 -1
- package/dist/{chunk-EDV7CYG6.cjs → chunk-ZP6Q3KXU.cjs} +4 -4
- package/dist/{chunk-EDV7CYG6.cjs.map → chunk-ZP6Q3KXU.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/connect/docx.cjs +9 -9
- package/dist/connect/docx.js +5 -5
- package/dist/connect/index.cjs +292 -292
- package/dist/connect/index.d.ts +1 -1
- package/dist/connect/index.js +13 -13
- package/dist/connect/viewer.cjs +1249 -121
- package/dist/connect/viewer.cjs.map +1 -1
- package/dist/connect/viewer.js +1145 -21
- package/dist/connect/viewer.js.map +1 -1
- package/dist/connection/viewer/parsed/ParsedPassage.d.ts +48 -0
- package/dist/connection/viewer/parsed/ParsedTextView.d.ts +17 -0
- package/dist/connection/viewer/parsed/PassageTagPanel.d.ts +18 -0
- package/dist/connection/viewer/parsed/citation-line.d.ts +17 -0
- package/dist/connection/viewer/parsed/document-tags.d.ts +8 -0
- package/dist/connection/viewer/parsed/useChunkTagging.d.ts +46 -0
- package/dist/connection/viewer/parsed/useCitationSelection.d.ts +27 -0
- package/dist/connection/viewer/parsed/useDocumentLabels.d.ts +38 -0
- package/dist/connection/viewer/parsed/useLazyPages.d.ts +18 -0
- package/dist/connection/viewer/parsed/usePageScrollSync.d.ts +17 -0
- package/dist/connection/viewer/parsed/usePassageCopy.d.ts +25 -0
- package/dist/connection/viewer/support.d.ts +27 -9
- package/dist/facts/index.cjs +55 -55
- package/dist/facts/index.js +5 -5
- package/dist/files/TagPassagePanel.d.ts +2 -1
- package/dist/files/index.cjs +169 -169
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +2 -2
- package/dist/home/index.js +2 -2
- package/dist/index.cjs +355 -355
- package/dist/index.js +8 -8
- package/dist/retrieval/index.cjs +1 -1
- package/dist/retrieval/index.js +1 -1
- package/dist/settings/index.cjs +164 -164
- package/dist/settings/index.js +3 -3
- package/dist/shell/index.cjs +2 -2
- package/dist/shell/index.js +2 -2
- package/dist/studio/index.cjs +2 -2
- package/dist/studio/index.js +2 -2
- package/dist/workflow-canvas/index.cjs +16 -16
- package/dist/workflow-canvas/index.js +4 -4
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ConnectedStreamedWordArtifact-D5LSMDO4.cjs.map +0 -1
- package/dist/chunk-TC25LGIM.js.map +0 -1
- package/dist/chunk-V4YZXGXR.cjs.map +0 -1
package/dist/connect/viewer.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
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
|
|
43
|
+
var React = require('react');
|
|
42
44
|
var lucideReact = require('lucide-react');
|
|
43
|
-
var 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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
78
|
+
const onDocumentsChanged = React.useCallback(
|
|
73
79
|
async (ids, change) => {
|
|
74
|
-
const refresh = [react
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
119
|
+
const finalise = react.useFinaliseTranslation();
|
|
114
120
|
const { openDocument } = documentTools.useDocumentTools();
|
|
115
121
|
const { notify } = chunkKPZZ5FHE_cjs.useBlocksEnvironment();
|
|
116
|
-
if (!
|
|
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(
|
|
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] =
|
|
154
|
-
const handleOpenCrop =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
198
|
-
const [webmHasVideoTrack, setWebmHasVideoTrack] =
|
|
199
|
-
|
|
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
|
|
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 =
|
|
216
|
-
() =>
|
|
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
|
|
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 } =
|
|
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] =
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
305
|
+
React.useEffect(() => {
|
|
300
306
|
if (!isWebmFile || !pdfBlob) return;
|
|
301
307
|
let cancelled = false;
|
|
302
|
-
void react
|
|
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 =
|
|
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
|
|
350
|
+
const session = react.useArbiSessionStore();
|
|
345
351
|
const {
|
|
346
352
|
tab: activeTab,
|
|
347
353
|
compareId,
|
|
348
354
|
tabRequest,
|
|
349
355
|
phonePdfChosen
|
|
350
|
-
} = react
|
|
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 =
|
|
360
|
+
const phoneDefaultDecidedFor = React.useRef(null);
|
|
355
361
|
const hasDocumentData = !!documentData;
|
|
356
362
|
const documentKey = documentData?.external_id;
|
|
357
|
-
|
|
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
|
-
|
|
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
|
-
|
|
382
|
+
React.useEffect(() => {
|
|
377
383
|
if (activeTab === "versions" && documentData && !hasVersionsTab) {
|
|
378
384
|
setActiveTab(isXlsx ? "xlsx" : "pdf");
|
|
379
385
|
}
|
|
380
386
|
}, [activeTab, documentData, hasVersionsTab]);
|
|
381
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
478
|
-
const versions =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
1629
|
+
var SignaturePlacementViewer = React.lazy(
|
|
505
1630
|
() => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.SignaturePlacementViewer }))
|
|
506
1631
|
);
|
|
507
|
-
var SignatureRequestEditor =
|
|
1632
|
+
var SignatureRequestEditor = React.lazy(
|
|
508
1633
|
() => import('../document-tools/viewer/index.cjs').then((m) => ({ default: m.SignatureRequestEditor }))
|
|
509
1634
|
);
|
|
510
|
-
var GuidedSigningViewer =
|
|
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
|
|
515
|
-
const viewingId = react
|
|
516
|
-
const { isDetached } =
|
|
517
|
-
const onPageChange =
|
|
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
|
-
|
|
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(
|
|
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(
|
|
1684
|
+
if (isPdfLoading) return /* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerMessage, { children: loadingLabel });
|
|
560
1685
|
if (pdfError) {
|
|
561
1686
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
562
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1745
|
+
React.Suspense,
|
|
621
1746
|
{
|
|
622
|
-
fallback: /* @__PURE__ */ jsxRuntime.jsx(
|
|
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 =
|
|
646
|
-
() => import('../ConnectedNativeDocxEditor-
|
|
1770
|
+
var NativeDocxEditor = React.lazy(
|
|
1771
|
+
() => import('../ConnectedNativeDocxEditor-HTEW5JAH.cjs').then((m) => ({
|
|
647
1772
|
default: m.ConnectedNativeDocxEditor
|
|
648
1773
|
}))
|
|
649
1774
|
);
|
|
650
|
-
var StreamedWordArtifact =
|
|
651
|
-
() => import('../ConnectedStreamedWordArtifact-
|
|
1775
|
+
var StreamedWordArtifact = React.lazy(
|
|
1776
|
+
() => import('../ConnectedStreamedWordArtifact-QW74LKHN.cjs').then((m) => ({
|
|
652
1777
|
default: m.ConnectedStreamedWordArtifact
|
|
653
1778
|
}))
|
|
654
1779
|
);
|
|
655
|
-
var NativeDocxComparison =
|
|
656
|
-
() => import('../ConnectedNativeDocxComparison-
|
|
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
|
|
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
|
|
677
|
-
const session = react
|
|
678
|
-
const support =
|
|
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] =
|
|
685
|
-
const [isCompact, setIsCompact] =
|
|
686
|
-
const [pdfZoom, setPdfZoom] =
|
|
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
|
|
1816
|
+
} = react.useArbiSessionState((s) => s.documentViewer);
|
|
692
1817
|
const zoom = zoomTab === "html" ? textScale : pdfZoom;
|
|
693
|
-
const setZoom =
|
|
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] =
|
|
702
|
-
const containerRef =
|
|
703
|
-
const viewingDocumentPage = react
|
|
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] =
|
|
748
|
-
|
|
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] =
|
|
753
|
-
const [signAppearance, setSignAppearance] =
|
|
754
|
-
const [isSignOpen, setIsSignOpen] =
|
|
755
|
-
|
|
756
|
-
const [signatureFlow, setSignatureFlow] =
|
|
757
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
1911
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkT74Q3MCZ_cjs.ViewerZoomControl, { zoom, onCycle: () => setZoom(viewers.cycleZoom(zoom)) }),
|
|
787
1912
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
788
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
1191
|
-
activeTab === "docx" && isDocx && !isComparing && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
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(
|
|
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) &&
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
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
|
);
|