@arbidocs/blocks 0.5.120 → 0.5.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ClippingMediaViewer-B6WG7Q64.cjs +156 -0
- package/dist/ClippingMediaViewer-B6WG7Q64.cjs.map +1 -0
- package/dist/ClippingPdfViewer-6GCVTV3V.cjs +79 -0
- package/dist/ClippingPdfViewer-6GCVTV3V.cjs.map +1 -0
- package/dist/{ConnectedCallDock-WER7R222.cjs → ConnectedCallDock-DC5V5OUJ.cjs} +25 -23
- package/dist/ConnectedCallDock-DC5V5OUJ.cjs.map +1 -0
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs → ConnectedCallRoom-FQLXWTFB.cjs} +18 -16
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs.map → ConnectedCallRoom-FQLXWTFB.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs → ConnectedNativeDocxComparison-4Q5S7VLD.cjs} +17 -17
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs.map → ConnectedNativeDocxComparison-4Q5S7VLD.cjs.map} +1 -1
- package/dist/ConnectedPresentation-4HLDZDWV.cjs +183 -0
- package/dist/ConnectedPresentation-4HLDZDWV.cjs.map +1 -0
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs → ConnectedProductionSetDialog-4EAY6KAZ.cjs} +3 -3
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs.map → ConnectedProductionSetDialog-4EAY6KAZ.cjs.map} +1 -1
- package/dist/ConnectedSlidesTab-7QDE2CZD.cjs +234 -0
- package/dist/ConnectedSlidesTab-7QDE2CZD.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs → ConnectedStreamedWordArtifact-FFOQJBOI.cjs} +17 -17
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs.map → ConnectedStreamedWordArtifact-FFOQJBOI.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-BPIAJJED.cjs → DocumentReviewCard-SNWVEZ7S.cjs} +17 -16
- package/dist/DocumentReviewCard-SNWVEZ7S.cjs.map +1 -0
- package/dist/{FilesViewerDialog-67WK3TZC.cjs → FilesViewerDialog-IZI63FOV.cjs} +52 -45
- package/dist/FilesViewerDialog-IZI63FOV.cjs.map +1 -0
- package/dist/{GridViewImpl-ZMJJWTOM.cjs → GridViewImpl-LTYET77Q.cjs} +3 -3
- package/dist/GridViewImpl-LTYET77Q.cjs.map +1 -0
- package/dist/{WorkspaceTableView-J3C6VH4T.cjs → WorkspaceTableView-TEIRB6VJ.cjs} +11 -10
- package/dist/WorkspaceTableView-TEIRB6VJ.cjs.map +1 -0
- package/dist/agents/index.cjs +297 -297
- package/dist/{ai-IM4A23YT.cjs → ai-KBYNRNZ6.cjs} +28 -26
- package/dist/ai-KBYNRNZ6.cjs.map +1 -0
- package/dist/calls/connected/CallControls.d.ts +2 -0
- package/dist/calls/connected/CallControls.js +71 -9
- package/dist/calls/connected/CallControls.js.map +2 -2
- package/dist/calls/connected/ShareDocumentDialog.d.ts +14 -0
- package/dist/calls/connected/ShareDocumentDialog.js +77 -0
- package/dist/calls/connected/ShareDocumentDialog.js.map +7 -0
- package/dist/calls/index.cjs +121 -121
- package/dist/chat/index.cjs +9 -8
- package/dist/{chunk-T23UTIRI.cjs → chunk-2PZT3J34.cjs} +6 -6
- package/dist/{chunk-T23UTIRI.cjs.map → chunk-2PZT3J34.cjs.map} +1 -1
- package/dist/{chunk-SGYSDABK.cjs → chunk-2W5E62EY.cjs} +6 -6
- package/dist/{chunk-SGYSDABK.cjs.map → chunk-2W5E62EY.cjs.map} +1 -1
- package/dist/{chunk-TDO5UWXF.cjs → chunk-3SCNXNHI.cjs} +5 -5
- package/dist/{chunk-TDO5UWXF.cjs.map → chunk-3SCNXNHI.cjs.map} +1 -1
- package/dist/{chunk-KTQOGT2L.cjs → chunk-474GPLCM.cjs} +7 -7
- package/dist/{chunk-KTQOGT2L.cjs.map → chunk-474GPLCM.cjs.map} +1 -1
- package/dist/{chunk-TP5PGWIO.cjs → chunk-4IOYQLKG.cjs} +3 -3
- package/dist/{chunk-TP5PGWIO.cjs.map → chunk-4IOYQLKG.cjs.map} +1 -1
- package/dist/{chunk-NY3YUCOW.cjs → chunk-4NPCDS2X.cjs} +3 -3
- package/dist/{chunk-NY3YUCOW.cjs.map → chunk-4NPCDS2X.cjs.map} +1 -1
- package/dist/{chunk-HA66DHW6.cjs → chunk-4RBQ44RY.cjs} +28 -28
- package/dist/chunk-4RBQ44RY.cjs.map +1 -0
- package/dist/{chunk-BQ5RIWWT.cjs → chunk-4VZZWYEC.cjs} +3 -3
- package/dist/{chunk-BQ5RIWWT.cjs.map → chunk-4VZZWYEC.cjs.map} +1 -1
- package/dist/{chunk-BP3IJ34D.cjs → chunk-52KGMAO5.cjs} +15 -15
- package/dist/{chunk-BP3IJ34D.cjs.map → chunk-52KGMAO5.cjs.map} +1 -1
- package/dist/{chunk-5IZFSAEZ.cjs → chunk-5534FYXP.cjs} +4 -4
- package/dist/{chunk-5IZFSAEZ.cjs.map → chunk-5534FYXP.cjs.map} +1 -1
- package/dist/chunk-5GCCUXMT.cjs +63 -0
- package/dist/chunk-5GCCUXMT.cjs.map +1 -0
- package/dist/chunk-5LTIZ44D.cjs +95 -0
- package/dist/chunk-5LTIZ44D.cjs.map +1 -0
- package/dist/{chunk-DFBDQKGE.cjs → chunk-734NPQNR.cjs} +4 -4
- package/dist/{chunk-DFBDQKGE.cjs.map → chunk-734NPQNR.cjs.map} +1 -1
- package/dist/{chunk-X36UR4A7.cjs → chunk-7VUJGHMY.cjs} +323 -96
- package/dist/chunk-7VUJGHMY.cjs.map +1 -0
- package/dist/chunk-AFQTQC7A.cjs +35 -0
- package/dist/chunk-AFQTQC7A.cjs.map +1 -0
- package/dist/{chunk-YYSBWMDJ.cjs → chunk-AY6EZSZB.cjs} +4 -4
- package/dist/{chunk-YYSBWMDJ.cjs.map → chunk-AY6EZSZB.cjs.map} +1 -1
- package/dist/{chunk-BUVIBHFU.cjs → chunk-BVAT4EVC.cjs} +38 -38
- package/dist/chunk-BVAT4EVC.cjs.map +1 -0
- package/dist/{chunk-ECLUFKYR.cjs → chunk-C2OICDMI.cjs} +10 -10
- package/dist/{chunk-ECLUFKYR.cjs.map → chunk-C2OICDMI.cjs.map} +1 -1
- package/dist/{chunk-CPR6EHG7.cjs → chunk-DR2AH7JL.cjs} +179 -55
- package/dist/chunk-DR2AH7JL.cjs.map +1 -0
- package/dist/{chunk-NJCK6V6U.cjs → chunk-EATIFPKP.cjs} +4 -60
- package/dist/chunk-EATIFPKP.cjs.map +1 -0
- package/dist/{chunk-B3LZITVF.cjs → chunk-EHP6OH5D.cjs} +11 -451
- package/dist/chunk-EHP6OH5D.cjs.map +1 -0
- package/dist/{chunk-775S43W7.cjs → chunk-ENGL7P3I.cjs} +31 -31
- package/dist/{chunk-775S43W7.cjs.map → chunk-ENGL7P3I.cjs.map} +1 -1
- package/dist/{chunk-VZCPMXWC.cjs → chunk-FKFQCK3C.cjs} +4 -4
- package/dist/{chunk-VZCPMXWC.cjs.map → chunk-FKFQCK3C.cjs.map} +1 -1
- package/dist/{chunk-6UTKM5AB.cjs → chunk-GKVE5JGB.cjs} +76 -76
- package/dist/chunk-GKVE5JGB.cjs.map +1 -0
- package/dist/{chunk-Q6CLWOP2.cjs → chunk-GPX5VC57.cjs} +50 -50
- package/dist/{chunk-Q6CLWOP2.cjs.map → chunk-GPX5VC57.cjs.map} +1 -1
- package/dist/{chunk-WAV762GP.cjs → chunk-GQXPNIRE.cjs} +6 -6
- package/dist/{chunk-WAV762GP.cjs.map → chunk-GQXPNIRE.cjs.map} +1 -1
- package/dist/chunk-GX2EBMJW.cjs +133 -0
- package/dist/chunk-GX2EBMJW.cjs.map +1 -0
- package/dist/{chunk-7OPOPYV6.cjs → chunk-H5OLHP2U.cjs} +3 -3
- package/dist/{chunk-7OPOPYV6.cjs.map → chunk-H5OLHP2U.cjs.map} +1 -1
- package/dist/chunk-HYUKPHCT.cjs +66 -0
- package/dist/chunk-HYUKPHCT.cjs.map +1 -0
- package/dist/{chunk-NLSWDP42.cjs → chunk-JQLWKNJO.cjs} +22 -12
- package/dist/chunk-JQLWKNJO.cjs.map +1 -0
- package/dist/{chunk-CKCG4NDB.cjs → chunk-JZEYHDWJ.cjs} +75 -75
- package/dist/{chunk-CKCG4NDB.cjs.map → chunk-JZEYHDWJ.cjs.map} +1 -1
- package/dist/{chunk-PGJYD67F.cjs → chunk-KNGZZC4O.cjs} +7 -6
- package/dist/chunk-KNGZZC4O.cjs.map +1 -0
- package/dist/{chunk-W6INT5GS.cjs → chunk-KP5AITQ4.cjs} +10 -10
- package/dist/{chunk-W6INT5GS.cjs.map → chunk-KP5AITQ4.cjs.map} +1 -1
- package/dist/{chunk-YYPZOEED.cjs → chunk-LHWOKOMP.cjs} +23 -2
- package/dist/chunk-LHWOKOMP.cjs.map +1 -0
- package/dist/{chunk-WXUU3COI.cjs → chunk-MZ2KZXNU.cjs} +3 -3
- package/dist/{chunk-WXUU3COI.cjs.map → chunk-MZ2KZXNU.cjs.map} +1 -1
- package/dist/chunk-NAJN32MF.cjs +154 -0
- package/dist/chunk-NAJN32MF.cjs.map +1 -0
- package/dist/{chunk-557MJ4IH.cjs → chunk-NLOETJCB.cjs} +17 -154
- package/dist/chunk-NLOETJCB.cjs.map +1 -0
- package/dist/{chunk-4XJEHKVZ.cjs → chunk-PIYYBPHH.cjs} +4 -4
- package/dist/{chunk-4XJEHKVZ.cjs.map → chunk-PIYYBPHH.cjs.map} +1 -1
- package/dist/chunk-Q3XJUXID.cjs +4774 -0
- package/dist/chunk-Q3XJUXID.cjs.map +1 -0
- package/dist/{chunk-325GVZE6.cjs → chunk-Q6DQGGP4.cjs} +3 -3
- package/dist/{chunk-325GVZE6.cjs.map → chunk-Q6DQGGP4.cjs.map} +1 -1
- package/dist/chunk-QFXILJMJ.cjs +458 -0
- package/dist/chunk-QFXILJMJ.cjs.map +1 -0
- package/dist/{chunk-QQWHG3KF.cjs → chunk-RYVZDFVO.cjs} +5 -5
- package/dist/{chunk-QQWHG3KF.cjs.map → chunk-RYVZDFVO.cjs.map} +1 -1
- package/dist/{chunk-EOG6OT5I.cjs → chunk-TXP2N3DC.cjs} +4 -4
- package/dist/{chunk-EOG6OT5I.cjs.map → chunk-TXP2N3DC.cjs.map} +1 -1
- package/dist/{chunk-KXIRVKCJ.cjs → chunk-UUENH4BJ.cjs} +3 -3
- package/dist/{chunk-KXIRVKCJ.cjs.map → chunk-UUENH4BJ.cjs.map} +1 -1
- package/dist/chunk-VJ5ZLRBD.cjs +27 -0
- package/dist/chunk-VJ5ZLRBD.cjs.map +1 -0
- package/dist/{chunk-3GWWOYGS.cjs → chunk-W6B3RYTX.cjs} +4 -4
- package/dist/{chunk-3GWWOYGS.cjs.map → chunk-W6B3RYTX.cjs.map} +1 -1
- package/dist/chunk-WOOOMTTA.cjs +19 -0
- package/dist/chunk-WOOOMTTA.cjs.map +1 -0
- package/dist/{chunk-CJYWHUZR.cjs → chunk-XCKHOXRP.cjs} +4 -4
- package/dist/{chunk-CJYWHUZR.cjs.map → chunk-XCKHOXRP.cjs.map} +1 -1
- package/dist/{chunk-6WMMZLEV.cjs → chunk-XJEXFEWG.cjs} +2 -27
- package/dist/chunk-XJEXFEWG.cjs.map +1 -0
- package/dist/chunk-XK4TVJKD.cjs +73 -0
- package/dist/chunk-XK4TVJKD.cjs.map +1 -0
- package/dist/chunk-XTR26TNE.cjs +1358 -0
- package/dist/chunk-XTR26TNE.cjs.map +1 -0
- package/dist/{chunk-E7TE2WVT.cjs → chunk-ZVEW3JBT.cjs} +3 -3
- package/dist/{chunk-E7TE2WVT.cjs.map → chunk-ZVEW3JBT.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +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 +20 -20
- package/dist/connect/index.cjs +1150 -1232
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +40 -34
- package/dist/connection/ai.d.ts +1 -1
- 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 +220 -0
- package/dist/connection/presentation/ConnectedSlidesTab.js.map +7 -0
- package/dist/connection/presentation/CropClipDialog.d.ts +11 -0
- package/dist/connection/presentation/CropClipDialog.js +86 -0
- package/dist/connection/presentation/CropClipDialog.js.map +7 -0
- package/dist/connection/presentation/GenerateTile.d.ts +4 -0
- package/dist/connection/presentation/GenerateTile.js +24 -0
- package/dist/connection/presentation/GenerateTile.js.map +7 -0
- package/dist/connection/presentation/LabelColumnMenu.d.ts +8 -0
- package/dist/connection/presentation/LabelColumnMenu.js +38 -0
- package/dist/connection/presentation/LabelColumnMenu.js.map +7 -0
- package/dist/connection/presentation/PresentationDialogs.d.ts +39 -0
- package/dist/connection/presentation/PresentationDialogs.js +295 -0
- package/dist/connection/presentation/PresentationDialogs.js.map +7 -0
- package/dist/connection/presentation/PresentationFileCard.d.ts +10 -0
- package/dist/connection/presentation/PresentationFileCard.js +35 -0
- package/dist/connection/presentation/PresentationFileCard.js.map +7 -0
- package/dist/connection/presentation/PresentationPill.d.ts +8 -0
- package/dist/connection/presentation/PresentationPill.js +44 -0
- package/dist/connection/presentation/PresentationPill.js.map +7 -0
- package/dist/connection/presentation/PresentationSlot.d.ts +7 -0
- package/dist/connection/presentation/PresentationSlot.js +35 -0
- package/dist/connection/presentation/PresentationSlot.js.map +7 -0
- package/dist/connection/presentation/requests.d.ts +16 -0
- package/dist/connection/presentation/requests.js +20 -0
- package/dist/connection/presentation/requests.js.map +7 -0
- package/dist/connection/presentation/useImageGeneration.d.ts +11 -0
- package/dist/connection/presentation/useImageGeneration.js +66 -0
- package/dist/connection/presentation/useImageGeneration.js.map +7 -0
- package/dist/connection/presentation/useLabelColumns.d.ts +15 -0
- package/dist/connection/presentation/useLabelColumns.js +33 -0
- package/dist/connection/presentation/useLabelColumns.js.map +7 -0
- package/dist/connection/presentation/usePresentationController.d.ts +15 -0
- package/dist/connection/presentation/usePresentationController.js +118 -0
- package/dist/connection/presentation/usePresentationController.js.map +7 -0
- package/dist/connection/presentation/usePresentationFiles.d.ts +44 -0
- package/dist/connection/presentation/usePresentationFiles.js +307 -0
- package/dist/connection/presentation/usePresentationFiles.js.map +7 -0
- package/dist/connection/presentation/useViewerClipping.d.ts +14 -0
- package/dist/connection/presentation/useViewerClipping.js +18 -0
- package/dist/connection/presentation/useViewerClipping.js.map +7 -0
- package/dist/connection/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 +37 -0
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/drafts.js +6 -4
- package/dist/connection/viewer/drafts.js.map +2 -2
- package/dist/connection/viewer/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/dashboards/index.cjs +1 -1
- package/dist/databases/index.cjs +49 -49
- package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
- package/dist/document-tools/DocumentToolButtons.js +22 -1
- package/dist/document-tools/DocumentToolButtons.js.map +2 -2
- package/dist/document-tools/index.cjs +16 -12
- package/dist/document-tools/index.d.ts +1 -1
- package/dist/document-tools/index.js +2 -0
- package/dist/document-tools/index.js.map +2 -2
- package/dist/embed/index.cjs +41 -39
- 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 +225 -225
- package/dist/files/navigator/DocumentSearchList.js +1 -1
- package/dist/files/navigator/DocumentSearchList.js.map +2 -2
- package/dist/index.cjs +1666 -1664
- package/dist/index.cjs.map +1 -1
- package/dist/presentation/BoxActionBar.d.ts +11 -0
- package/dist/presentation/BoxActionBar.js +182 -0
- package/dist/presentation/BoxActionBar.js.map +7 -0
- package/dist/presentation/ClipActionBar.d.ts +26 -0
- package/dist/presentation/ClipActionBar.js +103 -0
- package/dist/presentation/ClipActionBar.js.map +7 -0
- package/dist/presentation/ClipCaptureOverlay.d.ts +14 -0
- package/dist/presentation/ClipCaptureOverlay.js +69 -0
- package/dist/presentation/ClipCaptureOverlay.js.map +7 -0
- package/dist/presentation/ClipImage.d.ts +21 -0
- package/dist/presentation/ClipImage.js +119 -0
- package/dist/presentation/ClipImage.js.map +7 -0
- package/dist/presentation/ClipTray.d.ts +11 -0
- package/dist/presentation/ClipTray.js +152 -0
- package/dist/presentation/ClipTray.js.map +7 -0
- package/dist/presentation/ClipViewControls.d.ts +11 -0
- package/dist/presentation/ClipViewControls.js +142 -0
- package/dist/presentation/ClipViewControls.js.map +7 -0
- package/dist/presentation/DesignMenu.d.ts +8 -0
- package/dist/presentation/DesignMenu.js +199 -0
- package/dist/presentation/DesignMenu.js.map +7 -0
- package/dist/presentation/LayoutMenu.d.ts +17 -0
- package/dist/presentation/LayoutMenu.js +122 -0
- package/dist/presentation/LayoutMenu.js.map +7 -0
- package/dist/presentation/MediaClip.d.ts +15 -0
- package/dist/presentation/MediaClip.js +67 -0
- package/dist/presentation/MediaClip.js.map +7 -0
- package/dist/presentation/Notice.d.ts +6 -0
- package/dist/presentation/Notice.js +43 -0
- package/dist/presentation/Notice.js.map +7 -0
- package/dist/presentation/PresentationStage.d.ts +32 -0
- package/dist/presentation/PresentationStage.js +232 -0
- package/dist/presentation/PresentationStage.js.map +7 -0
- package/dist/presentation/PresenterView.d.ts +16 -0
- package/dist/presentation/PresenterView.js +69 -0
- package/dist/presentation/PresenterView.js.map +7 -0
- package/dist/presentation/SlideDecor.d.ts +25 -0
- package/dist/presentation/SlideDecor.js +189 -0
- package/dist/presentation/SlideDecor.js.map +7 -0
- package/dist/presentation/SlidesEditor.d.ts +25 -0
- package/dist/presentation/SlidesEditor.js +359 -0
- package/dist/presentation/SlidesEditor.js.map +7 -0
- package/dist/presentation/StageBox.d.ts +30 -0
- package/dist/presentation/StageBox.js +281 -0
- package/dist/presentation/StageBox.js.map +7 -0
- package/dist/presentation/StageItem.d.ts +37 -0
- package/dist/presentation/StageItem.js +211 -0
- package/dist/presentation/StageItem.js.map +7 -0
- package/dist/presentation/box-style.d.ts +6 -0
- package/dist/presentation/box-style.js +19 -0
- package/dist/presentation/box-style.js.map +7 -0
- package/dist/presentation/boxes.d.ts +105 -0
- package/dist/presentation/boxes.js +103 -0
- package/dist/presentation/boxes.js.map +7 -0
- package/dist/presentation/draw-boxes.d.ts +8 -0
- package/dist/presentation/draw-boxes.js +130 -0
- package/dist/presentation/draw-boxes.js.map +7 -0
- package/dist/presentation/export-boxes.d.ts +10 -0
- package/dist/presentation/export-boxes.js +74 -0
- package/dist/presentation/export-boxes.js.map +7 -0
- package/dist/presentation/export-pptx.d.ts +16 -0
- package/dist/presentation/export-pptx.js +194 -0
- package/dist/presentation/export-pptx.js.map +7 -0
- package/dist/presentation/import-pptx.d.ts +35 -0
- package/dist/presentation/import-pptx.js +659 -0
- package/dist/presentation/import-pptx.js.map +7 -0
- package/dist/presentation/merge-outside-edits.d.ts +12 -0
- package/dist/presentation/merge-outside-edits.js +35 -0
- package/dist/presentation/merge-outside-edits.js.map +7 -0
- package/dist/presentation/model.d.ts +201 -0
- package/dist/presentation/model.js +271 -0
- package/dist/presentation/model.js.map +7 -0
- package/dist/presentation/panel-id.d.ts +34 -0
- package/dist/presentation/panel-id.js +24 -0
- package/dist/presentation/panel-id.js.map +7 -0
- package/dist/presentation/persistence.d.ts +121 -0
- package/dist/presentation/persistence.js +141 -0
- package/dist/presentation/persistence.js.map +7 -0
- package/dist/presentation/pptx-data.d.ts +22 -0
- package/dist/presentation/pptx-data.js +83 -0
- package/dist/presentation/pptx-data.js.map +7 -0
- package/dist/presentation/pptx-xml.d.ts +90 -0
- package/dist/presentation/pptx-xml.js +333 -0
- package/dist/presentation/pptx-xml.js.map +7 -0
- package/dist/presentation/render-slides.d.ts +58 -0
- package/dist/presentation/render-slides.js +309 -0
- package/dist/presentation/render-slides.js.map +7 -0
- package/dist/presentation/saved-boxes.d.ts +11 -0
- package/dist/presentation/saved-boxes.js +80 -0
- package/dist/presentation/saved-boxes.js.map +7 -0
- package/dist/presentation/slide-layout.d.ts +54 -0
- package/dist/presentation/slide-layout.js +117 -0
- package/dist/presentation/slide-layout.js.map +7 -0
- package/dist/presentation/stage-videos.d.ts +5 -0
- package/dist/presentation/stage-videos.js +19 -0
- package/dist/presentation/stage-videos.js.map +7 -0
- package/dist/presentation/store.d.ts +203 -0
- package/dist/presentation/store.js +429 -0
- package/dist/presentation/store.js.map +7 -0
- package/dist/presentation/theme.d.ts +102 -0
- package/dist/presentation/theme.js +276 -0
- package/dist/presentation/theme.js.map +7 -0
- package/dist/presentation/useClipDrag.d.ts +26 -0
- package/dist/presentation/useClipDrag.js +65 -0
- package/dist/presentation/useClipDrag.js.map +7 -0
- package/dist/presentation/useObjectUrl.d.ts +6 -0
- package/dist/presentation/useObjectUrl.js +15 -0
- package/dist/presentation/useObjectUrl.js.map +7 -0
- package/dist/presentation/usePresenterKeys.d.ts +13 -0
- package/dist/presentation/usePresenterKeys.js +62 -0
- package/dist/presentation/usePresenterKeys.js.map +7 -0
- package/dist/settings/index.cjs +151 -150
- package/dist/shell/PanelPortal.js +1 -0
- package/dist/shell/PanelPortal.js.map +2 -2
- package/dist/shell/index.cjs +112 -110
- package/dist/shell/panel-windows.d.ts +2 -0
- package/dist/shell/panel-windows.js +7 -2
- package/dist/shell/panel-windows.js.map +2 -2
- package/dist/studio/index.cjs +28 -26
- package/dist/studio/index.cjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +55 -54
- 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-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/mail/useMailboxDefaults.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * What the mail kits take from the signed-in session: how a person is named (contacts and\n * workspace co-members), recipient suggestions (the one people source), the open workspace's\n * documents to attach, and saving an email into a workspace.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport {\n documentMailAttachment,\n useArbi,\n useArbiSessionState,\n useDocuments,\n usePeople,\n usePeopleSearch,\n useWorkspaces,\n type MailAddress,\n} from '@arbidocs/react'\nimport { getDocumentTitle, getFileTypeIcon } from '@arbidocs/react/ui'\nimport type { MailDocumentSource, MailRecipientSuggestions, MailWorkspaces } from './types'\n\n/** Recipient suggestions while an address is typed: contacts and workspace co-members. */\nexport const peopleRecipients: MailRecipientSuggestions = {\n useSuggestions: (query) => usePeopleSearch(query).people,\n}\n\n/**\n * How a mail address is shown: the name on the message, else the name of a person you know with\n * that address (a contact's card, a workspace co-member), else the address. Recipients are stored\n * as bare addresses when composed, so the lookup is what lets sent mail show \"Pat Quinn\".\n */\nexport function useMailPersonLabel(): (person: MailAddress) => string {\n const { byEmail } = usePeople()\n return useCallback(\n (person: MailAddress) => person.name || byEmail(person.email)?.name || person.email,\n [byEmail]\n )\n}\n\n/**\n * The open workspace's documents, attachable as their files (\"From workspace\"); drafts never\n * uploaded as a file are left out. None without an open workspace.\n */\nexport function useWorkspaceMailDocuments(): MailDocumentSource | undefined {\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const { data: workspaceDocuments = [] } = useDocuments()\n const arbi = useArbi()\n return useMemo<MailDocumentSource | undefined>(() => {\n if (!workspaceId) return undefined\n const files = workspaceDocuments.filter((doc) => Boolean(doc.file_name))\n return {\n documents: files.map((doc) => {\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type })\n return { id: doc.external_id, title: getDocumentTitle(doc), icon: <Icon size={14} /> }\n }),\n toAttachment: async (id, maxBytes) => {\n const doc = files.find((d) => d.external_id === id)\n if (!doc) throw new Error('Could not attach the document')\n return documentMailAttachment(arbi, doc, maxBytes)\n },\n }\n }, [workspaceId, workspaceDocuments, arbi])\n}\n\n/**\n * The user's workspaces mail can be added to: the private ones (mail added is private, and a\n * public workspace's key is shared with everyone); the open one is preselected.\n */\nexport function useMailWorkspaces(): MailWorkspaces {\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const { data: workspaces = [] } = useWorkspaces()\n return useMemo<MailWorkspaces>(() => {\n const own = workspaces.filter((w) => !w.is_public)\n return {\n workspaces: own.map((w) => ({ id: w.external_id, name: w.name })),\n defaultWorkspaceId: own.some((w) => w.external_id === workspaceId) ? workspaceId : undefined,\n }\n }, [workspaces, workspaceId])\n}\n"],
|
|
5
|
-
"mappings": ";AAoD0E;AA9C1E,SAAS,aAAa,eAAe;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,kBAAkB,uBAAuB;AAI3C,MAAM,mBAA6C;AAAA,EACxD,gBAAgB,CAAC,UAAU,gBAAgB,KAAK,EAAE;AACpD;AAOO,SAAS,qBAAsD;AACpE,QAAM,EAAE,QAAQ,IAAI,UAAU;AAC9B,SAAO;AAAA,IACL,CAAC,WAAwB,OAAO,QAAQ,QAAQ,OAAO,KAAK,GAAG,QAAQ,OAAO;AAAA,IAC9E,CAAC,OAAO;AAAA,EACV;AACF;AAMO,SAAS,4BAA4D;AAC1E,QAAM,cAAc,oBAAoB,CAAC,MAAM,EAAE,WAAW;AAC5D,QAAM,EAAE,MAAM,qBAAqB,CAAC,EAAE,IAAI,aAAa;AACvD,QAAM,OAAO,QAAQ;AACrB,SAAO,QAAwC,MAAM;AACnD,QAAI,CAAC,YAAa,QAAO;AACzB,UAAM,QAAQ,mBAAmB,OAAO,CAAC,QAAQ,QAAQ,IAAI,SAAS,CAAC;AACvE,WAAO;AAAA,MACL,WAAW,MAAM,IAAI,CAAC,QAAQ;AAC5B,cAAM,OAAO,gBAAgB,IAAI,WAAW,EAAE,MAAM,IAAI,
|
|
4
|
+
"sourcesContent": ["/**\n * What the mail kits take from the signed-in session: how a person is named (contacts and\n * workspace co-members), recipient suggestions (the one people source), the open workspace's\n * documents to attach, and saving an email into a workspace.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport {\n documentMailAttachment,\n useArbi,\n useArbiSessionState,\n useDocuments,\n usePeople,\n usePeopleSearch,\n useWorkspaces,\n type MailAddress,\n} from '@arbidocs/react'\nimport { getDocumentTitle, getFileTypeIcon } from '@arbidocs/react/ui'\nimport type { MailDocumentSource, MailRecipientSuggestions, MailWorkspaces } from './types'\n\n/** Recipient suggestions while an address is typed: contacts and workspace co-members. */\nexport const peopleRecipients: MailRecipientSuggestions = {\n useSuggestions: (query) => usePeopleSearch(query).people,\n}\n\n/**\n * How a mail address is shown: the name on the message, else the name of a person you know with\n * that address (a contact's card, a workspace co-member), else the address. Recipients are stored\n * as bare addresses when composed, so the lookup is what lets sent mail show \"Pat Quinn\".\n */\nexport function useMailPersonLabel(): (person: MailAddress) => string {\n const { byEmail } = usePeople()\n return useCallback(\n (person: MailAddress) => person.name || byEmail(person.email)?.name || person.email,\n [byEmail]\n )\n}\n\n/**\n * The open workspace's documents, attachable as their files (\"From workspace\"); drafts never\n * uploaded as a file are left out. None without an open workspace.\n */\nexport function useWorkspaceMailDocuments(): MailDocumentSource | undefined {\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const { data: workspaceDocuments = [] } = useDocuments()\n const arbi = useArbi()\n return useMemo<MailDocumentSource | undefined>(() => {\n if (!workspaceId) return undefined\n const files = workspaceDocuments.filter((doc) => Boolean(doc.file_name))\n return {\n documents: files.map((doc) => {\n const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type, folder: doc.folder })\n return { id: doc.external_id, title: getDocumentTitle(doc), icon: <Icon size={14} /> }\n }),\n toAttachment: async (id, maxBytes) => {\n const doc = files.find((d) => d.external_id === id)\n if (!doc) throw new Error('Could not attach the document')\n return documentMailAttachment(arbi, doc, maxBytes)\n },\n }\n }, [workspaceId, workspaceDocuments, arbi])\n}\n\n/**\n * The user's workspaces mail can be added to: the private ones (mail added is private, and a\n * public workspace's key is shared with everyone); the open one is preselected.\n */\nexport function useMailWorkspaces(): MailWorkspaces {\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const { data: workspaces = [] } = useWorkspaces()\n return useMemo<MailWorkspaces>(() => {\n const own = workspaces.filter((w) => !w.is_public)\n return {\n workspaces: own.map((w) => ({ id: w.external_id, name: w.name })),\n defaultWorkspaceId: own.some((w) => w.external_id === workspaceId) ? workspaceId : undefined,\n }\n }, [workspaces, workspaceId])\n}\n"],
|
|
5
|
+
"mappings": ";AAoD0E;AA9C1E,SAAS,aAAa,eAAe;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,kBAAkB,uBAAuB;AAI3C,MAAM,mBAA6C;AAAA,EACxD,gBAAgB,CAAC,UAAU,gBAAgB,KAAK,EAAE;AACpD;AAOO,SAAS,qBAAsD;AACpE,QAAM,EAAE,QAAQ,IAAI,UAAU;AAC9B,SAAO;AAAA,IACL,CAAC,WAAwB,OAAO,QAAQ,QAAQ,OAAO,KAAK,GAAG,QAAQ,OAAO;AAAA,IAC9E,CAAC,OAAO;AAAA,EACV;AACF;AAMO,SAAS,4BAA4D;AAC1E,QAAM,cAAc,oBAAoB,CAAC,MAAM,EAAE,WAAW;AAC5D,QAAM,EAAE,MAAM,qBAAqB,CAAC,EAAE,IAAI,aAAa;AACvD,QAAM,OAAO,QAAQ;AACrB,SAAO,QAAwC,MAAM;AACnD,QAAI,CAAC,YAAa,QAAO;AACzB,UAAM,QAAQ,mBAAmB,OAAO,CAAC,QAAQ,QAAQ,IAAI,SAAS,CAAC;AACvE,WAAO;AAAA,MACL,WAAW,MAAM,IAAI,CAAC,QAAQ;AAC5B,cAAM,OAAO,gBAAgB,IAAI,WAAW,EAAE,MAAM,IAAI,WAAW,QAAQ,IAAI,OAAO,CAAC;AACvF,eAAO,EAAE,IAAI,IAAI,aAAa,OAAO,iBAAiB,GAAG,GAAG,MAAM,oBAAC,QAAK,MAAM,IAAI,EAAG;AAAA,MACvF,CAAC;AAAA,MACD,cAAc,OAAO,IAAI,aAAa;AACpC,cAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE;AAClD,YAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+BAA+B;AACzD,eAAO,uBAAuB,MAAM,KAAK,QAAQ;AAAA,MACnD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,aAAa,oBAAoB,IAAI,CAAC;AAC5C;AAMO,SAAS,oBAAoC;AAClD,QAAM,cAAc,oBAAoB,CAAC,MAAM,EAAE,WAAW;AAC5D,QAAM,EAAE,MAAM,aAAa,CAAC,EAAE,IAAI,cAAc;AAChD,SAAO,QAAwB,MAAM;AACnC,UAAM,MAAM,WAAW,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS;AACjD,WAAO;AAAA,MACL,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,MAAM,EAAE,KAAK,EAAE;AAAA,MAChE,oBAAoB,IAAI,KAAK,CAAC,MAAM,EAAE,gBAAgB,WAAW,IAAI,cAAc;AAAA,IACrF;AAAA,EACF,GAAG,CAAC,YAAY,WAAW,CAAC;AAC9B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,16 +4,17 @@ import { useIsPhone } from "../../lib/use-media-query.js";
|
|
|
4
4
|
import { useArbiSessionState, useArbiSessionStore } from "@arbidocs/react";
|
|
5
5
|
function useSessionPanelMode(panelId, defaultMode = "docked", isOpen = true) {
|
|
6
6
|
const panelModes = useArbiSessionState((s) => s.shell.panels.modes);
|
|
7
|
+
const openedPoppedOut = useArbiSessionState((s) => s.shell.panels.popout === panelId);
|
|
7
8
|
const setPanelModeStore = useArbiSessionStore().setPanelMode;
|
|
8
9
|
const isSmallScreen = useIsPhone();
|
|
9
10
|
const prevOpenRef = useRef(false);
|
|
10
11
|
const mode = isSmallScreen ? "overlay" : panelModes[panelId] || defaultMode;
|
|
11
12
|
useEffect(() => {
|
|
12
|
-
if (isOpen && !prevOpenRef.current) {
|
|
13
|
+
if (isOpen && !prevOpenRef.current && !(openedPoppedOut && !isSmallScreen)) {
|
|
13
14
|
setPanelModeStore(panelId, isSmallScreen ? "overlay" : defaultMode);
|
|
14
15
|
}
|
|
15
16
|
prevOpenRef.current = isOpen;
|
|
16
|
-
}, [isOpen, panelId, defaultMode, isSmallScreen, setPanelModeStore]);
|
|
17
|
+
}, [isOpen, panelId, defaultMode, isSmallScreen, setPanelModeStore, openedPoppedOut]);
|
|
17
18
|
useEffect(() => {
|
|
18
19
|
if (isSmallScreen && isOpen && panelModes[panelId] && panelModes[panelId] !== "overlay") {
|
|
19
20
|
setPanelModeStore(panelId, "overlay");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/panels/useSessionPanelMode.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * useSessionPanelMode Hook\n *\n * Reads and writes a panel's display mode (floating/docked/popout) from the shared session.\n *\n * defaultMode is applied every time the panel opens (isOpen transitions to true),\n * so a panel with defaultMode=\"docked\" will always dock on open \u2014 even if it was\n * previously kicked to floating by another panel docking.\n *\n * Users can still switch modes manually; the switch is respected until the panel\n * closes and reopens.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport { useIsPhone } from '../../lib/use-media-query'\nimport { useArbiSessionState, useArbiSessionStore, type ArbiPanelMode } from '@arbidocs/react'\n\nexport type PanelMode = ArbiPanelMode\n\nexport function useSessionPanelMode(\n panelId: string,\n defaultMode: PanelMode = 'docked',\n isOpen = true\n) {\n const panelModes = useArbiSessionState((s) => s.shell.panels.modes)\n const setPanelModeStore = useArbiSessionStore().setPanelMode\n const isSmallScreen = useIsPhone()\n const prevOpenRef = useRef(false)\n\n // The right-hand panel mirrors the left sidebar: parked in the layout\n // ('docked', which pushes content) or floating over it ('overlay', a\n // slide-out sheet + backdrop). On phones the parked split and popout windows\n // don't fit, so coerce to 'overlay' below the breakpoint \u2014 only the *default*\n // changes with screen size. Driving the *stored* mode keeps every consumer\n // consistent (slot placement + the FloatingPanel renderer all agree).\n const mode: PanelMode = isSmallScreen ? 'overlay' : panelModes[panelId] || defaultMode\n\n // Reset to the effective default when the panel opens (small screen always\n // 'overlay'), so sidebar buttons reliably bring panels back to their mode.\n useEffect(() => {\n if (isOpen && !prevOpenRef.current) {\n setPanelModeStore(panelId, isSmallScreen ? 'overlay' : defaultMode)\n }\n prevOpenRef.current = isOpen\n }, [isOpen, panelId, defaultMode, isSmallScreen, setPanelModeStore])\n\n // If the viewport shrinks past the breakpoint while a panel is open and still\n // parked/popout, snap it to 'overlay' so the split layout never clips.\n useEffect(() => {\n if (isSmallScreen && isOpen && panelModes[panelId] && panelModes[panelId] !== 'overlay') {\n setPanelModeStore(panelId, 'overlay')\n }\n }, [isSmallScreen, isOpen, panelId, panelModes, setPanelModeStore])\n\n const setPanelMode = useCallback(\n (newMode: PanelMode) => {\n // Mode switching is a desktop affordance; on phones everything is 'main'.\n if (isSmallScreen) return\n setPanelModeStore(panelId, newMode)\n },\n [panelId, isSmallScreen, setPanelModeStore]\n )\n\n return { mode, setPanelMode }\n}\n"],
|
|
5
|
-
"mappings": ";AAaA,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB,2BAA+C;AAItE,SAAS,oBACd,SACA,cAAyB,UACzB,SAAS,MACT;AACA,QAAM,aAAa,oBAAoB,CAAC,MAAM,EAAE,MAAM,OAAO,KAAK;
|
|
4
|
+
"sourcesContent": ["/**\n * useSessionPanelMode Hook\n *\n * Reads and writes a panel's display mode (floating/docked/popout) from the shared session.\n *\n * defaultMode is applied every time the panel opens (isOpen transitions to true),\n * so a panel with defaultMode=\"docked\" will always dock on open \u2014 even if it was\n * previously kicked to floating by another panel docking.\n *\n * Users can still switch modes manually; the switch is respected until the panel\n * closes and reopens.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport { useIsPhone } from '../../lib/use-media-query'\nimport { useArbiSessionState, useArbiSessionStore, type ArbiPanelMode } from '@arbidocs/react'\n\nexport type PanelMode = ArbiPanelMode\n\nexport function useSessionPanelMode(\n panelId: string,\n defaultMode: PanelMode = 'docked',\n isOpen = true\n) {\n const panelModes = useArbiSessionState((s) => s.shell.panels.modes)\n // Opened straight into a window of its own (`openPanel(id, 'popout')`, e.g. a document opened to\n // share in a call): that is where it opens, not its default place.\n const openedPoppedOut = useArbiSessionState((s) => s.shell.panels.popout === panelId)\n const setPanelModeStore = useArbiSessionStore().setPanelMode\n const isSmallScreen = useIsPhone()\n const prevOpenRef = useRef(false)\n\n // The right-hand panel mirrors the left sidebar: parked in the layout\n // ('docked', which pushes content) or floating over it ('overlay', a\n // slide-out sheet + backdrop). On phones the parked split and popout windows\n // don't fit, so coerce to 'overlay' below the breakpoint \u2014 only the *default*\n // changes with screen size. Driving the *stored* mode keeps every consumer\n // consistent (slot placement + the FloatingPanel renderer all agree).\n const mode: PanelMode = isSmallScreen ? 'overlay' : panelModes[panelId] || defaultMode\n\n // Reset to the effective default when the panel opens (small screen always\n // 'overlay'), so sidebar buttons reliably bring panels back to their mode.\n useEffect(() => {\n if (isOpen && !prevOpenRef.current && !(openedPoppedOut && !isSmallScreen)) {\n setPanelModeStore(panelId, isSmallScreen ? 'overlay' : defaultMode)\n }\n prevOpenRef.current = isOpen\n }, [isOpen, panelId, defaultMode, isSmallScreen, setPanelModeStore, openedPoppedOut])\n\n // If the viewport shrinks past the breakpoint while a panel is open and still\n // parked/popout, snap it to 'overlay' so the split layout never clips.\n useEffect(() => {\n if (isSmallScreen && isOpen && panelModes[panelId] && panelModes[panelId] !== 'overlay') {\n setPanelModeStore(panelId, 'overlay')\n }\n }, [isSmallScreen, isOpen, panelId, panelModes, setPanelModeStore])\n\n const setPanelMode = useCallback(\n (newMode: PanelMode) => {\n // Mode switching is a desktop affordance; on phones everything is 'main'.\n if (isSmallScreen) return\n setPanelModeStore(panelId, newMode)\n },\n [panelId, isSmallScreen, setPanelModeStore]\n )\n\n return { mode, setPanelMode }\n}\n"],
|
|
5
|
+
"mappings": ";AAaA,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB,2BAA+C;AAItE,SAAS,oBACd,SACA,cAAyB,UACzB,SAAS,MACT;AACA,QAAM,aAAa,oBAAoB,CAAC,MAAM,EAAE,MAAM,OAAO,KAAK;AAGlE,QAAM,kBAAkB,oBAAoB,CAAC,MAAM,EAAE,MAAM,OAAO,WAAW,OAAO;AACpF,QAAM,oBAAoB,oBAAoB,EAAE;AAChD,QAAM,gBAAgB,WAAW;AACjC,QAAM,cAAc,OAAO,KAAK;AAQhC,QAAM,OAAkB,gBAAgB,YAAY,WAAW,OAAO,KAAK;AAI3E,YAAU,MAAM;AACd,QAAI,UAAU,CAAC,YAAY,WAAW,EAAE,mBAAmB,CAAC,gBAAgB;AAC1E,wBAAkB,SAAS,gBAAgB,YAAY,WAAW;AAAA,IACpE;AACA,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,QAAQ,SAAS,aAAa,eAAe,mBAAmB,eAAe,CAAC;AAIpF,YAAU,MAAM;AACd,QAAI,iBAAiB,UAAU,WAAW,OAAO,KAAK,WAAW,OAAO,MAAM,WAAW;AACvF,wBAAkB,SAAS,SAAS;AAAA,IACtC;AAAA,EACF,GAAG,CAAC,eAAe,QAAQ,SAAS,YAAY,iBAAiB,CAAC;AAElE,QAAM,eAAe;AAAA,IACnB,CAAC,YAAuB;AAEtB,UAAI,cAAe;AACnB,wBAAkB,SAAS,OAAO;AAAA,IACpC;AAAA,IACA,CAAC,SAAS,eAAe,iBAAiB;AAAA,EAC5C;AAEA,SAAO,EAAE,MAAM,aAAa;AAC9B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An image or a video while clipping for a presentation: drag over it and that area becomes a clip
|
|
3
|
+
* (of a video: from the moment on screen). A video has its own small bar (play / pause, scrub, and
|
|
4
|
+
* "Add whole frame"), since the drag area covers the picture.
|
|
5
|
+
*/
|
|
6
|
+
export interface ClippingMediaViewerProps {
|
|
7
|
+
file: Blob;
|
|
8
|
+
kind: 'image' | 'video';
|
|
9
|
+
documentId: string;
|
|
10
|
+
fileName: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function ClippingMediaViewer({ file, kind, documentId, fileName, }: ClippingMediaViewerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { Pause, Play, Plus } from "lucide-react";
|
|
5
|
+
import { Button } from "@arbidocs/react/ui";
|
|
6
|
+
import { ClipCaptureOverlay } from "../../presentation/ClipCaptureOverlay.js";
|
|
7
|
+
import { formatTime, mediaCaption } from "../../presentation/model.js";
|
|
8
|
+
import { usePresentation } from "../../presentation/store.js";
|
|
9
|
+
import { useObjectUrl } from "../../presentation/useObjectUrl.js";
|
|
10
|
+
const WHOLE = { x: 0, y: 0, w: 1, h: 1 };
|
|
11
|
+
function ClippingMediaViewer({
|
|
12
|
+
file,
|
|
13
|
+
kind,
|
|
14
|
+
documentId,
|
|
15
|
+
fileName
|
|
16
|
+
}) {
|
|
17
|
+
const url = useObjectUrl(file);
|
|
18
|
+
const videoRef = useRef(null);
|
|
19
|
+
const imageRef = useRef(null);
|
|
20
|
+
const [natural, setNatural] = useState(null);
|
|
21
|
+
const [time, setTime] = useState(0);
|
|
22
|
+
const [duration, setDuration] = useState(0);
|
|
23
|
+
const [playing, setPlaying] = useState(false);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const media = videoRef.current ?? imageRef.current;
|
|
26
|
+
if (!media || !url) return;
|
|
27
|
+
const read = () => {
|
|
28
|
+
const width = media instanceof HTMLVideoElement ? media.videoWidth : media.naturalWidth;
|
|
29
|
+
const height = media instanceof HTMLVideoElement ? media.videoHeight : media.naturalHeight;
|
|
30
|
+
if (width && height) setNatural(width / height);
|
|
31
|
+
if (media instanceof HTMLVideoElement) setDuration(media.duration || 0);
|
|
32
|
+
};
|
|
33
|
+
read();
|
|
34
|
+
const event = media instanceof HTMLVideoElement ? "loadedmetadata" : "load";
|
|
35
|
+
media.addEventListener(event, read);
|
|
36
|
+
return () => media.removeEventListener(event, read);
|
|
37
|
+
}, [url]);
|
|
38
|
+
const capture = useCallback(
|
|
39
|
+
({ rect, aspect }) => {
|
|
40
|
+
const start = kind === "video" ? videoRef.current?.currentTime ?? 0 : void 0;
|
|
41
|
+
usePresentation.getState().addClip({
|
|
42
|
+
kind,
|
|
43
|
+
documentId,
|
|
44
|
+
fileName,
|
|
45
|
+
page: 1,
|
|
46
|
+
rect,
|
|
47
|
+
aspect,
|
|
48
|
+
masks: [],
|
|
49
|
+
source: file,
|
|
50
|
+
start,
|
|
51
|
+
caption: mediaCaption(fileName, start)
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
[kind, documentId, fileName, file]
|
|
55
|
+
);
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", "data-testid": "clipping-media-viewer", children: [
|
|
57
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-border bg-muted px-3 py-1.5 text-xs text-muted-foreground", children: kind === "video" ? "Drag over the video to clip that area from this moment, or add the whole frame." : "Drag over the part of the image to show it in the presentation." }),
|
|
58
|
+
/* @__PURE__ */ jsx("div", { className: "relative min-h-0 flex-1 bg-black", style: { containerType: "size" }, children: /* @__PURE__ */ jsxs(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: "absolute inset-0 m-auto",
|
|
62
|
+
style: natural ? {
|
|
63
|
+
width: `min(100cqw, calc(100cqh * ${natural}))`,
|
|
64
|
+
height: `min(100cqh, calc(100cqw / ${natural}))`
|
|
65
|
+
} : { width: "100%", height: "100%" },
|
|
66
|
+
children: [
|
|
67
|
+
kind === "video" ? /* @__PURE__ */ jsx(
|
|
68
|
+
"video",
|
|
69
|
+
{
|
|
70
|
+
ref: videoRef,
|
|
71
|
+
src: url,
|
|
72
|
+
playsInline: true,
|
|
73
|
+
preload: "auto",
|
|
74
|
+
className: "block h-full w-full",
|
|
75
|
+
onTimeUpdate: (event) => setTime(event.currentTarget.currentTime),
|
|
76
|
+
onPlay: () => setPlaying(true),
|
|
77
|
+
onPause: () => setPlaying(false)
|
|
78
|
+
}
|
|
79
|
+
) : /* @__PURE__ */ jsx(
|
|
80
|
+
"img",
|
|
81
|
+
{
|
|
82
|
+
ref: imageRef,
|
|
83
|
+
src: url,
|
|
84
|
+
alt: fileName,
|
|
85
|
+
draggable: false,
|
|
86
|
+
className: "block h-full w-full select-none"
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
natural && /* @__PURE__ */ jsx(ClipCaptureOverlay, { page: 1, onCapture: capture })
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
) }),
|
|
93
|
+
kind === "video" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-t border-border px-3 py-1.5", children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
Button,
|
|
96
|
+
{
|
|
97
|
+
type: "button",
|
|
98
|
+
size: "icon",
|
|
99
|
+
variant: "ghost",
|
|
100
|
+
className: "size-8",
|
|
101
|
+
onClick: () => {
|
|
102
|
+
const v = videoRef.current;
|
|
103
|
+
if (!v) return;
|
|
104
|
+
if (v.paused) void v.play();
|
|
105
|
+
else v.pause();
|
|
106
|
+
},
|
|
107
|
+
"aria-label": playing ? "Pause" : "Play",
|
|
108
|
+
children: playing ? /* @__PURE__ */ jsx(Pause, { className: "size-4" }) : /* @__PURE__ */ jsx(Play, { className: "size-4" })
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
/* @__PURE__ */ jsx(
|
|
112
|
+
"input",
|
|
113
|
+
{
|
|
114
|
+
type: "range",
|
|
115
|
+
min: 0,
|
|
116
|
+
max: duration || 0,
|
|
117
|
+
step: 0.1,
|
|
118
|
+
value: time,
|
|
119
|
+
onChange: (event) => {
|
|
120
|
+
const v = videoRef.current;
|
|
121
|
+
if (v) v.currentTime = Number(event.target.value);
|
|
122
|
+
},
|
|
123
|
+
className: "min-w-0 flex-1",
|
|
124
|
+
"aria-label": "Position in the video"
|
|
125
|
+
}
|
|
126
|
+
),
|
|
127
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
|
|
128
|
+
formatTime(time),
|
|
129
|
+
" / ",
|
|
130
|
+
formatTime(duration)
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs(
|
|
133
|
+
Button,
|
|
134
|
+
{
|
|
135
|
+
type: "button",
|
|
136
|
+
size: "sm",
|
|
137
|
+
variant: "outline",
|
|
138
|
+
disabled: !natural,
|
|
139
|
+
onClick: () => natural && capture({ rect: WHOLE, aspect: natural }),
|
|
140
|
+
"data-testid": "clip-whole-frame",
|
|
141
|
+
children: [
|
|
142
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-1 size-4" }),
|
|
143
|
+
"Add whole frame"
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
] })
|
|
148
|
+
] });
|
|
149
|
+
}
|
|
150
|
+
export {
|
|
151
|
+
ClippingMediaViewer
|
|
152
|
+
};
|
|
153
|
+
//# sourceMappingURL=ClippingMediaViewer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/presentation/ClippingMediaViewer.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * An image or a video while clipping for a presentation: drag over it and that area becomes a clip\n * (of a video: from the moment on screen). A video has its own small bar (play / pause, scrub, and\n * \"Add whole frame\"), since the drag area covers the picture.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { Pause, Play, Plus } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { ClipCaptureOverlay } from '../../presentation/ClipCaptureOverlay'\nimport { formatTime, mediaCaption, type Rect } from '../../presentation/model'\nimport { usePresentation } from '../../presentation/store'\nimport { useObjectUrl } from '../../presentation/useObjectUrl'\n\nexport interface ClippingMediaViewerProps {\n file: Blob\n kind: 'image' | 'video'\n documentId: string\n fileName: string\n}\n\nconst WHOLE: Rect = { x: 0, y: 0, w: 1, h: 1 }\n\nexport function ClippingMediaViewer({\n file,\n kind,\n documentId,\n fileName,\n}: ClippingMediaViewerProps) {\n const url = useObjectUrl(file)\n const videoRef = useRef<HTMLVideoElement>(null)\n const imageRef = useRef<HTMLImageElement>(null)\n // The picture's own width / height, once known.\n const [natural, setNatural] = useState<number | null>(null)\n const [time, setTime] = useState(0)\n const [duration, setDuration] = useState(0)\n const [playing, setPlaying] = useState(false)\n\n // Its size, read as soon as it is known: at once if it already loaded (a cached file can load\n // before any handler is attached), else when it does.\n useEffect(() => {\n const media = videoRef.current ?? imageRef.current\n if (!media || !url) return\n const read = () => {\n const width = media instanceof HTMLVideoElement ? media.videoWidth : media.naturalWidth\n const height = media instanceof HTMLVideoElement ? media.videoHeight : media.naturalHeight\n if (width && height) setNatural(width / height)\n if (media instanceof HTMLVideoElement) setDuration(media.duration || 0)\n }\n read()\n const event = media instanceof HTMLVideoElement ? 'loadedmetadata' : 'load'\n media.addEventListener(event, read)\n return () => media.removeEventListener(event, read)\n }, [url])\n\n const capture = useCallback(\n ({ rect, aspect }: { rect: Rect; aspect: number }) => {\n const start = kind === 'video' ? (videoRef.current?.currentTime ?? 0) : undefined\n usePresentation.getState().addClip({\n kind,\n documentId,\n fileName,\n page: 1,\n rect,\n aspect,\n masks: [],\n source: file,\n start,\n caption: mediaCaption(fileName, start),\n })\n },\n [kind, documentId, fileName, file]\n )\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\" data-testid=\"clipping-media-viewer\">\n <div className=\"border-b border-border bg-muted px-3 py-1.5 text-xs text-muted-foreground\">\n {kind === 'video'\n ? 'Drag over the video to clip that area from this moment, or add the whole frame.'\n : 'Drag over the part of the image to show it in the presentation.'}\n </div>\n <div className=\"relative min-h-0 flex-1 bg-black\" style={{ containerType: 'size' }}>\n {/* The picture as large as fits, aspect kept; the drag area covers exactly it. */}\n <div\n className=\"absolute inset-0 m-auto\"\n style={\n natural\n ? {\n width: `min(100cqw, calc(100cqh * ${natural}))`,\n height: `min(100cqh, calc(100cqw / ${natural}))`,\n }\n : { width: '100%', height: '100%' }\n }\n >\n {kind === 'video' ? (\n <video\n ref={videoRef}\n src={url}\n playsInline\n preload=\"auto\"\n className=\"block h-full w-full\"\n onTimeUpdate={(event) => setTime(event.currentTarget.currentTime)}\n onPlay={() => setPlaying(true)}\n onPause={() => setPlaying(false)}\n />\n ) : (\n <img\n ref={imageRef}\n src={url}\n alt={fileName}\n draggable={false}\n className=\"block h-full w-full select-none\"\n />\n )}\n {natural && <ClipCaptureOverlay page={1} onCapture={capture} />}\n </div>\n </div>\n {kind === 'video' && (\n <div className=\"flex items-center gap-2 border-t border-border px-3 py-1.5\">\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n className=\"size-8\"\n onClick={() => {\n const v = videoRef.current\n if (!v) return\n if (v.paused) void v.play()\n else v.pause()\n }}\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? <Pause className=\"size-4\" /> : <Play className=\"size-4\" />}\n </Button>\n <input\n type=\"range\"\n min={0}\n max={duration || 0}\n step={0.1}\n value={time}\n onChange={(event) => {\n const v = videoRef.current\n if (v) v.currentTime = Number(event.target.value)\n }}\n className=\"min-w-0 flex-1\"\n aria-label=\"Position in the video\"\n />\n <span className=\"text-xs tabular-nums text-muted-foreground\">\n {formatTime(time)} / {formatTime(duration)}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={!natural}\n onClick={() => natural && capture({ rect: WHOLE, aspect: natural })}\n data-testid=\"clip-whole-frame\"\n >\n <Plus className=\"mr-1 size-4\" />\n Add whole frame\n </Button>\n </div>\n )}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AA4EM,cAOE,YAPF;AAtEN,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AACzD,SAAS,OAAO,MAAM,YAAY;AAClC,SAAS,cAAc;AACvB,SAAS,0BAA0B;AACnC,SAAS,YAAY,oBAA+B;AACpD,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAS7B,MAAM,QAAc,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAEtC,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,QAAM,MAAM,aAAa,IAAI;AAC7B,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,WAAW,OAAyB,IAAI;AAE9C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,IAAI;AAC1D,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,CAAC;AAClC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,CAAC;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAI5C,YAAU,MAAM;AACd,UAAM,QAAQ,SAAS,WAAW,SAAS;AAC3C,QAAI,CAAC,SAAS,CAAC,IAAK;AACpB,UAAM,OAAO,MAAM;AACjB,YAAM,QAAQ,iBAAiB,mBAAmB,MAAM,aAAa,MAAM;AAC3E,YAAM,SAAS,iBAAiB,mBAAmB,MAAM,cAAc,MAAM;AAC7E,UAAI,SAAS,OAAQ,YAAW,QAAQ,MAAM;AAC9C,UAAI,iBAAiB,iBAAkB,aAAY,MAAM,YAAY,CAAC;AAAA,IACxE;AACA,SAAK;AACL,UAAM,QAAQ,iBAAiB,mBAAmB,mBAAmB;AACrE,UAAM,iBAAiB,OAAO,IAAI;AAClC,WAAO,MAAM,MAAM,oBAAoB,OAAO,IAAI;AAAA,EACpD,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,UAAU;AAAA,IACd,CAAC,EAAE,MAAM,OAAO,MAAsC;AACpD,YAAM,QAAQ,SAAS,UAAW,SAAS,SAAS,eAAe,IAAK;AACxE,sBAAgB,SAAS,EAAE,QAAQ;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,CAAC;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,SAAS,aAAa,UAAU,KAAK;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,YAAY,UAAU,IAAI;AAAA,EACnC;AAEA,SACE,qBAAC,SAAI,WAAU,gCAA+B,eAAY,yBACxD;AAAA,wBAAC,SAAI,WAAU,6EACZ,mBAAS,UACN,oFACA,mEACN;AAAA,IACA,oBAAC,SAAI,WAAU,oCAAmC,OAAO,EAAE,eAAe,OAAO,GAE/E;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OACE,UACI;AAAA,UACE,OAAO,6BAA6B,OAAO;AAAA,UAC3C,QAAQ,6BAA6B,OAAO;AAAA,QAC9C,IACA,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA,QAGrC;AAAA,mBAAS,UACR;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,aAAW;AAAA,cACX,SAAQ;AAAA,cACR,WAAU;AAAA,cACV,cAAc,CAAC,UAAU,QAAQ,MAAM,cAAc,WAAW;AAAA,cAChE,QAAQ,MAAM,WAAW,IAAI;AAAA,cAC7B,SAAS,MAAM,WAAW,KAAK;AAAA;AAAA,UACjC,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,KAAK;AAAA,cACL,KAAK;AAAA,cACL,WAAW;AAAA,cACX,WAAU;AAAA;AAAA,UACZ;AAAA,UAED,WAAW,oBAAC,sBAAmB,MAAM,GAAG,WAAW,SAAS;AAAA;AAAA;AAAA,IAC/D,GACF;AAAA,IACC,SAAS,WACR,qBAAC,SAAI,WAAU,8DACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,WAAU;AAAA,UACV,SAAS,MAAM;AACb,kBAAM,IAAI,SAAS;AACnB,gBAAI,CAAC,EAAG;AACR,gBAAI,EAAE,OAAQ,MAAK,EAAE,KAAK;AAAA,gBACrB,GAAE,MAAM;AAAA,UACf;AAAA,UACA,cAAY,UAAU,UAAU;AAAA,UAE/B,oBAAU,oBAAC,SAAM,WAAU,UAAS,IAAK,oBAAC,QAAK,WAAU,UAAS;AAAA;AAAA,MACrE;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK,YAAY;AAAA,UACjB,MAAM;AAAA,UACN,OAAO;AAAA,UACP,UAAU,CAAC,UAAU;AACnB,kBAAM,IAAI,SAAS;AACnB,gBAAI,EAAG,GAAE,cAAc,OAAO,MAAM,OAAO,KAAK;AAAA,UAClD;AAAA,UACA,WAAU;AAAA,UACV,cAAW;AAAA;AAAA,MACb;AAAA,MACA,qBAAC,UAAK,WAAU,8CACb;AAAA,mBAAW,IAAI;AAAA,QAAE;AAAA,QAAI,WAAW,QAAQ;AAAA,SAC3C;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,UAAU,CAAC;AAAA,UACX,SAAS,MAAM,WAAW,QAAQ,EAAE,MAAM,OAAO,QAAQ,QAAQ,CAAC;AAAA,UAClE,eAAY;AAAA,UAEZ;AAAA,gCAAC,QAAK,WAAU,eAAc;AAAA,YAAE;AAAA;AAAA;AAAA,MAElC;AAAA,OACF;AAAA,KAEJ;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PDF while clipping for a presentation: drag over a page and the area becomes a clip in the
|
|
3
|
+
* presentation (and goes on the current slide while that has fewer than two).
|
|
4
|
+
*
|
|
5
|
+
* Redactions are honoured: when the version has markup, its redaction marks (all but rejected
|
|
6
|
+
* ones) are read first and every clip carries those over its area as black masks, so a redacted
|
|
7
|
+
* passage never reaches a shared screen. Clipping waits for them, and stays off if they cannot be
|
|
8
|
+
* read.
|
|
9
|
+
*/
|
|
10
|
+
import { type ComponentType } from 'react';
|
|
11
|
+
import type { PdfViewerProps } from '@arbidocs/react/viewers';
|
|
12
|
+
export interface ClippingPdfViewerProps extends Omit<PdfViewerProps, 'renderPageOverlay'> {
|
|
13
|
+
file: Blob;
|
|
14
|
+
documentId: string;
|
|
15
|
+
/** The version on screen when it is an older one. */
|
|
16
|
+
version?: number;
|
|
17
|
+
fileName: string;
|
|
18
|
+
/** The version has markup, which may hold redactions. */
|
|
19
|
+
hasMarkup: boolean;
|
|
20
|
+
viewer: ComponentType<PdfViewerProps>;
|
|
21
|
+
}
|
|
22
|
+
export declare function ClippingPdfViewer({ documentId, version, fileName, hasMarkup, viewer: Viewer, ...viewerProps }: ClippingPdfViewerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { createMarkupStore, useDocumentTools } from "@arbidocs/react/document-tools";
|
|
5
|
+
import { ClipCaptureOverlay } from "../../presentation/ClipCaptureOverlay.js";
|
|
6
|
+
import { usePresentation } from "../../presentation/store.js";
|
|
7
|
+
const NO_MASKS = { status: "ready", masks: /* @__PURE__ */ new Map() };
|
|
8
|
+
function useRedactionMasks(documentId, version, hasMarkup) {
|
|
9
|
+
const { client } = useDocumentTools();
|
|
10
|
+
const [state, setState] = useState(hasMarkup ? { status: "loading" } : NO_MASKS);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!hasMarkup) {
|
|
13
|
+
setState(NO_MASKS);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
let cancelled = false;
|
|
17
|
+
setState({ status: "loading" });
|
|
18
|
+
createMarkupStore({ version, client }).load(documentId).then((layer) => {
|
|
19
|
+
if (cancelled) return;
|
|
20
|
+
const masks = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const mark of layer.annotations) {
|
|
22
|
+
if (mark.kind !== "redaction" || mark.status === "rejected") continue;
|
|
23
|
+
masks.set(mark.page, [...masks.get(mark.page) ?? [], ...mark.rects]);
|
|
24
|
+
}
|
|
25
|
+
setState({ status: "ready", masks });
|
|
26
|
+
}).catch(() => !cancelled && setState({ status: "error" }));
|
|
27
|
+
return () => {
|
|
28
|
+
cancelled = true;
|
|
29
|
+
};
|
|
30
|
+
}, [client, documentId, version, hasMarkup]);
|
|
31
|
+
return state;
|
|
32
|
+
}
|
|
33
|
+
function Notice({ children }) {
|
|
34
|
+
return /* @__PURE__ */ jsx("div", { className: "border-b border-border bg-muted px-3 py-1.5 text-xs text-muted-foreground", children });
|
|
35
|
+
}
|
|
36
|
+
function ClippingPdfViewer({
|
|
37
|
+
documentId,
|
|
38
|
+
version,
|
|
39
|
+
fileName,
|
|
40
|
+
hasMarkup,
|
|
41
|
+
viewer: Viewer,
|
|
42
|
+
...viewerProps
|
|
43
|
+
}) {
|
|
44
|
+
const masks = useRedactionMasks(documentId, version, hasMarkup);
|
|
45
|
+
const file = viewerProps.file;
|
|
46
|
+
const capture = useCallback(
|
|
47
|
+
({ page, rect, aspect }) => {
|
|
48
|
+
if (masks.status !== "ready") return;
|
|
49
|
+
usePresentation.getState().addClip({
|
|
50
|
+
kind: "pdf",
|
|
51
|
+
documentId,
|
|
52
|
+
version,
|
|
53
|
+
fileName,
|
|
54
|
+
page,
|
|
55
|
+
rect,
|
|
56
|
+
aspect,
|
|
57
|
+
masks: masks.masks.get(page) ?? [],
|
|
58
|
+
source: file
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
[masks, documentId, version, fileName, file]
|
|
62
|
+
);
|
|
63
|
+
const renderPageOverlay = useCallback(
|
|
64
|
+
({ pageNumber }) => masks.status === "ready" ? /* @__PURE__ */ jsx(ClipCaptureOverlay, { page: pageNumber, onCapture: capture }) : null,
|
|
65
|
+
[masks.status, capture]
|
|
66
|
+
);
|
|
67
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", "data-testid": "clipping-pdf-viewer", children: [
|
|
68
|
+
/* @__PURE__ */ jsx(Notice, { children: masks.status === "loading" ? "Reading the redactions before clipping\u2026" : masks.status === "error" ? "Couldn't read this document's redactions, so it can't be clipped." : "Drag over the part of a page to show it in the presentation." }),
|
|
69
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(Viewer, { ...viewerProps, renderPageOverlay }) })
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
ClippingPdfViewer
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=ClippingPdfViewer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/presentation/ClippingPdfViewer.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The PDF while clipping for a presentation: drag over a page and the area becomes a clip in the\n * presentation (and goes on the current slide while that has fewer than two).\n *\n * Redactions are honoured: when the version has markup, its redaction marks (all but rejected\n * ones) are read first and every clip carries those over its area as black masks, so a redacted\n * passage never reaches a shared screen. Clipping waits for them, and stays off if they cannot be\n * read.\n */\n\nimport { useCallback, useEffect, useState, type ComponentType, type ReactNode } from 'react'\nimport { createMarkupStore, useDocumentTools } from '@arbidocs/react/document-tools'\nimport type { PdfViewerProps } from '@arbidocs/react/viewers'\nimport { ClipCaptureOverlay } from '../../presentation/ClipCaptureOverlay'\nimport type { Rect } from '../../presentation/model'\nimport { usePresentation } from '../../presentation/store'\n\ntype MaskState =\n | { status: 'loading' }\n | { status: 'error' }\n | { status: 'ready'; masks: ReadonlyMap<number, Rect[]> }\n\nconst NO_MASKS: MaskState = { status: 'ready', masks: new Map() }\n\n/** The version's redaction rectangles by page; none to read when it has no markup. */\nfunction useRedactionMasks(documentId: string, version: number | undefined, hasMarkup: boolean) {\n const { client } = useDocumentTools()\n const [state, setState] = useState<MaskState>(hasMarkup ? { status: 'loading' } : NO_MASKS)\n useEffect(() => {\n if (!hasMarkup) {\n setState(NO_MASKS)\n return\n }\n let cancelled = false\n setState({ status: 'loading' })\n createMarkupStore({ version, client })\n .load(documentId)\n .then((layer) => {\n if (cancelled) return\n const masks = new Map<number, Rect[]>()\n for (const mark of layer.annotations) {\n if (mark.kind !== 'redaction' || mark.status === 'rejected') continue\n masks.set(mark.page, [...(masks.get(mark.page) ?? []), ...mark.rects])\n }\n setState({ status: 'ready', masks })\n })\n .catch(() => !cancelled && setState({ status: 'error' }))\n return () => {\n cancelled = true\n }\n }, [client, documentId, version, hasMarkup])\n return state\n}\n\nexport interface ClippingPdfViewerProps extends Omit<PdfViewerProps, 'renderPageOverlay'> {\n file: Blob\n documentId: string\n /** The version on screen when it is an older one. */\n version?: number\n fileName: string\n /** The version has markup, which may hold redactions. */\n hasMarkup: boolean\n viewer: ComponentType<PdfViewerProps>\n}\n\nfunction Notice({ children }: { children: ReactNode }) {\n return (\n <div className=\"border-b border-border bg-muted px-3 py-1.5 text-xs text-muted-foreground\">\n {children}\n </div>\n )\n}\n\nexport function ClippingPdfViewer({\n documentId,\n version,\n fileName,\n hasMarkup,\n viewer: Viewer,\n ...viewerProps\n}: ClippingPdfViewerProps) {\n const masks = useRedactionMasks(documentId, version, hasMarkup)\n const file = viewerProps.file\n\n const capture = useCallback(\n ({ page, rect, aspect }: { page: number; rect: Rect; aspect: number }) => {\n if (masks.status !== 'ready') return\n usePresentation.getState().addClip({\n kind: 'pdf',\n documentId,\n version,\n fileName,\n page,\n rect,\n aspect,\n masks: masks.masks.get(page) ?? [],\n source: file,\n })\n // It joins the presentation's tray (the viewer's Presentation pill counts it).\n },\n [masks, documentId, version, fileName, file]\n )\n\n const renderPageOverlay = useCallback(\n ({ pageNumber }: { pageNumber: number }) =>\n masks.status === 'ready' ? (\n <ClipCaptureOverlay page={pageNumber} onCapture={capture} />\n ) : null,\n [masks.status, capture]\n )\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\" data-testid=\"clipping-pdf-viewer\">\n <Notice>\n {masks.status === 'loading'\n ? 'Reading the redactions before clipping\u2026'\n : masks.status === 'error'\n ? \"Couldn't read this document's redactions, so it can't be clipped.\"\n : 'Drag over the part of a page to show it in the presentation.'}\n </Notice>\n <div className=\"min-h-0 flex-1\">\n <Viewer {...viewerProps} renderPageOverlay={renderPageOverlay} />\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAmEI,cA6CA,YA7CA;AAzDJ,SAAS,aAAa,WAAW,gBAAoD;AACrF,SAAS,mBAAmB,wBAAwB;AAEpD,SAAS,0BAA0B;AAEnC,SAAS,uBAAuB;AAOhC,MAAM,WAAsB,EAAE,QAAQ,SAAS,OAAO,oBAAI,IAAI,EAAE;AAGhE,SAAS,kBAAkB,YAAoB,SAA6B,WAAoB;AAC9F,QAAM,EAAE,OAAO,IAAI,iBAAiB;AACpC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB,YAAY,EAAE,QAAQ,UAAU,IAAI,QAAQ;AAC1F,YAAU,MAAM;AACd,QAAI,CAAC,WAAW;AACd,eAAS,QAAQ;AACjB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,aAAS,EAAE,QAAQ,UAAU,CAAC;AAC9B,sBAAkB,EAAE,SAAS,OAAO,CAAC,EAClC,KAAK,UAAU,EACf,KAAK,CAAC,UAAU;AACf,UAAI,UAAW;AACf,YAAM,QAAQ,oBAAI,IAAoB;AACtC,iBAAW,QAAQ,MAAM,aAAa;AACpC,YAAI,KAAK,SAAS,eAAe,KAAK,WAAW,WAAY;AAC7D,cAAM,IAAI,KAAK,MAAM,CAAC,GAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,GAAI,GAAG,KAAK,KAAK,CAAC;AAAA,MACvE;AACA,eAAS,EAAE,QAAQ,SAAS,MAAM,CAAC;AAAA,IACrC,CAAC,EACA,MAAM,MAAM,CAAC,aAAa,SAAS,EAAE,QAAQ,QAAQ,CAAC,CAAC;AAC1D,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,SAAS,SAAS,CAAC;AAC3C,SAAO;AACT;AAaA,SAAS,OAAO,EAAE,SAAS,GAA4B;AACrD,SACE,oBAAC,SAAI,WAAU,6EACZ,UACH;AAEJ;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,GAAG;AACL,GAA2B;AACzB,QAAM,QAAQ,kBAAkB,YAAY,SAAS,SAAS;AAC9D,QAAM,OAAO,YAAY;AAEzB,QAAM,UAAU;AAAA,IACd,CAAC,EAAE,MAAM,MAAM,OAAO,MAAoD;AACxE,UAAI,MAAM,WAAW,QAAS;AAC9B,sBAAgB,SAAS,EAAE,QAAQ;AAAA,QACjC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,MAAM,MAAM,IAAI,IAAI,KAAK,CAAC;AAAA,QACjC,QAAQ;AAAA,MACV,CAAC;AAAA,IAEH;AAAA,IACA,CAAC,OAAO,YAAY,SAAS,UAAU,IAAI;AAAA,EAC7C;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,EAAE,WAAW,MACZ,MAAM,WAAW,UACf,oBAAC,sBAAmB,MAAM,YAAY,WAAW,SAAS,IACxD;AAAA,IACN,CAAC,MAAM,QAAQ,OAAO;AAAA,EACxB;AAEA,SACE,qBAAC,SAAI,WAAU,gCAA+B,eAAY,uBACxD;AAAA,wBAAC,UACE,gBAAM,WAAW,YACd,iDACA,MAAM,WAAW,UACf,sEACA,gEACR;AAAA,IACA,oBAAC,SAAI,WAAU,kBACb,8BAAC,UAAQ,GAAG,aAAa,mBAAsC,GACjE;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The presentation's own window, mounted once by the app shell (the session's `PRESENTATION_PANEL`,
|
|
3
|
+
* a pop-out). It presents: the slides alone, what is shared in a call or put full screen; or, when
|
|
4
|
+
* the editor is popped out of the viewer's slides tab, it edits there, beside the documents its
|
|
5
|
+
* clips come from. A window opened only to present closes when presenting ends.
|
|
6
|
+
*
|
|
7
|
+
* It also keeps what the presentation needs wherever it is edited: the theme's logo image, read
|
|
8
|
+
* when the logo changes; and a clean slate when the session signs out or another user signs in
|
|
9
|
+
* (the presentation holds decrypted files in memory).
|
|
10
|
+
*/
|
|
11
|
+
/** The presentation's window, with the document tools it needs (sources, redactions). */
|
|
12
|
+
export declare function ConnectedPresentation(): import("react").JSX.Element;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import { PanelLeftClose } from "lucide-react";
|
|
5
|
+
import {
|
|
6
|
+
isPanelOpen,
|
|
7
|
+
useArbiSession,
|
|
8
|
+
useArbiSessionState,
|
|
9
|
+
useArbiSessionStore
|
|
10
|
+
} from "@arbidocs/react";
|
|
11
|
+
import { Button } from "@arbidocs/react/ui";
|
|
12
|
+
import { ConnectedPanelHost } from "../panels/ConnectedPanelHost.js";
|
|
13
|
+
import { ConnectedDocumentToolsProvider } from "../viewer/ConnectedDocumentToolsProvider.js";
|
|
14
|
+
import { PRESENTATION_PANEL, presentationWindowOnlyPresents } from "../../presentation/panel-id.js";
|
|
15
|
+
import { PresenterView } from "../../presentation/PresenterView.js";
|
|
16
|
+
import { usePresentation } from "../../presentation/store.js";
|
|
17
|
+
import { usePresentationController } from "./usePresentationController.js";
|
|
18
|
+
import { usePresentationFiles } from "./usePresentationFiles.js";
|
|
19
|
+
function ConnectedPresentation() {
|
|
20
|
+
return /* @__PURE__ */ jsx(ConnectedDocumentToolsProvider, { children: /* @__PURE__ */ jsx(PresentationWindow, {}) });
|
|
21
|
+
}
|
|
22
|
+
function PresentationWindow() {
|
|
23
|
+
const session = useArbiSessionStore();
|
|
24
|
+
const notify = usePresentation((s) => s.notify);
|
|
25
|
+
const presenting = usePresentation((s) => s.presenting);
|
|
26
|
+
const isOpen = useArbiSessionState((state) => isPanelOpen(state, PRESENTATION_PANEL));
|
|
27
|
+
const { user } = useArbiSession();
|
|
28
|
+
const userId = user?.external_id ?? null;
|
|
29
|
+
const shownFor = useRef(userId);
|
|
30
|
+
const { downloadFile } = usePresentationFiles();
|
|
31
|
+
const logoId = usePresentation((s) => s.theme.logo?.documentId ?? null);
|
|
32
|
+
const controller = usePresentationController(isOpen && !presenting);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (shownFor.current === userId) return;
|
|
35
|
+
shownFor.current = userId;
|
|
36
|
+
usePresentation.getState().reset();
|
|
37
|
+
session.closePanel(PRESENTATION_PANEL);
|
|
38
|
+
}, [userId, session]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!logoId) return;
|
|
41
|
+
let current = true;
|
|
42
|
+
downloadFile(logoId).then((image) => current && usePresentation.getState().setLogoImage(image)).catch(() => current && notify("The logo could not be read", "error"));
|
|
43
|
+
return () => {
|
|
44
|
+
current = false;
|
|
45
|
+
};
|
|
46
|
+
}, [logoId, downloadFile, notify]);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!isOpen) usePresentation.getState().setPresenting(false);
|
|
49
|
+
}, [isOpen]);
|
|
50
|
+
const wasPresenting = useRef(presenting);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (wasPresenting.current && !presenting && isOpen && presentationWindowOnlyPresents()) {
|
|
53
|
+
session.closePanel(PRESENTATION_PANEL);
|
|
54
|
+
}
|
|
55
|
+
wasPresenting.current = presenting;
|
|
56
|
+
}, [presenting, isOpen, session]);
|
|
57
|
+
const onClose = useCallback(() => session.closePanel(PRESENTATION_PANEL), [session]);
|
|
58
|
+
return /* @__PURE__ */ jsx(
|
|
59
|
+
ConnectedPanelHost,
|
|
60
|
+
{
|
|
61
|
+
panelId: PRESENTATION_PANEL,
|
|
62
|
+
isOpen,
|
|
63
|
+
onClose,
|
|
64
|
+
title: "Presentation",
|
|
65
|
+
defaultMode: "popout",
|
|
66
|
+
defaultWidth: 960,
|
|
67
|
+
closeTestId: "presentation-panel-close",
|
|
68
|
+
children: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
+
!presenting && controller.dialogs,
|
|
70
|
+
/* @__PURE__ */ jsx(
|
|
71
|
+
PresenterView,
|
|
72
|
+
{
|
|
73
|
+
...controller.editor,
|
|
74
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
75
|
+
controller.editor.actions,
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
Button,
|
|
78
|
+
{
|
|
79
|
+
type: "button",
|
|
80
|
+
size: "icon",
|
|
81
|
+
variant: "ghost",
|
|
82
|
+
className: "size-8 text-muted-foreground hover:text-foreground pointer-coarse:size-11",
|
|
83
|
+
title: "Back into the app's viewer",
|
|
84
|
+
"aria-label": "Back to the viewer",
|
|
85
|
+
onClick: onClose,
|
|
86
|
+
"data-testid": "presentation-pop-in",
|
|
87
|
+
children: /* @__PURE__ */ jsx(PanelLeftClose, { className: "size-4" })
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
] })
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
] })
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
ConnectedPresentation
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=ConnectedPresentation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/presentation/ConnectedPresentation.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The presentation's own window, mounted once by the app shell (the session's `PRESENTATION_PANEL`,\n * a pop-out). It presents: the slides alone, what is shared in a call or put full screen; or, when\n * the editor is popped out of the viewer's slides tab, it edits there, beside the documents its\n * clips come from. A window opened only to present closes when presenting ends.\n *\n * It also keeps what the presentation needs wherever it is edited: the theme's logo image, read\n * when the logo changes; and a clean slate when the session signs out or another user signs in\n * (the presentation holds decrypted files in memory).\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport { PanelLeftClose } from 'lucide-react'\nimport {\n isPanelOpen,\n useArbiSession,\n useArbiSessionState,\n useArbiSessionStore,\n} from '@arbidocs/react'\nimport { Button } from '@arbidocs/react/ui'\nimport { ConnectedPanelHost } from '../panels/ConnectedPanelHost'\nimport { ConnectedDocumentToolsProvider } from '../viewer/ConnectedDocumentToolsProvider'\nimport { PRESENTATION_PANEL, presentationWindowOnlyPresents } from '../../presentation/panel-id'\nimport { PresenterView } from '../../presentation/PresenterView'\nimport { usePresentation } from '../../presentation/store'\nimport { usePresentationController } from './usePresentationController'\nimport { usePresentationFiles } from './usePresentationFiles'\n\n/** The presentation's window, with the document tools it needs (sources, redactions). */\nexport function ConnectedPresentation() {\n return (\n <ConnectedDocumentToolsProvider>\n <PresentationWindow />\n </ConnectedDocumentToolsProvider>\n )\n}\n\nfunction PresentationWindow() {\n const session = useArbiSessionStore()\n const notify = usePresentation((s) => s.notify)\n const presenting = usePresentation((s) => s.presenting)\n const isOpen = useArbiSessionState((state) => isPanelOpen(state, PRESENTATION_PANEL))\n const { user } = useArbiSession()\n const userId = user?.external_id ?? null\n const shownFor = useRef(userId)\n const { downloadFile } = usePresentationFiles()\n const logoId = usePresentation((s) => s.theme.logo?.documentId ?? null)\n const controller = usePresentationController(isOpen && !presenting)\n\n useEffect(() => {\n if (shownFor.current === userId) return\n shownFor.current = userId\n usePresentation.getState().reset()\n session.closePanel(PRESENTATION_PANEL)\n }, [userId, session])\n\n // The theme's logo image, fetched whenever the logo changes (the theme keeps a reference only).\n useEffect(() => {\n if (!logoId) return\n let current = true\n downloadFile(logoId)\n .then((image) => current && usePresentation.getState().setLogoImage(image))\n .catch(() => current && notify('The logo could not be read', 'error'))\n return () => {\n current = false\n }\n }, [logoId, downloadFile, notify])\n\n // A closed window is not presenting.\n useEffect(() => {\n if (!isOpen) usePresentation.getState().setPresenting(false)\n }, [isOpen])\n\n // Opened only to present: closed when presenting ends (Escape).\n const wasPresenting = useRef(presenting)\n useEffect(() => {\n if (wasPresenting.current && !presenting && isOpen && presentationWindowOnlyPresents()) {\n session.closePanel(PRESENTATION_PANEL)\n }\n wasPresenting.current = presenting\n }, [presenting, isOpen, session])\n\n const onClose = useCallback(() => session.closePanel(PRESENTATION_PANEL), [session])\n\n return (\n <ConnectedPanelHost\n panelId={PRESENTATION_PANEL}\n isOpen={isOpen}\n onClose={onClose}\n title=\"Presentation\"\n defaultMode=\"popout\"\n defaultWidth={960}\n closeTestId=\"presentation-panel-close\"\n >\n {/* Inside the panel, so its dialogs open in its window. */}\n {() => (\n <>\n {!presenting && controller.dialogs}\n <PresenterView\n {...controller.editor}\n actions={\n <>\n {controller.editor.actions}\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"ghost\"\n className=\"size-8 text-muted-foreground hover:text-foreground pointer-coarse:size-11\"\n title=\"Back into the app's viewer\"\n aria-label=\"Back to the viewer\"\n onClick={onClose}\n data-testid=\"presentation-pop-in\"\n >\n <PanelLeftClose className=\"size-4\" />\n </Button>\n </>\n }\n />\n </>\n )}\n </ConnectedPanelHost>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgCM,SAqEQ,UArER,KAqEQ,YArER;AArBN,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,0BAA0B;AACnC,SAAS,sCAAsC;AAC/C,SAAS,oBAAoB,sCAAsC;AACnE,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,iCAAiC;AAC1C,SAAS,4BAA4B;AAG9B,SAAS,wBAAwB;AACtC,SACE,oBAAC,kCACC,8BAAC,sBAAmB,GACtB;AAEJ;AAEA,SAAS,qBAAqB;AAC5B,QAAM,UAAU,oBAAoB;AACpC,QAAM,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM;AAC9C,QAAM,aAAa,gBAAgB,CAAC,MAAM,EAAE,UAAU;AACtD,QAAM,SAAS,oBAAoB,CAAC,UAAU,YAAY,OAAO,kBAAkB,CAAC;AACpF,QAAM,EAAE,KAAK,IAAI,eAAe;AAChC,QAAM,SAAS,MAAM,eAAe;AACpC,QAAM,WAAW,OAAO,MAAM;AAC9B,QAAM,EAAE,aAAa,IAAI,qBAAqB;AAC9C,QAAM,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,MAAM,cAAc,IAAI;AACtE,QAAM,aAAa,0BAA0B,UAAU,CAAC,UAAU;AAElE,YAAU,MAAM;AACd,QAAI,SAAS,YAAY,OAAQ;AACjC,aAAS,UAAU;AACnB,oBAAgB,SAAS,EAAE,MAAM;AACjC,YAAQ,WAAW,kBAAkB;AAAA,EACvC,GAAG,CAAC,QAAQ,OAAO,CAAC;AAGpB,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,QAAI,UAAU;AACd,iBAAa,MAAM,EAChB,KAAK,CAAC,UAAU,WAAW,gBAAgB,SAAS,EAAE,aAAa,KAAK,CAAC,EACzE,MAAM,MAAM,WAAW,OAAO,8BAA8B,OAAO,CAAC;AACvE,WAAO,MAAM;AACX,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,QAAQ,cAAc,MAAM,CAAC;AAGjC,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ,iBAAgB,SAAS,EAAE,cAAc,KAAK;AAAA,EAC7D,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,gBAAgB,OAAO,UAAU;AACvC,YAAU,MAAM;AACd,QAAI,cAAc,WAAW,CAAC,cAAc,UAAU,+BAA+B,GAAG;AACtF,cAAQ,WAAW,kBAAkB;AAAA,IACvC;AACA,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,YAAY,QAAQ,OAAO,CAAC;AAEhC,QAAM,UAAU,YAAY,MAAM,QAAQ,WAAW,kBAAkB,GAAG,CAAC,OAAO,CAAC;AAEnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,cAAc;AAAA,MACd,aAAY;AAAA,MAGX,gBACC,iCACG;AAAA,SAAC,cAAc,WAAW;AAAA,QAC3B;AAAA,UAAC;AAAA;AAAA,YACE,GAAG,WAAW;AAAA,YACf,SACE,iCACG;AAAA,yBAAW,OAAO;AAAA,cACnB;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,OAAM;AAAA,kBACN,cAAW;AAAA,kBACX,SAAS;AAAA,kBACT,eAAY;AAAA,kBAEZ,8BAAC,kBAAe,WAAU,UAAS;AAAA;AAAA,cACrC;AAAA,eACF;AAAA;AAAA,QAEJ;AAAA,SACF;AAAA;AAAA,EAEJ;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A presentation's slides tab in the document viewer: the slides editor, on the presentation the
|
|
3
|
+
* viewer shows. Opening a saved presentation loads it (unless it is the one being edited); a new
|
|
4
|
+
* one (a presentation draft) takes the clips gathered so far. Clips gathered with no presentation
|
|
5
|
+
* open join the one opened next. Saving a draft makes it a document, and the tab moves to it.
|
|
6
|
+
*
|
|
7
|
+
* The editor can also move to the presentation's own window (Pop out), beside the documents its
|
|
8
|
+
* clips come from; the tab then says so. Present opens that window with the slides alone.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConnectedSlidesTabProps {
|
|
11
|
+
/** The viewed document's id, or a presentation draft's (`draft-…`). */
|
|
12
|
+
documentId: string;
|
|
13
|
+
/** The version on screen, when an older one. */
|
|
14
|
+
version?: number;
|
|
15
|
+
/** The document's current version: a newer one than the one being edited is opened. */
|
|
16
|
+
currentVersion?: number;
|
|
17
|
+
/** A new presentation, not saved yet: its draft title. */
|
|
18
|
+
draftTitle?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function ConnectedSlidesTab({ documentId, version, currentVersion, draftTitle, }: ConnectedSlidesTabProps): import("react").JSX.Element;
|