@arbidocs/blocks 0.5.121 → 0.5.123

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 (208) hide show
  1. package/dist/{ClippingMediaViewer-B6WG7Q64.cjs → ClippingMediaViewer-IEIBT74X.cjs} +8 -8
  2. package/dist/{ClippingMediaViewer-B6WG7Q64.cjs.map → ClippingMediaViewer-IEIBT74X.cjs.map} +1 -1
  3. package/dist/{ClippingPdfViewer-6GCVTV3V.cjs → ClippingPdfViewer-OGYLMVCE.cjs} +5 -5
  4. package/dist/{ClippingPdfViewer-6GCVTV3V.cjs.map → ClippingPdfViewer-OGYLMVCE.cjs.map} +1 -1
  5. package/dist/{ConnectedCallDock-DC5V5OUJ.cjs → ConnectedCallDock-XJOYVVAH.cjs} +21 -21
  6. package/dist/{ConnectedCallDock-DC5V5OUJ.cjs.map → ConnectedCallDock-XJOYVVAH.cjs.map} +1 -1
  7. package/dist/{ConnectedCallRoom-FQLXWTFB.cjs → ConnectedCallRoom-CUDYAPQK.cjs} +14 -14
  8. package/dist/{ConnectedCallRoom-FQLXWTFB.cjs.map → ConnectedCallRoom-CUDYAPQK.cjs.map} +1 -1
  9. package/dist/{ConnectedNativeDocxComparison-4Q5S7VLD.cjs → ConnectedNativeDocxComparison-QKHCYD6W.cjs} +15 -15
  10. package/dist/{ConnectedNativeDocxComparison-4Q5S7VLD.cjs.map → ConnectedNativeDocxComparison-QKHCYD6W.cjs.map} +1 -1
  11. package/dist/ConnectedPresentation-5DOJ35XL.cjs +321 -0
  12. package/dist/ConnectedPresentation-5DOJ35XL.cjs.map +1 -0
  13. package/dist/{ConnectedProductionSetDialog-4EAY6KAZ.cjs → ConnectedProductionSetDialog-LHB4VQWC.cjs} +3 -3
  14. package/dist/{ConnectedProductionSetDialog-4EAY6KAZ.cjs.map → ConnectedProductionSetDialog-LHB4VQWC.cjs.map} +1 -1
  15. package/dist/{ConnectedSlidesTab-7QDE2CZD.cjs → ConnectedSlidesTab-7YMEDGUU.cjs} +73 -49
  16. package/dist/ConnectedSlidesTab-7YMEDGUU.cjs.map +1 -0
  17. package/dist/{ConnectedStreamedWordArtifact-FFOQJBOI.cjs → ConnectedStreamedWordArtifact-AG62232A.cjs} +15 -15
  18. package/dist/{ConnectedStreamedWordArtifact-FFOQJBOI.cjs.map → ConnectedStreamedWordArtifact-AG62232A.cjs.map} +1 -1
  19. package/dist/{DocumentReviewCard-SNWVEZ7S.cjs → DocumentReviewCard-M53XFLI2.cjs} +15 -15
  20. package/dist/{DocumentReviewCard-SNWVEZ7S.cjs.map → DocumentReviewCard-M53XFLI2.cjs.map} +1 -1
  21. package/dist/{FilesViewerDialog-IZI63FOV.cjs → FilesViewerDialog-2QCCRWF2.cjs} +50 -49
  22. package/dist/FilesViewerDialog-2QCCRWF2.cjs.map +1 -0
  23. package/dist/{WorkspaceTableView-TEIRB6VJ.cjs → WorkspaceTableView-3XYAV4BV.cjs} +8 -8
  24. package/dist/{WorkspaceTableView-TEIRB6VJ.cjs.map → WorkspaceTableView-3XYAV4BV.cjs.map} +1 -1
  25. package/dist/agents/index.cjs +296 -296
  26. package/dist/{ai-KBYNRNZ6.cjs → ai-IEIR7SC2.cjs} +25 -25
  27. package/dist/ai-IEIR7SC2.cjs.map +1 -0
  28. package/dist/calls/index.cjs +121 -121
  29. package/dist/chat/index.cjs +1 -1
  30. package/dist/{chunk-NLOETJCB.cjs → chunk-2F57IO7S.cjs} +12 -12
  31. package/dist/{chunk-NLOETJCB.cjs.map → chunk-2F57IO7S.cjs.map} +1 -1
  32. package/dist/chunk-2RLA6QO2.cjs +174 -0
  33. package/dist/chunk-2RLA6QO2.cjs.map +1 -0
  34. package/dist/{chunk-Q6DQGGP4.cjs → chunk-325GVZE6.cjs} +3 -3
  35. package/dist/{chunk-Q6DQGGP4.cjs.map → chunk-325GVZE6.cjs.map} +1 -1
  36. package/dist/{chunk-LHWOKOMP.cjs → chunk-46P7IDBX.cjs} +3 -3
  37. package/dist/chunk-46P7IDBX.cjs.map +1 -0
  38. package/dist/{chunk-XTR26TNE.cjs → chunk-4TTX6ZNS.cjs} +20 -4
  39. package/dist/chunk-4TTX6ZNS.cjs.map +1 -0
  40. package/dist/{chunk-BVAT4EVC.cjs → chunk-5QERK4PK.cjs} +35 -35
  41. package/dist/{chunk-BVAT4EVC.cjs.map → chunk-5QERK4PK.cjs.map} +1 -1
  42. package/dist/{chunk-GX2EBMJW.cjs → chunk-6OK7ESTL.cjs} +7 -6
  43. package/dist/chunk-6OK7ESTL.cjs.map +1 -0
  44. package/dist/{chunk-C2OICDMI.cjs → chunk-7557LDAN.cjs} +10 -10
  45. package/dist/{chunk-C2OICDMI.cjs.map → chunk-7557LDAN.cjs.map} +1 -1
  46. package/dist/{chunk-474GPLCM.cjs → chunk-7L4X6QN2.cjs} +6 -6
  47. package/dist/{chunk-474GPLCM.cjs.map → chunk-7L4X6QN2.cjs.map} +1 -1
  48. package/dist/{chunk-52KGMAO5.cjs → chunk-7NLO7ASW.cjs} +15 -15
  49. package/dist/{chunk-52KGMAO5.cjs.map → chunk-7NLO7ASW.cjs.map} +1 -1
  50. package/dist/{chunk-H5OLHP2U.cjs → chunk-7OPOPYV6.cjs} +3 -3
  51. package/dist/{chunk-H5OLHP2U.cjs.map → chunk-7OPOPYV6.cjs.map} +1 -1
  52. package/dist/{chunk-W6B3RYTX.cjs → chunk-7PN3YENO.cjs} +4 -4
  53. package/dist/{chunk-W6B3RYTX.cjs.map → chunk-7PN3YENO.cjs.map} +1 -1
  54. package/dist/{chunk-734NPQNR.cjs → chunk-ADDQKZ5I.cjs} +4 -4
  55. package/dist/{chunk-734NPQNR.cjs.map → chunk-ADDQKZ5I.cjs.map} +1 -1
  56. package/dist/{chunk-JQLWKNJO.cjs → chunk-ALK3PUUB.cjs} +4 -4
  57. package/dist/{chunk-JQLWKNJO.cjs.map → chunk-ALK3PUUB.cjs.map} +1 -1
  58. package/dist/{chunk-4VZZWYEC.cjs → chunk-BQ5RIWWT.cjs} +3 -3
  59. package/dist/{chunk-4VZZWYEC.cjs.map → chunk-BQ5RIWWT.cjs.map} +1 -1
  60. package/dist/{chunk-Q3XJUXID.cjs → chunk-DWMWEALB.cjs} +499 -409
  61. package/dist/chunk-DWMWEALB.cjs.map +1 -0
  62. package/dist/{chunk-3SCNXNHI.cjs → chunk-E3L5DB5F.cjs} +5 -5
  63. package/dist/{chunk-3SCNXNHI.cjs.map → chunk-E3L5DB5F.cjs.map} +1 -1
  64. package/dist/{chunk-VJ5ZLRBD.cjs → chunk-GFUOCGY6.cjs} +8 -3
  65. package/dist/chunk-GFUOCGY6.cjs.map +1 -0
  66. package/dist/{chunk-7VUJGHMY.cjs → chunk-JD2HX2BR.cjs} +272 -156
  67. package/dist/chunk-JD2HX2BR.cjs.map +1 -0
  68. package/dist/{chunk-RYVZDFVO.cjs → chunk-JJZOL5MG.cjs} +3 -3
  69. package/dist/{chunk-RYVZDFVO.cjs.map → chunk-JJZOL5MG.cjs.map} +1 -1
  70. package/dist/{chunk-QFXILJMJ.cjs → chunk-K4763GD5.cjs} +17 -174
  71. package/dist/chunk-K4763GD5.cjs.map +1 -0
  72. package/dist/{chunk-EHP6OH5D.cjs → chunk-KA3F6TIH.cjs} +11 -11
  73. package/dist/{chunk-EHP6OH5D.cjs.map → chunk-KA3F6TIH.cjs.map} +1 -1
  74. package/dist/{chunk-UUENH4BJ.cjs → chunk-KXIRVKCJ.cjs} +3 -3
  75. package/dist/{chunk-UUENH4BJ.cjs.map → chunk-KXIRVKCJ.cjs.map} +1 -1
  76. package/dist/{chunk-AY6EZSZB.cjs → chunk-L4CIFLCU.cjs} +4 -4
  77. package/dist/{chunk-AY6EZSZB.cjs.map → chunk-L4CIFLCU.cjs.map} +1 -1
  78. package/dist/{chunk-4RBQ44RY.cjs → chunk-MLA2BJ2Y.cjs} +28 -28
  79. package/dist/{chunk-4RBQ44RY.cjs.map → chunk-MLA2BJ2Y.cjs.map} +1 -1
  80. package/dist/{chunk-DR2AH7JL.cjs → chunk-NG2EE7HR.cjs} +48 -48
  81. package/dist/{chunk-DR2AH7JL.cjs.map → chunk-NG2EE7HR.cjs.map} +1 -1
  82. package/dist/{chunk-ENGL7P3I.cjs → chunk-NQML7IUC.cjs} +26 -26
  83. package/dist/{chunk-ENGL7P3I.cjs.map → chunk-NQML7IUC.cjs.map} +1 -1
  84. package/dist/{chunk-4NPCDS2X.cjs → chunk-NY3YUCOW.cjs} +3 -3
  85. package/dist/{chunk-4NPCDS2X.cjs.map → chunk-NY3YUCOW.cjs.map} +1 -1
  86. package/dist/{chunk-JZEYHDWJ.cjs → chunk-OHHKBURG.cjs} +76 -76
  87. package/dist/chunk-OHHKBURG.cjs.map +1 -0
  88. package/dist/{chunk-5534FYXP.cjs → chunk-SDRYSLOX.cjs} +4 -4
  89. package/dist/{chunk-5534FYXP.cjs.map → chunk-SDRYSLOX.cjs.map} +1 -1
  90. package/dist/{chunk-2W5E62EY.cjs → chunk-SGYSDABK.cjs} +6 -6
  91. package/dist/{chunk-2W5E62EY.cjs.map → chunk-SGYSDABK.cjs.map} +1 -1
  92. package/dist/{chunk-KP5AITQ4.cjs → chunk-SNPK3R3O.cjs} +7 -7
  93. package/dist/{chunk-KP5AITQ4.cjs.map → chunk-SNPK3R3O.cjs.map} +1 -1
  94. package/dist/{chunk-EATIFPKP.cjs → chunk-T73BHNQX.cjs} +4 -4
  95. package/dist/{chunk-EATIFPKP.cjs.map → chunk-T73BHNQX.cjs.map} +1 -1
  96. package/dist/{chunk-4IOYQLKG.cjs → chunk-TP5PGWIO.cjs} +3 -3
  97. package/dist/{chunk-4IOYQLKG.cjs.map → chunk-TP5PGWIO.cjs.map} +1 -1
  98. package/dist/{chunk-GKVE5JGB.cjs → chunk-UFT22LAB.cjs} +3 -3
  99. package/dist/{chunk-GKVE5JGB.cjs.map → chunk-UFT22LAB.cjs.map} +1 -1
  100. package/dist/{chunk-FKFQCK3C.cjs → chunk-V6MW7B4B.cjs} +4 -4
  101. package/dist/{chunk-FKFQCK3C.cjs.map → chunk-V6MW7B4B.cjs.map} +1 -1
  102. package/dist/{chunk-2PZT3J34.cjs → chunk-VWBYE3XY.cjs} +6 -6
  103. package/dist/{chunk-2PZT3J34.cjs.map → chunk-VWBYE3XY.cjs.map} +1 -1
  104. package/dist/{chunk-GQXPNIRE.cjs → chunk-WAV762GP.cjs} +6 -6
  105. package/dist/{chunk-GQXPNIRE.cjs.map → chunk-WAV762GP.cjs.map} +1 -1
  106. package/dist/{chunk-5LTIZ44D.cjs → chunk-WFMWKPGY.cjs} +14 -7
  107. package/dist/chunk-WFMWKPGY.cjs.map +1 -0
  108. package/dist/{chunk-GPX5VC57.cjs → chunk-WV7BCGCK.cjs} +50 -50
  109. package/dist/{chunk-GPX5VC57.cjs.map → chunk-WV7BCGCK.cjs.map} +1 -1
  110. package/dist/{chunk-MZ2KZXNU.cjs → chunk-WXUU3COI.cjs} +3 -3
  111. package/dist/{chunk-MZ2KZXNU.cjs.map → chunk-WXUU3COI.cjs.map} +1 -1
  112. package/dist/{chunk-NAJN32MF.cjs → chunk-XF355M7O.cjs} +13 -13
  113. package/dist/{chunk-NAJN32MF.cjs.map → chunk-XF355M7O.cjs.map} +1 -1
  114. package/dist/connect/docx.cjs +18 -18
  115. package/dist/connect/index.cjs +995 -994
  116. package/dist/connect/index.cjs.map +1 -1
  117. package/dist/connect/viewer.cjs +38 -37
  118. package/dist/connection/conversation/ConnectedMessage.js +1 -1
  119. package/dist/connection/conversation/ConnectedMessage.js.map +2 -2
  120. package/dist/connection/presentation/ConnectedSlidesTab.js +39 -15
  121. package/dist/connection/presentation/ConnectedSlidesTab.js.map +2 -2
  122. package/dist/connection/presentation/PresentationPill.js +3 -8
  123. package/dist/connection/presentation/PresentationPill.js.map +2 -2
  124. package/dist/connection/presentation/requests.d.ts +5 -0
  125. package/dist/connection/presentation/requests.js +8 -1
  126. package/dist/connection/presentation/requests.js.map +2 -2
  127. package/dist/connection/viewer/ConnectedDocumentViewer.js +51 -60
  128. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  129. package/dist/connection/viewer/ViewerMoreMenu.d.ts +18 -0
  130. package/dist/connection/viewer/ViewerMoreMenu.js +45 -0
  131. package/dist/connection/viewer/ViewerMoreMenu.js.map +7 -0
  132. package/dist/connection/viewer/ViewerPdfPane.js +4 -1
  133. package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
  134. package/dist/connection/viewer/documentPlace.d.ts +5 -4
  135. package/dist/connection/viewer/documentPlace.js +2 -2
  136. package/dist/connection/viewer/documentPlace.js.map +2 -2
  137. package/dist/connection/viewer/pdf/PdfClipOutlines.d.ts +11 -0
  138. package/dist/connection/viewer/pdf/PdfClipOutlines.js +42 -0
  139. package/dist/connection/viewer/pdf/PdfClipOutlines.js.map +7 -0
  140. package/dist/connection/viewer/pdf/PdfPassageHighlights.js +3 -2
  141. package/dist/connection/viewer/pdf/PdfPassageHighlights.js.map +2 -2
  142. package/dist/connection/viewer/pdf/clipOutlines.d.ts +17 -0
  143. package/dist/connection/viewer/pdf/clipOutlines.js +24 -0
  144. package/dist/connection/viewer/pdf/clipOutlines.js.map +7 -0
  145. package/dist/connection/viewer/pdf/passageHighlights.d.ts +2 -0
  146. package/dist/connection/viewer/pdf/passageHighlights.js +12 -1
  147. package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
  148. package/dist/connection/viewer/pdf/usePdfClipOutlines.d.ts +7 -0
  149. package/dist/connection/viewer/pdf/usePdfClipOutlines.js +36 -0
  150. package/dist/connection/viewer/pdf/usePdfClipOutlines.js.map +7 -0
  151. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +11 -2
  152. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
  153. package/dist/dashboards/index.cjs +1 -1
  154. package/dist/document-tools/DocumentToolButtons.js +2 -2
  155. package/dist/document-tools/DocumentToolButtons.js.map +2 -2
  156. package/dist/document-tools/index.cjs +13 -13
  157. package/dist/embed/index.cjs +38 -38
  158. package/dist/files/index.cjs +224 -224
  159. package/dist/index.cjs +1596 -1595
  160. package/dist/index.cjs.map +1 -1
  161. package/dist/presentation/BoxActionBar.d.ts +2 -2
  162. package/dist/presentation/BoxActionBar.js +62 -30
  163. package/dist/presentation/BoxActionBar.js.map +2 -2
  164. package/dist/presentation/ClipActionBar.js +60 -7
  165. package/dist/presentation/ClipActionBar.js.map +2 -2
  166. package/dist/presentation/ClipViewControls.d.ts +3 -3
  167. package/dist/presentation/ClipViewControls.js +59 -64
  168. package/dist/presentation/ClipViewControls.js.map +2 -2
  169. package/dist/presentation/PresentControls.d.ts +11 -0
  170. package/dist/presentation/PresentControls.js +117 -0
  171. package/dist/presentation/PresentControls.js.map +7 -0
  172. package/dist/presentation/PresenterView.js +36 -5
  173. package/dist/presentation/PresenterView.js.map +2 -2
  174. package/dist/presentation/SlidesEditor.js +73 -43
  175. package/dist/presentation/SlidesEditor.js.map +2 -2
  176. package/dist/presentation/StageItem.js +0 -5
  177. package/dist/presentation/StageItem.js.map +2 -2
  178. package/dist/presentation/panel-id.d.ts +12 -2
  179. package/dist/presentation/panel-id.js +6 -1
  180. package/dist/presentation/panel-id.js.map +2 -2
  181. package/dist/presentation/slide-layout.d.ts +5 -1
  182. package/dist/presentation/slide-layout.js +16 -0
  183. package/dist/presentation/slide-layout.js.map +2 -2
  184. package/dist/settings/index.cjs +146 -146
  185. package/dist/shell/PanelPortal.js +13 -4
  186. package/dist/shell/PanelPortal.js.map +2 -2
  187. package/dist/shell/index.cjs +92 -91
  188. package/dist/shell/panel-windows.js +1 -0
  189. package/dist/shell/panel-windows.js.map +2 -2
  190. package/dist/studio/index.cjs +28 -28
  191. package/dist/styles.css +1 -1
  192. package/dist/workflow-canvas/index.cjs +52 -52
  193. package/node_modules/@arbidocs/coedit/package.json +1 -1
  194. package/package.json +5 -5
  195. package/dist/ConnectedPresentation-4HLDZDWV.cjs +0 -183
  196. package/dist/ConnectedPresentation-4HLDZDWV.cjs.map +0 -1
  197. package/dist/ConnectedSlidesTab-7QDE2CZD.cjs.map +0 -1
  198. package/dist/FilesViewerDialog-IZI63FOV.cjs.map +0 -1
  199. package/dist/ai-KBYNRNZ6.cjs.map +0 -1
  200. package/dist/chunk-5LTIZ44D.cjs.map +0 -1
  201. package/dist/chunk-7VUJGHMY.cjs.map +0 -1
  202. package/dist/chunk-GX2EBMJW.cjs.map +0 -1
  203. package/dist/chunk-JZEYHDWJ.cjs.map +0 -1
  204. package/dist/chunk-LHWOKOMP.cjs.map +0 -1
  205. package/dist/chunk-Q3XJUXID.cjs.map +0 -1
  206. package/dist/chunk-QFXILJMJ.cjs.map +0 -1
  207. package/dist/chunk-VJ5ZLRBD.cjs.map +0 -1
  208. package/dist/chunk-XTR26TNE.cjs.map +0 -1
@@ -3,10 +3,10 @@
3
3
 
4
4
  var chunkWOOOMTTA_cjs = require('./chunk-WOOOMTTA.cjs');
5
5
  var chunk5GCCUXMT_cjs = require('./chunk-5GCCUXMT.cjs');
6
- var chunkNLOETJCB_cjs = require('./chunk-NLOETJCB.cjs');
7
- var chunkGKVE5JGB_cjs = require('./chunk-GKVE5JGB.cjs');
8
- var chunk5LTIZ44D_cjs = require('./chunk-5LTIZ44D.cjs');
9
- var chunkXTR26TNE_cjs = require('./chunk-XTR26TNE.cjs');
6
+ var chunk2F57IO7S_cjs = require('./chunk-2F57IO7S.cjs');
7
+ var chunkUFT22LAB_cjs = require('./chunk-UFT22LAB.cjs');
8
+ var chunkWFMWKPGY_cjs = require('./chunk-WFMWKPGY.cjs');
9
+ var chunk4TTX6ZNS_cjs = require('./chunk-4TTX6ZNS.cjs');
10
10
  var chunk7JLJH5CW_cjs = require('./chunk-7JLJH5CW.cjs');
11
11
  var chunkVZOOGA47_cjs = require('./chunk-VZOOGA47.cjs');
12
12
  var chunkTKHCIHE2_cjs = require('./chunk-TKHCIHE2.cjs');
@@ -62,7 +62,7 @@ function MediaClip({
62
62
  preload: "auto",
63
63
  className: "pointer-events-none block select-none",
64
64
  style: cropStyle(clip.rect),
65
- ...live ? { [chunk5LTIZ44D_cjs.STAGE_VIDEO_ATTRIBUTE]: "" } : {}
65
+ ...live ? { [chunkWFMWKPGY_cjs.STAGE_VIDEO_ATTRIBUTE]: "" } : {}
66
66
  }
67
67
  ) : /* @__PURE__ */ jsxRuntime.jsx(
68
68
  "img",
@@ -191,7 +191,7 @@ var DROP_ATTRIBUTE = "data-presentation-drop";
191
191
  function dropAt(doc, clipId, x, y) {
192
192
  const target = doc.elementFromPoint(x, y)?.closest(`[${DROP_ATTRIBUTE}]`);
193
193
  if (!target) return false;
194
- const state = chunkXTR26TNE_cjs.usePresentation.getState();
194
+ const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
195
195
  if (target.getAttribute(DROP_ATTRIBUTE) === "slide") {
196
196
  const index2 = Number(target.getAttribute("data-slide-index"));
197
197
  if (!Number.isInteger(index2)) return false;
@@ -211,7 +211,7 @@ function useClipDrag(clipId, onTap) {
211
211
  const end = () => {
212
212
  press.current = null;
213
213
  setGhost(null);
214
- chunkXTR26TNE_cjs.usePresentation.getState().setDragging(null);
214
+ chunk4TTX6ZNS_cjs.usePresentation.getState().setDragging(null);
215
215
  };
216
216
  return {
217
217
  ghost,
@@ -227,7 +227,7 @@ function useClipDrag(clipId, onTap) {
227
227
  if (Math.hypot(event.clientX - p.x, event.clientY - p.y) < DRAG_THRESHOLD) return;
228
228
  p.dragging = true;
229
229
  event.currentTarget.setPointerCapture(event.pointerId);
230
- chunkXTR26TNE_cjs.usePresentation.getState().setDragging(clipId);
230
+ chunk4TTX6ZNS_cjs.usePresentation.getState().setDragging(clipId);
231
231
  }
232
232
  event.preventDefault();
233
233
  setGhost({ x: event.clientX, y: event.clientY });
@@ -265,7 +265,7 @@ function Label({ clip }) {
265
265
  "aria-label": "Clip label",
266
266
  className: "w-full rounded border border-input bg-background px-1 text-[11px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
267
267
  onBlur: (event) => {
268
- chunkXTR26TNE_cjs.usePresentation.getState().setCaption(clip.id, event.target.value);
268
+ chunk4TTX6ZNS_cjs.usePresentation.getState().setCaption(clip.id, event.target.value);
269
269
  setEditing(false);
270
270
  },
271
271
  onKeyDown: (event) => {
@@ -287,7 +287,7 @@ function Label({ clip }) {
287
287
  );
288
288
  }
289
289
  function TrayTile({ clip, onSlide }) {
290
- const { place, removeClip } = chunkXTR26TNE_cjs.usePresentation.getState();
290
+ const { place, removeClip } = chunk4TTX6ZNS_cjs.usePresentation.getState();
291
291
  const drag = useClipDrag(clip.id, () => !onSlide && place(clip.id));
292
292
  const itemRef = react.useRef(null);
293
293
  const size = tileSize(clip.aspect);
@@ -354,9 +354,9 @@ function TrayTile({ clip, onSlide }) {
354
354
  );
355
355
  }
356
356
  function ClipTray({ start }) {
357
- const all = chunkXTR26TNE_cjs.usePresentation((s) => s.clips);
357
+ const all = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips);
358
358
  const clips = react.useMemo(() => all.filter((clip) => !clip.plain), [all]);
359
- const slide = chunkXTR26TNE_cjs.usePresentation(chunkXTR26TNE_cjs.currentSlide);
359
+ const slide = chunk4TTX6ZNS_cjs.usePresentation(chunk4TTX6ZNS_cjs.currentSlide);
360
360
  const onSlide = new Set(slide?.items.map((item) => item.clipId));
361
361
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t border-border bg-background", "data-testid": "clip-tray-bar", children: clips.length || start ? /* @__PURE__ */ jsxRuntime.jsxs(
362
362
  "ul",
@@ -411,7 +411,7 @@ function CustomColor({
411
411
  "input",
412
412
  {
413
413
  type: "color",
414
- value: chunkXTR26TNE_cjs.isHexColor(value) ? value : "#1f2937",
414
+ value: chunk4TTX6ZNS_cjs.isHexColor(value) ? value : "#1f2937",
415
415
  onChange: (event) => onChange(event.target.value),
416
416
  "aria-label": label,
417
417
  className: "absolute inset-0 cursor-pointer opacity-0"
@@ -422,10 +422,10 @@ function CustomColor({
422
422
  );
423
423
  }
424
424
  function DesignMenu({ onChooseLogo }) {
425
- const theme = chunkXTR26TNE_cjs.usePresentation((s) => s.theme);
426
- const setTheme = chunkXTR26TNE_cjs.usePresentation((s) => s.setTheme);
427
- const customBackground = chunkXTR26TNE_cjs.isHexColor(theme.background);
428
- const customAccent = !chunkXTR26TNE_cjs.ACCENTS.some((accent) => accent.color === theme.accent);
425
+ const theme = chunk4TTX6ZNS_cjs.usePresentation((s) => s.theme);
426
+ const setTheme = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setTheme);
427
+ const customBackground = chunk4TTX6ZNS_cjs.isHexColor(theme.background);
428
+ const customAccent = !chunk4TTX6ZNS_cjs.ACCENTS.some((accent) => accent.color === theme.accent);
429
429
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
430
430
  /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
431
431
  ui.Button,
@@ -442,7 +442,7 @@ function DesignMenu({ onChooseLogo }) {
442
442
  ) }),
443
443
  /* @__PURE__ */ jsxRuntime.jsxs(ui.PopoverContent, { align: "end", className: "flex w-[21.5rem] flex-col gap-4 overflow-x-hidden p-4", children: [
444
444
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-7 gap-2", children: [
445
- chunkXTR26TNE_cjs.BACKGROUNDS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
445
+ chunk4TTX6ZNS_cjs.BACKGROUNDS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
446
446
  "button",
447
447
  {
448
448
  type: "button",
@@ -454,7 +454,7 @@ function DesignMenu({ onChooseLogo }) {
454
454
  "size-8 rounded-md border border-border shadow-sm",
455
455
  theme.background === preset.id && "ring-2 ring-primary ring-offset-1 ring-offset-background"
456
456
  ),
457
- style: { background: chunkXTR26TNE_cjs.backgroundCss(preset.id), containerType: "inline-size" },
457
+ style: { background: chunk4TTX6ZNS_cjs.backgroundCss(preset.id), containerType: "inline-size" },
458
458
  "data-testid": `design-background-${preset.id}`
459
459
  },
460
460
  preset.id
@@ -469,7 +469,7 @@ function DesignMenu({ onChooseLogo }) {
469
469
  }
470
470
  )
471
471
  ] }) }),
472
- /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Typeface", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: Object.keys(chunkXTR26TNE_cjs.FONTS).map((font) => /* @__PURE__ */ jsxRuntime.jsxs(
472
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Typeface", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: Object.keys(chunk4TTX6ZNS_cjs.FONTS).map((font) => /* @__PURE__ */ jsxRuntime.jsxs(
473
473
  "button",
474
474
  {
475
475
  type: "button",
@@ -481,14 +481,14 @@ function DesignMenu({ onChooseLogo }) {
481
481
  ),
482
482
  "data-testid": `design-font-${font}`,
483
483
  children: [
484
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl leading-tight", style: { fontFamily: chunkXTR26TNE_cjs.FONTS[font].css }, children: "Aa" }),
485
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-muted-foreground", children: chunkXTR26TNE_cjs.FONTS[font].label })
484
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl leading-tight", style: { fontFamily: chunk4TTX6ZNS_cjs.FONTS[font].css }, children: "Aa" }),
485
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-muted-foreground", children: chunk4TTX6ZNS_cjs.FONTS[font].label })
486
486
  ]
487
487
  },
488
488
  font
489
489
  )) }) }),
490
490
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Accent", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
491
- chunkXTR26TNE_cjs.ACCENTS.map((accent) => /* @__PURE__ */ jsxRuntime.jsx(
491
+ chunk4TTX6ZNS_cjs.ACCENTS.map((accent) => /* @__PURE__ */ jsxRuntime.jsx(
492
492
  "button",
493
493
  {
494
494
  type: "button",
@@ -500,7 +500,7 @@ function DesignMenu({ onChooseLogo }) {
500
500
  "flex size-8 items-center justify-center rounded-full border border-black/10 shadow-sm",
501
501
  theme.accent === accent.color && "ring-2 ring-primary ring-offset-1 ring-offset-background"
502
502
  ),
503
- style: { background: chunkXTR26TNE_cjs.accentColor(accent.color) },
503
+ style: { background: chunk4TTX6ZNS_cjs.accentColor(accent.color) },
504
504
  children: theme.accent === accent.color && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5 text-black/70" })
505
505
  },
506
506
  accent.color
@@ -508,7 +508,7 @@ function DesignMenu({ onChooseLogo }) {
508
508
  /* @__PURE__ */ jsxRuntime.jsx(
509
509
  CustomColor,
510
510
  {
511
- value: chunkXTR26TNE_cjs.accentColor(theme.accent),
511
+ value: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
512
512
  selected: customAccent,
513
513
  label: "Your own accent colour",
514
514
  round: true,
@@ -571,13 +571,13 @@ var at = (box2) => ({
571
571
  height: `${box2.h * 100}%`
572
572
  });
573
573
  function LayoutThumb({ layout, className }) {
574
- const geometry = chunkXTR26TNE_cjs.slideGeometry({ layout, caption: "Title" }, { labels: false, logo: null });
574
+ const geometry = chunk4TTX6ZNS_cjs.slideGeometry({ layout, caption: "Title" }, { labels: false, logo: null });
575
575
  const { top, right = 0, bottom = 0, columns } = geometry.reserve;
576
576
  const room = {
577
- x: chunkXTR26TNE_cjs.STAGE_MARGIN,
578
- y: chunkXTR26TNE_cjs.STAGE_MARGIN + top,
579
- w: 1 - 2 * chunkXTR26TNE_cjs.STAGE_MARGIN - right,
580
- h: 1 - 2 * chunkXTR26TNE_cjs.STAGE_MARGIN - top - bottom
577
+ x: chunk4TTX6ZNS_cjs.STAGE_MARGIN,
578
+ y: chunk4TTX6ZNS_cjs.STAGE_MARGIN + top,
579
+ w: 1 - 2 * chunk4TTX6ZNS_cjs.STAGE_MARGIN - right,
580
+ h: 1 - 2 * chunk4TTX6ZNS_cjs.STAGE_MARGIN - top - bottom
581
581
  };
582
582
  const blocks = layout === "title" || layout === "section" || layout === "free" ? [] : columns === 2 ? [
583
583
  { ...room, w: room.w / 2 - 0.02 },
@@ -628,10 +628,10 @@ function LayoutMenu({
628
628
  className,
629
629
  compact = false
630
630
  }) {
631
- const layout = chunkXTR26TNE_cjs.usePresentation(
632
- (s) => (index === void 0 ? chunkXTR26TNE_cjs.currentSlide(s) : s.slides[index])?.layout ?? "clips"
631
+ const layout = chunk4TTX6ZNS_cjs.usePresentation(
632
+ (s) => (index === void 0 ? chunk4TTX6ZNS_cjs.currentSlide(s) : s.slides[index])?.layout ?? "clips"
633
633
  );
634
- const setSlideLayout = chunkXTR26TNE_cjs.usePresentation((s) => s.setSlideLayout);
634
+ const setSlideLayout = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setSlideLayout);
635
635
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
636
636
  /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
637
637
  ui.Button,
@@ -644,7 +644,7 @@ function LayoutMenu({
644
644
  className
645
645
  ),
646
646
  title: "Slide layout",
647
- "aria-label": `Slide layout: ${chunkXTR26TNE_cjs.LAYOUT_INFO[layout].label}`,
647
+ "aria-label": `Slide layout: ${chunk4TTX6ZNS_cjs.LAYOUT_INFO[layout].label}`,
648
648
  "data-testid": "presentation-layout",
649
649
  children: [
650
650
  /* @__PURE__ */ jsxRuntime.jsx(LayoutThumb, { layout, className: compact ? "w-6" : "w-7" }),
@@ -652,7 +652,7 @@ function LayoutMenu({
652
652
  ]
653
653
  }
654
654
  ) }),
655
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuContent, { align: "start", className: "w-56", children: chunkXTR26TNE_cjs.SLIDE_LAYOUTS.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
655
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuContent, { align: "start", className: "w-56", children: chunk4TTX6ZNS_cjs.SLIDE_LAYOUTS.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
656
656
  ui.DropdownMenuItem,
657
657
  {
658
658
  onSelect: () => setSlideLayout(option, index),
@@ -660,7 +660,7 @@ function LayoutMenu({
660
660
  "data-testid": `presentation-layout-${option}`,
661
661
  children: [
662
662
  /* @__PURE__ */ jsxRuntime.jsx(LayoutThumb, { layout: option, className: "w-12" }),
663
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: chunkXTR26TNE_cjs.LAYOUT_INFO[option].label })
663
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: chunk4TTX6ZNS_cjs.LAYOUT_INFO[option].label })
664
664
  ]
665
665
  },
666
666
  option
@@ -668,11 +668,11 @@ function LayoutMenu({
668
668
  ] });
669
669
  }
670
670
  function Notice() {
671
- const notice = chunkXTR26TNE_cjs.usePresentation((s) => s.notice);
671
+ const notice = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notice);
672
672
  react.useEffect(() => {
673
673
  if (!notice) return;
674
674
  const timer = setTimeout(
675
- () => chunkXTR26TNE_cjs.usePresentation.getState().clearNotice(notice.id),
675
+ () => chunk4TTX6ZNS_cjs.usePresentation.getState().clearNotice(notice.id),
676
676
  notice.kind === "error" ? 8e3 : 3e3
677
677
  );
678
678
  return () => clearTimeout(timer);
@@ -693,7 +693,7 @@ function Notice() {
693
693
  type: "button",
694
694
  className: "ml-1 rounded p-0.5 text-muted-foreground hover:text-foreground",
695
695
  "aria-label": "Dismiss",
696
- onClick: () => chunkXTR26TNE_cjs.usePresentation.getState().clearNotice(notice.id),
696
+ onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().clearNotice(notice.id),
697
697
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" })
698
698
  }
699
699
  )
@@ -701,6 +701,132 @@ function Notice() {
701
701
  }
702
702
  );
703
703
  }
704
+ var PAN_STEP = 0.1;
705
+ var MAX_ZOOM = 800;
706
+ var HOLD_DELAY = 350;
707
+ var HOLD_EVERY = 90;
708
+ var BUTTON = "flex size-7 items-center justify-center rounded-full border border-border bg-background text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-30 pointer-coarse:size-11";
709
+ function HoldButton({
710
+ label,
711
+ disabled,
712
+ onStep,
713
+ className,
714
+ children
715
+ }) {
716
+ const timer = react.useRef(null);
717
+ const stop = () => {
718
+ if (timer.current) clearTimeout(timer.current);
719
+ timer.current = null;
720
+ };
721
+ react.useEffect(() => stop, []);
722
+ react.useEffect(() => {
723
+ if (disabled) stop();
724
+ }, [disabled]);
725
+ const start = (event) => {
726
+ event.stopPropagation();
727
+ if (disabled || event.button !== 0) return;
728
+ onStep();
729
+ const repeat = () => {
730
+ onStep();
731
+ timer.current = setTimeout(repeat, HOLD_EVERY);
732
+ };
733
+ timer.current = setTimeout(repeat, HOLD_DELAY);
734
+ };
735
+ return /* @__PURE__ */ jsxRuntime.jsx(
736
+ "button",
737
+ {
738
+ type: "button",
739
+ className: ui.cn(BUTTON, className),
740
+ title: label,
741
+ "aria-label": label,
742
+ disabled,
743
+ onPointerDown: start,
744
+ onPointerUp: stop,
745
+ onPointerLeave: stop,
746
+ onPointerCancel: stop,
747
+ onClick: (event) => event.detail === 0 && onStep(),
748
+ children
749
+ }
750
+ );
751
+ }
752
+ function ClipViewControls({ clip }) {
753
+ const { panClip, setClipZoom } = chunk4TTX6ZNS_cjs.usePresentation.getState();
754
+ const { rect } = clip;
755
+ const zoomBase = clip.zoomBase ?? rect.w;
756
+ const minZoom = Math.min(100, Math.floor(zoomBase / Math.min(1, rect.w / rect.h) * 100));
757
+ const pan = (dx, dy) => () => panClip(clip.id, dx * rect.w, dy * rect.h);
758
+ const zoom = Math.round(zoomBase / rect.w * 100);
759
+ const edge = 1e-6;
760
+ return /* @__PURE__ */ jsxRuntime.jsxs(
761
+ "div",
762
+ {
763
+ className: "flex flex-col items-center gap-2 p-1",
764
+ onPointerDown: (event) => event.stopPropagation(),
765
+ "data-testid": "clip-view-controls",
766
+ children: [
767
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 grid-rows-3 place-items-center gap-0.5", children: [
768
+ /* @__PURE__ */ jsxRuntime.jsx(
769
+ HoldButton,
770
+ {
771
+ label: "Show more above",
772
+ disabled: rect.y <= edge,
773
+ onStep: pan(0, -PAN_STEP),
774
+ className: "col-start-2 row-start-1",
775
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "size-4" })
776
+ }
777
+ ),
778
+ /* @__PURE__ */ jsxRuntime.jsx(
779
+ HoldButton,
780
+ {
781
+ label: "Show more on the left",
782
+ disabled: rect.x <= edge,
783
+ onStep: pan(-PAN_STEP, 0),
784
+ className: "col-start-1 row-start-2",
785
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-4" })
786
+ }
787
+ ),
788
+ /* @__PURE__ */ jsxRuntime.jsx(
789
+ HoldButton,
790
+ {
791
+ label: "Show more on the right",
792
+ disabled: rect.x + rect.w >= 1 - edge,
793
+ onStep: pan(PAN_STEP, 0),
794
+ className: "col-start-3 row-start-2",
795
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-4" })
796
+ }
797
+ ),
798
+ /* @__PURE__ */ jsxRuntime.jsx(
799
+ HoldButton,
800
+ {
801
+ label: "Show more below",
802
+ disabled: rect.y + rect.h >= 1 - edge,
803
+ onStep: pan(0, PAN_STEP),
804
+ className: "col-start-2 row-start-3",
805
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4" })
806
+ }
807
+ )
808
+ ] }),
809
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "clip-zoom-control", children: /* @__PURE__ */ jsxRuntime.jsx(
810
+ chunk5GCCUXMT_cjs.ZoomSlider,
811
+ {
812
+ value: zoom,
813
+ min: minZoom,
814
+ max: Math.max(MAX_ZOOM, zoom),
815
+ zoomOutStep: 25,
816
+ onChange: (value) => setClipZoom(clip.id, value),
817
+ label: "Zoom",
818
+ valueLabel: /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-testid": "clip-zoom", children: [
819
+ zoom,
820
+ "%"
821
+ ] }),
822
+ className: "pointer-coarse:h-11",
823
+ sliderClassName: "w-28"
824
+ }
825
+ ) })
826
+ ]
827
+ }
828
+ );
829
+ }
704
830
  var ACTION = "inline-flex size-7 items-center justify-center rounded text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:size-11";
705
831
  var SIZES = [
706
832
  { command: "fit", label: "Fit the slide", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "size-4" }) },
@@ -729,7 +855,8 @@ function ClipActionBar({
729
855
  onEditImage,
730
856
  onCropImage
731
857
  }) {
732
- const actions = chunkXTR26TNE_cjs.usePresentation.getState();
858
+ const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
859
+ const clip = chunk4TTX6ZNS_cjs.usePresentation((state) => state.clips.find((entry) => entry.id === clipId));
733
860
  return /* @__PURE__ */ jsxRuntime.jsxs(
734
861
  "div",
735
862
  {
@@ -740,7 +867,7 @@ function ClipActionBar({
740
867
  onPointerDown: (event) => event.stopPropagation(),
741
868
  "data-testid": "clip-action-bar",
742
869
  children: [
743
- SIZES.map(({ command, label, icon }) => /* @__PURE__ */ jsxRuntime.jsx(Action, { label, onClick: () => actions.applyFrame(clipId, command), children: icon }, command)),
870
+ /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Fit the slide", onClick: () => actions.applyFrame(clipId, "fit"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "size-4" }) }),
744
871
  /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
745
872
  /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: ACTION, title: "Align", "aria-label": "Align", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenterHorizontal, { className: "size-4" }) }) }),
746
873
  /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuContent, { align: "start", children: ALIGNMENTS.map(({ alignment, label, icon }) => /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.align(clipId, alignment), children: [
@@ -748,11 +875,56 @@ function ClipActionBar({
748
875
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: label })
749
876
  ] }, alignment)) })
750
877
  ] }),
751
- onCropImage && /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Crop", onClick: onCropImage, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crop, { className: "size-4" }) }),
752
- onEditImage && /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Edit image", onClick: onEditImage, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-4" }) }),
753
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-0.5 h-5 w-px bg-border" }),
754
- /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Bring to front", onClick: () => actions.bringToFront(clipId), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BringToFront, { className: "size-4" }) }),
755
- /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Send to back", onClick: () => actions.sendToBack(clipId), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendToBack, { className: "size-4" }) }),
878
+ clip && /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
879
+ /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
880
+ "button",
881
+ {
882
+ type: "button",
883
+ className: ACTION,
884
+ title: "View: scroll or zoom what the clip shows (or scroll over it)",
885
+ "aria-label": "View",
886
+ "data-testid": "clip-view-button",
887
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ZoomIn, { className: "size-4" })
888
+ }
889
+ ) }),
890
+ /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverContent, { align: "start", className: "w-auto p-2", children: /* @__PURE__ */ jsxRuntime.jsx(ClipViewControls, { clip }) })
891
+ ] }),
892
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
893
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
894
+ "button",
895
+ {
896
+ type: "button",
897
+ className: ACTION,
898
+ title: "More",
899
+ "aria-label": "More",
900
+ "data-testid": "clip-more-menu",
901
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "size-4" })
902
+ }
903
+ ) }),
904
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuContent, { align: "start", children: [
905
+ SIZES.filter(({ command }) => command !== "fit").map(({ command, label, icon }) => /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.applyFrame(clipId, command), children: [
906
+ icon,
907
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: label })
908
+ ] }, command)),
909
+ onCropImage && /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: onCropImage, children: [
910
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crop, { className: "size-4" }),
911
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Crop" })
912
+ ] }),
913
+ onEditImage && /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: onEditImage, children: [
914
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-4" }),
915
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Edit image" })
916
+ ] }),
917
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuSeparator, {}),
918
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.bringToFront(clipId), children: [
919
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BringToFront, { className: "size-4" }),
920
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Bring to front" })
921
+ ] }),
922
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.sendToBack(clipId), children: [
923
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendToBack, { className: "size-4" }),
924
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Send to back" })
925
+ ] })
926
+ ] })
927
+ ] }),
756
928
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-0.5 h-5 w-px bg-border" }),
757
929
  /* @__PURE__ */ jsxRuntime.jsx(
758
930
  "button",
@@ -808,7 +980,7 @@ function Text({
808
980
  box2.anchor === "middle" && "justify-center",
809
981
  box2.anchor === "bottom" && "justify-end"
810
982
  ),
811
- style: textStyle(box2, empty ? PLACEHOLDER_COLOR : chunkXTR26TNE_cjs.TEXT_COLORS[box2.tone]),
983
+ style: textStyle(box2, empty ? PLACEHOLDER_COLOR : chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone]),
812
984
  onPointerDown: onEdit ? (event) => event.stopPropagation() : void 0,
813
985
  onClick: onEdit,
814
986
  "data-testid": testId,
@@ -857,7 +1029,7 @@ function TextField({
857
1029
  box2.align === "center" && "text-center"
858
1030
  ),
859
1031
  style: {
860
- ...textStyle(box2, chunkXTR26TNE_cjs.TEXT_COLORS[box2.tone]),
1032
+ ...textStyle(box2, chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone]),
861
1033
  fontFamily: "inherit",
862
1034
  // Bulleted lines keep their indent while typed.
863
1035
  paddingLeft: box2.bullets ? "1.22em" : void 0
@@ -891,10 +1063,10 @@ var SlideDecor = react.memo(function SlideDecor2({
891
1063
  dim
892
1064
  }) {
893
1065
  const [typing, setTyping] = react.useState(null);
894
- const geometry = chunkXTR26TNE_cjs.slideGeometry(slide, { labels, logo: theme.logo?.corner ?? null });
1066
+ const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, { labels, logo: theme.logo?.corner ?? null });
895
1067
  const title = slide.caption.trim();
896
1068
  const titled = slide.layout === "title" || slide.layout === "section";
897
- const info = chunkXTR26TNE_cjs.LAYOUT_INFO[slide.layout];
1069
+ const info = chunk4TTX6ZNS_cjs.LAYOUT_INFO[slide.layout];
898
1070
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("pointer-events-none absolute inset-0", dim && "opacity-30"), children: [
899
1071
  !geometry.title ? null : editing && typing === "title" ? /* @__PURE__ */ jsxRuntime.jsx(
900
1072
  TextField,
@@ -912,7 +1084,7 @@ var SlideDecor = react.memo(function SlideDecor2({
912
1084
  {
913
1085
  box: geometry.title,
914
1086
  lines: title ? [title] : [],
915
- accent: chunkXTR26TNE_cjs.accentColor(theme.accent),
1087
+ accent: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
916
1088
  placeholder: editable && (titled || editing) ? "Click to add a title" : void 0,
917
1089
  onEdit: editing ? () => setTyping("title") : void 0,
918
1090
  testId: "stage-slide-caption"
@@ -922,7 +1094,7 @@ var SlideDecor = react.memo(function SlideDecor2({
922
1094
  "div",
923
1095
  {
924
1096
  className: "absolute",
925
- style: { ...boxStyle(geometry.rule), background: chunkXTR26TNE_cjs.accentColor(theme.accent) }
1097
+ style: { ...boxStyle(geometry.rule), background: chunk4TTX6ZNS_cjs.accentColor(theme.accent) }
926
1098
  }
927
1099
  ),
928
1100
  geometry.text && (editing && typing === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -940,8 +1112,8 @@ var SlideDecor = react.memo(function SlideDecor2({
940
1112
  Text,
941
1113
  {
942
1114
  box: geometry.text,
943
- lines: chunkXTR26TNE_cjs.textLines(slide.points),
944
- accent: chunkXTR26TNE_cjs.accentColor(theme.accent),
1115
+ lines: chunk4TTX6ZNS_cjs.textLines(slide.points),
1116
+ accent: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
945
1117
  placeholder: editable ? info.text : void 0,
946
1118
  onEdit: editing ? () => setTyping("text") : void 0,
947
1119
  testId: "stage-slide-points"
@@ -950,137 +1122,6 @@ var SlideDecor = react.memo(function SlideDecor2({
950
1122
  geometry.logo && logoImage && /* @__PURE__ */ jsxRuntime.jsx(Logo, { image: logoImage, box: geometry.logo })
951
1123
  ] });
952
1124
  });
953
- var PAN_STEP = 0.1;
954
- var MAX_ZOOM = 800;
955
- var HOLD_DELAY = 350;
956
- var HOLD_EVERY = 90;
957
- var BUTTON = "pointer-events-auto flex size-7 items-center justify-center rounded-full border border-border bg-background/90 text-foreground shadow-sm backdrop-blur-sm hover:bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-30 pointer-coarse:size-11";
958
- function HoldButton({
959
- label,
960
- disabled,
961
- onStep,
962
- className,
963
- children
964
- }) {
965
- const timer = react.useRef(null);
966
- const stop = () => {
967
- if (timer.current) clearTimeout(timer.current);
968
- timer.current = null;
969
- };
970
- react.useEffect(() => stop, []);
971
- react.useEffect(() => {
972
- if (disabled) stop();
973
- }, [disabled]);
974
- const start = (event) => {
975
- event.stopPropagation();
976
- if (disabled || event.button !== 0) return;
977
- onStep();
978
- const repeat = () => {
979
- onStep();
980
- timer.current = setTimeout(repeat, HOLD_EVERY);
981
- };
982
- timer.current = setTimeout(repeat, HOLD_DELAY);
983
- };
984
- return /* @__PURE__ */ jsxRuntime.jsx(
985
- "button",
986
- {
987
- type: "button",
988
- className: ui.cn(BUTTON, className),
989
- title: label,
990
- "aria-label": label,
991
- disabled,
992
- onPointerDown: start,
993
- onPointerUp: stop,
994
- onPointerLeave: stop,
995
- onPointerCancel: stop,
996
- onClick: (event) => event.detail === 0 && onStep(),
997
- children
998
- }
999
- );
1000
- }
1001
- function ClipViewControls({ clip }) {
1002
- const { panClip, setClipZoom } = chunkXTR26TNE_cjs.usePresentation.getState();
1003
- const { rect } = clip;
1004
- const zoomBase = clip.zoomBase ?? rect.w;
1005
- const minZoom = Math.min(100, Math.floor(zoomBase / Math.min(1, rect.w / rect.h) * 100));
1006
- const pan = (dx, dy) => () => panClip(clip.id, dx * rect.w, dy * rect.h);
1007
- const zoom = Math.round(zoomBase / rect.w * 100);
1008
- const edge = 1e-6;
1009
- return /* @__PURE__ */ jsxRuntime.jsxs(
1010
- "div",
1011
- {
1012
- className: "pointer-events-none absolute inset-0 z-10",
1013
- onPointerDown: (event) => event.stopPropagation(),
1014
- "data-testid": "clip-view-controls",
1015
- children: [
1016
- /* @__PURE__ */ jsxRuntime.jsx(
1017
- HoldButton,
1018
- {
1019
- label: "Show more above",
1020
- disabled: rect.y <= edge,
1021
- onStep: pan(0, -PAN_STEP),
1022
- className: "absolute left-1/2 top-4 -translate-x-1/2 pointer-coarse:top-7",
1023
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "size-4" })
1024
- }
1025
- ),
1026
- /* @__PURE__ */ jsxRuntime.jsx(
1027
- HoldButton,
1028
- {
1029
- label: "Show more below",
1030
- disabled: rect.y + rect.h >= 1 - edge,
1031
- onStep: pan(0, PAN_STEP),
1032
- className: "absolute bottom-10 left-1/2 -translate-x-1/2 pointer-coarse:bottom-14",
1033
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4" })
1034
- }
1035
- ),
1036
- /* @__PURE__ */ jsxRuntime.jsx(
1037
- HoldButton,
1038
- {
1039
- label: "Show more on the left",
1040
- disabled: rect.x <= edge,
1041
- onStep: pan(-PAN_STEP, 0),
1042
- className: "absolute left-4 top-1/2 -translate-y-1/2 pointer-coarse:left-7",
1043
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-4" })
1044
- }
1045
- ),
1046
- /* @__PURE__ */ jsxRuntime.jsx(
1047
- HoldButton,
1048
- {
1049
- label: "Show more on the right",
1050
- disabled: rect.x + rect.w >= 1 - edge,
1051
- onStep: pan(PAN_STEP, 0),
1052
- className: "absolute right-4 top-1/2 -translate-y-1/2 pointer-coarse:right-7",
1053
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-4" })
1054
- }
1055
- ),
1056
- /* @__PURE__ */ jsxRuntime.jsx(
1057
- "div",
1058
- {
1059
- className: "pointer-events-auto absolute bottom-1.5 left-1/2 -translate-x-1/2",
1060
- "data-testid": "clip-zoom-control",
1061
- children: /* @__PURE__ */ jsxRuntime.jsx(
1062
- chunk5GCCUXMT_cjs.ZoomSlider,
1063
- {
1064
- value: zoom,
1065
- min: minZoom,
1066
- max: Math.max(MAX_ZOOM, zoom),
1067
- zoomOutStep: 25,
1068
- onChange: (value) => setClipZoom(clip.id, value),
1069
- label: "Zoom",
1070
- valueLabel: /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-testid": "clip-zoom", children: [
1071
- zoom,
1072
- "%"
1073
- ] }),
1074
- className: "bg-background/95 shadow-sm backdrop-blur-sm pointer-coarse:h-11",
1075
- sliderClassName: "w-24"
1076
- }
1077
- )
1078
- }
1079
- )
1080
- ]
1081
- }
1082
- );
1083
- }
1084
1125
  var isEdge = (kind) => kind === "n" || kind === "e" || kind === "s" || kind === "w";
1085
1126
  var EDGES = [
1086
1127
  { edge: "n", left: "50%", top: "0%", cursor: "ns-resize", label: "top" },
@@ -1094,7 +1135,7 @@ var CORNERS = [
1094
1135
  { corner: "sw", left: "0%", top: "100%", cursor: "nesw-resize" },
1095
1136
  { corner: "se", left: "100%", top: "100%", cursor: "nwse-resize" }
1096
1137
  ];
1097
- var EDGE_CSS = chunkXTR26TNE_cjs.clipEdgeCss();
1138
+ var EDGE_CSS = chunk4TTX6ZNS_cjs.clipEdgeCss();
1098
1139
  var StageItem = react.memo(function StageItem2({
1099
1140
  clip,
1100
1141
  frame,
@@ -1106,7 +1147,6 @@ var StageItem = react.memo(function StageItem2({
1106
1147
  }) {
1107
1148
  const element = react.useRef(null);
1108
1149
  const gesture = react.useRef(null);
1109
- const [dragging, setDragging] = react.useState(false);
1110
1150
  const [reshape, setReshape] = react.useState(null);
1111
1151
  const shown = reshape ? { ...clip, ...reshape.shape } : clip;
1112
1152
  const box2 = reshape?.frame ?? frame;
@@ -1156,7 +1196,6 @@ var StageItem = react.memo(function StageItem2({
1156
1196
  const g = gesture.current;
1157
1197
  if (!g) return;
1158
1198
  if (!g.next) {
1159
- setDragging(true);
1160
1199
  host.dragging(true);
1161
1200
  if (element.current) element.current.style.willChange = "transform";
1162
1201
  }
@@ -1164,14 +1203,14 @@ var StageItem = react.memo(function StageItem2({
1164
1203
  const dy = (event.clientY - g.pointer.y) / g.stage.height;
1165
1204
  const free = event.altKey;
1166
1205
  if (isEdge(g.kind)) {
1167
- const result = chunkXTR26TNE_cjs.reshapeFrame(g.frame, g.shape, g.kind, dx, dy, g.others, free);
1206
+ const result = chunk4TTX6ZNS_cjs.reshapeFrame(g.frame, g.shape, g.kind, dx, dy, g.others, free);
1168
1207
  g.next = {
1169
1208
  frame: result.frame,
1170
1209
  shape: { rect: result.rect, aspect: result.aspect },
1171
1210
  guides: result.guides
1172
1211
  };
1173
1212
  } else {
1174
- g.next = g.kind === "move" ? chunkXTR26TNE_cjs.moveFrame(g.frame, g.shape.aspect, dx, dy, g.others, free) : chunkXTR26TNE_cjs.resizeFrame(g.frame, g.shape.aspect, g.kind, dx, dy, g.others, free);
1213
+ g.next = g.kind === "move" ? chunk4TTX6ZNS_cjs.moveFrame(g.frame, g.shape.aspect, dx, dy, g.others, free) : chunk4TTX6ZNS_cjs.resizeFrame(g.frame, g.shape.aspect, g.kind, dx, dy, g.others, free);
1175
1214
  }
1176
1215
  g.request ??= view().requestAnimationFrame(apply);
1177
1216
  };
@@ -1187,7 +1226,6 @@ var StageItem = react.memo(function StageItem2({
1187
1226
  }
1188
1227
  if (!g.next) return;
1189
1228
  setReshape(null);
1190
- setDragging(false);
1191
1229
  host.dragging(false);
1192
1230
  host.guides([]);
1193
1231
  host.commit(clip.id, g.next.frame, g.next.shape);
@@ -1208,7 +1246,7 @@ var StageItem = react.memo(function StageItem2({
1208
1246
  left: `${box2.x * 100}%`,
1209
1247
  top: `${box2.y * 100}%`,
1210
1248
  width: `${box2.w * 100}%`,
1211
- height: `${chunkXTR26TNE_cjs.frameHeight(box2, shown.aspect) * 100}%`
1249
+ height: `${chunk4TTX6ZNS_cjs.frameHeight(box2, shown.aspect) * 100}%`
1212
1250
  },
1213
1251
  onPointerDown: (event) => start(event, "move"),
1214
1252
  onPointerMove: move,
@@ -1233,11 +1271,10 @@ var StageItem = react.memo(function StageItem2({
1233
1271
  "div",
1234
1272
  {
1235
1273
  className: "pointer-events-none absolute left-0 top-full mt-[0.5cqw] max-w-full truncate text-[1.7cqw] leading-tight",
1236
- style: { color: chunkXTR26TNE_cjs.TEXT_COLORS.muted },
1274
+ style: { color: chunk4TTX6ZNS_cjs.TEXT_COLORS.muted },
1237
1275
  children: label
1238
1276
  }
1239
1277
  ),
1240
- selected && !dragging && /* @__PURE__ */ jsxRuntime.jsx(ClipViewControls, { clip }),
1241
1278
  selected && CORNERS.map(({ corner, left, top, cursor }) => /* @__PURE__ */ jsxRuntime.jsx(
1242
1279
  "div",
1243
1280
  {
@@ -1277,14 +1314,14 @@ var StageItem = react.memo(function StageItem2({
1277
1314
  });
1278
1315
 
1279
1316
  // src/presentation/box-style.ts
1280
- var cqw = (points) => `${chunkXTR26TNE_cjs.pointsToStage(points) * 100}cqw`;
1317
+ var cqw = (points) => `${chunk4TTX6ZNS_cjs.pointsToStage(points) * 100}cqw`;
1281
1318
  function runStyle(run, font) {
1282
1319
  return {
1283
- fontSize: cqw(run.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE),
1320
+ fontSize: cqw(run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE),
1284
1321
  fontWeight: run.bold ? 700 : 400,
1285
1322
  fontStyle: run.italic ? "italic" : void 0,
1286
1323
  textDecoration: run.underline ? "underline" : void 0,
1287
- color: run.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body,
1324
+ color: run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1288
1325
  fontFamily: run.font ? `"${run.font}", ${font}` : font
1289
1326
  };
1290
1327
  }
@@ -1306,7 +1343,7 @@ var withAlpha = (hex3, alpha = 1) => {
1306
1343
  function shapeStyle(box2) {
1307
1344
  const { frame } = box2;
1308
1345
  const line = box2.line;
1309
- const shorter = Math.min(frame.w, frame.h * 1 / chunkXTR26TNE_cjs.STAGE_ASPECT);
1346
+ const shorter = Math.min(frame.w, frame.h * 1 / chunk4TTX6ZNS_cjs.STAGE_ASPECT);
1310
1347
  return {
1311
1348
  background: box2.fill && box2.shape !== "line" ? withAlpha(box2.fill, box2.fillAlpha) : void 0,
1312
1349
  border: line && box2.shape !== "line" ? `${cqw(line.width)} ${line.dash ? "dashed" : "solid"} ${line.color}` : void 0,
@@ -1319,7 +1356,7 @@ function Paragraphs({
1319
1356
  }) {
1320
1357
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: paragraphs.map((paragraph, index) => {
1321
1358
  const first = paragraph.runs[0];
1322
- const size = first?.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE;
1359
+ const size = first?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE;
1323
1360
  const indent = (paragraph.level ?? 0) * 0.5 * size;
1324
1361
  const empty = !paragraph.runs.some((run) => run.text);
1325
1362
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1406,7 +1443,7 @@ var StageBox = react.memo(function StageBox2({
1406
1443
  const dx = (event.clientX - g.pointer.x) / g.stage.width;
1407
1444
  const dy = (event.clientY - g.pointer.y) / g.stage.height;
1408
1445
  if (!g.next) setDragging(true);
1409
- g.next = g.handle === "move" ? chunkXTR26TNE_cjs.moveBox(g.frame, dx, dy) : chunkXTR26TNE_cjs.stretchBox(g.frame, g.handle, dx, dy);
1446
+ g.next = g.handle === "move" ? chunk4TTX6ZNS_cjs.moveBox(g.frame, dx, dy) : chunk4TTX6ZNS_cjs.stretchBox(g.frame, g.handle, dx, dy);
1410
1447
  g.request ??= view().requestAnimationFrame(apply);
1411
1448
  };
1412
1449
  const end = () => {
@@ -1430,8 +1467,8 @@ var StageBox = react.memo(function StageBox2({
1430
1467
  host.commit(box2.id, g.next);
1431
1468
  };
1432
1469
  const hasText = box2.shape !== "line";
1433
- const inset = cqw(box2.inset ?? chunkXTR26TNE_cjs.DEFAULT_INSET);
1434
- const run = chunkXTR26TNE_cjs.firstRun(box2);
1470
+ const inset = cqw(box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET);
1471
+ const run = chunk4TTX6ZNS_cjs.firstRun(box2);
1435
1472
  const transform = box2.rotation ? `rotate(${box2.rotation}deg)` : void 0;
1436
1473
  return /* @__PURE__ */ jsxRuntime.jsxs(
1437
1474
  "div",
@@ -1479,7 +1516,7 @@ var StageBox = react.memo(function StageBox2({
1479
1516
  y1: box2.flipV ? "100%" : "0%",
1480
1517
  x2: "100%",
1481
1518
  y2: box2.flipV ? "0%" : "100%",
1482
- stroke: box2.line?.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body,
1519
+ stroke: box2.line?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1483
1520
  style: { strokeWidth: cqw(box2.line?.width ?? 1) },
1484
1521
  strokeDasharray: box2.line?.dash ? "6 4" : void 0
1485
1522
  }
@@ -1498,7 +1535,7 @@ var StageBox = react.memo(function StageBox2({
1498
1535
  "textarea",
1499
1536
  {
1500
1537
  autoFocus: true,
1501
- defaultValue: chunkXTR26TNE_cjs.boxText(box2),
1538
+ defaultValue: chunk4TTX6ZNS_cjs.boxText(box2),
1502
1539
  className: "pointer-events-auto w-full flex-1 resize-none bg-transparent p-0 outline-none",
1503
1540
  style: {
1504
1541
  ...runStyle(run ?? { }, font),
@@ -1517,11 +1554,11 @@ var StageBox = react.memo(function StageBox2({
1517
1554
  "aria-label": "Text",
1518
1555
  "data-testid": "stage-box-text-input"
1519
1556
  }
1520
- ) : chunkXTR26TNE_cjs.boxText(box2) || !editable ? /* @__PURE__ */ jsxRuntime.jsx(Paragraphs, { paragraphs: box2.paragraphs, font }) : box2.shape === "text" && /* @__PURE__ */ jsxRuntime.jsx(
1557
+ ) : chunk4TTX6ZNS_cjs.boxText(box2) || !editable ? /* @__PURE__ */ jsxRuntime.jsx(Paragraphs, { paragraphs: box2.paragraphs, font }) : box2.shape === "text" && /* @__PURE__ */ jsxRuntime.jsx(
1521
1558
  "span",
1522
1559
  {
1523
1560
  className: "text-white/40",
1524
- style: { fontSize: cqw(run?.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE) },
1561
+ style: { fontSize: cqw(run?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) },
1525
1562
  children: "Double-click to type"
1526
1563
  }
1527
1564
  )
@@ -1547,12 +1584,6 @@ var StageBox = react.memo(function StageBox2({
1547
1584
  });
1548
1585
  var SIZE_STEPS = [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 44, 54, 66, 80, 96];
1549
1586
  var nextSize = (size, up) => up ? SIZE_STEPS.find((step) => step > size + 0.5) ?? size : [...SIZE_STEPS].reverse().find((step) => step < size - 0.5) ?? size;
1550
- var ALIGN_NEXT = {
1551
- left: "center",
1552
- center: "right",
1553
- right: "left",
1554
- justify: "left"
1555
- };
1556
1587
  var ALIGN_ICON = {
1557
1588
  left: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { className: "size-4" }),
1558
1589
  center: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenter, { className: "size-4" }),
@@ -1587,9 +1618,9 @@ function ColorAction({
1587
1618
  ] });
1588
1619
  }
1589
1620
  function BoxActionBar({ box: box2, onRemoved }) {
1590
- const actions = chunkXTR26TNE_cjs.usePresentation.getState();
1591
- const run = chunkXTR26TNE_cjs.firstRun(box2);
1592
- const size = run?.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE;
1621
+ const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
1622
+ const run = chunk4TTX6ZNS_cjs.firstRun(box2);
1623
+ const size = run?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE;
1593
1624
  const align = box2.paragraphs[0]?.align ?? "left";
1594
1625
  const update = (change) => actions.updateBox(box2.id, change);
1595
1626
  const text = box2.shape !== "line";
@@ -1612,7 +1643,7 @@ function BoxActionBar({ box: box2, onRemoved }) {
1612
1643
  Action,
1613
1644
  {
1614
1645
  label: "Smaller",
1615
- onClick: () => update((b) => chunkXTR26TNE_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, false) }))),
1646
+ onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, false) }))),
1616
1647
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AArrowDown, { className: "size-4" })
1617
1648
  }
1618
1649
  ),
@@ -1628,7 +1659,7 @@ function BoxActionBar({ box: box2, onRemoved }) {
1628
1659
  Action,
1629
1660
  {
1630
1661
  label: "Larger",
1631
- onClick: () => update((b) => chunkXTR26TNE_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, true) }))),
1662
+ onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, true) }))),
1632
1663
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AArrowUp, { className: "size-4" })
1633
1664
  }
1634
1665
  ),
@@ -1636,35 +1667,16 @@ function BoxActionBar({ box: box2, onRemoved }) {
1636
1667
  Action,
1637
1668
  {
1638
1669
  label: "Bold",
1639
- onClick: () => update((b) => chunkXTR26TNE_cjs.styleRuns(b, (r) => ({ ...r, bold: !run?.bold }))),
1670
+ onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, bold: !run?.bold }))),
1640
1671
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { className: ui.cn("size-4", run?.bold && "text-primary") })
1641
1672
  }
1642
1673
  ),
1643
- /* @__PURE__ */ jsxRuntime.jsx(
1644
- Action,
1645
- {
1646
- label: "Italic",
1647
- onClick: () => update((b) => chunkXTR26TNE_cjs.styleRuns(b, (r) => ({ ...r, italic: !run?.italic }))),
1648
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { className: ui.cn("size-4", run?.italic && "text-primary") })
1649
- }
1650
- ),
1651
- /* @__PURE__ */ jsxRuntime.jsx(
1652
- Action,
1653
- {
1654
- label: "Align",
1655
- onClick: () => update((b) => ({
1656
- ...b,
1657
- paragraphs: b.paragraphs.map((p) => ({ ...p, align: ALIGN_NEXT[align] }))
1658
- })),
1659
- children: ALIGN_ICON[align]
1660
- }
1661
- ),
1662
1674
  /* @__PURE__ */ jsxRuntime.jsx(
1663
1675
  ColorAction,
1664
1676
  {
1665
1677
  label: "Text colour",
1666
- value: run?.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body,
1667
- onChange: (color) => update((b) => chunkXTR26TNE_cjs.styleRuns(b, (r) => ({ ...r, color }))),
1678
+ value: run?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1679
+ onChange: (color) => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, color }))),
1668
1680
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Baseline, { className: "size-4" })
1669
1681
  }
1670
1682
  )
@@ -1680,10 +1692,58 @@ function BoxActionBar({ box: box2, onRemoved }) {
1680
1692
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaintBucket, { className: "size-4" })
1681
1693
  }
1682
1694
  ),
1683
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-0.5 h-5 w-px bg-border" }),
1684
- /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "In front of the clips", onClick: () => actions.restackBox(box2.id, "front"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BringToFront, { className: "size-4" }) }),
1685
- /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Behind the clips", onClick: () => actions.restackBox(box2.id, "back"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendToBack, { className: "size-4" }) }),
1686
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-0.5 h-5 w-px bg-border" }),
1695
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
1696
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
1697
+ "button",
1698
+ {
1699
+ type: "button",
1700
+ className: ACTION,
1701
+ title: "More",
1702
+ "aria-label": "More",
1703
+ "data-testid": "box-more-menu",
1704
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "size-4" })
1705
+ }
1706
+ ) }),
1707
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuContent, { align: "start", children: [
1708
+ text && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1709
+ /* @__PURE__ */ jsxRuntime.jsxs(
1710
+ ui.DropdownMenuCheckboxItem,
1711
+ {
1712
+ checked: !!run?.italic,
1713
+ onCheckedChange: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, italic: !run?.italic }))),
1714
+ children: [
1715
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { className: "size-4" }),
1716
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Italic" })
1717
+ ]
1718
+ }
1719
+ ),
1720
+ ["left", "center", "right"].map((value) => /* @__PURE__ */ jsxRuntime.jsxs(
1721
+ ui.DropdownMenuCheckboxItem,
1722
+ {
1723
+ checked: align === value,
1724
+ onCheckedChange: () => update((b) => ({
1725
+ ...b,
1726
+ paragraphs: b.paragraphs.map((p) => ({ ...p, align: value }))
1727
+ })),
1728
+ children: [
1729
+ ALIGN_ICON[value],
1730
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: value === "left" ? "Align left" : value === "center" ? "Centre" : "Align right" })
1731
+ ]
1732
+ },
1733
+ value
1734
+ )),
1735
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuSeparator, {})
1736
+ ] }),
1737
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.restackBox(box2.id, "front"), children: [
1738
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BringToFront, { className: "size-4" }),
1739
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "In front of the clips" })
1740
+ ] }),
1741
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.restackBox(box2.id, "back"), children: [
1742
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendToBack, { className: "size-4" }),
1743
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Behind the clips" })
1744
+ ] })
1745
+ ] })
1746
+ ] }),
1687
1747
  /* @__PURE__ */ jsxRuntime.jsx(
1688
1748
  "button",
1689
1749
  {
@@ -1728,18 +1788,18 @@ function PresentationStage({
1728
1788
  overlay,
1729
1789
  className
1730
1790
  }) {
1731
- const index = chunkXTR26TNE_cjs.usePresentation((s) => slideIndex ?? s.current);
1732
- const slide = chunkXTR26TNE_cjs.usePresentation((s) => s.slides[index]);
1733
- const clips = chunkXTR26TNE_cjs.usePresentation((s) => s.clips);
1734
- const blank = chunkXTR26TNE_cjs.usePresentation((s) => s.blank && !editable);
1735
- const captions = chunkXTR26TNE_cjs.usePresentation((s) => s.captions);
1736
- const columnValues = chunkXTR26TNE_cjs.usePresentation((s) => s.columnValues);
1737
- const theme = chunkXTR26TNE_cjs.usePresentation((s) => s.theme);
1738
- const logoImage = chunkXTR26TNE_cjs.usePresentation((s) => s.logoImage);
1739
- const media = chunkXTR26TNE_cjs.usePresentation((s) => s.media);
1791
+ const index = chunk4TTX6ZNS_cjs.usePresentation((s) => slideIndex ?? s.current);
1792
+ const slide = chunk4TTX6ZNS_cjs.usePresentation((s) => s.slides[index]);
1793
+ const clips = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips);
1794
+ const blank = chunk4TTX6ZNS_cjs.usePresentation((s) => s.blank && !editable);
1795
+ const captions = chunk4TTX6ZNS_cjs.usePresentation((s) => s.captions);
1796
+ const columnValues = chunk4TTX6ZNS_cjs.usePresentation((s) => s.columnValues);
1797
+ const theme = chunk4TTX6ZNS_cjs.usePresentation((s) => s.theme);
1798
+ const logoImage = chunk4TTX6ZNS_cjs.usePresentation((s) => s.logoImage);
1799
+ const media = chunk4TTX6ZNS_cjs.usePresentation((s) => s.media);
1740
1800
  const stageRef = react.useRef(null);
1741
1801
  const guideLayer = react.useRef(null);
1742
- const dropping = chunkXTR26TNE_cjs.usePresentation((s) => editable && s.dragging !== null);
1802
+ const dropping = chunk4TTX6ZNS_cjs.usePresentation((s) => editable && s.dragging !== null);
1743
1803
  const [dragging, setDragging] = react.useState(false);
1744
1804
  const latest = react.useRef({ slide, clips, index, onSelect });
1745
1805
  latest.current = { slide, clips, index, onSelect };
@@ -1754,13 +1814,13 @@ function PresentationStage({
1754
1814
  }));
1755
1815
  },
1756
1816
  select: (clipId) => {
1757
- chunkXTR26TNE_cjs.usePresentation.getState().goTo(latest.current.index);
1817
+ chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(latest.current.index);
1758
1818
  latest.current.onSelect?.(clipId);
1759
1819
  },
1760
1820
  guides: (guides) => guideLayer.current?.set(guides),
1761
1821
  dragging: setDragging,
1762
1822
  commit: (clipId, frame, shape) => {
1763
- const state = chunkXTR26TNE_cjs.usePresentation.getState();
1823
+ const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
1764
1824
  state.goTo(latest.current.index);
1765
1825
  if (shape) state.reshapeClip(clipId, frame, shape.rect, shape.aspect);
1766
1826
  else state.setFrame(clipId, frame);
@@ -1772,15 +1832,15 @@ function PresentationStage({
1772
1832
  () => ({
1773
1833
  stageBox: () => stageRef.current?.getBoundingClientRect() ?? null,
1774
1834
  select: (boxId) => {
1775
- chunkXTR26TNE_cjs.usePresentation.getState().goTo(latest.current.index);
1835
+ chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(latest.current.index);
1776
1836
  latest.current.onSelect?.(boxId);
1777
1837
  },
1778
- commit: (boxId, frame) => chunkXTR26TNE_cjs.usePresentation.getState().updateBox(boxId, (box2) => ({ ...box2, frame })),
1779
- setText: (boxId, text) => chunkXTR26TNE_cjs.usePresentation.getState().setBoxText(boxId, text)
1838
+ commit: (boxId, frame) => chunk4TTX6ZNS_cjs.usePresentation.getState().updateBox(boxId, (box2) => ({ ...box2, frame })),
1839
+ setText: (boxId, text) => chunk4TTX6ZNS_cjs.usePresentation.getState().setBoxText(boxId, text)
1780
1840
  }),
1781
1841
  []
1782
1842
  );
1783
- const font = chunkXTR26TNE_cjs.FONTS[theme.font].css;
1843
+ const font = chunk4TTX6ZNS_cjs.FONTS[theme.font].css;
1784
1844
  const boxes = slide?.boxes ?? [];
1785
1845
  const selectedBox = selected ? boxes.find((box2) => box2.id === selected) : void 0;
1786
1846
  const renderBoxes = (front) => boxes.filter((box2) => !!box2.front === front).map((box2) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -1806,7 +1866,7 @@ function PresentationStage({
1806
1866
  const item = event.target?.closest?.(
1807
1867
  `[data-testid="stage-item-${selected}"]`
1808
1868
  );
1809
- const clip = chunkXTR26TNE_cjs.usePresentation.getState().clips.find((entry) => entry.id === selected);
1869
+ const clip = chunk4TTX6ZNS_cjs.usePresentation.getState().clips.find((entry) => entry.id === selected);
1810
1870
  if (!item || !clip) return;
1811
1871
  event.preventDefault();
1812
1872
  const box2 = item.getBoundingClientRect();
@@ -1819,7 +1879,7 @@ function PresentationStage({
1819
1879
  };
1820
1880
  request ??= view.requestAnimationFrame(() => {
1821
1881
  request = null;
1822
- chunkXTR26TNE_cjs.usePresentation.getState().panClip(selected, sum.x, sum.y);
1882
+ chunk4TTX6ZNS_cjs.usePresentation.getState().panClip(selected, sum.x, sum.y);
1823
1883
  sum = { x: 0, y: 0 };
1824
1884
  });
1825
1885
  };
@@ -1848,12 +1908,12 @@ function PresentationStage({
1848
1908
  width: "min(100cqw, calc(100cqh * 16 / 9))",
1849
1909
  height: "min(100cqh, calc(100cqw * 9 / 16))",
1850
1910
  containerType: "inline-size",
1851
- background: slide?.background ? chunkXTR26TNE_cjs.slideBackgroundCss(slide.background, media) : chunkXTR26TNE_cjs.backgroundCss(theme.background),
1852
- fontFamily: chunkXTR26TNE_cjs.FONTS[theme.font].css
1911
+ background: slide?.background ? chunk4TTX6ZNS_cjs.slideBackgroundCss(slide.background, media) : chunk4TTX6ZNS_cjs.backgroundCss(theme.background),
1912
+ fontFamily: chunk4TTX6ZNS_cjs.FONTS[theme.font].css
1853
1913
  },
1854
1914
  onPointerDown: () => {
1855
1915
  if (!editable) return;
1856
- chunkXTR26TNE_cjs.usePresentation.getState().goTo(index);
1916
+ chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(index);
1857
1917
  onSelect?.(null);
1858
1918
  },
1859
1919
  ...editable ? { [DROP_ATTRIBUTE]: "stage", "data-slide-index": index } : {},
@@ -1883,7 +1943,7 @@ function PresentationStage({
1883
1943
  editable,
1884
1944
  selected: editable && selected === clip.id,
1885
1945
  dim: false,
1886
- label: captions ? chunkXTR26TNE_cjs.clipLabel(clip, columnValues) : "",
1946
+ label: captions ? chunk4TTX6ZNS_cjs.clipLabel(clip, columnValues) : "",
1887
1947
  host
1888
1948
  },
1889
1949
  clip.id
@@ -1909,27 +1969,6 @@ function PresentationStage({
1909
1969
  }
1910
1970
  );
1911
1971
  }
1912
- function SlideAction({
1913
- label,
1914
- onClick,
1915
- disabled,
1916
- children
1917
- }) {
1918
- return /* @__PURE__ */ jsxRuntime.jsx(
1919
- ui.Button,
1920
- {
1921
- type: "button",
1922
- size: "icon",
1923
- variant: "ghost",
1924
- className: "size-7 text-muted-foreground hover:text-foreground pointer-coarse:size-10",
1925
- title: label,
1926
- "aria-label": label,
1927
- disabled,
1928
- onClick,
1929
- children
1930
- }
1931
- );
1932
- }
1933
1972
  var SlideCard = react.memo(function SlideCard2({
1934
1973
  index,
1935
1974
  count,
@@ -1939,20 +1978,20 @@ var SlideCard = react.memo(function SlideCard2({
1939
1978
  onEditImage,
1940
1979
  onCropImage
1941
1980
  }) {
1942
- const empty = chunkXTR26TNE_cjs.usePresentation((s) => {
1981
+ const empty = chunk4TTX6ZNS_cjs.usePresentation((s) => {
1943
1982
  const slide = s.slides[index];
1944
- return !!slide && !slide.items.length && !slide.boxes.length && slide.layout !== "title" && slide.layout !== "section";
1983
+ return !!slide && !slide.items.length && !slide.boxes.length && !slide.points.trim() && slide.layout !== "title" && slide.layout !== "section";
1945
1984
  });
1946
- const notes = chunkXTR26TNE_cjs.usePresentation((s) => s.slides[index]?.notes ?? "");
1985
+ const notes = chunk4TTX6ZNS_cjs.usePresentation((s) => s.slides[index]?.notes ?? "");
1947
1986
  const textEditing = react.useMemo(
1948
1987
  () => ({
1949
- onTitle: (title) => chunkXTR26TNE_cjs.usePresentation.getState().setSlideCaption(title, index),
1950
- onPoints: (points) => chunkXTR26TNE_cjs.usePresentation.getState().setSlidePoints(points, index)
1988
+ onTitle: (title) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlideCaption(title, index),
1989
+ onPoints: (points) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlidePoints(points, index)
1951
1990
  }),
1952
1991
  [index]
1953
1992
  );
1954
1993
  const select = react.useCallback((clipId) => onSelect(index, clipId), [onSelect, index]);
1955
- const actions = chunkXTR26TNE_cjs.usePresentation.getState();
1994
+ const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
1956
1995
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative flex gap-2", "data-testid": `slide-${index}`, children: [
1957
1996
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-9 shrink-0 flex-col items-center gap-0.5", children: [
1958
1997
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1976,26 +2015,61 @@ var SlideCard = react.memo(function SlideCard2({
1976
2015
  "data-testid": `slide-actions-${index}`,
1977
2016
  children: [
1978
2017
  /* @__PURE__ */ jsxRuntime.jsx(LayoutMenu, { index, compact: true }),
1979
- /* @__PURE__ */ jsxRuntime.jsx(
1980
- SlideAction,
1981
- {
1982
- label: "Move up",
1983
- disabled: index === 0,
1984
- onClick: () => actions.moveSlide(index, index - 1),
1985
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "size-3.5" })
1986
- }
1987
- ),
1988
- /* @__PURE__ */ jsxRuntime.jsx(
1989
- SlideAction,
1990
- {
1991
- label: "Move down",
1992
- disabled: index === count - 1,
1993
- onClick: () => actions.moveSlide(index, index + 1),
1994
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "size-3.5" })
1995
- }
1996
- ),
1997
- /* @__PURE__ */ jsxRuntime.jsx(SlideAction, { label: "Duplicate", onClick: () => actions.duplicateSlide(index), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "size-3.5" }) }),
1998
- /* @__PURE__ */ jsxRuntime.jsx(SlideAction, { label: "Delete slide", onClick: () => actions.removeSlide(index), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-3.5" }) })
2018
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
2019
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2020
+ ui.Button,
2021
+ {
2022
+ type: "button",
2023
+ size: "icon",
2024
+ variant: "ghost",
2025
+ className: "size-7 text-muted-foreground hover:text-foreground pointer-coarse:size-11",
2026
+ title: "Slide actions",
2027
+ "aria-label": `Slide ${index + 1} actions`,
2028
+ "data-testid": `slide-menu-${index}`,
2029
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "size-3.5" })
2030
+ }
2031
+ ) }),
2032
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuContent, { align: "start", children: [
2033
+ /* @__PURE__ */ jsxRuntime.jsxs(
2034
+ ui.DropdownMenuItem,
2035
+ {
2036
+ disabled: index === 0,
2037
+ onSelect: () => actions.moveSlide(index, index - 1),
2038
+ children: [
2039
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "size-4" }),
2040
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Move up" })
2041
+ ]
2042
+ }
2043
+ ),
2044
+ /* @__PURE__ */ jsxRuntime.jsxs(
2045
+ ui.DropdownMenuItem,
2046
+ {
2047
+ disabled: index === count - 1,
2048
+ onSelect: () => actions.moveSlide(index, index + 1),
2049
+ children: [
2050
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "size-4" }),
2051
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Move down" })
2052
+ ]
2053
+ }
2054
+ ),
2055
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuItem, { onSelect: () => actions.duplicateSlide(index), children: [
2056
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "size-4" }),
2057
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Duplicate" })
2058
+ ] }),
2059
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuSeparator, {}),
2060
+ /* @__PURE__ */ jsxRuntime.jsxs(
2061
+ ui.DropdownMenuItem,
2062
+ {
2063
+ className: "text-destructive",
2064
+ onSelect: () => actions.removeSlide(index),
2065
+ children: [
2066
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-4" }),
2067
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: "Delete slide" })
2068
+ ]
2069
+ }
2070
+ )
2071
+ ] })
2072
+ ] })
1999
2073
  ]
2000
2074
  }
2001
2075
  )
@@ -2027,7 +2101,7 @@ var SlideCard = react.memo(function SlideCard2({
2027
2101
  value: notes,
2028
2102
  rows: notes.split("\n").length,
2029
2103
  placeholder: "Speaker notes",
2030
- onChange: (event) => chunkXTR26TNE_cjs.usePresentation.getState().setSlideNotes(event.target.value, index),
2104
+ onChange: (event) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlideNotes(event.target.value, index),
2031
2105
  className: "mt-2 block w-full resize-none rounded-sm border-0 bg-transparent px-1 py-0.5 text-xs text-muted-foreground placeholder:text-muted-foreground/50 focus:bg-background focus:text-foreground focus:outline-none focus:ring-1 focus:ring-ring",
2032
2106
  "aria-label": `Speaker notes for slide ${index + 1}`,
2033
2107
  "data-testid": `slide-notes-${index}`
@@ -2051,10 +2125,10 @@ var INSERTS = [
2051
2125
  ];
2052
2126
  function InsertMenu({ onInserted }) {
2053
2127
  const insert = (shape) => {
2054
- const state = chunkXTR26TNE_cjs.usePresentation.getState();
2128
+ const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
2055
2129
  const slide = state.slides[state.current];
2056
- const box2 = chunkXTR26TNE_cjs.newBox(shape, chunkXTR26TNE_cjs.accentColor(state.theme.accent));
2057
- const dark = chunkXTR26TNE_cjs.isLightBackground(slide?.background);
2130
+ const box2 = chunk4TTX6ZNS_cjs.newBox(shape, chunk4TTX6ZNS_cjs.accentColor(state.theme.accent));
2131
+ const dark = chunk4TTX6ZNS_cjs.isLightBackground(slide?.background);
2058
2132
  const { id, ...rest } = dark ? {
2059
2133
  ...box2,
2060
2134
  paragraphs: box2.paragraphs.map((p) => ({
@@ -2097,7 +2171,7 @@ function InsertSlide({ after, always }) {
2097
2171
  "button",
2098
2172
  {
2099
2173
  type: "button",
2100
- onClick: () => chunkXTR26TNE_cjs.usePresentation.getState().addSlide(void 0, after),
2174
+ onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().addSlide(void 0, after),
2101
2175
  className: ui.cn(
2102
2176
  "flex items-center gap-1 rounded-full border border-dashed border-border bg-background px-2.5 py-0.5 text-xs text-muted-foreground transition-opacity hover:border-solid hover:text-foreground focus-visible:opacity-100",
2103
2177
  !always && "opacity-0 group-hover/insert:opacity-100 pointer-coarse:opacity-100"
@@ -2120,10 +2194,11 @@ function SlidesEditor({
2120
2194
  onEditImage,
2121
2195
  onCropImage
2122
2196
  }) {
2123
- const ids = chunkXTR26TNE_cjs.usePresentation((s) => s.slides.map((slide) => slide.id).join(" "));
2197
+ const ids = chunk4TTX6ZNS_cjs.usePresentation((s) => s.slides.map((slide) => slide.id).join(" "));
2124
2198
  const slideIds = react.useMemo(() => ids.split(" "), [ids]);
2125
- const current2 = chunkXTR26TNE_cjs.usePresentation((s) => s.current);
2126
- const captions = chunkXTR26TNE_cjs.usePresentation((s) => s.captions);
2199
+ const current2 = chunk4TTX6ZNS_cjs.usePresentation((s) => s.current);
2200
+ const captions = chunk4TTX6ZNS_cjs.usePresentation((s) => s.captions);
2201
+ const presenting = chunk4TTX6ZNS_cjs.usePresentation((s) => s.presenting);
2127
2202
  const [selection, setSelection] = react.useState(null);
2128
2203
  const [view, setView] = react.useState(null);
2129
2204
  const list = react.useRef(null);
@@ -2137,7 +2212,7 @@ function SlidesEditor({
2137
2212
  () => ({ clipId: selection?.clipId ?? null, clear: () => setSelection(null) }),
2138
2213
  [selection]
2139
2214
  );
2140
- chunk5LTIZ44D_cjs.usePresenterKeys(view, false, keySelection);
2215
+ chunkWFMWKPGY_cjs.usePresenterKeys(view, false, keySelection);
2141
2216
  react.useEffect(() => {
2142
2217
  const card = list.current?.querySelector(`[data-testid="slide-${current2}"]`);
2143
2218
  card?.scrollIntoView?.({ block: "nearest", behavior: "smooth" });
@@ -2193,13 +2268,28 @@ function SlidesEditor({
2193
2268
  ui.DropdownMenuCheckboxItem,
2194
2269
  {
2195
2270
  checked: captions,
2196
- onCheckedChange: (on) => chunkXTR26TNE_cjs.usePresentation.getState().setCaptions(!!on),
2271
+ onCheckedChange: (on) => chunk4TTX6ZNS_cjs.usePresentation.getState().setCaptions(!!on),
2197
2272
  children: "Show source labels"
2198
2273
  }
2199
2274
  )
2200
2275
  ] })
2201
2276
  ] }),
2202
- /* @__PURE__ */ jsxRuntime.jsxs(
2277
+ presenting ? /* @__PURE__ */ jsxRuntime.jsxs(
2278
+ ui.Button,
2279
+ {
2280
+ type: "button",
2281
+ size: "sm",
2282
+ variant: "destructive",
2283
+ className: "ml-0.5 h-8 rounded-full",
2284
+ onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().setPresenting(false),
2285
+ title: "Stop presenting (the presentation window closes)",
2286
+ "data-testid": "presentation-stop-button",
2287
+ children: [
2288
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "size-3 fill-current" }),
2289
+ "Stop presenting"
2290
+ ]
2291
+ }
2292
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
2203
2293
  ui.Button,
2204
2294
  {
2205
2295
  type: "button",
@@ -2230,7 +2320,7 @@ function SlidesEditor({
2230
2320
  // src/presentation/draw-boxes.ts
2231
2321
  var LINE_HEIGHT = 1.2;
2232
2322
  function fontOf(run, themeFont, width) {
2233
- const size = chunkXTR26TNE_cjs.pointsToStage(run.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE) * width;
2323
+ const size = chunk4TTX6ZNS_cjs.pointsToStage(run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) * width;
2234
2324
  const family = run.font ? `"${run.font}", ${themeFont}` : themeFont;
2235
2325
  return `${run.italic ? "italic " : ""}${run.bold ? 700 : 400} ${size}px ${family}`;
2236
2326
  }
@@ -2248,9 +2338,9 @@ function drawBox(context, box2, width, height, themeFont) {
2248
2338
  context.translate(frame.x * width + w / 2, frame.y * height + h / 2);
2249
2339
  if (box2.rotation) context.rotate(box2.rotation * Math.PI / 180);
2250
2340
  context.translate(-w / 2, -h / 2);
2251
- const lineWidth = box2.line ? Math.max(1, chunkXTR26TNE_cjs.pointsToStage(box2.line.width) * width) : 0;
2341
+ const lineWidth = box2.line ? Math.max(1, chunk4TTX6ZNS_cjs.pointsToStage(box2.line.width) * width) : 0;
2252
2342
  if (box2.shape === "line") {
2253
- context.strokeStyle = box2.line?.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body;
2343
+ context.strokeStyle = box2.line?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
2254
2344
  context.lineWidth = lineWidth || 1;
2255
2345
  if (box2.line?.dash) context.setLineDash([lineWidth * 3, lineWidth * 2]);
2256
2346
  context.beginPath();
@@ -2275,12 +2365,12 @@ function drawBox(context, box2, width, height, themeFont) {
2275
2365
  context.stroke();
2276
2366
  context.setLineDash([]);
2277
2367
  }
2278
- const inset = chunkXTR26TNE_cjs.pointsToStage(box2.inset ?? chunkXTR26TNE_cjs.DEFAULT_INSET) * width;
2368
+ const inset = chunk4TTX6ZNS_cjs.pointsToStage(box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET) * width;
2279
2369
  const room = w - 2 * inset;
2280
2370
  context.textBaseline = "alphabetic";
2281
2371
  const lines = [];
2282
2372
  for (const paragraph of box2.paragraphs) {
2283
- const size = chunkXTR26TNE_cjs.pointsToStage(paragraph.runs[0]?.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE) * width;
2373
+ const size = chunk4TTX6ZNS_cjs.pointsToStage(paragraph.runs[0]?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) * width;
2284
2374
  const indent = (paragraph.level ?? 0) * 0.5 * size + (paragraph.bullet ? size * 0.9 : 0);
2285
2375
  const words = [];
2286
2376
  for (const run of paragraph.runs) {
@@ -2326,12 +2416,12 @@ function drawBox(context, box2, width, height, themeFont) {
2326
2416
  const baseline = y + line.size * (LINE_HEIGHT - 0.2);
2327
2417
  if (line.bullet) {
2328
2418
  context.font = fontOf(line.bullet, themeFont, width);
2329
- context.fillStyle = line.bullet.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body;
2419
+ context.fillStyle = line.bullet.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
2330
2420
  context.fillText("\u2022", inset + line.indent - line.size * 0.9, baseline);
2331
2421
  }
2332
2422
  for (const piece of line.pieces) {
2333
2423
  context.font = fontOf(piece.run, themeFont, width);
2334
- context.fillStyle = piece.run.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body;
2424
+ context.fillStyle = piece.run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
2335
2425
  context.fillText(piece.text, x, baseline);
2336
2426
  if (piece.run.underline) {
2337
2427
  context.fillRect(x, baseline + line.size * 0.08, piece.width, Math.max(1, line.size * 0.05));
@@ -2348,7 +2438,7 @@ var boxWords = (box2) => box2.paragraphs.map(
2348
2438
  ).filter(Boolean);
2349
2439
 
2350
2440
  // src/presentation/render-slides.ts
2351
- var SLIDE_PIXELS = { width: 1920, height: Math.round(1920 / chunkXTR26TNE_cjs.STAGE_ASPECT) };
2441
+ var SLIDE_PIXELS = { width: 1920, height: Math.round(1920 / chunk4TTX6ZNS_cjs.STAGE_ASPECT) };
2352
2442
  async function videoFrame(source, seconds) {
2353
2443
  const video = document.createElement("video");
2354
2444
  video.muted = true;
@@ -2460,7 +2550,7 @@ async function drawRoundedClip(context, clip, box2, stageWidth, shadow = true) {
2460
2550
  outline2();
2461
2551
  context.clip();
2462
2552
  await drawClip(context, clip, box2);
2463
- if (clip.kind === "pdf") chunkXTR26TNE_cjs.paintClipEdge(context, box2, stageWidth);
2553
+ if (clip.kind === "pdf") chunk4TTX6ZNS_cjs.paintClipEdge(context, box2, stageWidth);
2464
2554
  context.restore();
2465
2555
  context.save();
2466
2556
  context.strokeStyle = "rgba(255,255,255,0.15)";
@@ -2492,7 +2582,7 @@ function wrapLines(context, text, width, max) {
2492
2582
  function drawText(context, box2, lines, theme, width, height) {
2493
2583
  const size = box2.size * width;
2494
2584
  const lineHeight = size * box2.leading;
2495
- context.font = `${box2.weight} ${size}px ${chunkXTR26TNE_cjs.FONTS[theme.font].css}`;
2585
+ context.font = `${box2.weight} ${size}px ${chunk4TTX6ZNS_cjs.FONTS[theme.font].css}`;
2496
2586
  context.textBaseline = "top";
2497
2587
  const indent = box2.bullets ? size * 1.22 : 0;
2498
2588
  const left = box2.x * width;
@@ -2514,10 +2604,10 @@ function drawText(context, box2, lines, theme, width, height) {
2514
2604
  for (const wrapped of paragraphs) {
2515
2605
  if (box2.bullets) {
2516
2606
  const square = size * 0.42;
2517
- context.fillStyle = chunkXTR26TNE_cjs.accentColor(theme.accent);
2607
+ context.fillStyle = chunk4TTX6ZNS_cjs.accentColor(theme.accent);
2518
2608
  context.fillRect(left, y + size * 0.5 - square / 2, square, square);
2519
2609
  }
2520
- context.fillStyle = chunkXTR26TNE_cjs.TEXT_COLORS[box2.tone];
2610
+ context.fillStyle = chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone];
2521
2611
  context.textAlign = box2.align === "center" ? "center" : "left";
2522
2612
  for (const line of wrapped) {
2523
2613
  const x = box2.align === "center" ? left + box2.w * width / 2 : left + indent;
@@ -2553,11 +2643,11 @@ async function loadImage(file) {
2553
2643
  }
2554
2644
  }
2555
2645
  function slideWords(slide) {
2556
- const own = slide.layout === "free" ? [] : [slide.caption.trim(), ...chunkXTR26TNE_cjs.textLines(slide.points)];
2646
+ const own = slide.layout === "free" ? [] : [slide.caption.trim(), ...chunk4TTX6ZNS_cjs.textLines(slide.points)];
2557
2647
  return [...own, ...slide.boxes.flatMap(boxWords)].filter(Boolean);
2558
2648
  }
2559
2649
  function drawSlideText(context, slide, look, width, height) {
2560
- const geometry = chunkXTR26TNE_cjs.slideGeometry(slide, {
2650
+ const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, {
2561
2651
  labels: look.labels,
2562
2652
  logo: look.theme.logo?.corner ?? null
2563
2653
  });
@@ -2565,13 +2655,13 @@ function drawSlideText(context, slide, look, width, height) {
2565
2655
  if (title && geometry.title) {
2566
2656
  drawText(context, geometry.title, [title], look.theme, width, height);
2567
2657
  if (geometry.rule) {
2568
- context.fillStyle = chunkXTR26TNE_cjs.accentColor(look.theme.accent);
2658
+ context.fillStyle = chunk4TTX6ZNS_cjs.accentColor(look.theme.accent);
2569
2659
  const r = geometry.rule;
2570
2660
  context.fillRect(r.x * width, r.y * height, r.w * width, r.h * height);
2571
2661
  }
2572
2662
  }
2573
2663
  if (geometry.text) {
2574
- drawText(context, geometry.text, chunkXTR26TNE_cjs.textLines(slide.points), look.theme, width, height);
2664
+ drawText(context, geometry.text, chunk4TTX6ZNS_cjs.textLines(slide.points), look.theme, width, height);
2575
2665
  }
2576
2666
  return geometry;
2577
2667
  }
@@ -2583,13 +2673,13 @@ async function renderSlide(slide, clips, look) {
2583
2673
  const context = canvas.getContext("2d");
2584
2674
  if (!context) throw new Error("Could not draw the slides");
2585
2675
  if (slide.background) {
2586
- await chunkXTR26TNE_cjs.paintSlideBackground(context, width, height, slide.background, look.media);
2676
+ await chunk4TTX6ZNS_cjs.paintSlideBackground(context, width, height, slide.background, look.media);
2587
2677
  } else {
2588
- chunkXTR26TNE_cjs.paintBackground(context, width, height, look.theme.background);
2678
+ chunk4TTX6ZNS_cjs.paintBackground(context, width, height, look.theme.background);
2589
2679
  }
2590
2680
  const geometry = drawSlideText(context, slide, look, width, height);
2591
2681
  const text = slideWords(slide);
2592
- const font = chunkXTR26TNE_cjs.FONTS[look.theme.font].css;
2682
+ const font = chunk4TTX6ZNS_cjs.FONTS[look.theme.font].css;
2593
2683
  const drawBoxes = (front) => {
2594
2684
  for (const box2 of slide.boxes) {
2595
2685
  if (!!box2.front === front) drawBox(context, box2, width, height, font);
@@ -2603,16 +2693,16 @@ async function renderSlide(slide, clips, look) {
2603
2693
  x: item.frame.x * width,
2604
2694
  y: item.frame.y * height,
2605
2695
  width: item.frame.w * width,
2606
- height: chunkXTR26TNE_cjs.frameHeight(item.frame, clip.aspect) * height
2696
+ height: chunk4TTX6ZNS_cjs.frameHeight(item.frame, clip.aspect) * height
2607
2697
  };
2608
2698
  if (clip.plain) {
2609
2699
  await drawClip(context, clip, box2);
2610
2700
  continue;
2611
2701
  }
2612
2702
  await drawRoundedClip(context, clip, box2, width);
2613
- const label = chunkXTR26TNE_cjs.clipLabel(clip, look.columnValues);
2703
+ const label = chunk4TTX6ZNS_cjs.clipLabel(clip, look.columnValues);
2614
2704
  if (look.labels && label) {
2615
- context.fillStyle = chunkXTR26TNE_cjs.TEXT_COLORS.muted;
2705
+ context.fillStyle = chunk4TTX6ZNS_cjs.TEXT_COLORS.muted;
2616
2706
  context.font = `${Math.round(width * 0.017)}px ${font}`;
2617
2707
  context.textAlign = "left";
2618
2708
  context.textBaseline = "top";
@@ -2655,7 +2745,7 @@ function addBox(pptx, page, box2, themeFont) {
2655
2745
  if (box2.shape === "line") {
2656
2746
  page.addShape(pptx.ShapeType.line, {
2657
2747
  ...place,
2658
- line: line ?? { color: hex(chunkXTR26TNE_cjs.TEXT_COLORS.body), width: 1 }
2748
+ line: line ?? { color: hex(chunk4TTX6ZNS_cjs.TEXT_COLORS.body), width: 1 }
2659
2749
  });
2660
2750
  return;
2661
2751
  }
@@ -2672,9 +2762,9 @@ function addBox(pptx, page, box2, themeFont) {
2672
2762
  runs.push({
2673
2763
  text: run.text,
2674
2764
  options: {
2675
- fontSize: run.size ?? chunkXTR26TNE_cjs.DEFAULT_TEXT_SIZE,
2765
+ fontSize: run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE,
2676
2766
  fontFace: run.font ?? themeFont,
2677
- color: hex(run.color ?? chunkXTR26TNE_cjs.TEXT_COLORS.body),
2767
+ color: hex(run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body),
2678
2768
  ...run.bold ? { bold: true } : {},
2679
2769
  ...run.italic ? { italic: true } : {},
2680
2770
  ...run.underline ? { underline: { style: "sng" } } : {},
@@ -2696,7 +2786,7 @@ function addBox(pptx, page, box2, themeFont) {
2696
2786
  // Its part in the slide (its title, its body), kept by name: read back when imported.
2697
2787
  ...box2.role ? { objectName: `ARBI ${box2.role}` } : {},
2698
2788
  valign: box2.anchor ?? "top",
2699
- margin: box2.inset ?? chunkXTR26TNE_cjs.DEFAULT_INSET,
2789
+ margin: box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET,
2700
2790
  lineSpacingMultiple: 1,
2701
2791
  fit: "none"
2702
2792
  });
@@ -2726,10 +2816,10 @@ var box = (b) => ({
2726
2816
  function textOptions(text, look) {
2727
2817
  return {
2728
2818
  ...box(text),
2729
- fontFace: chunkXTR26TNE_cjs.FONTS[look.theme.font].pptx,
2819
+ fontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
2730
2820
  fontSize: toPoints(text.size),
2731
2821
  bold: text.weight >= 600,
2732
- color: hex2(chunkXTR26TNE_cjs.TEXT_COLORS[text.tone]),
2822
+ color: hex2(chunk4TTX6ZNS_cjs.TEXT_COLORS[text.tone]),
2733
2823
  align: text.align,
2734
2824
  valign: text.anchor ?? "top",
2735
2825
  lineSpacingMultiple: text.leading,
@@ -2742,18 +2832,18 @@ async function buildPptx(deck, look) {
2742
2832
  pptx.layout = "LAYOUT_WIDE";
2743
2833
  pptx.title = deck.title;
2744
2834
  pptx.theme = {
2745
- headFontFace: chunkXTR26TNE_cjs.FONTS[look.theme.font].pptx,
2746
- bodyFontFace: chunkXTR26TNE_cjs.FONTS[look.theme.font].pptx
2835
+ headFontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
2836
+ bodyFontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx
2747
2837
  };
2748
2838
  const { width, height } = SLIDE_PIXELS;
2749
2839
  const background = await canvasImage(
2750
2840
  width,
2751
2841
  height,
2752
- (context) => chunkXTR26TNE_cjs.paintBackground(context, width, height, look.theme.background)
2842
+ (context) => chunk4TTX6ZNS_cjs.paintBackground(context, width, height, look.theme.background)
2753
2843
  );
2754
2844
  const logo = look.logo ? await loadImage(look.logo) : null;
2755
2845
  const logoData = logo ? await canvasImage(logo.width, logo.height, (context) => context.drawImage(logo, 0, 0)) : null;
2756
- const themeFont = chunkXTR26TNE_cjs.FONTS[look.theme.font].pptx;
2846
+ const themeFont = chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx;
2757
2847
  for (const slide of deck.slides) {
2758
2848
  const page = pptx.addSlide();
2759
2849
  if (slide.background?.color && !slide.background.gradient && !slide.background.image) {
@@ -2764,14 +2854,14 @@ async function buildPptx(deck, look) {
2764
2854
  data: await canvasImage(
2765
2855
  width,
2766
2856
  height,
2767
- (context) => chunkXTR26TNE_cjs.paintSlideBackground(context, width, height, own, look.media)
2857
+ (context) => chunk4TTX6ZNS_cjs.paintSlideBackground(context, width, height, own, look.media)
2768
2858
  )
2769
2859
  };
2770
2860
  } else {
2771
2861
  page.background = { data: background };
2772
2862
  }
2773
2863
  if (slide.notes?.trim()) page.addNotes(slide.notes);
2774
- const geometry = chunkXTR26TNE_cjs.slideGeometry(slide, {
2864
+ const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, {
2775
2865
  labels: look.labels,
2776
2866
  logo: look.theme.logo?.corner ?? null
2777
2867
  });
@@ -2779,7 +2869,7 @@ async function buildPptx(deck, look) {
2779
2869
  for (const item of slide.items) {
2780
2870
  const clip = deck.clips.find((entry) => entry.id === item.clipId);
2781
2871
  if (!clip) continue;
2782
- const frame = { ...item.frame, h: chunkXTR26TNE_cjs.frameHeight(item.frame, clip.aspect) };
2872
+ const frame = { ...item.frame, h: chunk4TTX6ZNS_cjs.frameHeight(item.frame, clip.aspect) };
2783
2873
  if (clip.plain) {
2784
2874
  const source = clip.kind === "image" ? await createImageBitmap(clip.source) : null;
2785
2875
  const scale = source ? Math.min(1, 2400 / Math.max(1, clip.rect.w * source.width)) : 1.5;
@@ -2811,13 +2901,13 @@ async function buildPptx(deck, look) {
2811
2901
  altText: clip.caption,
2812
2902
  shadow: { type: "outer", blur: 10, offset: 3, angle: 90, color: "000000", opacity: 0.45 }
2813
2903
  });
2814
- const label = chunkXTR26TNE_cjs.clipLabel(clip, look.columnValues);
2904
+ const label = chunk4TTX6ZNS_cjs.clipLabel(clip, look.columnValues);
2815
2905
  if (look.labels && label) {
2816
2906
  page.addText(label, {
2817
2907
  ...box({ x: frame.x, y: frame.y + frame.h + 8e-3, w: frame.w, h: 0.045 }),
2818
- fontFace: chunkXTR26TNE_cjs.FONTS[look.theme.font].pptx,
2908
+ fontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
2819
2909
  fontSize: toPoints(0.017),
2820
- color: hex2(chunkXTR26TNE_cjs.TEXT_COLORS.muted),
2910
+ color: hex2(chunk4TTX6ZNS_cjs.TEXT_COLORS.muted),
2821
2911
  margin: 0,
2822
2912
  valign: "top",
2823
2913
  fit: "shrink"
@@ -2830,12 +2920,12 @@ async function buildPptx(deck, look) {
2830
2920
  if (geometry.rule) {
2831
2921
  page.addShape(pptx.ShapeType.rect, {
2832
2922
  ...box(geometry.rule),
2833
- fill: { color: hex2(chunkXTR26TNE_cjs.accentColor(look.theme.accent)) },
2834
- line: { color: hex2(chunkXTR26TNE_cjs.accentColor(look.theme.accent)), width: 0 }
2923
+ fill: { color: hex2(chunk4TTX6ZNS_cjs.accentColor(look.theme.accent)) },
2924
+ line: { color: hex2(chunk4TTX6ZNS_cjs.accentColor(look.theme.accent)), width: 0 }
2835
2925
  });
2836
2926
  }
2837
2927
  }
2838
- const lines = chunkXTR26TNE_cjs.textLines(slide.points);
2928
+ const lines = chunk4TTX6ZNS_cjs.textLines(slide.points);
2839
2929
  if (geometry.text && lines.length) {
2840
2930
  const text = geometry.text;
2841
2931
  page.addText(
@@ -2869,7 +2959,7 @@ async function buildPptx(deck, look) {
2869
2959
  }
2870
2960
  }
2871
2961
  const deckFile = await pptx.write({ outputType: "blob" });
2872
- return accentBullets(deckFile, chunkXTR26TNE_cjs.accentColor(look.theme.accent));
2962
+ return accentBullets(deckFile, chunk4TTX6ZNS_cjs.accentColor(look.theme.accent));
2873
2963
  }
2874
2964
  async function accentBullets(deck, accent) {
2875
2965
  const { default: JSZip } = await import('jszip');
@@ -3400,7 +3490,7 @@ function renditionClip(deck, part, area, what) {
3400
3490
  fileName: fileName ?? "Presentation.pptx",
3401
3491
  page: part.page,
3402
3492
  rect,
3403
- aspect: frame.w * chunkXTR26TNE_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3493
+ aspect: frame.w * chunk4TTX6ZNS_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3404
3494
  caption: "",
3405
3495
  plain: true
3406
3496
  });
@@ -3539,7 +3629,7 @@ async function readShape(shape, transform, deck, part, inherit, built) {
3539
3629
  fileName: target?.target.split("/").pop() ?? "Picture",
3540
3630
  page: 1,
3541
3631
  rect,
3542
- aspect: frame.w * chunkXTR26TNE_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3632
+ aspect: frame.w * chunk4TTX6ZNS_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3543
3633
  caption: "",
3544
3634
  media: key,
3545
3635
  plain: true
@@ -3762,7 +3852,7 @@ async function importPptx(bytes, options = {}) {
3762
3852
  const cx = numAttr(size, "cx", 12192e3);
3763
3853
  const cy = numAttr(size, "cy", 6858e3);
3764
3854
  const deckAspect = cx / cy;
3765
- const place = deckAspect < chunkXTR26TNE_cjs.STAGE_ASPECT ? { w: deckAspect / chunkXTR26TNE_cjs.STAGE_ASPECT, h: 1, x: (1 - deckAspect / chunkXTR26TNE_cjs.STAGE_ASPECT) / 2, y: 0 } : { w: 1, h: chunkXTR26TNE_cjs.STAGE_ASPECT / deckAspect, x: 0, y: (1 - chunkXTR26TNE_cjs.STAGE_ASPECT / deckAspect) / 2 };
3855
+ const place = deckAspect < chunk4TTX6ZNS_cjs.STAGE_ASPECT ? { w: deckAspect / chunk4TTX6ZNS_cjs.STAGE_ASPECT, h: 1, x: (1 - deckAspect / chunk4TTX6ZNS_cjs.STAGE_ASPECT) / 2, y: 0 } : { w: 1, h: chunk4TTX6ZNS_cjs.STAGE_ASPECT / deckAspect, x: 0, y: (1 - chunk4TTX6ZNS_cjs.STAGE_ASPECT / deckAspect) / 2 };
3766
3856
  const slides = await slideParts(pkg);
3767
3857
  const firstLayout = slides.length ? await pkg.related(slides[0].part, "/slideLayout") : null;
3768
3858
  const firstMaster = firstLayout ? await pkg.related(firstLayout, "/slideMaster") : null;
@@ -3771,7 +3861,7 @@ async function importPptx(bytes, options = {}) {
3771
3861
  theme: firstMaster ? await readTheme(pkg, firstMaster) : { scheme: {}, map: {}, majorFont: "Calibri", minorFont: "Calibri", lineWidths: [] },
3772
3862
  slideSize: { cx, cy },
3773
3863
  place,
3774
- pointScale: chunkXTR26TNE_cjs.SLIDE_POINTS.h * place.h / (cy / EMU_PER_POINT),
3864
+ pointScale: chunk4TTX6ZNS_cjs.SLIDE_POINTS.h * place.h / (cy / EMU_PER_POINT),
3775
3865
  defaultText: kid(pres.documentElement, "defaultTextStyle"),
3776
3866
  options,
3777
3867
  clips: [],
@@ -3867,7 +3957,7 @@ async function importPptx(bytes, options = {}) {
3867
3957
  version: 1,
3868
3958
  title: options.title ?? (coreTitle?.trim() || "Presentation"),
3869
3959
  captions: false,
3870
- theme: chunkXTR26TNE_cjs.DEFAULT_THEME,
3960
+ theme: chunk4TTX6ZNS_cjs.DEFAULT_THEME,
3871
3961
  clips: deck.clips,
3872
3962
  slides: saved,
3873
3963
  ...Object.keys(deck.media).length ? { media: deck.media } : {}
@@ -3955,7 +4045,7 @@ async function presentationData(bytes) {
3955
4045
  if (isZipBytes(bytes)) return readPptxPresentationData(bytes);
3956
4046
  const isPdf = bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70;
3957
4047
  if (!isPdf) return new TextDecoder().decode(bytes);
3958
- const data = await documentTools.readPdfAttachment(bytes, chunkXTR26TNE_cjs.PRESENTATION_ATTACHMENT);
4048
+ const data = await documentTools.readPdfAttachment(bytes, chunk4TTX6ZNS_cjs.PRESENTATION_ATTACHMENT);
3959
4049
  if (!data) {
3960
4050
  throw new Error(
3961
4051
  "This PDF has no editable presentation in it (it may have been changed outside ARBI)."
@@ -3964,7 +4054,7 @@ async function presentationData(bytes) {
3964
4054
  return new TextDecoder().decode(data);
3965
4055
  }
3966
4056
  function current(withoutClips) {
3967
- const state = chunkXTR26TNE_cjs.usePresentation.getState();
4057
+ const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
3968
4058
  return withoutClips ? {
3969
4059
  ...state,
3970
4060
  clips: [],
@@ -3986,18 +4076,18 @@ function usePresentationFiles() {
3986
4076
  const state = current(withoutClips);
3987
4077
  const deck = await buildPptx({ title, slides: state.slides, clips: state.clips }, lookOf(state));
3988
4078
  const fingerprints = await slideFingerprints(deck);
3989
- const data = chunkXTR26TNE_cjs.serializePresentation({ ...state, title, fingerprints });
4079
+ const data = chunk4TTX6ZNS_cjs.serializePresentation({ ...state, title, fingerprints });
3990
4080
  return writePptxPresentationData(deck, JSON.stringify(data, null, 2));
3991
4081
  }, []);
3992
4082
  const save = react.useCallback(
3993
4083
  async (title, { asNew = false, template = false } = {}) => {
3994
4084
  if (!arbi || !workspaceId) throw new Error("Open a workspace to save the presentation.");
3995
- const state = chunkXTR26TNE_cjs.usePresentation.getState();
4085
+ const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
3996
4086
  const versionOf = asNew || template ? null : state.savedId;
3997
4087
  const deck = await buildFile(title, template);
3998
- const file = new File([deck], chunkXTR26TNE_cjs.presentationFileName(title), { type: PPTX_TYPE });
4088
+ const file = new File([deck], chunk4TTX6ZNS_cjs.presentationFileName(title), { type: PPTX_TYPE });
3999
4089
  const result = await arbi.documents.upload([file], {
4000
- folder: template ? chunkXTR26TNE_cjs.TEMPLATES_FOLDER : chunkXTR26TNE_cjs.PRESENTATIONS_FOLDER,
4090
+ folder: template ? chunk4TTX6ZNS_cjs.TEMPLATES_FOLDER : chunk4TTX6ZNS_cjs.PRESENTATIONS_FOLDER,
4001
4091
  workspaceExtId: workspaceId,
4002
4092
  ...versionOf ? { versionOf } : {}
4003
4093
  });
@@ -4022,8 +4112,8 @@ function usePresentationFiles() {
4022
4112
  }
4023
4113
  const pdf = await documentTools.imagesToPdf(pages, { title });
4024
4114
  const result = await arbi.documents.upload(
4025
- [new File([pdf], `${chunkXTR26TNE_cjs.safeFileStem(title)}.pdf`, { type: "application/pdf" })],
4026
- { folder: chunkXTR26TNE_cjs.EXPORTS_FOLDER, workspaceExtId: workspaceId }
4115
+ [new File([pdf], `${chunk4TTX6ZNS_cjs.safeFileStem(title)}.pdf`, { type: "application/pdf" })],
4116
+ { folder: chunk4TTX6ZNS_cjs.EXPORTS_FOLDER, workspaceExtId: workspaceId }
4027
4117
  );
4028
4118
  const id = result.doc_ext_ids?.[0];
4029
4119
  if (!id) throw new Error("The PDF could not be saved.");
@@ -4038,10 +4128,10 @@ function usePresentationFiles() {
4038
4128
  return docs.filter((doc) => {
4039
4129
  const folder = doc.folder ?? "";
4040
4130
  if (!ui.isPresentationFileName(doc.file_name, folder)) return false;
4041
- return scope === "templates" ? folder === chunkXTR26TNE_cjs.TEMPLATES_FOLDER : folder.startsWith(chunkXTR26TNE_cjs.PRESENTATIONS_FOLDER) && folder !== chunkXTR26TNE_cjs.TEMPLATES_FOLDER && !folder.startsWith(chunkXTR26TNE_cjs.EXPORTS_FOLDER);
4131
+ return scope === "templates" ? folder === chunk4TTX6ZNS_cjs.TEMPLATES_FOLDER : folder.startsWith(chunk4TTX6ZNS_cjs.PRESENTATIONS_FOLDER) && folder !== chunk4TTX6ZNS_cjs.TEMPLATES_FOLDER && !folder.startsWith(chunk4TTX6ZNS_cjs.EXPORTS_FOLDER);
4042
4132
  }).map((doc) => ({
4043
4133
  id: doc.external_id,
4044
- title: chunkXTR26TNE_cjs.presentationTitle(doc.file_name ?? ""),
4134
+ title: chunk4TTX6ZNS_cjs.presentationTitle(doc.file_name ?? ""),
4045
4135
  updatedAt: doc.updated_at ?? doc.created_at ?? null
4046
4136
  })).sort((a, b) => (a.updatedAt ?? "") < (b.updatedAt ?? "") ? 1 : -1);
4047
4137
  },
@@ -4057,7 +4147,7 @@ function usePresentationFiles() {
4057
4147
  const openedVersion = version ?? doc?.current_version ?? null;
4058
4148
  if (text === null) {
4059
4149
  const imported = await importPptx(bytes, {
4060
- title: chunkXTR26TNE_cjs.presentationTitle(doc?.file_name ?? "Presentation.pptx"),
4150
+ title: chunk4TTX6ZNS_cjs.presentationTitle(doc?.file_name ?? "Presentation.pptx"),
4061
4151
  documentId: id,
4062
4152
  version: version ?? doc?.current_version,
4063
4153
  fileName: doc?.file_name ?? void 0
@@ -4069,7 +4159,7 @@ function usePresentationFiles() {
4069
4159
  openedVersion
4070
4160
  };
4071
4161
  }
4072
- let saved = chunkXTR26TNE_cjs.parsePresentation(text);
4162
+ let saved = chunk4TTX6ZNS_cjs.parsePresentation(text);
4073
4163
  let changedOutside;
4074
4164
  if (isZipBytes(bytes) && saved.slides.some((slide) => slide.fingerprint)) {
4075
4165
  const now = await slideFingerprints(bytes);
@@ -4100,7 +4190,7 @@ function usePresentationFiles() {
4100
4190
  const startFromTemplate = react.useCallback(
4101
4191
  async (id) => {
4102
4192
  const { saved } = await readSaved(id);
4103
- chunkXTR26TNE_cjs.usePresentation.getState().load({
4193
+ chunk4TTX6ZNS_cjs.usePresentation.getState().load({
4104
4194
  title: "Untitled presentation",
4105
4195
  savedId: null,
4106
4196
  captions: saved.captions,
@@ -4177,7 +4267,7 @@ function usePresentationFiles() {
4177
4267
  );
4178
4268
  const kept = [];
4179
4269
  const newIndex = opened.map((clip) => clip ? kept.push(clip) - 1 : -1);
4180
- chunkXTR26TNE_cjs.usePresentation.getState().load({
4270
+ chunk4TTX6ZNS_cjs.usePresentation.getState().load({
4181
4271
  title: saved.title,
4182
4272
  savedId: legacy ? null : id,
4183
4273
  version: legacy ? null : openedVersion,
@@ -4226,7 +4316,7 @@ function useGenerateImageLaunch() {
4226
4316
  if (!arbi || !workspaceId) throw new Error("Open a workspace to generate images.");
4227
4317
  const prompt = typeof inputs.prompt === "string" ? inputs.prompt.trim() : "";
4228
4318
  if (!prompt) return;
4229
- const tools = chunkNLOETJCB_cjs.PROMPT_BINDINGS[chunk7JLJH5CW_cjs.GENERATE_IMAGE_ID].tools?.(inputs);
4319
+ const tools = chunk2F57IO7S_cjs.PROMPT_BINDINGS[chunk7JLJH5CW_cjs.GENERATE_IMAGE_ID].tools?.(inputs);
4230
4320
  let image;
4231
4321
  let answer = "";
4232
4322
  let failure = "";
@@ -4251,7 +4341,7 @@ function useGenerateImageLaunch() {
4251
4341
  throw new Error(failure || answer.trim() || "The image could not be generated.");
4252
4342
  const source = await (await arbi.documents.download(documentId)).blob();
4253
4343
  const fileName = `${prompt.split("\n")[0].slice(0, 60)}.png`;
4254
- chunkXTR26TNE_cjs.usePresentation.getState().addClip({
4344
+ chunk4TTX6ZNS_cjs.usePresentation.getState().addClip({
4255
4345
  kind: "image",
4256
4346
  documentId,
4257
4347
  fileName,
@@ -4260,7 +4350,7 @@ function useGenerateImageLaunch() {
4260
4350
  aspect: await aspectOf(source),
4261
4351
  masks: [],
4262
4352
  source,
4263
- caption: chunkXTR26TNE_cjs.mediaCaption(fileName)
4353
+ caption: chunk4TTX6ZNS_cjs.mediaCaption(fileName)
4264
4354
  });
4265
4355
  },
4266
4356
  [arbi, workspaceId]
@@ -4271,8 +4361,8 @@ function GenerateImageDialog({
4271
4361
  onOpenChange,
4272
4362
  referenceId
4273
4363
  }) {
4274
- const notify = chunkXTR26TNE_cjs.usePresentation((s) => s.notify);
4275
- const { skills } = chunkGKVE5JGB_cjs.useWorkflowDefinitions();
4364
+ const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
4365
+ const { skills } = chunkUFT22LAB_cjs.useWorkflowDefinitions();
4276
4366
  const run = useGenerateImageLaunch();
4277
4367
  const workflows = react.useMemo(
4278
4368
  () => skills.filter((w) => w.id === chunk7JLJH5CW_cjs.GENERATE_IMAGE_ID).map((w) => ({ ...w, options: { ...w.options, agent: false } })),
@@ -4292,7 +4382,7 @@ function GenerateImageDialog({
4292
4382
  );
4293
4383
  if (!open || !workflows.length) return null;
4294
4384
  return /* @__PURE__ */ jsxRuntime.jsx(
4295
- chunkNLOETJCB_cjs.ConnectedWorkflowStart,
4385
+ chunk2F57IO7S_cjs.ConnectedWorkflowStart,
4296
4386
  {
4297
4387
  workflows,
4298
4388
  showTiles: false,
@@ -4331,9 +4421,9 @@ function SavePresentationDialog({
4331
4421
  onOpenChange,
4332
4422
  mode = "save"
4333
4423
  }) {
4334
- const notify = chunkXTR26TNE_cjs.usePresentation((s) => s.notify);
4424
+ const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
4335
4425
  const { save, exportPdf } = usePresentationFiles();
4336
- const current2 = chunkXTR26TNE_cjs.usePresentation((s) => s.title);
4426
+ const current2 = chunk4TTX6ZNS_cjs.usePresentation((s) => s.title);
4337
4427
  const [title, setTitle] = react.useState(current2);
4338
4428
  const [busy, setBusy] = react.useState(false);
4339
4429
  const text = SAVE_TEXT[mode];
@@ -4403,7 +4493,7 @@ function OpenPresentationDialog({
4403
4493
  templates = false
4404
4494
  }) {
4405
4495
  const { confirm } = chunkTKHCIHE2_cjs.useBlocksEnvironment();
4406
- const notify = chunkXTR26TNE_cjs.usePresentation((s) => s.notify);
4496
+ const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
4407
4497
  const { list, startFromTemplate } = usePresentationFiles();
4408
4498
  const [entries, setEntries] = react.useState(null);
4409
4499
  const [opening, setOpening] = react.useState(null);
@@ -4418,7 +4508,7 @@ function OpenPresentationDialog({
4418
4508
  onOpened(entry.id);
4419
4509
  return;
4420
4510
  }
4421
- if (chunkXTR26TNE_cjs.usePresentation.getState().clips.length) {
4511
+ if (chunk4TTX6ZNS_cjs.usePresentation.getState().clips.length) {
4422
4512
  const ok = await confirm({
4423
4513
  title: "New from template",
4424
4514
  message: "Replace the presentation that is open? Save it first to keep it.",
@@ -4469,8 +4559,8 @@ function OpenPresentationDialog({
4469
4559
  }
4470
4560
  var IMAGE_FILE = /\.(png|jpe?g|gif|webp|svg)$/i;
4471
4561
  function ChooseLogoDialog({ open, onOpenChange }) {
4472
- const setTheme = chunkXTR26TNE_cjs.usePresentation((s) => s.setTheme);
4473
- const corner = chunkXTR26TNE_cjs.usePresentation((s) => s.theme.logo?.corner ?? "br");
4562
+ const setTheme = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setTheme);
4563
+ const corner = chunk4TTX6ZNS_cjs.usePresentation((s) => s.theme.logo?.corner ?? "br");
4474
4564
  const { data: documents } = react$1.useDocuments(void 0, { enabled: open });
4475
4565
  const [picked, setPicked] = react.useState("");
4476
4566
  const groups = react.useMemo(
@@ -4557,7 +4647,7 @@ function CropClipDialog({ clip, onOpenChange }) {
4557
4647
  w: Math.min(1, area.width / natural.width),
4558
4648
  h: Math.min(1, area.height / natural.height)
4559
4649
  };
4560
- chunkXTR26TNE_cjs.usePresentation.getState().cropClip(clip.id, rect, area.width / area.height);
4650
+ chunk4TTX6ZNS_cjs.usePresentation.getState().cropClip(clip.id, rect, area.width / area.height);
4561
4651
  onOpenChange(false);
4562
4652
  };
4563
4653
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4606,8 +4696,8 @@ function CropClipDialog({ clip, onOpenChange }) {
4606
4696
  var EMPTY = new Blob();
4607
4697
  var NONE = "none";
4608
4698
  function LabelColumnMenu({ columns }) {
4609
- const labelColumn = chunkXTR26TNE_cjs.usePresentation((s) => s.labelColumn);
4610
- const setLabelColumn = chunkXTR26TNE_cjs.usePresentation((s) => s.setLabelColumn);
4699
+ const labelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.labelColumn);
4700
+ const setLabelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setLabelColumn);
4611
4701
  if (!columns.length) return null;
4612
4702
  const chosen = columns.find((column) => column.id === labelColumn);
4613
4703
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuSub, { children: [
@@ -4650,8 +4740,8 @@ function useLabelColumns(active) {
4650
4740
  const workspaceId = react$1.useArbiSessionState((s) => s.workspaceId);
4651
4741
  const { data: tags } = react$1.useTags(workspaceId, { enabled: active });
4652
4742
  const { data: documents } = react$1.useDocuments(workspaceId, { enabled: active });
4653
- const labelColumn = chunkXTR26TNE_cjs.usePresentation((s) => s.labelColumn);
4654
- const documentIds = chunkXTR26TNE_cjs.usePresentation((s) => s.clips.map((clip) => clip.documentId).join(" "));
4743
+ const labelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.labelColumn);
4744
+ const documentIds = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips.map((clip) => clip.documentId).join(" "));
4655
4745
  const columns = react.useMemo(
4656
4746
  () => (tags ?? []).filter((tag) => tag.kind !== "search" && VALUE_FORMATS.has(tag.tag_type.type)).map((tag) => ({ id: tag.external_id, name: tag.name })).sort((a, b) => a.name.localeCompare(b.name)),
4657
4747
  [tags]
@@ -4666,23 +4756,23 @@ function useLabelColumns(active) {
4666
4756
  if (note2) values[doc.external_id] = note2;
4667
4757
  }
4668
4758
  }
4669
- chunkXTR26TNE_cjs.usePresentation.getState().setColumnValues(values);
4759
+ chunk4TTX6ZNS_cjs.usePresentation.getState().setColumnValues(values);
4670
4760
  }, [labelColumn, documentIds, documents]);
4671
4761
  return columns;
4672
4762
  }
4673
4763
  function usePresentationController(active) {
4674
4764
  const session = react$1.useArbiSessionStore();
4675
- const notify = chunkXTR26TNE_cjs.usePresentation((s) => s.notify);
4765
+ const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
4676
4766
  const { save, canSave } = usePresentationFiles();
4677
4767
  const labelColumns = useLabelColumns(active);
4678
4768
  const [dialog, setDialog] = react.useState(null);
4679
4769
  const [reference, setReference] = react.useState(null);
4680
4770
  const [cropping, setCropping] = react.useState(null);
4681
- const cropClip = chunkXTR26TNE_cjs.usePresentation((s) => s.clips.find((c) => c.id === cropping) ?? null);
4771
+ const cropClip = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips.find((c) => c.id === cropping) ?? null);
4682
4772
  const [saving, setSaving] = react.useState(false);
4683
4773
  const close = (open) => !open && setDialog(null);
4684
4774
  const quickSave = react.useCallback(async () => {
4685
- const { savedId, title } = chunkXTR26TNE_cjs.usePresentation.getState();
4775
+ const { savedId, title } = chunk4TTX6ZNS_cjs.usePresentation.getState();
4686
4776
  if (!savedId) return setDialog("save");
4687
4777
  setSaving(true);
4688
4778
  try {
@@ -4716,7 +4806,7 @@ function usePresentationController(active) {
4716
4806
  {
4717
4807
  open: dialog === "open" || dialog === "fromTemplate",
4718
4808
  templates: dialog === "fromTemplate",
4719
- onOpened: (id) => chunk5LTIZ44D_cjs.editPresentation(session, id ? { kind: "open", documentId: id } : { kind: "new" }),
4809
+ onOpened: (id) => chunkWFMWKPGY_cjs.editPresentation(session, id ? { kind: "open", documentId: id } : { kind: "new" }),
4720
4810
  onOpenChange: close
4721
4811
  }
4722
4812
  ),
@@ -4758,7 +4848,7 @@ function usePresentationController(active) {
4758
4848
  trayStart: canSave && /* @__PURE__ */ jsxRuntime.jsx(GenerateTile, { onClick: () => generate(null) }),
4759
4849
  onChooseLogo: canSave ? () => setDialog("logo") : void 0,
4760
4850
  onEditImage: (clipId) => {
4761
- const clip = chunkXTR26TNE_cjs.usePresentation.getState().clips.find((c) => c.id === clipId);
4851
+ const clip = chunk4TTX6ZNS_cjs.usePresentation.getState().clips.find((c) => c.id === clipId);
4762
4852
  if (clip) generate(clip.documentId);
4763
4853
  },
4764
4854
  onCropImage: setCropping
@@ -4770,5 +4860,5 @@ exports.PresentationStage = PresentationStage;
4770
4860
  exports.SlidesEditor = SlidesEditor;
4771
4861
  exports.usePresentationController = usePresentationController;
4772
4862
  exports.usePresentationFiles = usePresentationFiles;
4773
- //# sourceMappingURL=chunk-Q3XJUXID.cjs.map
4774
- //# sourceMappingURL=chunk-Q3XJUXID.cjs.map
4863
+ //# sourceMappingURL=chunk-DWMWEALB.cjs.map
4864
+ //# sourceMappingURL=chunk-DWMWEALB.cjs.map