@arbidocs/blocks 0.5.119 → 0.5.121
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-B6WG7Q64.cjs +156 -0
- package/dist/ClippingMediaViewer-B6WG7Q64.cjs.map +1 -0
- package/dist/ClippingPdfViewer-6GCVTV3V.cjs +79 -0
- package/dist/ClippingPdfViewer-6GCVTV3V.cjs.map +1 -0
- package/dist/{ConnectedCallDock-WER7R222.cjs → ConnectedCallDock-DC5V5OUJ.cjs} +25 -23
- package/dist/ConnectedCallDock-DC5V5OUJ.cjs.map +1 -0
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs → ConnectedCallRoom-FQLXWTFB.cjs} +18 -16
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs.map → ConnectedCallRoom-FQLXWTFB.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs → ConnectedNativeDocxComparison-4Q5S7VLD.cjs} +17 -17
- package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs.map → ConnectedNativeDocxComparison-4Q5S7VLD.cjs.map} +1 -1
- package/dist/ConnectedPresentation-4HLDZDWV.cjs +183 -0
- package/dist/ConnectedPresentation-4HLDZDWV.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-7QDE2CZD.cjs +234 -0
- package/dist/ConnectedSlidesTab-7QDE2CZD.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs → ConnectedStreamedWordArtifact-FFOQJBOI.cjs} +17 -17
- package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs.map → ConnectedStreamedWordArtifact-FFOQJBOI.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-ZSBZBGFK.cjs → DocumentReviewCard-SNWVEZ7S.cjs} +19 -18
- package/dist/DocumentReviewCard-SNWVEZ7S.cjs.map +1 -0
- package/dist/{FilesViewerDialog-6UKR5WEF.cjs → FilesViewerDialog-IZI63FOV.cjs} +54 -47
- package/dist/FilesViewerDialog-IZI63FOV.cjs.map +1 -0
- package/dist/{GridViewImpl-ZMJJWTOM.cjs → GridViewImpl-LTYET77Q.cjs} +3 -3
- package/dist/GridViewImpl-LTYET77Q.cjs.map +1 -0
- package/dist/{WorkspaceTableView-J3C6VH4T.cjs → WorkspaceTableView-TEIRB6VJ.cjs} +11 -10
- package/dist/WorkspaceTableView-TEIRB6VJ.cjs.map +1 -0
- package/dist/agents/index.cjs +297 -297
- package/dist/agents/tasks/ConversationListView.js +10 -2
- package/dist/agents/tasks/ConversationListView.js.map +2 -2
- package/dist/agents/tasks/TaskTable.js +5 -4
- package/dist/agents/tasks/TaskTable.js.map +2 -2
- package/dist/agents/tasks/WorkflowsTable.js +4 -5
- package/dist/agents/tasks/WorkflowsTable.js.map +2 -2
- package/dist/agents/tasks/taskColumns.js +1 -1
- package/dist/agents/tasks/taskColumns.js.map +1 -1
- package/dist/agents/tasks/taskTableLabels.js +1 -1
- package/dist/agents/tasks/taskTableLabels.js.map +1 -1
- package/dist/agents/tasks/workflowTableLabels.js +1 -1
- package/dist/agents/tasks/workflowTableLabels.js.map +1 -1
- package/dist/{ai-IM4A23YT.cjs → ai-KBYNRNZ6.cjs} +28 -26
- package/dist/ai-KBYNRNZ6.cjs.map +1 -0
- package/dist/calls/connected/CallControls.d.ts +2 -0
- package/dist/calls/connected/CallControls.js +71 -9
- package/dist/calls/connected/CallControls.js.map +2 -2
- package/dist/calls/connected/ShareDocumentDialog.d.ts +14 -0
- package/dist/calls/connected/ShareDocumentDialog.js +77 -0
- package/dist/calls/connected/ShareDocumentDialog.js.map +7 -0
- package/dist/calls/index.cjs +121 -121
- package/dist/chat/index.cjs +9 -8
- package/dist/{chunk-T23UTIRI.cjs → chunk-2PZT3J34.cjs} +6 -6
- package/dist/{chunk-T23UTIRI.cjs.map → chunk-2PZT3J34.cjs.map} +1 -1
- package/dist/{chunk-SGYSDABK.cjs → chunk-2W5E62EY.cjs} +6 -6
- package/dist/{chunk-SGYSDABK.cjs.map → chunk-2W5E62EY.cjs.map} +1 -1
- package/dist/{chunk-TDO5UWXF.cjs → chunk-3SCNXNHI.cjs} +5 -5
- package/dist/{chunk-TDO5UWXF.cjs.map → chunk-3SCNXNHI.cjs.map} +1 -1
- package/dist/{chunk-KTQOGT2L.cjs → chunk-474GPLCM.cjs} +7 -7
- package/dist/{chunk-KTQOGT2L.cjs.map → chunk-474GPLCM.cjs.map} +1 -1
- package/dist/{chunk-TP5PGWIO.cjs → chunk-4IOYQLKG.cjs} +3 -3
- package/dist/{chunk-TP5PGWIO.cjs.map → chunk-4IOYQLKG.cjs.map} +1 -1
- package/dist/{chunk-NY3YUCOW.cjs → chunk-4NPCDS2X.cjs} +3 -3
- package/dist/{chunk-NY3YUCOW.cjs.map → chunk-4NPCDS2X.cjs.map} +1 -1
- package/dist/{chunk-CPG7II4E.cjs → chunk-4RBQ44RY.cjs} +28 -28
- package/dist/chunk-4RBQ44RY.cjs.map +1 -0
- package/dist/{chunk-BQ5RIWWT.cjs → chunk-4VZZWYEC.cjs} +3 -3
- package/dist/{chunk-BQ5RIWWT.cjs.map → chunk-4VZZWYEC.cjs.map} +1 -1
- package/dist/{chunk-Y24V6HPR.cjs → chunk-52KGMAO5.cjs} +15 -15
- package/dist/{chunk-Y24V6HPR.cjs.map → chunk-52KGMAO5.cjs.map} +1 -1
- package/dist/{chunk-HB2O4THB.cjs → chunk-5534FYXP.cjs} +4 -4
- package/dist/{chunk-HB2O4THB.cjs.map → chunk-5534FYXP.cjs.map} +1 -1
- package/dist/chunk-5GCCUXMT.cjs +63 -0
- package/dist/chunk-5GCCUXMT.cjs.map +1 -0
- package/dist/chunk-5LTIZ44D.cjs +95 -0
- package/dist/chunk-5LTIZ44D.cjs.map +1 -0
- package/dist/{chunk-YGXOKB5Z.cjs → chunk-734NPQNR.cjs} +4 -4
- package/dist/{chunk-YGXOKB5Z.cjs.map → chunk-734NPQNR.cjs.map} +1 -1
- package/dist/{chunk-SB4M3ITT.cjs → chunk-7VUJGHMY.cjs} +444 -100
- package/dist/chunk-7VUJGHMY.cjs.map +1 -0
- package/dist/chunk-AFQTQC7A.cjs +35 -0
- package/dist/chunk-AFQTQC7A.cjs.map +1 -0
- package/dist/{chunk-XKVPSOKP.cjs → chunk-AY6EZSZB.cjs} +4 -4
- package/dist/{chunk-XKVPSOKP.cjs.map → chunk-AY6EZSZB.cjs.map} +1 -1
- package/dist/{chunk-TT4IF52H.cjs → chunk-BVAT4EVC.cjs} +40 -41
- package/dist/chunk-BVAT4EVC.cjs.map +1 -0
- package/dist/{chunk-VGCTYTEW.cjs → chunk-C2OICDMI.cjs} +10 -10
- package/dist/{chunk-VGCTYTEW.cjs.map → chunk-C2OICDMI.cjs.map} +1 -1
- package/dist/{chunk-CPR6EHG7.cjs → chunk-DR2AH7JL.cjs} +179 -55
- package/dist/chunk-DR2AH7JL.cjs.map +1 -0
- package/dist/{chunk-NJCK6V6U.cjs → chunk-EATIFPKP.cjs} +4 -60
- package/dist/chunk-EATIFPKP.cjs.map +1 -0
- package/dist/{chunk-B3LZITVF.cjs → chunk-EHP6OH5D.cjs} +11 -451
- package/dist/chunk-EHP6OH5D.cjs.map +1 -0
- package/dist/{chunk-DDIW4HLU.cjs → chunk-ENGL7P3I.cjs} +46 -37
- package/dist/chunk-ENGL7P3I.cjs.map +1 -0
- package/dist/{chunk-QHOHDNBU.cjs → chunk-FKFQCK3C.cjs} +4 -4
- package/dist/{chunk-QHOHDNBU.cjs.map → chunk-FKFQCK3C.cjs.map} +1 -1
- package/dist/{chunk-6UTKM5AB.cjs → chunk-GKVE5JGB.cjs} +76 -76
- package/dist/chunk-GKVE5JGB.cjs.map +1 -0
- package/dist/{chunk-B2HNNG25.cjs → chunk-GPX5VC57.cjs} +50 -50
- package/dist/{chunk-B2HNNG25.cjs.map → chunk-GPX5VC57.cjs.map} +1 -1
- package/dist/{chunk-WAV762GP.cjs → chunk-GQXPNIRE.cjs} +6 -6
- package/dist/{chunk-WAV762GP.cjs.map → chunk-GQXPNIRE.cjs.map} +1 -1
- package/dist/chunk-GX2EBMJW.cjs +133 -0
- package/dist/chunk-GX2EBMJW.cjs.map +1 -0
- package/dist/{chunk-7OPOPYV6.cjs → chunk-H5OLHP2U.cjs} +3 -3
- package/dist/{chunk-7OPOPYV6.cjs.map → chunk-H5OLHP2U.cjs.map} +1 -1
- package/dist/chunk-HYUKPHCT.cjs +66 -0
- package/dist/chunk-HYUKPHCT.cjs.map +1 -0
- package/dist/{chunk-NNUK5ZM7.cjs → chunk-JQLWKNJO.cjs} +29 -27
- package/dist/chunk-JQLWKNJO.cjs.map +1 -0
- package/dist/{chunk-OEREKAAP.cjs → chunk-JZEYHDWJ.cjs} +75 -75
- package/dist/{chunk-OEREKAAP.cjs.map → chunk-JZEYHDWJ.cjs.map} +1 -1
- package/dist/{chunk-PGJYD67F.cjs → chunk-KNGZZC4O.cjs} +7 -6
- package/dist/chunk-KNGZZC4O.cjs.map +1 -0
- package/dist/{chunk-NIE3N6OM.cjs → chunk-KP5AITQ4.cjs} +10 -10
- package/dist/{chunk-NIE3N6OM.cjs.map → chunk-KP5AITQ4.cjs.map} +1 -1
- package/dist/{chunk-YYPZOEED.cjs → chunk-LHWOKOMP.cjs} +23 -2
- package/dist/chunk-LHWOKOMP.cjs.map +1 -0
- package/dist/{chunk-57NHXEU2.cjs → chunk-MXBXZXXQ.cjs} +5 -5
- package/dist/{chunk-57NHXEU2.cjs.map → chunk-MXBXZXXQ.cjs.map} +1 -1
- package/dist/{chunk-WXUU3COI.cjs → chunk-MZ2KZXNU.cjs} +3 -3
- package/dist/{chunk-WXUU3COI.cjs.map → chunk-MZ2KZXNU.cjs.map} +1 -1
- package/dist/chunk-NAJN32MF.cjs +154 -0
- package/dist/chunk-NAJN32MF.cjs.map +1 -0
- package/dist/{chunk-557MJ4IH.cjs → chunk-NLOETJCB.cjs} +17 -154
- package/dist/chunk-NLOETJCB.cjs.map +1 -0
- package/dist/{chunk-4XJEHKVZ.cjs → chunk-PIYYBPHH.cjs} +4 -4
- package/dist/{chunk-4XJEHKVZ.cjs.map → chunk-PIYYBPHH.cjs.map} +1 -1
- package/dist/chunk-Q3XJUXID.cjs +4774 -0
- package/dist/chunk-Q3XJUXID.cjs.map +1 -0
- package/dist/{chunk-325GVZE6.cjs → chunk-Q6DQGGP4.cjs} +3 -3
- package/dist/{chunk-325GVZE6.cjs.map → chunk-Q6DQGGP4.cjs.map} +1 -1
- package/dist/chunk-QFXILJMJ.cjs +458 -0
- package/dist/chunk-QFXILJMJ.cjs.map +1 -0
- package/dist/{chunk-R7CJEIA5.cjs → chunk-RYVZDFVO.cjs} +8 -9
- package/dist/chunk-RYVZDFVO.cjs.map +1 -0
- package/dist/{chunk-VLCY46K6.cjs → chunk-TG2GM7WJ.cjs} +4 -3
- package/dist/chunk-TG2GM7WJ.cjs.map +1 -0
- package/dist/{chunk-EOG6OT5I.cjs → chunk-TXP2N3DC.cjs} +4 -4
- package/dist/{chunk-EOG6OT5I.cjs.map → chunk-TXP2N3DC.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-VJ5ZLRBD.cjs +27 -0
- package/dist/chunk-VJ5ZLRBD.cjs.map +1 -0
- package/dist/{chunk-P77YTTJ3.cjs → chunk-W6B3RYTX.cjs} +4 -4
- package/dist/{chunk-P77YTTJ3.cjs.map → chunk-W6B3RYTX.cjs.map} +1 -1
- package/dist/chunk-WOOOMTTA.cjs +19 -0
- package/dist/chunk-WOOOMTTA.cjs.map +1 -0
- package/dist/{chunk-ZPPMAL5P.cjs → chunk-WQMR3O2D.cjs} +6 -10
- package/dist/chunk-WQMR3O2D.cjs.map +1 -0
- package/dist/{chunk-CJYWHUZR.cjs → chunk-XCKHOXRP.cjs} +4 -4
- package/dist/{chunk-CJYWHUZR.cjs.map → chunk-XCKHOXRP.cjs.map} +1 -1
- package/dist/{chunk-6WMMZLEV.cjs → chunk-XJEXFEWG.cjs} +2 -27
- package/dist/chunk-XJEXFEWG.cjs.map +1 -0
- package/dist/chunk-XK4TVJKD.cjs +73 -0
- package/dist/chunk-XK4TVJKD.cjs.map +1 -0
- package/dist/chunk-XTR26TNE.cjs +1358 -0
- package/dist/chunk-XTR26TNE.cjs.map +1 -0
- package/dist/{chunk-E7TE2WVT.cjs → chunk-ZVEW3JBT.cjs} +3 -3
- package/dist/{chunk-E7TE2WVT.cjs.map → chunk-ZVEW3JBT.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +73 -73
- package/dist/collaboration/sharing/ShareControl.js +10 -2
- package/dist/collaboration/sharing/ShareControl.js.map +2 -2
- package/dist/components/SharedCell.d.ts +2 -4
- package/dist/components/SharedCell.js +4 -8
- package/dist/components/SharedCell.js.map +2 -2
- package/dist/components/ZoomSlider.d.ts +25 -0
- package/dist/components/ZoomSlider.js +59 -0
- package/dist/components/ZoomSlider.js.map +7 -0
- package/dist/connect/docx.cjs +20 -20
- package/dist/connect/index.cjs +1210 -1264
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +42 -36
- package/dist/connection/ai.d.ts +1 -1
- package/dist/connection/facts/factPageColumns.js +3 -9
- package/dist/connection/facts/factPageColumns.js.map +2 -2
- package/dist/connection/files/ConnectedNewFileMenu.d.ts +2 -1
- package/dist/connection/files/ConnectedNewFileMenu.js +9 -3
- package/dist/connection/files/ConnectedNewFileMenu.js.map +2 -2
- package/dist/connection/files/explorer/ConnectedFilesExplorer.js +1 -1
- package/dist/connection/files/explorer/ConnectedFilesExplorer.js.map +2 -2
- package/dist/connection/files/explorer/FileTiles.js +1 -1
- package/dist/connection/files/explorer/FileTiles.js.map +2 -2
- package/dist/connection/files/fields/documentField.js +1 -1
- package/dist/connection/files/fields/documentField.js.map +2 -2
- package/dist/connection/files/grid/cells.js +1 -3
- package/dist/connection/files/grid/cells.js.map +2 -2
- package/dist/connection/files/grid/documentColumns.js +4 -3
- package/dist/connection/files/grid/documentColumns.js.map +2 -2
- package/dist/connection/files/page/DocumentsFilterBarActions.js +17 -28
- package/dist/connection/files/page/DocumentsFilterBarActions.js.map +2 -2
- package/dist/connection/mail/useMailboxDefaults.js +1 -1
- package/dist/connection/mail/useMailboxDefaults.js.map +2 -2
- package/dist/connection/panels/useSessionPanelMode.js +3 -2
- package/dist/connection/panels/useSessionPanelMode.js.map +2 -2
- package/dist/connection/presentation/ClippingMediaViewer.d.ts +12 -0
- package/dist/connection/presentation/ClippingMediaViewer.js +153 -0
- package/dist/connection/presentation/ClippingMediaViewer.js.map +7 -0
- package/dist/connection/presentation/ClippingPdfViewer.d.ts +22 -0
- package/dist/connection/presentation/ClippingPdfViewer.js +75 -0
- package/dist/connection/presentation/ClippingPdfViewer.js.map +7 -0
- package/dist/connection/presentation/ConnectedPresentation.d.ts +12 -0
- package/dist/connection/presentation/ConnectedPresentation.js +100 -0
- package/dist/connection/presentation/ConnectedPresentation.js.map +7 -0
- package/dist/connection/presentation/ConnectedSlidesTab.d.ts +20 -0
- package/dist/connection/presentation/ConnectedSlidesTab.js +220 -0
- package/dist/connection/presentation/ConnectedSlidesTab.js.map +7 -0
- package/dist/connection/presentation/CropClipDialog.d.ts +11 -0
- package/dist/connection/presentation/CropClipDialog.js +86 -0
- package/dist/connection/presentation/CropClipDialog.js.map +7 -0
- package/dist/connection/presentation/GenerateTile.d.ts +4 -0
- package/dist/connection/presentation/GenerateTile.js +24 -0
- package/dist/connection/presentation/GenerateTile.js.map +7 -0
- package/dist/connection/presentation/LabelColumnMenu.d.ts +8 -0
- package/dist/connection/presentation/LabelColumnMenu.js +38 -0
- package/dist/connection/presentation/LabelColumnMenu.js.map +7 -0
- package/dist/connection/presentation/PresentationDialogs.d.ts +39 -0
- package/dist/connection/presentation/PresentationDialogs.js +295 -0
- package/dist/connection/presentation/PresentationDialogs.js.map +7 -0
- package/dist/connection/presentation/PresentationFileCard.d.ts +10 -0
- package/dist/connection/presentation/PresentationFileCard.js +35 -0
- package/dist/connection/presentation/PresentationFileCard.js.map +7 -0
- package/dist/connection/presentation/PresentationPill.d.ts +8 -0
- package/dist/connection/presentation/PresentationPill.js +44 -0
- package/dist/connection/presentation/PresentationPill.js.map +7 -0
- package/dist/connection/presentation/PresentationSlot.d.ts +7 -0
- package/dist/connection/presentation/PresentationSlot.js +35 -0
- package/dist/connection/presentation/PresentationSlot.js.map +7 -0
- package/dist/connection/presentation/requests.d.ts +16 -0
- package/dist/connection/presentation/requests.js +20 -0
- package/dist/connection/presentation/requests.js.map +7 -0
- package/dist/connection/presentation/useImageGeneration.d.ts +11 -0
- package/dist/connection/presentation/useImageGeneration.js +66 -0
- package/dist/connection/presentation/useImageGeneration.js.map +7 -0
- package/dist/connection/presentation/useLabelColumns.d.ts +15 -0
- package/dist/connection/presentation/useLabelColumns.js +33 -0
- package/dist/connection/presentation/useLabelColumns.js.map +7 -0
- package/dist/connection/presentation/usePresentationController.d.ts +15 -0
- package/dist/connection/presentation/usePresentationController.js +118 -0
- package/dist/connection/presentation/usePresentationController.js.map +7 -0
- package/dist/connection/presentation/usePresentationFiles.d.ts +44 -0
- package/dist/connection/presentation/usePresentationFiles.js +307 -0
- package/dist/connection/presentation/usePresentationFiles.js.map +7 -0
- package/dist/connection/presentation/useViewerClipping.d.ts +14 -0
- package/dist/connection/presentation/useViewerClipping.js +18 -0
- package/dist/connection/presentation/useViewerClipping.js.map +7 -0
- package/dist/connection/sharing/WorkspaceMembersList.d.ts +4 -0
- package/dist/connection/sharing/WorkspaceMembersList.js +34 -0
- package/dist/connection/sharing/WorkspaceMembersList.js.map +7 -0
- package/dist/connection/shell/ConnectedAppShell.js +9 -1
- package/dist/connection/shell/ConnectedAppShell.js.map +2 -2
- package/dist/connection/viewer/CleanViewControl.d.ts +8 -0
- package/dist/connection/viewer/CleanViewControl.js +76 -0
- package/dist/connection/viewer/CleanViewControl.js.map +7 -0
- package/dist/connection/viewer/ConnectedDocumentViewer.js +31 -31
- package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
- package/dist/connection/viewer/ViewerCropModal.d.ts +5 -0
- package/dist/connection/viewer/ViewerCropModal.js +22 -0
- package/dist/connection/viewer/ViewerCropModal.js.map +7 -0
- package/dist/connection/viewer/ViewerPdfPane.d.ts +3 -1
- package/dist/connection/viewer/ViewerPdfPane.js +57 -2
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/drafts.js +6 -4
- package/dist/connection/viewer/drafts.js.map +2 -2
- package/dist/connection/viewer/pdf/PdfPassageHighlights.d.ts +12 -0
- package/dist/connection/viewer/pdf/PdfPassageHighlights.js +36 -0
- package/dist/connection/viewer/pdf/PdfPassageHighlights.js.map +7 -0
- package/dist/connection/viewer/pdf/passageHighlights.d.ts +26 -0
- package/dist/connection/viewer/pdf/passageHighlights.js +40 -0
- package/dist/connection/viewer/pdf/passageHighlights.js.map +7 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.d.ts +9 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +47 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +7 -0
- package/dist/connection/viewer/shareDocument.d.ts +11 -0
- package/dist/connection/viewer/shareDocument.js +11 -0
- package/dist/connection/viewer/shareDocument.js.map +7 -0
- package/dist/connection/viewer/slidesTabChunk.d.ts +2 -0
- package/dist/connection/viewer/slidesTabChunk.js +9 -0
- package/dist/connection/viewer/slidesTabChunk.js.map +7 -0
- package/dist/connection/viewer/useCleanView.d.ts +14 -0
- package/dist/connection/viewer/useCleanView.js +29 -0
- package/dist/connection/viewer/useCleanView.js.map +7 -0
- package/dist/connection/viewer/useViewedDocument.d.ts +1 -0
- package/dist/connection/viewer/useViewedDocument.js +9 -1
- package/dist/connection/viewer/useViewedDocument.js.map +2 -2
- package/dist/connection/viewer/useViewerTabs.js +18 -4
- package/dist/connection/viewer/useViewerTabs.js.map +2 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.d.ts +14 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.js +5 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.js.map +2 -2
- package/dist/connection/workflows/workflowsPageLabels.js +1 -1
- package/dist/connection/workflows/workflowsPageLabels.js.map +1 -1
- package/dist/dashboards/index.cjs +1 -1
- package/dist/databases/index.cjs +49 -49
- package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
- package/dist/document-tools/DocumentToolButtons.js +22 -1
- package/dist/document-tools/DocumentToolButtons.js.map +2 -2
- package/dist/document-tools/index.cjs +16 -12
- package/dist/document-tools/index.d.ts +1 -1
- package/dist/document-tools/index.js +2 -0
- package/dist/document-tools/index.js.map +2 -2
- package/dist/embed/index.cjs +43 -41
- package/dist/facts/factColumns.js +3 -3
- package/dist/facts/factColumns.js.map +1 -1
- package/dist/facts/index.cjs +42 -42
- package/dist/files/GridViewImpl.js +1 -1
- package/dist/files/GridViewImpl.js.map +2 -2
- package/dist/files/HtmlViewerParts.js +7 -15
- package/dist/files/HtmlViewerParts.js.map +2 -2
- package/dist/files/ViewerChrome.d.ts +5 -1
- package/dist/files/ViewerChrome.js +16 -6
- package/dist/files/ViewerChrome.js.map +2 -2
- package/dist/files/index.cjs +226 -226
- package/dist/files/navigator/DocumentSearchList.js +1 -1
- package/dist/files/navigator/DocumentSearchList.js.map +2 -2
- package/dist/index.cjs +1668 -1666
- package/dist/index.cjs.map +1 -1
- package/dist/presentation/BoxActionBar.d.ts +11 -0
- package/dist/presentation/BoxActionBar.js +182 -0
- package/dist/presentation/BoxActionBar.js.map +7 -0
- package/dist/presentation/ClipActionBar.d.ts +26 -0
- package/dist/presentation/ClipActionBar.js +103 -0
- package/dist/presentation/ClipActionBar.js.map +7 -0
- package/dist/presentation/ClipCaptureOverlay.d.ts +14 -0
- package/dist/presentation/ClipCaptureOverlay.js +69 -0
- package/dist/presentation/ClipCaptureOverlay.js.map +7 -0
- package/dist/presentation/ClipImage.d.ts +21 -0
- package/dist/presentation/ClipImage.js +119 -0
- package/dist/presentation/ClipImage.js.map +7 -0
- package/dist/presentation/ClipTray.d.ts +11 -0
- package/dist/presentation/ClipTray.js +152 -0
- package/dist/presentation/ClipTray.js.map +7 -0
- package/dist/presentation/ClipViewControls.d.ts +11 -0
- package/dist/presentation/ClipViewControls.js +142 -0
- package/dist/presentation/ClipViewControls.js.map +7 -0
- package/dist/presentation/DesignMenu.d.ts +8 -0
- package/dist/presentation/DesignMenu.js +199 -0
- package/dist/presentation/DesignMenu.js.map +7 -0
- package/dist/presentation/LayoutMenu.d.ts +17 -0
- package/dist/presentation/LayoutMenu.js +122 -0
- package/dist/presentation/LayoutMenu.js.map +7 -0
- package/dist/presentation/MediaClip.d.ts +15 -0
- package/dist/presentation/MediaClip.js +67 -0
- package/dist/presentation/MediaClip.js.map +7 -0
- package/dist/presentation/Notice.d.ts +6 -0
- package/dist/presentation/Notice.js +43 -0
- package/dist/presentation/Notice.js.map +7 -0
- package/dist/presentation/PresentationStage.d.ts +32 -0
- package/dist/presentation/PresentationStage.js +232 -0
- package/dist/presentation/PresentationStage.js.map +7 -0
- package/dist/presentation/PresenterView.d.ts +16 -0
- package/dist/presentation/PresenterView.js +69 -0
- package/dist/presentation/PresenterView.js.map +7 -0
- package/dist/presentation/SlideDecor.d.ts +25 -0
- package/dist/presentation/SlideDecor.js +189 -0
- package/dist/presentation/SlideDecor.js.map +7 -0
- package/dist/presentation/SlidesEditor.d.ts +25 -0
- package/dist/presentation/SlidesEditor.js +359 -0
- package/dist/presentation/SlidesEditor.js.map +7 -0
- package/dist/presentation/StageBox.d.ts +30 -0
- package/dist/presentation/StageBox.js +281 -0
- package/dist/presentation/StageBox.js.map +7 -0
- package/dist/presentation/StageItem.d.ts +37 -0
- package/dist/presentation/StageItem.js +211 -0
- package/dist/presentation/StageItem.js.map +7 -0
- package/dist/presentation/box-style.d.ts +6 -0
- package/dist/presentation/box-style.js +19 -0
- package/dist/presentation/box-style.js.map +7 -0
- package/dist/presentation/boxes.d.ts +105 -0
- package/dist/presentation/boxes.js +103 -0
- package/dist/presentation/boxes.js.map +7 -0
- package/dist/presentation/draw-boxes.d.ts +8 -0
- package/dist/presentation/draw-boxes.js +130 -0
- package/dist/presentation/draw-boxes.js.map +7 -0
- package/dist/presentation/export-boxes.d.ts +10 -0
- package/dist/presentation/export-boxes.js +74 -0
- package/dist/presentation/export-boxes.js.map +7 -0
- package/dist/presentation/export-pptx.d.ts +16 -0
- package/dist/presentation/export-pptx.js +194 -0
- package/dist/presentation/export-pptx.js.map +7 -0
- package/dist/presentation/import-pptx.d.ts +35 -0
- package/dist/presentation/import-pptx.js +659 -0
- package/dist/presentation/import-pptx.js.map +7 -0
- package/dist/presentation/merge-outside-edits.d.ts +12 -0
- package/dist/presentation/merge-outside-edits.js +35 -0
- package/dist/presentation/merge-outside-edits.js.map +7 -0
- package/dist/presentation/model.d.ts +201 -0
- package/dist/presentation/model.js +271 -0
- package/dist/presentation/model.js.map +7 -0
- package/dist/presentation/panel-id.d.ts +34 -0
- package/dist/presentation/panel-id.js +24 -0
- package/dist/presentation/panel-id.js.map +7 -0
- package/dist/presentation/persistence.d.ts +121 -0
- package/dist/presentation/persistence.js +141 -0
- package/dist/presentation/persistence.js.map +7 -0
- package/dist/presentation/pptx-data.d.ts +22 -0
- package/dist/presentation/pptx-data.js +83 -0
- package/dist/presentation/pptx-data.js.map +7 -0
- package/dist/presentation/pptx-xml.d.ts +90 -0
- package/dist/presentation/pptx-xml.js +333 -0
- package/dist/presentation/pptx-xml.js.map +7 -0
- package/dist/presentation/render-slides.d.ts +58 -0
- package/dist/presentation/render-slides.js +309 -0
- package/dist/presentation/render-slides.js.map +7 -0
- package/dist/presentation/saved-boxes.d.ts +11 -0
- package/dist/presentation/saved-boxes.js +80 -0
- package/dist/presentation/saved-boxes.js.map +7 -0
- package/dist/presentation/slide-layout.d.ts +54 -0
- package/dist/presentation/slide-layout.js +117 -0
- package/dist/presentation/slide-layout.js.map +7 -0
- package/dist/presentation/stage-videos.d.ts +5 -0
- package/dist/presentation/stage-videos.js +19 -0
- package/dist/presentation/stage-videos.js.map +7 -0
- package/dist/presentation/store.d.ts +203 -0
- package/dist/presentation/store.js +429 -0
- package/dist/presentation/store.js.map +7 -0
- package/dist/presentation/theme.d.ts +102 -0
- package/dist/presentation/theme.js +276 -0
- package/dist/presentation/theme.js.map +7 -0
- package/dist/presentation/useClipDrag.d.ts +26 -0
- package/dist/presentation/useClipDrag.js +65 -0
- package/dist/presentation/useClipDrag.js.map +7 -0
- package/dist/presentation/useObjectUrl.d.ts +6 -0
- package/dist/presentation/useObjectUrl.js +15 -0
- package/dist/presentation/useObjectUrl.js.map +7 -0
- package/dist/presentation/usePresenterKeys.d.ts +13 -0
- package/dist/presentation/usePresenterKeys.js +62 -0
- package/dist/presentation/usePresenterKeys.js.map +7 -0
- package/dist/settings/index.cjs +151 -150
- package/dist/shell/PanelPortal.js +1 -0
- package/dist/shell/PanelPortal.js.map +2 -2
- package/dist/shell/index.cjs +112 -110
- package/dist/shell/panel-windows.d.ts +2 -0
- package/dist/shell/panel-windows.js +7 -2
- package/dist/shell/panel-windows.js.map +2 -2
- package/dist/studio/index.cjs +28 -26
- package/dist/studio/index.cjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +58 -57
- package/dist/workflow-canvas/index.cjs.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +6 -5
- package/dist/ConnectedCallDock-WER7R222.cjs.map +0 -1
- package/dist/DocumentReviewCard-ZSBZBGFK.cjs.map +0 -1
- package/dist/FilesViewerDialog-6UKR5WEF.cjs.map +0 -1
- package/dist/GridViewImpl-ZMJJWTOM.cjs.map +0 -1
- package/dist/WorkspaceTableView-J3C6VH4T.cjs.map +0 -1
- package/dist/ai-IM4A23YT.cjs.map +0 -1
- package/dist/chunk-557MJ4IH.cjs.map +0 -1
- package/dist/chunk-6UTKM5AB.cjs.map +0 -1
- package/dist/chunk-6WMMZLEV.cjs.map +0 -1
- package/dist/chunk-B3LZITVF.cjs.map +0 -1
- package/dist/chunk-CPG7II4E.cjs.map +0 -1
- package/dist/chunk-CPR6EHG7.cjs.map +0 -1
- package/dist/chunk-DDIW4HLU.cjs.map +0 -1
- package/dist/chunk-NJCK6V6U.cjs.map +0 -1
- package/dist/chunk-NNUK5ZM7.cjs.map +0 -1
- package/dist/chunk-PGJYD67F.cjs.map +0 -1
- package/dist/chunk-R7CJEIA5.cjs.map +0 -1
- package/dist/chunk-SB4M3ITT.cjs.map +0 -1
- package/dist/chunk-TT4IF52H.cjs.map +0 -1
- package/dist/chunk-VLCY46K6.cjs.map +0 -1
- package/dist/chunk-YYPZOEED.cjs.map +0 -1
- package/dist/chunk-ZPPMAL5P.cjs.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/viewer/ViewerCropModal.tsx"],
|
|
4
|
+
"sourcesContent": ["import { DEFAULT_ASPECT_OPTIONS, ImageCropModal } from '@arbidocs/react'\nimport type { useImageCrop } from './useImageCrop'\n\n/** The viewer's image crop: to a new document, at full resolution (a crop frames, it never downscales). */\nexport function ViewerCropModal({ crop }: { crop: ReturnType<typeof useImageCrop> }) {\n return (\n <ImageCropModal\n open={crop.cropImageUrl !== null}\n image={crop.cropImageUrl}\n title=\"Crop image\"\n saveLabel=\"Save as a copy\"\n aspectOptions={DEFAULT_ASPECT_OPTIONS}\n output={{ mimeType: 'image/png' }}\n onComplete={crop.handleCropComplete}\n onCancel={crop.closeCrop}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAMI;AANJ,SAAS,wBAAwB,sBAAsB;AAIhD,SAAS,gBAAgB,EAAE,KAAK,GAA8C;AACnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,KAAK,iBAAiB;AAAA,MAC5B,OAAO,KAAK;AAAA,MACZ,OAAM;AAAA,MACN,WAAU;AAAA,MACV,eAAe;AAAA,MACf,QAAQ,EAAE,UAAU,YAAY;AAAA,MAChC,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA;AAAA,EACjB;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -34,6 +34,8 @@ export interface ViewerPdfPaneProps {
|
|
|
34
34
|
placingSignature: boolean;
|
|
35
35
|
onPlacingDone: (appearance?: SignatureAppearance) => void;
|
|
36
36
|
annotating: boolean;
|
|
37
|
+
/** Clip mode: dragging over a page adds that area to the presentation. */
|
|
38
|
+
clipping?: boolean;
|
|
37
39
|
markup: ReturnType<typeof useDocumentMarkup>;
|
|
38
40
|
pdfSnapshotNumber: number | undefined;
|
|
39
41
|
isSigned: boolean;
|
|
@@ -44,4 +46,4 @@ export interface ViewerPdfPaneProps {
|
|
|
44
46
|
key: number;
|
|
45
47
|
} | null;
|
|
46
48
|
}
|
|
47
|
-
export declare function ViewerPdfPane({ documentId, doc, pdfBlob, isPdfLoading, pdfError, onDownload, viewerProps, signatureFlow, onSignatureFlow, currentUserId, placingSignature, onPlacingDone, annotating, markup, pdfSnapshotNumber, isSigned, placeMark, }: ViewerPdfPaneProps): import("react").JSX.Element;
|
|
49
|
+
export declare function ViewerPdfPane({ documentId, doc, pdfBlob, isPdfLoading, pdfError, onDownload, viewerProps, signatureFlow, onSignatureFlow, currentUserId, placingSignature, onPlacingDone, annotating, clipping, markup, pdfSnapshotNumber, isSigned, placeMark, }: ViewerPdfPaneProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { lazy, Suspense, useCallback } from "react";
|
|
4
4
|
import { useArbiSessionState, useArbiSessionStore } from "@arbidocs/react";
|
|
5
5
|
import {
|
|
@@ -10,7 +10,10 @@ import {
|
|
|
10
10
|
} from "@arbidocs/react/viewers";
|
|
11
11
|
import { friendlyFileType } from "@arbidocs/react/ui";
|
|
12
12
|
import { ViewerLoadError, ViewerMessage, ViewerPreviewUnavailable } from "../../files/index.js";
|
|
13
|
+
import { usePdfPassageHighlights } from "./pdf/usePdfPassageHighlights.js";
|
|
13
14
|
import { useViewerIsDetached } from "./support.js";
|
|
15
|
+
import { isLegacyPresentationFile } from "../../presentation/panel-id.js";
|
|
16
|
+
import { PresentationFileCard } from "../presentation/PresentationFileCard.js";
|
|
14
17
|
import { fileExtension } from "./useViewedDocument.js";
|
|
15
18
|
const AnnotatedPdfViewer = lazy(
|
|
16
19
|
() => import("../../document-tools/viewer/index.js").then((m) => ({ default: m.AnnotatedPdfViewer }))
|
|
@@ -21,6 +24,12 @@ const SignaturePlacementViewer = lazy(
|
|
|
21
24
|
const SignatureRequestEditor = lazy(
|
|
22
25
|
() => import("../../document-tools/viewer/index.js").then((m) => ({ default: m.SignatureRequestEditor }))
|
|
23
26
|
);
|
|
27
|
+
const ClippingPdfViewer = lazy(
|
|
28
|
+
() => import("../presentation/ClippingPdfViewer.js").then((m) => ({ default: m.ClippingPdfViewer }))
|
|
29
|
+
);
|
|
30
|
+
const ClippingMediaViewer = lazy(
|
|
31
|
+
() => import("../presentation/ClippingMediaViewer.js").then((m) => ({ default: m.ClippingMediaViewer }))
|
|
32
|
+
);
|
|
24
33
|
const GuidedSigningViewer = lazy(
|
|
25
34
|
() => import("../../document-tools/viewer/index.js").then((m) => ({ default: m.GuidedSigningViewer }))
|
|
26
35
|
);
|
|
@@ -34,7 +43,24 @@ function SessionPdfViewer(props) {
|
|
|
34
43
|
},
|
|
35
44
|
[session, viewingId]
|
|
36
45
|
);
|
|
37
|
-
|
|
46
|
+
const passageHighlights = usePdfPassageHighlights(viewingId);
|
|
47
|
+
const { renderPageOverlay: modeOverlay } = props;
|
|
48
|
+
const renderPageOverlay = useCallback(
|
|
49
|
+
(page) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
passageHighlights(page.pageNumber),
|
|
51
|
+
modeOverlay?.(page)
|
|
52
|
+
] }),
|
|
53
|
+
[passageHighlights, modeOverlay]
|
|
54
|
+
);
|
|
55
|
+
return /* @__PURE__ */ jsx(
|
|
56
|
+
KitPdfViewer,
|
|
57
|
+
{
|
|
58
|
+
...props,
|
|
59
|
+
renderPageOverlay,
|
|
60
|
+
onPageChange,
|
|
61
|
+
disableFontFace: !!isDetached
|
|
62
|
+
}
|
|
63
|
+
);
|
|
38
64
|
}
|
|
39
65
|
function ViewerPdfPane({
|
|
40
66
|
documentId,
|
|
@@ -50,6 +76,7 @@ function ViewerPdfPane({
|
|
|
50
76
|
placingSignature,
|
|
51
77
|
onPlacingDone,
|
|
52
78
|
annotating,
|
|
79
|
+
clipping = false,
|
|
53
80
|
markup,
|
|
54
81
|
pdfSnapshotNumber,
|
|
55
82
|
isSigned,
|
|
@@ -57,6 +84,9 @@ function ViewerPdfPane({
|
|
|
57
84
|
}) {
|
|
58
85
|
const { documentData, isDownloadOnly, isVideo, isAudio, isImage, isDocx } = doc;
|
|
59
86
|
const showMarkup = markup.hasMarkup && !markup.showOriginal;
|
|
87
|
+
if (isLegacyPresentationFile(documentData?.file_name)) {
|
|
88
|
+
return /* @__PURE__ */ jsx(PresentationFileCard, { documentId, fileName: documentData?.file_name ?? "" });
|
|
89
|
+
}
|
|
60
90
|
if (isDownloadOnly) {
|
|
61
91
|
return /* @__PURE__ */ jsx(
|
|
62
92
|
ViewerPreviewUnavailable,
|
|
@@ -85,6 +115,17 @@ function ViewerPdfPane({
|
|
|
85
115
|
);
|
|
86
116
|
}
|
|
87
117
|
if (!pdfBlob) return /* @__PURE__ */ jsx(ViewerMessage, { children: loadingLabel });
|
|
118
|
+
if (clipping && (isImage || isVideo)) {
|
|
119
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsx(
|
|
120
|
+
ClippingMediaViewer,
|
|
121
|
+
{
|
|
122
|
+
file: pdfBlob,
|
|
123
|
+
kind: isVideo ? "video" : "image",
|
|
124
|
+
documentId,
|
|
125
|
+
fileName: documentData?.file_name || (isVideo ? "Video" : "Image")
|
|
126
|
+
}
|
|
127
|
+
) });
|
|
128
|
+
}
|
|
88
129
|
if (isVideo) return /* @__PURE__ */ jsx(VideoViewer, { blob: pdfBlob, title: documentData?.file_name || "Video" });
|
|
89
130
|
if (isAudio) return /* @__PURE__ */ jsx(AudioViewer, { blob: pdfBlob, title: documentData?.file_name || "Audio" });
|
|
90
131
|
if (isImage) {
|
|
@@ -135,6 +176,20 @@ function ViewerPdfPane({
|
|
|
135
176
|
}
|
|
136
177
|
) });
|
|
137
178
|
}
|
|
179
|
+
if (clipping) {
|
|
180
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ViewerMessage, { children: "Loading\u2026" }), children: /* @__PURE__ */ jsx(
|
|
181
|
+
ClippingPdfViewer,
|
|
182
|
+
{
|
|
183
|
+
...viewerProps,
|
|
184
|
+
file: pdfBlob,
|
|
185
|
+
documentId,
|
|
186
|
+
version: pdfSnapshotNumber,
|
|
187
|
+
fileName: documentData?.file_name || "Document",
|
|
188
|
+
hasMarkup: markup.hasMarkup,
|
|
189
|
+
viewer: SessionPdfViewer
|
|
190
|
+
}
|
|
191
|
+
) });
|
|
192
|
+
}
|
|
138
193
|
if (annotating || showMarkup) {
|
|
139
194
|
return /* @__PURE__ */ jsx(
|
|
140
195
|
Suspense,
|
|
@@ -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 { useViewerIsDetached } from './support'\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)\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 return <KitPdfViewer {...props} onPageChange={onPageChange} disableFontFace={!!isDetached} />\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 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 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 // 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 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 // 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 { 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 const { renderPageOverlay: modeOverlay } = props\n const renderPageOverlay = useCallback<NonNullable<PdfViewerProps['renderPageOverlay']>>(\n (page) => (\n <>\n {passageHighlights(page.pageNumber)}\n {modeOverlay?.(page)}\n </>\n ),\n [passageHighlights, 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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
|
-
import { Camera, Check, FileText, Mic, Video as VideoIcon } from "lucide-react";
|
|
4
|
+
import { Camera, Check, FileText, Mic, Presentation, Video as VideoIcon } from "lucide-react";
|
|
5
5
|
import {
|
|
6
6
|
DOCUMENT_VIEWER_PANEL,
|
|
7
7
|
DraftTitleControls,
|
|
@@ -33,7 +33,8 @@ const KIND_OPTIONS = [
|
|
|
33
33
|
{ value: "text", icon: /* @__PURE__ */ jsx(FileText, { className: "w-4 h-4" }), label: "Doc" },
|
|
34
34
|
{ value: "audio", icon: /* @__PURE__ */ jsx(Mic, { className: "w-4 h-4" }), label: "Voice" },
|
|
35
35
|
{ value: "video", icon: /* @__PURE__ */ jsx(VideoIcon, { className: "w-4 h-4" }), label: "Video" },
|
|
36
|
-
{ value: "photo", icon: /* @__PURE__ */ jsx(Camera, { className: "w-4 h-4" }), label: "Photo" }
|
|
36
|
+
{ value: "photo", icon: /* @__PURE__ */ jsx(Camera, { className: "w-4 h-4" }), label: "Photo" },
|
|
37
|
+
{ value: "presentation", icon: /* @__PURE__ */ jsx(Presentation, { className: "w-4 h-4" }), label: "Presentation" }
|
|
37
38
|
];
|
|
38
39
|
const useDraft = (documentId) => useArbiSessionState((state) => state.draftDocuments[documentId]);
|
|
39
40
|
function ViewerDraftKind({ documentId }) {
|
|
@@ -72,7 +73,8 @@ const TITLE_PLACEHOLDER = {
|
|
|
72
73
|
text: "New Doc",
|
|
73
74
|
audio: "New Audio",
|
|
74
75
|
photo: "New Photo",
|
|
75
|
-
video: "New Video"
|
|
76
|
+
video: "New Video",
|
|
77
|
+
presentation: "New Presentation"
|
|
76
78
|
};
|
|
77
79
|
function selectTitleOnFocus(event) {
|
|
78
80
|
if (event.target instanceof HTMLInputElement) event.target.select();
|
|
@@ -115,7 +117,7 @@ function ViewerCaptureDraft({ documentId }) {
|
|
|
115
117
|
const { notify } = useBlocksEnvironment();
|
|
116
118
|
const upload = useUploadDocuments();
|
|
117
119
|
const { data: userSettings } = useUserSettings();
|
|
118
|
-
if (!draft || draft.kind === "text") return null;
|
|
120
|
+
if (!draft || draft.kind === "text" || draft.kind === "presentation") return null;
|
|
119
121
|
const kind = draft.kind;
|
|
120
122
|
const file = CAPTURE_FILE[kind];
|
|
121
123
|
const discard = () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/viewer/drafts.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The viewer's unsaved drafts (the session's `draftDocuments`, started with `startDraftDocument`)\n * and its related documents. A draft has no backend record until it is saved: its kind (Doc,\n * Voice, Photo, Video) replaces the tabs, its editable name replaces the title, and a capture\n * draft's recorder is the whole body. A capture saves straight to the workspace as its own\n * document (`useUploadDocuments`), with the user's active configuration, so the backend can name it\n * from its content.\n */\n\nimport { useMemo, type FocusEvent, type ReactNode } from 'react'\nimport { Camera, Check, FileText, Mic, Video as VideoIcon } from 'lucide-react'\nimport {\n DOCUMENT_VIEWER_PANEL,\n DraftTitleControls,\n PhotoCapture,\n VideoCapture,\n VoiceNoteRecorder,\n isPanelOpen,\n useArbi,\n useArbiSessionState,\n useArbiSessionStore,\n useConfig,\n useSaveConfigField,\n useUploadDocuments,\n useUserSettings,\n type ArbiDraftDocument,\n type ArbiDraftKind,\n type WorkspaceDocument,\n} from '@arbidocs/react'\nimport {\n useDictateContext,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@arbidocs/react/ui'\nimport { logger } from '@arbidocs/client'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { RelatedDocumentsCell } from '../files/grid/cells'\nimport { useFilesDialogs } from '../files/store'\nimport type { ViewerDocumentRecord } from './support'\nimport { compareDocumentsIn } from './compareDocuments'\n\nconst KIND_OPTIONS: { value: ArbiDraftKind; icon: ReactNode; label: string }[] = [\n { value: 'text', icon: <FileText className=\"w-4 h-4\" />, label: 'Doc' },\n { value: 'audio', icon: <Mic className=\"w-4 h-4\" />, label: 'Voice' },\n { value: 'video', icon: <VideoIcon className=\"w-4 h-4\" />, label: 'Video' },\n { value: 'photo', icon: <Camera className=\"w-4 h-4\" />, label: 'Photo' },\n]\n\nconst useDraft = (documentId: string): ArbiDraftDocument | undefined =>\n useArbiSessionState((state) => state.draftDocuments[documentId])\n\n/**\n * A draft's kind, in place of the tabs: the icon of its kind opens the four kinds, so the user can\n * switch before capturing or typing anything.\n */\nexport function ViewerDraftKind({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n if (!draft) return null\n const current = KIND_OPTIONS.find((option) => option.value === draft.kind) ?? KIND_OPTIONS[0]\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n title={`Draft kind: ${current.label}. Click to change.`}\n aria-label={`Draft kind: ${current.label}. Click to change.`}\n className=\"px-3 py-2 transition-all duration-200 font-medium border-b-2 border-transparent text-muted-foreground hover:text-foreground hover:border-border flex-shrink-0 flex items-center\"\n data-testid=\"draft-kind-trigger\"\n >\n {current.icon}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" sideOffset={4} className=\"w-40\">\n {KIND_OPTIONS.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onSelect={() => session.setDraftDocumentKind(documentId, option.value)}\n data-testid={`draft-kind-option-${option.value}`}\n >\n {option.icon}\n <span>{option.label}</span>\n {option.value === draft.kind && <Check className=\"ml-auto w-4 h-4\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nconst TITLE_PLACEHOLDER: Record<ArbiDraftKind, string> = {\n text: 'New Doc',\n audio: 'New Audio',\n photo: 'New Photo',\n video: 'New Video',\n}\n\n// The draft starts with a real default name (\"New Doc\"), not a placeholder, so focusing the field\n// selects it: typing then replaces it instead of appending to it.\nfunction selectTitleOnFocus(event: FocusEvent<HTMLDivElement>) {\n if (event.target instanceof HTMLInputElement) event.target.select()\n}\n\n/**\n * A draft's editable name, in place of the title, with the auto-name switch: the active\n * configuration's `DoctagLLM.AUTO_RENAME`, the same setting as the upload dialog's.\n */\nexport function ViewerDraftTitle({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n const { data: userSettings } = useUserSettings()\n const { data: activeConfig } = useConfig(userSettings?.last_config || 'default')\n const configField = useSaveConfigField()\n const config = activeConfig as { DoctagLLM?: { AUTO_RENAME?: boolean } } | undefined\n const autoRename = config?.DoctagLLM?.AUTO_RENAME ?? false\n\n if (!draft) return null\n return (\n <div className=\"contents\" onFocus={selectTitleOnFocus}>\n <DraftTitleControls\n title={draft.title}\n onTitleChange={(title) => session.updateDraftDocument(documentId, { title })}\n placeholder={TITLE_PLACEHOLDER[draft.kind] ?? TITLE_PLACEHOLDER.text}\n autoRename={autoRename}\n onAutoRenameChange={(value) => configField.save('DoctagLLM', 'AUTO_RENAME', value)}\n />\n </div>\n )\n}\n\n/** Each capture's file name and the type used when the recorder reports none. */\nconst CAPTURE_FILE: Record<\n 'audio' | 'photo' | 'video',\n { name: string; fallbackType: string; saved: string; label: string }\n> = {\n audio: {\n name: 'voice-note.webm',\n fallbackType: 'audio/webm',\n saved: 'Voice note saved \u2014 transcribing\u2026',\n label: 'voice note',\n },\n photo: { name: 'photo.png', fallbackType: 'image/png', saved: 'Photo saved', label: 'photo' },\n video: { name: 'video.webm', fallbackType: 'video/webm', saved: 'Video saved', label: 'video' },\n}\n\n/**\n * A capture draft's recorder (voice, photo or video), the whole body of the viewer. The finished\n * capture is kept in the draft first, so it survives the viewer closing even if the save fails;\n * the draft is cleared once the saved document's id is known and the viewer moves to it.\n */\nexport function ViewerCaptureDraft({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n const arbi = useArbi()\n const dictate = useDictateContext()\n const { notify } = useBlocksEnvironment()\n const upload = useUploadDocuments()\n const { data: userSettings } = useUserSettings()\n\n if (!draft || draft.kind === 'text') return null\n const kind = draft.kind\n const file = CAPTURE_FILE[kind]\n\n const discard = () => {\n session.clearDraftDocument(documentId)\n session.setViewingDocument(null)\n }\n const save = async (blob: Blob, mimeType: string | null) => {\n session.updateDraftDocument(documentId, { mediaBlob: blob })\n try {\n const response = await upload.mutateAsync({\n files: [new File([blob], file.name, { type: mimeType || file.fallbackType })],\n options: { configExtId: userSettings?.last_config ?? undefined },\n })\n // The id often arrives later (on the realtime channel): only leave the draft for a real one.\n const newDocId = response.doc_ext_ids?.[0]\n if (newDocId) {\n session.clearDraftDocument(documentId)\n session.setViewingDocument({ id: newDocId, page: null })\n }\n notify(file.saved, 'success')\n } catch (err) {\n logger.error(`[ViewerCaptureDraft] Saving the ${file.label} failed`, err)\n notify(`Could not save the ${file.label}. Please try again.`, 'error')\n }\n }\n const onError = (message: string) => notify(message, 'error')\n\n return (\n <div className=\"h-full overflow-hidden\" data-testid=\"media-capture-recorder\">\n {kind === 'audio' && (\n <VoiceNoteRecorder\n title={draft.title}\n isSaving={upload.isPending}\n onSave={save}\n onDiscard={discard}\n onError={onError}\n // A rough transcript while reviewing (the host's dictation, else the session's); the real\n // one comes with the saved document.\n transcribe={(blob) =>\n dictate ? dictate.transcribe(blob) : arbi.assistant.transcribe(blob)\n }\n />\n )}\n {kind === 'photo' && (\n <PhotoCapture\n onSave={save}\n onDiscard={discard}\n onError={onError}\n isSaving={upload.isPending}\n />\n )}\n {kind === 'video' && (\n <VideoCapture\n onSave={save}\n onDiscard={discard}\n onError={onError}\n isSaving={upload.isPending}\n />\n )}\n </div>\n )\n}\n\n/**\n * The documents related to the open one (its email family, copies, near duplicates), beside its\n * name: one opens in the viewer, and each can be deleted or compared with it.\n */\nexport function ViewerRelatedDocuments({ document }: { document: ViewerDocumentRecord }) {\n const session = useArbiSessionStore()\n const related = useArbiSessionState((state) => state.relatedDocuments.get(document.external_id))\n const viewerOpen = useArbiSessionState((state) => isPanelOpen(state, DOCUMENT_VIEWER_PANEL))\n const viewingId = useArbiSessionState((state) => state.viewingDocument?.id ?? null)\n const onCompare = useMemo(\n () => (id: string, otherId: string) => compareDocumentsIn(session, id, otherId),\n [session]\n )\n if (!related) return null\n return (\n <RelatedDocumentsCell\n currentDoc={document as WorkspaceDocument}\n related={related}\n viewingDocumentId={viewerOpen ? viewingId : null}\n onDocumentClick={(id) => session.setViewingDocument({ id, page: null })}\n onDelete={(doc) => useFilesDialogs.getState().requestDelete(doc)}\n onCompare={onCompare}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": ";AA4CyB,
|
|
4
|
+
"sourcesContent": ["/**\n * The viewer's unsaved drafts (the session's `draftDocuments`, started with `startDraftDocument`)\n * and its related documents. A draft has no backend record until it is saved: its kind (Doc,\n * Voice, Photo, Video) replaces the tabs, its editable name replaces the title, and a capture\n * draft's recorder is the whole body. A capture saves straight to the workspace as its own\n * document (`useUploadDocuments`), with the user's active configuration, so the backend can name it\n * from its content.\n */\n\nimport { useMemo, type FocusEvent, type ReactNode } from 'react'\nimport { Camera, Check, FileText, Mic, Presentation, Video as VideoIcon } from 'lucide-react'\nimport {\n DOCUMENT_VIEWER_PANEL,\n DraftTitleControls,\n PhotoCapture,\n VideoCapture,\n VoiceNoteRecorder,\n isPanelOpen,\n useArbi,\n useArbiSessionState,\n useArbiSessionStore,\n useConfig,\n useSaveConfigField,\n useUploadDocuments,\n useUserSettings,\n type ArbiDraftDocument,\n type ArbiDraftKind,\n type WorkspaceDocument,\n} from '@arbidocs/react'\nimport {\n useDictateContext,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@arbidocs/react/ui'\nimport { logger } from '@arbidocs/client'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { RelatedDocumentsCell } from '../files/grid/cells'\nimport { useFilesDialogs } from '../files/store'\nimport type { ViewerDocumentRecord } from './support'\nimport { compareDocumentsIn } from './compareDocuments'\n\nconst KIND_OPTIONS: { value: ArbiDraftKind; icon: ReactNode; label: string }[] = [\n { value: 'text', icon: <FileText className=\"w-4 h-4\" />, label: 'Doc' },\n { value: 'audio', icon: <Mic className=\"w-4 h-4\" />, label: 'Voice' },\n { value: 'video', icon: <VideoIcon className=\"w-4 h-4\" />, label: 'Video' },\n { value: 'photo', icon: <Camera className=\"w-4 h-4\" />, label: 'Photo' },\n { value: 'presentation', icon: <Presentation className=\"w-4 h-4\" />, label: 'Presentation' },\n]\n\nconst useDraft = (documentId: string): ArbiDraftDocument | undefined =>\n useArbiSessionState((state) => state.draftDocuments[documentId])\n\n/**\n * A draft's kind, in place of the tabs: the icon of its kind opens the four kinds, so the user can\n * switch before capturing or typing anything.\n */\nexport function ViewerDraftKind({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n if (!draft) return null\n const current = KIND_OPTIONS.find((option) => option.value === draft.kind) ?? KIND_OPTIONS[0]\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n title={`Draft kind: ${current.label}. Click to change.`}\n aria-label={`Draft kind: ${current.label}. Click to change.`}\n className=\"px-3 py-2 transition-all duration-200 font-medium border-b-2 border-transparent text-muted-foreground hover:text-foreground hover:border-border flex-shrink-0 flex items-center\"\n data-testid=\"draft-kind-trigger\"\n >\n {current.icon}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" sideOffset={4} className=\"w-40\">\n {KIND_OPTIONS.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onSelect={() => session.setDraftDocumentKind(documentId, option.value)}\n data-testid={`draft-kind-option-${option.value}`}\n >\n {option.icon}\n <span>{option.label}</span>\n {option.value === draft.kind && <Check className=\"ml-auto w-4 h-4\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nconst TITLE_PLACEHOLDER: Record<ArbiDraftKind, string> = {\n text: 'New Doc',\n audio: 'New Audio',\n photo: 'New Photo',\n video: 'New Video',\n presentation: 'New Presentation',\n}\n\n// The draft starts with a real default name (\"New Doc\"), not a placeholder, so focusing the field\n// selects it: typing then replaces it instead of appending to it.\nfunction selectTitleOnFocus(event: FocusEvent<HTMLDivElement>) {\n if (event.target instanceof HTMLInputElement) event.target.select()\n}\n\n/**\n * A draft's editable name, in place of the title, with the auto-name switch: the active\n * configuration's `DoctagLLM.AUTO_RENAME`, the same setting as the upload dialog's.\n */\nexport function ViewerDraftTitle({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n const { data: userSettings } = useUserSettings()\n const { data: activeConfig } = useConfig(userSettings?.last_config || 'default')\n const configField = useSaveConfigField()\n const config = activeConfig as { DoctagLLM?: { AUTO_RENAME?: boolean } } | undefined\n const autoRename = config?.DoctagLLM?.AUTO_RENAME ?? false\n\n if (!draft) return null\n return (\n <div className=\"contents\" onFocus={selectTitleOnFocus}>\n <DraftTitleControls\n title={draft.title}\n onTitleChange={(title) => session.updateDraftDocument(documentId, { title })}\n placeholder={TITLE_PLACEHOLDER[draft.kind] ?? TITLE_PLACEHOLDER.text}\n autoRename={autoRename}\n onAutoRenameChange={(value) => configField.save('DoctagLLM', 'AUTO_RENAME', value)}\n />\n </div>\n )\n}\n\n/** Each capture's file name and the type used when the recorder reports none. */\nconst CAPTURE_FILE: Record<\n 'audio' | 'photo' | 'video',\n { name: string; fallbackType: string; saved: string; label: string }\n> = {\n audio: {\n name: 'voice-note.webm',\n fallbackType: 'audio/webm',\n saved: 'Voice note saved \u2014 transcribing\u2026',\n label: 'voice note',\n },\n photo: { name: 'photo.png', fallbackType: 'image/png', saved: 'Photo saved', label: 'photo' },\n video: { name: 'video.webm', fallbackType: 'video/webm', saved: 'Video saved', label: 'video' },\n}\n\n/**\n * A capture draft's recorder (voice, photo or video), the whole body of the viewer. The finished\n * capture is kept in the draft first, so it survives the viewer closing even if the save fails;\n * the draft is cleared once the saved document's id is known and the viewer moves to it.\n */\nexport function ViewerCaptureDraft({ documentId }: { documentId: string }) {\n const draft = useDraft(documentId)\n const session = useArbiSessionStore()\n const arbi = useArbi()\n const dictate = useDictateContext()\n const { notify } = useBlocksEnvironment()\n const upload = useUploadDocuments()\n const { data: userSettings } = useUserSettings()\n\n if (!draft || draft.kind === 'text' || draft.kind === 'presentation') return null\n const kind = draft.kind\n const file = CAPTURE_FILE[kind]\n\n const discard = () => {\n session.clearDraftDocument(documentId)\n session.setViewingDocument(null)\n }\n const save = async (blob: Blob, mimeType: string | null) => {\n session.updateDraftDocument(documentId, { mediaBlob: blob })\n try {\n const response = await upload.mutateAsync({\n files: [new File([blob], file.name, { type: mimeType || file.fallbackType })],\n options: { configExtId: userSettings?.last_config ?? undefined },\n })\n // The id often arrives later (on the realtime channel): only leave the draft for a real one.\n const newDocId = response.doc_ext_ids?.[0]\n if (newDocId) {\n session.clearDraftDocument(documentId)\n session.setViewingDocument({ id: newDocId, page: null })\n }\n notify(file.saved, 'success')\n } catch (err) {\n logger.error(`[ViewerCaptureDraft] Saving the ${file.label} failed`, err)\n notify(`Could not save the ${file.label}. Please try again.`, 'error')\n }\n }\n const onError = (message: string) => notify(message, 'error')\n\n return (\n <div className=\"h-full overflow-hidden\" data-testid=\"media-capture-recorder\">\n {kind === 'audio' && (\n <VoiceNoteRecorder\n title={draft.title}\n isSaving={upload.isPending}\n onSave={save}\n onDiscard={discard}\n onError={onError}\n // A rough transcript while reviewing (the host's dictation, else the session's); the real\n // one comes with the saved document.\n transcribe={(blob) =>\n dictate ? dictate.transcribe(blob) : arbi.assistant.transcribe(blob)\n }\n />\n )}\n {kind === 'photo' && (\n <PhotoCapture\n onSave={save}\n onDiscard={discard}\n onError={onError}\n isSaving={upload.isPending}\n />\n )}\n {kind === 'video' && (\n <VideoCapture\n onSave={save}\n onDiscard={discard}\n onError={onError}\n isSaving={upload.isPending}\n />\n )}\n </div>\n )\n}\n\n/**\n * The documents related to the open one (its email family, copies, near duplicates), beside its\n * name: one opens in the viewer, and each can be deleted or compared with it.\n */\nexport function ViewerRelatedDocuments({ document }: { document: ViewerDocumentRecord }) {\n const session = useArbiSessionStore()\n const related = useArbiSessionState((state) => state.relatedDocuments.get(document.external_id))\n const viewerOpen = useArbiSessionState((state) => isPanelOpen(state, DOCUMENT_VIEWER_PANEL))\n const viewingId = useArbiSessionState((state) => state.viewingDocument?.id ?? null)\n const onCompare = useMemo(\n () => (id: string, otherId: string) => compareDocumentsIn(session, id, otherId),\n [session]\n )\n if (!related) return null\n return (\n <RelatedDocumentsCell\n currentDoc={document as WorkspaceDocument}\n related={related}\n viewingDocumentId={viewerOpen ? viewingId : null}\n onDocumentClick={(id) => session.setViewingDocument({ id, page: null })}\n onDelete={(doc) => useFilesDialogs.getState().requestDelete(doc)}\n onCompare={onCompare}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AA4CyB,cAkCf,YAlCe;AAnCzB,SAAS,eAAgD;AACzD,SAAS,QAAQ,OAAO,UAAU,KAAK,cAAc,SAAS,iBAAiB;AAC/E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AACrC,SAAS,uBAAuB;AAEhC,SAAS,0BAA0B;AAEnC,MAAM,eAA2E;AAAA,EAC/E,EAAE,OAAO,QAAQ,MAAM,oBAAC,YAAS,WAAU,WAAU,GAAI,OAAO,MAAM;AAAA,EACtE,EAAE,OAAO,SAAS,MAAM,oBAAC,OAAI,WAAU,WAAU,GAAI,OAAO,QAAQ;AAAA,EACpE,EAAE,OAAO,SAAS,MAAM,oBAAC,aAAU,WAAU,WAAU,GAAI,OAAO,QAAQ;AAAA,EAC1E,EAAE,OAAO,SAAS,MAAM,oBAAC,UAAO,WAAU,WAAU,GAAI,OAAO,QAAQ;AAAA,EACvE,EAAE,OAAO,gBAAgB,MAAM,oBAAC,gBAAa,WAAU,WAAU,GAAI,OAAO,eAAe;AAC7F;AAEA,MAAM,WAAW,CAAC,eAChB,oBAAoB,CAAC,UAAU,MAAM,eAAe,UAAU,CAAC;AAM1D,SAAS,gBAAgB,EAAE,WAAW,GAA2B;AACtE,QAAM,QAAQ,SAAS,UAAU;AACjC,QAAM,UAAU,oBAAoB;AACpC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,aAAa,KAAK,CAAC,WAAW,OAAO,UAAU,MAAM,IAAI,KAAK,aAAa,CAAC;AAC5F,SACE,qBAAC,gBACC;AAAA,wBAAC,uBAAoB,SAAO,MAC1B;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,eAAe,QAAQ,KAAK;AAAA,QACnC,cAAY,eAAe,QAAQ,KAAK;AAAA,QACxC,WAAU;AAAA,QACV,eAAY;AAAA,QAEX,kBAAQ;AAAA;AAAA,IACX,GACF;AAAA,IACA,oBAAC,uBAAoB,OAAM,SAAQ,YAAY,GAAG,WAAU,QACzD,uBAAa,IAAI,CAAC,WACjB;AAAA,MAAC;AAAA;AAAA,QAEC,UAAU,MAAM,QAAQ,qBAAqB,YAAY,OAAO,KAAK;AAAA,QACrE,eAAa,qBAAqB,OAAO,KAAK;AAAA,QAE7C;AAAA,iBAAO;AAAA,UACR,oBAAC,UAAM,iBAAO,OAAM;AAAA,UACnB,OAAO,UAAU,MAAM,QAAQ,oBAAC,SAAM,WAAU,mBAAkB;AAAA;AAAA;AAAA,MAN9D,OAAO;AAAA,IAOd,CACD,GACH;AAAA,KACF;AAEJ;AAEA,MAAM,oBAAmD;AAAA,EACvD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,cAAc;AAChB;AAIA,SAAS,mBAAmB,OAAmC;AAC7D,MAAI,MAAM,kBAAkB,iBAAkB,OAAM,OAAO,OAAO;AACpE;AAMO,SAAS,iBAAiB,EAAE,WAAW,GAA2B;AACvE,QAAM,QAAQ,SAAS,UAAU;AACjC,QAAM,UAAU,oBAAoB;AACpC,QAAM,EAAE,MAAM,aAAa,IAAI,gBAAgB;AAC/C,QAAM,EAAE,MAAM,aAAa,IAAI,UAAU,cAAc,eAAe,SAAS;AAC/E,QAAM,cAAc,mBAAmB;AACvC,QAAM,SAAS;AACf,QAAM,aAAa,QAAQ,WAAW,eAAe;AAErD,MAAI,CAAC,MAAO,QAAO;AACnB,SACE,oBAAC,SAAI,WAAU,YAAW,SAAS,oBACjC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,MAAM;AAAA,MACb,eAAe,CAAC,UAAU,QAAQ,oBAAoB,YAAY,EAAE,MAAM,CAAC;AAAA,MAC3E,aAAa,kBAAkB,MAAM,IAAI,KAAK,kBAAkB;AAAA,MAChE;AAAA,MACA,oBAAoB,CAAC,UAAU,YAAY,KAAK,aAAa,eAAe,KAAK;AAAA;AAAA,EACnF,GACF;AAEJ;AAGA,MAAM,eAGF;AAAA,EACF,OAAO;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,IACd,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA,OAAO,EAAE,MAAM,aAAa,cAAc,aAAa,OAAO,eAAe,OAAO,QAAQ;AAAA,EAC5F,OAAO,EAAE,MAAM,cAAc,cAAc,cAAc,OAAO,eAAe,OAAO,QAAQ;AAChG;AAOO,SAAS,mBAAmB,EAAE,WAAW,GAA2B;AACzE,QAAM,QAAQ,SAAS,UAAU;AACjC,QAAM,UAAU,oBAAoB;AACpC,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,kBAAkB;AAClC,QAAM,EAAE,OAAO,IAAI,qBAAqB;AACxC,QAAM,SAAS,mBAAmB;AAClC,QAAM,EAAE,MAAM,aAAa,IAAI,gBAAgB;AAE/C,MAAI,CAAC,SAAS,MAAM,SAAS,UAAU,MAAM,SAAS,eAAgB,QAAO;AAC7E,QAAM,OAAO,MAAM;AACnB,QAAM,OAAO,aAAa,IAAI;AAE9B,QAAM,UAAU,MAAM;AACpB,YAAQ,mBAAmB,UAAU;AACrC,YAAQ,mBAAmB,IAAI;AAAA,EACjC;AACA,QAAM,OAAO,OAAO,MAAY,aAA4B;AAC1D,YAAQ,oBAAoB,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3D,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,YAAY;AAAA,QACxC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,MAAM,EAAE,MAAM,YAAY,KAAK,aAAa,CAAC,CAAC;AAAA,QAC5E,SAAS,EAAE,aAAa,cAAc,eAAe,OAAU;AAAA,MACjE,CAAC;AAED,YAAM,WAAW,SAAS,cAAc,CAAC;AACzC,UAAI,UAAU;AACZ,gBAAQ,mBAAmB,UAAU;AACrC,gBAAQ,mBAAmB,EAAE,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACzD;AACA,aAAO,KAAK,OAAO,SAAS;AAAA,IAC9B,SAAS,KAAK;AACZ,aAAO,MAAM,mCAAmC,KAAK,KAAK,WAAW,GAAG;AACxE,aAAO,sBAAsB,KAAK,KAAK,uBAAuB,OAAO;AAAA,IACvE;AAAA,EACF;AACA,QAAM,UAAU,CAAC,YAAoB,OAAO,SAAS,OAAO;AAE5D,SACE,qBAAC,SAAI,WAAU,0BAAyB,eAAY,0BACjD;AAAA,aAAS,WACR;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,MAAM;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,QAAQ;AAAA,QACR,WAAW;AAAA,QACX;AAAA,QAGA,YAAY,CAAC,SACX,UAAU,QAAQ,WAAW,IAAI,IAAI,KAAK,UAAU,WAAW,IAAI;AAAA;AAAA,IAEvE;AAAA,IAED,SAAS,WACR;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,WAAW;AAAA,QACX;AAAA,QACA,UAAU,OAAO;AAAA;AAAA,IACnB;AAAA,IAED,SAAS,WACR;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,WAAW;AAAA,QACX;AAAA,QACA,UAAU,OAAO;AAAA;AAAA,IACnB;AAAA,KAEJ;AAEJ;AAMO,SAAS,uBAAuB,EAAE,SAAS,GAAuC;AACvF,QAAM,UAAU,oBAAoB;AACpC,QAAM,UAAU,oBAAoB,CAAC,UAAU,MAAM,iBAAiB,IAAI,SAAS,WAAW,CAAC;AAC/F,QAAM,aAAa,oBAAoB,CAAC,UAAU,YAAY,OAAO,qBAAqB,CAAC;AAC3F,QAAM,YAAY,oBAAoB,CAAC,UAAU,MAAM,iBAAiB,MAAM,IAAI;AAClF,QAAM,YAAY;AAAA,IAChB,MAAM,CAAC,IAAY,YAAoB,mBAAmB,SAAS,IAAI,OAAO;AAAA,IAC9E,CAAC,OAAO;AAAA,EACV;AACA,MAAI,CAAC,QAAS,QAAO;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,YAAY;AAAA,MACZ;AAAA,MACA,mBAAmB,aAAa,YAAY;AAAA,MAC5C,iBAAiB,CAAC,OAAO,QAAQ,mBAAmB,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,MACtE,UAAU,CAAC,QAAQ,gBAAgB,SAAS,EAAE,cAAc,GAAG;AAAA,MAC/D;AAAA;AAAA,EACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lit passages of one PDF page, drawn over it. The boxes are fractions of the page, so the layer
|
|
3
|
+
* fills the page area and scales with it; it takes no pointer events, so the PDF stays selectable.
|
|
4
|
+
*/
|
|
5
|
+
import type { PdfPassageBox } from './passageHighlights';
|
|
6
|
+
export interface PdfPassageHighlightsProps {
|
|
7
|
+
boxes: readonly PdfPassageBox[];
|
|
8
|
+
/** The passage being read: its box is told to the host once it is drawn, to bring it into view. */
|
|
9
|
+
activeId: string | null;
|
|
10
|
+
onActiveDrawn: (element: HTMLElement) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function PdfPassageHighlights({ boxes, activeId, onActiveDrawn, }: PdfPassageHighlightsProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "@arbidocs/react/ui";
|
|
4
|
+
function PdfPassageHighlights({
|
|
5
|
+
boxes,
|
|
6
|
+
activeId,
|
|
7
|
+
onActiveDrawn
|
|
8
|
+
}) {
|
|
9
|
+
return /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0", "data-testid": "pdf-passage-highlights", children: boxes.map(({ chunkId, box: [x0, y0, x1, y1], highlight }) => /* @__PURE__ */ jsx(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
ref: chunkId === activeId ? (element) => {
|
|
13
|
+
if (element) onActiveDrawn(element);
|
|
14
|
+
} : void 0,
|
|
15
|
+
"data-testid": "pdf-passage-highlight",
|
|
16
|
+
"data-chunk-id": chunkId,
|
|
17
|
+
"data-highlight": highlight,
|
|
18
|
+
className: cn(
|
|
19
|
+
// multiplied, so the page's text stays as dark as it was under the wash
|
|
20
|
+
"absolute rounded-sm mix-blend-multiply",
|
|
21
|
+
highlight === "strong" ? "bg-ai-soft ring-1 ring-ai-accent/50" : "bg-ai-soft/60"
|
|
22
|
+
),
|
|
23
|
+
style: {
|
|
24
|
+
left: `${x0 * 100}%`,
|
|
25
|
+
top: `${y0 * 100}%`,
|
|
26
|
+
width: `${(x1 - x0) * 100}%`,
|
|
27
|
+
height: `${(y1 - y0) * 100}%`
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
chunkId
|
|
31
|
+
)) });
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
PdfPassageHighlights
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=PdfPassageHighlights.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/connection/viewer/pdf/PdfPassageHighlights.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The lit passages of one PDF page, drawn over it. The boxes are fractions of the page, so the layer\n * fills the page area and scales with it; it takes no pointer events, so the PDF stays selectable.\n */\n\nimport { cn } from '@arbidocs/react/ui'\nimport type { PdfPassageBox } from './passageHighlights'\n\nexport interface PdfPassageHighlightsProps {\n boxes: readonly PdfPassageBox[]\n /** The passage being read: its box is told to the host once it is drawn, to bring it into view. */\n activeId: string | null\n onActiveDrawn: (element: HTMLElement) => void\n}\n\nexport function PdfPassageHighlights({\n boxes,\n activeId,\n onActiveDrawn,\n}: PdfPassageHighlightsProps) {\n return (\n <div className=\"pointer-events-none absolute inset-0\" data-testid=\"pdf-passage-highlights\">\n {boxes.map(({ chunkId, box: [x0, y0, x1, y1], highlight }) => (\n <div\n key={chunkId}\n ref={\n chunkId === activeId\n ? (element) => {\n if (element) onActiveDrawn(element)\n }\n : undefined\n }\n data-testid=\"pdf-passage-highlight\"\n data-chunk-id={chunkId}\n data-highlight={highlight}\n className={cn(\n // multiplied, so the page's text stays as dark as it was under the wash\n 'absolute rounded-sm mix-blend-multiply',\n highlight === 'strong' ? 'bg-ai-soft ring-1 ring-ai-accent/50' : 'bg-ai-soft/60'\n )}\n style={{\n left: `${x0 * 100}%`,\n top: `${y0 * 100}%`,\n width: `${(x1 - x0) * 100}%`,\n height: `${(y1 - y0) * 100}%`,\n }}\n />\n ))}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAuBQ;AAlBR,SAAS,UAAU;AAUZ,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,SACE,oBAAC,SAAI,WAAU,wCAAuC,eAAY,0BAC/D,gBAAM,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,UAAU,MACtD;AAAA,IAAC;AAAA;AAAA,MAEC,KACE,YAAY,WACR,CAAC,YAAY;AACX,YAAI,QAAS,eAAc,OAAO;AAAA,MACpC,IACA;AAAA,MAEN,eAAY;AAAA,MACZ,iBAAe;AAAA,MACf,kBAAgB;AAAA,MAChB,WAAW;AAAA;AAAA,QAET;AAAA,QACA,cAAc,WAAW,wCAAwC;AAAA,MACnE;AAAA,MACA,OAAO;AAAA,QACL,MAAM,GAAG,KAAK,GAAG;AAAA,QACjB,KAAK,GAAG,KAAK,GAAG;AAAA,QAChB,OAAO,IAAI,KAAK,MAAM,GAAG;AAAA,QACzB,QAAQ,IAAI,KAAK,MAAM,GAAG;AAAA,MAC5B;AAAA;AAAA,IArBK;AAAA,EAsBP,CACD,GACH;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which passages light up on the PDF, and where. The rules are the parsed view's (`ParsedPassage`):
|
|
3
|
+
* while a fact's Citation popover is open its cited passages are light and the one being read is
|
|
4
|
+
* strong; otherwise the passage a citation opened the document at is the one lit. A passage's box
|
|
5
|
+
* is the parser's (`page_bbox`: fractions of its page, top-left origin), so it lands on the page
|
|
6
|
+
* at any zoom.
|
|
7
|
+
*/
|
|
8
|
+
import type { ProcessedPage } from '@arbidocs/react/viewers';
|
|
9
|
+
import type { PassageHighlight } from '../../../files';
|
|
10
|
+
/** [x0, y0, x1, y1] as fractions of the page. */
|
|
11
|
+
export type PageBox = readonly [number, number, number, number];
|
|
12
|
+
export interface PdfPassageBox {
|
|
13
|
+
chunkId: string;
|
|
14
|
+
box: PageBox;
|
|
15
|
+
highlight: PassageHighlight;
|
|
16
|
+
}
|
|
17
|
+
export interface PassageHighlightState {
|
|
18
|
+
/** A fact's cited passages (its Citation popover is open); empty when none is. */
|
|
19
|
+
cited: ReadonlySet<string>;
|
|
20
|
+
/** The passage being read: the one a citation opened the document at. */
|
|
21
|
+
active: string | null;
|
|
22
|
+
}
|
|
23
|
+
/** How a passage is lit, or null when it is not. */
|
|
24
|
+
export declare function passageHighlight(chunkId: string, { cited, active }: PassageHighlightState): PassageHighlight | null;
|
|
25
|
+
/** The lit passages' boxes, by page number. Passages without a usable box are left out. */
|
|
26
|
+
export declare function passageBoxesByPage(pages: readonly ProcessedPage[], state: PassageHighlightState): Map<number, PdfPassageBox[]>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
function passageHighlight(chunkId, { cited, active }) {
|
|
3
|
+
if (cited.size > 0) {
|
|
4
|
+
if (!cited.has(chunkId)) return null;
|
|
5
|
+
return chunkId === active ? "strong" : "light";
|
|
6
|
+
}
|
|
7
|
+
return chunkId === active ? "light" : null;
|
|
8
|
+
}
|
|
9
|
+
function asBox(bbox) {
|
|
10
|
+
if (!bbox || bbox.length !== 4 || !bbox.every(Number.isFinite)) return null;
|
|
11
|
+
const [x0, y0, x1, y1] = bbox;
|
|
12
|
+
if (x1 <= x0 || y1 <= y0) return null;
|
|
13
|
+
return [x0, y0, x1, y1];
|
|
14
|
+
}
|
|
15
|
+
function isWholePage([x0, y0, x1, y1]) {
|
|
16
|
+
return x0 <= 0 && y0 <= 0 && x1 >= 1 && y1 >= 1;
|
|
17
|
+
}
|
|
18
|
+
function passageBoxesByPage(pages, state) {
|
|
19
|
+
const byPage = /* @__PURE__ */ new Map();
|
|
20
|
+
if (state.cited.size === 0 && !state.active) return byPage;
|
|
21
|
+
for (const page of pages) {
|
|
22
|
+
if (page.pageNumber === null) continue;
|
|
23
|
+
for (const chunk of page.chunks) {
|
|
24
|
+
const chunkId = chunk.chunkExtId;
|
|
25
|
+
if (!chunkId) continue;
|
|
26
|
+
const highlight = passageHighlight(chunkId, state);
|
|
27
|
+
const box = highlight && asBox(chunk.pageBbox);
|
|
28
|
+
if (!highlight || !box || isWholePage(box)) continue;
|
|
29
|
+
const boxes = byPage.get(page.pageNumber) ?? [];
|
|
30
|
+
boxes.push({ chunkId, box, highlight });
|
|
31
|
+
byPage.set(page.pageNumber, boxes);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return byPage;
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
passageBoxesByPage,
|
|
38
|
+
passageHighlight
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=passageHighlights.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/connection/viewer/pdf/passageHighlights.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Which passages light up on the PDF, and where. The rules are the parsed view's (`ParsedPassage`):\n * while a fact's Citation popover is open its cited passages are light and the one being read is\n * strong; otherwise the passage a citation opened the document at is the one lit. A passage's box\n * is the parser's (`page_bbox`: fractions of its page, top-left origin), so it lands on the page\n * at any zoom.\n */\n\nimport type { ProcessedPage } from '@arbidocs/react/viewers'\nimport type { PassageHighlight } from '../../../files'\n\n/** [x0, y0, x1, y1] as fractions of the page. */\nexport type PageBox = readonly [number, number, number, number]\n\nexport interface PdfPassageBox {\n chunkId: string\n box: PageBox\n highlight: PassageHighlight\n}\n\nexport interface PassageHighlightState {\n /** A fact's cited passages (its Citation popover is open); empty when none is. */\n cited: ReadonlySet<string>\n /** The passage being read: the one a citation opened the document at. */\n active: string | null\n}\n\n/** How a passage is lit, or null when it is not. */\nexport function passageHighlight(\n chunkId: string,\n { cited, active }: PassageHighlightState\n): PassageHighlight | null {\n if (cited.size > 0) {\n if (!cited.has(chunkId)) return null\n return chunkId === active ? 'strong' : 'light'\n }\n return chunkId === active ? 'light' : null\n}\n\n/** A drawable box: four finite fractions with area. */\nfunction asBox(bbox: readonly number[] | undefined): PageBox | null {\n if (!bbox || bbox.length !== 4 || !bbox.every(Number.isFinite)) return null\n const [x0, y0, x1, y1] = bbox\n if (x1 <= x0 || y1 <= y0) return null\n return [x0, y0, x1, y1]\n}\n\n/**\n * The page's whole area: what the parser gives a chunk on a page where it recognized no block to\n * place it by. It says \"this page\", and a rectangle over the whole page would say nothing more.\n */\nfunction isWholePage([x0, y0, x1, y1]: PageBox): boolean {\n return x0 <= 0 && y0 <= 0 && x1 >= 1 && y1 >= 1\n}\n\n/** The lit passages' boxes, by page number. Passages without a usable box are left out. */\nexport function passageBoxesByPage(\n pages: readonly ProcessedPage[],\n state: PassageHighlightState\n): Map<number, PdfPassageBox[]> {\n const byPage = new Map<number, PdfPassageBox[]>()\n if (state.cited.size === 0 && !state.active) return byPage\n for (const page of pages) {\n if (page.pageNumber === null) continue\n for (const chunk of page.chunks) {\n const chunkId = chunk.chunkExtId\n if (!chunkId) continue\n const highlight = passageHighlight(chunkId, state)\n const box = highlight && asBox(chunk.pageBbox)\n if (!highlight || !box || isWholePage(box)) continue\n const boxes = byPage.get(page.pageNumber) ?? []\n boxes.push({ chunkId, box, highlight })\n byPage.set(page.pageNumber, boxes)\n }\n }\n return byPage\n}\n"],
|
|
5
|
+
"mappings": ";AA4BO,SAAS,iBACd,SACA,EAAE,OAAO,OAAO,GACS;AACzB,MAAI,MAAM,OAAO,GAAG;AAClB,QAAI,CAAC,MAAM,IAAI,OAAO,EAAG,QAAO;AAChC,WAAO,YAAY,SAAS,WAAW;AAAA,EACzC;AACA,SAAO,YAAY,SAAS,UAAU;AACxC;AAGA,SAAS,MAAM,MAAqD;AAClE,MAAI,CAAC,QAAQ,KAAK,WAAW,KAAK,CAAC,KAAK,MAAM,OAAO,QAAQ,EAAG,QAAO;AACvE,QAAM,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI;AACzB,MAAI,MAAM,MAAM,MAAM,GAAI,QAAO;AACjC,SAAO,CAAC,IAAI,IAAI,IAAI,EAAE;AACxB;AAMA,SAAS,YAAY,CAAC,IAAI,IAAI,IAAI,EAAE,GAAqB;AACvD,SAAO,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;AAChD;AAGO,SAAS,mBACd,OACA,OAC8B;AAC9B,QAAM,SAAS,oBAAI,IAA6B;AAChD,MAAI,MAAM,MAAM,SAAS,KAAK,CAAC,MAAM,OAAQ,QAAO;AACpD,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,KAAM;AAC9B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,UAAU,MAAM;AACtB,UAAI,CAAC,QAAS;AACd,YAAM,YAAY,iBAAiB,SAAS,KAAK;AACjD,YAAM,MAAM,aAAa,MAAM,MAAM,QAAQ;AAC7C,UAAI,CAAC,aAAa,CAAC,OAAO,YAAY,GAAG,EAAG;AAC5C,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,KAAK,CAAC;AAC9C,YAAM,KAAK,EAAE,SAAS,KAAK,UAAU,CAAC;AACtC,aAAO,IAAI,KAAK,YAAY,KAAK;AAAA,IACnC;AAAA,EACF;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The passages a citation lights, drawn over the PDF page by page: a fact's cited passages (its
|
|
3
|
+
* Citation popover is open) and the passage a citation opened the document at, as the parsed view
|
|
4
|
+
* lights them. Nothing is fetched until one is lit; the parsed chunks are the parsed view's own
|
|
5
|
+
* query, so opening that tab afterwards costs nothing more.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
/** A PDF viewer's page overlay for the document being viewed: `(page) => highlights | null`. */
|
|
9
|
+
export declare function usePdfPassageHighlights(documentId: string | undefined): (pageNumber: number) => ReactNode;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
4
|
+
import { useArbiSessionState, useParsedDocument } from "@arbidocs/react";
|
|
5
|
+
import { useProcessedChunks } from "@arbidocs/react/viewers";
|
|
6
|
+
import { useViewerPassageCitation } from "../support.js";
|
|
7
|
+
import { PdfPassageHighlights } from "./PdfPassageHighlights.js";
|
|
8
|
+
import { passageBoxesByPage } from "./passageHighlights.js";
|
|
9
|
+
const NONE = [];
|
|
10
|
+
const NO_FOOTNOTES = {};
|
|
11
|
+
function usePdfPassageHighlights(documentId) {
|
|
12
|
+
const citedIds = useViewerPassageCitation()?.highlighted ?? NONE;
|
|
13
|
+
const cited = useMemo(() => new Set(citedIds), [citedIds]);
|
|
14
|
+
const active = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
|
|
15
|
+
const { data: parsed } = useParsedDocument(documentId, "final", {
|
|
16
|
+
enabled: cited.size > 0 || !!active
|
|
17
|
+
});
|
|
18
|
+
const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES);
|
|
19
|
+
const boxesByPage = useMemo(
|
|
20
|
+
() => passageBoxesByPage(processedChunks, { cited, active }),
|
|
21
|
+
[processedChunks, cited, active]
|
|
22
|
+
);
|
|
23
|
+
const centredFor = useRef(null);
|
|
24
|
+
const activeKey = active ? `${documentId}:${active}` : null;
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!activeKey) centredFor.current = null;
|
|
27
|
+
}, [activeKey]);
|
|
28
|
+
const centre = useCallback(
|
|
29
|
+
(element) => {
|
|
30
|
+
if (!activeKey || centredFor.current === activeKey) return;
|
|
31
|
+
centredFor.current = activeKey;
|
|
32
|
+
element.scrollIntoView?.({ block: "center", behavior: "smooth" });
|
|
33
|
+
},
|
|
34
|
+
[activeKey]
|
|
35
|
+
);
|
|
36
|
+
return useCallback(
|
|
37
|
+
(pageNumber) => {
|
|
38
|
+
const boxes = boxesByPage.get(pageNumber);
|
|
39
|
+
return boxes ? /* @__PURE__ */ jsx(PdfPassageHighlights, { boxes, activeId: active, onActiveDrawn: centre }) : null;
|
|
40
|
+
},
|
|
41
|
+
[boxesByPage, active, centre]
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
usePdfPassageHighlights
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=usePdfPassageHighlights.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/connection/viewer/pdf/usePdfPassageHighlights.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The passages a citation lights, drawn over the PDF page by page: a fact's cited passages (its\n * Citation popover is open) and the passage a citation opened the document at, as the parsed view\n * lights them. Nothing is fetched until one is lit; the parsed chunks are the parsed view's own\n * query, so opening that tab afterwards costs nothing more.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react'\nimport { useArbiSessionState, useParsedDocument } from '@arbidocs/react'\nimport { useProcessedChunks } from '@arbidocs/react/viewers'\nimport { useViewerPassageCitation } from '../support'\nimport { PdfPassageHighlights } from './PdfPassageHighlights'\nimport { passageBoxesByPage } from './passageHighlights'\n\nconst NONE: readonly string[] = []\nconst NO_FOOTNOTES: Record<string, string> = {}\n\n/** A PDF viewer's page overlay for the document being viewed: `(page) => highlights | null`. */\nexport function usePdfPassageHighlights(\n documentId: string | undefined\n): (pageNumber: number) => ReactNode {\n const citedIds = useViewerPassageCitation()?.highlighted ?? NONE\n const cited = useMemo(() => new Set(citedIds), [citedIds])\n const active = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null)\n\n const { data: parsed } = useParsedDocument(documentId, 'final', {\n enabled: cited.size > 0 || !!active,\n })\n const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES)\n const boxesByPage = useMemo(\n () => passageBoxesByPage(processedChunks, { cited, active }),\n [processedChunks, cited, active]\n )\n\n // The passage being read is brought into view once, when its page first draws it: the viewer\n // opens the page, this centres the passage on it, and scrolling away is then left alone.\n const centredFor = useRef<string | null>(null)\n const activeKey = active ? `${documentId}:${active}` : null\n useEffect(() => {\n if (!activeKey) centredFor.current = null\n }, [activeKey])\n const centre = useCallback(\n (element: HTMLElement) => {\n if (!activeKey || centredFor.current === activeKey) return\n centredFor.current = activeKey\n element.scrollIntoView?.({ block: 'center', behavior: 'smooth' })\n },\n [activeKey]\n )\n\n return useCallback(\n (pageNumber: number) => {\n const boxes = boxesByPage.get(pageNumber)\n return boxes ? (\n <PdfPassageHighlights boxes={boxes} activeId={active} onActiveDrawn={centre} />\n ) : null\n },\n [boxesByPage, active, centre]\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAsDQ;AA/CR,SAAS,aAAa,WAAW,SAAS,cAA8B;AACxE,SAAS,qBAAqB,yBAAyB;AACvD,SAAS,0BAA0B;AACnC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AAEnC,MAAM,OAA0B,CAAC;AACjC,MAAM,eAAuC,CAAC;AAGvC,SAAS,wBACd,YACmC;AACnC,QAAM,WAAW,yBAAyB,GAAG,eAAe;AAC5D,QAAM,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,GAAG,CAAC,QAAQ,CAAC;AACzD,QAAM,SAAS,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,aAAa,IAAI;AAE9E,QAAM,EAAE,MAAM,OAAO,IAAI,kBAAkB,YAAY,SAAS;AAAA,IAC9D,SAAS,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,EAC/B,CAAC;AACD,QAAM,EAAE,gBAAgB,IAAI,mBAAmB,QAAQ,QAAQ,YAAY;AAC3E,QAAM,cAAc;AAAA,IAClB,MAAM,mBAAmB,iBAAiB,EAAE,OAAO,OAAO,CAAC;AAAA,IAC3D,CAAC,iBAAiB,OAAO,MAAM;AAAA,EACjC;AAIA,QAAM,aAAa,OAAsB,IAAI;AAC7C,QAAM,YAAY,SAAS,GAAG,UAAU,IAAI,MAAM,KAAK;AACvD,YAAU,MAAM;AACd,QAAI,CAAC,UAAW,YAAW,UAAU;AAAA,EACvC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,SAAS;AAAA,IACb,CAAC,YAAyB;AACxB,UAAI,CAAC,aAAa,WAAW,YAAY,UAAW;AACpD,iBAAW,UAAU;AACrB,cAAQ,iBAAiB,EAAE,OAAO,UAAU,UAAU,SAAS,CAAC;AAAA,IAClE;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,CAAC,eAAuB;AACtB,YAAM,QAAQ,YAAY,IAAI,UAAU;AACxC,aAAO,QACL,oBAAC,wBAAqB,OAAc,UAAU,QAAQ,eAAe,QAAQ,IAC3E;AAAA,IACN;AAAA,IACA,CAAC,aAAa,QAAQ,MAAM;AAAA,EAC9B;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ArbiSessionStore } from '@arbidocs/react';
|
|
2
|
+
type Session = Pick<ArbiSessionStore, 'setViewingDocument' | 'setDocumentViewer' | 'openPanel'>;
|
|
3
|
+
/**
|
|
4
|
+
* Open a document in a window of its own, to be shared in a call (Share screen/tab): the viewer's
|
|
5
|
+
* clean view, only its pages (a presentation's are its slides). Call it from a click: the browser
|
|
6
|
+
* opens a window only for one.
|
|
7
|
+
*/
|
|
8
|
+
export declare function openDocumentToShare(session: Session, doc: {
|
|
9
|
+
id: string;
|
|
10
|
+
}): void;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DOCUMENT_VIEWER_PANEL } from "@arbidocs/react";
|
|
3
|
+
function openDocumentToShare(session, doc) {
|
|
4
|
+
session.setViewingDocument({ id: doc.id, page: null });
|
|
5
|
+
session.setDocumentViewer({ presenting: true, tab: "pdf" });
|
|
6
|
+
session.openPanel(DOCUMENT_VIEWER_PANEL, "popout");
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
openDocumentToShare
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=shareDocument.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/viewer/shareDocument.ts"],
|
|
4
|
+
"sourcesContent": ["import { DOCUMENT_VIEWER_PANEL, type ArbiSessionStore } from '@arbidocs/react'\n\ntype Session = Pick<ArbiSessionStore, 'setViewingDocument' | 'setDocumentViewer' | 'openPanel'>\n\n/**\n * Open a document in a window of its own, to be shared in a call (Share screen/tab): the viewer's\n * clean view, only its pages (a presentation's are its slides). Call it from a click: the browser\n * opens a window only for one.\n */\nexport function openDocumentToShare(session: Session, doc: { id: string }): void {\n session.setViewingDocument({ id: doc.id, page: null })\n session.setDocumentViewer({ presenting: true, tab: 'pdf' })\n session.openPanel(DOCUMENT_VIEWER_PANEL, 'popout')\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,6BAAoD;AAStD,SAAS,oBAAoB,SAAkB,KAA2B;AAC/E,UAAQ,mBAAmB,EAAE,IAAI,IAAI,IAAI,MAAM,KAAK,CAAC;AACrD,UAAQ,kBAAkB,EAAE,YAAY,MAAM,KAAK,MAAM,CAAC;AAC1D,UAAQ,UAAU,uBAAuB,QAAQ;AACnD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/viewer/slidesTabChunk.ts"],
|
|
4
|
+
"sourcesContent": ["import { lazy } from 'react'\n\n/** A presentation's slides tab: its own chunk, loaded when a presentation shows. */\nexport const SlidesTab = lazy(() =>\n import('../presentation/ConnectedSlidesTab').then((m) => ({ default: m.ConnectedSlidesTab }))\n)\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,YAAY;AAGd,MAAM,YAAY;AAAA,EAAK,MAC5B,OAAO,oCAAoC,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE;AAC9F;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|