@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
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const BRAND = "brand";
|
|
3
|
+
const DEFAULT_THEME = {
|
|
4
|
+
background: BRAND,
|
|
5
|
+
font: "sans",
|
|
6
|
+
accent: BRAND,
|
|
7
|
+
logo: null
|
|
8
|
+
};
|
|
9
|
+
const BACKGROUNDS = [
|
|
10
|
+
// The app's primary colour, read from its tokens when drawn (`brandColors`).
|
|
11
|
+
{ id: BRAND, label: "Brand", from: "", to: "", glow: 0.1 },
|
|
12
|
+
{ id: "graphite", label: "Graphite", from: "#2b3038", to: "#0c0e11", glow: 0.09 },
|
|
13
|
+
{ id: "midnight", label: "Midnight", from: "#17294a", to: "#050a15", glow: 0.1 },
|
|
14
|
+
{ id: "oxford", label: "Oxford", from: "#123d45", to: "#04141a", glow: 0.08 },
|
|
15
|
+
{ id: "claret", label: "Claret", from: "#4b1526", to: "#110409", glow: 0.08 },
|
|
16
|
+
{ id: "linen", label: "Linen", from: "#2a2b30", to: "#111215", glow: 0.06, texture: "linen" },
|
|
17
|
+
{ id: "onyx", label: "Onyx", from: "#000000", to: "#000000", glow: 0 }
|
|
18
|
+
];
|
|
19
|
+
const FONTS = {
|
|
20
|
+
sans: {
|
|
21
|
+
label: "Modern",
|
|
22
|
+
css: 'Calibri, Carlito, "Segoe UI", "Helvetica Neue", Arial, sans-serif',
|
|
23
|
+
pptx: "Calibri"
|
|
24
|
+
},
|
|
25
|
+
serif: {
|
|
26
|
+
label: "Editorial",
|
|
27
|
+
css: 'Georgia, Gelasio, "Times New Roman", serif',
|
|
28
|
+
pptx: "Georgia"
|
|
29
|
+
},
|
|
30
|
+
classic: {
|
|
31
|
+
label: "Classic",
|
|
32
|
+
css: 'Garamond, "EB Garamond", "Cormorant Garamond", "Times New Roman", serif',
|
|
33
|
+
pptx: "Garamond"
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const ACCENTS = [
|
|
37
|
+
{ label: "Brand", color: BRAND },
|
|
38
|
+
{ label: "Gold", color: "#c9a96e" },
|
|
39
|
+
{ label: "Teal", color: "#4fb3bf" },
|
|
40
|
+
{ label: "Blue", color: "#6b9bf2" },
|
|
41
|
+
{ label: "Coral", color: "#e57a6e" },
|
|
42
|
+
{ label: "Silver", color: "#cfd4dc" }
|
|
43
|
+
];
|
|
44
|
+
const TEXT_COLORS = { title: "#ffffff", body: "#e6e8ec", muted: "#aab0ba" };
|
|
45
|
+
const HEX = /^#[0-9a-f]{6}$/i;
|
|
46
|
+
const isHexColor = (value) => HEX.test(value);
|
|
47
|
+
function mix(hex, toward, amount) {
|
|
48
|
+
const channel = (i) => {
|
|
49
|
+
const value = parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16);
|
|
50
|
+
return Math.round(value + (toward - value) * amount).toString(16).padStart(2, "0");
|
|
51
|
+
};
|
|
52
|
+
return `#${channel(0)}${channel(1)}${channel(2)}`;
|
|
53
|
+
}
|
|
54
|
+
const BRAND_TOKENS = { primary: "229.85 50.43% 25.29%", secondary: "195 100% 47%" };
|
|
55
|
+
function hslToHex(h, s, l) {
|
|
56
|
+
const k = (n) => (n + h / 30) % 12;
|
|
57
|
+
const a = s * Math.min(l, 1 - l);
|
|
58
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
59
|
+
return `#${[f(0), f(8), f(4)].map(
|
|
60
|
+
(x) => Math.round(x * 255).toString(16).padStart(2, "0")
|
|
61
|
+
).join("")}`;
|
|
62
|
+
}
|
|
63
|
+
function readToken(name, fallback) {
|
|
64
|
+
const value = typeof document !== "undefined" && getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
|
|
65
|
+
const [h, s, l] = value.split(/\s+/).map((part) => parseFloat(part));
|
|
66
|
+
return [h, s / 100, l / 100];
|
|
67
|
+
}
|
|
68
|
+
let brand = null;
|
|
69
|
+
function brandColors() {
|
|
70
|
+
if (brand) return brand;
|
|
71
|
+
const [ph, ps, pl] = readToken("--primary", BRAND_TOKENS.primary);
|
|
72
|
+
const [sh, ss, sl] = readToken("--secondary", BRAND_TOKENS.secondary);
|
|
73
|
+
brand = { primary: hslToHex(ph, ps, Math.min(pl, 0.3)), secondary: hslToHex(sh, ss, sl) };
|
|
74
|
+
return brand;
|
|
75
|
+
}
|
|
76
|
+
const accentColor = (accent) => accent === BRAND ? brandColors().secondary : accent;
|
|
77
|
+
function backgroundSpec(background) {
|
|
78
|
+
if (background === BRAND) {
|
|
79
|
+
const { primary } = brandColors();
|
|
80
|
+
return { from: mix(primary, 255, 0.05), to: mix(primary, 0, 0.6), glow: 0.1 };
|
|
81
|
+
}
|
|
82
|
+
const preset = BACKGROUNDS.find((entry) => entry.id === background);
|
|
83
|
+
if (preset) return preset;
|
|
84
|
+
if (isHexColor(background)) {
|
|
85
|
+
return { from: mix(background, 255, 0.06), to: mix(background, 0, 0.62), glow: 0.08 };
|
|
86
|
+
}
|
|
87
|
+
return backgroundSpec(BRAND);
|
|
88
|
+
}
|
|
89
|
+
function backgroundCss(background) {
|
|
90
|
+
const spec = backgroundSpec(background);
|
|
91
|
+
const layers = [];
|
|
92
|
+
if (spec.glow > 0) {
|
|
93
|
+
layers.push(
|
|
94
|
+
`radial-gradient(120% 90% at 12% -10%, rgba(255,255,255,${spec.glow}), transparent 60%)`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (spec.texture === "linen") {
|
|
98
|
+
layers.push(
|
|
99
|
+
"repeating-linear-gradient(45deg, rgba(255,255,255,0.025) 0 0.06cqw, transparent 0.06cqw 0.32cqw)",
|
|
100
|
+
"repeating-linear-gradient(-45deg, rgba(255,255,255,0.02) 0 0.06cqw, transparent 0.06cqw 0.32cqw)"
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
layers.push(`linear-gradient(155deg, ${spec.from} 0%, ${spec.to} 100%)`);
|
|
104
|
+
return layers.join(", ");
|
|
105
|
+
}
|
|
106
|
+
function paintBackground(context, width, height, background) {
|
|
107
|
+
const spec = backgroundSpec(background);
|
|
108
|
+
const angle = 155 * Math.PI / 180;
|
|
109
|
+
const dx = Math.sin(angle);
|
|
110
|
+
const dy = -Math.cos(angle);
|
|
111
|
+
const length = Math.abs(width * dx) + Math.abs(height * dy);
|
|
112
|
+
const cx = width / 2;
|
|
113
|
+
const cy = height / 2;
|
|
114
|
+
const gradient = context.createLinearGradient(
|
|
115
|
+
cx - dx * length / 2,
|
|
116
|
+
cy - dy * length / 2,
|
|
117
|
+
cx + dx * length / 2,
|
|
118
|
+
cy + dy * length / 2
|
|
119
|
+
);
|
|
120
|
+
gradient.addColorStop(0, spec.from);
|
|
121
|
+
gradient.addColorStop(1, spec.to);
|
|
122
|
+
context.fillStyle = gradient;
|
|
123
|
+
context.fillRect(0, 0, width, height);
|
|
124
|
+
if (spec.texture === "linen") {
|
|
125
|
+
const step = width * 32e-4;
|
|
126
|
+
context.save();
|
|
127
|
+
context.lineWidth = width * 6e-4;
|
|
128
|
+
for (const [direction, alpha] of [
|
|
129
|
+
[1, 0.025],
|
|
130
|
+
[-1, 0.02]
|
|
131
|
+
]) {
|
|
132
|
+
context.strokeStyle = `rgba(255,255,255,${alpha})`;
|
|
133
|
+
context.beginPath();
|
|
134
|
+
for (let offset = -height; offset < width + height; offset += step) {
|
|
135
|
+
context.moveTo(offset, direction === 1 ? height : 0);
|
|
136
|
+
context.lineTo(offset + height, direction === 1 ? 0 : height);
|
|
137
|
+
}
|
|
138
|
+
context.stroke();
|
|
139
|
+
}
|
|
140
|
+
context.restore();
|
|
141
|
+
}
|
|
142
|
+
if (spec.glow > 0) {
|
|
143
|
+
const rx = width * 1.2;
|
|
144
|
+
const ry = height * 0.9;
|
|
145
|
+
context.save();
|
|
146
|
+
context.translate(width * 0.12, -height * 0.1);
|
|
147
|
+
context.scale(rx, ry);
|
|
148
|
+
const glow = context.createRadialGradient(0, 0, 0, 0, 0, 1);
|
|
149
|
+
glow.addColorStop(0, `rgba(255,255,255,${spec.glow})`);
|
|
150
|
+
glow.addColorStop(0.6, "rgba(255,255,255,0)");
|
|
151
|
+
context.fillStyle = glow;
|
|
152
|
+
context.fillRect(-1, -1, 2, 2);
|
|
153
|
+
context.restore();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const CLIP_EDGE_SOLID = 2e-3;
|
|
157
|
+
const CLIP_EDGE_FADE = 9e-3;
|
|
158
|
+
const CLIP_EDGE_MAX = 0.08;
|
|
159
|
+
function clipEdgeCss() {
|
|
160
|
+
const solid = `min(${CLIP_EDGE_SOLID * 100}cqw, ${CLIP_EDGE_MAX * 25}%)`;
|
|
161
|
+
const fade = `min(${CLIP_EDGE_FADE * 100}cqw, ${CLIP_EDGE_MAX * 100}%)`;
|
|
162
|
+
return ["to right", "to left", "to bottom", "to top"].map(
|
|
163
|
+
(direction) => `linear-gradient(${direction}, #fff 0, #fff ${solid}, rgba(255,255,255,0) ${fade})`
|
|
164
|
+
).join(", ");
|
|
165
|
+
}
|
|
166
|
+
function paintClipEdge(context, box, stageWidth) {
|
|
167
|
+
const sides = [
|
|
168
|
+
{ length: box.width, from: [box.x, 0], to: [box.x + 1, 0] },
|
|
169
|
+
{ length: box.width, from: [box.x + box.width, 0], to: [box.x + box.width - 1, 0] },
|
|
170
|
+
{ length: box.height, from: [0, box.y], to: [0, box.y + 1] },
|
|
171
|
+
{ length: box.height, from: [0, box.y + box.height], to: [0, box.y + box.height - 1] }
|
|
172
|
+
];
|
|
173
|
+
for (const side of sides) {
|
|
174
|
+
const fade = Math.min(CLIP_EDGE_FADE * stageWidth, CLIP_EDGE_MAX * side.length);
|
|
175
|
+
const solid = Math.min(CLIP_EDGE_SOLID * stageWidth, CLIP_EDGE_MAX * 0.25 * side.length);
|
|
176
|
+
const [fx, fy] = side.from;
|
|
177
|
+
const [tx, ty] = side.to;
|
|
178
|
+
const gradient = context.createLinearGradient(
|
|
179
|
+
fx,
|
|
180
|
+
fy,
|
|
181
|
+
fx + (tx - fx) * fade,
|
|
182
|
+
fy + (ty - fy) * fade
|
|
183
|
+
);
|
|
184
|
+
gradient.addColorStop(0, "rgba(255,255,255,1)");
|
|
185
|
+
gradient.addColorStop(Math.min(1, solid / fade), "rgba(255,255,255,1)");
|
|
186
|
+
gradient.addColorStop(1, "rgba(255,255,255,0)");
|
|
187
|
+
context.fillStyle = gradient;
|
|
188
|
+
context.fillRect(box.x, box.y, box.width, box.height);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function slideBackgroundCss(background, media) {
|
|
192
|
+
const image = background.image ? media[background.image] : void 0;
|
|
193
|
+
if (image) return `center / cover no-repeat url("${image}")`;
|
|
194
|
+
if (background.gradient) {
|
|
195
|
+
const { angle, from, to } = background.gradient;
|
|
196
|
+
return `linear-gradient(${angle}deg, ${from}, ${to})`;
|
|
197
|
+
}
|
|
198
|
+
return background.color ?? "#ffffff";
|
|
199
|
+
}
|
|
200
|
+
async function paintSlideBackground(context, width, height, background, media) {
|
|
201
|
+
const image = background.image ? media[background.image] : void 0;
|
|
202
|
+
if (image) {
|
|
203
|
+
const picture = new Image();
|
|
204
|
+
picture.src = image;
|
|
205
|
+
await picture.decode();
|
|
206
|
+
const scale = Math.max(width / picture.width, height / picture.height);
|
|
207
|
+
const w = picture.width * scale;
|
|
208
|
+
const h = picture.height * scale;
|
|
209
|
+
context.drawImage(picture, (width - w) / 2, (height - h) / 2, w, h);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (background.gradient) {
|
|
213
|
+
const { angle, from, to } = background.gradient;
|
|
214
|
+
const radians = angle * Math.PI / 180;
|
|
215
|
+
const dx = Math.sin(radians);
|
|
216
|
+
const dy = -Math.cos(radians);
|
|
217
|
+
const length = Math.abs(width * dx) + Math.abs(height * dy);
|
|
218
|
+
const gradient = context.createLinearGradient(
|
|
219
|
+
width / 2 - dx * length / 2,
|
|
220
|
+
height / 2 - dy * length / 2,
|
|
221
|
+
width / 2 + dx * length / 2,
|
|
222
|
+
height / 2 + dy * length / 2
|
|
223
|
+
);
|
|
224
|
+
gradient.addColorStop(0, from);
|
|
225
|
+
gradient.addColorStop(1, to);
|
|
226
|
+
context.fillStyle = gradient;
|
|
227
|
+
} else {
|
|
228
|
+
context.fillStyle = background.color ?? "#ffffff";
|
|
229
|
+
}
|
|
230
|
+
context.fillRect(0, 0, width, height);
|
|
231
|
+
}
|
|
232
|
+
function isLightBackground(background) {
|
|
233
|
+
const color = background?.gradient?.from ?? background?.color;
|
|
234
|
+
if (!color || !isHexColor(color)) return false;
|
|
235
|
+
const n = parseInt(color.slice(1), 16);
|
|
236
|
+
const luminance = 0.2126 * (n >> 16 & 255) + 0.7152 * (n >> 8 & 255) + 0.0722 * (n & 255);
|
|
237
|
+
return luminance > 150;
|
|
238
|
+
}
|
|
239
|
+
function parseTheme(value) {
|
|
240
|
+
const data = value ?? {};
|
|
241
|
+
const logo = data.logo;
|
|
242
|
+
return {
|
|
243
|
+
background: typeof data.background === "string" && (BACKGROUNDS.some((entry) => entry.id === data.background) || isHexColor(data.background)) ? data.background : DEFAULT_THEME.background,
|
|
244
|
+
font: data.font && data.font in FONTS ? data.font : DEFAULT_THEME.font,
|
|
245
|
+
accent: typeof data.accent === "string" && (isHexColor(data.accent) || data.accent === BRAND) ? data.accent : DEFAULT_THEME.accent,
|
|
246
|
+
logo: logo && typeof logo.documentId === "string" ? {
|
|
247
|
+
documentId: logo.documentId,
|
|
248
|
+
fileName: typeof logo.fileName === "string" ? logo.fileName : "",
|
|
249
|
+
corner: logo.corner === "bl" ? "bl" : "br"
|
|
250
|
+
} : null
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
export {
|
|
254
|
+
ACCENTS,
|
|
255
|
+
BACKGROUNDS,
|
|
256
|
+
BRAND,
|
|
257
|
+
CLIP_EDGE_FADE,
|
|
258
|
+
CLIP_EDGE_MAX,
|
|
259
|
+
CLIP_EDGE_SOLID,
|
|
260
|
+
DEFAULT_THEME,
|
|
261
|
+
FONTS,
|
|
262
|
+
TEXT_COLORS,
|
|
263
|
+
accentColor,
|
|
264
|
+
backgroundCss,
|
|
265
|
+
backgroundSpec,
|
|
266
|
+
brandColors,
|
|
267
|
+
clipEdgeCss,
|
|
268
|
+
isHexColor,
|
|
269
|
+
isLightBackground,
|
|
270
|
+
paintBackground,
|
|
271
|
+
paintClipEdge,
|
|
272
|
+
paintSlideBackground,
|
|
273
|
+
parseTheme,
|
|
274
|
+
slideBackgroundCss
|
|
275
|
+
};
|
|
276
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/presentation/theme.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * A presentation's theme: one look for every slide (background, typeface, accent colour, a logo\n * in the footer). The same values draw the stage (CSS), the saved PDF (canvas) and the PowerPoint\n * export, so they always match.\n *\n * Backgrounds are dark, for contrast with the clips: a deep diagonal gradient with a soft light\n * from the top left (the gloss), optionally a fine texture. A custom colour gets the same\n * treatment. Typefaces are ones PowerPoint has, so an exported deck keeps its type.\n */\n\nimport type { SlideBackground } from './boxes'\n\nexport type FontId = 'sans' | 'serif' | 'classic'\nexport type LogoCorner = 'bl' | 'br'\n\nexport interface ThemeLogo {\n /** An image document of the workspace (a reference; its file is fetched when opened). */\n documentId: string\n fileName: string\n corner: LogoCorner\n}\n\nexport interface Theme {\n /** A background preset's id, or a custom colour (`#rrggbb`). */\n background: string\n font: FontId\n /** `#rrggbb`: the rule under titles, bullets. */\n accent: string\n logo: ThemeLogo | null\n}\n\n/** The app's own colours (its `--primary` and `--secondary` tokens), as a background or accent. */\nexport const BRAND = 'brand'\n\n/** By default a presentation wears the app's brand: its primary as the background, its accent. */\nexport const DEFAULT_THEME: Theme = {\n background: BRAND,\n font: 'sans',\n accent: BRAND,\n logo: null,\n}\n\ninterface BackgroundSpec {\n /** Top left of the gradient. */\n from: string\n /** Bottom right. */\n to: string\n /** The light from the top left (white, this opacity). */\n glow: number\n texture?: 'linen'\n}\n\nexport const BACKGROUNDS: ({ id: string; label: string } & BackgroundSpec)[] = [\n // The app's primary colour, read from its tokens when drawn (`brandColors`).\n { id: BRAND, label: 'Brand', from: '', to: '', glow: 0.1 },\n { id: 'graphite', label: 'Graphite', from: '#2b3038', to: '#0c0e11', glow: 0.09 },\n { id: 'midnight', label: 'Midnight', from: '#17294a', to: '#050a15', glow: 0.1 },\n { id: 'oxford', label: 'Oxford', from: '#123d45', to: '#04141a', glow: 0.08 },\n { id: 'claret', label: 'Claret', from: '#4b1526', to: '#110409', glow: 0.08 },\n { id: 'linen', label: 'Linen', from: '#2a2b30', to: '#111215', glow: 0.06, texture: 'linen' },\n { id: 'onyx', label: 'Onyx', from: '#000000', to: '#000000', glow: 0 },\n]\n\nexport const FONTS: Record<FontId, { label: string; css: string; pptx: string }> = {\n sans: {\n label: 'Modern',\n css: 'Calibri, Carlito, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif',\n pptx: 'Calibri',\n },\n serif: {\n label: 'Editorial',\n css: 'Georgia, Gelasio, \"Times New Roman\", serif',\n pptx: 'Georgia',\n },\n classic: {\n label: 'Classic',\n css: 'Garamond, \"EB Garamond\", \"Cormorant Garamond\", \"Times New Roman\", serif',\n pptx: 'Garamond',\n },\n}\n\nexport const ACCENTS: { label: string; color: string }[] = [\n { label: 'Brand', color: BRAND },\n { label: 'Gold', color: '#c9a96e' },\n { label: 'Teal', color: '#4fb3bf' },\n { label: 'Blue', color: '#6b9bf2' },\n { label: 'Coral', color: '#e57a6e' },\n { label: 'Silver', color: '#cfd4dc' },\n]\n\n/** Slide text colours, over the dark background. */\nexport const TEXT_COLORS = { title: '#ffffff', body: '#e6e8ec', muted: '#aab0ba' }\n\nconst HEX = /^#[0-9a-f]{6}$/i\n\nexport const isHexColor = (value: string): boolean => HEX.test(value)\n\nfunction mix(hex: string, toward: number, amount: number): string {\n const channel = (i: number) => {\n const value = parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16)\n return Math.round(value + (toward - value) * amount)\n .toString(16)\n .padStart(2, '0')\n }\n return `#${channel(0)}${channel(1)}${channel(2)}`\n}\n\n/** The tokens as the app's light theme defines them, where the page has none (tests, workers). */\nconst BRAND_TOKENS = { primary: '229.85 50.43% 25.29%', secondary: '195 100% 47%' }\n\nfunction hslToHex(h: number, s: number, l: number): string {\n const k = (n: number) => (n + h / 30) % 12\n const a = s * Math.min(l, 1 - l)\n const f = (n: number) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))\n return `#${[f(0), f(8), f(4)]\n .map((x) =>\n Math.round(x * 255)\n .toString(16)\n .padStart(2, '0')\n )\n .join('')}`\n}\n\n/** A token's value (\"H S% L%\"), as hue and fractions. */\nfunction readToken(name: string, fallback: string): [number, number, number] {\n const value =\n (typeof document !== 'undefined' &&\n getComputedStyle(document.documentElement).getPropertyValue(name).trim()) ||\n fallback\n const [h, s, l] = value.split(/\\s+/).map((part) => parseFloat(part))\n return [h, s / 100, l / 100]\n}\n\nlet brand: { primary: string; secondary: string } | null = null\n\n/**\n * The app's brand colours, from its `--primary` and `--secondary` tokens (another host's, in that\n * host). The primary stays deep, as a slide background: in a dark mode, where the token is light,\n * its hue is kept at the light theme's depth. Read once.\n */\nexport function brandColors(): { primary: string; secondary: string } {\n if (brand) return brand\n const [ph, ps, pl] = readToken('--primary', BRAND_TOKENS.primary)\n const [sh, ss, sl] = readToken('--secondary', BRAND_TOKENS.secondary)\n brand = { primary: hslToHex(ph, ps, Math.min(pl, 0.3)), secondary: hslToHex(sh, ss, sl) }\n return brand\n}\n\n/** A theme's accent as a colour (`brand`: the app's secondary colour). */\nexport const accentColor = (accent: string): string =>\n accent === BRAND ? brandColors().secondary : accent\n\n/** The background a theme names: a preset, or a custom colour given the presets' finish. */\nexport function backgroundSpec(background: string): BackgroundSpec {\n if (background === BRAND) {\n const { primary } = brandColors()\n return { from: mix(primary, 255, 0.05), to: mix(primary, 0, 0.6), glow: 0.1 }\n }\n const preset = BACKGROUNDS.find((entry) => entry.id === background)\n if (preset) return preset\n if (isHexColor(background)) {\n return { from: mix(background, 255, 0.06), to: mix(background, 0, 0.62), glow: 0.08 }\n }\n return backgroundSpec(BRAND)\n}\n\n/** The background as CSS (container units: the texture keeps its size on any stage). */\nexport function backgroundCss(background: string): string {\n const spec = backgroundSpec(background)\n const layers: string[] = []\n if (spec.glow > 0) {\n layers.push(\n `radial-gradient(120% 90% at 12% -10%, rgba(255,255,255,${spec.glow}), transparent 60%)`\n )\n }\n if (spec.texture === 'linen') {\n layers.push(\n 'repeating-linear-gradient(45deg, rgba(255,255,255,0.025) 0 0.06cqw, transparent 0.06cqw 0.32cqw)',\n 'repeating-linear-gradient(-45deg, rgba(255,255,255,0.02) 0 0.06cqw, transparent 0.06cqw 0.32cqw)'\n )\n }\n layers.push(`linear-gradient(155deg, ${spec.from} 0%, ${spec.to} 100%)`)\n return layers.join(', ')\n}\n\n/** The background painted on a canvas (the saved PDF's pages, the PowerPoint backgrounds). */\nexport function paintBackground(\n context: CanvasRenderingContext2D,\n width: number,\n height: number,\n background: string\n): void {\n const spec = backgroundSpec(background)\n // CSS's 155deg gradient line: through the centre, long enough to reach the corners.\n const angle = (155 * Math.PI) / 180\n const dx = Math.sin(angle)\n const dy = -Math.cos(angle)\n const length = Math.abs(width * dx) + Math.abs(height * dy)\n const cx = width / 2\n const cy = height / 2\n const gradient = context.createLinearGradient(\n cx - (dx * length) / 2,\n cy - (dy * length) / 2,\n cx + (dx * length) / 2,\n cy + (dy * length) / 2\n )\n gradient.addColorStop(0, spec.from)\n gradient.addColorStop(1, spec.to)\n context.fillStyle = gradient\n context.fillRect(0, 0, width, height)\n\n if (spec.texture === 'linen') {\n const step = width * 0.0032\n context.save()\n context.lineWidth = width * 0.0006\n for (const [direction, alpha] of [\n [1, 0.025],\n [-1, 0.02],\n ] as const) {\n context.strokeStyle = `rgba(255,255,255,${alpha})`\n context.beginPath()\n for (let offset = -height; offset < width + height; offset += step) {\n context.moveTo(offset, direction === 1 ? height : 0)\n context.lineTo(offset + height, direction === 1 ? 0 : height)\n }\n context.stroke()\n }\n context.restore()\n }\n\n if (spec.glow > 0) {\n // An ellipse 120% \u00D7 90% of the slide centred above its top left, fading out by 60%.\n const rx = width * 1.2\n const ry = height * 0.9\n context.save()\n context.translate(width * 0.12, -height * 0.1)\n context.scale(rx, ry)\n const glow = context.createRadialGradient(0, 0, 0, 0, 0, 1)\n glow.addColorStop(0, `rgba(255,255,255,${spec.glow})`)\n glow.addColorStop(0.6, 'rgba(255,255,255,0)')\n context.fillStyle = glow\n context.fillRect(-1, -1, 2, 2)\n context.restore()\n }\n}\n\n/**\n * A page clip's soft edge: paper white at its very edge (`CLIP_EDGE_SOLID`), fading to nothing by\n * `CLIP_EDGE_FADE` (fractions of the stage width; never more than `CLIP_EDGE_MAX` of the clip), so\n * text cut by the clip fades out instead of being sliced, and the clip has a little margin.\n */\nexport const CLIP_EDGE_SOLID = 0.002\nexport const CLIP_EDGE_FADE = 0.009\nexport const CLIP_EDGE_MAX = 0.08\n\n/** The soft edge as CSS (on the stage: container units). */\nexport function clipEdgeCss(): string {\n const solid = `min(${CLIP_EDGE_SOLID * 100}cqw, ${CLIP_EDGE_MAX * 25}%)`\n const fade = `min(${CLIP_EDGE_FADE * 100}cqw, ${CLIP_EDGE_MAX * 100}%)`\n return ['to right', 'to left', 'to bottom', 'to top']\n .map(\n (direction) =>\n `linear-gradient(${direction}, #fff 0, #fff ${solid}, rgba(255,255,255,0) ${fade})`\n )\n .join(', ')\n}\n\n/** The soft edge painted over a clip drawn in `box` (the saved PDF, the PowerPoint images). */\nexport function paintClipEdge(\n context: CanvasRenderingContext2D,\n box: { x: number; y: number; width: number; height: number },\n stageWidth: number\n): void {\n const sides = [\n { length: box.width, from: [box.x, 0], to: [box.x + 1, 0] },\n { length: box.width, from: [box.x + box.width, 0], to: [box.x + box.width - 1, 0] },\n { length: box.height, from: [0, box.y], to: [0, box.y + 1] },\n { length: box.height, from: [0, box.y + box.height], to: [0, box.y + box.height - 1] },\n ]\n for (const side of sides) {\n const fade = Math.min(CLIP_EDGE_FADE * stageWidth, CLIP_EDGE_MAX * side.length)\n const solid = Math.min(CLIP_EDGE_SOLID * stageWidth, CLIP_EDGE_MAX * 0.25 * side.length)\n // Along the side's inward normal, `fade` long.\n const [fx, fy] = side.from\n const [tx, ty] = side.to\n const gradient = context.createLinearGradient(\n fx,\n fy,\n fx + (tx - fx) * fade,\n fy + (ty - fy) * fade\n )\n gradient.addColorStop(0, 'rgba(255,255,255,1)')\n gradient.addColorStop(Math.min(1, solid / fade), 'rgba(255,255,255,1)')\n gradient.addColorStop(1, 'rgba(255,255,255,0)')\n context.fillStyle = gradient\n context.fillRect(box.x, box.y, box.width, box.height)\n }\n}\n\n/** A slide's own background as CSS: its image (from the presentation's media), gradient or colour. */\nexport function slideBackgroundCss(\n background: SlideBackground,\n media: Readonly<Record<string, string>>\n): string {\n const image = background.image ? media[background.image] : undefined\n if (image) return `center / cover no-repeat url(\"${image}\")`\n if (background.gradient) {\n const { angle, from, to } = background.gradient\n return `linear-gradient(${angle}deg, ${from}, ${to})`\n }\n return background.color ?? '#ffffff'\n}\n\n/** A slide's own background painted on a canvas. */\nexport async function paintSlideBackground(\n context: CanvasRenderingContext2D,\n width: number,\n height: number,\n background: SlideBackground,\n media: Readonly<Record<string, string>>\n): Promise<void> {\n const image = background.image ? media[background.image] : undefined\n if (image) {\n const picture = new Image()\n picture.src = image\n await picture.decode()\n // Cover: fill the slide, cropping the overflow.\n const scale = Math.max(width / picture.width, height / picture.height)\n const w = picture.width * scale\n const h = picture.height * scale\n context.drawImage(picture, (width - w) / 2, (height - h) / 2, w, h)\n return\n }\n if (background.gradient) {\n const { angle, from, to } = background.gradient\n const radians = (angle * Math.PI) / 180\n const dx = Math.sin(radians)\n const dy = -Math.cos(radians)\n const length = Math.abs(width * dx) + Math.abs(height * dy)\n const gradient = context.createLinearGradient(\n width / 2 - (dx * length) / 2,\n height / 2 - (dy * length) / 2,\n width / 2 + (dx * length) / 2,\n height / 2 + (dy * length) / 2\n )\n gradient.addColorStop(0, from)\n gradient.addColorStop(1, to)\n context.fillStyle = gradient\n } else {\n context.fillStyle = background.color ?? '#ffffff'\n }\n context.fillRect(0, 0, width, height)\n}\n\n/** Whether a slide's background is light (text on it should be dark). */\nexport function isLightBackground(background: SlideBackground | undefined): boolean {\n const color = background?.gradient?.from ?? background?.color\n if (!color || !isHexColor(color)) return false\n const n = parseInt(color.slice(1), 16)\n const luminance = 0.2126 * ((n >> 16) & 255) + 0.7152 * ((n >> 8) & 255) + 0.0722 * (n & 255)\n return luminance > 150\n}\n\n/** A theme read from saved data, every field checked (anything wrong falls back to the default). */\nexport function parseTheme(value: unknown): Theme {\n const data = (value ?? {}) as Partial<Theme>\n const logo = data.logo as Partial<ThemeLogo> | null | undefined\n return {\n background:\n typeof data.background === 'string' &&\n (BACKGROUNDS.some((entry) => entry.id === data.background) || isHexColor(data.background))\n ? data.background\n : DEFAULT_THEME.background,\n font: data.font && data.font in FONTS ? data.font : DEFAULT_THEME.font,\n accent:\n typeof data.accent === 'string' && (isHexColor(data.accent) || data.accent === BRAND)\n ? data.accent\n : DEFAULT_THEME.accent,\n logo:\n logo && typeof logo.documentId === 'string'\n ? {\n documentId: logo.documentId,\n fileName: typeof logo.fileName === 'string' ? logo.fileName : '',\n corner: logo.corner === 'bl' ? 'bl' : 'br',\n }\n : null,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dragging a clip from the tray onto a slide, with pointer events: the same for a mouse, a pen and
|
|
3
|
+
* a finger (HTML drag and drop does not work on touch screens). A drag starts once the pointer has
|
|
4
|
+
* moved a little; a thumbnail follows it; on release, what is under it decides: the stage (the
|
|
5
|
+
* clip goes on the current slide where it was dropped) or a slide chip (on that slide). A press
|
|
6
|
+
* that does not move is a tap.
|
|
7
|
+
*
|
|
8
|
+
* Drop targets are marked with `data-presentation-drop` ("stage", or "slide" with
|
|
9
|
+
* `data-slide-index`), so they are found under the pointer in whichever window the tray is in.
|
|
10
|
+
*/
|
|
11
|
+
import { type PointerEvent as ReactPointerEvent } from 'react';
|
|
12
|
+
export declare const DROP_ATTRIBUTE = "data-presentation-drop";
|
|
13
|
+
export interface ClipDrag {
|
|
14
|
+
/** Where the dragged thumbnail is (client px), while dragging. */
|
|
15
|
+
ghost: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
} | null;
|
|
19
|
+
handlers: {
|
|
20
|
+
onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;
|
|
21
|
+
onPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;
|
|
22
|
+
onPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;
|
|
23
|
+
onPointerCancel: () => void;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export declare function useClipDrag(clipId: string, onTap: () => void): ClipDrag;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { usePresentation } from "./store.js";
|
|
4
|
+
const DRAG_THRESHOLD = 6;
|
|
5
|
+
const DROP_ATTRIBUTE = "data-presentation-drop";
|
|
6
|
+
function dropAt(doc, clipId, x, y) {
|
|
7
|
+
const target = doc.elementFromPoint(x, y)?.closest(`[${DROP_ATTRIBUTE}]`);
|
|
8
|
+
if (!target) return false;
|
|
9
|
+
const state = usePresentation.getState();
|
|
10
|
+
if (target.getAttribute(DROP_ATTRIBUTE) === "slide") {
|
|
11
|
+
const index2 = Number(target.getAttribute("data-slide-index"));
|
|
12
|
+
if (!Number.isInteger(index2)) return false;
|
|
13
|
+
state.goTo(index2);
|
|
14
|
+
state.place(clipId);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const index = Number(target.getAttribute("data-slide-index"));
|
|
18
|
+
if (target.hasAttribute("data-slide-index") && Number.isInteger(index)) state.goTo(index);
|
|
19
|
+
const box = target.getBoundingClientRect();
|
|
20
|
+
state.place(clipId, { x: (x - box.left) / box.width, y: (y - box.top) / box.height });
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
function useClipDrag(clipId, onTap) {
|
|
24
|
+
const press = useRef(null);
|
|
25
|
+
const [ghost, setGhost] = useState(null);
|
|
26
|
+
const end = () => {
|
|
27
|
+
press.current = null;
|
|
28
|
+
setGhost(null);
|
|
29
|
+
usePresentation.getState().setDragging(null);
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
ghost,
|
|
33
|
+
handlers: {
|
|
34
|
+
onPointerDown: (event) => {
|
|
35
|
+
if (event.button !== 0) return;
|
|
36
|
+
press.current = { x: event.clientX, y: event.clientY, dragging: false };
|
|
37
|
+
},
|
|
38
|
+
onPointerMove: (event) => {
|
|
39
|
+
const p = press.current;
|
|
40
|
+
if (!p) return;
|
|
41
|
+
if (!p.dragging) {
|
|
42
|
+
if (Math.hypot(event.clientX - p.x, event.clientY - p.y) < DRAG_THRESHOLD) return;
|
|
43
|
+
p.dragging = true;
|
|
44
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
45
|
+
usePresentation.getState().setDragging(clipId);
|
|
46
|
+
}
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
setGhost({ x: event.clientX, y: event.clientY });
|
|
49
|
+
},
|
|
50
|
+
onPointerUp: (event) => {
|
|
51
|
+
const p = press.current;
|
|
52
|
+
if (p?.dragging)
|
|
53
|
+
dropAt(event.currentTarget.ownerDocument, clipId, event.clientX, event.clientY);
|
|
54
|
+
else if (p) onTap();
|
|
55
|
+
end();
|
|
56
|
+
},
|
|
57
|
+
onPointerCancel: end
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
DROP_ATTRIBUTE,
|
|
63
|
+
useClipDrag
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=useClipDrag.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/presentation/useClipDrag.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Dragging a clip from the tray onto a slide, with pointer events: the same for a mouse, a pen and\n * a finger (HTML drag and drop does not work on touch screens). A drag starts once the pointer has\n * moved a little; a thumbnail follows it; on release, what is under it decides: the stage (the\n * clip goes on the current slide where it was dropped) or a slide chip (on that slide). A press\n * that does not move is a tap.\n *\n * Drop targets are marked with `data-presentation-drop` (\"stage\", or \"slide\" with\n * `data-slide-index`), so they are found under the pointer in whichever window the tray is in.\n */\n\nimport { useRef, useState, type PointerEvent as ReactPointerEvent } from 'react'\nimport { usePresentation } from './store'\n\n/** How far (px) the pointer moves before a press becomes a drag. */\nconst DRAG_THRESHOLD = 6\n\nexport const DROP_ATTRIBUTE = 'data-presentation-drop'\n\nexport interface ClipDrag {\n /** Where the dragged thumbnail is (client px), while dragging. */\n ghost: { x: number; y: number } | null\n handlers: {\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void\n onPointerMove: (event: ReactPointerEvent<HTMLElement>) => void\n onPointerUp: (event: ReactPointerEvent<HTMLElement>) => void\n onPointerCancel: () => void\n }\n}\n\n/** Drop a clip at a point of the window: on the stage there, or on a slide chip. */\nfunction dropAt(doc: Document, clipId: string, x: number, y: number): boolean {\n const target = doc.elementFromPoint(x, y)?.closest(`[${DROP_ATTRIBUTE}]`)\n if (!target) return false\n const state = usePresentation.getState()\n if (target.getAttribute(DROP_ATTRIBUTE) === 'slide') {\n const index = Number(target.getAttribute('data-slide-index'))\n if (!Number.isInteger(index)) return false\n state.goTo(index)\n state.place(clipId)\n return true\n }\n // A slide's stage (the editor shows them all): that slide, at the point.\n const index = Number(target.getAttribute('data-slide-index'))\n if (target.hasAttribute('data-slide-index') && Number.isInteger(index)) state.goTo(index)\n const box = target.getBoundingClientRect()\n state.place(clipId, { x: (x - box.left) / box.width, y: (y - box.top) / box.height })\n return true\n}\n\nexport function useClipDrag(clipId: string, onTap: () => void): ClipDrag {\n const press = useRef<{ x: number; y: number; dragging: boolean } | null>(null)\n const [ghost, setGhost] = useState<{ x: number; y: number } | null>(null)\n\n const end = () => {\n press.current = null\n setGhost(null)\n usePresentation.getState().setDragging(null)\n }\n\n return {\n ghost,\n handlers: {\n onPointerDown: (event) => {\n if (event.button !== 0) return\n press.current = { x: event.clientX, y: event.clientY, dragging: false }\n },\n onPointerMove: (event) => {\n const p = press.current\n if (!p) return\n if (!p.dragging) {\n if (Math.hypot(event.clientX - p.x, event.clientY - p.y) < DRAG_THRESHOLD) return\n p.dragging = true\n // Keep receiving the pointer wherever it goes, and stop the browser scrolling for it.\n event.currentTarget.setPointerCapture(event.pointerId)\n usePresentation.getState().setDragging(clipId)\n }\n event.preventDefault()\n setGhost({ x: event.clientX, y: event.clientY })\n },\n onPointerUp: (event) => {\n const p = press.current\n if (p?.dragging)\n dropAt(event.currentTarget.ownerDocument, clipId, event.clientX, event.clientY)\n else if (p) onTap()\n end()\n },\n onPointerCancel: end,\n },\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAWA,SAAS,QAAQ,gBAAwD;AACzE,SAAS,uBAAuB;AAGhC,MAAM,iBAAiB;AAEhB,MAAM,iBAAiB;AAc9B,SAAS,OAAO,KAAe,QAAgB,GAAW,GAAoB;AAC5E,QAAM,SAAS,IAAI,iBAAiB,GAAG,CAAC,GAAG,QAAQ,IAAI,cAAc,GAAG;AACxE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,gBAAgB,SAAS;AACvC,MAAI,OAAO,aAAa,cAAc,MAAM,SAAS;AACnD,UAAMA,SAAQ,OAAO,OAAO,aAAa,kBAAkB,CAAC;AAC5D,QAAI,CAAC,OAAO,UAAUA,MAAK,EAAG,QAAO;AACrC,UAAM,KAAKA,MAAK;AAChB,UAAM,MAAM,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,OAAO,OAAO,aAAa,kBAAkB,CAAC;AAC5D,MAAI,OAAO,aAAa,kBAAkB,KAAK,OAAO,UAAU,KAAK,EAAG,OAAM,KAAK,KAAK;AACxF,QAAM,MAAM,OAAO,sBAAsB;AACzC,QAAM,MAAM,QAAQ,EAAE,IAAI,IAAI,IAAI,QAAQ,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,OAAO,CAAC;AACpF,SAAO;AACT;AAEO,SAAS,YAAY,QAAgB,OAA6B;AACvE,QAAM,QAAQ,OAA2D,IAAI;AAC7E,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA0C,IAAI;AAExE,QAAM,MAAM,MAAM;AAChB,UAAM,UAAU;AAChB,aAAS,IAAI;AACb,oBAAgB,SAAS,EAAE,YAAY,IAAI;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,MACR,eAAe,CAAC,UAAU;AACxB,YAAI,MAAM,WAAW,EAAG;AACxB,cAAM,UAAU,EAAE,GAAG,MAAM,SAAS,GAAG,MAAM,SAAS,UAAU,MAAM;AAAA,MACxE;AAAA,MACA,eAAe,CAAC,UAAU;AACxB,cAAM,IAAI,MAAM;AAChB,YAAI,CAAC,EAAG;AACR,YAAI,CAAC,EAAE,UAAU;AACf,cAAI,KAAK,MAAM,MAAM,UAAU,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC,IAAI,eAAgB;AAC3E,YAAE,WAAW;AAEb,gBAAM,cAAc,kBAAkB,MAAM,SAAS;AACrD,0BAAgB,SAAS,EAAE,YAAY,MAAM;AAAA,QAC/C;AACA,cAAM,eAAe;AACrB,iBAAS,EAAE,GAAG,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;AAAA,MACjD;AAAA,MACA,aAAa,CAAC,UAAU;AACtB,cAAM,IAAI,MAAM;AAChB,YAAI,GAAG;AACL,iBAAO,MAAM,cAAc,eAAe,QAAQ,MAAM,SAAS,MAAM,OAAO;AAAA,iBACvE,EAAG,OAAM;AAClB,YAAI;AAAA,MACN;AAAA,MACA,iBAAiB;AAAA,IACnB;AAAA,EACF;AACF;",
|
|
6
|
+
"names": ["index"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An object URL for a file, owned by the mount that made it and revoked when it unmounts or the
|
|
3
|
+
* file changes. Made in an effect, not a memo: a memoised URL survives a remount (React's
|
|
4
|
+
* StrictMode replays mount effects) while the first mount's cleanup has already revoked it.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useObjectUrl(file: Blob): string | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
function useObjectUrl(file) {
|
|
4
|
+
const [url, setUrl] = useState();
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const next = URL.createObjectURL(file);
|
|
7
|
+
setUrl(next);
|
|
8
|
+
return () => URL.revokeObjectURL(next);
|
|
9
|
+
}, [file]);
|
|
10
|
+
return url;
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
useObjectUrl
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=useObjectUrl.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/presentation/useObjectUrl.ts"],
|
|
4
|
+
"sourcesContent": ["import { useEffect, useState } from 'react'\n\n/**\n * An object URL for a file, owned by the mount that made it and revoked when it unmounts or the\n * file changes. Made in an effect, not a memo: a memoised URL survives a remount (React's\n * StrictMode replays mount effects) while the first mount's cleanup has already revoked it.\n */\nexport function useObjectUrl(file: Blob): string | undefined {\n const [url, setUrl] = useState<string>()\n useEffect(() => {\n const next = URL.createObjectURL(file)\n setUrl(next)\n return () => URL.revokeObjectURL(next)\n }, [file])\n return url\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,WAAW,gBAAgB;AAO7B,SAAS,aAAa,MAAgC;AAC3D,QAAM,CAAC,KAAK,MAAM,IAAI,SAAiB;AACvC,YAAU,MAAM;AACd,UAAM,OAAO,IAAI,gBAAgB,IAAI;AACrC,WAAO,IAAI;AACX,WAAO,MAAM,IAAI,gBAAgB,IAAI;AAAA,EACvC,GAAG,CAAC,IAAI,CAAC;AACT,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keys of the presentation window. A presenter (or a presentation clicker, which sends Page Up /
|
|
3
|
+
* Page Down and "." or "b"): previous / next slide and blank the stage; while presenting, F for
|
|
4
|
+
* full screen and Escape back to editing. While editing with a clip selected: the arrows nudge it
|
|
5
|
+
* (Shift: further), Delete takes it off the slide and Escape deselects it.
|
|
6
|
+
*/
|
|
7
|
+
/** Full screen on or off for a window's page (from a key or click in that window). */
|
|
8
|
+
export declare function toggleFullscreen(view: Window): void;
|
|
9
|
+
export interface PresenterSelection {
|
|
10
|
+
clipId: string | null;
|
|
11
|
+
clear: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function usePresenterKeys(view: Window | null | undefined, presenting: boolean, selection?: PresenterSelection): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { toggleStageVideos } from "./stage-videos.js";
|
|
4
|
+
import { STAGE_ASPECT } from "./model.js";
|
|
5
|
+
import { usePresentation } from "./store.js";
|
|
6
|
+
import { moveBox } from "./boxes.js";
|
|
7
|
+
const NUDGE = 5e-3;
|
|
8
|
+
const BIG_NUDGE = 0.04;
|
|
9
|
+
function toggleFullscreen(view) {
|
|
10
|
+
const doc = view.document;
|
|
11
|
+
if (doc.fullscreenElement) void doc.exitFullscreen();
|
|
12
|
+
else void doc.documentElement.requestFullscreen?.();
|
|
13
|
+
}
|
|
14
|
+
function usePresenterKeys(view, presenting, selection) {
|
|
15
|
+
const selected = presenting ? null : selection?.clipId ?? null;
|
|
16
|
+
const clear = selection?.clear;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!view) return;
|
|
19
|
+
const onKeyDown = (event) => {
|
|
20
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey) return;
|
|
21
|
+
const target = event.target;
|
|
22
|
+
if (target?.closest?.('input, textarea, select, [contenteditable="true"]')) return;
|
|
23
|
+
const state = usePresentation.getState();
|
|
24
|
+
const key = event.key;
|
|
25
|
+
const onSlide = selected && state.slides[state.current]?.items.some((i) => i.clipId === selected);
|
|
26
|
+
const box = selected?.startsWith("box-") ? state.slides.flatMap((slide) => slide.boxes).find((entry) => entry.id === selected) : void 0;
|
|
27
|
+
if (box && key.startsWith("Arrow")) {
|
|
28
|
+
const step = event.shiftKey ? BIG_NUDGE : NUDGE;
|
|
29
|
+
const dx = key === "ArrowLeft" ? -step : key === "ArrowRight" ? step : 0;
|
|
30
|
+
const dy = (key === "ArrowUp" ? -step : key === "ArrowDown" ? step : 0) * STAGE_ASPECT;
|
|
31
|
+
state.updateBox(box.id, (entry) => ({ ...entry, frame: moveBox(entry.frame, dx, dy) }));
|
|
32
|
+
} else if (box && (key === "Delete" || key === "Backspace")) {
|
|
33
|
+
state.removeBox(box.id);
|
|
34
|
+
clear?.();
|
|
35
|
+
} else if (onSlide && key.startsWith("Arrow")) {
|
|
36
|
+
const step = event.shiftKey ? BIG_NUDGE : NUDGE;
|
|
37
|
+
const dx = key === "ArrowLeft" ? -step : key === "ArrowRight" ? step : 0;
|
|
38
|
+
const dy = (key === "ArrowUp" ? -step : key === "ArrowDown" ? step : 0) * STAGE_ASPECT;
|
|
39
|
+
state.nudge(selected, dx, dy);
|
|
40
|
+
} else if (onSlide && (key === "Delete" || key === "Backspace")) {
|
|
41
|
+
state.unplace(selected);
|
|
42
|
+
clear?.();
|
|
43
|
+
} else if (selected && key === "Escape") clear?.();
|
|
44
|
+
else if (!presenting) return;
|
|
45
|
+
else if (key === "ArrowRight" || key === "PageDown") state.goTo(state.current + 1);
|
|
46
|
+
else if (key === "ArrowLeft" || key === "PageUp") state.goTo(state.current - 1);
|
|
47
|
+
else if (key === "b" || key === "B" || key === ".") state.setBlank(!state.blank);
|
|
48
|
+
else if (presenting && (key === "f" || key === "F")) toggleFullscreen(view);
|
|
49
|
+
else if (presenting && key === " " && toggleStageVideos(view.document)) {
|
|
50
|
+
} else if (presenting && key === "Escape") state.setPresenting(false);
|
|
51
|
+
else return;
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
};
|
|
54
|
+
view.addEventListener("keydown", onKeyDown);
|
|
55
|
+
return () => view.removeEventListener("keydown", onKeyDown);
|
|
56
|
+
}, [view, presenting, selected, clear]);
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
toggleFullscreen,
|
|
60
|
+
usePresenterKeys
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=usePresenterKeys.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/presentation/usePresenterKeys.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The keys of the presentation window. A presenter (or a presentation clicker, which sends Page Up /\n * Page Down and \".\" or \"b\"): previous / next slide and blank the stage; while presenting, F for\n * full screen and Escape back to editing. While editing with a clip selected: the arrows nudge it\n * (Shift: further), Delete takes it off the slide and Escape deselects it.\n */\n\nimport { useEffect } from 'react'\nimport { toggleStageVideos } from './stage-videos'\nimport { STAGE_ASPECT } from './model'\nimport { usePresentation } from './store'\nimport { moveBox } from './boxes'\n\n/** A nudge, as a fraction of the stage width (vertical nudges move as far on screen). */\nconst NUDGE = 0.005\nconst BIG_NUDGE = 0.04\n\n/** Full screen on or off for a window's page (from a key or click in that window). */\nexport function toggleFullscreen(view: Window): void {\n const doc = view.document\n if (doc.fullscreenElement) void doc.exitFullscreen()\n else void doc.documentElement.requestFullscreen?.()\n}\n\nexport interface PresenterSelection {\n clipId: string | null\n clear: () => void\n}\n\nexport function usePresenterKeys(\n view: Window | null | undefined,\n presenting: boolean,\n selection?: PresenterSelection\n): void {\n const selected = presenting ? null : (selection?.clipId ?? null)\n const clear = selection?.clear\n useEffect(() => {\n if (!view) return\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey) return\n const target = event.target as HTMLElement | null\n if (target?.closest?.('input, textarea, select, [contenteditable=\"true\"]')) return\n const state = usePresentation.getState()\n const key = event.key\n const onSlide =\n selected && state.slides[state.current]?.items.some((i) => i.clipId === selected)\n const box = selected?.startsWith('box-')\n ? state.slides.flatMap((slide) => slide.boxes).find((entry) => entry.id === selected)\n : undefined\n if (box && key.startsWith('Arrow')) {\n const step = event.shiftKey ? BIG_NUDGE : NUDGE\n const dx = key === 'ArrowLeft' ? -step : key === 'ArrowRight' ? step : 0\n const dy = (key === 'ArrowUp' ? -step : key === 'ArrowDown' ? step : 0) * STAGE_ASPECT\n state.updateBox(box.id, (entry) => ({ ...entry, frame: moveBox(entry.frame, dx, dy) }))\n } else if (box && (key === 'Delete' || key === 'Backspace')) {\n state.removeBox(box.id)\n clear?.()\n } else if (onSlide && key.startsWith('Arrow')) {\n const step = event.shiftKey ? BIG_NUDGE : NUDGE\n const dx = key === 'ArrowLeft' ? -step : key === 'ArrowRight' ? step : 0\n const dy = (key === 'ArrowUp' ? -step : key === 'ArrowDown' ? step : 0) * STAGE_ASPECT\n state.nudge(selected, dx, dy)\n } else if (onSlide && (key === 'Delete' || key === 'Backspace')) {\n state.unplace(selected)\n clear?.()\n } else if (selected && key === 'Escape') clear?.()\n // Editing (in the app's own window too): only a selected clip takes keys.\n else if (!presenting) return\n else if (key === 'ArrowRight' || key === 'PageDown') state.goTo(state.current + 1)\n else if (key === 'ArrowLeft' || key === 'PageUp') state.goTo(state.current - 1)\n else if (key === 'b' || key === 'B' || key === '.') state.setBlank(!state.blank)\n else if (presenting && (key === 'f' || key === 'F')) toggleFullscreen(view)\n // Space plays or pauses the slide's videos.\n else if (presenting && key === ' ' && toggleStageVideos(view.document)) {\n // handled\n }\n // Out of full screen the browser takes the first Escape; the next one stops presenting.\n else if (presenting && key === 'Escape') state.setPresenting(false)\n else return\n event.preventDefault()\n }\n view.addEventListener('keydown', onKeyDown)\n return () => view.removeEventListener('keydown', onKeyDown)\n }, [view, presenting, selected, clear])\n}\n"],
|
|
5
|
+
"mappings": ";AAOA,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,eAAe;AAGxB,MAAM,QAAQ;AACd,MAAM,YAAY;AAGX,SAAS,iBAAiB,MAAoB;AACnD,QAAM,MAAM,KAAK;AACjB,MAAI,IAAI,kBAAmB,MAAK,IAAI,eAAe;AAAA,MAC9C,MAAK,IAAI,gBAAgB,oBAAoB;AACpD;AAOO,SAAS,iBACd,MACA,YACA,WACM;AACN,QAAM,WAAW,aAAa,OAAQ,WAAW,UAAU;AAC3D,QAAM,QAAQ,WAAW;AACzB,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,MAAM,oBAAoB,MAAM,WAAW,MAAM,WAAW,MAAM,OAAQ;AAC9E,YAAM,SAAS,MAAM;AACrB,UAAI,QAAQ,UAAU,mDAAmD,EAAG;AAC5E,YAAM,QAAQ,gBAAgB,SAAS;AACvC,YAAM,MAAM,MAAM;AAClB,YAAM,UACJ,YAAY,MAAM,OAAO,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ;AAClF,YAAM,MAAM,UAAU,WAAW,MAAM,IACnC,MAAM,OAAO,QAAQ,CAAC,UAAU,MAAM,KAAK,EAAE,KAAK,CAAC,UAAU,MAAM,OAAO,QAAQ,IAClF;AACJ,UAAI,OAAO,IAAI,WAAW,OAAO,GAAG;AAClC,cAAM,OAAO,MAAM,WAAW,YAAY;AAC1C,cAAM,KAAK,QAAQ,cAAc,CAAC,OAAO,QAAQ,eAAe,OAAO;AACvE,cAAM,MAAM,QAAQ,YAAY,CAAC,OAAO,QAAQ,cAAc,OAAO,KAAK;AAC1E,cAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,OAAO,QAAQ,MAAM,OAAO,IAAI,EAAE,EAAE,EAAE;AAAA,MACxF,WAAW,QAAQ,QAAQ,YAAY,QAAQ,cAAc;AAC3D,cAAM,UAAU,IAAI,EAAE;AACtB,gBAAQ;AAAA,MACV,WAAW,WAAW,IAAI,WAAW,OAAO,GAAG;AAC7C,cAAM,OAAO,MAAM,WAAW,YAAY;AAC1C,cAAM,KAAK,QAAQ,cAAc,CAAC,OAAO,QAAQ,eAAe,OAAO;AACvE,cAAM,MAAM,QAAQ,YAAY,CAAC,OAAO,QAAQ,cAAc,OAAO,KAAK;AAC1E,cAAM,MAAM,UAAU,IAAI,EAAE;AAAA,MAC9B,WAAW,YAAY,QAAQ,YAAY,QAAQ,cAAc;AAC/D,cAAM,QAAQ,QAAQ;AACtB,gBAAQ;AAAA,MACV,WAAW,YAAY,QAAQ,SAAU,SAAQ;AAAA,eAExC,CAAC,WAAY;AAAA,eACb,QAAQ,gBAAgB,QAAQ,WAAY,OAAM,KAAK,MAAM,UAAU,CAAC;AAAA,eACxE,QAAQ,eAAe,QAAQ,SAAU,OAAM,KAAK,MAAM,UAAU,CAAC;AAAA,eACrE,QAAQ,OAAO,QAAQ,OAAO,QAAQ,IAAK,OAAM,SAAS,CAAC,MAAM,KAAK;AAAA,eACtE,eAAe,QAAQ,OAAO,QAAQ,KAAM,kBAAiB,IAAI;AAAA,eAEjE,cAAc,QAAQ,OAAO,kBAAkB,KAAK,QAAQ,GAAG;AAAA,MAExE,WAES,cAAc,QAAQ,SAAU,OAAM,cAAc,KAAK;AAAA,UAC7D;AACL,YAAM,eAAe;AAAA,IACvB;AACA,SAAK,iBAAiB,WAAW,SAAS;AAC1C,WAAO,MAAM,KAAK,oBAAoB,WAAW,SAAS;AAAA,EAC5D,GAAG,CAAC,MAAM,YAAY,UAAU,KAAK,CAAC;AACxC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|