@arbidocs/blocks 0.5.120 → 0.5.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ClippingMediaViewer-IEIBT74X.cjs +156 -0
- package/dist/ClippingMediaViewer-IEIBT74X.cjs.map +1 -0
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs +79 -0
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs.map +1 -0
- package/dist/{ConnectedCallDock-WER7R222.cjs → ConnectedCallDock-XJOYVVAH.cjs} +9 -7
- package/dist/ConnectedCallDock-XJOYVVAH.cjs.map +1 -0
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs → ConnectedCallRoom-CUDYAPQK.cjs} +9 -7
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs.map → ConnectedCallRoom-CUDYAPQK.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs → ConnectedNativeDocxComparison-QKHCYD6W.cjs} +7 -7
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs.map → ConnectedNativeDocxComparison-QKHCYD6W.cjs.map} +1 -1
- package/dist/ConnectedPresentation-AU25OW25.cjs +321 -0
- package/dist/ConnectedPresentation-AU25OW25.cjs.map +1 -0
- package/dist/ConnectedSlidesTab-I75LKKN7.cjs +236 -0
- package/dist/ConnectedSlidesTab-I75LKKN7.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs → ConnectedStreamedWordArtifact-AG62232A.cjs} +7 -7
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs.map → ConnectedStreamedWordArtifact-AG62232A.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-BPIAJJED.cjs → DocumentReviewCard-M53XFLI2.cjs} +15 -14
- package/dist/DocumentReviewCard-M53XFLI2.cjs.map +1 -0
- package/dist/{FilesViewerDialog-67WK3TZC.cjs → FilesViewerDialog-4352KIOG.cjs} +30 -22
- package/dist/FilesViewerDialog-4352KIOG.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-3XYAV4BV.cjs} +9 -8
- package/dist/WorkspaceTableView-3XYAV4BV.cjs.map +1 -0
- package/dist/agents/index.cjs +186 -186
- package/dist/{ai-IM4A23YT.cjs → ai-IEIR7SC2.cjs} +17 -15
- package/dist/ai-IEIR7SC2.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 +2 -2
- package/dist/chat/index.cjs +8 -7
- package/dist/{chunk-557MJ4IH.cjs → chunk-2F57IO7S.cjs} +9 -146
- package/dist/chunk-2F57IO7S.cjs.map +1 -0
- package/dist/chunk-2RLA6QO2.cjs +174 -0
- package/dist/chunk-2RLA6QO2.cjs.map +1 -0
- package/dist/chunk-4TTX6ZNS.cjs +1374 -0
- package/dist/chunk-4TTX6ZNS.cjs.map +1 -0
- package/dist/chunk-5GCCUXMT.cjs +63 -0
- package/dist/chunk-5GCCUXMT.cjs.map +1 -0
- package/dist/{chunk-BUVIBHFU.cjs → chunk-5QERK4PK.cjs} +38 -38
- package/dist/chunk-5QERK4PK.cjs.map +1 -0
- package/dist/chunk-6OK7ESTL.cjs +134 -0
- package/dist/chunk-6OK7ESTL.cjs.map +1 -0
- package/dist/{chunk-ECLUFKYR.cjs → chunk-7557LDAN.cjs} +4 -4
- package/dist/{chunk-ECLUFKYR.cjs.map → chunk-7557LDAN.cjs.map} +1 -1
- package/dist/{chunk-KTQOGT2L.cjs → chunk-7L4X6QN2.cjs} +7 -7
- package/dist/{chunk-KTQOGT2L.cjs.map → chunk-7L4X6QN2.cjs.map} +1 -1
- package/dist/{chunk-BP3IJ34D.cjs → chunk-7NLO7ASW.cjs} +4 -4
- package/dist/{chunk-BP3IJ34D.cjs.map → chunk-7NLO7ASW.cjs.map} +1 -1
- package/dist/{chunk-3GWWOYGS.cjs → chunk-7PN3YENO.cjs} +4 -4
- package/dist/{chunk-3GWWOYGS.cjs.map → chunk-7PN3YENO.cjs.map} +1 -1
- package/dist/{chunk-DFBDQKGE.cjs → chunk-ADDQKZ5I.cjs} +4 -4
- package/dist/{chunk-DFBDQKGE.cjs.map → chunk-ADDQKZ5I.cjs.map} +1 -1
- package/dist/chunk-AFQTQC7A.cjs +35 -0
- package/dist/chunk-AFQTQC7A.cjs.map +1 -0
- package/dist/{chunk-NLSWDP42.cjs → chunk-ALK3PUUB.cjs} +21 -11
- package/dist/chunk-ALK3PUUB.cjs.map +1 -0
- package/dist/{chunk-775S43W7.cjs → chunk-CQQQIZU4.cjs} +8 -8
- package/dist/{chunk-775S43W7.cjs.map → chunk-CQQQIZU4.cjs.map} +1 -1
- package/dist/{chunk-TDO5UWXF.cjs → chunk-E3L5DB5F.cjs} +5 -5
- package/dist/{chunk-TDO5UWXF.cjs.map → chunk-E3L5DB5F.cjs.map} +1 -1
- package/dist/chunk-GFUOCGY6.cjs +32 -0
- package/dist/chunk-GFUOCGY6.cjs.map +1 -0
- package/dist/chunk-HYUKPHCT.cjs +66 -0
- package/dist/chunk-HYUKPHCT.cjs.map +1 -0
- package/dist/{chunk-QQWHG3KF.cjs → chunk-JJZOL5MG.cjs} +4 -4
- package/dist/{chunk-QQWHG3KF.cjs.map → chunk-JJZOL5MG.cjs.map} +1 -1
- package/dist/chunk-K4763GD5.cjs +301 -0
- package/dist/chunk-K4763GD5.cjs.map +1 -0
- package/dist/{chunk-B3LZITVF.cjs → chunk-KA3F6TIH.cjs} +2 -442
- package/dist/chunk-KA3F6TIH.cjs.map +1 -0
- package/dist/{chunk-PGJYD67F.cjs → chunk-KNGZZC4O.cjs} +7 -6
- package/dist/chunk-KNGZZC4O.cjs.map +1 -0
- package/dist/{chunk-YYPZOEED.cjs → chunk-LHWOKOMP.cjs} +23 -2
- package/dist/chunk-LHWOKOMP.cjs.map +1 -0
- package/dist/{chunk-HA66DHW6.cjs → chunk-MLA2BJ2Y.cjs} +28 -28
- package/dist/chunk-MLA2BJ2Y.cjs.map +1 -0
- package/dist/{chunk-CPR6EHG7.cjs → chunk-NG2EE7HR.cjs} +134 -10
- package/dist/chunk-NG2EE7HR.cjs.map +1 -0
- package/dist/{chunk-CKCG4NDB.cjs → chunk-OHHKBURG.cjs} +29 -29
- package/dist/chunk-OHHKBURG.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-YYSBWMDJ.cjs → chunk-QG2U2JGX.cjs} +4 -4
- package/dist/{chunk-YYSBWMDJ.cjs.map → chunk-QG2U2JGX.cjs.map} +1 -1
- package/dist/{chunk-5IZFSAEZ.cjs → chunk-SDRYSLOX.cjs} +4 -4
- package/dist/{chunk-5IZFSAEZ.cjs.map → chunk-SDRYSLOX.cjs.map} +1 -1
- package/dist/{chunk-NJCK6V6U.cjs → chunk-T73BHNQX.cjs} +2 -58
- package/dist/chunk-T73BHNQX.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-6UTKM5AB.cjs → chunk-UFT22LAB.cjs} +75 -75
- package/dist/chunk-UFT22LAB.cjs.map +1 -0
- package/dist/chunk-USNTRL22.cjs +4790 -0
- package/dist/chunk-USNTRL22.cjs.map +1 -0
- package/dist/{chunk-X36UR4A7.cjs → chunk-UTJ223TI.cjs} +413 -90
- package/dist/chunk-UTJ223TI.cjs.map +1 -0
- package/dist/{chunk-VZCPMXWC.cjs → chunk-V6MW7B4B.cjs} +4 -4
- package/dist/{chunk-VZCPMXWC.cjs.map → chunk-V6MW7B4B.cjs.map} +1 -1
- package/dist/{chunk-T23UTIRI.cjs → chunk-VWBYE3XY.cjs} +5 -5
- package/dist/{chunk-T23UTIRI.cjs.map → chunk-VWBYE3XY.cjs.map} +1 -1
- package/dist/chunk-WFMWKPGY.cjs +102 -0
- package/dist/chunk-WFMWKPGY.cjs.map +1 -0
- package/dist/chunk-WOOOMTTA.cjs +19 -0
- package/dist/chunk-WOOOMTTA.cjs.map +1 -0
- package/dist/{chunk-W6INT5GS.cjs → chunk-WRLGLZIA.cjs} +8 -8
- package/dist/{chunk-W6INT5GS.cjs.map → chunk-WRLGLZIA.cjs.map} +1 -1
- 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-XF355M7O.cjs +154 -0
- package/dist/chunk-XF355M7O.cjs.map +1 -0
- package/dist/{chunk-Q6CLWOP2.cjs → chunk-XGM4VVNV.cjs} +34 -34
- package/dist/{chunk-Q6CLWOP2.cjs.map → chunk-XGM4VVNV.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-E7TE2WVT.cjs → chunk-ZVEW3JBT.cjs} +3 -3
- package/dist/{chunk-E7TE2WVT.cjs.map → chunk-ZVEW3JBT.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +70 -70
- 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 +10 -10
- package/dist/connect/index.cjs +1066 -1147
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +19 -12
- package/dist/connection/ai.d.ts +1 -1
- package/dist/connection/conversation/ConnectedMessage.js +1 -1
- package/dist/connection/conversation/ConnectedMessage.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/documentColumns.js +1 -1
- 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 +222 -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 +39 -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 +21 -0
- package/dist/connection/presentation/requests.js +27 -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/shell/ConnectedAppShell.js +5 -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 +28 -29
- 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 +41 -1
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/documentPlace.d.ts +5 -4
- package/dist/connection/viewer/documentPlace.js +2 -2
- package/dist/connection/viewer/documentPlace.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/PdfClipOutlines.d.ts +11 -0
- package/dist/connection/viewer/pdf/PdfClipOutlines.js +42 -0
- package/dist/connection/viewer/pdf/PdfClipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/clipOutlines.d.ts +17 -0
- package/dist/connection/viewer/pdf/clipOutlines.js +24 -0
- package/dist/connection/viewer/pdf/clipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/passageHighlights.d.ts +2 -0
- package/dist/connection/viewer/pdf/passageHighlights.js +12 -1
- package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
- package/dist/connection/viewer/pdf/usePdfClipOutlines.d.ts +7 -0
- package/dist/connection/viewer/pdf/usePdfClipOutlines.js +36 -0
- package/dist/connection/viewer/pdf/usePdfClipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +11 -2
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
- 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/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 +17 -15
- package/dist/files/GridViewImpl.js +1 -1
- package/dist/files/GridViewImpl.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 +224 -224
- package/dist/files/navigator/DocumentSearchList.js +1 -1
- package/dist/files/navigator/DocumentSearchList.js.map +2 -2
- package/dist/index.cjs +359 -356
- 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/PresentControls.d.ts +11 -0
- package/dist/presentation/PresentControls.js +117 -0
- package/dist/presentation/PresentControls.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 +100 -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 +375 -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 +44 -0
- package/dist/presentation/panel-id.js +29 -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 +58 -0
- package/dist/presentation/slide-layout.js +133 -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 +149 -148
- package/dist/shell/PanelPortal.js +13 -3
- package/dist/shell/PanelPortal.js.map +2 -2
- package/dist/shell/index.cjs +49 -46
- package/dist/shell/panel-windows.d.ts +2 -0
- package/dist/shell/panel-windows.js +8 -2
- package/dist/shell/panel-windows.js.map +2 -2
- package/dist/studio/index.cjs +8 -6
- package/dist/studio/index.cjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +26 -25
- 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-BPIAJJED.cjs.map +0 -1
- package/dist/FilesViewerDialog-67WK3TZC.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-BUVIBHFU.cjs.map +0 -1
- package/dist/chunk-CKCG4NDB.cjs.map +0 -1
- package/dist/chunk-CPR6EHG7.cjs.map +0 -1
- package/dist/chunk-HA66DHW6.cjs.map +0 -1
- package/dist/chunk-NJCK6V6U.cjs.map +0 -1
- package/dist/chunk-NLSWDP42.cjs.map +0 -1
- package/dist/chunk-PGJYD67F.cjs.map +0 -1
- package/dist/chunk-X36UR4A7.cjs.map +0 -1
- package/dist/chunk-YYPZOEED.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/connection/files/explorer/ConnectedFilesExplorer.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The workspace's files as a file explorer (OneDrive / Drive style), bound to the session: folders\n * come from each document's `folder` path; renames, moves and deletes are written through\n * `@arbidocs/react`.\n *\n * - Breadcrumb navigation is the host's (`folderPath` / `onFolderPathChange`): it may keep the\n * folder in a filter, the URL or state.\n * - A virtualised tile grid that scales to thousands of documents, sized by `tileSize`.\n * - OS-style selection: click, \u2318/Ctrl-click, shift-range, the hover checkbox and a marquee.\n * - Drag files onto a folder tile to move them; drop OS files on the view to upload.\n *\n * Selection is the host's (`selectedIds` / `onSelectionChange`), so its bulk actions act on it.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport {\n DndContext,\n DragOverlay,\n MouseSensor,\n TouchSensor,\n pointerWithin,\n rectIntersection,\n useSensor,\n useSensors,\n type CollisionDetection,\n type DragEndEvent,\n type DragStartEvent,\n} from '@dnd-kit/core'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport {\n useDeleteDocuments,\n useDocumentHostActions,\n useDocumentThumbnails,\n useDownloadDocuments,\n useRenameFolder,\n useTags,\n useUpdateDocuments,\n useWorkspaces,\n} from '@arbidocs/react'\nimport { getDocumentTitle, getFileTypeIcon } from '@arbidocs/react/ui'\nimport {\n ExplorerDragPreview,\n ExplorerDropOverlay,\n ExplorerEmpty,\n ExplorerFrame,\n ExplorerMarquee,\n ExplorerScroller,\n ExplorerStage,\n} from '../../../files/ExplorerSurface'\nimport { ExplorerLoadingTiles } from '../../../files/Explorer'\nimport {\n buildExplorerEntries,\n collectFolderDocs,\n getExplorerDisplayName,\n joinFolderPath,\n searchExplorerDocuments,\n type ExplorerEntry,\n type ExplorerFolder,\n type ExplorerSort,\n} from '../../../files/folders'\nimport { canDeleteDocument, type WorkspaceMemberRole } from '../../../files/permissions'\nimport {\n RECENTLY_DELETED_HINT,\n RECENTLY_DELETED_HINT_PLURAL,\n} from '../../../files/recently-deleted'\nimport { useBlocksEnvironment } from '../../../provider/environment'\nimport { useConnectedWorkspace } from '../../ConnectionProvider'\nimport { useConnectedWorkspaceRole } from '../../ConnectedWorkflowsTable'\nimport { useFilesStore, usePendingFolders } from '../store'\nimport {\n FileTile,\n FolderTile,\n type ExplorerDensity,\n type FileTileDocument,\n type FileTileUser,\n} from './FileTiles'\n\n// Both densities are thumbnail grids, differing only in tile size. Row heights include the gap so\n// the virtualiser's estimate matches the rendered slot exactly.\nconst GRID_GAP = 12\n// The scroller's horizontal padding (px-4 each side).\nconst SCROLL_PADDING_X = 32\n// A portrait page (height / width), so cover-page thumbnails read.\nconst PAGE_ASPECT = 1.3\n/** The zoom slider's bounds: the target tile width in px (smaller: more tiles per row). */\nexport const TILE_MIN = 88\nexport const TILE_MAX = 232\nexport const TILE_DEFAULT = 200\n// Narrower tiles use the compact styling.\nconst COMPACT_BELOW = 132\nconst NO_DOCUMENTS: FileTileDocument[] = []\n\nexport interface ConnectedFilesExplorerHandle {\n /** Add a placeholder folder here and start naming it. */\n triggerNewFolder: () => void\n /** Scroll the tile of `docId` into view, when it is displayed. */\n scrollToDocument: (docId: string) => void\n}\n\nexport interface ConnectedFilesExplorerProps {\n documents: FileTileDocument[]\n isLoading: boolean\n /** The viewer may add, rename and move files here. */\n canUpload: boolean\n selectedIds: string[]\n onSelectionChange: (ids: string[]) => void\n onOpenDocument: (docId: string) => void\n onUploadFiles: (files: File[], folder?: string | null) => void\n /** The open folder (empty: the workspace root). */\n folderPath: readonly string[]\n onFolderPathChange: (path: string[]) => void\n /** A search across every folder (absent or empty: the open folder is listed). */\n search?: string\n sort: ExplorerSort\n sortReversed: boolean\n /** The target tile width in px (`TILE_MIN`..`TILE_MAX`). */\n tileSize: number\n /** The ids of the files displayed, in display order (a navigator steps the same list). */\n onOrderedFilesChange?: (docIds: string[]) => void\n /** Move the selected files: the host opens its folder picker. Absent: not offered. */\n onMoveSelected?: () => void\n /** Move a folder with its structure: the host opens its folder picker. */\n onFolderMove?: (folder: ExplorerFolder) => void\n /** Open a document in the host's review view. Absent: not offered. */\n onOpenInReview?: (docId: string) => void\n /** Shown instead of the explorer while the workspace has no documents and the viewer may add. */\n emptyWorkspace?: ReactNode\n}\n\n/** The workspace's name (the download archive is named after it), members and the viewer's role. */\nfunction useFilesWorkspace() {\n const { workspaceId, userId, live } = useConnectedWorkspace()\n const { members, role } = useConnectedWorkspaceRole()\n const { data: workspaces } = useWorkspaces({ enabled: live })\n const workspaceName = workspaces?.find((w) => w.external_id === workspaceId)?.name\n return {\n workspaceId: workspaceId ?? '',\n workspaceName,\n userId,\n role: (role ?? null) as WorkspaceMemberRole | null,\n members,\n }\n}\n\nexport const ConnectedFilesExplorer = forwardRef<\n ConnectedFilesExplorerHandle,\n ConnectedFilesExplorerProps\n>(function ConnectedFilesExplorer(\n {\n documents,\n isLoading,\n canUpload,\n selectedIds,\n onSelectionChange,\n onOrderedFilesChange,\n onOpenDocument,\n onUploadFiles,\n folderPath,\n onFolderPathChange,\n search = '',\n sort,\n sortReversed,\n tileSize,\n onMoveSelected,\n onFolderMove,\n onOpenInReview,\n emptyWorkspace,\n },\n ref\n) {\n const { confirm, notify } = useBlocksEnvironment()\n const currentPath = folderPath as string[]\n const density: ExplorerDensity = tileSize < COMPACT_BELOW ? 'list' : 'grid'\n const [containerWidth, setContainerWidth] = useState(0)\n const [activeDragId, setActiveDragId] = useState<string | null>(null)\n const [isFileDragOver, setIsFileDragOver] = useState(false)\n const [renamingId, setRenamingId] = useState<string | null>(null)\n\n const scrollRef = useRef<HTMLDivElement | null>(null)\n const anchorRef = useRef<string | null>(null)\n const dragIdsRef = useRef<string[]>([])\n const fileDragDepth = useRef(0)\n // The marquee is drawn by mutating this overlay's style (one paint per frame), so dragging the\n // lasso never re-renders the grid; the selection is computed once, on release.\n const marqueeOverlayRef = useRef<HTMLDivElement | null>(null)\n // The marquee gesture: its origin, whether it adds to the selection, and that selection.\n const marqueeRef = useRef<{ x: number; y: number; additive: boolean; base: string[] } | null>(\n null\n )\n // A background drag crossed the start threshold: the click that follows must not clear.\n const didMarqueeRef = useRef(false)\n\n const updateDocument = useUpdateDocuments()\n const deleteDocuments = useDeleteDocuments()\n const renameFolder = useRenameFolder()\n const { workspaceId: wsId, workspaceName, userId, role, members } = useFilesWorkspace()\n const { downloadDocuments, downloadDocument } = useDownloadDocuments({ workspaceName })\n const { data: workspaceTags } = useTags()\n const hostActions = useDocumentHostActions()\n\n // Member and label lookups for the hover card, memoised so they keep the tiles memoised.\n const userById = useMemo(() => {\n const map = new Map<string, FileTileUser>()\n for (const member of members) map.set(member.user.external_id, member.user)\n return map\n }, [members])\n const tagNameById = useMemo(() => {\n const map = new Map<string, string>()\n for (const tag of workspaceTags ?? []) map.set(tag.external_id, tag.name)\n return map\n }, [workspaceTags])\n\n // Placeholder (empty) folders of this workspace.\n const pendingFolders = usePendingFolders(wsId)\n const addPendingFolder = useFilesStore((state) => state.addPendingFolder)\n const removePendingFolder = useFilesStore((state) => state.removePendingFolder)\n // The placeholder folder being named inline (its full path).\n const [editingFolderPath, setEditingFolderPath] = useState<string | null>(null)\n\n const isSearching = search.trim().length > 0\n\n // The selection for handlers that run outside the render that produced it (drag, keys).\n const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds])\n const selectedIdsRef = useRef(selectedIds)\n selectedIdsRef.current = selectedIds\n\n // The open folder's entries, or a flat search result.\n const { folders, files } = useMemo(() => {\n const result = isSearching\n ? {\n folders: [] as ExplorerFolder[],\n files: searchExplorerDocuments(documents, search, sort),\n }\n : buildExplorerEntries(documents, currentPath, sort, [...pendingFolders])\n if (sortReversed) result.files = [...result.files].reverse()\n return result\n }, [documents, currentPath, sort, isSearching, search, sortReversed, pendingFolders])\n\n const entries: ExplorerEntry<FileTileDocument>[] = useMemo(\n () => [...folders, ...files.map((doc) => ({ kind: 'file' as const, doc }))],\n [folders, files]\n )\n const orderedFileIds = useMemo(() => files.map((d) => d.external_id), [files])\n // Each folder's documents (everything beneath it), and whether the selection holds all or some of\n // them: its checkbox and selected styling. Keyed by the joined path.\n const folderDocs = useMemo(() => {\n const map = new Map<string, FileTileDocument[]>()\n for (const f of folders) map.set(f.path.join('/'), collectFolderDocs(documents, f.path))\n return map\n }, [folders, documents])\n const folderSelection = useMemo(() => {\n const map = new Map<string, { all: boolean; some: boolean }>()\n for (const [key, docs] of folderDocs) {\n const sel = docs.reduce((n, d) => (selectedSet.has(d.external_id) ? n + 1 : n), 0)\n map.set(key, { all: docs.length > 0 && sel === docs.length, some: sel > 0 })\n }\n return map\n }, [folderDocs, selectedSet])\n\n // Columns from the measured width, each tile a portrait page so the thumbnail is legible.\n const contentWidth = Math.max(0, containerWidth - SCROLL_PADDING_X)\n const columnCount = Math.max(\n 1,\n Math.floor((contentWidth + GRID_GAP) / (tileSize + GRID_GAP)) || 1\n )\n const colWidth =\n contentWidth > 0 ? (contentWidth - (columnCount - 1) * GRID_GAP) / columnCount : tileSize\n const tileHeight = Math.max(120, Math.round(colWidth * PAGE_ASPECT))\n const rowHeight = tileHeight + GRID_GAP\n const rowCount = Math.ceil(entries.length / columnCount)\n\n const rowVirtualizer = useVirtualizer({\n count: rowCount,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => rowHeight,\n overscan: 3,\n })\n\n // The displayed files (on-screen rows plus overscan): the thumbnail loader fetches only these.\n const virtualRows = rowVirtualizer.getVirtualItems()\n const firstRow = virtualRows.length > 0 ? virtualRows[0].index : 0\n const lastRow = virtualRows.length > 0 ? virtualRows[virtualRows.length - 1].index : -1\n const visibleFileIds = useMemo(() => {\n const ids: string[] = []\n for (let r = firstRow; r <= lastRow; r++) {\n const start = r * columnCount\n for (let c = 0; c < columnCount; c++) {\n const entry = entries[start + c]\n if (entry?.kind === 'file') ids.push(entry.doc.external_id)\n }\n }\n return ids\n }, [firstRow, lastRow, columnCount, entries])\n const thumbnailsById = useDocumentThumbnails(visibleFileIds)\n\n useEffect(() => {\n rowVirtualizer.measure()\n }, [rowVirtualizer, columnCount, rowHeight, entries.length])\n\n // The empty workspace shows the host's dropzone instead of the scroller, so the first upload\n // mounts the scroller fresh: the width measurement re-runs on this flag (else the grid stays on\n // the loading tiles until a reload).\n const isWholeWorkspaceEmpty =\n !isLoading && documents.length === 0 && canUpload && emptyWorkspace !== undefined\n\n // The width is measured before paint (a first frame at width 0 would flash one stretched column)\n // and rounded and deduplicated, so sub-pixel resize noise does not re-run the tile maths.\n useLayoutEffect(() => {\n const el = scrollRef.current\n if (!el) return\n const apply = () => {\n const next = Math.round(el.clientWidth)\n setContainerWidth((prev) => (prev === next ? prev : next))\n }\n apply()\n const ro = new ResizeObserver(apply)\n ro.observe(el)\n return () => ro.disconnect()\n }, [isWholeWorkspaceEmpty])\n\n // A new listing scrolls to the top and drops the range anchor.\n useEffect(() => {\n anchorRef.current = null\n if (scrollRef.current) scrollRef.current.scrollTop = 0\n }, [currentPath, search])\n\n // ---- Marquee selection: a drag from empty space selects, on release, every tile it touches;\n // \u2318/Ctrl/Shift at the start adds to the selection. Clamped to the scroller.\n useEffect(() => {\n const MARQUEE_THRESHOLD = 5\n let rafId = 0\n let cur: { left: number; top: number; right: number; bottom: number } | null = null\n\n const paint = () => {\n rafId = 0\n const el = marqueeOverlayRef.current\n if (!el || !cur) return\n el.style.display = 'block'\n el.style.left = `${cur.left}px`\n el.style.top = `${cur.top}px`\n el.style.width = `${cur.right - cur.left}px`\n el.style.height = `${cur.bottom - cur.top}px`\n }\n\n const onMove = (e: PointerEvent) => {\n const m = marqueeRef.current\n if (!m) return\n if (\n !didMarqueeRef.current &&\n Math.hypot(e.clientX - m.x, e.clientY - m.y) < MARQUEE_THRESHOLD\n )\n return\n didMarqueeRef.current = true\n const b = scrollRef.current?.getBoundingClientRect()\n const px = b ? Math.max(b.left, Math.min(e.clientX, b.right)) : e.clientX\n const py = b ? Math.max(b.top, Math.min(e.clientY, b.bottom)) : e.clientY\n cur = {\n left: Math.min(m.x, px),\n top: Math.min(m.y, py),\n right: Math.max(m.x, px),\n bottom: Math.max(m.y, py),\n }\n if (!rafId) rafId = requestAnimationFrame(paint)\n }\n\n const onUp = () => {\n const m = marqueeRef.current\n if (!m) return\n marqueeRef.current = null\n if (rafId) cancelAnimationFrame(rafId)\n rafId = 0\n const el = marqueeOverlayRef.current\n if (el) el.style.display = 'none'\n if (!didMarqueeRef.current || !cur) return\n const box = cur\n const hit: string[] = []\n scrollRef.current?.querySelectorAll('[data-doc-id]').forEach((node) => {\n const r = node.getBoundingClientRect()\n if (r.left < box.right && r.right > box.left && r.top < box.bottom && r.bottom > box.top) {\n const id = node.getAttribute('data-doc-id')\n if (id) hit.push(id)\n }\n })\n onSelectionChange(m.additive ? Array.from(new Set([...m.base, ...hit])) : hit)\n }\n\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n return () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n if (rafId) cancelAnimationFrame(rafId)\n }\n }, [onSelectionChange])\n\n const handleScrollPointerDown = useCallback((e: React.PointerEvent) => {\n if (e.button !== 0) return\n const el = e.target as HTMLElement\n if (\n el.closest(\n '[data-testid=\"explorer-file\"],[data-testid=\"explorer-folder\"],button,input,select,a,[role=\"button\"]'\n )\n ) {\n return\n }\n const additive = e.shiftKey || e.metaKey || e.ctrlKey\n marqueeRef.current = {\n x: e.clientX,\n y: e.clientY,\n additive,\n base: additive ? selectedIdsRef.current : [],\n }\n didMarqueeRef.current = false\n }, [])\n\n // ---- Navigation\n\n const openFolder = useCallback(\n (folder: ExplorerFolder) => onFolderPathChange(folder.path),\n [onFolderPathChange]\n )\n\n // ---- Placeholder (empty) folders\n\n const handleNewFolder = useCallback(() => {\n if (!wsId) return\n const siblings = new Set(folders.map((f) => f.name.toLowerCase()))\n const base = 'New folder'\n let name = base\n let i = 2\n while (siblings.has(name.toLowerCase())) name = `${base} ${i++}`\n const path = joinFolderPath([...currentPath, name])\n if (!path) return\n addPendingFolder(wsId, path)\n setEditingFolderPath(path)\n }, [wsId, folders, currentPath, addPendingFolder])\n\n // Publish the displayed order only when the ids differ: `documents` is a new array on most\n // renders, and handing each new identity to the host's state would loop.\n const lastOrderedRef = useRef<string[]>([])\n useEffect(() => {\n const prev = lastOrderedRef.current\n if (prev.length === orderedFileIds.length && prev.every((id, i) => id === orderedFileIds[i])) {\n return\n }\n lastOrderedRef.current = orderedFileIds\n onOrderedFilesChange?.(orderedFileIds)\n }, [onOrderedFilesChange, orderedFileIds])\n\n const scrollToDocument = useCallback(\n (docId: string) => {\n const index = entries.findIndex((e) => e.kind === 'file' && e.doc.external_id === docId)\n if (index < 0) return\n rowVirtualizer.scrollToIndex(Math.floor(index / columnCount), { align: 'center' })\n },\n [entries, columnCount, rowVirtualizer]\n )\n\n useImperativeHandle(ref, () => ({ triggerNewFolder: handleNewFolder, scrollToDocument }), [\n handleNewFolder,\n scrollToDocument,\n ])\n\n const commitFolderName = useCallback(\n async (folder: ExplorerFolder, rawName: string) => {\n setEditingFolderPath(null)\n const name = rawName.trim()\n if (!wsId || !name || name === folder.name) return\n const siblings = new Set(folders.filter((f) => f !== folder).map((f) => f.name.toLowerCase()))\n if (siblings.has(name.toLowerCase())) {\n notify(`A folder named \"${name}\" already exists here.`, 'error')\n return\n }\n const oldPath = joinFolderPath(folder.path)\n const newPrefix = [...folder.path.slice(0, -1), name]\n const newPath = joinFolderPath(newPrefix)\n\n // Every document beneath the folder moves under the new name, the subtree with it.\n const docs = collectFolderDocs(documents, folder.path)\n try {\n if ((await renameFolder(docs, folder.path, newPrefix)) > 0) {\n notify(`Renamed folder to \"${name}\"`, 'success')\n }\n } catch {\n notify('Failed to rename folder. Please try again.', 'error')\n return\n }\n if (oldPath) removePendingFolder(wsId, oldPath)\n if (docs.length === 0 && newPath) addPendingFolder(wsId, newPath)\n },\n [wsId, folders, documents, renameFolder, notify, addPendingFolder, removePendingFolder]\n )\n\n const cancelFolderName = useCallback(() => setEditingFolderPath(null), [])\n\n // ---- Selection\n\n const clearSelection = useCallback(() => {\n if (selectedIdsRef.current.length > 0) onSelectionChange([])\n anchorRef.current = null\n }, [onSelectionChange])\n\n const handleSelect = useCallback(\n (doc: FileTileDocument, e: React.MouseEvent) => {\n const id = doc.external_id\n // Shift: the range from the anchor, which stays put so further shift-clicks re-extend it.\n if (e.shiftKey) {\n const from = anchorRef.current ?? id\n const a = orderedFileIds.indexOf(from)\n const b = orderedFileIds.indexOf(id)\n if (a !== -1 && b !== -1) {\n anchorRef.current = from\n const [lo, hi] = a < b ? [a, b] : [b, a]\n onSelectionChange(orderedFileIds.slice(lo, hi + 1))\n return\n }\n }\n // \u2318/Ctrl: toggle this file, keeping the rest; it becomes the anchor.\n if (e.metaKey || e.ctrlKey) {\n onSelectionChange(\n selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]\n )\n anchorRef.current = id\n return\n }\n onSelectionChange([id])\n anchorRef.current = id\n },\n [onSelectionChange, orderedFileIds, selectedIds, selectedSet]\n )\n\n const handleToggle = useCallback(\n (doc: FileTileDocument, e: React.MouseEvent) => {\n e.stopPropagation()\n const id = doc.external_id\n onSelectionChange(\n selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]\n )\n anchorRef.current = id\n },\n [onSelectionChange, selectedIds, selectedSet]\n )\n\n // A folder toggles every document inside it: a folder is shorthand for \"everything in it\".\n const handleToggleFolder = useCallback(\n (folder: ExplorerFolder, e: React.MouseEvent) => {\n e.stopPropagation()\n const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id)\n if (ids.length === 0) return\n if (ids.every((id) => selectedSet.has(id))) {\n const remove = new Set(ids)\n onSelectionChange(selectedIds.filter((id) => !remove.has(id)))\n } else {\n onSelectionChange(Array.from(new Set([...selectedIds, ...ids])))\n }\n anchorRef.current = null\n },\n [documents, onSelectionChange, selectedIds, selectedSet]\n )\n\n const handleOpenFile = useCallback(\n (doc: FileTileDocument) => onOpenDocument(doc.external_id),\n [onOpenDocument]\n )\n const handleOpenInReview = useMemo(\n () => (onOpenInReview ? (doc: FileTileDocument) => onOpenInReview(doc.external_id) : undefined),\n [onOpenInReview]\n )\n\n // ---- Rename (inline; the document's title)\n\n const startRename = useCallback((doc: FileTileDocument) => setRenamingId(doc.external_id), [])\n const cancelRename = useCallback(() => setRenamingId(null), [])\n const commitRename = useCallback(\n async (doc: FileTileDocument, name: string) => {\n setRenamingId(null)\n try {\n await updateDocument.mutateAsync({\n documents: [\n { external_id: doc.external_id, doc_metadata: { ...doc.doc_metadata, title: name } },\n ],\n })\n notify(`Renamed to \"${name}\"`, 'success')\n } catch {\n notify('Failed to rename. Please try again.', 'error')\n }\n },\n [updateDocument, notify]\n )\n\n // F2 renames the one selected file.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'F2' || renamingId) return\n const target = e.target as HTMLElement | null\n if (target && /^(input|textarea|select)$/i.test(target.tagName)) return\n if (selectedIdsRef.current.length === 1) setRenamingId(selectedIdsRef.current[0])\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [renamingId])\n\n // ---- A file's menu\n\n const handleDownload = useCallback(\n (doc: FileTileDocument) => void downloadDocument(doc),\n [downloadDocument]\n )\n\n // \"Move to\u2026\" acts on the selection: select just this file first.\n const handleMove = useMemo(\n () =>\n onMoveSelected\n ? (doc: FileTileDocument) => {\n onSelectionChange([doc.external_id])\n onMoveSelected()\n }\n : undefined,\n [onSelectionChange, onMoveSelected]\n )\n\n const handleDelete = useCallback(\n async (doc: FileTileDocument) => {\n const name = getExplorerDisplayName(doc)\n const confirmed = await confirm({\n message: `Delete \"${name}\"? ${RECENTLY_DELETED_HINT}`,\n title: 'Delete file',\n })\n if (!confirmed) return\n try {\n await deleteDocuments.mutateAsync([doc.external_id])\n onSelectionChange(selectedIdsRef.current.filter((id) => id !== doc.external_id))\n notify(`Deleted \"${name}\"`, 'success')\n } catch {\n notify('Failed to delete. Please try again.', 'error')\n }\n },\n [confirm, deleteDocuments, onSelectionChange, notify]\n )\n\n // ---- A folder's menu: each acts on everything the folder holds.\n\n const startFolderRename = useCallback(\n (folder: ExplorerFolder) => setEditingFolderPath(folder.path.join('/')),\n []\n )\n\n const handleFolderDownload = useCallback(\n (folder: ExplorerFolder) => {\n const docs = collectFolderDocs(documents, folder.path)\n if (docs.length > 0) void downloadDocuments(docs)\n },\n [documents, downloadDocuments]\n )\n\n const handleFolderMove = useMemo(() => {\n if (onFolderMove) return onFolderMove\n if (!onMoveSelected) return undefined\n // A flat move (the structure is not kept).\n return (folder: ExplorerFolder) => {\n const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id)\n if (ids.length === 0) return\n onSelectionChange(ids)\n onMoveSelected()\n }\n }, [documents, onFolderMove, onMoveSelected, onSelectionChange])\n\n const handleFolderDelete = useCallback(\n async (folder: ExplorerFolder) => {\n const docs = collectFolderDocs(documents, folder.path)\n // An empty placeholder: drop it (nothing to delete).\n if (docs.length === 0) {\n const path = joinFolderPath(folder.path)\n if (wsId && path) removePendingFolder(wsId, path)\n return\n }\n const confirmed = await confirm({\n message: `Delete folder \"${folder.name}\" and its ${docs.length} item${docs.length === 1 ? '' : 's'}? ${RECENTLY_DELETED_HINT_PLURAL}`,\n title: 'Delete folder',\n })\n if (!confirmed) return\n try {\n const ids = docs.map((d) => d.external_id)\n await deleteDocuments.mutateAsync(ids)\n const removed = new Set(ids)\n onSelectionChange(selectedIdsRef.current.filter((id) => !removed.has(id)))\n notify(`Deleted folder \"${folder.name}\"`, 'success')\n } catch {\n notify('Failed to delete folder. Please try again.', 'error')\n }\n },\n [confirm, documents, deleteDocuments, onSelectionChange, removePendingFolder, wsId, notify]\n )\n\n // Deleting a folder deletes every file inside: offered only when the viewer may delete them all.\n const canDeleteFolder = useCallback(\n (folder: ExplorerFolder) =>\n canUpload &&\n collectFolderDocs(documents, folder.path).every((doc) =>\n canDeleteDocument(doc, userId, role)\n ),\n [canUpload, documents, userId, role]\n )\n\n const handleBackgroundClick = useCallback(\n (e: React.MouseEvent) => {\n // The click that ends a marquee keeps its selection.\n if (didMarqueeRef.current) {\n didMarqueeRef.current = false\n return\n }\n if (!(e.target as HTMLElement).closest('[data-testid^=\"explorer-\"]')) clearSelection()\n },\n [clearSelection]\n )\n\n // ---- Moving: drag onto a folder\n\n const moveDocs = useCallback(\n async (ids: string[], folder: string | null) => {\n if (ids.length === 0) return\n try {\n await updateDocument.mutateAsync({\n documents: ids.map((external_id) => ({ external_id, folder })),\n })\n // The moved files left this view: a stale selection must not ride into the next drag.\n clearSelection()\n notify(\n `Moved ${ids.length} item${ids.length === 1 ? '' : 's'} to \"${folder ?? 'Home'}\"`,\n 'success'\n )\n } catch {\n notify('Failed to move. Please try again.', 'error')\n }\n },\n [updateDocument, clearSelection, notify]\n )\n\n // Mouse + touch sensors, not the pointer sensor: its pointer capture swallows the move events on\n // some setups, so the drop target is never found.\n const sensors = useSensors(\n useSensor(MouseSensor, { activationConstraint: { distance: 6 } }),\n useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } })\n )\n\n // The folder under the pointer; else (between tiles, a folder's edge) the one the dragged tile\n // overlaps most, so a drop near a folder still moves the files.\n const collisionDetection = useCallback<CollisionDetection>((args) => {\n const hits = pointerWithin(args)\n return hits.length > 0 ? hits : rectIntersection(args)\n }, [])\n\n const handleDragStart = useCallback(\n (event: DragStartEvent) => {\n const docId = event.active.data.current?.docId as string | undefined\n if (!docId) return\n setActiveDragId(docId)\n if (!selectedIdsRef.current.includes(docId)) {\n onSelectionChange([docId])\n dragIdsRef.current = [docId]\n } else {\n dragIdsRef.current = selectedIdsRef.current\n }\n },\n [onSelectionChange]\n )\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n setActiveDragId(null)\n const data = event.over?.data.current as { type?: string; path?: string[] } | undefined\n if (data?.type === 'folder' && data.path) {\n const targetFolder = joinFolderPath(data.path)\n // Files already in the target stay put.\n const moving = dragIdsRef.current.filter((id) => {\n const doc = documents.find((d) => d.external_id === id)\n return doc && (doc.folder ?? null) !== targetFolder\n })\n void moveDocs(moving, targetFolder)\n }\n },\n [documents, moveDocs]\n )\n\n // ---- Drop to upload (OS files)\n\n const handleNativeDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!canUpload) return\n if (e.dataTransfer.types.includes('Files')) {\n e.preventDefault()\n e.dataTransfer.dropEffect = 'copy'\n }\n },\n [canUpload]\n )\n\n const handleNativeDragEnter = useCallback(\n (e: React.DragEvent) => {\n if (!canUpload || !e.dataTransfer.types.includes('Files')) return\n fileDragDepth.current += 1\n setIsFileDragOver(true)\n },\n [canUpload]\n )\n\n const handleNativeDragLeave = useCallback(() => {\n fileDragDepth.current = Math.max(0, fileDragDepth.current - 1)\n if (fileDragDepth.current === 0) setIsFileDragOver(false)\n }, [])\n\n const handleNativeDrop = useCallback(\n (e: React.DragEvent) => {\n fileDragDepth.current = 0\n setIsFileDragOver(false)\n if (!canUpload) return\n const dropped = Array.from(e.dataTransfer.files ?? [])\n if (dropped.length > 0) {\n e.preventDefault()\n onUploadFiles(dropped, joinFolderPath(currentPath))\n }\n },\n [canUpload, currentPath, onUploadFiles]\n )\n\n // ---- Render\n\n const activeDoc = activeDragId ? documents.find((d) => d.external_id === activeDragId) : null\n const dragCount = dragIdsRef.current.length || 1\n\n if (isWholeWorkspaceEmpty) return <>{emptyWorkspace}</>\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={() => setActiveDragId(null)}\n >\n <ExplorerFrame data-testid=\"documents-explorer\">\n <ExplorerStage>\n <ExplorerScroller\n ref={scrollRef}\n onClick={handleBackgroundClick}\n onPointerDown={handleScrollPointerDown}\n onDragEnter={handleNativeDragEnter}\n onDragOver={handleNativeDragOver}\n onDragLeave={handleNativeDragLeave}\n onDrop={handleNativeDrop}\n data-testid=\"explorer-scroll\"\n >\n {isLoading && documents.length === 0 ? (\n <ExplorerLoadingTiles />\n ) : entries.length === 0 ? (\n <ExplorerEmpty\n title={isSearching ? `No files match \"${search.trim()}\"` : 'This folder is empty'}\n description={\n isSearching\n ? 'Try a different search.'\n : canUpload\n ? 'Drop files here or use Upload to add documents.'\n : 'No documents here yet.'\n }\n />\n ) : containerWidth === 0 ? (\n // Not measured yet: rendering now would flash one stretched column.\n <ExplorerLoadingTiles />\n ) : (\n <div\n style={{\n height: rowVirtualizer.getTotalSize(),\n position: 'relative',\n width: '100%',\n }}\n >\n {virtualRows.map((virtualRow) => {\n const start = virtualRow.index * columnCount\n const rowEntries = entries.slice(start, start + columnCount)\n return (\n <div\n key={virtualRow.key}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: tileHeight,\n transform: `translateY(${virtualRow.start}px)`,\n display: 'grid',\n gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,\n columnGap: GRID_GAP,\n }}\n >\n {rowEntries.map((entry) => {\n if (entry.kind === 'folder') {\n const key = entry.path.join('/')\n return (\n <FolderTile\n key={`folder:${key}`}\n folder={entry}\n density={density}\n editing={editingFolderPath === key}\n selected={folderSelection.get(key)?.all}\n partiallySelected={folderSelection.get(key)?.some}\n documents={folderDocs.get(key) ?? NO_DOCUMENTS}\n onOpen={openFolder}\n onToggleSelect={handleToggleFolder}\n onCommitName={commitFolderName}\n onCancelName={cancelFolderName}\n onStartRename={canUpload ? startFolderRename : undefined}\n onDownload={handleFolderDownload}\n onMove={canUpload ? handleFolderMove : undefined}\n onDelete={canDeleteFolder(entry) ? handleFolderDelete : undefined}\n actions={hostActions}\n />\n )\n }\n const doc = entry.doc\n return (\n <FileTile\n key={doc.external_id}\n doc={doc}\n density={density}\n selected={selectedSet.has(doc.external_id)}\n dragging={activeDragId === doc.external_id}\n dndActive={activeDragId !== null}\n renaming={renamingId === doc.external_id}\n canDelete={canDeleteDocument(doc, userId, role)}\n thumbnailUrl={thumbnailsById.get(doc.external_id)}\n modifiedBy={userById.get(\n doc.updated_by_ext_id ?? doc.created_by_ext_id\n )}\n tagNameById={tagNameById}\n onSelect={handleSelect}\n onToggle={handleToggle}\n onOpen={handleOpenFile}\n onReview={handleOpenInReview}\n onStartRename={startRename}\n onCommitRename={commitRename}\n onCancelRename={cancelRename}\n onDownload={handleDownload}\n onMove={canUpload ? handleMove : undefined}\n onDelete={handleDelete}\n actions={hostActions}\n />\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n </ExplorerScroller>\n\n {/* The marquee: always mounted, drawn by mutating its style during a drag. */}\n <ExplorerMarquee ref={marqueeOverlayRef} data-testid=\"explorer-marquee\" />\n\n {isFileDragOver && (\n <ExplorerDropOverlay\n label={`Drop to upload${\n currentPath.length > 0 ? ` to \"${currentPath[currentPath.length - 1]}\"` : ''\n }`}\n />\n )}\n </ExplorerStage>\n </ExplorerFrame>\n\n <DragOverlay dropAnimation={null}>\n {activeDoc ? <DragPreview doc={activeDoc} count={dragCount} /> : null}\n </DragOverlay>\n </DndContext>\n )\n})\n\n/** The preview under the cursor while files are dragged. */\nfunction DragPreview({ doc, count }: { doc: FileTileDocument; count: number }) {\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type })\n return (\n <ExplorerDragPreview\n icon={<Icon size={20} />}\n title={getDocumentTitle(doc, doc.file_name ?? 'Untitled')}\n count={count}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * The workspace's files as a file explorer (OneDrive / Drive style), bound to the session: folders\n * come from each document's `folder` path; renames, moves and deletes are written through\n * `@arbidocs/react`.\n *\n * - Breadcrumb navigation is the host's (`folderPath` / `onFolderPathChange`): it may keep the\n * folder in a filter, the URL or state.\n * - A virtualised tile grid that scales to thousands of documents, sized by `tileSize`.\n * - OS-style selection: click, \u2318/Ctrl-click, shift-range, the hover checkbox and a marquee.\n * - Drag files onto a folder tile to move them; drop OS files on the view to upload.\n *\n * Selection is the host's (`selectedIds` / `onSelectionChange`), so its bulk actions act on it.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport {\n DndContext,\n DragOverlay,\n MouseSensor,\n TouchSensor,\n pointerWithin,\n rectIntersection,\n useSensor,\n useSensors,\n type CollisionDetection,\n type DragEndEvent,\n type DragStartEvent,\n} from '@dnd-kit/core'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport {\n useDeleteDocuments,\n useDocumentHostActions,\n useDocumentThumbnails,\n useDownloadDocuments,\n useRenameFolder,\n useTags,\n useUpdateDocuments,\n useWorkspaces,\n} from '@arbidocs/react'\nimport { getDocumentTitle, getFileTypeIcon } from '@arbidocs/react/ui'\nimport {\n ExplorerDragPreview,\n ExplorerDropOverlay,\n ExplorerEmpty,\n ExplorerFrame,\n ExplorerMarquee,\n ExplorerScroller,\n ExplorerStage,\n} from '../../../files/ExplorerSurface'\nimport { ExplorerLoadingTiles } from '../../../files/Explorer'\nimport {\n buildExplorerEntries,\n collectFolderDocs,\n getExplorerDisplayName,\n joinFolderPath,\n searchExplorerDocuments,\n type ExplorerEntry,\n type ExplorerFolder,\n type ExplorerSort,\n} from '../../../files/folders'\nimport { canDeleteDocument, type WorkspaceMemberRole } from '../../../files/permissions'\nimport {\n RECENTLY_DELETED_HINT,\n RECENTLY_DELETED_HINT_PLURAL,\n} from '../../../files/recently-deleted'\nimport { useBlocksEnvironment } from '../../../provider/environment'\nimport { useConnectedWorkspace } from '../../ConnectionProvider'\nimport { useConnectedWorkspaceRole } from '../../ConnectedWorkflowsTable'\nimport { useFilesStore, usePendingFolders } from '../store'\nimport {\n FileTile,\n FolderTile,\n type ExplorerDensity,\n type FileTileDocument,\n type FileTileUser,\n} from './FileTiles'\n\n// Both densities are thumbnail grids, differing only in tile size. Row heights include the gap so\n// the virtualiser's estimate matches the rendered slot exactly.\nconst GRID_GAP = 12\n// The scroller's horizontal padding (px-4 each side).\nconst SCROLL_PADDING_X = 32\n// A portrait page (height / width), so cover-page thumbnails read.\nconst PAGE_ASPECT = 1.3\n/** The zoom slider's bounds: the target tile width in px (smaller: more tiles per row). */\nexport const TILE_MIN = 88\nexport const TILE_MAX = 232\nexport const TILE_DEFAULT = 200\n// Narrower tiles use the compact styling.\nconst COMPACT_BELOW = 132\nconst NO_DOCUMENTS: FileTileDocument[] = []\n\nexport interface ConnectedFilesExplorerHandle {\n /** Add a placeholder folder here and start naming it. */\n triggerNewFolder: () => void\n /** Scroll the tile of `docId` into view, when it is displayed. */\n scrollToDocument: (docId: string) => void\n}\n\nexport interface ConnectedFilesExplorerProps {\n documents: FileTileDocument[]\n isLoading: boolean\n /** The viewer may add, rename and move files here. */\n canUpload: boolean\n selectedIds: string[]\n onSelectionChange: (ids: string[]) => void\n onOpenDocument: (docId: string) => void\n onUploadFiles: (files: File[], folder?: string | null) => void\n /** The open folder (empty: the workspace root). */\n folderPath: readonly string[]\n onFolderPathChange: (path: string[]) => void\n /** A search across every folder (absent or empty: the open folder is listed). */\n search?: string\n sort: ExplorerSort\n sortReversed: boolean\n /** The target tile width in px (`TILE_MIN`..`TILE_MAX`). */\n tileSize: number\n /** The ids of the files displayed, in display order (a navigator steps the same list). */\n onOrderedFilesChange?: (docIds: string[]) => void\n /** Move the selected files: the host opens its folder picker. Absent: not offered. */\n onMoveSelected?: () => void\n /** Move a folder with its structure: the host opens its folder picker. */\n onFolderMove?: (folder: ExplorerFolder) => void\n /** Open a document in the host's review view. Absent: not offered. */\n onOpenInReview?: (docId: string) => void\n /** Shown instead of the explorer while the workspace has no documents and the viewer may add. */\n emptyWorkspace?: ReactNode\n}\n\n/** The workspace's name (the download archive is named after it), members and the viewer's role. */\nfunction useFilesWorkspace() {\n const { workspaceId, userId, live } = useConnectedWorkspace()\n const { members, role } = useConnectedWorkspaceRole()\n const { data: workspaces } = useWorkspaces({ enabled: live })\n const workspaceName = workspaces?.find((w) => w.external_id === workspaceId)?.name\n return {\n workspaceId: workspaceId ?? '',\n workspaceName,\n userId,\n role: (role ?? null) as WorkspaceMemberRole | null,\n members,\n }\n}\n\nexport const ConnectedFilesExplorer = forwardRef<\n ConnectedFilesExplorerHandle,\n ConnectedFilesExplorerProps\n>(function ConnectedFilesExplorer(\n {\n documents,\n isLoading,\n canUpload,\n selectedIds,\n onSelectionChange,\n onOrderedFilesChange,\n onOpenDocument,\n onUploadFiles,\n folderPath,\n onFolderPathChange,\n search = '',\n sort,\n sortReversed,\n tileSize,\n onMoveSelected,\n onFolderMove,\n onOpenInReview,\n emptyWorkspace,\n },\n ref\n) {\n const { confirm, notify } = useBlocksEnvironment()\n const currentPath = folderPath as string[]\n const density: ExplorerDensity = tileSize < COMPACT_BELOW ? 'list' : 'grid'\n const [containerWidth, setContainerWidth] = useState(0)\n const [activeDragId, setActiveDragId] = useState<string | null>(null)\n const [isFileDragOver, setIsFileDragOver] = useState(false)\n const [renamingId, setRenamingId] = useState<string | null>(null)\n\n const scrollRef = useRef<HTMLDivElement | null>(null)\n const anchorRef = useRef<string | null>(null)\n const dragIdsRef = useRef<string[]>([])\n const fileDragDepth = useRef(0)\n // The marquee is drawn by mutating this overlay's style (one paint per frame), so dragging the\n // lasso never re-renders the grid; the selection is computed once, on release.\n const marqueeOverlayRef = useRef<HTMLDivElement | null>(null)\n // The marquee gesture: its origin, whether it adds to the selection, and that selection.\n const marqueeRef = useRef<{ x: number; y: number; additive: boolean; base: string[] } | null>(\n null\n )\n // A background drag crossed the start threshold: the click that follows must not clear.\n const didMarqueeRef = useRef(false)\n\n const updateDocument = useUpdateDocuments()\n const deleteDocuments = useDeleteDocuments()\n const renameFolder = useRenameFolder()\n const { workspaceId: wsId, workspaceName, userId, role, members } = useFilesWorkspace()\n const { downloadDocuments, downloadDocument } = useDownloadDocuments({ workspaceName })\n const { data: workspaceTags } = useTags()\n const hostActions = useDocumentHostActions()\n\n // Member and label lookups for the hover card, memoised so they keep the tiles memoised.\n const userById = useMemo(() => {\n const map = new Map<string, FileTileUser>()\n for (const member of members) map.set(member.user.external_id, member.user)\n return map\n }, [members])\n const tagNameById = useMemo(() => {\n const map = new Map<string, string>()\n for (const tag of workspaceTags ?? []) map.set(tag.external_id, tag.name)\n return map\n }, [workspaceTags])\n\n // Placeholder (empty) folders of this workspace.\n const pendingFolders = usePendingFolders(wsId)\n const addPendingFolder = useFilesStore((state) => state.addPendingFolder)\n const removePendingFolder = useFilesStore((state) => state.removePendingFolder)\n // The placeholder folder being named inline (its full path).\n const [editingFolderPath, setEditingFolderPath] = useState<string | null>(null)\n\n const isSearching = search.trim().length > 0\n\n // The selection for handlers that run outside the render that produced it (drag, keys).\n const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds])\n const selectedIdsRef = useRef(selectedIds)\n selectedIdsRef.current = selectedIds\n\n // The open folder's entries, or a flat search result.\n const { folders, files } = useMemo(() => {\n const result = isSearching\n ? {\n folders: [] as ExplorerFolder[],\n files: searchExplorerDocuments(documents, search, sort),\n }\n : buildExplorerEntries(documents, currentPath, sort, [...pendingFolders])\n if (sortReversed) result.files = [...result.files].reverse()\n return result\n }, [documents, currentPath, sort, isSearching, search, sortReversed, pendingFolders])\n\n const entries: ExplorerEntry<FileTileDocument>[] = useMemo(\n () => [...folders, ...files.map((doc) => ({ kind: 'file' as const, doc }))],\n [folders, files]\n )\n const orderedFileIds = useMemo(() => files.map((d) => d.external_id), [files])\n // Each folder's documents (everything beneath it), and whether the selection holds all or some of\n // them: its checkbox and selected styling. Keyed by the joined path.\n const folderDocs = useMemo(() => {\n const map = new Map<string, FileTileDocument[]>()\n for (const f of folders) map.set(f.path.join('/'), collectFolderDocs(documents, f.path))\n return map\n }, [folders, documents])\n const folderSelection = useMemo(() => {\n const map = new Map<string, { all: boolean; some: boolean }>()\n for (const [key, docs] of folderDocs) {\n const sel = docs.reduce((n, d) => (selectedSet.has(d.external_id) ? n + 1 : n), 0)\n map.set(key, { all: docs.length > 0 && sel === docs.length, some: sel > 0 })\n }\n return map\n }, [folderDocs, selectedSet])\n\n // Columns from the measured width, each tile a portrait page so the thumbnail is legible.\n const contentWidth = Math.max(0, containerWidth - SCROLL_PADDING_X)\n const columnCount = Math.max(\n 1,\n Math.floor((contentWidth + GRID_GAP) / (tileSize + GRID_GAP)) || 1\n )\n const colWidth =\n contentWidth > 0 ? (contentWidth - (columnCount - 1) * GRID_GAP) / columnCount : tileSize\n const tileHeight = Math.max(120, Math.round(colWidth * PAGE_ASPECT))\n const rowHeight = tileHeight + GRID_GAP\n const rowCount = Math.ceil(entries.length / columnCount)\n\n const rowVirtualizer = useVirtualizer({\n count: rowCount,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => rowHeight,\n overscan: 3,\n })\n\n // The displayed files (on-screen rows plus overscan): the thumbnail loader fetches only these.\n const virtualRows = rowVirtualizer.getVirtualItems()\n const firstRow = virtualRows.length > 0 ? virtualRows[0].index : 0\n const lastRow = virtualRows.length > 0 ? virtualRows[virtualRows.length - 1].index : -1\n const visibleFileIds = useMemo(() => {\n const ids: string[] = []\n for (let r = firstRow; r <= lastRow; r++) {\n const start = r * columnCount\n for (let c = 0; c < columnCount; c++) {\n const entry = entries[start + c]\n if (entry?.kind === 'file') ids.push(entry.doc.external_id)\n }\n }\n return ids\n }, [firstRow, lastRow, columnCount, entries])\n const thumbnailsById = useDocumentThumbnails(visibleFileIds)\n\n useEffect(() => {\n rowVirtualizer.measure()\n }, [rowVirtualizer, columnCount, rowHeight, entries.length])\n\n // The empty workspace shows the host's dropzone instead of the scroller, so the first upload\n // mounts the scroller fresh: the width measurement re-runs on this flag (else the grid stays on\n // the loading tiles until a reload).\n const isWholeWorkspaceEmpty =\n !isLoading && documents.length === 0 && canUpload && emptyWorkspace !== undefined\n\n // The width is measured before paint (a first frame at width 0 would flash one stretched column)\n // and rounded and deduplicated, so sub-pixel resize noise does not re-run the tile maths.\n useLayoutEffect(() => {\n const el = scrollRef.current\n if (!el) return\n const apply = () => {\n const next = Math.round(el.clientWidth)\n setContainerWidth((prev) => (prev === next ? prev : next))\n }\n apply()\n const ro = new ResizeObserver(apply)\n ro.observe(el)\n return () => ro.disconnect()\n }, [isWholeWorkspaceEmpty])\n\n // A new listing scrolls to the top and drops the range anchor.\n useEffect(() => {\n anchorRef.current = null\n if (scrollRef.current) scrollRef.current.scrollTop = 0\n }, [currentPath, search])\n\n // ---- Marquee selection: a drag from empty space selects, on release, every tile it touches;\n // \u2318/Ctrl/Shift at the start adds to the selection. Clamped to the scroller.\n useEffect(() => {\n const MARQUEE_THRESHOLD = 5\n let rafId = 0\n let cur: { left: number; top: number; right: number; bottom: number } | null = null\n\n const paint = () => {\n rafId = 0\n const el = marqueeOverlayRef.current\n if (!el || !cur) return\n el.style.display = 'block'\n el.style.left = `${cur.left}px`\n el.style.top = `${cur.top}px`\n el.style.width = `${cur.right - cur.left}px`\n el.style.height = `${cur.bottom - cur.top}px`\n }\n\n const onMove = (e: PointerEvent) => {\n const m = marqueeRef.current\n if (!m) return\n if (\n !didMarqueeRef.current &&\n Math.hypot(e.clientX - m.x, e.clientY - m.y) < MARQUEE_THRESHOLD\n )\n return\n didMarqueeRef.current = true\n const b = scrollRef.current?.getBoundingClientRect()\n const px = b ? Math.max(b.left, Math.min(e.clientX, b.right)) : e.clientX\n const py = b ? Math.max(b.top, Math.min(e.clientY, b.bottom)) : e.clientY\n cur = {\n left: Math.min(m.x, px),\n top: Math.min(m.y, py),\n right: Math.max(m.x, px),\n bottom: Math.max(m.y, py),\n }\n if (!rafId) rafId = requestAnimationFrame(paint)\n }\n\n const onUp = () => {\n const m = marqueeRef.current\n if (!m) return\n marqueeRef.current = null\n if (rafId) cancelAnimationFrame(rafId)\n rafId = 0\n const el = marqueeOverlayRef.current\n if (el) el.style.display = 'none'\n if (!didMarqueeRef.current || !cur) return\n const box = cur\n const hit: string[] = []\n scrollRef.current?.querySelectorAll('[data-doc-id]').forEach((node) => {\n const r = node.getBoundingClientRect()\n if (r.left < box.right && r.right > box.left && r.top < box.bottom && r.bottom > box.top) {\n const id = node.getAttribute('data-doc-id')\n if (id) hit.push(id)\n }\n })\n onSelectionChange(m.additive ? Array.from(new Set([...m.base, ...hit])) : hit)\n }\n\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n return () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n if (rafId) cancelAnimationFrame(rafId)\n }\n }, [onSelectionChange])\n\n const handleScrollPointerDown = useCallback((e: React.PointerEvent) => {\n if (e.button !== 0) return\n const el = e.target as HTMLElement\n if (\n el.closest(\n '[data-testid=\"explorer-file\"],[data-testid=\"explorer-folder\"],button,input,select,a,[role=\"button\"]'\n )\n ) {\n return\n }\n const additive = e.shiftKey || e.metaKey || e.ctrlKey\n marqueeRef.current = {\n x: e.clientX,\n y: e.clientY,\n additive,\n base: additive ? selectedIdsRef.current : [],\n }\n didMarqueeRef.current = false\n }, [])\n\n // ---- Navigation\n\n const openFolder = useCallback(\n (folder: ExplorerFolder) => onFolderPathChange(folder.path),\n [onFolderPathChange]\n )\n\n // ---- Placeholder (empty) folders\n\n const handleNewFolder = useCallback(() => {\n if (!wsId) return\n const siblings = new Set(folders.map((f) => f.name.toLowerCase()))\n const base = 'New folder'\n let name = base\n let i = 2\n while (siblings.has(name.toLowerCase())) name = `${base} ${i++}`\n const path = joinFolderPath([...currentPath, name])\n if (!path) return\n addPendingFolder(wsId, path)\n setEditingFolderPath(path)\n }, [wsId, folders, currentPath, addPendingFolder])\n\n // Publish the displayed order only when the ids differ: `documents` is a new array on most\n // renders, and handing each new identity to the host's state would loop.\n const lastOrderedRef = useRef<string[]>([])\n useEffect(() => {\n const prev = lastOrderedRef.current\n if (prev.length === orderedFileIds.length && prev.every((id, i) => id === orderedFileIds[i])) {\n return\n }\n lastOrderedRef.current = orderedFileIds\n onOrderedFilesChange?.(orderedFileIds)\n }, [onOrderedFilesChange, orderedFileIds])\n\n const scrollToDocument = useCallback(\n (docId: string) => {\n const index = entries.findIndex((e) => e.kind === 'file' && e.doc.external_id === docId)\n if (index < 0) return\n rowVirtualizer.scrollToIndex(Math.floor(index / columnCount), { align: 'center' })\n },\n [entries, columnCount, rowVirtualizer]\n )\n\n useImperativeHandle(ref, () => ({ triggerNewFolder: handleNewFolder, scrollToDocument }), [\n handleNewFolder,\n scrollToDocument,\n ])\n\n const commitFolderName = useCallback(\n async (folder: ExplorerFolder, rawName: string) => {\n setEditingFolderPath(null)\n const name = rawName.trim()\n if (!wsId || !name || name === folder.name) return\n const siblings = new Set(folders.filter((f) => f !== folder).map((f) => f.name.toLowerCase()))\n if (siblings.has(name.toLowerCase())) {\n notify(`A folder named \"${name}\" already exists here.`, 'error')\n return\n }\n const oldPath = joinFolderPath(folder.path)\n const newPrefix = [...folder.path.slice(0, -1), name]\n const newPath = joinFolderPath(newPrefix)\n\n // Every document beneath the folder moves under the new name, the subtree with it.\n const docs = collectFolderDocs(documents, folder.path)\n try {\n if ((await renameFolder(docs, folder.path, newPrefix)) > 0) {\n notify(`Renamed folder to \"${name}\"`, 'success')\n }\n } catch {\n notify('Failed to rename folder. Please try again.', 'error')\n return\n }\n if (oldPath) removePendingFolder(wsId, oldPath)\n if (docs.length === 0 && newPath) addPendingFolder(wsId, newPath)\n },\n [wsId, folders, documents, renameFolder, notify, addPendingFolder, removePendingFolder]\n )\n\n const cancelFolderName = useCallback(() => setEditingFolderPath(null), [])\n\n // ---- Selection\n\n const clearSelection = useCallback(() => {\n if (selectedIdsRef.current.length > 0) onSelectionChange([])\n anchorRef.current = null\n }, [onSelectionChange])\n\n const handleSelect = useCallback(\n (doc: FileTileDocument, e: React.MouseEvent) => {\n const id = doc.external_id\n // Shift: the range from the anchor, which stays put so further shift-clicks re-extend it.\n if (e.shiftKey) {\n const from = anchorRef.current ?? id\n const a = orderedFileIds.indexOf(from)\n const b = orderedFileIds.indexOf(id)\n if (a !== -1 && b !== -1) {\n anchorRef.current = from\n const [lo, hi] = a < b ? [a, b] : [b, a]\n onSelectionChange(orderedFileIds.slice(lo, hi + 1))\n return\n }\n }\n // \u2318/Ctrl: toggle this file, keeping the rest; it becomes the anchor.\n if (e.metaKey || e.ctrlKey) {\n onSelectionChange(\n selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]\n )\n anchorRef.current = id\n return\n }\n onSelectionChange([id])\n anchorRef.current = id\n },\n [onSelectionChange, orderedFileIds, selectedIds, selectedSet]\n )\n\n const handleToggle = useCallback(\n (doc: FileTileDocument, e: React.MouseEvent) => {\n e.stopPropagation()\n const id = doc.external_id\n onSelectionChange(\n selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]\n )\n anchorRef.current = id\n },\n [onSelectionChange, selectedIds, selectedSet]\n )\n\n // A folder toggles every document inside it: a folder is shorthand for \"everything in it\".\n const handleToggleFolder = useCallback(\n (folder: ExplorerFolder, e: React.MouseEvent) => {\n e.stopPropagation()\n const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id)\n if (ids.length === 0) return\n if (ids.every((id) => selectedSet.has(id))) {\n const remove = new Set(ids)\n onSelectionChange(selectedIds.filter((id) => !remove.has(id)))\n } else {\n onSelectionChange(Array.from(new Set([...selectedIds, ...ids])))\n }\n anchorRef.current = null\n },\n [documents, onSelectionChange, selectedIds, selectedSet]\n )\n\n const handleOpenFile = useCallback(\n (doc: FileTileDocument) => onOpenDocument(doc.external_id),\n [onOpenDocument]\n )\n const handleOpenInReview = useMemo(\n () => (onOpenInReview ? (doc: FileTileDocument) => onOpenInReview(doc.external_id) : undefined),\n [onOpenInReview]\n )\n\n // ---- Rename (inline; the document's title)\n\n const startRename = useCallback((doc: FileTileDocument) => setRenamingId(doc.external_id), [])\n const cancelRename = useCallback(() => setRenamingId(null), [])\n const commitRename = useCallback(\n async (doc: FileTileDocument, name: string) => {\n setRenamingId(null)\n try {\n await updateDocument.mutateAsync({\n documents: [\n { external_id: doc.external_id, doc_metadata: { ...doc.doc_metadata, title: name } },\n ],\n })\n notify(`Renamed to \"${name}\"`, 'success')\n } catch {\n notify('Failed to rename. Please try again.', 'error')\n }\n },\n [updateDocument, notify]\n )\n\n // F2 renames the one selected file.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'F2' || renamingId) return\n const target = e.target as HTMLElement | null\n if (target && /^(input|textarea|select)$/i.test(target.tagName)) return\n if (selectedIdsRef.current.length === 1) setRenamingId(selectedIdsRef.current[0])\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [renamingId])\n\n // ---- A file's menu\n\n const handleDownload = useCallback(\n (doc: FileTileDocument) => void downloadDocument(doc),\n [downloadDocument]\n )\n\n // \"Move to\u2026\" acts on the selection: select just this file first.\n const handleMove = useMemo(\n () =>\n onMoveSelected\n ? (doc: FileTileDocument) => {\n onSelectionChange([doc.external_id])\n onMoveSelected()\n }\n : undefined,\n [onSelectionChange, onMoveSelected]\n )\n\n const handleDelete = useCallback(\n async (doc: FileTileDocument) => {\n const name = getExplorerDisplayName(doc)\n const confirmed = await confirm({\n message: `Delete \"${name}\"? ${RECENTLY_DELETED_HINT}`,\n title: 'Delete file',\n })\n if (!confirmed) return\n try {\n await deleteDocuments.mutateAsync([doc.external_id])\n onSelectionChange(selectedIdsRef.current.filter((id) => id !== doc.external_id))\n notify(`Deleted \"${name}\"`, 'success')\n } catch {\n notify('Failed to delete. Please try again.', 'error')\n }\n },\n [confirm, deleteDocuments, onSelectionChange, notify]\n )\n\n // ---- A folder's menu: each acts on everything the folder holds.\n\n const startFolderRename = useCallback(\n (folder: ExplorerFolder) => setEditingFolderPath(folder.path.join('/')),\n []\n )\n\n const handleFolderDownload = useCallback(\n (folder: ExplorerFolder) => {\n const docs = collectFolderDocs(documents, folder.path)\n if (docs.length > 0) void downloadDocuments(docs)\n },\n [documents, downloadDocuments]\n )\n\n const handleFolderMove = useMemo(() => {\n if (onFolderMove) return onFolderMove\n if (!onMoveSelected) return undefined\n // A flat move (the structure is not kept).\n return (folder: ExplorerFolder) => {\n const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id)\n if (ids.length === 0) return\n onSelectionChange(ids)\n onMoveSelected()\n }\n }, [documents, onFolderMove, onMoveSelected, onSelectionChange])\n\n const handleFolderDelete = useCallback(\n async (folder: ExplorerFolder) => {\n const docs = collectFolderDocs(documents, folder.path)\n // An empty placeholder: drop it (nothing to delete).\n if (docs.length === 0) {\n const path = joinFolderPath(folder.path)\n if (wsId && path) removePendingFolder(wsId, path)\n return\n }\n const confirmed = await confirm({\n message: `Delete folder \"${folder.name}\" and its ${docs.length} item${docs.length === 1 ? '' : 's'}? ${RECENTLY_DELETED_HINT_PLURAL}`,\n title: 'Delete folder',\n })\n if (!confirmed) return\n try {\n const ids = docs.map((d) => d.external_id)\n await deleteDocuments.mutateAsync(ids)\n const removed = new Set(ids)\n onSelectionChange(selectedIdsRef.current.filter((id) => !removed.has(id)))\n notify(`Deleted folder \"${folder.name}\"`, 'success')\n } catch {\n notify('Failed to delete folder. Please try again.', 'error')\n }\n },\n [confirm, documents, deleteDocuments, onSelectionChange, removePendingFolder, wsId, notify]\n )\n\n // Deleting a folder deletes every file inside: offered only when the viewer may delete them all.\n const canDeleteFolder = useCallback(\n (folder: ExplorerFolder) =>\n canUpload &&\n collectFolderDocs(documents, folder.path).every((doc) =>\n canDeleteDocument(doc, userId, role)\n ),\n [canUpload, documents, userId, role]\n )\n\n const handleBackgroundClick = useCallback(\n (e: React.MouseEvent) => {\n // The click that ends a marquee keeps its selection.\n if (didMarqueeRef.current) {\n didMarqueeRef.current = false\n return\n }\n if (!(e.target as HTMLElement).closest('[data-testid^=\"explorer-\"]')) clearSelection()\n },\n [clearSelection]\n )\n\n // ---- Moving: drag onto a folder\n\n const moveDocs = useCallback(\n async (ids: string[], folder: string | null) => {\n if (ids.length === 0) return\n try {\n await updateDocument.mutateAsync({\n documents: ids.map((external_id) => ({ external_id, folder })),\n })\n // The moved files left this view: a stale selection must not ride into the next drag.\n clearSelection()\n notify(\n `Moved ${ids.length} item${ids.length === 1 ? '' : 's'} to \"${folder ?? 'Home'}\"`,\n 'success'\n )\n } catch {\n notify('Failed to move. Please try again.', 'error')\n }\n },\n [updateDocument, clearSelection, notify]\n )\n\n // Mouse + touch sensors, not the pointer sensor: its pointer capture swallows the move events on\n // some setups, so the drop target is never found.\n const sensors = useSensors(\n useSensor(MouseSensor, { activationConstraint: { distance: 6 } }),\n useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } })\n )\n\n // The folder under the pointer; else (between tiles, a folder's edge) the one the dragged tile\n // overlaps most, so a drop near a folder still moves the files.\n const collisionDetection = useCallback<CollisionDetection>((args) => {\n const hits = pointerWithin(args)\n return hits.length > 0 ? hits : rectIntersection(args)\n }, [])\n\n const handleDragStart = useCallback(\n (event: DragStartEvent) => {\n const docId = event.active.data.current?.docId as string | undefined\n if (!docId) return\n setActiveDragId(docId)\n if (!selectedIdsRef.current.includes(docId)) {\n onSelectionChange([docId])\n dragIdsRef.current = [docId]\n } else {\n dragIdsRef.current = selectedIdsRef.current\n }\n },\n [onSelectionChange]\n )\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n setActiveDragId(null)\n const data = event.over?.data.current as { type?: string; path?: string[] } | undefined\n if (data?.type === 'folder' && data.path) {\n const targetFolder = joinFolderPath(data.path)\n // Files already in the target stay put.\n const moving = dragIdsRef.current.filter((id) => {\n const doc = documents.find((d) => d.external_id === id)\n return doc && (doc.folder ?? null) !== targetFolder\n })\n void moveDocs(moving, targetFolder)\n }\n },\n [documents, moveDocs]\n )\n\n // ---- Drop to upload (OS files)\n\n const handleNativeDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!canUpload) return\n if (e.dataTransfer.types.includes('Files')) {\n e.preventDefault()\n e.dataTransfer.dropEffect = 'copy'\n }\n },\n [canUpload]\n )\n\n const handleNativeDragEnter = useCallback(\n (e: React.DragEvent) => {\n if (!canUpload || !e.dataTransfer.types.includes('Files')) return\n fileDragDepth.current += 1\n setIsFileDragOver(true)\n },\n [canUpload]\n )\n\n const handleNativeDragLeave = useCallback(() => {\n fileDragDepth.current = Math.max(0, fileDragDepth.current - 1)\n if (fileDragDepth.current === 0) setIsFileDragOver(false)\n }, [])\n\n const handleNativeDrop = useCallback(\n (e: React.DragEvent) => {\n fileDragDepth.current = 0\n setIsFileDragOver(false)\n if (!canUpload) return\n const dropped = Array.from(e.dataTransfer.files ?? [])\n if (dropped.length > 0) {\n e.preventDefault()\n onUploadFiles(dropped, joinFolderPath(currentPath))\n }\n },\n [canUpload, currentPath, onUploadFiles]\n )\n\n // ---- Render\n\n const activeDoc = activeDragId ? documents.find((d) => d.external_id === activeDragId) : null\n const dragCount = dragIdsRef.current.length || 1\n\n if (isWholeWorkspaceEmpty) return <>{emptyWorkspace}</>\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={() => setActiveDragId(null)}\n >\n <ExplorerFrame data-testid=\"documents-explorer\">\n <ExplorerStage>\n <ExplorerScroller\n ref={scrollRef}\n onClick={handleBackgroundClick}\n onPointerDown={handleScrollPointerDown}\n onDragEnter={handleNativeDragEnter}\n onDragOver={handleNativeDragOver}\n onDragLeave={handleNativeDragLeave}\n onDrop={handleNativeDrop}\n data-testid=\"explorer-scroll\"\n >\n {isLoading && documents.length === 0 ? (\n <ExplorerLoadingTiles />\n ) : entries.length === 0 ? (\n <ExplorerEmpty\n title={isSearching ? `No files match \"${search.trim()}\"` : 'This folder is empty'}\n description={\n isSearching\n ? 'Try a different search.'\n : canUpload\n ? 'Drop files here or use Upload to add documents.'\n : 'No documents here yet.'\n }\n />\n ) : containerWidth === 0 ? (\n // Not measured yet: rendering now would flash one stretched column.\n <ExplorerLoadingTiles />\n ) : (\n <div\n style={{\n height: rowVirtualizer.getTotalSize(),\n position: 'relative',\n width: '100%',\n }}\n >\n {virtualRows.map((virtualRow) => {\n const start = virtualRow.index * columnCount\n const rowEntries = entries.slice(start, start + columnCount)\n return (\n <div\n key={virtualRow.key}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: tileHeight,\n transform: `translateY(${virtualRow.start}px)`,\n display: 'grid',\n gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,\n columnGap: GRID_GAP,\n }}\n >\n {rowEntries.map((entry) => {\n if (entry.kind === 'folder') {\n const key = entry.path.join('/')\n return (\n <FolderTile\n key={`folder:${key}`}\n folder={entry}\n density={density}\n editing={editingFolderPath === key}\n selected={folderSelection.get(key)?.all}\n partiallySelected={folderSelection.get(key)?.some}\n documents={folderDocs.get(key) ?? NO_DOCUMENTS}\n onOpen={openFolder}\n onToggleSelect={handleToggleFolder}\n onCommitName={commitFolderName}\n onCancelName={cancelFolderName}\n onStartRename={canUpload ? startFolderRename : undefined}\n onDownload={handleFolderDownload}\n onMove={canUpload ? handleFolderMove : undefined}\n onDelete={canDeleteFolder(entry) ? handleFolderDelete : undefined}\n actions={hostActions}\n />\n )\n }\n const doc = entry.doc\n return (\n <FileTile\n key={doc.external_id}\n doc={doc}\n density={density}\n selected={selectedSet.has(doc.external_id)}\n dragging={activeDragId === doc.external_id}\n dndActive={activeDragId !== null}\n renaming={renamingId === doc.external_id}\n canDelete={canDeleteDocument(doc, userId, role)}\n thumbnailUrl={thumbnailsById.get(doc.external_id)}\n modifiedBy={userById.get(\n doc.updated_by_ext_id ?? doc.created_by_ext_id\n )}\n tagNameById={tagNameById}\n onSelect={handleSelect}\n onToggle={handleToggle}\n onOpen={handleOpenFile}\n onReview={handleOpenInReview}\n onStartRename={startRename}\n onCommitRename={commitRename}\n onCancelRename={cancelRename}\n onDownload={handleDownload}\n onMove={canUpload ? handleMove : undefined}\n onDelete={handleDelete}\n actions={hostActions}\n />\n )\n })}\n </div>\n )\n })}\n </div>\n )}\n </ExplorerScroller>\n\n {/* The marquee: always mounted, drawn by mutating its style during a drag. */}\n <ExplorerMarquee ref={marqueeOverlayRef} data-testid=\"explorer-marquee\" />\n\n {isFileDragOver && (\n <ExplorerDropOverlay\n label={`Drop to upload${\n currentPath.length > 0 ? ` to \"${currentPath[currentPath.length - 1]}\"` : ''\n }`}\n />\n )}\n </ExplorerStage>\n </ExplorerFrame>\n\n <DragOverlay dropAnimation={null}>\n {activeDoc ? <DragPreview doc={activeDoc} count={dragCount} /> : null}\n </DragOverlay>\n </DndContext>\n )\n})\n\n/** The preview under the cursor while files are dragged. */\nfunction DragPreview({ doc, count }: { doc: FileTileDocument; count: number }) {\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type, folder: doc.folder })\n return (\n <ExplorerDragPreview\n icon={<Icon size={20} />}\n title={getDocumentTitle(doc, doc.file_name ?? 'Untitled')}\n count={count}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ConnectedFilesExplorer"]
|
|
7
7
|
}
|
|
@@ -226,7 +226,7 @@ const FileTile = memo(function FileTile2({
|
|
|
226
226
|
const isOffline = useOfflineDocumentIds().has(doc.external_id);
|
|
227
227
|
const isViewing = useOpenViewerDocumentId() === doc.external_id;
|
|
228
228
|
const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(status);
|
|
229
|
-
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
229
|
+
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type, folder: doc.folder });
|
|
230
230
|
const { data: mailPolicy } = useMailPolicy();
|
|
231
231
|
const shareAsEmail = async () => {
|
|
232
232
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/connection/files/explorer/FileTiles.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The explorer's one tile binding. The presentation (`ExplorerFileTile`, `ExplorerFolderTile`,\n * `ExplorerFileTooltip`) is in `files/`; this binds it to the session: @dnd-kit draggable and\n * droppable, the document's live processing status, the copies kept offline, the open viewer, the\n * document pill, the mail handoff and the member / label lookups. `FileTile` is a draggable\n * document, `FolderTile` a droppable folder (separate components so the dnd hooks always run).\n */\n\nimport { memo, useMemo, type ReactNode } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport {\n AlertTriangle,\n BookOpen,\n CheckCircle,\n Download,\n FileX,\n FolderInput,\n Mail,\n MessagesSquare,\n Pencil,\n Play,\n SkipForward,\n Sparkles,\n SquarePen,\n Trash2,\n} from 'lucide-react'\nimport {\n FINISHED_DOCUMENT_STATUSES,\n IN_FLIGHT_DOCUMENT_STATUSES,\n resolveDocumentStatus,\n useMailPolicy,\n useOfflineDocumentIds,\n useOpenViewerDocumentId,\n useProcessingTask,\n useProcessingTasks,\n type DocumentHostActions,\n type DocumentStartItem,\n type WorkspaceDocument,\n} from '@arbidocs/react'\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n DocumentEntity,\n VisibilityIcon,\n cn,\n formatFriendlyDate,\n getEntityLabel,\n getDocumentTitle,\n getFileTypeIcon,\n getUserAvatarColor,\n getUserDisplayName,\n getUserInitials,\n getDocumentSubject,\n} from '@arbidocs/react/ui'\nimport {\n ExplorerFileTile,\n ExplorerFileTooltip,\n ExplorerFolderTile,\n type ExplorerDensity,\n type ExplorerMenuItem,\n} from '../../../files/ExplorerTile'\nimport { StatusPill, type StatusTone } from '../../../files/StatusPill'\nimport { FailedStageIcon } from '../../../files/FailedStageIcon'\nimport { visibilityAudience } from '../../../files/visibility'\nimport {\n FolderProviderIcon,\n formatFolderSegment,\n hasFolderProviderIcon,\n type ExplorerFolder,\n} from '../../../files/folders'\nimport { useBlocksEnvironment } from '../../../provider/environment'\nimport { DocumentSyncGlyph } from '../DocumentSyncGlyph'\n\nexport type { ExplorerDensity }\n\n/** A workspace member as a tile shows them (avatar and name). */\nexport interface FileTileUser {\n external_id: string\n given_name: string\n family_name?: string | null\n email: string\n picture?: string | null\n}\n\n/** A document row as the tiles read it (the session's rows carry these). */\nexport type FileTileDocument = WorkspaceDocument & {\n failed_stage?: string | null\n}\n\nconst NO_ACTIONS: DocumentHostActions = {}\n\n// In-flight processing statuses (the table's status cell has the same) and the terminal ones.\nconst ACTIVE_STATUSES = IN_FLIGHT_DOCUMENT_STATUSES\nconst TERMINAL_STATUSES = FINISHED_DOCUMENT_STATUSES\nconst STATUS_LABEL: Record<string, string> = {\n uploading: 'Uploading',\n queued: 'Queued',\n parsing: 'Parsing',\n encrypting: 'Encrypting',\n indexing: 'Indexing',\n analysing: 'Analysing',\n}\n\n/** Whether a status is still being worked on. */\nexport function isActiveDocumentStatus(status: string): boolean {\n return ACTIVE_STATUSES.has(status.toLowerCase())\n}\n\n/**\n * The document's effective status: the newer of its row and its live processing\n * (`resolveDocumentStatus`). Reads only this document's live processing, so a tile re-renders only\n * when its own status changes.\n */\nfunction useDocStatus(doc: FileTileDocument): string {\n return resolveDocumentStatus(doc, useProcessingTask(doc.external_id))\n}\n\n/** The finished-state marker in the tile's lower-right corner (in-flight files use the overlay). */\nfunction TileStatusBadge({ doc, status }: { doc: FileTileDocument; status: string }): ReactNode {\n let tone: StatusTone = 'neutral'\n let icon: ReactNode = null\n let title = ''\n switch (status) {\n case 'completed':\n tone = 'success'\n icon = <CheckCircle className=\"size-4 text-green-text\" strokeWidth={2.75} />\n title = 'Ready'\n break\n case 'failed':\n tone = 'danger'\n icon = (\n <FailedStageIcon\n stage={doc.failed_stage ?? null}\n errorMessage={doc.error_message}\n className=\"size-4 text-red-text\"\n />\n )\n title = 'Failed'\n break\n case 'skipped':\n icon = <SkipForward className=\"size-4 text-muted-foreground\" strokeWidth={2.75} />\n title = 'Skipped'\n break\n case 'empty':\n tone = 'warning'\n icon = <FileX className=\"size-4 text-yellow-text\" strokeWidth={2.75} />\n title = 'Empty \u2014 no extractable content'\n break\n case 'low-content':\n tone = 'warning'\n icon = <AlertTriangle className=\"size-4 text-yellow-text\" strokeWidth={2.75} />\n title = 'Low content \u2014 minimal extractable content'\n break\n default:\n return null\n }\n return (\n <StatusPill\n tone={tone}\n icon={icon}\n title={title}\n testId={`explorer-file-status-${doc.external_id}`}\n />\n )\n}\n\n/**\n * Who can see the file, printed on the tile itself: a bare \"Shared\" does not say with whom, and a\n * hover title never reaches touch and keyboard users. The label is the audience's short name so it\n * fits beside the status check on narrow tiles; the title keeps the full sentence.\n */\nfunction TileVisibilityBadge({ doc }: { doc: FileTileDocument }): ReactNode {\n const shared = !!doc.shared\n return (\n <StatusPill\n icon={<VisibilityIcon isShared={shared} className=\"size-3.5\" aria-hidden />}\n label={shared ? getEntityLabel('WORKSPACE') : 'Only you'}\n title={visibilityAudience(shared)}\n testId={`explorer-file-visibility-${doc.external_id}`}\n />\n )\n}\n\n/** A tiny avatar (initials, or the picture when set) for the \"last modified by\" line. */\nfunction MiniUserAvatar({ user }: { user: FileTileUser }) {\n return (\n <Avatar className=\"h-4 w-4 border border-white\">\n {user.picture && <AvatarImage src={user.picture} alt={getUserDisplayName(user)} />}\n <AvatarFallback\n className={cn(\n 'text-xs font-semibold leading-none text-white',\n getUserAvatarColor(user.external_id)\n )}\n >\n {getUserInitials(user)}\n </AvatarFallback>\n </Avatar>\n )\n}\n\n/** The hover card of a document: the same in the explorer tiles and the table's name cell. */\nexport function FileTooltipContent({\n doc,\n modifiedBy,\n tagNameById,\n}: {\n doc: FileTileDocument\n modifiedBy?: FileTileUser\n tagNameById: ReadonlyMap<string, string>\n}) {\n const labels = (doc.doctags ?? [])\n .map((dt) => tagNameById.get(dt.tag_ext_id))\n .filter((name): name is string => !!name)\n return (\n <ExplorerFileTooltip\n title={getDocumentTitle(doc, doc.file_name ?? '')}\n summary={getDocumentSubject(doc)}\n modifiedLabel={doc.updated_at ? formatFriendlyDate(doc.updated_at, false) : null}\n modifiedByAvatar={modifiedBy && <MiniUserAvatar user={modifiedBy} />}\n shared={!!doc.shared}\n visibilityIcon={<VisibilityIcon isShared={!!doc.shared} className=\"h-3 w-3\" />}\n labels={labels}\n uiLabels={{ shared: visibilityAudience(true), private: visibilityAudience(false) }}\n />\n )\n}\n\n/** The \"Start\u2026\" submenu: one entry per thing the host can start on the file or folder. */\nexport function startMenuItem(items: readonly DocumentStartItem[]): ExplorerMenuItem[] {\n if (items.length === 0) return []\n return [\n {\n id: 'start',\n label: 'Start\u2026',\n icon: Sparkles,\n testId: 'explorer-start-menu',\n onSelect: () => {},\n submenu: items.map((item) => ({\n id: item.id,\n label: item.title,\n icon: Play,\n onSelect: item.run,\n testId: `explorer-start-${item.id}`,\n })),\n },\n ]\n}\n\ninterface FileTileProps {\n doc: FileTileDocument\n density: ExplorerDensity\n selected: boolean\n /** Part of an in-flight drag (dimmed). */\n dragging: boolean\n /** Any tile is being dragged: no hover card, so it cannot swallow the moves dnd-kit tracks. */\n dndActive: boolean\n /** Being renamed inline. */\n renaming: boolean\n /** The viewer may delete this document. */\n canDelete: boolean\n /** The first-page thumbnail (absent: the file-type icon). */\n thumbnailUrl?: string\n /** Who last changed the document (the hover card's avatar line). */\n modifiedBy?: FileTileUser\n /** Label id \u2192 name, for the document's labels on the hover card. */\n tagNameById: ReadonlyMap<string, string>\n onSelect: (doc: FileTileDocument, e: React.MouseEvent) => void\n onToggle: (doc: FileTileDocument, e: React.MouseEvent) => void\n onOpen: (doc: FileTileDocument) => void\n /** Open the document in the review view. Absent: not offered. */\n onReview?: (doc: FileTileDocument) => void\n onStartRename: (doc: FileTileDocument) => void\n onCommitRename: (doc: FileTileDocument, name: string) => void\n onCancelRename: () => void\n onDownload: (doc: FileTileDocument) => void\n onMove?: (doc: FileTileDocument) => void\n onDelete: (doc: FileTileDocument) => void\n /** The host's actions on documents (read once by the view). */\n actions?: DocumentHostActions\n}\n\nexport const FileTile = memo(function FileTile({\n doc,\n density,\n selected,\n dragging,\n dndActive,\n renaming,\n canDelete,\n thumbnailUrl,\n modifiedBy,\n tagNameById,\n onSelect,\n onToggle,\n onOpen,\n onReview,\n onStartRename,\n onCommitRename,\n onCancelRename,\n onDownload,\n onMove,\n onDelete,\n actions = NO_ACTIONS,\n}: FileTileProps) {\n const { attributes, listeners, setNodeRef } = useDraggable({\n id: `doc:${doc.external_id}`,\n data: { type: 'doc', docId: doc.external_id },\n })\n const { notify } = useBlocksEnvironment()\n const { startItemsForFile, openDocumentChat, emailDocument } = actions\n const status = useDocStatus(doc)\n const isProcessing = ACTIVE_STATUSES.has(status)\n const isOffline = useOfflineDocumentIds().has(doc.external_id)\n const isViewing = useOpenViewerDocumentId() === doc.external_id\n const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(status)\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type })\n const { data: mailPolicy } = useMailPolicy()\n\n const shareAsEmail = async () => {\n try {\n await emailDocument?.(doc)\n } catch (error) {\n notify(error instanceof Error ? error.message : 'Could not attach document', 'error')\n }\n }\n const startItems = startItemsForFile?.(doc)\n const menuItems: ExplorerMenuItem[] = [\n { id: 'open', label: 'Open', icon: SquarePen, onSelect: () => onOpen(doc) },\n ...(onReview\n ? [{ id: 'review', label: 'Open in Review', icon: BookOpen, onSelect: () => onReview(doc) }]\n : []),\n ...(openDocumentChat\n ? [\n {\n id: 'chat',\n label: 'Document chat',\n icon: MessagesSquare,\n onSelect: () => openDocumentChat(doc.external_id),\n },\n ]\n : []),\n ...startMenuItem(startItems ?? []),\n {\n id: 'rename',\n label: 'Rename',\n icon: Pencil,\n onSelect: () => onStartRename(doc),\n separatorBefore: true,\n },\n { id: 'download', label: 'Download', icon: Download, onSelect: () => onDownload(doc) },\n ...(emailDocument && mailPolicy?.enabled\n ? [\n {\n id: 'email',\n label: 'Send as email attachment',\n icon: Mail,\n onSelect: () => {\n void shareAsEmail()\n },\n },\n ]\n : []),\n ...(onMove\n ? [{ id: 'move', label: 'Move to\u2026', icon: FolderInput, onSelect: () => onMove(doc) }]\n : []),\n ...(canDelete\n ? [\n {\n id: 'delete',\n label: 'Delete',\n icon: Trash2,\n onSelect: () => onDelete(doc),\n destructive: true,\n separatorBefore: true,\n },\n ]\n : []),\n ]\n\n // No hover card while renaming (it would cover the input) or while anything is dragged: the\n // tooltip trigger merges pointer handlers onto the draggable node and swallows the move events\n // dnd-kit needs to find the drop target.\n const tooltip =\n renaming || dndActive ? undefined : (\n <FileTooltipContent doc={doc} modifiedBy={modifiedBy} tagNameById={tagNameById} />\n )\n\n return (\n <ExplorerFileTile\n id={doc.external_id}\n title={getDocumentTitle(doc, doc.file_name ?? '')}\n density={density}\n selected={selected}\n dragging={dragging}\n renaming={renaming}\n thumbnailUrl={thumbnailUrl}\n renderFileIcon={(size) => <Icon size={size} className=\"drop-shadow-sm\" />}\n progress={\n isProcessing\n ? { label: STATUS_LABEL[status] ?? status, queued: status === 'queued' }\n : undefined\n }\n statusMarker={\n <div className=\"flex items-center gap-1\">\n <TileVisibilityBadge doc={doc} />\n {showStatusMarker && <TileStatusBadge doc={doc} status={status} />}\n </div>\n }\n offlineMarker={\n isOffline ? (\n <DocumentSyncGlyph docExtId={doc.external_id} size={24} bgClassName=\"bg-primary\" />\n ) : undefined\n }\n entity={\n <DocumentEntity\n doc={doc}\n labelMaxWidth=\"max-w-full\"\n noClamp\n // The full name over two lines: \"(redacted)\" / \"(annotated)\" sit at the end, so a one-line\n // ellipsis hides exactly what tells a frozen copy from its original.\n labelClassName=\"whitespace-normal line-clamp-2 break-words\"\n viewing={isViewing}\n tooltipContent={\n <FileTooltipContent doc={doc} modifiedBy={modifiedBy} tagNameById={tagNameById} />\n }\n className={cn(\n 'w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm',\n density === 'list' ? 'text-xs' : undefined\n )}\n onClick={(e) => {\n e.stopPropagation()\n onOpen(doc)\n }}\n />\n }\n tooltip={tooltip}\n menuItems={menuItems}\n rootRef={setNodeRef}\n rootProps={{ ...listeners, ...attributes }}\n onOpen={() => onOpen(doc)}\n onSelect={(e) => onSelect(doc, e)}\n onToggle={(e) => onToggle(doc, e)}\n onCommitRename={(name) => onCommitRename(doc, name)}\n onCancelRename={onCancelRename}\n />\n )\n})\n\ninterface FolderTileProps {\n folder: ExplorerFolder\n density: ExplorerDensity\n /** Being renamed inline. */\n editing?: boolean\n /** Every document beneath the folder is selected. */\n selected?: boolean\n /** Some (not all) documents beneath the folder are selected. */\n partiallySelected?: boolean\n /** Every document beneath the folder (its count of files still processing). */\n documents: readonly FileTileDocument[]\n onOpen: (folder: ExplorerFolder) => void\n /** Toggle the whole folder (all its documents). */\n onToggleSelect?: (folder: ExplorerFolder, e: React.MouseEvent) => void\n onCommitName?: (folder: ExplorerFolder, name: string) => void\n onCancelName?: () => void\n onStartRename?: (folder: ExplorerFolder) => void\n onDownload?: (folder: ExplorerFolder) => void\n onMove?: (folder: ExplorerFolder) => void\n onDelete?: (folder: ExplorerFolder) => void\n /** The host's actions on documents (read once by the view). */\n actions?: DocumentHostActions\n}\n\nexport const FolderTile = memo(function FolderTile({\n folder,\n density,\n editing,\n selected,\n partiallySelected,\n documents,\n onOpen,\n onToggleSelect,\n onCommitName,\n onCancelName,\n onStartRename,\n onDownload,\n onMove,\n onDelete,\n actions = NO_ACTIONS,\n}: FolderTileProps) {\n const { setNodeRef, isOver } = useDroppable({\n id: `folder:${folder.path.join('/')}`,\n data: { type: 'folder', path: folder.path },\n })\n const { startItemsForFolder } = actions\n // Live processing is read here, not by the explorer, so an upload burst re-renders folder tiles\n // only.\n const tasks = useProcessingTasks()\n const processingCount = useMemo(\n () =>\n documents.filter((doc) =>\n isActiveDocumentStatus(resolveDocumentStatus(doc, tasks[doc.external_id]))\n ).length,\n [documents, tasks]\n )\n const isEmpty = folder.count === 0\n const iconSize = density === 'list' ? 34 : 48\n\n // A folder is not \"opened in review\"; an item is left out when its handler is absent (an empty\n // folder has nothing to start, download or move).\n const menuItems: ExplorerMenuItem[] = [\n ...(onStartRename\n ? [{ id: 'rename', label: 'Rename', icon: Pencil, onSelect: () => onStartRename(folder) }]\n : []),\n ...(!isEmpty ? startMenuItem(startItemsForFolder?.(folder.path.join('/')) ?? []) : []),\n ...(onDownload && !isEmpty\n ? [{ id: 'download', label: 'Download', icon: Download, onSelect: () => onDownload(folder) }]\n : []),\n ...(onMove && !isEmpty\n ? [{ id: 'move', label: 'Move to\u2026', icon: FolderInput, onSelect: () => onMove(folder) }]\n : []),\n ...(onDelete\n ? [\n {\n id: 'delete',\n label: 'Delete',\n icon: Trash2,\n onSelect: () => onDelete(folder),\n destructive: true,\n separatorBefore: true,\n },\n ]\n : []),\n ]\n\n // A provider root shows shortened (the account; the brand mark carries the provider). Rename and\n // the tooltip keep the full stored name.\n const displayName = folder.path.length === 1 ? formatFolderSegment(folder.name) : folder.name\n const providerIcon =\n folder.path.length === 1 && hasFolderProviderIcon(folder.name) ? (\n <span\n className=\"flex items-center justify-center drop-shadow-sm\"\n style={{ width: iconSize, height: iconSize }}\n >\n <FolderProviderIcon folderPath={folder.name} className=\"h-full w-full\" />\n </span>\n ) : undefined\n\n return (\n <ExplorerFolderTile\n name={folder.name}\n displayName={displayName === '' ? null : displayName}\n path={folder.path}\n count={folder.count}\n density={density}\n editing={editing}\n selected={selected}\n partiallySelected={partiallySelected}\n processingCount={processingCount}\n isOver={isOver}\n icon={providerIcon}\n menuItems={menuItems}\n rootRef={setNodeRef}\n onOpen={() => onOpen(folder)}\n onToggleSelect={onToggleSelect ? (e) => onToggleSelect(folder, e) : undefined}\n onCommitName={(name) => onCommitName?.(folder, name)}\n onCancelName={onCancelName}\n />\n )\n})\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * The explorer's one tile binding. The presentation (`ExplorerFileTile`, `ExplorerFolderTile`,\n * `ExplorerFileTooltip`) is in `files/`; this binds it to the session: @dnd-kit draggable and\n * droppable, the document's live processing status, the copies kept offline, the open viewer, the\n * document pill, the mail handoff and the member / label lookups. `FileTile` is a draggable\n * document, `FolderTile` a droppable folder (separate components so the dnd hooks always run).\n */\n\nimport { memo, useMemo, type ReactNode } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport {\n AlertTriangle,\n BookOpen,\n CheckCircle,\n Download,\n FileX,\n FolderInput,\n Mail,\n MessagesSquare,\n Pencil,\n Play,\n SkipForward,\n Sparkles,\n SquarePen,\n Trash2,\n} from 'lucide-react'\nimport {\n FINISHED_DOCUMENT_STATUSES,\n IN_FLIGHT_DOCUMENT_STATUSES,\n resolveDocumentStatus,\n useMailPolicy,\n useOfflineDocumentIds,\n useOpenViewerDocumentId,\n useProcessingTask,\n useProcessingTasks,\n type DocumentHostActions,\n type DocumentStartItem,\n type WorkspaceDocument,\n} from '@arbidocs/react'\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n DocumentEntity,\n VisibilityIcon,\n cn,\n formatFriendlyDate,\n getEntityLabel,\n getDocumentTitle,\n getFileTypeIcon,\n getUserAvatarColor,\n getUserDisplayName,\n getUserInitials,\n getDocumentSubject,\n} from '@arbidocs/react/ui'\nimport {\n ExplorerFileTile,\n ExplorerFileTooltip,\n ExplorerFolderTile,\n type ExplorerDensity,\n type ExplorerMenuItem,\n} from '../../../files/ExplorerTile'\nimport { StatusPill, type StatusTone } from '../../../files/StatusPill'\nimport { FailedStageIcon } from '../../../files/FailedStageIcon'\nimport { visibilityAudience } from '../../../files/visibility'\nimport {\n FolderProviderIcon,\n formatFolderSegment,\n hasFolderProviderIcon,\n type ExplorerFolder,\n} from '../../../files/folders'\nimport { useBlocksEnvironment } from '../../../provider/environment'\nimport { DocumentSyncGlyph } from '../DocumentSyncGlyph'\n\nexport type { ExplorerDensity }\n\n/** A workspace member as a tile shows them (avatar and name). */\nexport interface FileTileUser {\n external_id: string\n given_name: string\n family_name?: string | null\n email: string\n picture?: string | null\n}\n\n/** A document row as the tiles read it (the session's rows carry these). */\nexport type FileTileDocument = WorkspaceDocument & {\n failed_stage?: string | null\n}\n\nconst NO_ACTIONS: DocumentHostActions = {}\n\n// In-flight processing statuses (the table's status cell has the same) and the terminal ones.\nconst ACTIVE_STATUSES = IN_FLIGHT_DOCUMENT_STATUSES\nconst TERMINAL_STATUSES = FINISHED_DOCUMENT_STATUSES\nconst STATUS_LABEL: Record<string, string> = {\n uploading: 'Uploading',\n queued: 'Queued',\n parsing: 'Parsing',\n encrypting: 'Encrypting',\n indexing: 'Indexing',\n analysing: 'Analysing',\n}\n\n/** Whether a status is still being worked on. */\nexport function isActiveDocumentStatus(status: string): boolean {\n return ACTIVE_STATUSES.has(status.toLowerCase())\n}\n\n/**\n * The document's effective status: the newer of its row and its live processing\n * (`resolveDocumentStatus`). Reads only this document's live processing, so a tile re-renders only\n * when its own status changes.\n */\nfunction useDocStatus(doc: FileTileDocument): string {\n return resolveDocumentStatus(doc, useProcessingTask(doc.external_id))\n}\n\n/** The finished-state marker in the tile's lower-right corner (in-flight files use the overlay). */\nfunction TileStatusBadge({ doc, status }: { doc: FileTileDocument; status: string }): ReactNode {\n let tone: StatusTone = 'neutral'\n let icon: ReactNode = null\n let title = ''\n switch (status) {\n case 'completed':\n tone = 'success'\n icon = <CheckCircle className=\"size-4 text-green-text\" strokeWidth={2.75} />\n title = 'Ready'\n break\n case 'failed':\n tone = 'danger'\n icon = (\n <FailedStageIcon\n stage={doc.failed_stage ?? null}\n errorMessage={doc.error_message}\n className=\"size-4 text-red-text\"\n />\n )\n title = 'Failed'\n break\n case 'skipped':\n icon = <SkipForward className=\"size-4 text-muted-foreground\" strokeWidth={2.75} />\n title = 'Skipped'\n break\n case 'empty':\n tone = 'warning'\n icon = <FileX className=\"size-4 text-yellow-text\" strokeWidth={2.75} />\n title = 'Empty \u2014 no extractable content'\n break\n case 'low-content':\n tone = 'warning'\n icon = <AlertTriangle className=\"size-4 text-yellow-text\" strokeWidth={2.75} />\n title = 'Low content \u2014 minimal extractable content'\n break\n default:\n return null\n }\n return (\n <StatusPill\n tone={tone}\n icon={icon}\n title={title}\n testId={`explorer-file-status-${doc.external_id}`}\n />\n )\n}\n\n/**\n * Who can see the file, printed on the tile itself: a bare \"Shared\" does not say with whom, and a\n * hover title never reaches touch and keyboard users. The label is the audience's short name so it\n * fits beside the status check on narrow tiles; the title keeps the full sentence.\n */\nfunction TileVisibilityBadge({ doc }: { doc: FileTileDocument }): ReactNode {\n const shared = !!doc.shared\n return (\n <StatusPill\n icon={<VisibilityIcon isShared={shared} className=\"size-3.5\" aria-hidden />}\n label={shared ? getEntityLabel('WORKSPACE') : 'Only you'}\n title={visibilityAudience(shared)}\n testId={`explorer-file-visibility-${doc.external_id}`}\n />\n )\n}\n\n/** A tiny avatar (initials, or the picture when set) for the \"last modified by\" line. */\nfunction MiniUserAvatar({ user }: { user: FileTileUser }) {\n return (\n <Avatar className=\"h-4 w-4 border border-white\">\n {user.picture && <AvatarImage src={user.picture} alt={getUserDisplayName(user)} />}\n <AvatarFallback\n className={cn(\n 'text-xs font-semibold leading-none text-white',\n getUserAvatarColor(user.external_id)\n )}\n >\n {getUserInitials(user)}\n </AvatarFallback>\n </Avatar>\n )\n}\n\n/** The hover card of a document: the same in the explorer tiles and the table's name cell. */\nexport function FileTooltipContent({\n doc,\n modifiedBy,\n tagNameById,\n}: {\n doc: FileTileDocument\n modifiedBy?: FileTileUser\n tagNameById: ReadonlyMap<string, string>\n}) {\n const labels = (doc.doctags ?? [])\n .map((dt) => tagNameById.get(dt.tag_ext_id))\n .filter((name): name is string => !!name)\n return (\n <ExplorerFileTooltip\n title={getDocumentTitle(doc, doc.file_name ?? '')}\n summary={getDocumentSubject(doc)}\n modifiedLabel={doc.updated_at ? formatFriendlyDate(doc.updated_at, false) : null}\n modifiedByAvatar={modifiedBy && <MiniUserAvatar user={modifiedBy} />}\n shared={!!doc.shared}\n visibilityIcon={<VisibilityIcon isShared={!!doc.shared} className=\"h-3 w-3\" />}\n labels={labels}\n uiLabels={{ shared: visibilityAudience(true), private: visibilityAudience(false) }}\n />\n )\n}\n\n/** The \"Start\u2026\" submenu: one entry per thing the host can start on the file or folder. */\nexport function startMenuItem(items: readonly DocumentStartItem[]): ExplorerMenuItem[] {\n if (items.length === 0) return []\n return [\n {\n id: 'start',\n label: 'Start\u2026',\n icon: Sparkles,\n testId: 'explorer-start-menu',\n onSelect: () => {},\n submenu: items.map((item) => ({\n id: item.id,\n label: item.title,\n icon: Play,\n onSelect: item.run,\n testId: `explorer-start-${item.id}`,\n })),\n },\n ]\n}\n\ninterface FileTileProps {\n doc: FileTileDocument\n density: ExplorerDensity\n selected: boolean\n /** Part of an in-flight drag (dimmed). */\n dragging: boolean\n /** Any tile is being dragged: no hover card, so it cannot swallow the moves dnd-kit tracks. */\n dndActive: boolean\n /** Being renamed inline. */\n renaming: boolean\n /** The viewer may delete this document. */\n canDelete: boolean\n /** The first-page thumbnail (absent: the file-type icon). */\n thumbnailUrl?: string\n /** Who last changed the document (the hover card's avatar line). */\n modifiedBy?: FileTileUser\n /** Label id \u2192 name, for the document's labels on the hover card. */\n tagNameById: ReadonlyMap<string, string>\n onSelect: (doc: FileTileDocument, e: React.MouseEvent) => void\n onToggle: (doc: FileTileDocument, e: React.MouseEvent) => void\n onOpen: (doc: FileTileDocument) => void\n /** Open the document in the review view. Absent: not offered. */\n onReview?: (doc: FileTileDocument) => void\n onStartRename: (doc: FileTileDocument) => void\n onCommitRename: (doc: FileTileDocument, name: string) => void\n onCancelRename: () => void\n onDownload: (doc: FileTileDocument) => void\n onMove?: (doc: FileTileDocument) => void\n onDelete: (doc: FileTileDocument) => void\n /** The host's actions on documents (read once by the view). */\n actions?: DocumentHostActions\n}\n\nexport const FileTile = memo(function FileTile({\n doc,\n density,\n selected,\n dragging,\n dndActive,\n renaming,\n canDelete,\n thumbnailUrl,\n modifiedBy,\n tagNameById,\n onSelect,\n onToggle,\n onOpen,\n onReview,\n onStartRename,\n onCommitRename,\n onCancelRename,\n onDownload,\n onMove,\n onDelete,\n actions = NO_ACTIONS,\n}: FileTileProps) {\n const { attributes, listeners, setNodeRef } = useDraggable({\n id: `doc:${doc.external_id}`,\n data: { type: 'doc', docId: doc.external_id },\n })\n const { notify } = useBlocksEnvironment()\n const { startItemsForFile, openDocumentChat, emailDocument } = actions\n const status = useDocStatus(doc)\n const isProcessing = ACTIVE_STATUSES.has(status)\n const isOffline = useOfflineDocumentIds().has(doc.external_id)\n const isViewing = useOpenViewerDocumentId() === doc.external_id\n const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(status)\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type, folder: doc.folder })\n const { data: mailPolicy } = useMailPolicy()\n\n const shareAsEmail = async () => {\n try {\n await emailDocument?.(doc)\n } catch (error) {\n notify(error instanceof Error ? error.message : 'Could not attach document', 'error')\n }\n }\n const startItems = startItemsForFile?.(doc)\n const menuItems: ExplorerMenuItem[] = [\n { id: 'open', label: 'Open', icon: SquarePen, onSelect: () => onOpen(doc) },\n ...(onReview\n ? [{ id: 'review', label: 'Open in Review', icon: BookOpen, onSelect: () => onReview(doc) }]\n : []),\n ...(openDocumentChat\n ? [\n {\n id: 'chat',\n label: 'Document chat',\n icon: MessagesSquare,\n onSelect: () => openDocumentChat(doc.external_id),\n },\n ]\n : []),\n ...startMenuItem(startItems ?? []),\n {\n id: 'rename',\n label: 'Rename',\n icon: Pencil,\n onSelect: () => onStartRename(doc),\n separatorBefore: true,\n },\n { id: 'download', label: 'Download', icon: Download, onSelect: () => onDownload(doc) },\n ...(emailDocument && mailPolicy?.enabled\n ? [\n {\n id: 'email',\n label: 'Send as email attachment',\n icon: Mail,\n onSelect: () => {\n void shareAsEmail()\n },\n },\n ]\n : []),\n ...(onMove\n ? [{ id: 'move', label: 'Move to\u2026', icon: FolderInput, onSelect: () => onMove(doc) }]\n : []),\n ...(canDelete\n ? [\n {\n id: 'delete',\n label: 'Delete',\n icon: Trash2,\n onSelect: () => onDelete(doc),\n destructive: true,\n separatorBefore: true,\n },\n ]\n : []),\n ]\n\n // No hover card while renaming (it would cover the input) or while anything is dragged: the\n // tooltip trigger merges pointer handlers onto the draggable node and swallows the move events\n // dnd-kit needs to find the drop target.\n const tooltip =\n renaming || dndActive ? undefined : (\n <FileTooltipContent doc={doc} modifiedBy={modifiedBy} tagNameById={tagNameById} />\n )\n\n return (\n <ExplorerFileTile\n id={doc.external_id}\n title={getDocumentTitle(doc, doc.file_name ?? '')}\n density={density}\n selected={selected}\n dragging={dragging}\n renaming={renaming}\n thumbnailUrl={thumbnailUrl}\n renderFileIcon={(size) => <Icon size={size} className=\"drop-shadow-sm\" />}\n progress={\n isProcessing\n ? { label: STATUS_LABEL[status] ?? status, queued: status === 'queued' }\n : undefined\n }\n statusMarker={\n <div className=\"flex items-center gap-1\">\n <TileVisibilityBadge doc={doc} />\n {showStatusMarker && <TileStatusBadge doc={doc} status={status} />}\n </div>\n }\n offlineMarker={\n isOffline ? (\n <DocumentSyncGlyph docExtId={doc.external_id} size={24} bgClassName=\"bg-primary\" />\n ) : undefined\n }\n entity={\n <DocumentEntity\n doc={doc}\n labelMaxWidth=\"max-w-full\"\n noClamp\n // The full name over two lines: \"(redacted)\" / \"(annotated)\" sit at the end, so a one-line\n // ellipsis hides exactly what tells a frozen copy from its original.\n labelClassName=\"whitespace-normal line-clamp-2 break-words\"\n viewing={isViewing}\n tooltipContent={\n <FileTooltipContent doc={doc} modifiedBy={modifiedBy} tagNameById={tagNameById} />\n }\n className={cn(\n 'w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm',\n density === 'list' ? 'text-xs' : undefined\n )}\n onClick={(e) => {\n e.stopPropagation()\n onOpen(doc)\n }}\n />\n }\n tooltip={tooltip}\n menuItems={menuItems}\n rootRef={setNodeRef}\n rootProps={{ ...listeners, ...attributes }}\n onOpen={() => onOpen(doc)}\n onSelect={(e) => onSelect(doc, e)}\n onToggle={(e) => onToggle(doc, e)}\n onCommitRename={(name) => onCommitRename(doc, name)}\n onCancelRename={onCancelRename}\n />\n )\n})\n\ninterface FolderTileProps {\n folder: ExplorerFolder\n density: ExplorerDensity\n /** Being renamed inline. */\n editing?: boolean\n /** Every document beneath the folder is selected. */\n selected?: boolean\n /** Some (not all) documents beneath the folder are selected. */\n partiallySelected?: boolean\n /** Every document beneath the folder (its count of files still processing). */\n documents: readonly FileTileDocument[]\n onOpen: (folder: ExplorerFolder) => void\n /** Toggle the whole folder (all its documents). */\n onToggleSelect?: (folder: ExplorerFolder, e: React.MouseEvent) => void\n onCommitName?: (folder: ExplorerFolder, name: string) => void\n onCancelName?: () => void\n onStartRename?: (folder: ExplorerFolder) => void\n onDownload?: (folder: ExplorerFolder) => void\n onMove?: (folder: ExplorerFolder) => void\n onDelete?: (folder: ExplorerFolder) => void\n /** The host's actions on documents (read once by the view). */\n actions?: DocumentHostActions\n}\n\nexport const FolderTile = memo(function FolderTile({\n folder,\n density,\n editing,\n selected,\n partiallySelected,\n documents,\n onOpen,\n onToggleSelect,\n onCommitName,\n onCancelName,\n onStartRename,\n onDownload,\n onMove,\n onDelete,\n actions = NO_ACTIONS,\n}: FolderTileProps) {\n const { setNodeRef, isOver } = useDroppable({\n id: `folder:${folder.path.join('/')}`,\n data: { type: 'folder', path: folder.path },\n })\n const { startItemsForFolder } = actions\n // Live processing is read here, not by the explorer, so an upload burst re-renders folder tiles\n // only.\n const tasks = useProcessingTasks()\n const processingCount = useMemo(\n () =>\n documents.filter((doc) =>\n isActiveDocumentStatus(resolveDocumentStatus(doc, tasks[doc.external_id]))\n ).length,\n [documents, tasks]\n )\n const isEmpty = folder.count === 0\n const iconSize = density === 'list' ? 34 : 48\n\n // A folder is not \"opened in review\"; an item is left out when its handler is absent (an empty\n // folder has nothing to start, download or move).\n const menuItems: ExplorerMenuItem[] = [\n ...(onStartRename\n ? [{ id: 'rename', label: 'Rename', icon: Pencil, onSelect: () => onStartRename(folder) }]\n : []),\n ...(!isEmpty ? startMenuItem(startItemsForFolder?.(folder.path.join('/')) ?? []) : []),\n ...(onDownload && !isEmpty\n ? [{ id: 'download', label: 'Download', icon: Download, onSelect: () => onDownload(folder) }]\n : []),\n ...(onMove && !isEmpty\n ? [{ id: 'move', label: 'Move to\u2026', icon: FolderInput, onSelect: () => onMove(folder) }]\n : []),\n ...(onDelete\n ? [\n {\n id: 'delete',\n label: 'Delete',\n icon: Trash2,\n onSelect: () => onDelete(folder),\n destructive: true,\n separatorBefore: true,\n },\n ]\n : []),\n ]\n\n // A provider root shows shortened (the account; the brand mark carries the provider). Rename and\n // the tooltip keep the full stored name.\n const displayName = folder.path.length === 1 ? formatFolderSegment(folder.name) : folder.name\n const providerIcon =\n folder.path.length === 1 && hasFolderProviderIcon(folder.name) ? (\n <span\n className=\"flex items-center justify-center drop-shadow-sm\"\n style={{ width: iconSize, height: iconSize }}\n >\n <FolderProviderIcon folderPath={folder.name} className=\"h-full w-full\" />\n </span>\n ) : undefined\n\n return (\n <ExplorerFolderTile\n name={folder.name}\n displayName={displayName === '' ? null : displayName}\n path={folder.path}\n count={folder.count}\n density={density}\n editing={editing}\n selected={selected}\n partiallySelected={partiallySelected}\n processingCount={processingCount}\n isOver={isOver}\n icon={providerIcon}\n menuItems={menuItems}\n rootRef={setNodeRef}\n onOpen={() => onOpen(folder)}\n onToggleSelect={onToggleSelect ? (e) => onToggleSelect(folder, e) : undefined}\n onCommitName={(name) => onCommitName?.(folder, name)}\n onCancelName={onCancelName}\n />\n )\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["FileTile", "FolderTile"]
|
|
7
7
|
}
|
|
@@ -39,7 +39,7 @@ const READ_ONLY_FIELDS = {
|
|
|
39
39
|
n_pages: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: doc.n_pages || "N/A" }),
|
|
40
40
|
created_at: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: doc.created_at ? formatFriendlyDate(doc.created_at) : "N/A" }),
|
|
41
41
|
updated_at: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: doc.updated_at ? formatFriendlyDate(doc.updated_at) : "N/A" }),
|
|
42
|
-
file_type: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: friendlyFileType(doc.file_type, doc.file_name) }),
|
|
42
|
+
file_type: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: friendlyFileType(doc.file_type, doc.file_name, doc.folder) }),
|
|
43
43
|
file_size: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", children: doc.file_size ? `${Math.round(doc.file_size / 1024)} KB` : "N/A" }),
|
|
44
44
|
doc_id: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", isMono: true, children: doc.external_id || "N/A" }),
|
|
45
45
|
content_hash: (doc) => /* @__PURE__ */ jsx(FieldValue, { tone: "muted", isMono: true, isTruncated: true, children: doc.content_hash || "N/A" })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/connection/files/fields/documentField.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * One field of a document as the review form shows it (a column of the documents table, one per\n * row): its label, icon and the value, editable where the table's column is. Standard fields,\n * metadata, the folder, related documents, the labels and each annotation (with who last set it).\n */\n\nimport type { ElementType, ReactNode } from 'react'\nimport { isAnnotationTag, isLabelTag, type TagResponse } from '@arbidocs/sdk/browser'\nimport type { DocumentPerson, RelatedDocs, WorkspaceDocument } from '@arbidocs/react'\nimport {\n DebouncedInput,\n formatFriendlyDate,\n friendlyFileType,\n Textarea,\n formatDocDate,\n getDocumentDate,\n getDocumentTitle,\n} from '@arbidocs/react/ui'\nimport {\n FieldFolderSelect,\n FieldFolderValue,\n FieldNativeSelect,\n FieldValue,\n FieldWithAttribution,\n} from '../../../files/FieldParts'\nimport { DocumentUser } from './DocumentUser'\nimport {\n DocTagAttribution,\n FolderPicker,\n LabelsCombobox,\n RelatedDocuments,\n} from './DocumentFieldParts'\n\ntype DocTag = NonNullable<WorkspaceDocument['doctags']>[number]\nexport type DocTagCitations = NonNullable<DocTag['citations']> | null\n\n/** A field as the form lays it out. */\nexport interface DocumentFieldContent {\n label: string\n icon?: ReactNode\n /** The annotation the field is (its pill is shown as the label). */\n tag?: TagResponse\n children: ReactNode\n}\n\nexport interface DocumentFieldOptions {\n /** The column (a standard field's id, or an annotation's tag id). */\n columnId: string\n doc: WorkspaceDocument\n canEdit: boolean\n workspaceTags: TagResponse[]\n /** The workspace's documents (the folders to pick from). */\n allDocuments?: WorkspaceDocument[]\n /** Who uploaded the document. */\n creator?: DocumentPerson\n getColumnLabel: (colId: string) => string\n getColumnIcon: (colId: string) => ElementType | undefined\n isColumnEditable: (colId: string) => boolean\n onUpdateDocumentField: (field: string, value: unknown) => void\n onUpdateTagValue: (tag: TagResponse, value: string | boolean) => void\n onUpdateTagWithCitations: (tag: TagResponse, note: string, citations: DocTagCitations) => void\n /** Create a label and apply it (the labels picker). Absent: the picker only toggles. */\n onCreateAndApplyLabel?: (name: string) => void\n /** The document's related documents (email family, copies, duplicates, similar). */\n relatedDocs?: RelatedDocs<WorkspaceDocument>\n /** Open a related document. */\n onOpenDocument?: (docId: string) => void\n /** Delete a related document (asks first). */\n onDeleteDocument?: (docId: string) => void\n canDeleteRelatedDocument?: (doc: WorkspaceDocument) => boolean\n /** Compare with a similar document. Absent: not offered. */\n onCompareDocuments?: (docId: string, otherDocId: string) => void\n}\n\n/** The document metadata a field edits as text. */\nconst METADATA_FIELDS: Record<string, (doc: WorkspaceDocument) => string> = {\n title: (doc) => getDocumentTitle(doc),\n doc_nature: (doc) => doc.doc_metadata?.doc_nature || '',\n doc_author: (doc) => doc.doc_metadata?.doc_author || '',\n doc_subject: (doc) => doc.doc_metadata?.doc_subject || '',\n // As the table shows it: with the time when the value has one (emails).\n doc_date: (doc) => formatDocDate(getDocumentDate(doc)),\n}\n\nconst INPUT_CLASS = 'text-sm bg-muted/40 focus:bg-background transition-colors'\n\n/** A read-only standard field: its value (muted unless said otherwise). */\nconst READ_ONLY_FIELDS: Record<string, (doc: WorkspaceDocument) => ReactNode> = {\n file_name: (doc) => <FieldValue tone=\"strong\">{doc.file_name || 'N/A'}</FieldValue>,\n status: (doc) => <FieldValue tone=\"muted\">{doc.status || 'N/A'}</FieldValue>,\n n_pages: (doc) => <FieldValue tone=\"muted\">{doc.n_pages || 'N/A'}</FieldValue>,\n created_at: (doc) => (\n <FieldValue tone=\"muted\">\n {doc.created_at ? formatFriendlyDate(doc.created_at) : 'N/A'}\n </FieldValue>\n ),\n updated_at: (doc) => (\n <FieldValue tone=\"muted\">\n {doc.updated_at ? formatFriendlyDate(doc.updated_at) : 'N/A'}\n </FieldValue>\n ),\n file_type: (doc) => (\n <FieldValue tone=\"muted\"
|
|
5
|
-
"mappings": ";AAwFsB;AAjFtB,SAAS,iBAAiB,kBAAoC;AAE9D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4CP,MAAM,kBAAsE;AAAA,EAC1E,OAAO,CAAC,QAAQ,iBAAiB,GAAG;AAAA,EACpC,YAAY,CAAC,QAAQ,IAAI,cAAc,cAAc;AAAA,EACrD,YAAY,CAAC,QAAQ,IAAI,cAAc,cAAc;AAAA,EACrD,aAAa,CAAC,QAAQ,IAAI,cAAc,eAAe;AAAA;AAAA,EAEvD,UAAU,CAAC,QAAQ,cAAc,gBAAgB,GAAG,CAAC;AACvD;AAEA,MAAM,cAAc;AAGpB,MAAM,mBAA0E;AAAA,EAC9E,WAAW,CAAC,QAAQ,oBAAC,cAAW,MAAK,UAAU,cAAI,aAAa,OAAM;AAAA,EACtE,QAAQ,CAAC,QAAQ,oBAAC,cAAW,MAAK,SAAS,cAAI,UAAU,OAAM;AAAA,EAC/D,SAAS,CAAC,QAAQ,oBAAC,cAAW,MAAK,SAAS,cAAI,WAAW,OAAM;AAAA,EACjE,YAAY,CAAC,QACX,oBAAC,cAAW,MAAK,SACd,cAAI,aAAa,mBAAmB,IAAI,UAAU,IAAI,OACzD;AAAA,EAEF,YAAY,CAAC,QACX,oBAAC,cAAW,MAAK,SACd,cAAI,aAAa,mBAAmB,IAAI,UAAU,IAAI,OACzD;AAAA,EAEF,WAAW,CAAC,QACV,oBAAC,cAAW,MAAK,
|
|
4
|
+
"sourcesContent": ["/**\n * One field of a document as the review form shows it (a column of the documents table, one per\n * row): its label, icon and the value, editable where the table's column is. Standard fields,\n * metadata, the folder, related documents, the labels and each annotation (with who last set it).\n */\n\nimport type { ElementType, ReactNode } from 'react'\nimport { isAnnotationTag, isLabelTag, type TagResponse } from '@arbidocs/sdk/browser'\nimport type { DocumentPerson, RelatedDocs, WorkspaceDocument } from '@arbidocs/react'\nimport {\n DebouncedInput,\n formatFriendlyDate,\n friendlyFileType,\n Textarea,\n formatDocDate,\n getDocumentDate,\n getDocumentTitle,\n} from '@arbidocs/react/ui'\nimport {\n FieldFolderSelect,\n FieldFolderValue,\n FieldNativeSelect,\n FieldValue,\n FieldWithAttribution,\n} from '../../../files/FieldParts'\nimport { DocumentUser } from './DocumentUser'\nimport {\n DocTagAttribution,\n FolderPicker,\n LabelsCombobox,\n RelatedDocuments,\n} from './DocumentFieldParts'\n\ntype DocTag = NonNullable<WorkspaceDocument['doctags']>[number]\nexport type DocTagCitations = NonNullable<DocTag['citations']> | null\n\n/** A field as the form lays it out. */\nexport interface DocumentFieldContent {\n label: string\n icon?: ReactNode\n /** The annotation the field is (its pill is shown as the label). */\n tag?: TagResponse\n children: ReactNode\n}\n\nexport interface DocumentFieldOptions {\n /** The column (a standard field's id, or an annotation's tag id). */\n columnId: string\n doc: WorkspaceDocument\n canEdit: boolean\n workspaceTags: TagResponse[]\n /** The workspace's documents (the folders to pick from). */\n allDocuments?: WorkspaceDocument[]\n /** Who uploaded the document. */\n creator?: DocumentPerson\n getColumnLabel: (colId: string) => string\n getColumnIcon: (colId: string) => ElementType | undefined\n isColumnEditable: (colId: string) => boolean\n onUpdateDocumentField: (field: string, value: unknown) => void\n onUpdateTagValue: (tag: TagResponse, value: string | boolean) => void\n onUpdateTagWithCitations: (tag: TagResponse, note: string, citations: DocTagCitations) => void\n /** Create a label and apply it (the labels picker). Absent: the picker only toggles. */\n onCreateAndApplyLabel?: (name: string) => void\n /** The document's related documents (email family, copies, duplicates, similar). */\n relatedDocs?: RelatedDocs<WorkspaceDocument>\n /** Open a related document. */\n onOpenDocument?: (docId: string) => void\n /** Delete a related document (asks first). */\n onDeleteDocument?: (docId: string) => void\n canDeleteRelatedDocument?: (doc: WorkspaceDocument) => boolean\n /** Compare with a similar document. Absent: not offered. */\n onCompareDocuments?: (docId: string, otherDocId: string) => void\n}\n\n/** The document metadata a field edits as text. */\nconst METADATA_FIELDS: Record<string, (doc: WorkspaceDocument) => string> = {\n title: (doc) => getDocumentTitle(doc),\n doc_nature: (doc) => doc.doc_metadata?.doc_nature || '',\n doc_author: (doc) => doc.doc_metadata?.doc_author || '',\n doc_subject: (doc) => doc.doc_metadata?.doc_subject || '',\n // As the table shows it: with the time when the value has one (emails).\n doc_date: (doc) => formatDocDate(getDocumentDate(doc)),\n}\n\nconst INPUT_CLASS = 'text-sm bg-muted/40 focus:bg-background transition-colors'\n\n/** A read-only standard field: its value (muted unless said otherwise). */\nconst READ_ONLY_FIELDS: Record<string, (doc: WorkspaceDocument) => ReactNode> = {\n file_name: (doc) => <FieldValue tone=\"strong\">{doc.file_name || 'N/A'}</FieldValue>,\n status: (doc) => <FieldValue tone=\"muted\">{doc.status || 'N/A'}</FieldValue>,\n n_pages: (doc) => <FieldValue tone=\"muted\">{doc.n_pages || 'N/A'}</FieldValue>,\n created_at: (doc) => (\n <FieldValue tone=\"muted\">\n {doc.created_at ? formatFriendlyDate(doc.created_at) : 'N/A'}\n </FieldValue>\n ),\n updated_at: (doc) => (\n <FieldValue tone=\"muted\">\n {doc.updated_at ? formatFriendlyDate(doc.updated_at) : 'N/A'}\n </FieldValue>\n ),\n file_type: (doc) => (\n <FieldValue tone=\"muted\">\n {friendlyFileType(doc.file_type, doc.file_name, doc.folder)}\n </FieldValue>\n ),\n file_size: (doc) => (\n <FieldValue tone=\"muted\">\n {doc.file_size ? `${Math.round(doc.file_size / 1024)} KB` : 'N/A'}\n </FieldValue>\n ),\n doc_id: (doc) => (\n <FieldValue tone=\"muted\" isMono>\n {doc.external_id || 'N/A'}\n </FieldValue>\n ),\n content_hash: (doc) => (\n <FieldValue tone=\"muted\" isMono isTruncated>\n {doc.content_hash || 'N/A'}\n </FieldValue>\n ),\n}\n\n/** The field of `columnId`, or null when the document has none to show there. */\nexport function documentFieldContent(options: DocumentFieldOptions): DocumentFieldContent | null {\n const { columnId, doc, canEdit, workspaceTags, getColumnLabel, getColumnIcon } = options\n const Icon = getColumnIcon(columnId)\n const standard = (children: ReactNode): DocumentFieldContent => ({\n label: getColumnLabel(columnId),\n icon: Icon ? <Icon size={14} /> : undefined,\n children,\n })\n\n const metadata = METADATA_FIELDS[columnId]\n if (metadata) {\n const editable = options.isColumnEditable(columnId) && canEdit\n return standard(\n editable ? (\n <DebouncedInput\n value={metadata(doc)}\n onChange={(value) => options.onUpdateDocumentField(columnId, value)}\n multiline={true}\n placeholder={`Add ${getColumnLabel(columnId).toLowerCase()}\u2026`}\n className={INPUT_CLASS}\n />\n ) : (\n <FieldValue>{metadata(doc) || 'N/A'}</FieldValue>\n )\n )\n }\n\n const readOnly = READ_ONLY_FIELDS[columnId]\n if (readOnly) return standard(readOnly(doc))\n\n if (columnId === 'created_by') return standard(<DocumentUser user={options.creator} />)\n\n if (columnId === 'folder') {\n return standard(\n canEdit ? (\n <FieldFolderSelect\n folder={doc.folder}\n picker={\n <FolderPicker\n documents={options.allDocuments ?? []}\n value={doc.folder}\n onSelect={(folder) => options.onUpdateDocumentField('folder', folder)}\n />\n }\n />\n ) : (\n <FieldFolderValue folder={doc.folder} />\n )\n )\n }\n\n if (columnId === 'related') {\n const related = options.relatedDocs\n if (!related) return null\n return standard(\n <RelatedDocuments\n doc={doc}\n related={related}\n onOpen={options.onOpenDocument}\n onDelete={options.onDeleteDocument}\n canDelete={options.canDeleteRelatedDocument}\n onCompare={options.onCompareDocuments}\n />\n )\n }\n\n if (columnId === 'all_tags') {\n // The labels (and issues), toggled in place.\n const labelTags = workspaceTags.filter(isLabelTag)\n const appliedIds = new Set(\n (doc.doctags ?? [])\n .filter((dt) => labelTags.some((t) => t.external_id === dt.tag_ext_id))\n .map((dt) => dt.tag_ext_id)\n )\n return standard(\n <LabelsCombobox\n labelTags={labelTags}\n appliedTagIds={appliedIds}\n onToggle={(tag) => options.onUpdateTagValue(tag, !appliedIds.has(tag.external_id))}\n onCreateAndApply={options.onCreateAndApplyLabel}\n />\n )\n }\n\n // An annotation (a label is a value of the Labels field, not a field of its own).\n const tag = workspaceTags.find((t) => t.external_id === columnId)\n if (!tag || !isAnnotationTag(tag)) return null\n const doctag = doc.doctags?.find((dt) => dt.tag_ext_id === tag.external_id)\n\n let value: ReactNode\n if (tag.tag_type.type === 'select') {\n value = (\n <FieldNativeSelect\n value={doctag?.note || ''}\n options={tag.tag_type.options}\n onChange={(next) => options.onUpdateTagValue(tag, next)}\n ariaLabel={tag.name}\n />\n )\n } else if (tag.tag_type.type === 'number') {\n value = (\n <DebouncedInput\n type=\"number\"\n value={doctag?.note || ''}\n onChange={(next) => options.onUpdateTagValue(tag, next)}\n placeholder={`Add ${tag.name.toLowerCase()}\u2026`}\n className={INPUT_CLASS}\n />\n )\n } else {\n // A plain note: a value's citations come from generation and are kept as they are.\n value = (\n <Textarea\n value={doctag?.note || ''}\n onChange={(e) =>\n options.onUpdateTagWithCitations(tag, e.target.value, doctag?.citations ?? null)\n }\n placeholder=\"Add a note...\"\n rows={2}\n className={INPUT_CLASS}\n />\n )\n }\n\n return {\n label: tag.name,\n tag,\n children: doctag ? (\n <FieldWithAttribution attribution={<DocTagAttribution doctag={doctag} />}>\n {value}\n </FieldWithAttribution>\n ) : (\n value\n ),\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["value", "tag"]
|
|
7
7
|
}
|
|
@@ -406,7 +406,7 @@ function createDocumentColumns({
|
|
|
406
406
|
filter: "agTextColumnFilter",
|
|
407
407
|
filterParams: FILTER_PARAMS,
|
|
408
408
|
context: { icon: FileType },
|
|
409
|
-
valueGetter: (params) => friendlyFileType(params.data?.file_type, params.data?.file_name)
|
|
409
|
+
valueGetter: (params) => friendlyFileType(params.data?.file_type, params.data?.file_name, params.data?.folder)
|
|
410
410
|
});
|
|
411
411
|
allColumns.push({
|
|
412
412
|
colId: "folder",
|