@arbidocs/blocks 0.5.119 → 0.5.121

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/dist/ClippingMediaViewer-B6WG7Q64.cjs +156 -0
  2. package/dist/ClippingMediaViewer-B6WG7Q64.cjs.map +1 -0
  3. package/dist/ClippingPdfViewer-6GCVTV3V.cjs +79 -0
  4. package/dist/ClippingPdfViewer-6GCVTV3V.cjs.map +1 -0
  5. package/dist/{ConnectedCallDock-WER7R222.cjs → ConnectedCallDock-DC5V5OUJ.cjs} +25 -23
  6. package/dist/ConnectedCallDock-DC5V5OUJ.cjs.map +1 -0
  7. package/dist/{ConnectedCallRoom-T7OBQTYP.cjs → ConnectedCallRoom-FQLXWTFB.cjs} +18 -16
  8. package/dist/{ConnectedCallRoom-T7OBQTYP.cjs.map → ConnectedCallRoom-FQLXWTFB.cjs.map} +1 -1
  9. package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs → ConnectedNativeDocxComparison-4Q5S7VLD.cjs} +17 -17
  10. package/dist/{ConnectedNativeDocxComparison-546ILGLW.cjs.map → ConnectedNativeDocxComparison-4Q5S7VLD.cjs.map} +1 -1
  11. package/dist/ConnectedPresentation-4HLDZDWV.cjs +183 -0
  12. package/dist/ConnectedPresentation-4HLDZDWV.cjs.map +1 -0
  13. package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs → ConnectedProductionSetDialog-4EAY6KAZ.cjs} +3 -3
  14. package/dist/{ConnectedProductionSetDialog-LHB4VQWC.cjs.map → ConnectedProductionSetDialog-4EAY6KAZ.cjs.map} +1 -1
  15. package/dist/ConnectedSlidesTab-7QDE2CZD.cjs +234 -0
  16. package/dist/ConnectedSlidesTab-7QDE2CZD.cjs.map +1 -0
  17. package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs → ConnectedStreamedWordArtifact-FFOQJBOI.cjs} +17 -17
  18. package/dist/{ConnectedStreamedWordArtifact-S2ZFZLZQ.cjs.map → ConnectedStreamedWordArtifact-FFOQJBOI.cjs.map} +1 -1
  19. package/dist/{DocumentReviewCard-ZSBZBGFK.cjs → DocumentReviewCard-SNWVEZ7S.cjs} +19 -18
  20. package/dist/DocumentReviewCard-SNWVEZ7S.cjs.map +1 -0
  21. package/dist/{FilesViewerDialog-6UKR5WEF.cjs → FilesViewerDialog-IZI63FOV.cjs} +54 -47
  22. package/dist/FilesViewerDialog-IZI63FOV.cjs.map +1 -0
  23. package/dist/{GridViewImpl-ZMJJWTOM.cjs → GridViewImpl-LTYET77Q.cjs} +3 -3
  24. package/dist/GridViewImpl-LTYET77Q.cjs.map +1 -0
  25. package/dist/{WorkspaceTableView-J3C6VH4T.cjs → WorkspaceTableView-TEIRB6VJ.cjs} +11 -10
  26. package/dist/WorkspaceTableView-TEIRB6VJ.cjs.map +1 -0
  27. package/dist/agents/index.cjs +297 -297
  28. package/dist/agents/tasks/ConversationListView.js +10 -2
  29. package/dist/agents/tasks/ConversationListView.js.map +2 -2
  30. package/dist/agents/tasks/TaskTable.js +5 -4
  31. package/dist/agents/tasks/TaskTable.js.map +2 -2
  32. package/dist/agents/tasks/WorkflowsTable.js +4 -5
  33. package/dist/agents/tasks/WorkflowsTable.js.map +2 -2
  34. package/dist/agents/tasks/taskColumns.js +1 -1
  35. package/dist/agents/tasks/taskColumns.js.map +1 -1
  36. package/dist/agents/tasks/taskTableLabels.js +1 -1
  37. package/dist/agents/tasks/taskTableLabels.js.map +1 -1
  38. package/dist/agents/tasks/workflowTableLabels.js +1 -1
  39. package/dist/agents/tasks/workflowTableLabels.js.map +1 -1
  40. package/dist/{ai-IM4A23YT.cjs → ai-KBYNRNZ6.cjs} +28 -26
  41. package/dist/ai-KBYNRNZ6.cjs.map +1 -0
  42. package/dist/calls/connected/CallControls.d.ts +2 -0
  43. package/dist/calls/connected/CallControls.js +71 -9
  44. package/dist/calls/connected/CallControls.js.map +2 -2
  45. package/dist/calls/connected/ShareDocumentDialog.d.ts +14 -0
  46. package/dist/calls/connected/ShareDocumentDialog.js +77 -0
  47. package/dist/calls/connected/ShareDocumentDialog.js.map +7 -0
  48. package/dist/calls/index.cjs +121 -121
  49. package/dist/chat/index.cjs +9 -8
  50. package/dist/{chunk-T23UTIRI.cjs → chunk-2PZT3J34.cjs} +6 -6
  51. package/dist/{chunk-T23UTIRI.cjs.map → chunk-2PZT3J34.cjs.map} +1 -1
  52. package/dist/{chunk-SGYSDABK.cjs → chunk-2W5E62EY.cjs} +6 -6
  53. package/dist/{chunk-SGYSDABK.cjs.map → chunk-2W5E62EY.cjs.map} +1 -1
  54. package/dist/{chunk-TDO5UWXF.cjs → chunk-3SCNXNHI.cjs} +5 -5
  55. package/dist/{chunk-TDO5UWXF.cjs.map → chunk-3SCNXNHI.cjs.map} +1 -1
  56. package/dist/{chunk-KTQOGT2L.cjs → chunk-474GPLCM.cjs} +7 -7
  57. package/dist/{chunk-KTQOGT2L.cjs.map → chunk-474GPLCM.cjs.map} +1 -1
  58. package/dist/{chunk-TP5PGWIO.cjs → chunk-4IOYQLKG.cjs} +3 -3
  59. package/dist/{chunk-TP5PGWIO.cjs.map → chunk-4IOYQLKG.cjs.map} +1 -1
  60. package/dist/{chunk-NY3YUCOW.cjs → chunk-4NPCDS2X.cjs} +3 -3
  61. package/dist/{chunk-NY3YUCOW.cjs.map → chunk-4NPCDS2X.cjs.map} +1 -1
  62. package/dist/{chunk-CPG7II4E.cjs → chunk-4RBQ44RY.cjs} +28 -28
  63. package/dist/chunk-4RBQ44RY.cjs.map +1 -0
  64. package/dist/{chunk-BQ5RIWWT.cjs → chunk-4VZZWYEC.cjs} +3 -3
  65. package/dist/{chunk-BQ5RIWWT.cjs.map → chunk-4VZZWYEC.cjs.map} +1 -1
  66. package/dist/{chunk-Y24V6HPR.cjs → chunk-52KGMAO5.cjs} +15 -15
  67. package/dist/{chunk-Y24V6HPR.cjs.map → chunk-52KGMAO5.cjs.map} +1 -1
  68. package/dist/{chunk-HB2O4THB.cjs → chunk-5534FYXP.cjs} +4 -4
  69. package/dist/{chunk-HB2O4THB.cjs.map → chunk-5534FYXP.cjs.map} +1 -1
  70. package/dist/chunk-5GCCUXMT.cjs +63 -0
  71. package/dist/chunk-5GCCUXMT.cjs.map +1 -0
  72. package/dist/chunk-5LTIZ44D.cjs +95 -0
  73. package/dist/chunk-5LTIZ44D.cjs.map +1 -0
  74. package/dist/{chunk-YGXOKB5Z.cjs → chunk-734NPQNR.cjs} +4 -4
  75. package/dist/{chunk-YGXOKB5Z.cjs.map → chunk-734NPQNR.cjs.map} +1 -1
  76. package/dist/{chunk-SB4M3ITT.cjs → chunk-7VUJGHMY.cjs} +444 -100
  77. package/dist/chunk-7VUJGHMY.cjs.map +1 -0
  78. package/dist/chunk-AFQTQC7A.cjs +35 -0
  79. package/dist/chunk-AFQTQC7A.cjs.map +1 -0
  80. package/dist/{chunk-XKVPSOKP.cjs → chunk-AY6EZSZB.cjs} +4 -4
  81. package/dist/{chunk-XKVPSOKP.cjs.map → chunk-AY6EZSZB.cjs.map} +1 -1
  82. package/dist/{chunk-TT4IF52H.cjs → chunk-BVAT4EVC.cjs} +40 -41
  83. package/dist/chunk-BVAT4EVC.cjs.map +1 -0
  84. package/dist/{chunk-VGCTYTEW.cjs → chunk-C2OICDMI.cjs} +10 -10
  85. package/dist/{chunk-VGCTYTEW.cjs.map → chunk-C2OICDMI.cjs.map} +1 -1
  86. package/dist/{chunk-CPR6EHG7.cjs → chunk-DR2AH7JL.cjs} +179 -55
  87. package/dist/chunk-DR2AH7JL.cjs.map +1 -0
  88. package/dist/{chunk-NJCK6V6U.cjs → chunk-EATIFPKP.cjs} +4 -60
  89. package/dist/chunk-EATIFPKP.cjs.map +1 -0
  90. package/dist/{chunk-B3LZITVF.cjs → chunk-EHP6OH5D.cjs} +11 -451
  91. package/dist/chunk-EHP6OH5D.cjs.map +1 -0
  92. package/dist/{chunk-DDIW4HLU.cjs → chunk-ENGL7P3I.cjs} +46 -37
  93. package/dist/chunk-ENGL7P3I.cjs.map +1 -0
  94. package/dist/{chunk-QHOHDNBU.cjs → chunk-FKFQCK3C.cjs} +4 -4
  95. package/dist/{chunk-QHOHDNBU.cjs.map → chunk-FKFQCK3C.cjs.map} +1 -1
  96. package/dist/{chunk-6UTKM5AB.cjs → chunk-GKVE5JGB.cjs} +76 -76
  97. package/dist/chunk-GKVE5JGB.cjs.map +1 -0
  98. package/dist/{chunk-B2HNNG25.cjs → chunk-GPX5VC57.cjs} +50 -50
  99. package/dist/{chunk-B2HNNG25.cjs.map → chunk-GPX5VC57.cjs.map} +1 -1
  100. package/dist/{chunk-WAV762GP.cjs → chunk-GQXPNIRE.cjs} +6 -6
  101. package/dist/{chunk-WAV762GP.cjs.map → chunk-GQXPNIRE.cjs.map} +1 -1
  102. package/dist/chunk-GX2EBMJW.cjs +133 -0
  103. package/dist/chunk-GX2EBMJW.cjs.map +1 -0
  104. package/dist/{chunk-7OPOPYV6.cjs → chunk-H5OLHP2U.cjs} +3 -3
  105. package/dist/{chunk-7OPOPYV6.cjs.map → chunk-H5OLHP2U.cjs.map} +1 -1
  106. package/dist/chunk-HYUKPHCT.cjs +66 -0
  107. package/dist/chunk-HYUKPHCT.cjs.map +1 -0
  108. package/dist/{chunk-NNUK5ZM7.cjs → chunk-JQLWKNJO.cjs} +29 -27
  109. package/dist/chunk-JQLWKNJO.cjs.map +1 -0
  110. package/dist/{chunk-OEREKAAP.cjs → chunk-JZEYHDWJ.cjs} +75 -75
  111. package/dist/{chunk-OEREKAAP.cjs.map → chunk-JZEYHDWJ.cjs.map} +1 -1
  112. package/dist/{chunk-PGJYD67F.cjs → chunk-KNGZZC4O.cjs} +7 -6
  113. package/dist/chunk-KNGZZC4O.cjs.map +1 -0
  114. package/dist/{chunk-NIE3N6OM.cjs → chunk-KP5AITQ4.cjs} +10 -10
  115. package/dist/{chunk-NIE3N6OM.cjs.map → chunk-KP5AITQ4.cjs.map} +1 -1
  116. package/dist/{chunk-YYPZOEED.cjs → chunk-LHWOKOMP.cjs} +23 -2
  117. package/dist/chunk-LHWOKOMP.cjs.map +1 -0
  118. package/dist/{chunk-57NHXEU2.cjs → chunk-MXBXZXXQ.cjs} +5 -5
  119. package/dist/{chunk-57NHXEU2.cjs.map → chunk-MXBXZXXQ.cjs.map} +1 -1
  120. package/dist/{chunk-WXUU3COI.cjs → chunk-MZ2KZXNU.cjs} +3 -3
  121. package/dist/{chunk-WXUU3COI.cjs.map → chunk-MZ2KZXNU.cjs.map} +1 -1
  122. package/dist/chunk-NAJN32MF.cjs +154 -0
  123. package/dist/chunk-NAJN32MF.cjs.map +1 -0
  124. package/dist/{chunk-557MJ4IH.cjs → chunk-NLOETJCB.cjs} +17 -154
  125. package/dist/chunk-NLOETJCB.cjs.map +1 -0
  126. package/dist/{chunk-4XJEHKVZ.cjs → chunk-PIYYBPHH.cjs} +4 -4
  127. package/dist/{chunk-4XJEHKVZ.cjs.map → chunk-PIYYBPHH.cjs.map} +1 -1
  128. package/dist/chunk-Q3XJUXID.cjs +4774 -0
  129. package/dist/chunk-Q3XJUXID.cjs.map +1 -0
  130. package/dist/{chunk-325GVZE6.cjs → chunk-Q6DQGGP4.cjs} +3 -3
  131. package/dist/{chunk-325GVZE6.cjs.map → chunk-Q6DQGGP4.cjs.map} +1 -1
  132. package/dist/chunk-QFXILJMJ.cjs +458 -0
  133. package/dist/chunk-QFXILJMJ.cjs.map +1 -0
  134. package/dist/{chunk-R7CJEIA5.cjs → chunk-RYVZDFVO.cjs} +8 -9
  135. package/dist/chunk-RYVZDFVO.cjs.map +1 -0
  136. package/dist/{chunk-VLCY46K6.cjs → chunk-TG2GM7WJ.cjs} +4 -3
  137. package/dist/chunk-TG2GM7WJ.cjs.map +1 -0
  138. package/dist/{chunk-EOG6OT5I.cjs → chunk-TXP2N3DC.cjs} +4 -4
  139. package/dist/{chunk-EOG6OT5I.cjs.map → chunk-TXP2N3DC.cjs.map} +1 -1
  140. package/dist/{chunk-KXIRVKCJ.cjs → chunk-UUENH4BJ.cjs} +3 -3
  141. package/dist/{chunk-KXIRVKCJ.cjs.map → chunk-UUENH4BJ.cjs.map} +1 -1
  142. package/dist/chunk-VJ5ZLRBD.cjs +27 -0
  143. package/dist/chunk-VJ5ZLRBD.cjs.map +1 -0
  144. package/dist/{chunk-P77YTTJ3.cjs → chunk-W6B3RYTX.cjs} +4 -4
  145. package/dist/{chunk-P77YTTJ3.cjs.map → chunk-W6B3RYTX.cjs.map} +1 -1
  146. package/dist/chunk-WOOOMTTA.cjs +19 -0
  147. package/dist/chunk-WOOOMTTA.cjs.map +1 -0
  148. package/dist/{chunk-ZPPMAL5P.cjs → chunk-WQMR3O2D.cjs} +6 -10
  149. package/dist/chunk-WQMR3O2D.cjs.map +1 -0
  150. package/dist/{chunk-CJYWHUZR.cjs → chunk-XCKHOXRP.cjs} +4 -4
  151. package/dist/{chunk-CJYWHUZR.cjs.map → chunk-XCKHOXRP.cjs.map} +1 -1
  152. package/dist/{chunk-6WMMZLEV.cjs → chunk-XJEXFEWG.cjs} +2 -27
  153. package/dist/chunk-XJEXFEWG.cjs.map +1 -0
  154. package/dist/chunk-XK4TVJKD.cjs +73 -0
  155. package/dist/chunk-XK4TVJKD.cjs.map +1 -0
  156. package/dist/chunk-XTR26TNE.cjs +1358 -0
  157. package/dist/chunk-XTR26TNE.cjs.map +1 -0
  158. package/dist/{chunk-E7TE2WVT.cjs → chunk-ZVEW3JBT.cjs} +3 -3
  159. package/dist/{chunk-E7TE2WVT.cjs.map → chunk-ZVEW3JBT.cjs.map} +1 -1
  160. package/dist/collaboration/index.cjs +73 -73
  161. package/dist/collaboration/sharing/ShareControl.js +10 -2
  162. package/dist/collaboration/sharing/ShareControl.js.map +2 -2
  163. package/dist/components/SharedCell.d.ts +2 -4
  164. package/dist/components/SharedCell.js +4 -8
  165. package/dist/components/SharedCell.js.map +2 -2
  166. package/dist/components/ZoomSlider.d.ts +25 -0
  167. package/dist/components/ZoomSlider.js +59 -0
  168. package/dist/components/ZoomSlider.js.map +7 -0
  169. package/dist/connect/docx.cjs +20 -20
  170. package/dist/connect/index.cjs +1210 -1264
  171. package/dist/connect/index.cjs.map +1 -1
  172. package/dist/connect/viewer.cjs +42 -36
  173. package/dist/connection/ai.d.ts +1 -1
  174. package/dist/connection/facts/factPageColumns.js +3 -9
  175. package/dist/connection/facts/factPageColumns.js.map +2 -2
  176. package/dist/connection/files/ConnectedNewFileMenu.d.ts +2 -1
  177. package/dist/connection/files/ConnectedNewFileMenu.js +9 -3
  178. package/dist/connection/files/ConnectedNewFileMenu.js.map +2 -2
  179. package/dist/connection/files/explorer/ConnectedFilesExplorer.js +1 -1
  180. package/dist/connection/files/explorer/ConnectedFilesExplorer.js.map +2 -2
  181. package/dist/connection/files/explorer/FileTiles.js +1 -1
  182. package/dist/connection/files/explorer/FileTiles.js.map +2 -2
  183. package/dist/connection/files/fields/documentField.js +1 -1
  184. package/dist/connection/files/fields/documentField.js.map +2 -2
  185. package/dist/connection/files/grid/cells.js +1 -3
  186. package/dist/connection/files/grid/cells.js.map +2 -2
  187. package/dist/connection/files/grid/documentColumns.js +4 -3
  188. package/dist/connection/files/grid/documentColumns.js.map +2 -2
  189. package/dist/connection/files/page/DocumentsFilterBarActions.js +17 -28
  190. package/dist/connection/files/page/DocumentsFilterBarActions.js.map +2 -2
  191. package/dist/connection/mail/useMailboxDefaults.js +1 -1
  192. package/dist/connection/mail/useMailboxDefaults.js.map +2 -2
  193. package/dist/connection/panels/useSessionPanelMode.js +3 -2
  194. package/dist/connection/panels/useSessionPanelMode.js.map +2 -2
  195. package/dist/connection/presentation/ClippingMediaViewer.d.ts +12 -0
  196. package/dist/connection/presentation/ClippingMediaViewer.js +153 -0
  197. package/dist/connection/presentation/ClippingMediaViewer.js.map +7 -0
  198. package/dist/connection/presentation/ClippingPdfViewer.d.ts +22 -0
  199. package/dist/connection/presentation/ClippingPdfViewer.js +75 -0
  200. package/dist/connection/presentation/ClippingPdfViewer.js.map +7 -0
  201. package/dist/connection/presentation/ConnectedPresentation.d.ts +12 -0
  202. package/dist/connection/presentation/ConnectedPresentation.js +100 -0
  203. package/dist/connection/presentation/ConnectedPresentation.js.map +7 -0
  204. package/dist/connection/presentation/ConnectedSlidesTab.d.ts +20 -0
  205. package/dist/connection/presentation/ConnectedSlidesTab.js +220 -0
  206. package/dist/connection/presentation/ConnectedSlidesTab.js.map +7 -0
  207. package/dist/connection/presentation/CropClipDialog.d.ts +11 -0
  208. package/dist/connection/presentation/CropClipDialog.js +86 -0
  209. package/dist/connection/presentation/CropClipDialog.js.map +7 -0
  210. package/dist/connection/presentation/GenerateTile.d.ts +4 -0
  211. package/dist/connection/presentation/GenerateTile.js +24 -0
  212. package/dist/connection/presentation/GenerateTile.js.map +7 -0
  213. package/dist/connection/presentation/LabelColumnMenu.d.ts +8 -0
  214. package/dist/connection/presentation/LabelColumnMenu.js +38 -0
  215. package/dist/connection/presentation/LabelColumnMenu.js.map +7 -0
  216. package/dist/connection/presentation/PresentationDialogs.d.ts +39 -0
  217. package/dist/connection/presentation/PresentationDialogs.js +295 -0
  218. package/dist/connection/presentation/PresentationDialogs.js.map +7 -0
  219. package/dist/connection/presentation/PresentationFileCard.d.ts +10 -0
  220. package/dist/connection/presentation/PresentationFileCard.js +35 -0
  221. package/dist/connection/presentation/PresentationFileCard.js.map +7 -0
  222. package/dist/connection/presentation/PresentationPill.d.ts +8 -0
  223. package/dist/connection/presentation/PresentationPill.js +44 -0
  224. package/dist/connection/presentation/PresentationPill.js.map +7 -0
  225. package/dist/connection/presentation/PresentationSlot.d.ts +7 -0
  226. package/dist/connection/presentation/PresentationSlot.js +35 -0
  227. package/dist/connection/presentation/PresentationSlot.js.map +7 -0
  228. package/dist/connection/presentation/requests.d.ts +16 -0
  229. package/dist/connection/presentation/requests.js +20 -0
  230. package/dist/connection/presentation/requests.js.map +7 -0
  231. package/dist/connection/presentation/useImageGeneration.d.ts +11 -0
  232. package/dist/connection/presentation/useImageGeneration.js +66 -0
  233. package/dist/connection/presentation/useImageGeneration.js.map +7 -0
  234. package/dist/connection/presentation/useLabelColumns.d.ts +15 -0
  235. package/dist/connection/presentation/useLabelColumns.js +33 -0
  236. package/dist/connection/presentation/useLabelColumns.js.map +7 -0
  237. package/dist/connection/presentation/usePresentationController.d.ts +15 -0
  238. package/dist/connection/presentation/usePresentationController.js +118 -0
  239. package/dist/connection/presentation/usePresentationController.js.map +7 -0
  240. package/dist/connection/presentation/usePresentationFiles.d.ts +44 -0
  241. package/dist/connection/presentation/usePresentationFiles.js +307 -0
  242. package/dist/connection/presentation/usePresentationFiles.js.map +7 -0
  243. package/dist/connection/presentation/useViewerClipping.d.ts +14 -0
  244. package/dist/connection/presentation/useViewerClipping.js +18 -0
  245. package/dist/connection/presentation/useViewerClipping.js.map +7 -0
  246. package/dist/connection/sharing/WorkspaceMembersList.d.ts +4 -0
  247. package/dist/connection/sharing/WorkspaceMembersList.js +34 -0
  248. package/dist/connection/sharing/WorkspaceMembersList.js.map +7 -0
  249. package/dist/connection/shell/ConnectedAppShell.js +9 -1
  250. package/dist/connection/shell/ConnectedAppShell.js.map +2 -2
  251. package/dist/connection/viewer/CleanViewControl.d.ts +8 -0
  252. package/dist/connection/viewer/CleanViewControl.js +76 -0
  253. package/dist/connection/viewer/CleanViewControl.js.map +7 -0
  254. package/dist/connection/viewer/ConnectedDocumentViewer.js +31 -31
  255. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  256. package/dist/connection/viewer/ViewerCropModal.d.ts +5 -0
  257. package/dist/connection/viewer/ViewerCropModal.js +22 -0
  258. package/dist/connection/viewer/ViewerCropModal.js.map +7 -0
  259. package/dist/connection/viewer/ViewerPdfPane.d.ts +3 -1
  260. package/dist/connection/viewer/ViewerPdfPane.js +57 -2
  261. package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
  262. package/dist/connection/viewer/drafts.js +6 -4
  263. package/dist/connection/viewer/drafts.js.map +2 -2
  264. package/dist/connection/viewer/pdf/PdfPassageHighlights.d.ts +12 -0
  265. package/dist/connection/viewer/pdf/PdfPassageHighlights.js +36 -0
  266. package/dist/connection/viewer/pdf/PdfPassageHighlights.js.map +7 -0
  267. package/dist/connection/viewer/pdf/passageHighlights.d.ts +26 -0
  268. package/dist/connection/viewer/pdf/passageHighlights.js +40 -0
  269. package/dist/connection/viewer/pdf/passageHighlights.js.map +7 -0
  270. package/dist/connection/viewer/pdf/usePdfPassageHighlights.d.ts +9 -0
  271. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +47 -0
  272. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +7 -0
  273. package/dist/connection/viewer/shareDocument.d.ts +11 -0
  274. package/dist/connection/viewer/shareDocument.js +11 -0
  275. package/dist/connection/viewer/shareDocument.js.map +7 -0
  276. package/dist/connection/viewer/slidesTabChunk.d.ts +2 -0
  277. package/dist/connection/viewer/slidesTabChunk.js +9 -0
  278. package/dist/connection/viewer/slidesTabChunk.js.map +7 -0
  279. package/dist/connection/viewer/useCleanView.d.ts +14 -0
  280. package/dist/connection/viewer/useCleanView.js +29 -0
  281. package/dist/connection/viewer/useCleanView.js.map +7 -0
  282. package/dist/connection/viewer/useViewedDocument.d.ts +1 -0
  283. package/dist/connection/viewer/useViewedDocument.js +9 -1
  284. package/dist/connection/viewer/useViewedDocument.js.map +2 -2
  285. package/dist/connection/viewer/useViewerTabs.js +18 -4
  286. package/dist/connection/viewer/useViewerTabs.js.map +2 -2
  287. package/dist/connection/workflows/ConnectedWorkflowStart.d.ts +14 -2
  288. package/dist/connection/workflows/ConnectedWorkflowStart.js +5 -2
  289. package/dist/connection/workflows/ConnectedWorkflowStart.js.map +2 -2
  290. package/dist/connection/workflows/workflowsPageLabels.js +1 -1
  291. package/dist/connection/workflows/workflowsPageLabels.js.map +1 -1
  292. package/dist/dashboards/index.cjs +1 -1
  293. package/dist/databases/index.cjs +49 -49
  294. package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
  295. package/dist/document-tools/DocumentToolButtons.js +22 -1
  296. package/dist/document-tools/DocumentToolButtons.js.map +2 -2
  297. package/dist/document-tools/index.cjs +16 -12
  298. package/dist/document-tools/index.d.ts +1 -1
  299. package/dist/document-tools/index.js +2 -0
  300. package/dist/document-tools/index.js.map +2 -2
  301. package/dist/embed/index.cjs +43 -41
  302. package/dist/facts/factColumns.js +3 -3
  303. package/dist/facts/factColumns.js.map +1 -1
  304. package/dist/facts/index.cjs +42 -42
  305. package/dist/files/GridViewImpl.js +1 -1
  306. package/dist/files/GridViewImpl.js.map +2 -2
  307. package/dist/files/HtmlViewerParts.js +7 -15
  308. package/dist/files/HtmlViewerParts.js.map +2 -2
  309. package/dist/files/ViewerChrome.d.ts +5 -1
  310. package/dist/files/ViewerChrome.js +16 -6
  311. package/dist/files/ViewerChrome.js.map +2 -2
  312. package/dist/files/index.cjs +226 -226
  313. package/dist/files/navigator/DocumentSearchList.js +1 -1
  314. package/dist/files/navigator/DocumentSearchList.js.map +2 -2
  315. package/dist/index.cjs +1668 -1666
  316. package/dist/index.cjs.map +1 -1
  317. package/dist/presentation/BoxActionBar.d.ts +11 -0
  318. package/dist/presentation/BoxActionBar.js +182 -0
  319. package/dist/presentation/BoxActionBar.js.map +7 -0
  320. package/dist/presentation/ClipActionBar.d.ts +26 -0
  321. package/dist/presentation/ClipActionBar.js +103 -0
  322. package/dist/presentation/ClipActionBar.js.map +7 -0
  323. package/dist/presentation/ClipCaptureOverlay.d.ts +14 -0
  324. package/dist/presentation/ClipCaptureOverlay.js +69 -0
  325. package/dist/presentation/ClipCaptureOverlay.js.map +7 -0
  326. package/dist/presentation/ClipImage.d.ts +21 -0
  327. package/dist/presentation/ClipImage.js +119 -0
  328. package/dist/presentation/ClipImage.js.map +7 -0
  329. package/dist/presentation/ClipTray.d.ts +11 -0
  330. package/dist/presentation/ClipTray.js +152 -0
  331. package/dist/presentation/ClipTray.js.map +7 -0
  332. package/dist/presentation/ClipViewControls.d.ts +11 -0
  333. package/dist/presentation/ClipViewControls.js +142 -0
  334. package/dist/presentation/ClipViewControls.js.map +7 -0
  335. package/dist/presentation/DesignMenu.d.ts +8 -0
  336. package/dist/presentation/DesignMenu.js +199 -0
  337. package/dist/presentation/DesignMenu.js.map +7 -0
  338. package/dist/presentation/LayoutMenu.d.ts +17 -0
  339. package/dist/presentation/LayoutMenu.js +122 -0
  340. package/dist/presentation/LayoutMenu.js.map +7 -0
  341. package/dist/presentation/MediaClip.d.ts +15 -0
  342. package/dist/presentation/MediaClip.js +67 -0
  343. package/dist/presentation/MediaClip.js.map +7 -0
  344. package/dist/presentation/Notice.d.ts +6 -0
  345. package/dist/presentation/Notice.js +43 -0
  346. package/dist/presentation/Notice.js.map +7 -0
  347. package/dist/presentation/PresentationStage.d.ts +32 -0
  348. package/dist/presentation/PresentationStage.js +232 -0
  349. package/dist/presentation/PresentationStage.js.map +7 -0
  350. package/dist/presentation/PresenterView.d.ts +16 -0
  351. package/dist/presentation/PresenterView.js +69 -0
  352. package/dist/presentation/PresenterView.js.map +7 -0
  353. package/dist/presentation/SlideDecor.d.ts +25 -0
  354. package/dist/presentation/SlideDecor.js +189 -0
  355. package/dist/presentation/SlideDecor.js.map +7 -0
  356. package/dist/presentation/SlidesEditor.d.ts +25 -0
  357. package/dist/presentation/SlidesEditor.js +359 -0
  358. package/dist/presentation/SlidesEditor.js.map +7 -0
  359. package/dist/presentation/StageBox.d.ts +30 -0
  360. package/dist/presentation/StageBox.js +281 -0
  361. package/dist/presentation/StageBox.js.map +7 -0
  362. package/dist/presentation/StageItem.d.ts +37 -0
  363. package/dist/presentation/StageItem.js +211 -0
  364. package/dist/presentation/StageItem.js.map +7 -0
  365. package/dist/presentation/box-style.d.ts +6 -0
  366. package/dist/presentation/box-style.js +19 -0
  367. package/dist/presentation/box-style.js.map +7 -0
  368. package/dist/presentation/boxes.d.ts +105 -0
  369. package/dist/presentation/boxes.js +103 -0
  370. package/dist/presentation/boxes.js.map +7 -0
  371. package/dist/presentation/draw-boxes.d.ts +8 -0
  372. package/dist/presentation/draw-boxes.js +130 -0
  373. package/dist/presentation/draw-boxes.js.map +7 -0
  374. package/dist/presentation/export-boxes.d.ts +10 -0
  375. package/dist/presentation/export-boxes.js +74 -0
  376. package/dist/presentation/export-boxes.js.map +7 -0
  377. package/dist/presentation/export-pptx.d.ts +16 -0
  378. package/dist/presentation/export-pptx.js +194 -0
  379. package/dist/presentation/export-pptx.js.map +7 -0
  380. package/dist/presentation/import-pptx.d.ts +35 -0
  381. package/dist/presentation/import-pptx.js +659 -0
  382. package/dist/presentation/import-pptx.js.map +7 -0
  383. package/dist/presentation/merge-outside-edits.d.ts +12 -0
  384. package/dist/presentation/merge-outside-edits.js +35 -0
  385. package/dist/presentation/merge-outside-edits.js.map +7 -0
  386. package/dist/presentation/model.d.ts +201 -0
  387. package/dist/presentation/model.js +271 -0
  388. package/dist/presentation/model.js.map +7 -0
  389. package/dist/presentation/panel-id.d.ts +34 -0
  390. package/dist/presentation/panel-id.js +24 -0
  391. package/dist/presentation/panel-id.js.map +7 -0
  392. package/dist/presentation/persistence.d.ts +121 -0
  393. package/dist/presentation/persistence.js +141 -0
  394. package/dist/presentation/persistence.js.map +7 -0
  395. package/dist/presentation/pptx-data.d.ts +22 -0
  396. package/dist/presentation/pptx-data.js +83 -0
  397. package/dist/presentation/pptx-data.js.map +7 -0
  398. package/dist/presentation/pptx-xml.d.ts +90 -0
  399. package/dist/presentation/pptx-xml.js +333 -0
  400. package/dist/presentation/pptx-xml.js.map +7 -0
  401. package/dist/presentation/render-slides.d.ts +58 -0
  402. package/dist/presentation/render-slides.js +309 -0
  403. package/dist/presentation/render-slides.js.map +7 -0
  404. package/dist/presentation/saved-boxes.d.ts +11 -0
  405. package/dist/presentation/saved-boxes.js +80 -0
  406. package/dist/presentation/saved-boxes.js.map +7 -0
  407. package/dist/presentation/slide-layout.d.ts +54 -0
  408. package/dist/presentation/slide-layout.js +117 -0
  409. package/dist/presentation/slide-layout.js.map +7 -0
  410. package/dist/presentation/stage-videos.d.ts +5 -0
  411. package/dist/presentation/stage-videos.js +19 -0
  412. package/dist/presentation/stage-videos.js.map +7 -0
  413. package/dist/presentation/store.d.ts +203 -0
  414. package/dist/presentation/store.js +429 -0
  415. package/dist/presentation/store.js.map +7 -0
  416. package/dist/presentation/theme.d.ts +102 -0
  417. package/dist/presentation/theme.js +276 -0
  418. package/dist/presentation/theme.js.map +7 -0
  419. package/dist/presentation/useClipDrag.d.ts +26 -0
  420. package/dist/presentation/useClipDrag.js +65 -0
  421. package/dist/presentation/useClipDrag.js.map +7 -0
  422. package/dist/presentation/useObjectUrl.d.ts +6 -0
  423. package/dist/presentation/useObjectUrl.js +15 -0
  424. package/dist/presentation/useObjectUrl.js.map +7 -0
  425. package/dist/presentation/usePresenterKeys.d.ts +13 -0
  426. package/dist/presentation/usePresenterKeys.js +62 -0
  427. package/dist/presentation/usePresenterKeys.js.map +7 -0
  428. package/dist/settings/index.cjs +151 -150
  429. package/dist/shell/PanelPortal.js +1 -0
  430. package/dist/shell/PanelPortal.js.map +2 -2
  431. package/dist/shell/index.cjs +112 -110
  432. package/dist/shell/panel-windows.d.ts +2 -0
  433. package/dist/shell/panel-windows.js +7 -2
  434. package/dist/shell/panel-windows.js.map +2 -2
  435. package/dist/studio/index.cjs +28 -26
  436. package/dist/studio/index.cjs.map +1 -1
  437. package/dist/styles.css +1 -1
  438. package/dist/workflow-canvas/index.cjs +58 -57
  439. package/dist/workflow-canvas/index.cjs.map +1 -1
  440. package/node_modules/@arbidocs/coedit/package.json +1 -1
  441. package/package.json +6 -5
  442. package/dist/ConnectedCallDock-WER7R222.cjs.map +0 -1
  443. package/dist/DocumentReviewCard-ZSBZBGFK.cjs.map +0 -1
  444. package/dist/FilesViewerDialog-6UKR5WEF.cjs.map +0 -1
  445. package/dist/GridViewImpl-ZMJJWTOM.cjs.map +0 -1
  446. package/dist/WorkspaceTableView-J3C6VH4T.cjs.map +0 -1
  447. package/dist/ai-IM4A23YT.cjs.map +0 -1
  448. package/dist/chunk-557MJ4IH.cjs.map +0 -1
  449. package/dist/chunk-6UTKM5AB.cjs.map +0 -1
  450. package/dist/chunk-6WMMZLEV.cjs.map +0 -1
  451. package/dist/chunk-B3LZITVF.cjs.map +0 -1
  452. package/dist/chunk-CPG7II4E.cjs.map +0 -1
  453. package/dist/chunk-CPR6EHG7.cjs.map +0 -1
  454. package/dist/chunk-DDIW4HLU.cjs.map +0 -1
  455. package/dist/chunk-NJCK6V6U.cjs.map +0 -1
  456. package/dist/chunk-NNUK5ZM7.cjs.map +0 -1
  457. package/dist/chunk-PGJYD67F.cjs.map +0 -1
  458. package/dist/chunk-R7CJEIA5.cjs.map +0 -1
  459. package/dist/chunk-SB4M3ITT.cjs.map +0 -1
  460. package/dist/chunk-TT4IF52H.cjs.map +0 -1
  461. package/dist/chunk-VLCY46K6.cjs.map +0 -1
  462. package/dist/chunk-YYPZOEED.cjs.map +0 -1
  463. package/dist/chunk-ZPPMAL5P.cjs.map +0 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/presentation/store.ts"],
4
+ "sourcesContent": ["/**\n * The presentation of this session: the clips taken, the slides they are arranged on, the slide on\n * the stage, whether the stage is blanked and whether the presentation window presents (shows only\n * the stage, for sharing) or edits. Clips taken in the app's viewer land in it at once.\n *\n * Kept in memory only: a clip holds the decrypted PDF it is drawn from, so nothing is written to\n * storage, and everything is cleared when the session signs out (`ConnectedPresentation`).\n */\n\nimport { create } from 'zustand'\nimport { releasePdfRegionSource } from '@arbidocs/react/viewers'\nimport {\n alignFrame,\n autoLayout,\n defaultCaption,\n dropFrame,\n fitFrame,\n fullHeightFrame,\n fullWidthFrame,\n moveFrame,\n type Alignment,\n type Clip,\n type Rect,\n type Reserve,\n type Frame,\n type Slide,\n type SlideLayout,\n} from './model'\nimport { slideGeometry } from './slide-layout'\nimport { DEFAULT_THEME, type Theme } from './theme'\nimport { serializePresentation } from './persistence'\nimport { nextBoxId, withText, type SlideBackground, type SlideBox } from './boxes'\nimport type { SavedBox } from './saved-boxes'\n\n/** The smallest a clip's area can be zoomed to (a fraction of its source, either side). */\nconst MIN_CLIP_AREA = 0.02\n\n/** A slide holds a handful of clips: more would be too small to read on a shared screen. */\nexport const MAX_ITEMS_PER_SLIDE = 6\n/** A new clip goes on the slide by itself while the slide has fewer than this. */\nconst AUTO_PLACE_BELOW = 2\n\nexport type NewClip = Omit<Clip, 'id' | 'caption'> & { caption?: string }\nexport type FrameCommand = 'fullWidth' | 'fullHeight' | 'fit'\n\ninterface PresentationState {\n clips: Clip[]\n slides: Slide[]\n /** Index of the slide on the stage. */\n current: number\n /** The stage shows nothing (black) while true. */\n blank: boolean\n captions: boolean\n /** One look for every slide: background, typeface, accent, logo. Saved. */\n theme: Theme\n /** The theme's logo image (this session only; fetched by the host from `theme.logo`). */\n logoImage: Blob | null\n /**\n * The annotation column (a tag's id) whose value for each clip's document leads its label: an\n * Exhibit column's \"R-100\". Saved with the presentation.\n */\n labelColumn: string | null\n /** Each clip document's value in `labelColumn`, kept current by the host (not saved). */\n columnValues: Readonly<Record<string, string>>\n /** Present mode: the presentation window shows only the stage (what is shared). */\n presenting: boolean\n /** The presentation's name (its file's, once saved). */\n title: string\n /** The document it is saved as, once saved: saving again adds a version to it. */\n savedId: string | null\n /** Which version of that document this is (as opened or saved), when known. */\n version: number | null\n /**\n * The document (or draft) this presentation is edited as, in the viewer: its slides tab shows\n * it. Null: clips gathered with no presentation open yet (a new one takes them).\n */\n boundTo: string | null\n /** The presentation as last opened or saved (serialised), to tell unsaved changes; null: never. */\n clean: string | null\n /**\n * A message for the presentation window itself (saved, failed\u2026): the app's notifications show in\n * the app's window, out of sight behind a popped-out presentation.\n */\n notice: { text: string; kind: 'success' | 'error'; id: number } | null\n /** The clip being dragged from the tray, while it is (the drop targets light up). */\n dragging: string | null\n /** Images embedded in the presentation (an imported deck's pictures), as data URLs, by key. */\n media: Readonly<Record<string, string>>\n}\n\ninterface PresentationActions {\n /** Add a clip; it is placed on the current slide while that has fewer than two. */\n addClip(clip: NewClip): string\n removeClip(clipId: string): void\n setCaption(clipId: string, caption: string): void\n /** Put a clip on the current slide (at a point, when dropped there). */\n place(clipId: string, at?: { x: number; y: number }): void\n unplace(clipId: string): void\n /** Move or resize a clip by hand: the slide stops arranging itself. */\n setFrame(clipId: string, frame: Frame): void\n applyFrame(clipId: string, command: FrameCommand): void\n /** Overlapping clips: this one on top of the others (later items are drawn over earlier ones). */\n bringToFront(clipId: string): void\n /** Overlapping clips: this one under the others. */\n sendToBack(clipId: string): void\n /**\n * Scroll what a clip shows over its page, image or video by `dx, dy` (fractions of the source),\n * its size kept and kept within the source: e.g. to show the lines above or below a passage.\n */\n panClip(clipId: string, dx: number, dy: number): void\n /**\n * Zoom what a clip shows by `factor` (2: twice as close) about its centre: its area over the\n * source shrinks or grows, its shape kept, never past the source's edges.\n */\n zoomClip(clipId: string, factor: number): void\n /** Zoom a clip to `percent` of how close it was cut (100: as cut), about its centre. */\n setClipZoom(clipId: string, percent: number): void\n /** Align a clip on the stage (inside the margins and the slide's reserved room). */\n align(clipId: string, alignment: Alignment): void\n /** Nudge a clip by `dx, dy` (stage fractions), kept on the stage, not snapped. */\n nudge(clipId: string, dx: number, dy: number): void\n /** The current slide's caption (shown across its top; empty for none). */\n /** A slide's title (default the current slide's). */\n setSlideCaption(caption: string, index?: number): void\n /** The current slide's layout: it is arranged for it again. */\n setSlideLayout(layout: SlideLayout, index?: number): void\n /** The current slide's text (its points, or subtitle). */\n setSlidePoints(points: string, index?: number): void\n /** Change the theme; slides arranging themselves make room for a logo (or give it back). */\n setTheme(change: Partial<Theme>): void\n setLogoImage(image: Blob | null): void\n /** Arrange the current slide automatically again. */\n arrange(): void\n /** A new slide after the current one (by default with the current slide's layout). */\n addSlide(layout?: SlideLayout, after?: number): void\n /** Remove a slide (default the current one); the last one left is emptied instead. */\n removeSlide(index?: number): void\n /** A copy of a slide (its title, points and clips), right after it. */\n duplicateSlide(index: number): void\n /** Move a slide to `to` (the others shift up or down). */\n moveSlide(index: number, to: number): void\n goTo(index: number): void\n setBlank(blank: boolean): void\n setCaptions(captions: boolean): void\n setLabelColumn(tagId: string | null): void\n setColumnValues(values: Readonly<Record<string, string>>): void\n setPresenting(presenting: boolean): void\n setDragging(clipId: string | null): void\n setTitle(title: string): void\n notify(text: string, kind: 'success' | 'error'): void\n clearNotice(id: number): void\n /** Show another part of an image or video clip's source (a new crop): its area and shape. */\n cropClip(clipId: string, rect: Rect, aspect: number): void\n /**\n * A clip reshaped on the current slide (`reshapeFrame`): it shows `rect` of its source, in\n * `frame`, at the same scale and zoom. Slides arranging themselves arrange around its new shape.\n */\n reshapeClip(clipId: string, frame: Frame, rect: Rect, aspect: number): void\n /** A text box or shape on a slide (default the current one), on top; resolves with its id. */\n addBox(box: Omit<SlideBox, 'id'>, index?: number): string\n /** Change a box (wherever it is). */\n updateBox(boxId: string, change: (box: SlideBox) => SlideBox): void\n /** Type a box's text (one paragraph per line, each keeping its style). */\n setBoxText(boxId: string, text: string): void\n removeBox(boxId: string): void\n /** A box over the slide's clips and other boxes, or under them all. */\n restackBox(boxId: string, to: 'front' | 'back'): void\n /** A slide's speaker notes (default the current slide's). */\n setSlideNotes(notes: string, index?: number): void\n /** A slide's own background (none: the theme's). */\n setSlideBackground(background: SlideBackground | undefined, index?: number): void\n /** Saved as this document (under this title), as its `version`. */\n setSaved(savedId: string, title: string, version?: number | null): void\n /** Edited as this document or draft (see `boundTo`). */\n bind(boundTo: string | null): void\n /** Clips gathered before (with no presentation open), added to the tray, not placed. */\n adoptClips(clips: readonly Clip[]): void\n /** Replace the presentation with one opened from a file (its clips' sources fetched). */\n load(opened: {\n title: string\n /** The document it is saved as; null for a new one (from a template). */\n savedId: string | null\n /** Its version, when known. */\n version?: number | null\n /** Edited as (default `savedId`): an older file opened unsaved is still its own. */\n boundTo?: string | null\n captions: boolean\n labelColumn?: string | null\n theme?: Theme\n clips: Omit<Clip, 'id'>[]\n slides: {\n caption: string\n auto: boolean\n layout?: SlideLayout\n points?: string\n items: { clip: number; frame: Frame }[]\n boxes?: readonly SavedBox[]\n background?: SlideBackground\n notes?: string\n }[]\n media?: Readonly<Record<string, string>>\n }): void\n reset(): void\n}\n\nexport type PresentationStore = PresentationState & PresentationActions\n\nlet sequence = 0\nconst nextId = (kind: string) => `${kind}-${Date.now().toString(36)}-${++sequence}`\n\nconst emptySlide = (layout: SlideLayout = 'clips'): Slide => ({\n id: nextId('slide'),\n items: [],\n auto: true,\n caption: '',\n layout,\n points: '',\n boxes: [],\n})\n\nconst initialState = (): PresentationState => ({\n clips: [],\n slides: [emptySlide()],\n current: 0,\n blank: false,\n captions: true,\n theme: DEFAULT_THEME,\n logoImage: null,\n labelColumn: null,\n columnValues: {},\n presenting: false,\n dragging: null,\n notice: null,\n title: 'Untitled presentation',\n savedId: null,\n version: null,\n boundTo: null,\n clean: null,\n media: {},\n})\n\n/** What arranging a slide depends on besides its clips: labels shown, a logo in the footer. */\ntype Look = Pick<PresentationState, 'captions' | 'theme'>\n\n/** The slide arranged again from its clips' aspects, in the room its layout leaves them. */\nfunction arranged(slide: Slide, clips: readonly Clip[], look: Look): Slide {\n const aspects = slide.items.map((item) => aspectOf(clips, item.clipId))\n const frames = autoLayout(aspects, reserveOf(slide, look))\n return {\n ...slide,\n auto: true,\n items: slide.items.map((item, i) => ({ ...item, frame: frames[i] })),\n }\n}\n\n/**\n * The room a slide keeps free of clips: its title and text (by its layout), each clip's label\n * under it, the footer while a logo shows.\n */\nexport const reserveOf = (slide: Pick<Slide, 'caption' | 'layout'>, look: Look): Reserve =>\n slideGeometry(slide, { labels: look.captions, logo: look.theme.logo?.corner ?? null }).reserve\n\nfunction aspectOf(clips: readonly Clip[], clipId: string): number {\n return clips.find((clip) => clip.id === clipId)?.aspect ?? 1\n}\n\nexport const usePresentation = create<PresentationStore>()((set, get) => {\n /** Change the current slide; an auto slide is arranged again after the change. */\n const updateSlide = (change: (slide: Slide, clips: readonly Clip[]) => Slide, at?: number) =>\n set((state) => {\n const index = at ?? state.current\n const slide = state.slides[index]\n if (!slide) return state\n const next = change(slide, state.clips)\n if (next === slide) return state\n const slides = state.slides.slice()\n slides[index] = next.auto ? arranged(next, state.clips, state) : next\n return { slides }\n })\n\n /** Change the boxes of the slide holding `boxId` (`at`: the box's index there). */\n const updateBoxes = (\n boxId: string,\n change: (boxes: readonly SlideBox[], at: number) => SlideBox[]\n ) =>\n set((state) => {\n const index = state.slides.findIndex((slide) => slide.boxes.some((box) => box.id === boxId))\n if (index < 0) return state\n const slide = state.slides[index]\n const slides = state.slides.slice()\n slides[index] = {\n ...slide,\n boxes: change(\n slide.boxes,\n slide.boxes.findIndex((box) => box.id === boxId)\n ),\n }\n return { slides }\n })\n\n /** Restack a clip on the current slide: only the drawing order changes, never a position. */\n const restack = (clipId: string, to: 'front' | 'back') =>\n set((state) => {\n const slide = state.slides[state.current]\n const item = slide?.items.find((entry) => entry.clipId === clipId)\n if (!slide || !item) return state\n const rest = slide.items.filter((entry) => entry !== item)\n const items = to === 'front' ? [...rest, item] : [item, ...rest]\n if (items.every((entry, i) => entry === slide.items[i])) return state\n const slides = state.slides.slice()\n slides[state.current] = { ...slide, items }\n return { slides }\n })\n\n return {\n ...initialState(),\n\n addClip(clip) {\n const id = nextId('clip')\n const full: Clip = {\n ...clip,\n id,\n caption: clip.caption ?? defaultCaption(clip.fileName, clip.page),\n zoomBase: clip.zoomBase ?? clip.rect.w,\n }\n set((state) => ({ clips: [...state.clips, full] }))\n const slide = get().slides[get().current]\n if (slide && slide.items.length < AUTO_PLACE_BELOW) get().place(id)\n return id\n },\n\n removeClip(clipId) {\n const { clips, slides } = get()\n const removed = clips.find((clip) => clip.id === clipId)\n if (!removed) return\n const rest = clips.filter((clip) => clip.id !== clipId)\n set({\n clips: rest,\n slides: slides.map((slide) => {\n if (!slide.items.some((item) => item.clipId === clipId)) return slide\n const next = { ...slide, items: slide.items.filter((item) => item.clipId !== clipId) }\n return next.auto ? arranged(next, rest, get()) : next\n }),\n })\n // The PDF engine's copy of the file goes once no clip is drawn from it.\n if (!rest.some((clip) => clip.source === removed.source))\n releasePdfRegionSource(removed.source)\n },\n\n setCaption: (clipId, caption) =>\n set((state) => ({\n clips: state.clips.map((clip) => (clip.id === clipId ? { ...clip, caption } : clip)),\n })),\n\n place: (clipId, at) =>\n updateSlide((slide, clips) => {\n if (!clips.some((clip) => clip.id === clipId)) return slide\n const others = slide.items.filter((item) => item.clipId !== clipId)\n if (!at && others.length < slide.items.length) return slide\n if (others.length >= MAX_ITEMS_PER_SLIDE) return slide\n const aspect = aspectOf(clips, clipId)\n // An auto slide arranges it with the rest. A slide arranged by hand stays so: the clip goes\n // where it was dropped, or in the middle.\n const frame = slide.auto ? fitFrame(aspect) : dropFrame(aspect, at ?? { x: 0.5, y: 0.5 })\n return { ...slide, items: [...others, { clipId, frame }] }\n }),\n\n unplace: (clipId) =>\n updateSlide((slide) =>\n slide.items.some((item) => item.clipId === clipId)\n ? { ...slide, items: slide.items.filter((item) => item.clipId !== clipId) }\n : slide\n ),\n\n setFrame: (clipId, frame) =>\n updateSlide((slide) => ({\n ...slide,\n auto: false,\n items: slide.items.map((item) => (item.clipId === clipId ? { ...item, frame } : item)),\n })),\n\n applyFrame(clipId, command) {\n const slide = get().slides[get().current]\n const item = slide?.items.find((entry) => entry.clipId === clipId)\n if (!item) return\n const aspect = aspectOf(get().clips, clipId)\n const reserve = reserveOf(slide, get())\n const frame =\n command === 'fullWidth'\n ? fullWidthFrame(item.frame, aspect, reserve)\n : command === 'fullHeight'\n ? fullHeightFrame(item.frame, aspect, reserve)\n : fitFrame(aspect, reserve)\n get().setFrame(clipId, frame)\n // Made the size of the stage, it goes on top of the others.\n get().bringToFront(clipId)\n },\n\n bringToFront: (clipId) => restack(clipId, 'front'),\n sendToBack: (clipId) => restack(clipId, 'back'),\n\n panClip: (clipId, dx, dy) =>\n set((state) => {\n const clip = state.clips.find((entry) => entry.id === clipId)\n if (!clip) return state\n const { rect } = clip\n const x = Math.min(Math.max(rect.x + dx, 0), 1 - rect.w)\n const y = Math.min(Math.max(rect.y + dy, 0), 1 - rect.h)\n if (x === rect.x && y === rect.y) return state\n return {\n clips: state.clips.map((entry) =>\n entry === clip ? { ...clip, rect: { ...rect, x, y } } : entry\n ),\n }\n }),\n\n zoomClip: (clipId, factor) =>\n set((state) => {\n const clip = state.clips.find((entry) => entry.id === clipId)\n if (!clip || !(factor > 0)) return state\n const { rect } = clip\n // Its area scales by 1/factor; never larger than the source, nor smaller than a sliver.\n const largest = Math.min(1 / rect.w, 1 / rect.h)\n const smallest = Math.max(MIN_CLIP_AREA / rect.w, MIN_CLIP_AREA / rect.h)\n const scale = Math.min(Math.max(1 / factor, smallest), largest)\n if (scale === 1) return state\n const w = rect.w * scale\n const h = rect.h * scale\n const x = Math.min(Math.max(rect.x + (rect.w - w) / 2, 0), 1 - w)\n const y = Math.min(Math.max(rect.y + (rect.h - h) / 2, 0), 1 - h)\n return {\n clips: state.clips.map((entry) =>\n entry === clip ? { ...clip, rect: { x, y, w, h } } : entry\n ),\n }\n }),\n\n setClipZoom(clipId, percent) {\n const clip = get().clips.find((entry) => entry.id === clipId)\n if (!clip || !(percent > 0)) return\n const width = (clip.zoomBase ?? clip.rect.w) / (percent / 100)\n get().zoomClip(clipId, clip.rect.w / width)\n },\n\n align(clipId, alignment) {\n const slide = get().slides[get().current]\n const item = slide?.items.find((entry) => entry.clipId === clipId)\n if (!slide || !item) return\n const aspect = aspectOf(get().clips, clipId)\n get().setFrame(clipId, alignFrame(item.frame, aspect, alignment, reserveOf(slide, get())))\n },\n\n nudge(clipId, dx, dy) {\n const slide = get().slides[get().current]\n const item = slide?.items.find((entry) => entry.clipId === clipId)\n if (!item) return\n const aspect = aspectOf(get().clips, clipId)\n get().setFrame(clipId, moveFrame(item.frame, aspect, dx, dy, [], true).frame)\n },\n\n // An auto slide makes (or gives back) the caption's room; one arranged by hand keeps its places.\n // A blank slide's title is its title box's text.\n setSlideCaption: (caption, index) =>\n updateSlide(\n (slide) => ({\n ...slide,\n caption,\n boxes: slide.boxes.map((box) => (box.role === 'title' ? withText(box, caption) : box)),\n }),\n index\n ),\n setSlideLayout: (layout, index) =>\n updateSlide((slide) => ({ ...slide, layout, auto: true }), index),\n setSlidePoints: (points, index) => updateSlide((slide) => ({ ...slide, points }), index),\n\n setTheme: (change) =>\n set((state) => {\n const theme = { ...state.theme, ...change }\n const logoMoved = (theme.logo?.corner ?? null) !== (state.theme.logo?.corner ?? null)\n return {\n theme,\n ...(theme.logo?.documentId !== state.theme.logo?.documentId ? { logoImage: null } : {}),\n slides: logoMoved\n ? state.slides.map((slide) =>\n slide.auto ? arranged(slide, state.clips, { ...state, theme }) : slide\n )\n : state.slides,\n }\n }),\n setLogoImage: (logoImage) => set({ logoImage }),\n\n arrange: () => updateSlide((slide) => ({ ...slide, auto: true })),\n\n addSlide: (layout, after) =>\n set((state) => {\n const at = (after ?? state.current) + 1\n const slides = state.slides.slice()\n const before = state.slides[at - 1]\n const slide = emptySlide(layout ?? before?.layout ?? 'clips')\n // The slide it follows keeps its look (an imported deck's background).\n slides.splice(\n at,\n 0,\n before?.background ? { ...slide, background: before.background } : slide\n )\n return { slides, current: at }\n }),\n\n removeSlide: (index) =>\n set((state) => {\n const target = index ?? state.current\n if (state.slides.length <= 1) return { slides: [emptySlide()], current: 0 }\n const slides = state.slides.filter((_, i) => i !== target)\n const current = state.current > target ? state.current - 1 : state.current\n return { slides, current: Math.min(current, slides.length - 1) }\n }),\n\n duplicateSlide: (index) =>\n set((state) => {\n const slide = state.slides[index]\n if (!slide) return state\n const slides = state.slides.slice()\n slides.splice(index + 1, 0, {\n ...slide,\n id: nextId('slide'),\n items: slide.items.map((item) => ({ ...item, frame: { ...item.frame } })),\n boxes: slide.boxes.map((box) => ({ ...box, id: nextBoxId() })),\n })\n return { slides, current: index + 1 }\n }),\n\n moveSlide: (index, to) =>\n set((state) => {\n if (to < 0 || to >= state.slides.length || index === to || !state.slides[index]) {\n return state\n }\n const slides = state.slides.slice()\n const [slide] = slides.splice(index, 1)\n slides.splice(to, 0, slide)\n return { slides, current: to }\n }),\n\n goTo: (index) =>\n set((state) =>\n index < 0 || index >= state.slides.length || index === state.current\n ? state\n : { current: index }\n ),\n\n setBlank: (blank) => set({ blank }),\n // Slides arranged automatically make (or give back) the captions' room.\n setCaptions: (captions) =>\n set((state) => ({\n captions,\n slides: state.slides.map((slide) =>\n slide.auto ? arranged(slide, state.clips, { ...state, captions }) : slide\n ),\n })),\n setLabelColumn: (labelColumn) => set({ labelColumn }),\n setColumnValues: (columnValues) => set({ columnValues }),\n setPresenting: (presenting) => set({ presenting }),\n setDragging: (dragging) => set({ dragging }),\n setTitle: (title) => set({ title }),\n notify: (text, kind) => set({ notice: { text, kind, id: ++sequence } }),\n clearNotice: (id) => set((state) => (state.notice?.id === id ? { notice: null } : state)),\n\n cropClip: (clipId, rect, aspect) =>\n set((state) => {\n const clips = state.clips.map((clip) =>\n clip.id === clipId ? { ...clip, rect, aspect } : clip\n )\n return {\n clips,\n // Its shape changed: slides arranged automatically arrange again around it.\n slides: state.slides.map((slide) =>\n slide.auto && slide.items.some((item) => item.clipId === clipId)\n ? arranged(slide, clips, state)\n : slide\n ),\n }\n }),\n reshapeClip: (clipId, frame, rect, aspect) =>\n set((state) => {\n const clip = state.clips.find((entry) => entry.id === clipId)\n if (!clip) return state\n // Its zoom reads against its width when cut: that scales with the width it now shows.\n const zoomBase = ((clip.zoomBase ?? clip.rect.w) * rect.w) / clip.rect.w\n const clips = state.clips.map((entry) =>\n entry === clip ? { ...clip, rect, aspect, zoomBase } : entry\n )\n return {\n clips,\n slides: state.slides.map((slide, index) => {\n if (index === state.current) {\n return {\n ...slide,\n auto: false,\n items: slide.items.map((item) =>\n item.clipId === clipId ? { ...item, frame } : item\n ),\n }\n }\n return slide.auto && slide.items.some((item) => item.clipId === clipId)\n ? arranged(slide, clips, state)\n : slide\n }),\n }\n }),\n addBox(box, index) {\n const id = nextBoxId()\n updateSlide((slide) => ({ ...slide, boxes: [...slide.boxes, { ...box, id }] }), index)\n return id\n },\n updateBox: (boxId, change) =>\n updateBoxes(boxId, (boxes, at) => {\n const next = boxes.slice()\n next[at] = change(boxes[at])\n return next\n }),\n setBoxText(boxId, text) {\n get().updateBox(boxId, (box) => withText(box, text))\n // A blank slide's title box is its title too (what an outline reads).\n set((state) => ({\n slides: state.slides.map((slide) =>\n slide.boxes.some((box) => box.id === boxId && box.role === 'title')\n ? { ...slide, caption: text.replace(/\\s*\\n\\s*/g, ' ').trim() }\n : slide\n ),\n }))\n },\n removeBox: (boxId) => updateBoxes(boxId, (boxes, at) => boxes.filter((_, i) => i !== at)),\n restackBox: (boxId, to) =>\n updateBoxes(boxId, (boxes, at) => {\n const box = { ...boxes[at], front: to === 'front' }\n const rest = boxes.filter((_, i) => i !== at)\n return to === 'front' ? [...rest, box] : [box, ...rest]\n }),\n setSlideNotes: (notes, index) => updateSlide((slide) => ({ ...slide, notes }), index),\n setSlideBackground: (background, index) =>\n updateSlide((slide) => {\n const { background: _old, ...rest } = slide\n void _old\n return background ? { ...rest, background } : rest\n }, index),\n setSaved: (savedId, title, version = null) => {\n set({ savedId, title, boundTo: savedId, version })\n set({ clean: snapshotOf(get()) })\n },\n bind: (boundTo) => set({ boundTo }),\n adoptClips: (adopted) =>\n set((state) => ({\n clips: [\n ...state.clips,\n ...adopted.filter((clip) => !state.clips.some((entry) => entry.id === clip.id)),\n ],\n })),\n\n load(opened) {\n get().reset()\n const clips: Clip[] = opened.clips.map((clip) => ({ ...clip, id: nextId('clip') }))\n const slides: Slide[] = opened.slides.map((slide) => ({\n id: nextId('slide'),\n caption: slide.caption,\n auto: slide.auto,\n layout: slide.layout ?? 'clips',\n points: slide.points ?? '',\n // Items whose clip could not be opened are left out.\n items: slide.items\n .filter((item) => clips[item.clip])\n .map((item) => ({ clipId: clips[item.clip].id, frame: item.frame })),\n boxes: (slide.boxes ?? []).map((box) => ({ ...box, id: nextBoxId() })),\n ...(slide.background ? { background: slide.background } : {}),\n ...(slide.notes ? { notes: slide.notes } : {}),\n }))\n set({\n title: opened.title,\n savedId: opened.savedId,\n version: opened.version ?? null,\n boundTo: opened.boundTo ?? opened.savedId,\n captions: opened.captions,\n labelColumn: opened.labelColumn ?? null,\n theme: opened.theme ?? DEFAULT_THEME,\n clips,\n slides: slides.length ? slides : [emptySlide()],\n current: 0,\n media: opened.media ?? {},\n })\n set({ clean: opened.savedId ? snapshotOf(get()) : null })\n },\n\n reset() {\n for (const source of new Set(get().clips.map((clip) => clip.source))) {\n releasePdfRegionSource(source)\n }\n set(initialState())\n },\n }\n})\n\n/** The slide on the stage. */\nexport const currentSlide = (state: PresentationState): Slide | undefined =>\n state.slides[state.current]\n\n/** What is saved of a presentation, as text (to compare). */\nfunction snapshotOf(state: PresentationState): string {\n // Embedded images change only with the clips that show them: left out, so comparing stays cheap.\n return JSON.stringify(serializePresentation({ ...state, media: undefined }))\n}\n\n/**\n * The presentation has changes not saved: since it was opened or saved; or, never saved, anything\n * in it at all (a clip, a title, a point).\n */\nexport function hasUnsavedChanges(state: PresentationState): boolean {\n if (state.clean !== null) return snapshotOf(state) !== state.clean\n return (\n state.clips.length > 0 ||\n state.slides.some(\n (slide) =>\n slide.items.length || slide.boxes.length || slide.caption.trim() || slide.points.trim()\n )\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["slide"]
7
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * A presentation's theme: one look for every slide (background, typeface, accent colour, a logo
3
+ * in the footer). The same values draw the stage (CSS), the saved PDF (canvas) and the PowerPoint
4
+ * export, so they always match.
5
+ *
6
+ * Backgrounds are dark, for contrast with the clips: a deep diagonal gradient with a soft light
7
+ * from the top left (the gloss), optionally a fine texture. A custom colour gets the same
8
+ * treatment. Typefaces are ones PowerPoint has, so an exported deck keeps its type.
9
+ */
10
+ import type { SlideBackground } from './boxes';
11
+ export type FontId = 'sans' | 'serif' | 'classic';
12
+ export type LogoCorner = 'bl' | 'br';
13
+ export interface ThemeLogo {
14
+ /** An image document of the workspace (a reference; its file is fetched when opened). */
15
+ documentId: string;
16
+ fileName: string;
17
+ corner: LogoCorner;
18
+ }
19
+ export interface Theme {
20
+ /** A background preset's id, or a custom colour (`#rrggbb`). */
21
+ background: string;
22
+ font: FontId;
23
+ /** `#rrggbb`: the rule under titles, bullets. */
24
+ accent: string;
25
+ logo: ThemeLogo | null;
26
+ }
27
+ /** The app's own colours (its `--primary` and `--secondary` tokens), as a background or accent. */
28
+ export declare const BRAND = "brand";
29
+ /** By default a presentation wears the app's brand: its primary as the background, its accent. */
30
+ export declare const DEFAULT_THEME: Theme;
31
+ interface BackgroundSpec {
32
+ /** Top left of the gradient. */
33
+ from: string;
34
+ /** Bottom right. */
35
+ to: string;
36
+ /** The light from the top left (white, this opacity). */
37
+ glow: number;
38
+ texture?: 'linen';
39
+ }
40
+ export declare const BACKGROUNDS: ({
41
+ id: string;
42
+ label: string;
43
+ } & BackgroundSpec)[];
44
+ export declare const FONTS: Record<FontId, {
45
+ label: string;
46
+ css: string;
47
+ pptx: string;
48
+ }>;
49
+ export declare const ACCENTS: {
50
+ label: string;
51
+ color: string;
52
+ }[];
53
+ /** Slide text colours, over the dark background. */
54
+ export declare const TEXT_COLORS: {
55
+ title: string;
56
+ body: string;
57
+ muted: string;
58
+ };
59
+ export declare const isHexColor: (value: string) => boolean;
60
+ /**
61
+ * The app's brand colours, from its `--primary` and `--secondary` tokens (another host's, in that
62
+ * host). The primary stays deep, as a slide background: in a dark mode, where the token is light,
63
+ * its hue is kept at the light theme's depth. Read once.
64
+ */
65
+ export declare function brandColors(): {
66
+ primary: string;
67
+ secondary: string;
68
+ };
69
+ /** A theme's accent as a colour (`brand`: the app's secondary colour). */
70
+ export declare const accentColor: (accent: string) => string;
71
+ /** The background a theme names: a preset, or a custom colour given the presets' finish. */
72
+ export declare function backgroundSpec(background: string): BackgroundSpec;
73
+ /** The background as CSS (container units: the texture keeps its size on any stage). */
74
+ export declare function backgroundCss(background: string): string;
75
+ /** The background painted on a canvas (the saved PDF's pages, the PowerPoint backgrounds). */
76
+ export declare function paintBackground(context: CanvasRenderingContext2D, width: number, height: number, background: string): void;
77
+ /**
78
+ * A page clip's soft edge: paper white at its very edge (`CLIP_EDGE_SOLID`), fading to nothing by
79
+ * `CLIP_EDGE_FADE` (fractions of the stage width; never more than `CLIP_EDGE_MAX` of the clip), so
80
+ * text cut by the clip fades out instead of being sliced, and the clip has a little margin.
81
+ */
82
+ export declare const CLIP_EDGE_SOLID = 0.002;
83
+ export declare const CLIP_EDGE_FADE = 0.009;
84
+ export declare const CLIP_EDGE_MAX = 0.08;
85
+ /** The soft edge as CSS (on the stage: container units). */
86
+ export declare function clipEdgeCss(): string;
87
+ /** The soft edge painted over a clip drawn in `box` (the saved PDF, the PowerPoint images). */
88
+ export declare function paintClipEdge(context: CanvasRenderingContext2D, box: {
89
+ x: number;
90
+ y: number;
91
+ width: number;
92
+ height: number;
93
+ }, stageWidth: number): void;
94
+ /** A slide's own background as CSS: its image (from the presentation's media), gradient or colour. */
95
+ export declare function slideBackgroundCss(background: SlideBackground, media: Readonly<Record<string, string>>): string;
96
+ /** A slide's own background painted on a canvas. */
97
+ export declare function paintSlideBackground(context: CanvasRenderingContext2D, width: number, height: number, background: SlideBackground, media: Readonly<Record<string, string>>): Promise<void>;
98
+ /** Whether a slide's background is light (text on it should be dark). */
99
+ export declare function isLightBackground(background: SlideBackground | undefined): boolean;
100
+ /** A theme read from saved data, every field checked (anything wrong falls back to the default). */
101
+ export declare function parseTheme(value: unknown): Theme;
102
+ export {};
@@ -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