@arbidocs/blocks 0.5.123 → 0.5.125
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/{ClippingMediaViewer-IEIBT74X.cjs → ClippingMediaViewer-ZFEX5A3U.cjs} +11 -10
- package/dist/ClippingMediaViewer-ZFEX5A3U.cjs.map +1 -0
- package/dist/{ClippingPdfViewer-OGYLMVCE.cjs → ClippingPdfViewer-3LRTEPHV.cjs} +45 -11
- package/dist/ClippingPdfViewer-3LRTEPHV.cjs.map +1 -0
- package/dist/ConnectedCallDock-XJOYVVAH.cjs +6 -6
- package/dist/ConnectedCallRoom-CUDYAPQK.cjs +6 -6
- package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs → ConnectedNativeDocxComparison-7QQ55JIO.cjs} +13 -13
- package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs.map → ConnectedNativeDocxComparison-7QQ55JIO.cjs.map} +1 -1
- package/dist/{ConnectedPresentation-5DOJ35XL.cjs → ConnectedPresentation-L32JPRFI.cjs} +30 -156
- package/dist/ConnectedPresentation-L32JPRFI.cjs.map +1 -0
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs → ConnectedProductionSetDialog-4EAY6KAZ.cjs} +3 -3
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs.map → ConnectedProductionSetDialog-4EAY6KAZ.cjs.map} +1 -1
- package/dist/{ConnectedSlidesTab-7YMEDGUU.cjs → ConnectedSlidesTab-P7GGNUTO.cjs} +31 -29
- package/dist/ConnectedSlidesTab-P7GGNUTO.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs → ConnectedStreamedWordArtifact-7NJ3N52V.cjs} +13 -13
- package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs.map → ConnectedStreamedWordArtifact-7NJ3N52V.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-M53XFLI2.cjs → DocumentReviewCard-BFPOFQXI.cjs} +16 -16
- package/dist/{DocumentReviewCard-M53XFLI2.cjs.map → DocumentReviewCard-BFPOFQXI.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-2QCCRWF2.cjs → FilesViewerDialog-MHUVEZ7M.cjs} +35 -32
- package/dist/FilesViewerDialog-MHUVEZ7M.cjs.map +1 -0
- package/dist/{NativeDocxEditor-2LQY2CTV.cjs → NativeDocxEditor-SIRYPMBN.cjs} +6 -6
- package/dist/{NativeDocxEditor-2LQY2CTV.cjs.map → NativeDocxEditor-SIRYPMBN.cjs.map} +1 -1
- package/dist/SpotlightStrip-ED22UYTM.cjs +398 -0
- package/dist/SpotlightStrip-ED22UYTM.cjs.map +1 -0
- package/dist/{WorkspaceTableView-3XYAV4BV.cjs → WorkspaceTableView-MIFYXV3G.cjs} +8 -8
- package/dist/{WorkspaceTableView-3XYAV4BV.cjs.map → WorkspaceTableView-MIFYXV3G.cjs.map} +1 -1
- package/dist/agents/index.cjs +216 -216
- package/dist/ai-IEIR7SC2.cjs +3 -3
- package/dist/auth/index.cjs +1 -1
- package/dist/calls/index.cjs +2 -2
- package/dist/chat/index.cjs +6 -6
- package/dist/{chunk-GNZAH6UI.cjs → chunk-2K6IMIVL.cjs} +3 -3
- package/dist/{chunk-GNZAH6UI.cjs.map → chunk-2K6IMIVL.cjs.map} +1 -1
- package/dist/{chunk-NQML7IUC.cjs → chunk-3UP32FM3.cjs} +6 -6
- package/dist/{chunk-NQML7IUC.cjs.map → chunk-3UP32FM3.cjs.map} +1 -1
- package/dist/chunk-3ZZZO4F7.cjs +145 -0
- package/dist/chunk-3ZZZO4F7.cjs.map +1 -0
- package/dist/{chunk-L4CIFLCU.cjs → chunk-4LP5MJGQ.cjs} +4 -4
- package/dist/{chunk-L4CIFLCU.cjs.map → chunk-4LP5MJGQ.cjs.map} +1 -1
- package/dist/{chunk-JD2HX2BR.cjs → chunk-6JMW3IJ2.cjs} +152 -155
- package/dist/chunk-6JMW3IJ2.cjs.map +1 -0
- package/dist/{chunk-WV7BCGCK.cjs → chunk-7RJZIPLE.cjs} +33 -33
- package/dist/{chunk-WV7BCGCK.cjs.map → chunk-7RJZIPLE.cjs.map} +1 -1
- package/dist/{chunk-WFMWKPGY.cjs → chunk-ADPRIBSH.cjs} +9 -33
- package/dist/chunk-ADPRIBSH.cjs.map +1 -0
- package/dist/{chunk-7NLO7ASW.cjs → chunk-AISYXX4M.cjs} +4 -4
- package/dist/{chunk-7NLO7ASW.cjs.map → chunk-AISYXX4M.cjs.map} +1 -1
- package/dist/{chunk-5QERK4PK.cjs → chunk-AS6QZETU.cjs} +35 -35
- package/dist/{chunk-5QERK4PK.cjs.map → chunk-AS6QZETU.cjs.map} +1 -1
- package/dist/{chunk-V6MW7B4B.cjs → chunk-B3R62764.cjs} +6 -6
- package/dist/{chunk-V6MW7B4B.cjs.map → chunk-B3R62764.cjs.map} +1 -1
- package/dist/{chunk-VKH3BEZE.cjs → chunk-BLIO3B7Z.cjs} +3 -3
- package/dist/{chunk-VKH3BEZE.cjs.map → chunk-BLIO3B7Z.cjs.map} +1 -1
- package/dist/{chunk-46P7IDBX.cjs → chunk-CQ2RJYE2.cjs} +4 -4
- package/dist/chunk-CQ2RJYE2.cjs.map +1 -0
- package/dist/{chunk-MXBXZXXQ.cjs → chunk-ENOPKX7E.cjs} +3 -3
- package/dist/{chunk-MXBXZXXQ.cjs.map → chunk-ENOPKX7E.cjs.map} +1 -1
- package/dist/{chunk-2CSLFAGF.cjs → chunk-GAMRVB3I.cjs} +4 -3
- package/dist/chunk-GAMRVB3I.cjs.map +1 -0
- package/dist/chunk-IRGRMJPP.cjs +18 -0
- package/dist/{chunk-SDRYSLOX.cjs.map → chunk-IRGRMJPP.cjs.map} +1 -1
- package/dist/{chunk-ADDQKZ5I.cjs → chunk-J3FFSEKO.cjs} +4 -4
- package/dist/{chunk-ADDQKZ5I.cjs.map → chunk-J3FFSEKO.cjs.map} +1 -1
- package/dist/chunk-JITYC4OS.cjs +66 -0
- package/dist/chunk-JITYC4OS.cjs.map +1 -0
- package/dist/chunk-JY7UUZQG.cjs +1513 -0
- package/dist/chunk-JY7UUZQG.cjs.map +1 -0
- package/dist/{chunk-ALK3PUUB.cjs → chunk-L6HTZIBD.cjs} +3 -3
- package/dist/{chunk-ALK3PUUB.cjs.map → chunk-L6HTZIBD.cjs.map} +1 -1
- package/dist/chunk-MVXHTAJ4.cjs +111 -0
- package/dist/chunk-MVXHTAJ4.cjs.map +1 -0
- package/dist/{chunk-OHHKBURG.cjs → chunk-OGK377NL.cjs} +33 -33
- package/dist/{chunk-OHHKBURG.cjs.map → chunk-OGK377NL.cjs.map} +1 -1
- package/dist/{chunk-T73BHNQX.cjs → chunk-OHWHYVKG.cjs} +3 -3
- package/dist/{chunk-T73BHNQX.cjs.map → chunk-OHWHYVKG.cjs.map} +1 -1
- package/dist/{chunk-4TTX6ZNS.cjs → chunk-ORNLCBNE.cjs} +24 -2
- package/dist/chunk-ORNLCBNE.cjs.map +1 -0
- package/dist/{chunk-MLA2BJ2Y.cjs → chunk-PSB64T43.cjs} +28 -28
- package/dist/{chunk-MLA2BJ2Y.cjs.map → chunk-PSB64T43.cjs.map} +1 -1
- package/dist/{chunk-COD5ENHK.cjs → chunk-PVJ5ODDB.cjs} +4 -4
- package/dist/{chunk-COD5ENHK.cjs.map → chunk-PVJ5ODDB.cjs.map} +1 -1
- package/dist/{chunk-7557LDAN.cjs → chunk-PWBRE7JA.cjs} +5 -5
- package/dist/{chunk-7557LDAN.cjs.map → chunk-PWBRE7JA.cjs.map} +1 -1
- package/dist/{chunk-7PN3YENO.cjs → chunk-QIK7E6VF.cjs} +4 -4
- package/dist/{chunk-7PN3YENO.cjs.map → chunk-QIK7E6VF.cjs.map} +1 -1
- package/dist/{chunk-DWMWEALB.cjs → chunk-TSFNLY3K.cjs} +143 -1634
- package/dist/chunk-TSFNLY3K.cjs.map +1 -0
- package/dist/{chunk-YGBHY67W.cjs → chunk-UA7HOLAZ.cjs} +5 -5
- package/dist/{chunk-YGBHY67W.cjs.map → chunk-UA7HOLAZ.cjs.map} +1 -1
- package/dist/{chunk-KXIRVKCJ.cjs → chunk-UUENH4BJ.cjs} +3 -3
- package/dist/{chunk-KXIRVKCJ.cjs.map → chunk-UUENH4BJ.cjs.map} +1 -1
- package/dist/chunk-WVZLAAIZ.cjs +31 -0
- package/dist/chunk-WVZLAAIZ.cjs.map +1 -0
- package/dist/{chunk-E3L5DB5F.cjs → chunk-YOEP3I4V.cjs} +5 -5
- package/dist/{chunk-E3L5DB5F.cjs.map → chunk-YOEP3I4V.cjs.map} +1 -1
- package/dist/{chunk-SNPK3R3O.cjs → chunk-YVO6Z5BS.cjs} +10 -10
- package/dist/{chunk-SNPK3R3O.cjs.map → chunk-YVO6Z5BS.cjs.map} +1 -1
- package/dist/chunk-ZZZITHGK.cjs +119 -0
- package/dist/chunk-ZZZITHGK.cjs.map +1 -0
- package/dist/connect/docx.cjs +17 -17
- package/dist/connect/index.cjs +994 -994
- package/dist/connect/viewer.cjs +28 -25
- package/dist/connection/presentation/ClippingMediaViewer.js +3 -3
- package/dist/connection/presentation/ClippingMediaViewer.js.map +2 -2
- package/dist/connection/presentation/ClippingPdfViewer.d.ts +4 -3
- package/dist/connection/presentation/ClippingPdfViewer.js +48 -9
- package/dist/connection/presentation/ClippingPdfViewer.js.map +2 -2
- package/dist/connection/presentation/SpotlightLayer.d.ts +5 -0
- package/dist/connection/presentation/SpotlightLayer.js +19 -0
- package/dist/connection/presentation/SpotlightLayer.js.map +7 -0
- package/dist/connection/presentation/SpotlightStrip.d.ts +10 -0
- package/dist/connection/presentation/SpotlightStrip.js +237 -0
- package/dist/connection/presentation/SpotlightStrip.js.map +7 -0
- package/dist/connection/presentation/useViewerClipping.d.ts +4 -3
- package/dist/connection/presentation/useViewerClipping.js +8 -4
- package/dist/connection/presentation/useViewerClipping.js.map +2 -2
- package/dist/connection/viewer/ConnectedDocumentViewer.js +1 -1
- package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
- package/dist/connection/viewer/VersionDropdown.js +1 -1
- package/dist/connection/viewer/VersionDropdown.js.map +1 -1
- package/dist/connection/viewer/ViewerPdfPane.js +2 -0
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/pdf/passageHighlights.d.ts +5 -0
- package/dist/connection/viewer/pdf/passageHighlights.js +14 -1
- package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
- package/dist/connection/viewer/pdf/usePassageTextFallback.d.ts +12 -0
- package/dist/connection/viewer/pdf/usePassageTextFallback.js +30 -0
- package/dist/connection/viewer/pdf/usePassageTextFallback.js.map +7 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +2 -11
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
- package/dist/connection/viewer/useCleanView.d.ts +3 -1
- package/dist/connection/viewer/useCleanView.js +6 -3
- package/dist/connection/viewer/useCleanView.js.map +2 -2
- package/dist/connection/viewer/useViewerTabs.js +13 -1
- package/dist/connection/viewer/useViewerTabs.js.map +2 -2
- package/dist/document-tools/DocumentToolButtons.js +1 -1
- package/dist/document-tools/DocumentToolButtons.js.map +1 -1
- package/dist/document-tools/index.cjs +20 -20
- package/dist/docx/DocxCommandMenu.js +2 -1
- package/dist/docx/DocxCommandMenu.js.map +2 -2
- package/dist/docx/index.cjs +38 -38
- package/dist/embed/index.cjs +20 -20
- package/dist/facts/index.cjs +64 -64
- package/dist/files/index.cjs +223 -223
- package/dist/index.cjs +521 -521
- package/dist/presentation/ClipCaptureOverlay.d.ts +7 -3
- package/dist/presentation/ClipCaptureOverlay.js +43 -14
- package/dist/presentation/ClipCaptureOverlay.js.map +2 -2
- package/dist/presentation/PresentControls.d.ts +8 -0
- package/dist/presentation/PresentControls.js +1 -0
- package/dist/presentation/PresentControls.js.map +2 -2
- package/dist/presentation/PresentationStage.d.ts +10 -2
- package/dist/presentation/PresentationStage.js +6 -3
- package/dist/presentation/PresentationStage.js.map +2 -2
- package/dist/presentation/PresenterView.js +1 -22
- package/dist/presentation/PresenterView.js.map +2 -2
- package/dist/presentation/SpotlightView.d.ts +19 -0
- package/dist/presentation/SpotlightView.js +180 -0
- package/dist/presentation/SpotlightView.js.map +7 -0
- package/dist/presentation/passage-clip.d.ts +17 -0
- package/dist/presentation/passage-clip.js +25 -0
- package/dist/presentation/passage-clip.js.map +7 -0
- package/dist/presentation/spotlight.d.ts +58 -0
- package/dist/presentation/spotlight.js +110 -0
- package/dist/presentation/spotlight.js.map +7 -0
- package/dist/presentation/store.d.ts +5 -0
- package/dist/presentation/store.js +19 -0
- package/dist/presentation/store.js.map +2 -2
- package/dist/presentation/usePointerActive.d.ts +2 -0
- package/dist/presentation/usePointerActive.js +28 -0
- package/dist/presentation/usePointerActive.js.map +7 -0
- package/dist/settings/index.cjs +146 -146
- package/dist/site/index.cjs +6 -6
- package/dist/studio/index.cjs +9 -9
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +35 -35
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ClippingMediaViewer-IEIBT74X.cjs.map +0 -1
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs.map +0 -1
- package/dist/ConnectedPresentation-5DOJ35XL.cjs.map +0 -1
- package/dist/ConnectedSlidesTab-7YMEDGUU.cjs.map +0 -1
- package/dist/FilesViewerDialog-2QCCRWF2.cjs.map +0 -1
- package/dist/chunk-2CSLFAGF.cjs.map +0 -1
- package/dist/chunk-46P7IDBX.cjs.map +0 -1
- package/dist/chunk-4TTX6ZNS.cjs.map +0 -1
- package/dist/chunk-DWMWEALB.cjs.map +0 -1
- package/dist/chunk-JD2HX2BR.cjs.map +0 -1
- package/dist/chunk-SDRYSLOX.cjs +0 -18
- package/dist/chunk-WFMWKPGY.cjs.map +0 -1
- package/dist/chunk-XK4TVJKD.cjs +0 -73
- package/dist/chunk-XK4TVJKD.cjs.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/presentation/SpotlightStrip.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The clips gathered in the viewer, in a small strip over the document: each clip (\u00D7 takes it\n * out), a note to show as the spotlight's title, another document to clip from, and Show (or S),\n * which puts them in the spotlight over this same viewer. Rarer actions \u2014 keep them as a slide,\n * add them to the presentation's tray, clear them \u2014 are in its \"\u2026\" menu.\n *\n * The strip and the spotlight stay over whichever document the viewer shows, so clips are gathered\n * from several documents in a row. Esc brings the document back where it was scrolled to.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Eraser, MoreHorizontal, Inbox, Presentation, StickyNote, X } from 'lucide-react'\nimport { useArbiSessionStore, useDocuments } from '@arbidocs/react'\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n cn,\n getDocumentTitle,\n} from '@arbidocs/react/ui'\nimport { ClipImage } from '../../presentation/ClipImage'\nimport type { Clip } from '../../presentation/model'\nimport { SpotlightView, type ScreenRect } from '../../presentation/SpotlightView'\nimport { useSpotlight } from '../../presentation/spotlight'\nimport { DocumentPicker, type PickerGroup } from '../../settings/DocumentPicker'\n\n/** The viewer this strip is over (its frame), found from the strip's own element. */\nconst frameOf = (node: HTMLElement | null) =>\n node?.closest<HTMLElement>('[data-slot=\"viewer-frame\"]') ?? null\n\nconst isTyping = (target: EventTarget | null) =>\n !!(target as HTMLElement | null)?.closest?.('input, textarea, select, [contenteditable=\"true\"]')\n\n/**\n * Where a clip is on screen now: its area of its page, while its document is clipped in the viewer\n * (`data-clip-document`) and that page is in view.\n */\nfunction clipOnPage(frame: HTMLElement, clip: Clip): ScreenRect | null {\n const clipped = Array.from(frame.querySelectorAll('[data-clip-document]')).find(\n (element) => element.getAttribute('data-clip-document') === clip.documentId\n )\n const page = clipped?.querySelector<HTMLElement>(`[data-page-number=\"${clip.page}\"]`)\n if (!page) return null\n const box = page.getBoundingClientRect()\n const view = frame.ownerDocument.defaultView\n const rect = {\n left: box.left + clip.rect.x * box.width,\n top: box.top + clip.rect.y * box.height,\n width: clip.rect.w * box.width,\n height: clip.rect.h * box.height,\n }\n const visible =\n rect.width > 0 &&\n rect.top + rect.height > 0 &&\n rect.left + rect.width > 0 &&\n (!view || (rect.top < view.innerHeight && rect.left < view.innerWidth))\n return visible ? rect : null\n}\n\nfunction useDocumentSwitcher(clips: readonly Clip[]) {\n const session = useArbiSessionStore()\n const { data: documents } = useDocuments()\n const groups = useMemo<PickerGroup[]>(() => {\n const all = (documents ?? [])\n .map((doc) => ({\n id: doc.external_id,\n title: getDocumentTitle(doc, 'Untitled'),\n fileName: doc.file_name,\n }))\n .sort((a, b) => a.title.localeCompare(b.title))\n const clipped = new Set(clips.map((clip) => clip.documentId))\n const from = all.filter((doc) => clipped.has(doc.id))\n return [\n ...(from.length ? [{ id: 'clipped', heading: 'Clipped from', docs: from }] : []),\n { id: 'all', heading: 'Documents', docs: all },\n ]\n }, [documents, clips])\n const open = (id: string) => session.setViewingDocument({ id, page: null })\n return { groups, open }\n}\n\nexport function SpotlightStrip() {\n const clips = useSpotlight((s) => s.clips)\n const note = useSpotlight((s) => s.note)\n const showing = useSpotlight((s) => s.showing)\n const actions = useSpotlight.getState()\n const switcher = useDocumentSwitcher(clips)\n const [noteOpen, setNoteOpen] = useState(false)\n\n const strip = useRef<HTMLDivElement | null>(null)\n const [view, setView] = useState<Window | null>(null)\n const stripRef = useCallback((node: HTMLDivElement | null) => {\n strip.current = node\n if (node) setView(node.ownerDocument.defaultView)\n }, [])\n\n // S shows the spotlight (not while typing).\n useEffect(() => {\n if (!view || showing) return\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.metaKey || event.ctrlKey || event.altKey || isTyping(event.target)) return\n if (event.key !== 's' && event.key !== 'S') return\n event.preventDefault()\n useSpotlight.getState().show()\n }\n view.addEventListener('keydown', onKeyDown)\n return () => view.removeEventListener('keydown', onKeyDown)\n }, [view, showing])\n\n // Back from the spotlight, the document is where it was scrolled to.\n const scrolled = useRef<{ element: HTMLElement; top: number; left: number } | null>(null)\n useEffect(() => {\n const scroller = frameOf(strip.current)?.querySelector<HTMLElement>(\n '[data-slot=\"pdf-scroller\"]'\n )\n if (showing) {\n scrolled.current = scroller\n ? { element: scroller, top: scroller.scrollTop, left: scroller.scrollLeft }\n : null\n return\n }\n const before = scrolled.current\n scrolled.current = null\n if (before?.element.isConnected) {\n before.element.scrollTop = before.top\n before.element.scrollLeft = before.left\n }\n }, [showing])\n\n const fromRect = useCallback((clip: Clip) => {\n const frame = frameOf(strip.current)\n const onPage = frame ? clipOnPage(frame, clip) : null\n // Not on screen (another document's clip): from its chip in the strip.\n return (\n onPage ??\n strip.current?.querySelector(`[data-spotlight-clip=\"${clip.id}\"]`)?.getBoundingClientRect() ??\n null\n )\n }, [])\n\n const count = `${clips.length} clip${clips.length === 1 ? '' : 's'}`\n return (\n <>\n <div\n ref={stripRef}\n className={cn(\n 'absolute bottom-[4.5rem] left-1/2 z-20 flex max-w-[calc(100%-1.5rem)] -translate-x-1/2 items-center gap-1.5 rounded-full border border-border bg-background/95 p-1 pl-1.5 shadow-lg backdrop-blur',\n showing && 'invisible'\n )}\n role=\"toolbar\"\n aria-label=\"Gathered clips\"\n data-testid=\"spotlight-strip\"\n >\n <ul className=\"flex min-w-0 items-center gap-1 overflow-x-auto [scrollbar-width:none]\">\n {clips.map((clip, index) => (\n <li\n key={clip.id}\n className=\"group relative h-8 shrink-0 overflow-hidden rounded-md border border-border bg-white\"\n style={{ width: `${Math.min(4.5, Math.max(1.5, 2 * clip.aspect))}rem` }}\n title={clip.caption}\n data-spotlight-clip={clip.id}\n data-testid={`spotlight-chip-${index}`}\n >\n <ClipImage clip={clip} className=\"h-full w-full\" />\n <button\n type=\"button\"\n className=\"absolute inset-0 flex items-center justify-center bg-black/50 text-white opacity-0 transition-opacity focus-visible:opacity-100 group-hover:opacity-100\"\n onClick={() => actions.remove(clip.id)}\n aria-label={`Remove ${clip.caption}`}\n data-testid={`spotlight-remove-${index}`}\n >\n <X className=\"size-3.5\" />\n </button>\n </li>\n ))}\n </ul>\n <span className=\"shrink-0 text-xs text-muted-foreground\" data-testid=\"spotlight-count\">\n {count}\n </span>\n <Popover open={noteOpen} onOpenChange={setNoteOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant={note ? 'secondary' : 'ghost'}\n size=\"sm\"\n className=\"h-7 max-w-40 shrink-0 gap-1 rounded-full px-2 text-xs\"\n title={note ? `Note: ${note}` : 'Type a note to show as the title'}\n data-testid=\"spotlight-note\"\n >\n <StickyNote className=\"size-3.5 shrink-0\" />\n {note ? <span className=\"truncate\">{note}</span> : <span>Note</span>}\n </Button>\n </PopoverTrigger>\n <PopoverContent side=\"top\" className=\"w-72 p-2\">\n <Input\n autoFocus\n value={note}\n placeholder=\"Type a note\"\n onChange={(event) => actions.setNote(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') setNoteOpen(false)\n }}\n data-testid=\"spotlight-note-input\"\n />\n </PopoverContent>\n </Popover>\n <div className=\"w-44 shrink-0 [&_[role=combobox]]:h-7 [&_[role=combobox]]:rounded-full [&_[role=combobox]]:text-xs\">\n <DocumentPicker\n groups={switcher.groups}\n value=\"\"\n onValueChange={switcher.open}\n labels={{ placeholder: 'Clip another document' }}\n />\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 shrink-0 gap-1 rounded-full px-3 text-xs\"\n onClick={actions.show}\n title=\"Show the clips over the document (S)\"\n data-testid=\"spotlight-show\"\n >\n <Presentation className=\"size-3.5\" />\n Show\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7 shrink-0 rounded-full\"\n aria-label=\"More\"\n data-testid=\"spotlight-more\"\n >\n <MoreHorizontal className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" side=\"top\">\n <DropdownMenuItem onSelect={actions.keep} data-testid=\"spotlight-menu-keep\">\n <Presentation className=\"mr-2 size-4\" /> Keep as slide\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={actions.addToTray} data-testid=\"spotlight-menu-tray\">\n <Inbox className=\"mr-2 size-4\" /> Add to the presentation tray\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={actions.clear} data-testid=\"spotlight-menu-clear\">\n <Eraser className=\"mr-2 size-4\" /> Clear the clips\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n {showing && <SpotlightView fromRect={fromRect} />}\n </>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The document viewer's Clip mode: whether it is on, and its header controls. Clips made in it
|
|
3
|
-
*
|
|
4
|
-
* from one document to the next, so clips are gathered from
|
|
5
|
-
* the Presentation pill goes back to
|
|
3
|
+
* are gathered in the viewer's spotlight strip (`SpotlightStrip`: Show them over the document, or
|
|
4
|
+
* keep them as a slide); it stays on from one document to the next, so clips are gathered from
|
|
5
|
+
* several documents in a row. Beside it, the Presentation pill goes back to the presentation.
|
|
6
6
|
*/
|
|
7
7
|
import { type ReactNode } from 'react';
|
|
8
8
|
export declare function useViewerClipping(
|
|
@@ -11,4 +11,5 @@ clippable: boolean, compact: boolean): {
|
|
|
11
11
|
clipping: boolean;
|
|
12
12
|
stop: () => void;
|
|
13
13
|
button: ReactNode;
|
|
14
|
+
layer: ReactNode;
|
|
14
15
|
};
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import { useSpotlight } from "../../presentation/spotlight.js";
|
|
4
5
|
import { ClipButton } from "../../document-tools/DocumentToolButtons.js";
|
|
5
6
|
import { PresentationPill } from "./PresentationPill.js";
|
|
7
|
+
import { SpotlightLayer } from "./SpotlightLayer.js";
|
|
6
8
|
function useViewerClipping(clippable, compact) {
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
+
const on = useSpotlight((s) => s.clipping);
|
|
10
|
+
const setOn = useSpotlight((s) => s.setClipping);
|
|
11
|
+
const stop = useCallback(() => setOn(false), [setOn]);
|
|
9
12
|
const button = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10
13
|
/* @__PURE__ */ jsx(PresentationPill, { compact }),
|
|
11
14
|
clippable && /* @__PURE__ */ jsx(ClipButton, { active: on, compact, onClick: () => setOn(!on) })
|
|
12
15
|
] });
|
|
13
|
-
|
|
16
|
+
const layer = /* @__PURE__ */ jsx(SpotlightLayer, {});
|
|
17
|
+
return { clipping: on && clippable, stop, button, layer };
|
|
14
18
|
}
|
|
15
19
|
export {
|
|
16
20
|
useViewerClipping
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/presentation/useViewerClipping.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The document viewer's Clip mode: whether it is on, and its header controls. Clips made in it\n *
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * The document viewer's Clip mode: whether it is on, and its header controls. Clips made in it\n * are gathered in the viewer's spotlight strip (`SpotlightStrip`: Show them over the document, or\n * keep them as a slide); it stays on from one document to the next, so clips are gathered from\n * several documents in a row. Beside it, the Presentation pill goes back to the presentation.\n */\n\nimport { useCallback, type ReactNode } from 'react'\nimport { useSpotlight } from '../../presentation/spotlight'\nimport { ClipButton } from '../../document-tools/DocumentToolButtons'\nimport { PresentationPill } from './PresentationPill'\nimport { SpotlightLayer } from './SpotlightLayer'\n\nexport function useViewerClipping(\n /** A PDF, an image or a video is on screen. Clip mode shows over the viewer's other modes. */\n clippable: boolean,\n compact: boolean\n): { clipping: boolean; stop: () => void; button: ReactNode; layer: ReactNode } {\n // In the spotlight's store: it stays on while the viewer opens another document.\n const on = useSpotlight((s) => s.clipping)\n const setOn = useSpotlight((s) => s.setClipping)\n const stop = useCallback(() => setOn(false), [setOn])\n const button = (\n <>\n <PresentationPill compact={compact} />\n {clippable && <ClipButton active={on} compact={compact} onClick={() => setOn(!on)} />}\n </>\n )\n // Over the viewer's body: the gathered clips' strip, and the spotlight.\n const layer = <SpotlightLayer />\n return { clipping: on && clippable, stop, button, layer }\n}\n"],
|
|
5
|
+
"mappings": ";AAuBI,mBACE,KADF;AAhBJ,SAAS,mBAAmC;AAC5C,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAExB,SAAS,kBAEd,WACA,SAC8E;AAE9E,QAAM,KAAK,aAAa,CAAC,MAAM,EAAE,QAAQ;AACzC,QAAM,QAAQ,aAAa,CAAC,MAAM,EAAE,WAAW;AAC/C,QAAM,OAAO,YAAY,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC;AACpD,QAAM,SACJ,iCACE;AAAA,wBAAC,oBAAiB,SAAkB;AAAA,IACnC,aAAa,oBAAC,cAAW,QAAQ,IAAI,SAAkB,SAAS,MAAM,MAAM,CAAC,EAAE,GAAG;AAAA,KACrF;AAGF,QAAM,QAAQ,oBAAC,kBAAe;AAC9B,SAAO,EAAE,UAAU,MAAM,WAAW,MAAM,QAAQ,MAAM;AAC1D;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -425,7 +425,7 @@ function DocumentViewerContent({
|
|
|
425
425
|
isComparing
|
|
426
426
|
});
|
|
427
427
|
const clip = useViewerClipping(annotatable || !!pdfBlob && (isImage || isVideo), isCompact);
|
|
428
|
-
const clean = useCleanView();
|
|
428
|
+
const clean = useCleanView(clip.layer);
|
|
429
429
|
const signatureBanner = !isDraft && !liveKind && !snapshotDocumentId && /* @__PURE__ */ jsx(
|
|
430
430
|
SignatureRequestBanner,
|
|
431
431
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/viewer/ConnectedDocumentViewer.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The whole document viewer on the signed-in session: a document (or one of its versions, read\n * only) as its PDF, its text, the Word editor, a sheet, an image, a recording or a live artifact;\n * its versions and comparisons; markup, signing and signature requests; sharing, Email, Translate\n * and Finalise. Runs under any host (`useConnectedWorkspace`): the open document, tab and comparison\n * are the session state's, navigation the `BlocksEnvironment`'s, and what only the host knows comes\n * as its host config's `viewer`.\n */\n\nimport { lazy, Suspense, useCallback, useEffect, useRef, useState, type ReactNode } from 'react'\nimport {\n ChevronDown,\n Languages,\n Link2,\n Mail,\n MessageSquare,\n MessageSquarePlus,\n PenLine,\n Signature,\n Users,\n} from 'lucide-react'\nimport { useArbi, useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport { findVersion, parseVersionRef, versionLabel } from '@arbidocs/react/artifacts'\nimport {\n SIGNED_LOCKED_REASON,\n canAnnotate,\n useDocumentMarkup,\n useDocumentSignatures,\n useDocumentTools,\n type SignatureAppearance,\n} from '@arbidocs/react/document-tools'\nimport { XlsxViewer, cycleZoom } from '@arbidocs/react/viewers'\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n getEntityLabel,\n SharingEntity,\n} from '@arbidocs/react/ui'\nimport {\n ArtifactCodeView,\n ArtifactCompareBar,\n ArtifactPreview,\n VersionTimeline,\n} from '../../artifacts'\nimport { latestThreadOfDocument, useRegisterOpenDocument } from '@arbidocs/react/shell'\nimport { ShareControl } from '../../collaboration/sharing/ShareControl'\nimport {\n ViewerCaptureDraft,\n ViewerDraftKind,\n ViewerDraftTitle,\n ViewerRelatedDocuments,\n} from './drafts'\nimport {\n AnnotateButton,\n DownloadMarkupButton,\n FileShareDialog,\n MarkupNotices,\n MarkupViewNote,\n PlaceMySignatureMenuItems,\n ShowOriginalButton,\n SignDocumentDialog,\n SignedEditNote,\n SignatureRequestBanner,\n SignatureStatus,\n VersionSnapshotBar,\n} from '../../document-tools'\nimport { useViewerClipping } from '../presentation/useViewerClipping'\nimport { useCleanView } from './useCleanView'\nimport {\n DocumentLabelBar,\n PdfPageNav,\n ViewerControlBar,\n ViewerFrame,\n ViewerHeaderEnd,\n ViewerHeaderStart,\n ViewerImageActions,\n ViewerMessage,\n ViewerPageCounter,\n ViewerPane,\n ViewerStatusNote,\n ViewerTabBar,\n ViewerTitle,\n ViewerZoomControl,\n} from '../../files'\nimport { ErrorBoundary } from '../../components/ErrorBoundary'\nimport { fmtDate } from '../../lib/format'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { TabHeader } from '../../shell'\nimport { useConnectedWorkspace } from '../ConnectionProvider'\nimport { useConnectedConversations } from '../workspaceData'\nimport { ConnectedDocumentToolsProvider } from './ConnectedDocumentToolsProvider'\nimport { FinaliseTranslationButton } from './FinaliseTranslationButton'\nimport { useDocumentViewerSupport } from './support'\nimport { useImageCrop } from './useImageCrop'\nimport { ViewerCropModal } from './ViewerCropModal'\nimport { ViewerMoreMenu } from './ViewerMoreMenu'\nimport { useViewedDocument } from './useViewedDocument'\nimport { useViewerBlobs } from './useViewerBlobs'\nimport { useViewerTabs } from './useViewerTabs'\nimport { useViewerVersions } from './useViewerVersions'\nimport { VersionDropdown } from './VersionDropdown'\nimport { ParsedTextView } from './parsed/ParsedTextView'\nimport { ViewerPdfPane, type SignatureFlow } from './ViewerPdfPane'\n// The Word editor itself is its own chunk (`docxEditorChunk`), loaded when a Word document shows.\nimport { ConnectedNativeDocxEditor as NativeDocxEditor } from '../docx/ConnectedNativeDocxEditor'\nimport { canChangeVisibility } from '../../files/permissions'\nimport { SlidesTab } from './slidesTabChunk'\n\nconst StreamedWordArtifact = lazy(() =>\n import('../docx/ConnectedStreamedWordArtifact').then((m) => ({\n default: m.ConnectedStreamedWordArtifact,\n }))\n)\nconst NativeDocxComparison = lazy(() =>\n import('../docx/ConnectedNativeDocxComparison').then((m) => ({\n default: m.ConnectedNativeDocxComparison,\n }))\n)\n\nconst UPLOADED_NO_VERSIONS =\n 'No earlier versions yet. Replacing, editing or signing this file adds a new version here.'\n\nexport interface ConnectedDocumentViewerProps {\n /**\n * The document, or a version reference `doc-\u2026@v{n}` (a citation, a \"made from v2\" link): an\n * earlier version opens read-only. Default: the session state's viewing document.\n */\n documentId?: string\n /** Controls at the right end of the header (a panel's dock / pop-out switcher). */\n headerActions?: ReactNode\n /** Where html/react artifacts load their sandbox runtime from. */\n artifactRuntimeUrl?: string\n}\n\nexport function ConnectedDocumentViewer(props: ConnectedDocumentViewerProps) {\n const viewing = useArbiSessionState((s) => s.viewingDocument?.id)\n const openedId = props.documentId ?? viewing\n if (!openedId) return null\n // A viewer that throws (a PDF the browser cannot render, say) shows the error here, in the\n // viewer's place, instead of unmounting the whole app.\n return (\n <ErrorBoundary\n resetKey={openedId}\n labels={{ title: \"This document couldn't be displayed\" }}\n testId=\"document-viewer-error\"\n >\n <ConnectedDocumentToolsProvider>\n <DocumentViewerContent {...props} openedId={openedId} />\n </ConnectedDocumentToolsProvider>\n </ErrorBoundary>\n )\n}\n\nfunction DocumentViewerContent({\n openedId,\n headerActions,\n artifactRuntimeUrl = '/artifact-runtime/',\n}: ConnectedDocumentViewerProps & { openedId: string }) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n const support = useDocumentViewerSupport()\n const formatDate = support.formatDate ?? fmtDate\n const tools = useDocumentTools()\n const { openConversation, openNewConversation, notify } = useBlocksEnvironment()\n const { userId: currentUserId } = useConnectedWorkspace()\n // A document keeps one id for its whole life; its versions are inside it.\n const documentId = parseVersionRef(openedId).docId\n const [totalPages, setTotalPages] = useState<number>(0)\n const [isCompact, setIsCompact] = useState(false)\n // Zoom of the PDF (canvas scale) / text, as a multiplier of fit width; pinch, double-tap and the\n // zoom button all drive it. The text view's size is a reading preference for every document.\n const [pdfZoom, setPdfZoom] = useState(1)\n const {\n tab: zoomTab,\n textScale,\n compareId: compareDocumentId,\n } = useArbiSessionState((s) => s.documentViewer)\n const zoom = zoomTab === 'html' ? textScale : pdfZoom\n const setZoom = useCallback(\n (next: number | ((z: number) => number)) => {\n const value = typeof next === 'function' ? next(zoom) : next\n if (zoomTab === 'html') session.setDocumentViewer({ textScale: value })\n else setPdfZoom(value)\n },\n [zoomTab, session, zoom]\n )\n const [scrollTrigger, setScrollTrigger] = useState(0) // Incremented to scroll the viewers\n const containerRef = useRef<HTMLDivElement>(null)\n\n const viewingDocumentPage = useArbiSessionState((s) => s.viewingDocument?.page ?? null)\n const setViewingDocumentPage = (page: number) =>\n session.setViewingDocument({ id: openedId, page })\n const setViewingDocumentId = (id: string) => session.setViewingDocument({ id })\n const setActiveTab = (tab: Parameters<typeof session.setDocumentViewer>[0]['tab']) =>\n session.setDocumentViewer({ tab })\n const setCompareDocumentId = (id: string | null) => session.setDocumentViewer({ compareId: id })\n const { data: conversations } = useConnectedConversations()\n\n // An earlier version opened read-only (`doc-\u2026@v{n}`) from the Versions tab, a citation or a\n // \"made from\" link. Word documents show it in the Word editor, artifacts in theirs, everything\n // else as its PDF. The version on screen is the session's viewing id, not local state: the\n // viewer remounts when its panel moves to a new window, and the version must come along.\n const snapshotRef = parseVersionRef(openedId).version ? openedId : null\n // Every version of the document, oldest first. Every version of an artifact shares one name, so\n // both sides of a comparison get the timeline's \"v1/v2/v3\" label.\n const { versions, translations } = useViewerVersions(documentId)\n const currentVersionId = versions.find((v) => v.isCurrent)?.id ?? documentId\n // Opening the current version is the live document itself, not a read-only copy of it.\n const snapshotDocumentId = snapshotRef && snapshotRef !== currentVersionId ? snapshotRef : null\n const doc = useViewedDocument(documentId)\n const setSnapshotDocumentId = (ref: string | null) => setViewingDocumentId(ref ?? documentId)\n // Drafting mode: a thread bound to the open document (or the one it was made in) drafts in it,\n // also while an earlier version of it is on screen; a turn sent then brings the live document\n // back, where the assistant's edits appear. Being open binds no chat to it.\n useRegisterOpenDocument({\n documentId: doc.savedDocumentId,\n shownId: openedId,\n showLive: () => setViewingDocumentId(documentId),\n workspaceId: doc.workspaceId,\n conversationId: doc.documentData?.conversation_ext_id ?? null,\n })\n const {\n documentData,\n streamingDoc,\n isStreaming,\n draftDoc,\n isPresentation,\n isDraft,\n isCaptureDraft,\n labelSummaries,\n isImage,\n isVideo,\n isAudio,\n isMedia,\n isArtifact,\n liveKind,\n liveSource,\n isDocx,\n isXlsx,\n isDownloadOnly,\n } = doc\n // The thread bound to this document: its latest one, else a new chat bound to it. The document\n // stays on screen beside it.\n const chatAboutDocument = () => {\n const savedId = doc.savedDocumentId\n if (!savedId) return\n const latest = latestThreadOfDocument(conversations, savedId)\n if (latest) {\n openConversation(latest, { keepDocumentOpen: true })\n return\n }\n // Opening a new chat starts it unbound; it is bound after.\n openNewConversation({ keepDocumentOpen: true })\n session.setNewChatDocumentId(savedId)\n }\n // A thread by its title, for the threads a document (and each version) was made in.\n const threadTitle = (id: string) =>\n conversations.find((c) => c.external_id === id)?.title?.trim() || 'Its thread'\n // The thread a generated document was made in (none for an upload).\n const madeInId = documentData?.conversation_ext_id ?? null\n const madeIn = madeInId ? { id: madeInId, title: threadTitle(madeInId) } : null\n const pdfSnapshotId = snapshotDocumentId && (!isArtifact || isDocx) ? snapshotDocumentId : null\n // The document on screen: an earlier version when one is open, else the current one.\n const shownDocumentId = pdfSnapshotId || documentId\n const blobs = useViewerBlobs(shownDocumentId, doc)\n const [minimumPdfVersion, setMinimumPdfVersion] = useState<number | null>(null)\n useEffect(() => setMinimumPdfVersion(null), [documentId])\n const versionReady =\n !!pdfSnapshotId ||\n minimumPdfVersion === null ||\n (documentData?.current_version ?? 0) >= minimumPdfVersion\n const { xlsxBlob, xlsxError, handleDirectDownload } = blobs\n const pdfBlob = versionReady ? blobs.pdfBlob : null\n const pdfVerified = !!pdfBlob && blobs.pdfVerified !== false\n // Annotation mode for the PDF view; off for every newly opened document.\n const [annotating, setAnnotating] = useState(false)\n const [sharingFile, setSharingFile] = useState(false)\n useEffect(() => setAnnotating(false), [documentId])\n // My signature: one's saved signature or initials, to place as a picture stamp in the markup.\n const [placeMark, setPlaceMark] = useState<{ image: string; label: string; key: number } | null>(\n null\n )\n // Translations are listed with the versions (each is its own document), so they open the tab too.\n const hasHistory =\n versions.length > 1 || (documentData?.current_version ?? 1) > 1 || translations.length > 0\n const {\n activeTab,\n handleTabChange: changeTab,\n viewerTabs,\n } = useViewerTabs(doc, isCompact, hasHistory)\n const saveWordRef = useRef<(() => Promise<boolean | number>) | null>(null)\n const transitionPending = useRef(false)\n const transitionKey = JSON.stringify([openedId, doc.workspaceId])\n const transitionScope = useRef({ key: transitionKey, generation: 0 })\n if (transitionScope.current.key !== transitionKey) {\n transitionScope.current = {\n key: transitionKey,\n generation: transitionScope.current.generation + 1,\n }\n }\n useEffect(\n () => () => {\n transitionScope.current.generation += 1\n },\n []\n )\n const requestViewerTransition = async (transition: () => void): Promise<boolean> => {\n if (transitionPending.current) return false\n const leavingWord =\n isDocx &&\n !isDraft &&\n !isStreaming &&\n !snapshotDocumentId &&\n (activeTab === 'docx' || (isArtifact && !liveKind && activeTab === 'edit'))\n if (leavingWord) {\n transitionPending.current = true\n const generation = transitionScope.current.generation\n try {\n const saved = saveWordRef.current && (await saveWordRef.current())\n if (!saved) {\n notify('Could not save the current document. Stay in the editor and try again.', 'error')\n return false\n }\n if (generation !== transitionScope.current.generation) return false\n if (typeof saved === 'number') setMinimumPdfVersion(saved)\n } finally {\n transitionPending.current = false\n }\n }\n transition()\n return true\n }\n const handleTabChange = (tab: string) => {\n if (tab === activeTab) return\n void requestViewerTransition(() => changeTab(tab))\n }\n const crop = useImageCrop(\n documentId,\n documentData?.file_name,\n pdfBlob,\n documentData?.workspace_ext_id\n )\n // Signing: choose where the signature goes (placing), then the Sign dialog.\n const [placingSignature, setPlacingSignature] = useState(false)\n const [signAppearance, setSignAppearance] = useState<SignatureAppearance | undefined>()\n const [isSignOpen, setIsSignOpen] = useState(false)\n const signingScope = JSON.stringify([\n documentId,\n snapshotDocumentId,\n documentData?.current_version,\n ])\n const signingScopeRef = useRef(signingScope)\n const signingScopeMatches = signingScopeRef.current === signingScope\n // Leaving the placement when another version opens or returns: it belongs to the copy on screen.\n useEffect(() => {\n setPlacingSignature(false)\n setIsSignOpen(false)\n setSignAppearance(undefined)\n signingScopeRef.current = signingScope\n }, [signingScope])\n // A signature request: the author placing fields ('prepare'), or a signer walked through theirs.\n const [signatureFlow, setSignatureFlow] = useState<SignatureFlow>(null)\n useEffect(() => setSignatureFlow(null), [signingScope])\n const signatureDocumentId =\n pdfSnapshotId ||\n (documentData?.current_version ? `${documentId}@v${documentData.current_version}` : documentId)\n const { data: signatureStatus } = useDocumentSignatures(\n signatureDocumentId,\n !isDraft && !liveKind\n )\n\n // The Word editor on the current version: the editor's own ribbon says \"Co-edit mode\", so the\n // header carries no version label and, when narrow, no title row above the ribbon.\n const isCoEditing =\n !snapshotDocumentId &&\n !compareDocumentId &&\n !isDraft &&\n ((activeTab === 'docx' && isDocx) ||\n (activeTab === 'slides' && isPresentation) ||\n (activeTab === 'edit' && isArtifact && !liveKind && !isStreaming))\n const currentVersionLabel = isCoEditing\n ? undefined\n : !snapshotDocumentId && !compareDocumentId && (isDocx || (isArtifact && !liveKind))\n ? 'Live'\n : versionLabel(versions, snapshotDocumentId || documentId)\n const compareVersionLabel = versionLabel(versions, compareDocumentId)\n const snapshotNumber = findVersion(versions, snapshotDocumentId)?.number\n // The markup of the version on screen: the default view when it has any (\"Show original\" hides).\n const pdfSnapshotNumber = pdfSnapshotId\n ? (parseVersionRef(pdfSnapshotId).version ?? undefined)\n : undefined\n // A signed version is locked: only a further signature changes it. Its marks stay in the markup\n // layer (never in its PDF), and editing its content saves a new, unsigned version.\n const isSigned = !!signatureStatus?.signed\n const markup = useDocumentMarkup(documentData, pdfSnapshotNumber, isSigned)\n\n // Detect container width changes (640px = the sm: breakpoint).\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) setIsCompact(entry.contentRect.width < 640)\n })\n resizeObserver.observe(container)\n return () => resizeObserver.disconnect()\n }, [])\n\n const handleLoadSuccess = useCallback((numPages: number) => setTotalPages(numPages), [])\n\n // Go to a page: the counter, or one step from the arrows.\n const goToPage = (page: number) => {\n setViewingDocumentPage(page)\n setScrollTrigger((prev) => prev + 1)\n }\n const stepPage = (delta: number) => {\n const next = (viewingDocumentPage || 1) + delta\n if (next >= 1 && next <= totalPages) goToPage(next)\n }\n\n const documentTitle =\n streamingDoc?.title ||\n draftDoc?.title ||\n documentData?.doc_metadata?.title ||\n documentData?.file_name ||\n 'Document'\n\n // The page / zoom controls, shared by the PDF and the text view. They sit in the control bar\n // under the body, so they never cover the text being read.\n const pageNav = totalPages > 0 && (\n <>\n <ViewerZoomControl zoom={zoom} onCycle={() => setZoom(cycleZoom(zoom))} />\n <PdfPageNav\n canPrev={(viewingDocumentPage || 1) > 1}\n canNext={(viewingDocumentPage || 1) < totalPages}\n onPrev={() => stepPage(-1)}\n onNext={() => stepPage(1)}\n counter={\n <ViewerPageCounter page={viewingDocumentPage || 1} total={totalPages} onGoTo={goToPage} />\n }\n />\n </>\n )\n\n // Compare: a \"Compare vs. [doc]\" row of its own below the tab/title bar (a docked panel is\n // narrow), with the flip-direction arrow and the way out.\n const isComparing = !!compareDocumentId\n const compareTarget = compareDocumentId ? parseVersionRef(compareDocumentId).docId : null\n const compareIndicator = isComparing && compareTarget && (\n <ArtifactCompareBar\n compareTarget={support.renderDocumentPill?.(compareTarget) ?? compareTarget}\n versionLabel={compareVersionLabel}\n mode=\"flip\"\n showTrackChanges={false}\n onToggleTrackChanges={() => {}}\n onFlip={() => {\n setViewingDocumentId(compareDocumentId!)\n setCompareDocumentId(documentId)\n }}\n onStop={() => setCompareDocumentId(null)}\n />\n )\n\n // Document name block: the name, related documents and status notes. Roomy headers keep it on\n // the tab row; a narrow (phone / docked) header gives it a row of its own so the name is never\n // cut down to a couple of letters by the tabs and actions.\n const titleBlock = (\n <>\n {/* A draft gets an editable name + auto-name toggle instead of the plain read-only name. */}\n {isDraft ? (\n <ViewerDraftTitle documentId={documentId} />\n ) : (\n <ViewerTitle\n title={documentTitle}\n versionLabel={currentVersionLabel}\n shrink={!!liveKind || isCompact}\n />\n )}\n {/* The narrow header's Share is icon-only, so the state is spelled out here as text. */}\n {isCompact && !isDraft && documentData?.shared && (\n <SharingEntity shared variant=\"icon\" data-testid=\"document-shared-status\" />\n )}\n {/* Likewise \"Show original\" is a bare page icon there: say which view is on screen. */}\n {isCompact &&\n activeTab === 'pdf' &&\n pdfBlob &&\n markup.hasMarkup &&\n !annotating &&\n !placingSignature && (\n <MarkupViewNote\n showOriginal={markup.showOriginal}\n onToggle={() => markup.setShowOriginal((on) => !on)}\n />\n )}\n {/* Related documents, except during a comparison (its own row says which). */}\n {!isComparing && !liveKind && documentData && (\n <ViewerRelatedDocuments document={documentData} />\n )}\n {isStreaming && <ViewerStatusNote pulse>streaming...</ViewerStatusNote>}\n {/* Nothing is generating: this document simply does not exist on the backend yet. */}\n {isDraft && (\n <ViewerStatusNote testId=\"draft-unsaved-indicator\">Draft \u2014 not saved</ViewerStatusNote>\n )}\n {signatureStatus?.signed && (\n <SignatureStatus status={signatureStatus} formatDate={formatDate} />\n )}\n </>\n )\n\n const leftContent = (\n <ViewerHeaderStart>\n {isDraft ? (\n // A draft's kind replaces the tabs: neither Versions nor the text view means anything\n // before the first save.\n <ViewerDraftKind documentId={documentId} />\n ) : (\n <>\n <ViewerTabBar\n tabs={viewerTabs.filter((tab) => tab.id !== 'versions')}\n activeId={activeTab}\n onChange={handleTabChange}\n />\n {(isArtifact || isDocx || hasHistory) && !liveKind && !isComparing && (\n <VersionDropdown\n versions={versions}\n activeId={\n snapshotDocumentId ??\n (currentVersionId === documentId && documentData?.current_version\n ? `${documentId}@v${documentData.current_version}`\n : currentVersionId)\n }\n isSnapshot={!!snapshotDocumentId}\n onOpen={(id) => {\n void requestViewerTransition(() => {\n setSnapshotDocumentId(id === currentVersionId ? null : id)\n if (activeTab === 'versions')\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : 'pdf')\n })\n }}\n onHistory={() => handleTabChange('versions')}\n />\n )}\n </>\n )}\n {!isCompact && titleBlock}\n </ViewerHeaderStart>\n )\n\n const annotatable = canAnnotate({\n activeTab,\n hasPdf: pdfVerified,\n isImage,\n isVideo,\n isAudio,\n isDownloadOnly,\n isDraft,\n isStreaming,\n isSnapshot: !!snapshotDocumentId,\n isComparing,\n })\n const clip = useViewerClipping(annotatable || (!!pdfBlob && (isImage || isVideo)), isCompact)\n const clean = useCleanView()\n\n // A request waiting for this user's signature, or their own in flight: shown over the PDF and\n // the Word editor alike; signing happens on the PDF.\n const signatureBanner = !isDraft && !liveKind && !snapshotDocumentId && (\n <SignatureRequestBanner\n documentId={documentId}\n hidden={!!signatureFlow}\n onSign={(request) => {\n void requestViewerTransition(() => {\n setAnnotating(false)\n setPlacingSignature(false)\n if (activeTab !== 'pdf') changeTab('pdf')\n setSignatureFlow({ kind: 'sign', request })\n })\n }}\n onEditDraft={(draft) => {\n void requestViewerTransition(() => {\n if (activeTab !== 'pdf') changeTab('pdf')\n setSignatureFlow({ kind: 'prepare', draft })\n })\n }}\n />\n )\n\n const share = () => {\n const name = (liveKind ? documentTitle : documentData?.file_name) || undefined\n if (support.share) {\n support.share({ id: documentId, name, isPrivate: !documentData?.shared })\n return\n }\n void arbi.documents\n .update([{ external_id: documentId, shared: !documentData?.shared }])\n .then(() => tools.onDocumentsChanged?.([documentId], 'markup'))\n .catch(() => notify(\"Couldn't change who can see this document\", 'error'))\n }\n const shownRef = snapshotDocumentId || documentId\n\n const rightContent = (\n <ViewerHeaderEnd isCompact={isCompact}>\n {/* Annotate: only for a PDF on screen (text and Word files are shown as a PDF too). Marks\n sit in a layer beside the document; Freeze saves a separate copy with them built in. */}\n {annotatable && (\n <AnnotateButton\n active={annotating}\n compact={isCompact}\n onClick={() => {\n setPlacingSignature(false)\n clip.stop()\n markup.setShowOriginal(false)\n setAnnotating((on) => !on)\n }}\n />\n )}\n {clip.button}\n {/* The markup is the default view; \"Show original\" shows the untouched file. */}\n {activeTab === 'pdf' && pdfBlob && !placingSignature && (markup.hasMarkup || annotating) && (\n <ShowOriginalButton\n active={markup.showOriginal}\n compact={isCompact}\n onClick={() => {\n setAnnotating(false)\n markup.setShowOriginal((on) => !on)\n }}\n />\n )}\n {activeTab === 'pdf' && markup.hasMarkup && !annotating && (\n <DownloadMarkupButton\n onClick={() => void markup.downloadMarkup()}\n // A signed version is locked: Download serves the signed file as it is.\n disabledReason={isSigned ? SIGNED_LOCKED_REASON : undefined}\n />\n )}\n {/* Image actions: start a generation from this image, or crop it into a new document. */}\n {activeTab === 'pdf' && isImage && pdfBlob && (\n <ViewerImageActions\n compact={isCompact}\n onUseAsReference={\n support.useImageAsReference ? () => support.useImageAsReference!(documentId) : undefined\n }\n onCrop={crop.handleOpenCrop}\n />\n )}\n {/* The thread it was made in: open it at the answer that made it. */}\n {madeIn && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size={isCompact ? 'icon' : 'sm'}\n onClick={() =>\n openConversation(madeIn.id, {\n messageId: documentData?.source_message_ext_id ?? undefined,\n })\n }\n title={`Open the thread it was made in: ${madeIn.title}`}\n aria-label={`Open the thread it was made in: ${madeIn.title}`}\n data-testid=\"document-open-thread\"\n >\n <MessageSquare className=\"size-4\" />\n {!isCompact && <span className=\"max-w-[10rem] truncate\">{madeIn.title}</span>}\n </Button>\n )}\n {documentId && documentData && !isDraft && !isStreaming && (\n <>\n <FileShareDialog\n open={sharingFile}\n onOpenChange={setSharingFile}\n documentId={documentId}\n version={pdfSnapshotNumber ?? documentData.current_version ?? 1}\n />\n </>\n )}\n {/* Chat about this document: the thread bound to it (its questions edit it), the latest one\n or a new one. Only such a thread drafts in a document: one merely open binds no chat. */}\n {doc.savedDocumentId && !snapshotDocumentId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size={isCompact ? 'icon' : 'sm'}\n onClick={chatAboutDocument}\n title=\"Chat about this document: a thread that works in it, with edits as tracked changes\"\n aria-label=\"Chat about this document\"\n data-testid=\"document-chat-about\"\n className=\"pointer-coarse:min-h-11\"\n >\n <MessageSquarePlus className=\"size-4\" />\n {!isCompact && <span className=\"ml-1\">Chat</span>}\n </Button>\n )}\n {/* Share always asks first (the host's share dialog), so a click never changes who can see\n the file by surprise. */}\n {documentId && doc.workspaceId && (\n <ShareControl\n state={documentData?.shared ? 'shared' : 'private'}\n onToggle={share}\n disabled={!canChangeVisibility(documentData, currentUserId)}\n disabledTooltip=\"Only the owner can change visibility\"\n tooltip={\n documentData?.shared\n ? 'Shared with the workspace \u2014 click to share with specific people'\n : 'Share with the workspace, then optionally notify specific people by email'\n }\n variant=\"outline\"\n compact={isCompact}\n showState={!isCompact}\n labels={{\n shared: getEntityLabel('WORKSPACE'),\n private: 'Only you',\n mixed: 'Partly shared',\n }}\n testId=\"share-document-button\"\n stateTestId=\"document-title-shared-indicator\"\n />\n )}\n {/* Finalise (a translation): its current version saved as a new labelled PDF. */}\n {!isStreaming && !snapshotDocumentId && (\n <FinaliseTranslationButton document={documentData ?? undefined} isCompact={isCompact} />\n )}\n {/* Every signing action starts in one menu: sign yourself, save/place a mark, or request\n signatures from others. */}\n {annotatable && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant={\n placingSignature || signatureFlow?.kind === 'prepare' ? 'default' : 'outline'\n }\n size={isCompact ? 'icon' : 'sm'}\n aria-label=\"Sign\"\n title=\"Sign or request signatures\"\n data-testid=\"signing-menu-trigger\"\n className=\"pointer-coarse:min-h-11\"\n >\n <Signature className=\"size-4\" />\n {!isCompact && <span className=\"ml-1\">Sign</span>}\n <ChevronDown className=\"ml-1 size-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" forceMount>\n <DropdownMenuItem\n data-testid=\"sign-document-button\"\n onSelect={() => {\n setAnnotating(false)\n if (isSigned) {\n setSignatureFlow(null)\n setPlacingSignature((on) => !on)\n } else {\n setPlacingSignature(false)\n setSignatureFlow({ kind: 'prepare', self: true })\n }\n }}\n >\n <PenLine className=\"mr-2 size-4\" /> Sign this document\n </DropdownMenuItem>\n {!isSigned && (\n <>\n <PlaceMySignatureMenuItems\n onPlace={(mark) => {\n setPlacingSignature(false)\n setSignatureFlow(null)\n markup.setShowOriginal(false)\n setAnnotating(true)\n setPlaceMark({ ...mark, key: Date.now() })\n }}\n />\n <DropdownMenuItem\n data-testid=\"request-signatures-button\"\n onSelect={() => {\n setAnnotating(false)\n setPlacingSignature(false)\n setSignatureFlow(signatureFlow?.kind === 'prepare' ? null : { kind: 'prepare' })\n }}\n >\n <Users className=\"mr-2 size-4\" /> Ask someone to sign\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {isSignOpen && pdfBlob && pdfVerified && signingScopeMatches && (\n <SignDocumentDialog\n open={isSignOpen}\n onOpenChange={setIsSignOpen}\n documentId={documentId}\n pdfBlob={pdfBlob}\n // The PDF on screen is the current version's (an earlier one cannot be signed): the\n // server refuses if another version has landed since.\n version={documentData?.current_version ?? undefined}\n appearance={signAppearance}\n />\n )}\n <ViewerMoreMenu\n compact={isCompact}\n items={[\n ...(documentId && documentData && !isDraft && !isStreaming\n ? [\n {\n key: 'share-file',\n label: 'Share file\u2026',\n icon: <Link2 className=\"size-4\" />,\n description: 'Send a link to this version of the file',\n onSelect: () => setSharingFile(true),\n testId: 'share-file-button',\n },\n ]\n : []),\n ...(tools.emailDocument && !isDraft && !isStreaming && documentData?.file_name\n ? [\n {\n key: 'email',\n label: 'Email\u2026',\n icon: <Mail className=\"size-4\" />,\n description: 'Email this document (attached)',\n onSelect: () => tools.emailDocument?.(shownRef),\n testId: 'email-document-button',\n },\n ]\n : []),\n ...(support.translate &&\n !isDraft &&\n !isStreaming &&\n !liveKind &&\n !isImage &&\n documentData?.file_name\n ? [\n {\n key: 'translate',\n label: 'Translate\u2026',\n icon: <Languages className=\"size-4\" />,\n description: 'A new editable document, original and translation side by side',\n onSelect: () => support.translate!(shownRef),\n testId: 'translate-document-button',\n },\n ]\n : []),\n ]}\n />\n {headerActions}\n </ViewerHeaderEnd>\n )\n\n const viewerProps = {\n currentPage: viewingDocumentPage || undefined,\n onLoadSuccess: handleLoadSuccess,\n scrollTrigger,\n zoom,\n onZoomChange: setZoom,\n }\n\n return (\n <ViewerFrame\n frameRef={containerRef}\n contentId={documentId}\n header={\n <>\n <TabHeader\n tabs={[]}\n activeTabId={activeTab}\n onTabChange={handleTabChange}\n leftContent={leftContent}\n rightContent={rightContent}\n variant=\"underline\"\n />\n {isCompact && !isCoEditing && (\n <div data-slot=\"viewer-title-row\" className=\"flex min-w-0 items-center gap-2 px-3 pb-2\">\n {titleBlock}\n </div>\n )}\n {/* In the sticky header, not the content area: the PDF view scrolls its first page into\n view, which scrolls a bar above it out of sight. */}\n {snapshotDocumentId && (\n <VersionSnapshotBar\n versionNumber={snapshotNumber}\n live={isDocx || isArtifact}\n onAsk={\n support.askAboutVersion\n ? () => support.askAboutVersion!(snapshotDocumentId)\n : undefined\n }\n onReturn={() => setSnapshotDocumentId(null)}\n />\n )}\n </>\n }\n compareRow={isComparing ? compareIndicator || undefined : undefined}\n {...clean.frame}\n footer={<ViewerCropModal crop={crop} />}\n >\n {isComparing && (\n <Suspense fallback={<ViewerMessage>Loading comparison\u2026</ViewerMessage>}>\n <NativeDocxComparison\n baseId={compareDocumentId!}\n revisedId={documentId}\n title={documentTitle}\n />\n </Suspense>\n )}\n {/* A capture draft (photo/video/audio) has no backend document at all until it is saved:\n its recorder takes over the whole content area. */}\n {isCaptureDraft && <ViewerCaptureDraft documentId={documentId} />}\n\n {/* Media stay mounted (hidden) on the text tab, so playback goes on while reading the\n transcript. */}\n {!isCaptureDraft &&\n (activeTab === 'pdf' || (isMedia && activeTab === 'html')) &&\n (!isArtifact || (isDocx && !isDraft && !isStreaming && !liveKind)) &&\n !isComparing && (\n <ViewerPane hidden={activeTab !== 'pdf'}>\n {/* The labels are the document's, whichever view it is read in: the PDF gets the\n chips without the passage stepper (no parsed passages to walk here). */}\n {!clean.on && <DocumentLabelBar summaries={labelSummaries} />}\n {!clean.on && !isMedia && !isImage && signatureBanner}\n {!clean.on && activeTab === 'pdf' && pdfBlob && !pdfVerified && (\n <ViewerMessage>\n Offline copy: its version cannot be verified. Reconnect before signing.{' '}\n <button type=\"button\" onClick={() => void blobs.retryPdf()} className=\"underline\">\n Retry loading the current PDF\n </button>\n </ViewerMessage>\n )}\n {!clean.on && activeTab === 'pdf' && !isMedia && !isImage && (\n <MarkupNotices\n legacyPrompt={markup.legacyPrompt}\n olderNote={markup.olderNote}\n onOpenVersion={(n) => setSnapshotDocumentId(`${documentId}@v${n}`)}\n />\n )}\n <ViewerControlBar controls={!clean.on && activeTab === 'pdf' && pageNav}>\n <ViewerPdfPane\n documentId={documentId}\n doc={doc}\n pdfBlob={pdfBlob}\n isPdfLoading={!versionReady || blobs.isPdfLoading}\n pdfError={blobs.pdfError}\n onDownload={() => void handleDirectDownload()}\n viewerProps={viewerProps}\n signatureFlow={pdfVerified && signingScopeMatches ? signatureFlow : null}\n onSignatureFlow={setSignatureFlow}\n currentUserId={currentUserId}\n placingSignature={pdfVerified && signingScopeMatches && placingSignature}\n onPlacingDone={(appearance) => {\n setPlacingSignature(false)\n if (!appearance) return\n setSignAppearance(appearance)\n setIsSignOpen(true)\n }}\n annotating={annotating}\n clipping={clip.clipping}\n markup={markup}\n pdfSnapshotNumber={pdfSnapshotNumber}\n isSigned={isSigned}\n placeMark={placeMark}\n />\n </ViewerControlBar>\n </ViewerPane>\n )}\n\n {activeTab === 'preview' && isArtifact && liveKind && (\n // The preview loads its JSX compiler on first use, so it stays out of the main bundle.\n <ArtifactPreview\n kind={liveKind}\n source={liveSource}\n isStreaming={isStreaming}\n runtimeUrl={artifactRuntimeUrl}\n />\n )}\n\n {activeTab === 'edit' && isArtifact && liveKind && (\n <ArtifactCodeView source={liveSource} fileName={documentData?.file_name ?? undefined} />\n )}\n\n {/* A document draft is stored as DOCX: once generation ends the Word editor opens the stored\n document. Only a draft still being generated shows the streamed preview. */}\n {activeTab === 'edit' && isArtifact && !liveKind && !isStreaming && !isComparing && (\n <Suspense fallback={<ViewerMessage>Loading editor\u2026</ViewerMessage>}>\n {isSigned && !snapshotDocumentId && <SignedEditNote />}\n <NativeDocxEditor\n key={`${snapshotDocumentId || documentId}-${snapshotDocumentId ? 'snapshot' : 'live'}`}\n documentId={snapshotDocumentId || documentId}\n title={documentTitle}\n draftContent={isDraft ? draftDoc?.content || '' : undefined}\n snapshot={!!snapshotDocumentId}\n saveRef={saveWordRef}\n onSaved={(id) => {\n if (!isDraft) return\n session.clearDraftDocument(documentId)\n setViewingDocumentId(id)\n }}\n />\n </Suspense>\n )}\n\n {activeTab === 'versions' && (isArtifact || isDocx || hasHistory) && !isComparing && (\n <VersionTimeline\n // Each version made in a thread names it and opens it at the turn that made it.\n versions={versions.map((v) => ({\n ...v,\n madeIn: v.thread\n ? {\n label: threadTitle(v.thread.conversationId),\n onOpen: () =>\n openConversation(v.thread!.conversationId, {\n messageId: v.thread!.messageId ?? undefined,\n }),\n }\n : null,\n }))}\n currentId={currentVersionId}\n live={!!liveKind}\n // An uploaded file is not a draft: its versions come from replacing, editing or signing.\n labels={isArtifact ? undefined : { emptyDocument: UPLOADED_NO_VERSIONS }}\n formatDate={formatDate}\n onOpen={(id) => {\n // The current version is the live document itself, not a read-only copy of it.\n setSnapshotDocumentId(id === currentVersionId ? null : id)\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : 'pdf')\n }}\n onCompare={(id) => session.setDocumentViewer({ compareId: id, tab: 'html' })}\n translations={translations}\n onOpenTranslation={(id) => setViewingDocumentId(id)}\n />\n )}\n\n {activeTab === 'xlsx' &&\n isXlsx &&\n (xlsxBlob ? (\n <XlsxViewer blob={xlsxBlob} />\n ) : (\n <ViewerMessage>\n {xlsxError ? 'Failed to load spreadsheet' : 'Loading spreadsheet...'}\n </ViewerMessage>\n ))}\n\n {activeTab === 'slides' && isPresentation && (\n <Suspense fallback={<ViewerMessage>Loading slides\u2026</ViewerMessage>}>\n <SlidesTab\n documentId={documentId}\n version={snapshotDocumentId ? snapshotNumber : undefined}\n currentVersion={documentData?.current_version ?? undefined}\n draftTitle={isDraft ? (draftDoc?.title ?? '') : undefined}\n />\n </Suspense>\n )}\n {activeTab === 'docx' && isDocx && !isComparing && (\n <Suspense fallback={<ViewerMessage>Loading editor\u2026</ViewerMessage>}>\n {signatureBanner}\n {isSigned && !snapshotDocumentId && <SignedEditNote />}\n <NativeDocxEditor\n key={`${snapshotDocumentId || documentId}-${snapshotDocumentId ? 'snapshot' : 'live'}`}\n documentId={snapshotDocumentId || documentId}\n title={documentTitle}\n snapshot={!!snapshotDocumentId}\n saveRef={saveWordRef}\n />\n </Suspense>\n )}\n\n {streamingDoc &&\n isStreaming &&\n isArtifact &&\n !liveKind &&\n !isComparing &&\n (activeTab === 'html' || activeTab === 'edit') && (\n <Suspense fallback={<ViewerMessage>Opening draft\u2026</ViewerMessage>}>\n <StreamedWordArtifact\n key={documentId}\n documentId={documentId.startsWith('doc-') ? documentId : undefined}\n title={documentTitle}\n content={streamingDoc.content}\n busy={isStreaming}\n />\n </Suspense>\n )}\n\n {!isCaptureDraft &&\n !isComparing &&\n activeTab === 'html' &&\n !(isStreaming && isArtifact && !liveKind) && (\n <ViewerPane>\n <ViewerControlBar controls={pageNav}>\n <ParsedTextView\n documentId={pdfSnapshotId || documentId}\n onLoadSuccess={handleLoadSuccess}\n scrollTrigger={scrollTrigger}\n zoom={zoom}\n onZoomChange={setZoom}\n />\n </ViewerControlBar>\n </ViewerPane>\n )}\n </ViewerFrame>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * The whole document viewer on the signed-in session: a document (or one of its versions, read\n * only) as its PDF, its text, the Word editor, a sheet, an image, a recording or a live artifact;\n * its versions and comparisons; markup, signing and signature requests; sharing, Email, Translate\n * and Finalise. Runs under any host (`useConnectedWorkspace`): the open document, tab and comparison\n * are the session state's, navigation the `BlocksEnvironment`'s, and what only the host knows comes\n * as its host config's `viewer`.\n */\n\nimport { lazy, Suspense, useCallback, useEffect, useRef, useState, type ReactNode } from 'react'\nimport {\n ChevronDown,\n Languages,\n Link2,\n Mail,\n MessageSquare,\n MessageSquarePlus,\n PenLine,\n Signature,\n Users,\n} from 'lucide-react'\nimport { useArbi, useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport { findVersion, parseVersionRef, versionLabel } from '@arbidocs/react/artifacts'\nimport {\n SIGNED_LOCKED_REASON,\n canAnnotate,\n useDocumentMarkup,\n useDocumentSignatures,\n useDocumentTools,\n type SignatureAppearance,\n} from '@arbidocs/react/document-tools'\nimport { XlsxViewer, cycleZoom } from '@arbidocs/react/viewers'\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n getEntityLabel,\n SharingEntity,\n} from '@arbidocs/react/ui'\nimport {\n ArtifactCodeView,\n ArtifactCompareBar,\n ArtifactPreview,\n VersionTimeline,\n} from '../../artifacts'\nimport { latestThreadOfDocument, useRegisterOpenDocument } from '@arbidocs/react/shell'\nimport { ShareControl } from '../../collaboration/sharing/ShareControl'\nimport {\n ViewerCaptureDraft,\n ViewerDraftKind,\n ViewerDraftTitle,\n ViewerRelatedDocuments,\n} from './drafts'\nimport {\n AnnotateButton,\n DownloadMarkupButton,\n FileShareDialog,\n MarkupNotices,\n MarkupViewNote,\n PlaceMySignatureMenuItems,\n ShowOriginalButton,\n SignDocumentDialog,\n SignedEditNote,\n SignatureRequestBanner,\n SignatureStatus,\n VersionSnapshotBar,\n} from '../../document-tools'\nimport { useViewerClipping } from '../presentation/useViewerClipping'\nimport { useCleanView } from './useCleanView'\nimport {\n DocumentLabelBar,\n PdfPageNav,\n ViewerControlBar,\n ViewerFrame,\n ViewerHeaderEnd,\n ViewerHeaderStart,\n ViewerImageActions,\n ViewerMessage,\n ViewerPageCounter,\n ViewerPane,\n ViewerStatusNote,\n ViewerTabBar,\n ViewerTitle,\n ViewerZoomControl,\n} from '../../files'\nimport { ErrorBoundary } from '../../components/ErrorBoundary'\nimport { fmtDate } from '../../lib/format'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { TabHeader } from '../../shell'\nimport { useConnectedWorkspace } from '../ConnectionProvider'\nimport { useConnectedConversations } from '../workspaceData'\nimport { ConnectedDocumentToolsProvider } from './ConnectedDocumentToolsProvider'\nimport { FinaliseTranslationButton } from './FinaliseTranslationButton'\nimport { useDocumentViewerSupport } from './support'\nimport { useImageCrop } from './useImageCrop'\nimport { ViewerCropModal } from './ViewerCropModal'\nimport { ViewerMoreMenu } from './ViewerMoreMenu'\nimport { useViewedDocument } from './useViewedDocument'\nimport { useViewerBlobs } from './useViewerBlobs'\nimport { useViewerTabs } from './useViewerTabs'\nimport { useViewerVersions } from './useViewerVersions'\nimport { VersionDropdown } from './VersionDropdown'\nimport { ParsedTextView } from './parsed/ParsedTextView'\nimport { ViewerPdfPane, type SignatureFlow } from './ViewerPdfPane'\n// The Word editor itself is its own chunk (`docxEditorChunk`), loaded when a Word document shows.\nimport { ConnectedNativeDocxEditor as NativeDocxEditor } from '../docx/ConnectedNativeDocxEditor'\nimport { canChangeVisibility } from '../../files/permissions'\nimport { SlidesTab } from './slidesTabChunk'\n\nconst StreamedWordArtifact = lazy(() =>\n import('../docx/ConnectedStreamedWordArtifact').then((m) => ({\n default: m.ConnectedStreamedWordArtifact,\n }))\n)\nconst NativeDocxComparison = lazy(() =>\n import('../docx/ConnectedNativeDocxComparison').then((m) => ({\n default: m.ConnectedNativeDocxComparison,\n }))\n)\n\nconst UPLOADED_NO_VERSIONS =\n 'No earlier versions yet. Replacing, editing or signing this file adds a new version here.'\n\nexport interface ConnectedDocumentViewerProps {\n /**\n * The document, or a version reference `doc-\u2026@v{n}` (a citation, a \"made from v2\" link): an\n * earlier version opens read-only. Default: the session state's viewing document.\n */\n documentId?: string\n /** Controls at the right end of the header (a panel's dock / pop-out switcher). */\n headerActions?: ReactNode\n /** Where html/react artifacts load their sandbox runtime from. */\n artifactRuntimeUrl?: string\n}\n\nexport function ConnectedDocumentViewer(props: ConnectedDocumentViewerProps) {\n const viewing = useArbiSessionState((s) => s.viewingDocument?.id)\n const openedId = props.documentId ?? viewing\n if (!openedId) return null\n // A viewer that throws (a PDF the browser cannot render, say) shows the error here, in the\n // viewer's place, instead of unmounting the whole app.\n return (\n <ErrorBoundary\n resetKey={openedId}\n labels={{ title: \"This document couldn't be displayed\" }}\n testId=\"document-viewer-error\"\n >\n <ConnectedDocumentToolsProvider>\n <DocumentViewerContent {...props} openedId={openedId} />\n </ConnectedDocumentToolsProvider>\n </ErrorBoundary>\n )\n}\n\nfunction DocumentViewerContent({\n openedId,\n headerActions,\n artifactRuntimeUrl = '/artifact-runtime/',\n}: ConnectedDocumentViewerProps & { openedId: string }) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n const support = useDocumentViewerSupport()\n const formatDate = support.formatDate ?? fmtDate\n const tools = useDocumentTools()\n const { openConversation, openNewConversation, notify } = useBlocksEnvironment()\n const { userId: currentUserId } = useConnectedWorkspace()\n // A document keeps one id for its whole life; its versions are inside it.\n const documentId = parseVersionRef(openedId).docId\n const [totalPages, setTotalPages] = useState<number>(0)\n const [isCompact, setIsCompact] = useState(false)\n // Zoom of the PDF (canvas scale) / text, as a multiplier of fit width; pinch, double-tap and the\n // zoom button all drive it. The text view's size is a reading preference for every document.\n const [pdfZoom, setPdfZoom] = useState(1)\n const {\n tab: zoomTab,\n textScale,\n compareId: compareDocumentId,\n } = useArbiSessionState((s) => s.documentViewer)\n const zoom = zoomTab === 'html' ? textScale : pdfZoom\n const setZoom = useCallback(\n (next: number | ((z: number) => number)) => {\n const value = typeof next === 'function' ? next(zoom) : next\n if (zoomTab === 'html') session.setDocumentViewer({ textScale: value })\n else setPdfZoom(value)\n },\n [zoomTab, session, zoom]\n )\n const [scrollTrigger, setScrollTrigger] = useState(0) // Incremented to scroll the viewers\n const containerRef = useRef<HTMLDivElement>(null)\n\n const viewingDocumentPage = useArbiSessionState((s) => s.viewingDocument?.page ?? null)\n const setViewingDocumentPage = (page: number) =>\n session.setViewingDocument({ id: openedId, page })\n const setViewingDocumentId = (id: string) => session.setViewingDocument({ id })\n const setActiveTab = (tab: Parameters<typeof session.setDocumentViewer>[0]['tab']) =>\n session.setDocumentViewer({ tab })\n const setCompareDocumentId = (id: string | null) => session.setDocumentViewer({ compareId: id })\n const { data: conversations } = useConnectedConversations()\n\n // An earlier version opened read-only (`doc-\u2026@v{n}`) from the Versions tab, a citation or a\n // \"made from\" link. Word documents show it in the Word editor, artifacts in theirs, everything\n // else as its PDF. The version on screen is the session's viewing id, not local state: the\n // viewer remounts when its panel moves to a new window, and the version must come along.\n const snapshotRef = parseVersionRef(openedId).version ? openedId : null\n // Every version of the document, oldest first. Every version of an artifact shares one name, so\n // both sides of a comparison get the timeline's \"v1/v2/v3\" label.\n const { versions, translations } = useViewerVersions(documentId)\n const currentVersionId = versions.find((v) => v.isCurrent)?.id ?? documentId\n // Opening the current version is the live document itself, not a read-only copy of it.\n const snapshotDocumentId = snapshotRef && snapshotRef !== currentVersionId ? snapshotRef : null\n const doc = useViewedDocument(documentId)\n const setSnapshotDocumentId = (ref: string | null) => setViewingDocumentId(ref ?? documentId)\n // Drafting mode: a thread bound to the open document (or the one it was made in) drafts in it,\n // also while an earlier version of it is on screen; a turn sent then brings the live document\n // back, where the assistant's edits appear. Being open binds no chat to it.\n useRegisterOpenDocument({\n documentId: doc.savedDocumentId,\n shownId: openedId,\n showLive: () => setViewingDocumentId(documentId),\n workspaceId: doc.workspaceId,\n conversationId: doc.documentData?.conversation_ext_id ?? null,\n })\n const {\n documentData,\n streamingDoc,\n isStreaming,\n draftDoc,\n isPresentation,\n isDraft,\n isCaptureDraft,\n labelSummaries,\n isImage,\n isVideo,\n isAudio,\n isMedia,\n isArtifact,\n liveKind,\n liveSource,\n isDocx,\n isXlsx,\n isDownloadOnly,\n } = doc\n // The thread bound to this document: its latest one, else a new chat bound to it. The document\n // stays on screen beside it.\n const chatAboutDocument = () => {\n const savedId = doc.savedDocumentId\n if (!savedId) return\n const latest = latestThreadOfDocument(conversations, savedId)\n if (latest) {\n openConversation(latest, { keepDocumentOpen: true })\n return\n }\n // Opening a new chat starts it unbound; it is bound after.\n openNewConversation({ keepDocumentOpen: true })\n session.setNewChatDocumentId(savedId)\n }\n // A thread by its title, for the threads a document (and each version) was made in.\n const threadTitle = (id: string) =>\n conversations.find((c) => c.external_id === id)?.title?.trim() || 'Its thread'\n // The thread a generated document was made in (none for an upload).\n const madeInId = documentData?.conversation_ext_id ?? null\n const madeIn = madeInId ? { id: madeInId, title: threadTitle(madeInId) } : null\n const pdfSnapshotId = snapshotDocumentId && (!isArtifact || isDocx) ? snapshotDocumentId : null\n // The document on screen: an earlier version when one is open, else the current one.\n const shownDocumentId = pdfSnapshotId || documentId\n const blobs = useViewerBlobs(shownDocumentId, doc)\n const [minimumPdfVersion, setMinimumPdfVersion] = useState<number | null>(null)\n useEffect(() => setMinimumPdfVersion(null), [documentId])\n const versionReady =\n !!pdfSnapshotId ||\n minimumPdfVersion === null ||\n (documentData?.current_version ?? 0) >= minimumPdfVersion\n const { xlsxBlob, xlsxError, handleDirectDownload } = blobs\n const pdfBlob = versionReady ? blobs.pdfBlob : null\n const pdfVerified = !!pdfBlob && blobs.pdfVerified !== false\n // Annotation mode for the PDF view; off for every newly opened document.\n const [annotating, setAnnotating] = useState(false)\n const [sharingFile, setSharingFile] = useState(false)\n useEffect(() => setAnnotating(false), [documentId])\n // My signature: one's saved signature or initials, to place as a picture stamp in the markup.\n const [placeMark, setPlaceMark] = useState<{ image: string; label: string; key: number } | null>(\n null\n )\n // Translations are listed with the versions (each is its own document), so they open the tab too.\n const hasHistory =\n versions.length > 1 || (documentData?.current_version ?? 1) > 1 || translations.length > 0\n const {\n activeTab,\n handleTabChange: changeTab,\n viewerTabs,\n } = useViewerTabs(doc, isCompact, hasHistory)\n const saveWordRef = useRef<(() => Promise<boolean | number>) | null>(null)\n const transitionPending = useRef(false)\n const transitionKey = JSON.stringify([openedId, doc.workspaceId])\n const transitionScope = useRef({ key: transitionKey, generation: 0 })\n if (transitionScope.current.key !== transitionKey) {\n transitionScope.current = {\n key: transitionKey,\n generation: transitionScope.current.generation + 1,\n }\n }\n useEffect(\n () => () => {\n transitionScope.current.generation += 1\n },\n []\n )\n const requestViewerTransition = async (transition: () => void): Promise<boolean> => {\n if (transitionPending.current) return false\n const leavingWord =\n isDocx &&\n !isDraft &&\n !isStreaming &&\n !snapshotDocumentId &&\n (activeTab === 'docx' || (isArtifact && !liveKind && activeTab === 'edit'))\n if (leavingWord) {\n transitionPending.current = true\n const generation = transitionScope.current.generation\n try {\n const saved = saveWordRef.current && (await saveWordRef.current())\n if (!saved) {\n notify('Could not save the current document. Stay in the editor and try again.', 'error')\n return false\n }\n if (generation !== transitionScope.current.generation) return false\n if (typeof saved === 'number') setMinimumPdfVersion(saved)\n } finally {\n transitionPending.current = false\n }\n }\n transition()\n return true\n }\n const handleTabChange = (tab: string) => {\n if (tab === activeTab) return\n void requestViewerTransition(() => changeTab(tab))\n }\n const crop = useImageCrop(\n documentId,\n documentData?.file_name,\n pdfBlob,\n documentData?.workspace_ext_id\n )\n // Signing: choose where the signature goes (placing), then the Sign dialog.\n const [placingSignature, setPlacingSignature] = useState(false)\n const [signAppearance, setSignAppearance] = useState<SignatureAppearance | undefined>()\n const [isSignOpen, setIsSignOpen] = useState(false)\n const signingScope = JSON.stringify([\n documentId,\n snapshotDocumentId,\n documentData?.current_version,\n ])\n const signingScopeRef = useRef(signingScope)\n const signingScopeMatches = signingScopeRef.current === signingScope\n // Leaving the placement when another version opens or returns: it belongs to the copy on screen.\n useEffect(() => {\n setPlacingSignature(false)\n setIsSignOpen(false)\n setSignAppearance(undefined)\n signingScopeRef.current = signingScope\n }, [signingScope])\n // A signature request: the author placing fields ('prepare'), or a signer walked through theirs.\n const [signatureFlow, setSignatureFlow] = useState<SignatureFlow>(null)\n useEffect(() => setSignatureFlow(null), [signingScope])\n const signatureDocumentId =\n pdfSnapshotId ||\n (documentData?.current_version ? `${documentId}@v${documentData.current_version}` : documentId)\n const { data: signatureStatus } = useDocumentSignatures(\n signatureDocumentId,\n !isDraft && !liveKind\n )\n\n // The Word editor on the current version: the editor's own ribbon says \"Co-edit mode\", so the\n // header carries no version label and, when narrow, no title row above the ribbon.\n const isCoEditing =\n !snapshotDocumentId &&\n !compareDocumentId &&\n !isDraft &&\n ((activeTab === 'docx' && isDocx) ||\n (activeTab === 'slides' && isPresentation) ||\n (activeTab === 'edit' && isArtifact && !liveKind && !isStreaming))\n const currentVersionLabel = isCoEditing\n ? undefined\n : !snapshotDocumentId && !compareDocumentId && (isDocx || (isArtifact && !liveKind))\n ? 'Live'\n : versionLabel(versions, snapshotDocumentId || documentId)\n const compareVersionLabel = versionLabel(versions, compareDocumentId)\n const snapshotNumber = findVersion(versions, snapshotDocumentId)?.number\n // The markup of the version on screen: the default view when it has any (\"Show original\" hides).\n const pdfSnapshotNumber = pdfSnapshotId\n ? (parseVersionRef(pdfSnapshotId).version ?? undefined)\n : undefined\n // A signed version is locked: only a further signature changes it. Its marks stay in the markup\n // layer (never in its PDF), and editing its content saves a new, unsigned version.\n const isSigned = !!signatureStatus?.signed\n const markup = useDocumentMarkup(documentData, pdfSnapshotNumber, isSigned)\n\n // Detect container width changes (640px = the sm: breakpoint).\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) setIsCompact(entry.contentRect.width < 640)\n })\n resizeObserver.observe(container)\n return () => resizeObserver.disconnect()\n }, [])\n\n const handleLoadSuccess = useCallback((numPages: number) => setTotalPages(numPages), [])\n\n // Go to a page: the counter, or one step from the arrows.\n const goToPage = (page: number) => {\n setViewingDocumentPage(page)\n setScrollTrigger((prev) => prev + 1)\n }\n const stepPage = (delta: number) => {\n const next = (viewingDocumentPage || 1) + delta\n if (next >= 1 && next <= totalPages) goToPage(next)\n }\n\n const documentTitle =\n streamingDoc?.title ||\n draftDoc?.title ||\n documentData?.doc_metadata?.title ||\n documentData?.file_name ||\n 'Document'\n\n // The page / zoom controls, shared by the PDF and the text view. They sit in the control bar\n // under the body, so they never cover the text being read.\n const pageNav = totalPages > 0 && (\n <>\n <ViewerZoomControl zoom={zoom} onCycle={() => setZoom(cycleZoom(zoom))} />\n <PdfPageNav\n canPrev={(viewingDocumentPage || 1) > 1}\n canNext={(viewingDocumentPage || 1) < totalPages}\n onPrev={() => stepPage(-1)}\n onNext={() => stepPage(1)}\n counter={\n <ViewerPageCounter page={viewingDocumentPage || 1} total={totalPages} onGoTo={goToPage} />\n }\n />\n </>\n )\n\n // Compare: a \"Compare vs. [doc]\" row of its own below the tab/title bar (a docked panel is\n // narrow), with the flip-direction arrow and the way out.\n const isComparing = !!compareDocumentId\n const compareTarget = compareDocumentId ? parseVersionRef(compareDocumentId).docId : null\n const compareIndicator = isComparing && compareTarget && (\n <ArtifactCompareBar\n compareTarget={support.renderDocumentPill?.(compareTarget) ?? compareTarget}\n versionLabel={compareVersionLabel}\n mode=\"flip\"\n showTrackChanges={false}\n onToggleTrackChanges={() => {}}\n onFlip={() => {\n setViewingDocumentId(compareDocumentId!)\n setCompareDocumentId(documentId)\n }}\n onStop={() => setCompareDocumentId(null)}\n />\n )\n\n // Document name block: the name, related documents and status notes. Roomy headers keep it on\n // the tab row; a narrow (phone / docked) header gives it a row of its own so the name is never\n // cut down to a couple of letters by the tabs and actions.\n const titleBlock = (\n <>\n {/* A draft gets an editable name + auto-name toggle instead of the plain read-only name. */}\n {isDraft ? (\n <ViewerDraftTitle documentId={documentId} />\n ) : (\n <ViewerTitle\n title={documentTitle}\n versionLabel={currentVersionLabel}\n shrink={!!liveKind || isCompact}\n />\n )}\n {/* The narrow header's Share is icon-only, so the state is spelled out here as text. */}\n {isCompact && !isDraft && documentData?.shared && (\n <SharingEntity shared variant=\"icon\" data-testid=\"document-shared-status\" />\n )}\n {/* Likewise \"Show original\" is a bare page icon there: say which view is on screen. */}\n {isCompact &&\n activeTab === 'pdf' &&\n pdfBlob &&\n markup.hasMarkup &&\n !annotating &&\n !placingSignature && (\n <MarkupViewNote\n showOriginal={markup.showOriginal}\n onToggle={() => markup.setShowOriginal((on) => !on)}\n />\n )}\n {/* Related documents, except during a comparison (its own row says which). */}\n {!isComparing && !liveKind && documentData && (\n <ViewerRelatedDocuments document={documentData} />\n )}\n {isStreaming && <ViewerStatusNote pulse>streaming...</ViewerStatusNote>}\n {/* Nothing is generating: this document simply does not exist on the backend yet. */}\n {isDraft && (\n <ViewerStatusNote testId=\"draft-unsaved-indicator\">Draft \u2014 not saved</ViewerStatusNote>\n )}\n {signatureStatus?.signed && (\n <SignatureStatus status={signatureStatus} formatDate={formatDate} />\n )}\n </>\n )\n\n const leftContent = (\n <ViewerHeaderStart>\n {isDraft ? (\n // A draft's kind replaces the tabs: neither Versions nor the text view means anything\n // before the first save.\n <ViewerDraftKind documentId={documentId} />\n ) : (\n <>\n <ViewerTabBar\n tabs={viewerTabs.filter((tab) => tab.id !== 'versions')}\n activeId={activeTab}\n onChange={handleTabChange}\n />\n {(isArtifact || isDocx || hasHistory) && !liveKind && !isComparing && (\n <VersionDropdown\n versions={versions}\n activeId={\n snapshotDocumentId ??\n (currentVersionId === documentId && documentData?.current_version\n ? `${documentId}@v${documentData.current_version}`\n : currentVersionId)\n }\n isSnapshot={!!snapshotDocumentId}\n onOpen={(id) => {\n void requestViewerTransition(() => {\n setSnapshotDocumentId(id === currentVersionId ? null : id)\n if (activeTab === 'versions')\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : 'pdf')\n })\n }}\n onHistory={() => handleTabChange('versions')}\n />\n )}\n </>\n )}\n {!isCompact && titleBlock}\n </ViewerHeaderStart>\n )\n\n const annotatable = canAnnotate({\n activeTab,\n hasPdf: pdfVerified,\n isImage,\n isVideo,\n isAudio,\n isDownloadOnly,\n isDraft,\n isStreaming,\n isSnapshot: !!snapshotDocumentId,\n isComparing,\n })\n const clip = useViewerClipping(annotatable || (!!pdfBlob && (isImage || isVideo)), isCompact)\n const clean = useCleanView(clip.layer)\n\n // A request waiting for this user's signature, or their own in flight: shown over the PDF and\n // the Word editor alike; signing happens on the PDF.\n const signatureBanner = !isDraft && !liveKind && !snapshotDocumentId && (\n <SignatureRequestBanner\n documentId={documentId}\n hidden={!!signatureFlow}\n onSign={(request) => {\n void requestViewerTransition(() => {\n setAnnotating(false)\n setPlacingSignature(false)\n if (activeTab !== 'pdf') changeTab('pdf')\n setSignatureFlow({ kind: 'sign', request })\n })\n }}\n onEditDraft={(draft) => {\n void requestViewerTransition(() => {\n if (activeTab !== 'pdf') changeTab('pdf')\n setSignatureFlow({ kind: 'prepare', draft })\n })\n }}\n />\n )\n\n const share = () => {\n const name = (liveKind ? documentTitle : documentData?.file_name) || undefined\n if (support.share) {\n support.share({ id: documentId, name, isPrivate: !documentData?.shared })\n return\n }\n void arbi.documents\n .update([{ external_id: documentId, shared: !documentData?.shared }])\n .then(() => tools.onDocumentsChanged?.([documentId], 'markup'))\n .catch(() => notify(\"Couldn't change who can see this document\", 'error'))\n }\n const shownRef = snapshotDocumentId || documentId\n\n const rightContent = (\n <ViewerHeaderEnd isCompact={isCompact}>\n {/* Annotate: only for a PDF on screen (text and Word files are shown as a PDF too). Marks\n sit in a layer beside the document; Freeze saves a separate copy with them built in. */}\n {annotatable && (\n <AnnotateButton\n active={annotating}\n compact={isCompact}\n onClick={() => {\n setPlacingSignature(false)\n clip.stop()\n markup.setShowOriginal(false)\n setAnnotating((on) => !on)\n }}\n />\n )}\n {clip.button}\n {/* The markup is the default view; \"Show original\" shows the untouched file. */}\n {activeTab === 'pdf' && pdfBlob && !placingSignature && (markup.hasMarkup || annotating) && (\n <ShowOriginalButton\n active={markup.showOriginal}\n compact={isCompact}\n onClick={() => {\n setAnnotating(false)\n markup.setShowOriginal((on) => !on)\n }}\n />\n )}\n {activeTab === 'pdf' && markup.hasMarkup && !annotating && (\n <DownloadMarkupButton\n onClick={() => void markup.downloadMarkup()}\n // A signed version is locked: Download serves the signed file as it is.\n disabledReason={isSigned ? SIGNED_LOCKED_REASON : undefined}\n />\n )}\n {/* Image actions: start a generation from this image, or crop it into a new document. */}\n {activeTab === 'pdf' && isImage && pdfBlob && (\n <ViewerImageActions\n compact={isCompact}\n onUseAsReference={\n support.useImageAsReference ? () => support.useImageAsReference!(documentId) : undefined\n }\n onCrop={crop.handleOpenCrop}\n />\n )}\n {/* The thread it was made in: open it at the answer that made it. */}\n {madeIn && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size={isCompact ? 'icon' : 'sm'}\n onClick={() =>\n openConversation(madeIn.id, {\n messageId: documentData?.source_message_ext_id ?? undefined,\n })\n }\n title={`Open the thread it was made in: ${madeIn.title}`}\n aria-label={`Open the thread it was made in: ${madeIn.title}`}\n data-testid=\"document-open-thread\"\n >\n <MessageSquare className=\"size-4\" />\n {!isCompact && <span className=\"max-w-[10rem] truncate\">{madeIn.title}</span>}\n </Button>\n )}\n {documentId && documentData && !isDraft && !isStreaming && (\n <>\n <FileShareDialog\n open={sharingFile}\n onOpenChange={setSharingFile}\n documentId={documentId}\n version={pdfSnapshotNumber ?? documentData.current_version ?? 1}\n />\n </>\n )}\n {/* Chat about this document: the thread bound to it (its questions edit it), the latest one\n or a new one. Only such a thread drafts in a document: one merely open binds no chat. */}\n {doc.savedDocumentId && !snapshotDocumentId && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size={isCompact ? 'icon' : 'sm'}\n onClick={chatAboutDocument}\n title=\"Chat about this document: a thread that works in it, with edits as tracked changes\"\n aria-label=\"Chat about this document\"\n data-testid=\"document-chat-about\"\n className=\"pointer-coarse:min-h-11\"\n >\n <MessageSquarePlus className=\"size-4\" />\n {!isCompact && <span className=\"ml-1\">Chat</span>}\n </Button>\n )}\n {/* Share always asks first (the host's share dialog), so a click never changes who can see\n the file by surprise. */}\n {documentId && doc.workspaceId && (\n <ShareControl\n state={documentData?.shared ? 'shared' : 'private'}\n onToggle={share}\n disabled={!canChangeVisibility(documentData, currentUserId)}\n disabledTooltip=\"Only the owner can change visibility\"\n tooltip={\n documentData?.shared\n ? 'Shared with the workspace \u2014 click to share with specific people'\n : 'Share with the workspace, then optionally notify specific people by email'\n }\n variant=\"outline\"\n compact={isCompact}\n showState={!isCompact}\n labels={{\n shared: getEntityLabel('WORKSPACE'),\n private: 'Only you',\n mixed: 'Partly shared',\n }}\n testId=\"share-document-button\"\n stateTestId=\"document-title-shared-indicator\"\n />\n )}\n {/* Finalise (a translation): its current version saved as a new labelled PDF. */}\n {!isStreaming && !snapshotDocumentId && (\n <FinaliseTranslationButton document={documentData ?? undefined} isCompact={isCompact} />\n )}\n {/* Every signing action starts in one menu: sign yourself, save/place a mark, or request\n signatures from others. */}\n {annotatable && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant={\n placingSignature || signatureFlow?.kind === 'prepare' ? 'default' : 'outline'\n }\n size={isCompact ? 'icon' : 'sm'}\n aria-label=\"Sign\"\n title=\"Sign or request signatures\"\n data-testid=\"signing-menu-trigger\"\n className=\"pointer-coarse:min-h-11\"\n >\n <Signature className=\"size-4\" />\n {!isCompact && <span className=\"ml-1\">Sign</span>}\n <ChevronDown className=\"ml-1 size-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" forceMount>\n <DropdownMenuItem\n data-testid=\"sign-document-button\"\n onSelect={() => {\n setAnnotating(false)\n if (isSigned) {\n setSignatureFlow(null)\n setPlacingSignature((on) => !on)\n } else {\n setPlacingSignature(false)\n setSignatureFlow({ kind: 'prepare', self: true })\n }\n }}\n >\n <PenLine className=\"mr-2 size-4\" /> Sign this document\n </DropdownMenuItem>\n {!isSigned && (\n <>\n <PlaceMySignatureMenuItems\n onPlace={(mark) => {\n setPlacingSignature(false)\n setSignatureFlow(null)\n markup.setShowOriginal(false)\n setAnnotating(true)\n setPlaceMark({ ...mark, key: Date.now() })\n }}\n />\n <DropdownMenuItem\n data-testid=\"request-signatures-button\"\n onSelect={() => {\n setAnnotating(false)\n setPlacingSignature(false)\n setSignatureFlow(signatureFlow?.kind === 'prepare' ? null : { kind: 'prepare' })\n }}\n >\n <Users className=\"mr-2 size-4\" /> Ask someone to sign\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {isSignOpen && pdfBlob && pdfVerified && signingScopeMatches && (\n <SignDocumentDialog\n open={isSignOpen}\n onOpenChange={setIsSignOpen}\n documentId={documentId}\n pdfBlob={pdfBlob}\n // The PDF on screen is the current version's (an earlier one cannot be signed): the\n // server refuses if another version has landed since.\n version={documentData?.current_version ?? undefined}\n appearance={signAppearance}\n />\n )}\n <ViewerMoreMenu\n compact={isCompact}\n items={[\n ...(documentId && documentData && !isDraft && !isStreaming\n ? [\n {\n key: 'share-file',\n label: 'Share file\u2026',\n icon: <Link2 className=\"size-4\" />,\n description: 'Send a link to this version of the file',\n onSelect: () => setSharingFile(true),\n testId: 'share-file-button',\n },\n ]\n : []),\n ...(tools.emailDocument && !isDraft && !isStreaming && documentData?.file_name\n ? [\n {\n key: 'email',\n label: 'Email\u2026',\n icon: <Mail className=\"size-4\" />,\n description: 'Email this document (attached)',\n onSelect: () => tools.emailDocument?.(shownRef),\n testId: 'email-document-button',\n },\n ]\n : []),\n ...(support.translate &&\n !isDraft &&\n !isStreaming &&\n !liveKind &&\n !isImage &&\n documentData?.file_name\n ? [\n {\n key: 'translate',\n label: 'Translate\u2026',\n icon: <Languages className=\"size-4\" />,\n description: 'A new editable document, original and translation side by side',\n onSelect: () => support.translate!(shownRef),\n testId: 'translate-document-button',\n },\n ]\n : []),\n ]}\n />\n {headerActions}\n </ViewerHeaderEnd>\n )\n\n const viewerProps = {\n currentPage: viewingDocumentPage || undefined,\n onLoadSuccess: handleLoadSuccess,\n scrollTrigger,\n zoom,\n onZoomChange: setZoom,\n }\n\n return (\n <ViewerFrame\n frameRef={containerRef}\n contentId={documentId}\n header={\n <>\n <TabHeader\n tabs={[]}\n activeTabId={activeTab}\n onTabChange={handleTabChange}\n leftContent={leftContent}\n rightContent={rightContent}\n variant=\"underline\"\n />\n {isCompact && !isCoEditing && (\n <div data-slot=\"viewer-title-row\" className=\"flex min-w-0 items-center gap-2 px-3 pb-2\">\n {titleBlock}\n </div>\n )}\n {/* In the sticky header, not the content area: the PDF view scrolls its first page into\n view, which scrolls a bar above it out of sight. */}\n {snapshotDocumentId && (\n <VersionSnapshotBar\n versionNumber={snapshotNumber}\n live={isDocx || isArtifact}\n onAsk={\n support.askAboutVersion\n ? () => support.askAboutVersion!(snapshotDocumentId)\n : undefined\n }\n onReturn={() => setSnapshotDocumentId(null)}\n />\n )}\n </>\n }\n compareRow={isComparing ? compareIndicator || undefined : undefined}\n {...clean.frame}\n footer={<ViewerCropModal crop={crop} />}\n >\n {isComparing && (\n <Suspense fallback={<ViewerMessage>Loading comparison\u2026</ViewerMessage>}>\n <NativeDocxComparison\n baseId={compareDocumentId!}\n revisedId={documentId}\n title={documentTitle}\n />\n </Suspense>\n )}\n {/* A capture draft (photo/video/audio) has no backend document at all until it is saved:\n its recorder takes over the whole content area. */}\n {isCaptureDraft && <ViewerCaptureDraft documentId={documentId} />}\n\n {/* Media stay mounted (hidden) on the text tab, so playback goes on while reading the\n transcript. */}\n {!isCaptureDraft &&\n (activeTab === 'pdf' || (isMedia && activeTab === 'html')) &&\n (!isArtifact || (isDocx && !isDraft && !isStreaming && !liveKind)) &&\n !isComparing && (\n <ViewerPane hidden={activeTab !== 'pdf'}>\n {/* The labels are the document's, whichever view it is read in: the PDF gets the\n chips without the passage stepper (no parsed passages to walk here). */}\n {!clean.on && <DocumentLabelBar summaries={labelSummaries} />}\n {!clean.on && !isMedia && !isImage && signatureBanner}\n {!clean.on && activeTab === 'pdf' && pdfBlob && !pdfVerified && (\n <ViewerMessage>\n Offline copy: its version cannot be verified. Reconnect before signing.{' '}\n <button type=\"button\" onClick={() => void blobs.retryPdf()} className=\"underline\">\n Retry loading the current PDF\n </button>\n </ViewerMessage>\n )}\n {!clean.on && activeTab === 'pdf' && !isMedia && !isImage && (\n <MarkupNotices\n legacyPrompt={markup.legacyPrompt}\n olderNote={markup.olderNote}\n onOpenVersion={(n) => setSnapshotDocumentId(`${documentId}@v${n}`)}\n />\n )}\n <ViewerControlBar controls={!clean.on && activeTab === 'pdf' && pageNav}>\n <ViewerPdfPane\n documentId={documentId}\n doc={doc}\n pdfBlob={pdfBlob}\n isPdfLoading={!versionReady || blobs.isPdfLoading}\n pdfError={blobs.pdfError}\n onDownload={() => void handleDirectDownload()}\n viewerProps={viewerProps}\n signatureFlow={pdfVerified && signingScopeMatches ? signatureFlow : null}\n onSignatureFlow={setSignatureFlow}\n currentUserId={currentUserId}\n placingSignature={pdfVerified && signingScopeMatches && placingSignature}\n onPlacingDone={(appearance) => {\n setPlacingSignature(false)\n if (!appearance) return\n setSignAppearance(appearance)\n setIsSignOpen(true)\n }}\n annotating={annotating}\n clipping={clip.clipping}\n markup={markup}\n pdfSnapshotNumber={pdfSnapshotNumber}\n isSigned={isSigned}\n placeMark={placeMark}\n />\n </ViewerControlBar>\n </ViewerPane>\n )}\n\n {activeTab === 'preview' && isArtifact && liveKind && (\n // The preview loads its JSX compiler on first use, so it stays out of the main bundle.\n <ArtifactPreview\n kind={liveKind}\n source={liveSource}\n isStreaming={isStreaming}\n runtimeUrl={artifactRuntimeUrl}\n />\n )}\n\n {activeTab === 'edit' && isArtifact && liveKind && (\n <ArtifactCodeView source={liveSource} fileName={documentData?.file_name ?? undefined} />\n )}\n\n {/* A document draft is stored as DOCX: once generation ends the Word editor opens the stored\n document. Only a draft still being generated shows the streamed preview. */}\n {activeTab === 'edit' && isArtifact && !liveKind && !isStreaming && !isComparing && (\n <Suspense fallback={<ViewerMessage>Loading editor\u2026</ViewerMessage>}>\n {isSigned && !snapshotDocumentId && <SignedEditNote />}\n <NativeDocxEditor\n key={`${snapshotDocumentId || documentId}-${snapshotDocumentId ? 'snapshot' : 'live'}`}\n documentId={snapshotDocumentId || documentId}\n title={documentTitle}\n draftContent={isDraft ? draftDoc?.content || '' : undefined}\n snapshot={!!snapshotDocumentId}\n saveRef={saveWordRef}\n onSaved={(id) => {\n if (!isDraft) return\n session.clearDraftDocument(documentId)\n setViewingDocumentId(id)\n }}\n />\n </Suspense>\n )}\n\n {activeTab === 'versions' && (isArtifact || isDocx || hasHistory) && !isComparing && (\n <VersionTimeline\n // Each version made in a thread names it and opens it at the turn that made it.\n versions={versions.map((v) => ({\n ...v,\n madeIn: v.thread\n ? {\n label: threadTitle(v.thread.conversationId),\n onOpen: () =>\n openConversation(v.thread!.conversationId, {\n messageId: v.thread!.messageId ?? undefined,\n }),\n }\n : null,\n }))}\n currentId={currentVersionId}\n live={!!liveKind}\n // An uploaded file is not a draft: its versions come from replacing, editing or signing.\n labels={isArtifact ? undefined : { emptyDocument: UPLOADED_NO_VERSIONS }}\n formatDate={formatDate}\n onOpen={(id) => {\n // The current version is the live document itself, not a read-only copy of it.\n setSnapshotDocumentId(id === currentVersionId ? null : id)\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : 'pdf')\n }}\n onCompare={(id) => session.setDocumentViewer({ compareId: id, tab: 'html' })}\n translations={translations}\n onOpenTranslation={(id) => setViewingDocumentId(id)}\n />\n )}\n\n {activeTab === 'xlsx' &&\n isXlsx &&\n (xlsxBlob ? (\n <XlsxViewer blob={xlsxBlob} />\n ) : (\n <ViewerMessage>\n {xlsxError ? 'Failed to load spreadsheet' : 'Loading spreadsheet...'}\n </ViewerMessage>\n ))}\n\n {activeTab === 'slides' && isPresentation && (\n <Suspense fallback={<ViewerMessage>Loading slides\u2026</ViewerMessage>}>\n <SlidesTab\n documentId={documentId}\n version={snapshotDocumentId ? snapshotNumber : undefined}\n currentVersion={documentData?.current_version ?? undefined}\n draftTitle={isDraft ? (draftDoc?.title ?? '') : undefined}\n />\n </Suspense>\n )}\n {activeTab === 'docx' && isDocx && !isComparing && (\n <Suspense fallback={<ViewerMessage>Loading editor\u2026</ViewerMessage>}>\n {signatureBanner}\n {isSigned && !snapshotDocumentId && <SignedEditNote />}\n <NativeDocxEditor\n key={`${snapshotDocumentId || documentId}-${snapshotDocumentId ? 'snapshot' : 'live'}`}\n documentId={snapshotDocumentId || documentId}\n title={documentTitle}\n snapshot={!!snapshotDocumentId}\n saveRef={saveWordRef}\n />\n </Suspense>\n )}\n\n {streamingDoc &&\n isStreaming &&\n isArtifact &&\n !liveKind &&\n !isComparing &&\n (activeTab === 'html' || activeTab === 'edit') && (\n <Suspense fallback={<ViewerMessage>Opening draft\u2026</ViewerMessage>}>\n <StreamedWordArtifact\n key={documentId}\n documentId={documentId.startsWith('doc-') ? documentId : undefined}\n title={documentTitle}\n content={streamingDoc.content}\n busy={isStreaming}\n />\n </Suspense>\n )}\n\n {!isCaptureDraft &&\n !isComparing &&\n activeTab === 'html' &&\n !(isStreaming && isArtifact && !liveKind) && (\n <ViewerPane>\n <ViewerControlBar controls={pageNav}>\n <ParsedTextView\n documentId={pdfSnapshotId || documentId}\n onLoadSuccess={handleLoadSuccess}\n scrollTrigger={scrollTrigger}\n zoom={zoom}\n onZoomChange={setZoom}\n />\n </ViewerControlBar>\n </ViewerPane>\n )}\n </ViewerFrame>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,7 +14,7 @@ function VersionDropdown({
|
|
|
14
14
|
{
|
|
15
15
|
"aria-label": "Active document version",
|
|
16
16
|
"data-testid": "document-version-dropdown",
|
|
17
|
-
className: "max-w-44 rounded border border-input bg-background px-2 py-1 text-sm",
|
|
17
|
+
className: "max-w-44 rounded border border-input bg-background px-2 py-1 text-sm pointer-coarse:min-h-11",
|
|
18
18
|
value: active?.id ?? "",
|
|
19
19
|
onChange: (event) => {
|
|
20
20
|
const id = event.currentTarget.value;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/viewer/VersionDropdown.tsx"],
|
|
4
|
-
"sourcesContent": ["import type { ArtifactVersion } from '@arbidocs/react/artifacts'\n\n/** The version on screen, with a direct way to open another version. */\nexport function VersionDropdown({\n versions,\n activeId,\n isSnapshot,\n onOpen,\n onHistory,\n}: {\n versions: readonly ArtifactVersion[]\n activeId: string | null\n isSnapshot: boolean\n onOpen: (id: string) => void\n onHistory: () => void\n}) {\n const active = versions.find((version) => version.id === activeId)\n const pendingVersion = activeId?.match(/@v([1-9]\\d*)$/)?.[1]\n return (\n <select\n aria-label=\"Active document version\"\n data-testid=\"document-version-dropdown\"\n className=\"max-w-44 rounded border border-input bg-background px-2 py-1 text-sm\"\n value={active?.id ?? ''}\n onChange={(event) => {\n const id = event.currentTarget.value\n if (id === '__history') onHistory()\n else if (versions.some((version) => version.id === id)) onOpen(id)\n }}\n >\n {!active && (\n <option value=\"\">\n {pendingVersion\n ? `v${pendingVersion} \u00B7 ${isSnapshot ? 'Read only' : 'Current'}`\n : 'Version unavailable'}\n </option>\n )}\n {[...versions]\n .sort((a, b) => b.number - a.number)\n .map((version) => (\n <option key={version.id} value={version.id}>\n v{version.number}\n {version.isCurrent ? ' \u00B7 Current' : ' \u00B7 Read only'}\n </option>\n ))}\n <option value=\"__history\">Version history\u2026</option>\n </select>\n )\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { ArtifactVersion } from '@arbidocs/react/artifacts'\n\n/** The version on screen, with a direct way to open another version. */\nexport function VersionDropdown({\n versions,\n activeId,\n isSnapshot,\n onOpen,\n onHistory,\n}: {\n versions: readonly ArtifactVersion[]\n activeId: string | null\n isSnapshot: boolean\n onOpen: (id: string) => void\n onHistory: () => void\n}) {\n const active = versions.find((version) => version.id === activeId)\n const pendingVersion = activeId?.match(/@v([1-9]\\d*)$/)?.[1]\n return (\n <select\n aria-label=\"Active document version\"\n data-testid=\"document-version-dropdown\"\n className=\"max-w-44 rounded border border-input bg-background px-2 py-1 text-sm pointer-coarse:min-h-11\"\n value={active?.id ?? ''}\n onChange={(event) => {\n const id = event.currentTarget.value\n if (id === '__history') onHistory()\n else if (versions.some((version) => version.id === id)) onOpen(id)\n }}\n >\n {!active && (\n <option value=\"\">\n {pendingVersion\n ? `v${pendingVersion} \u00B7 ${isSnapshot ? 'Read only' : 'Current'}`\n : 'Version unavailable'}\n </option>\n )}\n {[...versions]\n .sort((a, b) => b.number - a.number)\n .map((version) => (\n <option key={version.id} value={version.id}>\n v{version.number}\n {version.isCurrent ? ' \u00B7 Current' : ' \u00B7 Read only'}\n </option>\n ))}\n <option value=\"__history\">Version history\u2026</option>\n </select>\n )\n}\n"],
|
|
5
5
|
"mappings": ";AA+BQ,cASE,YATF;AA5BD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,SAAS,SAAS,KAAK,CAAC,YAAY,QAAQ,OAAO,QAAQ;AACjE,QAAM,iBAAiB,UAAU,MAAM,eAAe,IAAI,CAAC;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAW;AAAA,MACX,eAAY;AAAA,MACZ,WAAU;AAAA,MACV,OAAO,QAAQ,MAAM;AAAA,MACrB,UAAU,CAAC,UAAU;AACnB,cAAM,KAAK,MAAM,cAAc;AAC/B,YAAI,OAAO,YAAa,WAAU;AAAA,iBACzB,SAAS,KAAK,CAAC,YAAY,QAAQ,OAAO,EAAE,EAAG,QAAO,EAAE;AAAA,MACnE;AAAA,MAEC;AAAA,SAAC,UACA,oBAAC,YAAO,OAAM,IACX,2BACG,IAAI,cAAc,SAAM,aAAa,cAAc,SAAS,KAC5D,uBACN;AAAA,QAED,CAAC,GAAG,QAAQ,EACV,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAClC,IAAI,CAAC,YACJ,qBAAC,YAAwB,OAAO,QAAQ,IAAI;AAAA;AAAA,UACxC,QAAQ;AAAA,UACT,QAAQ,YAAY,kBAAe;AAAA,aAFzB,QAAQ,EAGrB,CACD;AAAA,QACH,oBAAC,YAAO,OAAM,aAAY,mCAAgB;AAAA;AAAA;AAAA,EAC5C;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -12,6 +12,7 @@ import { friendlyFileType } from "@arbidocs/react/ui";
|
|
|
12
12
|
import { ViewerLoadError, ViewerMessage, ViewerPreviewUnavailable } from "../../files/index.js";
|
|
13
13
|
import { usePdfClipOutlines } from "./pdf/usePdfClipOutlines.js";
|
|
14
14
|
import { usePdfPassageHighlights } from "./pdf/usePdfPassageHighlights.js";
|
|
15
|
+
import { usePassageTextFallback } from "./pdf/usePassageTextFallback.js";
|
|
15
16
|
import { useViewerIsDetached } from "./support.js";
|
|
16
17
|
import { isLegacyPresentationFile } from "../../presentation/panel-id.js";
|
|
17
18
|
import { PresentationFileCard } from "../presentation/PresentationFileCard.js";
|
|
@@ -86,6 +87,7 @@ function ViewerPdfPane({
|
|
|
86
87
|
placeMark = null
|
|
87
88
|
}) {
|
|
88
89
|
const { documentData, isDownloadOnly, isVideo, isAudio, isImage, isDocx } = doc;
|
|
90
|
+
usePassageTextFallback(!!pdfError);
|
|
89
91
|
const showMarkup = markup.hasMarkup && !markup.showOriginal;
|
|
90
92
|
if (isLegacyPresentationFile(documentData?.file_name)) {
|
|
91
93
|
return /* @__PURE__ */ jsx(PresentationFileCard, { documentId, fileName: documentData?.file_name ?? "" });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/viewer/ViewerPdfPane.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The PDF (or media) body of the document viewer: loading and failure states, the image, audio and\n * video players, and the PDF with its tools \u2014 the markup layer, signature placement, a signature\n * request being prepared or signed.\n */\n\nimport { lazy, Suspense, useCallback } from 'react'\nimport { useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport type {\n SignatureAppearance,\n SignatureRequest,\n useDocumentMarkup,\n} from '@arbidocs/react/document-tools'\nimport {\n AudioViewer,\n ImageViewer,\n PdfViewer as KitPdfViewer,\n VideoViewer,\n type PdfViewerProps,\n} from '@arbidocs/react/viewers'\nimport { friendlyFileType } from '@arbidocs/react/ui'\nimport { ViewerLoadError, ViewerMessage, ViewerPreviewUnavailable } from '../../files'\nimport { usePdfClipOutlines } from './pdf/usePdfClipOutlines'\nimport { usePdfPassageHighlights } from './pdf/usePdfPassageHighlights'\nimport { useViewerIsDetached } from './support'\nimport { isLegacyPresentationFile } from '../../presentation/panel-id'\nimport { PresentationFileCard } from '../presentation/PresentationFileCard'\nimport { fileExtension, type ViewedDocument } from './useViewedDocument'\n\n// The markup viewer brings in pdf-lib, which nothing else needs: load it only when it is shown.\nconst AnnotatedPdfViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.AnnotatedPdfViewer }))\n)\nconst SignaturePlacementViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.SignaturePlacementViewer }))\n)\n// Signature requests: placing fields for signers, and a signer's guided signing.\nconst SignatureRequestEditor = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.SignatureRequestEditor }))\n)\n// Clip mode for the presentation: its own chunk (the presentation module).\nconst ClippingPdfViewer = lazy(() =>\n import('../presentation/ClippingPdfViewer').then((m) => ({ default: m.ClippingPdfViewer }))\n)\nconst ClippingMediaViewer = lazy(() =>\n import('../presentation/ClippingMediaViewer').then((m) => ({ default: m.ClippingMediaViewer }))\n)\nconst GuidedSigningViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.GuidedSigningViewer }))\n)\n\n/** A signature request: the author placing fields, or a signer walked through theirs. */\nexport type SignatureFlow =\n | { kind: 'prepare'; draft?: SignatureRequest; self?: boolean }\n | { kind: 'sign'; request: SignatureRequest }\n | null\n\n/**\n * The kit PDF viewer, reporting the page read into the session state; in a detached window its\n * pages render without the opener's web fonts (canvas text in another document cannot use them).\n */\nfunction SessionPdfViewer(props: Omit<PdfViewerProps, 'onPageChange' | 'disableFontFace'>) {\n const session = useArbiSessionStore()\n const viewingId = useArbiSessionState((s) => s.viewingDocument?.id)\n const isDetached = useViewerIsDetached()\n const onPageChange = useCallback(\n (page: number) => {\n if (viewingId) session.setViewingDocument({ id: viewingId, page })\n },\n [session, viewingId]\n )\n // The passages a citation lights, over their pages, under whatever the mode draws (markup).\n const passageHighlights = usePdfPassageHighlights(viewingId)\n // The open presentation's clips of this document, where they were cut.\n const clipOutlines = usePdfClipOutlines(viewingId)\n const { renderPageOverlay: modeOverlay } = props\n const renderPageOverlay = useCallback<NonNullable<PdfViewerProps['renderPageOverlay']>>(\n (page) => (\n <>\n {passageHighlights(page.pageNumber)}\n {clipOutlines(page.pageNumber)}\n {modeOverlay?.(page)}\n </>\n ),\n [passageHighlights, clipOutlines, modeOverlay]\n )\n return (\n <KitPdfViewer\n {...props}\n renderPageOverlay={renderPageOverlay}\n onPageChange={onPageChange}\n disableFontFace={!!isDetached}\n />\n )\n}\n\nexport interface ViewerPdfPaneProps {\n documentId: string\n doc: ViewedDocument\n pdfBlob: Blob | null\n isPdfLoading: boolean\n pdfError: unknown\n onDownload: () => void\n viewerProps: {\n currentPage: number | undefined\n onLoadSuccess: (pages: number) => void\n scrollTrigger: number\n zoom: number\n onZoomChange: (zoom: number) => void\n }\n signatureFlow: SignatureFlow\n onSignatureFlow: (flow: SignatureFlow) => void\n currentUserId: string | undefined\n placingSignature: boolean\n onPlacingDone: (appearance?: SignatureAppearance) => void\n annotating: boolean\n /** Clip mode: dragging over a page adds that area to the presentation. */\n clipping?: boolean\n markup: ReturnType<typeof useDocumentMarkup>\n pdfSnapshotNumber: number | undefined\n isSigned: boolean\n /** One's saved signature or initials to place as a picture stamp (PDF tab \u203A My signature). */\n placeMark?: { image: string; label: string; key: number } | null\n}\n\nexport function ViewerPdfPane({\n documentId,\n doc,\n pdfBlob,\n isPdfLoading,\n pdfError,\n onDownload,\n viewerProps,\n signatureFlow,\n onSignatureFlow,\n currentUserId,\n placingSignature,\n onPlacingDone,\n annotating,\n clipping = false,\n markup,\n pdfSnapshotNumber,\n isSigned,\n placeMark = null,\n}: ViewerPdfPaneProps) {\n const { documentData, isDownloadOnly, isVideo, isAudio, isImage, isDocx } = doc\n const showMarkup = markup.hasMarkup && !markup.showOriginal\n\n // A presentation saved before it was a PDF (its data alone): what it is, and Edit presentation.\n if (isLegacyPresentationFile(documentData?.file_name)) {\n return <PresentationFileCard documentId={documentId} fileName={documentData?.file_name ?? ''} />\n }\n\n // Files that cannot be previewed in the browser: the download, at once.\n if (isDownloadOnly) {\n return (\n <ViewerPreviewUnavailable\n extension={fileExtension(documentData?.file_name)}\n onDownload={onDownload}\n />\n )\n }\n\n // Text files are rendered to a PDF too, so name what the user opened, not the rendering.\n const loadingLabel = isVideo\n ? 'Loading video...'\n : isAudio\n ? 'Loading audio...'\n : isImage\n ? 'Loading image...'\n : !documentData\n ? 'Loading document...'\n : friendlyFileType(documentData.file_type, documentData.file_name) === 'Text'\n ? 'Loading text...'\n : 'Loading PDF...'\n const errorLabel = isVideo\n ? 'Failed to load video'\n : isAudio\n ? 'Failed to load audio'\n : isImage\n ? 'Failed to load image'\n : 'Failed to load PDF'\n\n if (\n isDocx &&\n !pdfSnapshotNumber &&\n documentData &&\n !['completed', 'low-content', 'failed'].includes(documentData.status || '')\n ) {\n return (\n <ViewerMessage>\n PDF and search indexing are processing. Open the DOCX tab to edit now.\n </ViewerMessage>\n )\n }\n if (isDocx && !pdfSnapshotNumber && documentData?.status === 'failed') {\n return (\n <ViewerMessage>\n PDF conversion failed. Open the Word editor or download the document.\n </ViewerMessage>\n )\n }\n if (isPdfLoading) return <ViewerMessage>{loadingLabel}</ViewerMessage>\n if (pdfError) {\n return (\n <ViewerLoadError\n message={\n isVideo || isAudio || isImage\n ? `${errorLabel} \u2014 download it instead.`\n : \"Couldn't display the PDF \u2014 download it instead.\"\n }\n onDownload={onDownload}\n />\n )\n }\n // Nothing is fetched yet: the PDF is read once the document record has loaded, so the viewer\n // would otherwise sit empty for that first stretch.\n if (!pdfBlob) return <ViewerMessage>{loadingLabel}</ViewerMessage>\n\n // Clip mode on an image or a video: drag over it for the presentation.\n if (clipping && (isImage || isVideo)) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <ClippingMediaViewer\n file={pdfBlob}\n kind={isVideo ? 'video' : 'image'}\n documentId={documentId}\n fileName={documentData?.file_name || (isVideo ? 'Video' : 'Image')}\n />\n </Suspense>\n )\n }\n if (isVideo) return <VideoViewer blob={pdfBlob} title={documentData?.file_name || 'Video'} />\n if (isAudio) return <AudioViewer blob={pdfBlob} title={documentData?.file_name || 'Audio'} />\n if (isImage) {\n return <ImageViewer blob={pdfBlob} alt={documentData?.file_name || 'Document image'} />\n }\n if (signatureFlow?.kind === 'prepare') {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <SignatureRequestEditor\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber ?? documentData?.current_version ?? undefined}\n selfSigning={signatureFlow.self}\n draft={signatureFlow.draft}\n shareFile={!signatureFlow.draft}\n viewer={SessionPdfViewer}\n onCancel={() => onSignatureFlow(null)}\n onSaved={() => onSignatureFlow(null)}\n />\n </Suspense>\n )\n }\n if (signatureFlow?.kind === 'sign' && currentUserId) {\n const { currentPage: _page, scrollTrigger: _trigger, ...guidedProps } = viewerProps\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <GuidedSigningViewer\n {...guidedProps}\n file={pdfBlob}\n request={signatureFlow.request}\n signer={currentUserId}\n viewer={SessionPdfViewer}\n onClose={() => onSignatureFlow(null)}\n onSigned={() => onSignatureFlow(null)}\n />\n </Suspense>\n )\n }\n if (placingSignature) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <SignaturePlacementViewer\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n viewer={SessionPdfViewer}\n onCancel={() => onPlacingDone()}\n onContinue={(appearance) => onPlacingDone(appearance)}\n />\n </Suspense>\n )\n }\n if (clipping) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <ClippingPdfViewer\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber}\n fileName={documentData?.file_name || 'Document'}\n hasMarkup={markup.hasMarkup}\n viewer={SessionPdfViewer}\n />\n </Suspense>\n )\n }\n // Annotate mode, or the markup as the reading view: one viewer, so leaving annotate mode keeps\n // (and saves) what was just drawn.\n if (annotating || showMarkup) {\n return (\n <Suspense\n fallback={\n <ViewerMessage>\n {annotating ? 'Loading annotation tools\u2026' : 'Loading markup\u2026'}\n </ViewerMessage>\n }\n >\n <AnnotatedPdfViewer\n key={`${documentId}@${pdfSnapshotNumber ?? 'current'}`}\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber}\n editing={annotating}\n onMarkupChange={markup.onMarkupChange}\n fileName={documentData?.file_name}\n shared={documentData?.shared ?? false}\n folder={documentData?.folder}\n workspaceId={documentData?.workspace_ext_id}\n viewer={SessionPdfViewer}\n signed={isSigned}\n placeStamp={placeMark}\n />\n </Suspense>\n )\n }\n return <SessionPdfViewer {...viewerProps} file={pdfBlob} />\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * The PDF (or media) body of the document viewer: loading and failure states, the image, audio and\n * video players, and the PDF with its tools \u2014 the markup layer, signature placement, a signature\n * request being prepared or signed.\n */\n\nimport { lazy, Suspense, useCallback } from 'react'\nimport { useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport type {\n SignatureAppearance,\n SignatureRequest,\n useDocumentMarkup,\n} from '@arbidocs/react/document-tools'\nimport {\n AudioViewer,\n ImageViewer,\n PdfViewer as KitPdfViewer,\n VideoViewer,\n type PdfViewerProps,\n} from '@arbidocs/react/viewers'\nimport { friendlyFileType } from '@arbidocs/react/ui'\nimport { ViewerLoadError, ViewerMessage, ViewerPreviewUnavailable } from '../../files'\nimport { usePdfClipOutlines } from './pdf/usePdfClipOutlines'\nimport { usePdfPassageHighlights } from './pdf/usePdfPassageHighlights'\nimport { usePassageTextFallback } from './pdf/usePassageTextFallback'\nimport { useViewerIsDetached } from './support'\nimport { isLegacyPresentationFile } from '../../presentation/panel-id'\nimport { PresentationFileCard } from '../presentation/PresentationFileCard'\nimport { fileExtension, type ViewedDocument } from './useViewedDocument'\n\n// The markup viewer brings in pdf-lib, which nothing else needs: load it only when it is shown.\nconst AnnotatedPdfViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.AnnotatedPdfViewer }))\n)\nconst SignaturePlacementViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.SignaturePlacementViewer }))\n)\n// Signature requests: placing fields for signers, and a signer's guided signing.\nconst SignatureRequestEditor = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.SignatureRequestEditor }))\n)\n// Clip mode for the presentation: its own chunk (the presentation module).\nconst ClippingPdfViewer = lazy(() =>\n import('../presentation/ClippingPdfViewer').then((m) => ({ default: m.ClippingPdfViewer }))\n)\nconst ClippingMediaViewer = lazy(() =>\n import('../presentation/ClippingMediaViewer').then((m) => ({ default: m.ClippingMediaViewer }))\n)\nconst GuidedSigningViewer = lazy(() =>\n import('../../document-tools/viewer').then((m) => ({ default: m.GuidedSigningViewer }))\n)\n\n/** A signature request: the author placing fields, or a signer walked through theirs. */\nexport type SignatureFlow =\n | { kind: 'prepare'; draft?: SignatureRequest; self?: boolean }\n | { kind: 'sign'; request: SignatureRequest }\n | null\n\n/**\n * The kit PDF viewer, reporting the page read into the session state; in a detached window its\n * pages render without the opener's web fonts (canvas text in another document cannot use them).\n */\nfunction SessionPdfViewer(props: Omit<PdfViewerProps, 'onPageChange' | 'disableFontFace'>) {\n const session = useArbiSessionStore()\n const viewingId = useArbiSessionState((s) => s.viewingDocument?.id)\n const isDetached = useViewerIsDetached()\n const onPageChange = useCallback(\n (page: number) => {\n if (viewingId) session.setViewingDocument({ id: viewingId, page })\n },\n [session, viewingId]\n )\n // The passages a citation lights, over their pages, under whatever the mode draws (markup).\n const passageHighlights = usePdfPassageHighlights(viewingId)\n // The open presentation's clips of this document, where they were cut.\n const clipOutlines = usePdfClipOutlines(viewingId)\n const { renderPageOverlay: modeOverlay } = props\n const renderPageOverlay = useCallback<NonNullable<PdfViewerProps['renderPageOverlay']>>(\n (page) => (\n <>\n {passageHighlights(page.pageNumber)}\n {clipOutlines(page.pageNumber)}\n {modeOverlay?.(page)}\n </>\n ),\n [passageHighlights, clipOutlines, modeOverlay]\n )\n return (\n <KitPdfViewer\n {...props}\n renderPageOverlay={renderPageOverlay}\n onPageChange={onPageChange}\n disableFontFace={!!isDetached}\n />\n )\n}\n\nexport interface ViewerPdfPaneProps {\n documentId: string\n doc: ViewedDocument\n pdfBlob: Blob | null\n isPdfLoading: boolean\n pdfError: unknown\n onDownload: () => void\n viewerProps: {\n currentPage: number | undefined\n onLoadSuccess: (pages: number) => void\n scrollTrigger: number\n zoom: number\n onZoomChange: (zoom: number) => void\n }\n signatureFlow: SignatureFlow\n onSignatureFlow: (flow: SignatureFlow) => void\n currentUserId: string | undefined\n placingSignature: boolean\n onPlacingDone: (appearance?: SignatureAppearance) => void\n annotating: boolean\n /** Clip mode: dragging over a page adds that area to the presentation. */\n clipping?: boolean\n markup: ReturnType<typeof useDocumentMarkup>\n pdfSnapshotNumber: number | undefined\n isSigned: boolean\n /** One's saved signature or initials to place as a picture stamp (PDF tab \u203A My signature). */\n placeMark?: { image: string; label: string; key: number } | null\n}\n\nexport function ViewerPdfPane({\n documentId,\n doc,\n pdfBlob,\n isPdfLoading,\n pdfError,\n onDownload,\n viewerProps,\n signatureFlow,\n onSignatureFlow,\n currentUserId,\n placingSignature,\n onPlacingDone,\n annotating,\n clipping = false,\n markup,\n pdfSnapshotNumber,\n isSigned,\n placeMark = null,\n}: ViewerPdfPaneProps) {\n const { documentData, isDownloadOnly, isVideo, isAudio, isImage, isDocx } = doc\n // A passage the PDF cannot light (no box on its page, or no PDF) opens on the text view.\n usePassageTextFallback(!!pdfError)\n const showMarkup = markup.hasMarkup && !markup.showOriginal\n\n // A presentation saved before it was a PDF (its data alone): what it is, and Edit presentation.\n if (isLegacyPresentationFile(documentData?.file_name)) {\n return <PresentationFileCard documentId={documentId} fileName={documentData?.file_name ?? ''} />\n }\n\n // Files that cannot be previewed in the browser: the download, at once.\n if (isDownloadOnly) {\n return (\n <ViewerPreviewUnavailable\n extension={fileExtension(documentData?.file_name)}\n onDownload={onDownload}\n />\n )\n }\n\n // Text files are rendered to a PDF too, so name what the user opened, not the rendering.\n const loadingLabel = isVideo\n ? 'Loading video...'\n : isAudio\n ? 'Loading audio...'\n : isImage\n ? 'Loading image...'\n : !documentData\n ? 'Loading document...'\n : friendlyFileType(documentData.file_type, documentData.file_name) === 'Text'\n ? 'Loading text...'\n : 'Loading PDF...'\n const errorLabel = isVideo\n ? 'Failed to load video'\n : isAudio\n ? 'Failed to load audio'\n : isImage\n ? 'Failed to load image'\n : 'Failed to load PDF'\n\n if (\n isDocx &&\n !pdfSnapshotNumber &&\n documentData &&\n !['completed', 'low-content', 'failed'].includes(documentData.status || '')\n ) {\n return (\n <ViewerMessage>\n PDF and search indexing are processing. Open the DOCX tab to edit now.\n </ViewerMessage>\n )\n }\n if (isDocx && !pdfSnapshotNumber && documentData?.status === 'failed') {\n return (\n <ViewerMessage>\n PDF conversion failed. Open the Word editor or download the document.\n </ViewerMessage>\n )\n }\n if (isPdfLoading) return <ViewerMessage>{loadingLabel}</ViewerMessage>\n if (pdfError) {\n return (\n <ViewerLoadError\n message={\n isVideo || isAudio || isImage\n ? `${errorLabel} \u2014 download it instead.`\n : \"Couldn't display the PDF \u2014 download it instead.\"\n }\n onDownload={onDownload}\n />\n )\n }\n // Nothing is fetched yet: the PDF is read once the document record has loaded, so the viewer\n // would otherwise sit empty for that first stretch.\n if (!pdfBlob) return <ViewerMessage>{loadingLabel}</ViewerMessage>\n\n // Clip mode on an image or a video: drag over it for the presentation.\n if (clipping && (isImage || isVideo)) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <ClippingMediaViewer\n file={pdfBlob}\n kind={isVideo ? 'video' : 'image'}\n documentId={documentId}\n fileName={documentData?.file_name || (isVideo ? 'Video' : 'Image')}\n />\n </Suspense>\n )\n }\n if (isVideo) return <VideoViewer blob={pdfBlob} title={documentData?.file_name || 'Video'} />\n if (isAudio) return <AudioViewer blob={pdfBlob} title={documentData?.file_name || 'Audio'} />\n if (isImage) {\n return <ImageViewer blob={pdfBlob} alt={documentData?.file_name || 'Document image'} />\n }\n if (signatureFlow?.kind === 'prepare') {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <SignatureRequestEditor\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber ?? documentData?.current_version ?? undefined}\n selfSigning={signatureFlow.self}\n draft={signatureFlow.draft}\n shareFile={!signatureFlow.draft}\n viewer={SessionPdfViewer}\n onCancel={() => onSignatureFlow(null)}\n onSaved={() => onSignatureFlow(null)}\n />\n </Suspense>\n )\n }\n if (signatureFlow?.kind === 'sign' && currentUserId) {\n const { currentPage: _page, scrollTrigger: _trigger, ...guidedProps } = viewerProps\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <GuidedSigningViewer\n {...guidedProps}\n file={pdfBlob}\n request={signatureFlow.request}\n signer={currentUserId}\n viewer={SessionPdfViewer}\n onClose={() => onSignatureFlow(null)}\n onSigned={() => onSignatureFlow(null)}\n />\n </Suspense>\n )\n }\n if (placingSignature) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <SignaturePlacementViewer\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n viewer={SessionPdfViewer}\n onCancel={() => onPlacingDone()}\n onContinue={(appearance) => onPlacingDone(appearance)}\n />\n </Suspense>\n )\n }\n if (clipping) {\n return (\n <Suspense fallback={<ViewerMessage>Loading\u2026</ViewerMessage>}>\n <ClippingPdfViewer\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber}\n fileName={documentData?.file_name || 'Document'}\n hasMarkup={markup.hasMarkup}\n viewer={SessionPdfViewer}\n />\n </Suspense>\n )\n }\n // Annotate mode, or the markup as the reading view: one viewer, so leaving annotate mode keeps\n // (and saves) what was just drawn.\n if (annotating || showMarkup) {\n return (\n <Suspense\n fallback={\n <ViewerMessage>\n {annotating ? 'Loading annotation tools\u2026' : 'Loading markup\u2026'}\n </ViewerMessage>\n }\n >\n <AnnotatedPdfViewer\n key={`${documentId}@${pdfSnapshotNumber ?? 'current'}`}\n {...viewerProps}\n file={pdfBlob}\n documentId={documentId}\n version={pdfSnapshotNumber}\n editing={annotating}\n onMarkupChange={markup.onMarkupChange}\n fileName={documentData?.file_name}\n shared={documentData?.shared ?? false}\n folder={documentData?.folder}\n workspaceId={documentData?.workspace_ext_id}\n viewer={SessionPdfViewer}\n signed={isSigned}\n placeStamp={placeMark}\n />\n </Suspense>\n )\n }\n return <SessionPdfViewer {...viewerProps} file={pdfBlob} />\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|