@arbidocs/blocks 0.5.123 → 0.5.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ClippingMediaViewer-IEIBT74X.cjs → ClippingMediaViewer-ZFEX5A3U.cjs} +11 -10
- package/dist/ClippingMediaViewer-ZFEX5A3U.cjs.map +1 -0
- package/dist/{ClippingPdfViewer-OGYLMVCE.cjs → ClippingPdfViewer-3LRTEPHV.cjs} +45 -11
- package/dist/ClippingPdfViewer-3LRTEPHV.cjs.map +1 -0
- package/dist/ConnectedCallDock-XJOYVVAH.cjs +6 -6
- package/dist/ConnectedCallRoom-CUDYAPQK.cjs +6 -6
- package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs → ConnectedNativeDocxComparison-7QQ55JIO.cjs} +13 -13
- package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs.map → ConnectedNativeDocxComparison-7QQ55JIO.cjs.map} +1 -1
- package/dist/{ConnectedPresentation-5DOJ35XL.cjs → ConnectedPresentation-L32JPRFI.cjs} +30 -156
- package/dist/ConnectedPresentation-L32JPRFI.cjs.map +1 -0
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs → ConnectedProductionSetDialog-4EAY6KAZ.cjs} +3 -3
- package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs.map → ConnectedProductionSetDialog-4EAY6KAZ.cjs.map} +1 -1
- package/dist/{ConnectedSlidesTab-7YMEDGUU.cjs → ConnectedSlidesTab-P7GGNUTO.cjs} +31 -29
- package/dist/ConnectedSlidesTab-P7GGNUTO.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs → ConnectedStreamedWordArtifact-7NJ3N52V.cjs} +13 -13
- package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs.map → ConnectedStreamedWordArtifact-7NJ3N52V.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-M53XFLI2.cjs → DocumentReviewCard-BFPOFQXI.cjs} +16 -16
- package/dist/{DocumentReviewCard-M53XFLI2.cjs.map → DocumentReviewCard-BFPOFQXI.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-2QCCRWF2.cjs → FilesViewerDialog-MHUVEZ7M.cjs} +35 -32
- package/dist/FilesViewerDialog-MHUVEZ7M.cjs.map +1 -0
- package/dist/{NativeDocxEditor-2LQY2CTV.cjs → NativeDocxEditor-SIRYPMBN.cjs} +6 -6
- package/dist/{NativeDocxEditor-2LQY2CTV.cjs.map → NativeDocxEditor-SIRYPMBN.cjs.map} +1 -1
- package/dist/SpotlightStrip-ED22UYTM.cjs +398 -0
- package/dist/SpotlightStrip-ED22UYTM.cjs.map +1 -0
- package/dist/{WorkspaceTableView-3XYAV4BV.cjs → WorkspaceTableView-MIFYXV3G.cjs} +8 -8
- package/dist/{WorkspaceTableView-3XYAV4BV.cjs.map → WorkspaceTableView-MIFYXV3G.cjs.map} +1 -1
- package/dist/agents/index.cjs +216 -216
- package/dist/ai-IEIR7SC2.cjs +3 -3
- package/dist/auth/index.cjs +1 -1
- package/dist/calls/index.cjs +2 -2
- package/dist/chat/index.cjs +6 -6
- package/dist/{chunk-GNZAH6UI.cjs → chunk-2K6IMIVL.cjs} +3 -3
- package/dist/{chunk-GNZAH6UI.cjs.map → chunk-2K6IMIVL.cjs.map} +1 -1
- package/dist/{chunk-NQML7IUC.cjs → chunk-3UP32FM3.cjs} +6 -6
- package/dist/{chunk-NQML7IUC.cjs.map → chunk-3UP32FM3.cjs.map} +1 -1
- package/dist/chunk-3ZZZO4F7.cjs +145 -0
- package/dist/chunk-3ZZZO4F7.cjs.map +1 -0
- package/dist/{chunk-L4CIFLCU.cjs → chunk-4LP5MJGQ.cjs} +4 -4
- package/dist/{chunk-L4CIFLCU.cjs.map → chunk-4LP5MJGQ.cjs.map} +1 -1
- package/dist/{chunk-JD2HX2BR.cjs → chunk-6JMW3IJ2.cjs} +152 -155
- package/dist/chunk-6JMW3IJ2.cjs.map +1 -0
- package/dist/{chunk-WV7BCGCK.cjs → chunk-7RJZIPLE.cjs} +33 -33
- package/dist/{chunk-WV7BCGCK.cjs.map → chunk-7RJZIPLE.cjs.map} +1 -1
- package/dist/{chunk-WFMWKPGY.cjs → chunk-ADPRIBSH.cjs} +9 -33
- package/dist/chunk-ADPRIBSH.cjs.map +1 -0
- package/dist/{chunk-7NLO7ASW.cjs → chunk-AISYXX4M.cjs} +4 -4
- package/dist/{chunk-7NLO7ASW.cjs.map → chunk-AISYXX4M.cjs.map} +1 -1
- package/dist/{chunk-5QERK4PK.cjs → chunk-AS6QZETU.cjs} +35 -35
- package/dist/{chunk-5QERK4PK.cjs.map → chunk-AS6QZETU.cjs.map} +1 -1
- package/dist/{chunk-V6MW7B4B.cjs → chunk-B3R62764.cjs} +6 -6
- package/dist/{chunk-V6MW7B4B.cjs.map → chunk-B3R62764.cjs.map} +1 -1
- package/dist/{chunk-VKH3BEZE.cjs → chunk-BLIO3B7Z.cjs} +3 -3
- package/dist/{chunk-VKH3BEZE.cjs.map → chunk-BLIO3B7Z.cjs.map} +1 -1
- package/dist/{chunk-46P7IDBX.cjs → chunk-CQ2RJYE2.cjs} +4 -4
- package/dist/chunk-CQ2RJYE2.cjs.map +1 -0
- package/dist/{chunk-MXBXZXXQ.cjs → chunk-ENOPKX7E.cjs} +3 -3
- package/dist/{chunk-MXBXZXXQ.cjs.map → chunk-ENOPKX7E.cjs.map} +1 -1
- package/dist/{chunk-2CSLFAGF.cjs → chunk-GAMRVB3I.cjs} +4 -3
- package/dist/chunk-GAMRVB3I.cjs.map +1 -0
- package/dist/chunk-IRGRMJPP.cjs +18 -0
- package/dist/{chunk-SDRYSLOX.cjs.map → chunk-IRGRMJPP.cjs.map} +1 -1
- package/dist/{chunk-ADDQKZ5I.cjs → chunk-J3FFSEKO.cjs} +4 -4
- package/dist/{chunk-ADDQKZ5I.cjs.map → chunk-J3FFSEKO.cjs.map} +1 -1
- package/dist/chunk-JITYC4OS.cjs +66 -0
- package/dist/chunk-JITYC4OS.cjs.map +1 -0
- package/dist/chunk-JY7UUZQG.cjs +1513 -0
- package/dist/chunk-JY7UUZQG.cjs.map +1 -0
- package/dist/{chunk-ALK3PUUB.cjs → chunk-L6HTZIBD.cjs} +3 -3
- package/dist/{chunk-ALK3PUUB.cjs.map → chunk-L6HTZIBD.cjs.map} +1 -1
- package/dist/chunk-MVXHTAJ4.cjs +111 -0
- package/dist/chunk-MVXHTAJ4.cjs.map +1 -0
- package/dist/{chunk-OHHKBURG.cjs → chunk-OGK377NL.cjs} +33 -33
- package/dist/{chunk-OHHKBURG.cjs.map → chunk-OGK377NL.cjs.map} +1 -1
- package/dist/{chunk-T73BHNQX.cjs → chunk-OHWHYVKG.cjs} +3 -3
- package/dist/{chunk-T73BHNQX.cjs.map → chunk-OHWHYVKG.cjs.map} +1 -1
- package/dist/{chunk-4TTX6ZNS.cjs → chunk-ORNLCBNE.cjs} +24 -2
- package/dist/chunk-ORNLCBNE.cjs.map +1 -0
- package/dist/{chunk-MLA2BJ2Y.cjs → chunk-PSB64T43.cjs} +28 -28
- package/dist/{chunk-MLA2BJ2Y.cjs.map → chunk-PSB64T43.cjs.map} +1 -1
- package/dist/{chunk-COD5ENHK.cjs → chunk-PVJ5ODDB.cjs} +4 -4
- package/dist/{chunk-COD5ENHK.cjs.map → chunk-PVJ5ODDB.cjs.map} +1 -1
- package/dist/{chunk-7557LDAN.cjs → chunk-PWBRE7JA.cjs} +5 -5
- package/dist/{chunk-7557LDAN.cjs.map → chunk-PWBRE7JA.cjs.map} +1 -1
- package/dist/{chunk-7PN3YENO.cjs → chunk-QIK7E6VF.cjs} +4 -4
- package/dist/{chunk-7PN3YENO.cjs.map → chunk-QIK7E6VF.cjs.map} +1 -1
- package/dist/{chunk-DWMWEALB.cjs → chunk-TSFNLY3K.cjs} +143 -1634
- package/dist/chunk-TSFNLY3K.cjs.map +1 -0
- package/dist/{chunk-YGBHY67W.cjs → chunk-UA7HOLAZ.cjs} +5 -5
- package/dist/{chunk-YGBHY67W.cjs.map → chunk-UA7HOLAZ.cjs.map} +1 -1
- package/dist/{chunk-KXIRVKCJ.cjs → chunk-UUENH4BJ.cjs} +3 -3
- package/dist/{chunk-KXIRVKCJ.cjs.map → chunk-UUENH4BJ.cjs.map} +1 -1
- package/dist/chunk-WVZLAAIZ.cjs +31 -0
- package/dist/chunk-WVZLAAIZ.cjs.map +1 -0
- package/dist/{chunk-E3L5DB5F.cjs → chunk-YOEP3I4V.cjs} +5 -5
- package/dist/{chunk-E3L5DB5F.cjs.map → chunk-YOEP3I4V.cjs.map} +1 -1
- package/dist/{chunk-SNPK3R3O.cjs → chunk-YVO6Z5BS.cjs} +10 -10
- package/dist/{chunk-SNPK3R3O.cjs.map → chunk-YVO6Z5BS.cjs.map} +1 -1
- package/dist/chunk-ZZZITHGK.cjs +119 -0
- package/dist/chunk-ZZZITHGK.cjs.map +1 -0
- package/dist/connect/docx.cjs +17 -17
- package/dist/connect/index.cjs +994 -994
- package/dist/connect/viewer.cjs +28 -25
- package/dist/connection/presentation/ClippingMediaViewer.js +3 -3
- package/dist/connection/presentation/ClippingMediaViewer.js.map +2 -2
- package/dist/connection/presentation/ClippingPdfViewer.d.ts +4 -3
- package/dist/connection/presentation/ClippingPdfViewer.js +48 -9
- package/dist/connection/presentation/ClippingPdfViewer.js.map +2 -2
- package/dist/connection/presentation/SpotlightLayer.d.ts +5 -0
- package/dist/connection/presentation/SpotlightLayer.js +19 -0
- package/dist/connection/presentation/SpotlightLayer.js.map +7 -0
- package/dist/connection/presentation/SpotlightStrip.d.ts +10 -0
- package/dist/connection/presentation/SpotlightStrip.js +237 -0
- package/dist/connection/presentation/SpotlightStrip.js.map +7 -0
- package/dist/connection/presentation/useViewerClipping.d.ts +4 -3
- package/dist/connection/presentation/useViewerClipping.js +8 -4
- package/dist/connection/presentation/useViewerClipping.js.map +2 -2
- package/dist/connection/viewer/ConnectedDocumentViewer.js +1 -1
- package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
- package/dist/connection/viewer/VersionDropdown.js +1 -1
- package/dist/connection/viewer/VersionDropdown.js.map +1 -1
- package/dist/connection/viewer/ViewerPdfPane.js +2 -0
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/pdf/passageHighlights.d.ts +5 -0
- package/dist/connection/viewer/pdf/passageHighlights.js +14 -1
- package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
- package/dist/connection/viewer/pdf/usePassageTextFallback.d.ts +12 -0
- package/dist/connection/viewer/pdf/usePassageTextFallback.js +30 -0
- package/dist/connection/viewer/pdf/usePassageTextFallback.js.map +7 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +2 -11
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
- package/dist/connection/viewer/useCleanView.d.ts +3 -1
- package/dist/connection/viewer/useCleanView.js +6 -3
- package/dist/connection/viewer/useCleanView.js.map +2 -2
- package/dist/connection/viewer/useViewerTabs.js +13 -1
- package/dist/connection/viewer/useViewerTabs.js.map +2 -2
- package/dist/document-tools/DocumentToolButtons.js +1 -1
- package/dist/document-tools/DocumentToolButtons.js.map +1 -1
- package/dist/document-tools/index.cjs +20 -20
- package/dist/docx/DocxCommandMenu.js +2 -1
- package/dist/docx/DocxCommandMenu.js.map +2 -2
- package/dist/docx/index.cjs +38 -38
- package/dist/embed/index.cjs +20 -20
- package/dist/facts/index.cjs +64 -64
- package/dist/files/index.cjs +223 -223
- package/dist/index.cjs +521 -521
- package/dist/presentation/ClipCaptureOverlay.d.ts +7 -3
- package/dist/presentation/ClipCaptureOverlay.js +43 -14
- package/dist/presentation/ClipCaptureOverlay.js.map +2 -2
- package/dist/presentation/PresentControls.d.ts +8 -0
- package/dist/presentation/PresentControls.js +1 -0
- package/dist/presentation/PresentControls.js.map +2 -2
- package/dist/presentation/PresentationStage.d.ts +10 -2
- package/dist/presentation/PresentationStage.js +6 -3
- package/dist/presentation/PresentationStage.js.map +2 -2
- package/dist/presentation/PresenterView.js +1 -22
- package/dist/presentation/PresenterView.js.map +2 -2
- package/dist/presentation/SpotlightView.d.ts +19 -0
- package/dist/presentation/SpotlightView.js +180 -0
- package/dist/presentation/SpotlightView.js.map +7 -0
- package/dist/presentation/passage-clip.d.ts +17 -0
- package/dist/presentation/passage-clip.js +25 -0
- package/dist/presentation/passage-clip.js.map +7 -0
- package/dist/presentation/spotlight.d.ts +58 -0
- package/dist/presentation/spotlight.js +110 -0
- package/dist/presentation/spotlight.js.map +7 -0
- package/dist/presentation/store.d.ts +5 -0
- package/dist/presentation/store.js +19 -0
- package/dist/presentation/store.js.map +2 -2
- package/dist/presentation/usePointerActive.d.ts +2 -0
- package/dist/presentation/usePointerActive.js +28 -0
- package/dist/presentation/usePointerActive.js.map +7 -0
- package/dist/settings/index.cjs +146 -146
- package/dist/site/index.cjs +6 -6
- package/dist/studio/index.cjs +9 -9
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +35 -35
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ClippingMediaViewer-IEIBT74X.cjs.map +0 -1
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs.map +0 -1
- package/dist/ConnectedPresentation-5DOJ35XL.cjs.map +0 -1
- package/dist/ConnectedSlidesTab-7YMEDGUU.cjs.map +0 -1
- package/dist/FilesViewerDialog-2QCCRWF2.cjs.map +0 -1
- package/dist/chunk-2CSLFAGF.cjs.map +0 -1
- package/dist/chunk-46P7IDBX.cjs.map +0 -1
- package/dist/chunk-4TTX6ZNS.cjs.map +0 -1
- package/dist/chunk-DWMWEALB.cjs.map +0 -1
- package/dist/chunk-JD2HX2BR.cjs.map +0 -1
- package/dist/chunk-SDRYSLOX.cjs +0 -18
- package/dist/chunk-WFMWKPGY.cjs.map +0 -1
- package/dist/chunk-XK4TVJKD.cjs +0 -73
- package/dist/chunk-XK4TVJKD.cjs.map +0 -1
package/dist/connect/viewer.cjs
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
4
|
+
var chunk6JMW3IJ2_cjs = require('../chunk-6JMW3IJ2.cjs');
|
|
5
|
+
require('../chunk-JITYC4OS.cjs');
|
|
6
|
+
require('../chunk-WVZLAAIZ.cjs');
|
|
7
|
+
require('../chunk-MVXHTAJ4.cjs');
|
|
8
|
+
require('../chunk-ADPRIBSH.cjs');
|
|
9
|
+
require('../chunk-ORNLCBNE.cjs');
|
|
7
10
|
require('../chunk-4CIVQWAX.cjs');
|
|
8
11
|
var chunkPL7HUTM3_cjs = require('../chunk-PL7HUTM3.cjs');
|
|
9
12
|
require('../chunk-GFUOCGY6.cjs');
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
12
|
-
require('../chunk-
|
|
13
|
-
require('../chunk-
|
|
13
|
+
require('../chunk-J3FFSEKO.cjs');
|
|
14
|
+
require('../chunk-PWBRE7JA.cjs');
|
|
15
|
+
require('../chunk-4ONPEVTP.cjs');
|
|
16
|
+
require('../chunk-V3KLUWQQ.cjs');
|
|
17
|
+
require('../chunk-CQ2RJYE2.cjs');
|
|
18
|
+
require('../chunk-2K6IMIVL.cjs');
|
|
19
|
+
require('../chunk-JH6JTI76.cjs');
|
|
20
|
+
require('../chunk-ZESMRGDV.cjs');
|
|
21
|
+
require('../chunk-UUENH4BJ.cjs');
|
|
22
|
+
require('../chunk-AS6QZETU.cjs');
|
|
23
|
+
require('../chunk-OHWHYVKG.cjs');
|
|
14
24
|
require('../chunk-HYUKPHCT.cjs');
|
|
15
|
-
require('../chunk-
|
|
25
|
+
require('../chunk-L6HTZIBD.cjs');
|
|
16
26
|
require('../chunk-223D4727.cjs');
|
|
17
27
|
require('../chunk-SNUBQMIS.cjs');
|
|
18
|
-
require('../chunk-7557LDAN.cjs');
|
|
19
|
-
require('../chunk-4ONPEVTP.cjs');
|
|
20
|
-
require('../chunk-V3KLUWQQ.cjs');
|
|
21
28
|
require('../chunk-P5AQYC4D.cjs');
|
|
22
29
|
require('../chunk-WAV762GP.cjs');
|
|
23
|
-
require('../chunk-46P7IDBX.cjs');
|
|
24
|
-
require('../chunk-GNZAH6UI.cjs');
|
|
25
|
-
require('../chunk-JH6JTI76.cjs');
|
|
26
30
|
require('../chunk-QQMMCXBP.cjs');
|
|
27
31
|
require('../chunk-DTMBAFIL.cjs');
|
|
28
|
-
require('../chunk-ZESMRGDV.cjs');
|
|
29
32
|
require('../chunk-VCEX7COE.cjs');
|
|
30
33
|
require('../chunk-34HQO4ZQ.cjs');
|
|
31
34
|
require('../chunk-KA3F6TIH.cjs');
|
|
32
35
|
require('../chunk-K4763GD5.cjs');
|
|
33
36
|
require('../chunk-2RLA6QO2.cjs');
|
|
37
|
+
require('../chunk-BLIO3B7Z.cjs');
|
|
34
38
|
require('../chunk-MZZ3SBQL.cjs');
|
|
35
39
|
require('../chunk-NY3YUCOW.cjs');
|
|
36
40
|
require('../chunk-325GVZE6.cjs');
|
|
@@ -38,30 +42,27 @@ require('../chunk-WQMR3O2D.cjs');
|
|
|
38
42
|
require('../chunk-ORELHENJ.cjs');
|
|
39
43
|
require('../chunk-NWNVWO6L.cjs');
|
|
40
44
|
require('../chunk-SK6HQ46Q.cjs');
|
|
41
|
-
require('../chunk-TG2GM7WJ.cjs');
|
|
42
|
-
require('../chunk-MNIQDXM6.cjs');
|
|
43
|
-
require('../chunk-E3Y7RI3J.cjs');
|
|
44
|
-
require('../chunk-VKH3BEZE.cjs');
|
|
45
45
|
require('../chunk-OEJQFPWO.cjs');
|
|
46
|
+
require('../chunk-TG2GM7WJ.cjs');
|
|
47
|
+
require('../chunk-JJZOL5MG.cjs');
|
|
46
48
|
require('../chunk-OYXWQTHF.cjs');
|
|
47
49
|
require('../chunk-S237ORM3.cjs');
|
|
48
50
|
require('../chunk-II2OEXHW.cjs');
|
|
49
|
-
require('../chunk-JJZOL5MG.cjs');
|
|
50
51
|
require('../chunk-3YEXZX4H.cjs');
|
|
51
52
|
require('../chunk-4PA6VCCR.cjs');
|
|
52
53
|
require('../chunk-WXUU3COI.cjs');
|
|
53
54
|
require('../chunk-AHDJXIUB.cjs');
|
|
54
|
-
require('../chunk-YVCOQHCE.cjs');
|
|
55
55
|
require('../chunk-RL2HI6NP.cjs');
|
|
56
56
|
require('../chunk-6UZC4XVV.cjs');
|
|
57
|
+
require('../chunk-YVCOQHCE.cjs');
|
|
57
58
|
require('../chunk-JV5TVUOU.cjs');
|
|
59
|
+
require('../chunk-VZOOGA47.cjs');
|
|
58
60
|
require('../chunk-ZVEW3JBT.cjs');
|
|
59
61
|
require('../chunk-EG7EJFUE.cjs');
|
|
60
62
|
require('../chunk-VG24E4JJ.cjs');
|
|
61
63
|
require('../chunk-U2FFG2B3.cjs');
|
|
62
64
|
require('../chunk-KKYNTWDU.cjs');
|
|
63
65
|
require('../chunk-M74FWYNL.cjs');
|
|
64
|
-
require('../chunk-VZOOGA47.cjs');
|
|
65
66
|
require('../chunk-HQDR43JC.cjs');
|
|
66
67
|
require('../chunk-JR2YSBD5.cjs');
|
|
67
68
|
require('../chunk-3YZKDCWY.cjs');
|
|
@@ -78,21 +79,23 @@ require('../chunk-KQF7POTG.cjs');
|
|
|
78
79
|
require('../chunk-75BNMCUX.cjs');
|
|
79
80
|
require('../chunk-FX3K6LNZ.cjs');
|
|
80
81
|
require('../chunk-QGVOT7E4.cjs');
|
|
82
|
+
require('../chunk-IPSHAMO2.cjs');
|
|
81
83
|
require('../chunk-QRAQZTJE.cjs');
|
|
82
84
|
require('../chunk-UDSHVNU3.cjs');
|
|
83
|
-
require('../chunk-IPSHAMO2.cjs');
|
|
84
85
|
require('../chunk-PPCATBOY.cjs');
|
|
86
|
+
require('../chunk-LJJJ6CYH.cjs');
|
|
87
|
+
require('../chunk-MNIQDXM6.cjs');
|
|
88
|
+
require('../chunk-E3Y7RI3J.cjs');
|
|
85
89
|
require('../chunk-TKHCIHE2.cjs');
|
|
86
90
|
require('../chunk-JDFBEGQO.cjs');
|
|
87
91
|
require('../chunk-ULWRNGGE.cjs');
|
|
88
|
-
require('../chunk-LJJJ6CYH.cjs');
|
|
89
92
|
require('../chunk-PLIF5CUV.cjs');
|
|
90
93
|
|
|
91
94
|
|
|
92
95
|
|
|
93
96
|
Object.defineProperty(exports, "ConnectedDocumentViewer", {
|
|
94
97
|
enumerable: true,
|
|
95
|
-
get: function () { return
|
|
98
|
+
get: function () { return chunk6JMW3IJ2_cjs.ConnectedDocumentViewer; }
|
|
96
99
|
});
|
|
97
100
|
Object.defineProperty(exports, "ConnectedDocumentToolsProvider", {
|
|
98
101
|
enumerable: true,
|
|
@@ -5,7 +5,7 @@ import { Pause, Play, Plus } from "lucide-react";
|
|
|
5
5
|
import { Button } from "@arbidocs/react/ui";
|
|
6
6
|
import { ClipCaptureOverlay } from "../../presentation/ClipCaptureOverlay.js";
|
|
7
7
|
import { formatTime, mediaCaption } from "../../presentation/model.js";
|
|
8
|
-
import {
|
|
8
|
+
import { useSpotlight } from "../../presentation/spotlight.js";
|
|
9
9
|
import { useObjectUrl } from "../../presentation/useObjectUrl.js";
|
|
10
10
|
const WHOLE = { x: 0, y: 0, w: 1, h: 1 };
|
|
11
11
|
function ClippingMediaViewer({
|
|
@@ -38,7 +38,7 @@ function ClippingMediaViewer({
|
|
|
38
38
|
const capture = useCallback(
|
|
39
39
|
({ rect, aspect }) => {
|
|
40
40
|
const start = kind === "video" ? videoRef.current?.currentTime ?? 0 : void 0;
|
|
41
|
-
|
|
41
|
+
useSpotlight.getState().gather({
|
|
42
42
|
kind,
|
|
43
43
|
documentId,
|
|
44
44
|
fileName,
|
|
@@ -54,7 +54,7 @@ function ClippingMediaViewer({
|
|
|
54
54
|
[kind, documentId, fileName, file]
|
|
55
55
|
);
|
|
56
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
|
|
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 clip it." }),
|
|
58
58
|
/* @__PURE__ */ jsx("div", { className: "relative min-h-0 flex-1 bg-black", style: { containerType: "size" }, children: /* @__PURE__ */ jsxs(
|
|
59
59
|
"div",
|
|
60
60
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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 {
|
|
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,
|
|
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 { useSpotlight } from '../../presentation/spotlight'\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 useSpotlight.getState().gather({\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 clip it.'}\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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The PDF while clipping
|
|
3
|
-
*
|
|
2
|
+
* The PDF while clipping: a click on a passage clips that passage (outlined under the pointer), a
|
|
3
|
+
* drag over a page clips that area. Clips are gathered in the viewer's spotlight strip
|
|
4
|
+
* (`SpotlightStrip`), to show over the document or keep as a slide.
|
|
4
5
|
*
|
|
5
6
|
* Redactions are honoured: when the version has markup, its redaction marks (all but rejected
|
|
6
7
|
* ones) are read first and every clip carries those over its area as black masks, so a redacted
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
* read.
|
|
9
10
|
*/
|
|
10
11
|
import { type ComponentType } from 'react';
|
|
11
|
-
import type
|
|
12
|
+
import { type PdfViewerProps } from '@arbidocs/react/viewers';
|
|
12
13
|
export interface ClippingPdfViewerProps extends Omit<PdfViewerProps, 'renderPageOverlay'> {
|
|
13
14
|
file: Blob;
|
|
14
15
|
documentId: string;
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useState
|
|
8
|
+
} from "react";
|
|
9
|
+
import { useParsedDocument } from "@arbidocs/react";
|
|
4
10
|
import { createMarkupStore, useDocumentTools } from "@arbidocs/react/document-tools";
|
|
11
|
+
import { useProcessedChunks } from "@arbidocs/react/viewers";
|
|
5
12
|
import { ClipCaptureOverlay } from "../../presentation/ClipCaptureOverlay.js";
|
|
6
|
-
import {
|
|
13
|
+
import { passageClipRect } from "../../presentation/passage-clip.js";
|
|
14
|
+
import { useSpotlight } from "../../presentation/spotlight.js";
|
|
15
|
+
import { placedPassagesByPage } from "../viewer/pdf/passageHighlights.js";
|
|
7
16
|
const NO_MASKS = { status: "ready", masks: /* @__PURE__ */ new Map() };
|
|
8
17
|
function useRedactionMasks(documentId, version, hasMarkup) {
|
|
9
18
|
const { client } = useDocumentTools();
|
|
@@ -30,6 +39,20 @@ function useRedactionMasks(documentId, version, hasMarkup) {
|
|
|
30
39
|
}, [client, documentId, version, hasMarkup]);
|
|
31
40
|
return state;
|
|
32
41
|
}
|
|
42
|
+
const NO_FOOTNOTES = {};
|
|
43
|
+
const NO_PASSAGES = /* @__PURE__ */ new Map();
|
|
44
|
+
function usePassageAreas(documentId, current) {
|
|
45
|
+
const { data: parsed } = useParsedDocument(documentId, "final", { enabled: current });
|
|
46
|
+
const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES);
|
|
47
|
+
return useMemo(() => {
|
|
48
|
+
if (!current || !processedChunks.length) return NO_PASSAGES;
|
|
49
|
+
const areas = /* @__PURE__ */ new Map();
|
|
50
|
+
for (const [page, boxes] of placedPassagesByPage(processedChunks)) {
|
|
51
|
+
areas.set(page, boxes.map(passageClipRect));
|
|
52
|
+
}
|
|
53
|
+
return areas;
|
|
54
|
+
}, [current, processedChunks]);
|
|
55
|
+
}
|
|
33
56
|
function Notice({ children }) {
|
|
34
57
|
return /* @__PURE__ */ jsx("div", { className: "border-b border-border bg-muted px-3 py-1.5 text-xs text-muted-foreground", children });
|
|
35
58
|
}
|
|
@@ -42,11 +65,12 @@ function ClippingPdfViewer({
|
|
|
42
65
|
...viewerProps
|
|
43
66
|
}) {
|
|
44
67
|
const masks = useRedactionMasks(documentId, version, hasMarkup);
|
|
68
|
+
const passages = usePassageAreas(documentId, version === void 0);
|
|
45
69
|
const file = viewerProps.file;
|
|
46
70
|
const capture = useCallback(
|
|
47
71
|
({ page, rect, aspect }) => {
|
|
48
72
|
if (masks.status !== "ready") return;
|
|
49
|
-
|
|
73
|
+
useSpotlight.getState().gather({
|
|
50
74
|
kind: "pdf",
|
|
51
75
|
documentId,
|
|
52
76
|
version,
|
|
@@ -61,13 +85,28 @@ function ClippingPdfViewer({
|
|
|
61
85
|
[masks, documentId, version, fileName, file]
|
|
62
86
|
);
|
|
63
87
|
const renderPageOverlay = useCallback(
|
|
64
|
-
({ pageNumber }) => masks.status === "ready" ? /* @__PURE__ */ jsx(
|
|
65
|
-
|
|
88
|
+
({ pageNumber }) => masks.status === "ready" ? /* @__PURE__ */ jsx(
|
|
89
|
+
ClipCaptureOverlay,
|
|
90
|
+
{
|
|
91
|
+
page: pageNumber,
|
|
92
|
+
passages: passages.get(pageNumber),
|
|
93
|
+
onCapture: capture
|
|
94
|
+
}
|
|
95
|
+
) : null,
|
|
96
|
+
[masks.status, capture, passages]
|
|
97
|
+
);
|
|
98
|
+
return /* @__PURE__ */ jsxs(
|
|
99
|
+
"div",
|
|
100
|
+
{
|
|
101
|
+
className: "flex h-full min-h-0 flex-col",
|
|
102
|
+
"data-clip-document": documentId,
|
|
103
|
+
"data-testid": "clipping-pdf-viewer",
|
|
104
|
+
children: [
|
|
105
|
+
/* @__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." : passages.size ? "Click a passage to clip it, or drag over any area." : "Drag over the part of a page to clip it." }),
|
|
106
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(Viewer, { ...viewerProps, renderPageOverlay }) })
|
|
107
|
+
]
|
|
108
|
+
}
|
|
66
109
|
);
|
|
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
110
|
}
|
|
72
111
|
export {
|
|
73
112
|
ClippingPdfViewer
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/presentation/ClippingPdfViewer.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The PDF while clipping
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * The PDF while clipping: a click on a passage clips that passage (outlined under the pointer), a\n * drag over a page clips that area. Clips are gathered in the viewer's spotlight strip\n * (`SpotlightStrip`), to show over the document or keep as a slide.\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 {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport { useParsedDocument } from '@arbidocs/react'\nimport { createMarkupStore, useDocumentTools } from '@arbidocs/react/document-tools'\nimport { useProcessedChunks, type PdfViewerProps } from '@arbidocs/react/viewers'\nimport { ClipCaptureOverlay } from '../../presentation/ClipCaptureOverlay'\nimport type { Rect } from '../../presentation/model'\nimport { passageClipRect } from '../../presentation/passage-clip'\nimport { useSpotlight } from '../../presentation/spotlight'\nimport { placedPassagesByPage } from '../viewer/pdf/passageHighlights'\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\nconst NO_FOOTNOTES: Record<string, string> = {}\nconst NO_PASSAGES: ReadonlyMap<number, Rect[]> = new Map()\n\n/**\n * The areas a click clips, by page: each passage the parser placed, with its margin. Only for the\n * current version (the passages are its own); an older one is clipped by dragging.\n */\nfunction usePassageAreas(documentId: string, current: boolean): ReadonlyMap<number, Rect[]> {\n const { data: parsed } = useParsedDocument(documentId, 'final', { enabled: current })\n const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES)\n return useMemo(() => {\n if (!current || !processedChunks.length) return NO_PASSAGES\n const areas = new Map<number, Rect[]>()\n for (const [page, boxes] of placedPassagesByPage(processedChunks)) {\n areas.set(page, boxes.map(passageClipRect))\n }\n return areas\n }, [current, processedChunks])\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 passages = usePassageAreas(documentId, version === undefined)\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 useSpotlight.getState().gather({\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 viewer's spotlight strip.\n },\n [masks, documentId, version, fileName, file]\n )\n\n const renderPageOverlay = useCallback(\n ({ pageNumber }: { pageNumber: number }) =>\n masks.status === 'ready' ? (\n <ClipCaptureOverlay\n page={pageNumber}\n passages={passages.get(pageNumber)}\n onCapture={capture}\n />\n ) : null,\n [masks.status, capture, passages]\n )\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-col\"\n // The spotlight finds a clip's page here, to fly it from there.\n data-clip-document={documentId}\n data-testid=\"clipping-pdf-viewer\"\n >\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 : passages.size\n ? 'Click a passage to clip it, or drag over any area.'\n : 'Drag over the part of a page to clip it.'}\n </Notice>\n <div className=\"min-h-0 flex-1\">\n <Viewer {...viewerProps} renderPageOverlay={renderPageOverlay} />\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The viewer's spotlight, over its body: nothing until a clip is gathered, then the strip of
|
|
3
|
+
* gathered clips and, when shown, the spotlight itself (their own chunk, loaded then).
|
|
4
|
+
*/
|
|
5
|
+
export declare function SpotlightLayer(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { lazy, Suspense, useEffect } from "react";
|
|
4
|
+
import { useSpotlight } from "../../presentation/spotlight.js";
|
|
5
|
+
import { useConnectedWorkspace } from "../ConnectionProvider.js";
|
|
6
|
+
const SpotlightStrip = lazy(
|
|
7
|
+
() => import("./SpotlightStrip.js").then((m) => ({ default: m.SpotlightStrip }))
|
|
8
|
+
);
|
|
9
|
+
function SpotlightLayer() {
|
|
10
|
+
const { userId } = useConnectedWorkspace();
|
|
11
|
+
const gathered = useSpotlight((s) => s.clips.length > 0);
|
|
12
|
+
useEffect(() => useSpotlight.getState().own(userId ?? null), [userId]);
|
|
13
|
+
if (!gathered) return null;
|
|
14
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(SpotlightStrip, {}) });
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
SpotlightLayer
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=SpotlightLayer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/connection/presentation/SpotlightLayer.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * The viewer's spotlight, over its body: nothing until a clip is gathered, then the strip of\n * gathered clips and, when shown, the spotlight itself (their own chunk, loaded then).\n */\n\nimport { lazy, Suspense, useEffect } from 'react'\nimport { useSpotlight } from '../../presentation/spotlight'\nimport { useConnectedWorkspace } from '../ConnectionProvider'\n\nconst SpotlightStrip = lazy(() =>\n import('./SpotlightStrip').then((m) => ({ default: m.SpotlightStrip }))\n)\n\nexport function SpotlightLayer() {\n // Clips gathered by another user are dropped.\n const { userId } = useConnectedWorkspace()\n const gathered = useSpotlight((s) => s.clips.length > 0)\n useEffect(() => useSpotlight.getState().own(userId ?? null), [userId])\n if (!gathered) return null\n return (\n <Suspense fallback={null}>\n <SpotlightStrip />\n </Suspense>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAqBM;AAhBN,SAAS,MAAM,UAAU,iBAAiB;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,6BAA6B;AAEtC,MAAM,iBAAiB;AAAA,EAAK,MAC1B,OAAO,kBAAkB,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE;AACxE;AAEO,SAAS,iBAAiB;AAE/B,QAAM,EAAE,OAAO,IAAI,sBAAsB;AACzC,QAAM,WAAW,aAAa,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC;AACvD,YAAU,MAAM,aAAa,SAAS,EAAE,IAAI,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC;AACrE,MAAI,CAAC,SAAU,QAAO;AACtB,SACE,oBAAC,YAAS,UAAU,MAClB,8BAAC,kBAAe,GAClB;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The clips gathered in the viewer, in a small strip over the document: each clip (× takes it
|
|
3
|
+
* out), a note to show as the spotlight's title, another document to clip from, and Show (or S),
|
|
4
|
+
* which puts them in the spotlight over this same viewer. Rarer actions — keep them as a slide,
|
|
5
|
+
* add them to the presentation's tray, clear them — are in its "…" menu.
|
|
6
|
+
*
|
|
7
|
+
* The strip and the spotlight stay over whichever document the viewer shows, so clips are gathered
|
|
8
|
+
* from several documents in a row. Esc brings the document back where it was scrolled to.
|
|
9
|
+
*/
|
|
10
|
+
export declare function SpotlightStrip(): import("react").JSX.Element;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { Eraser, MoreHorizontal, Inbox, Presentation, StickyNote, X } from "lucide-react";
|
|
5
|
+
import { useArbiSessionStore, useDocuments } from "@arbidocs/react";
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
DropdownMenu,
|
|
9
|
+
DropdownMenuContent,
|
|
10
|
+
DropdownMenuItem,
|
|
11
|
+
DropdownMenuTrigger,
|
|
12
|
+
Input,
|
|
13
|
+
Popover,
|
|
14
|
+
PopoverContent,
|
|
15
|
+
PopoverTrigger,
|
|
16
|
+
cn,
|
|
17
|
+
getDocumentTitle
|
|
18
|
+
} from "@arbidocs/react/ui";
|
|
19
|
+
import { ClipImage } from "../../presentation/ClipImage.js";
|
|
20
|
+
import { SpotlightView } from "../../presentation/SpotlightView.js";
|
|
21
|
+
import { useSpotlight } from "../../presentation/spotlight.js";
|
|
22
|
+
import { DocumentPicker } from "../../settings/DocumentPicker.js";
|
|
23
|
+
const frameOf = (node) => node?.closest('[data-slot="viewer-frame"]') ?? null;
|
|
24
|
+
const isTyping = (target) => !!target?.closest?.('input, textarea, select, [contenteditable="true"]');
|
|
25
|
+
function clipOnPage(frame, clip) {
|
|
26
|
+
const clipped = Array.from(frame.querySelectorAll("[data-clip-document]")).find(
|
|
27
|
+
(element) => element.getAttribute("data-clip-document") === clip.documentId
|
|
28
|
+
);
|
|
29
|
+
const page = clipped?.querySelector(`[data-page-number="${clip.page}"]`);
|
|
30
|
+
if (!page) return null;
|
|
31
|
+
const box = page.getBoundingClientRect();
|
|
32
|
+
const view = frame.ownerDocument.defaultView;
|
|
33
|
+
const rect = {
|
|
34
|
+
left: box.left + clip.rect.x * box.width,
|
|
35
|
+
top: box.top + clip.rect.y * box.height,
|
|
36
|
+
width: clip.rect.w * box.width,
|
|
37
|
+
height: clip.rect.h * box.height
|
|
38
|
+
};
|
|
39
|
+
const visible = rect.width > 0 && rect.top + rect.height > 0 && rect.left + rect.width > 0 && (!view || rect.top < view.innerHeight && rect.left < view.innerWidth);
|
|
40
|
+
return visible ? rect : null;
|
|
41
|
+
}
|
|
42
|
+
function useDocumentSwitcher(clips) {
|
|
43
|
+
const session = useArbiSessionStore();
|
|
44
|
+
const { data: documents } = useDocuments();
|
|
45
|
+
const groups = useMemo(() => {
|
|
46
|
+
const all = (documents ?? []).map((doc) => ({
|
|
47
|
+
id: doc.external_id,
|
|
48
|
+
title: getDocumentTitle(doc, "Untitled"),
|
|
49
|
+
fileName: doc.file_name
|
|
50
|
+
})).sort((a, b) => a.title.localeCompare(b.title));
|
|
51
|
+
const clipped = new Set(clips.map((clip) => clip.documentId));
|
|
52
|
+
const from = all.filter((doc) => clipped.has(doc.id));
|
|
53
|
+
return [
|
|
54
|
+
...from.length ? [{ id: "clipped", heading: "Clipped from", docs: from }] : [],
|
|
55
|
+
{ id: "all", heading: "Documents", docs: all }
|
|
56
|
+
];
|
|
57
|
+
}, [documents, clips]);
|
|
58
|
+
const open = (id) => session.setViewingDocument({ id, page: null });
|
|
59
|
+
return { groups, open };
|
|
60
|
+
}
|
|
61
|
+
function SpotlightStrip() {
|
|
62
|
+
const clips = useSpotlight((s) => s.clips);
|
|
63
|
+
const note = useSpotlight((s) => s.note);
|
|
64
|
+
const showing = useSpotlight((s) => s.showing);
|
|
65
|
+
const actions = useSpotlight.getState();
|
|
66
|
+
const switcher = useDocumentSwitcher(clips);
|
|
67
|
+
const [noteOpen, setNoteOpen] = useState(false);
|
|
68
|
+
const strip = useRef(null);
|
|
69
|
+
const [view, setView] = useState(null);
|
|
70
|
+
const stripRef = useCallback((node) => {
|
|
71
|
+
strip.current = node;
|
|
72
|
+
if (node) setView(node.ownerDocument.defaultView);
|
|
73
|
+
}, []);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!view || showing) return;
|
|
76
|
+
const onKeyDown = (event) => {
|
|
77
|
+
if (event.metaKey || event.ctrlKey || event.altKey || isTyping(event.target)) return;
|
|
78
|
+
if (event.key !== "s" && event.key !== "S") return;
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
useSpotlight.getState().show();
|
|
81
|
+
};
|
|
82
|
+
view.addEventListener("keydown", onKeyDown);
|
|
83
|
+
return () => view.removeEventListener("keydown", onKeyDown);
|
|
84
|
+
}, [view, showing]);
|
|
85
|
+
const scrolled = useRef(null);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const scroller = frameOf(strip.current)?.querySelector(
|
|
88
|
+
'[data-slot="pdf-scroller"]'
|
|
89
|
+
);
|
|
90
|
+
if (showing) {
|
|
91
|
+
scrolled.current = scroller ? { element: scroller, top: scroller.scrollTop, left: scroller.scrollLeft } : null;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const before = scrolled.current;
|
|
95
|
+
scrolled.current = null;
|
|
96
|
+
if (before?.element.isConnected) {
|
|
97
|
+
before.element.scrollTop = before.top;
|
|
98
|
+
before.element.scrollLeft = before.left;
|
|
99
|
+
}
|
|
100
|
+
}, [showing]);
|
|
101
|
+
const fromRect = useCallback((clip) => {
|
|
102
|
+
const frame = frameOf(strip.current);
|
|
103
|
+
const onPage = frame ? clipOnPage(frame, clip) : null;
|
|
104
|
+
return onPage ?? strip.current?.querySelector(`[data-spotlight-clip="${clip.id}"]`)?.getBoundingClientRect() ?? null;
|
|
105
|
+
}, []);
|
|
106
|
+
const count = `${clips.length} clip${clips.length === 1 ? "" : "s"}`;
|
|
107
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
108
|
+
/* @__PURE__ */ jsxs(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
ref: stripRef,
|
|
112
|
+
className: cn(
|
|
113
|
+
"absolute bottom-[4.5rem] left-1/2 z-20 flex max-w-[calc(100%-1.5rem)] -translate-x-1/2 items-center gap-1.5 rounded-full border border-border bg-background/95 p-1 pl-1.5 shadow-lg backdrop-blur",
|
|
114
|
+
showing && "invisible"
|
|
115
|
+
),
|
|
116
|
+
role: "toolbar",
|
|
117
|
+
"aria-label": "Gathered clips",
|
|
118
|
+
"data-testid": "spotlight-strip",
|
|
119
|
+
children: [
|
|
120
|
+
/* @__PURE__ */ jsx("ul", { className: "flex min-w-0 items-center gap-1 overflow-x-auto [scrollbar-width:none]", children: clips.map((clip, index) => /* @__PURE__ */ jsxs(
|
|
121
|
+
"li",
|
|
122
|
+
{
|
|
123
|
+
className: "group relative h-8 shrink-0 overflow-hidden rounded-md border border-border bg-white",
|
|
124
|
+
style: { width: `${Math.min(4.5, Math.max(1.5, 2 * clip.aspect))}rem` },
|
|
125
|
+
title: clip.caption,
|
|
126
|
+
"data-spotlight-clip": clip.id,
|
|
127
|
+
"data-testid": `spotlight-chip-${index}`,
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ jsx(ClipImage, { clip, className: "h-full w-full" }),
|
|
130
|
+
/* @__PURE__ */ jsx(
|
|
131
|
+
"button",
|
|
132
|
+
{
|
|
133
|
+
type: "button",
|
|
134
|
+
className: "absolute inset-0 flex items-center justify-center bg-black/50 text-white opacity-0 transition-opacity focus-visible:opacity-100 group-hover:opacity-100",
|
|
135
|
+
onClick: () => actions.remove(clip.id),
|
|
136
|
+
"aria-label": `Remove ${clip.caption}`,
|
|
137
|
+
"data-testid": `spotlight-remove-${index}`,
|
|
138
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
clip.id
|
|
144
|
+
)) }),
|
|
145
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-muted-foreground", "data-testid": "spotlight-count", children: count }),
|
|
146
|
+
/* @__PURE__ */ jsxs(Popover, { open: noteOpen, onOpenChange: setNoteOpen, children: [
|
|
147
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
148
|
+
Button,
|
|
149
|
+
{
|
|
150
|
+
type: "button",
|
|
151
|
+
variant: note ? "secondary" : "ghost",
|
|
152
|
+
size: "sm",
|
|
153
|
+
className: "h-7 max-w-40 shrink-0 gap-1 rounded-full px-2 text-xs",
|
|
154
|
+
title: note ? `Note: ${note}` : "Type a note to show as the title",
|
|
155
|
+
"data-testid": "spotlight-note",
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ jsx(StickyNote, { className: "size-3.5 shrink-0" }),
|
|
158
|
+
note ? /* @__PURE__ */ jsx("span", { className: "truncate", children: note }) : /* @__PURE__ */ jsx("span", { children: "Note" })
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
) }),
|
|
162
|
+
/* @__PURE__ */ jsx(PopoverContent, { side: "top", className: "w-72 p-2", children: /* @__PURE__ */ jsx(
|
|
163
|
+
Input,
|
|
164
|
+
{
|
|
165
|
+
autoFocus: true,
|
|
166
|
+
value: note,
|
|
167
|
+
placeholder: "Type a note",
|
|
168
|
+
onChange: (event) => actions.setNote(event.target.value),
|
|
169
|
+
onKeyDown: (event) => {
|
|
170
|
+
if (event.key === "Enter") setNoteOpen(false);
|
|
171
|
+
},
|
|
172
|
+
"data-testid": "spotlight-note-input"
|
|
173
|
+
}
|
|
174
|
+
) })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsx("div", { className: "w-44 shrink-0 [&_[role=combobox]]:h-7 [&_[role=combobox]]:rounded-full [&_[role=combobox]]:text-xs", children: /* @__PURE__ */ jsx(
|
|
177
|
+
DocumentPicker,
|
|
178
|
+
{
|
|
179
|
+
groups: switcher.groups,
|
|
180
|
+
value: "",
|
|
181
|
+
onValueChange: switcher.open,
|
|
182
|
+
labels: { placeholder: "Clip another document" }
|
|
183
|
+
}
|
|
184
|
+
) }),
|
|
185
|
+
/* @__PURE__ */ jsxs(
|
|
186
|
+
Button,
|
|
187
|
+
{
|
|
188
|
+
type: "button",
|
|
189
|
+
size: "sm",
|
|
190
|
+
className: "h-7 shrink-0 gap-1 rounded-full px-3 text-xs",
|
|
191
|
+
onClick: actions.show,
|
|
192
|
+
title: "Show the clips over the document (S)",
|
|
193
|
+
"data-testid": "spotlight-show",
|
|
194
|
+
children: [
|
|
195
|
+
/* @__PURE__ */ jsx(Presentation, { className: "size-3.5" }),
|
|
196
|
+
"Show"
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
201
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
202
|
+
Button,
|
|
203
|
+
{
|
|
204
|
+
type: "button",
|
|
205
|
+
variant: "ghost",
|
|
206
|
+
size: "icon",
|
|
207
|
+
className: "size-7 shrink-0 rounded-full",
|
|
208
|
+
"aria-label": "More",
|
|
209
|
+
"data-testid": "spotlight-more",
|
|
210
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" })
|
|
211
|
+
}
|
|
212
|
+
) }),
|
|
213
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", side: "top", children: [
|
|
214
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: actions.keep, "data-testid": "spotlight-menu-keep", children: [
|
|
215
|
+
/* @__PURE__ */ jsx(Presentation, { className: "mr-2 size-4" }),
|
|
216
|
+
" Keep as slide"
|
|
217
|
+
] }),
|
|
218
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: actions.addToTray, "data-testid": "spotlight-menu-tray", children: [
|
|
219
|
+
/* @__PURE__ */ jsx(Inbox, { className: "mr-2 size-4" }),
|
|
220
|
+
" Add to the presentation tray"
|
|
221
|
+
] }),
|
|
222
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: actions.clear, "data-testid": "spotlight-menu-clear", children: [
|
|
223
|
+
/* @__PURE__ */ jsx(Eraser, { className: "mr-2 size-4" }),
|
|
224
|
+
" Clear the clips"
|
|
225
|
+
] })
|
|
226
|
+
] })
|
|
227
|
+
] })
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
showing && /* @__PURE__ */ jsx(SpotlightView, { fromRect })
|
|
232
|
+
] });
|
|
233
|
+
}
|
|
234
|
+
export {
|
|
235
|
+
SpotlightStrip
|
|
236
|
+
};
|
|
237
|
+
//# sourceMappingURL=SpotlightStrip.js.map
|