@arbidocs/blocks 0.5.123 → 0.5.124

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 (117) hide show
  1. package/dist/{ClippingMediaViewer-IEIBT74X.cjs → ClippingMediaViewer-ZFEX5A3U.cjs} +11 -10
  2. package/dist/ClippingMediaViewer-ZFEX5A3U.cjs.map +1 -0
  3. package/dist/{ClippingPdfViewer-OGYLMVCE.cjs → ClippingPdfViewer-3LRTEPHV.cjs} +45 -11
  4. package/dist/ClippingPdfViewer-3LRTEPHV.cjs.map +1 -0
  5. package/dist/ConnectedNativeDocxComparison-QKHCYD6W.cjs +1 -1
  6. package/dist/{ConnectedPresentation-5DOJ35XL.cjs → ConnectedPresentation-OV2KBOLK.cjs} +27 -153
  7. package/dist/ConnectedPresentation-OV2KBOLK.cjs.map +1 -0
  8. package/dist/{ConnectedSlidesTab-7YMEDGUU.cjs → ConnectedSlidesTab-LUAGZ6FD.cjs} +29 -27
  9. package/dist/ConnectedSlidesTab-LUAGZ6FD.cjs.map +1 -0
  10. package/dist/ConnectedStreamedWordArtifact-AG62232A.cjs +1 -1
  11. package/dist/{FilesViewerDialog-2QCCRWF2.cjs → FilesViewerDialog-JWKNJLWG.cjs} +12 -9
  12. package/dist/FilesViewerDialog-JWKNJLWG.cjs.map +1 -0
  13. package/dist/SpotlightStrip-ED22UYTM.cjs +398 -0
  14. package/dist/SpotlightStrip-ED22UYTM.cjs.map +1 -0
  15. package/dist/agents/index.cjs +176 -176
  16. package/dist/{chunk-46P7IDBX.cjs → chunk-3IH55CDE.cjs} +3 -3
  17. package/dist/chunk-3IH55CDE.cjs.map +1 -0
  18. package/dist/chunk-3ZZZO4F7.cjs +145 -0
  19. package/dist/chunk-3ZZZO4F7.cjs.map +1 -0
  20. package/dist/{chunk-WFMWKPGY.cjs → chunk-ADPRIBSH.cjs} +9 -33
  21. package/dist/chunk-ADPRIBSH.cjs.map +1 -0
  22. package/dist/{chunk-JD2HX2BR.cjs → chunk-BX6G2ZCI.cjs} +58 -86
  23. package/dist/chunk-BX6G2ZCI.cjs.map +1 -0
  24. package/dist/{chunk-NQML7IUC.cjs → chunk-CQQQIZU4.cjs} +3 -3
  25. package/dist/{chunk-NQML7IUC.cjs.map → chunk-CQQQIZU4.cjs.map} +1 -1
  26. package/dist/{chunk-SNPK3R3O.cjs → chunk-EMRY62HS.cjs} +5 -5
  27. package/dist/{chunk-SNPK3R3O.cjs.map → chunk-EMRY62HS.cjs.map} +1 -1
  28. package/dist/{chunk-DWMWEALB.cjs → chunk-H236SNEV.cjs} +143 -1634
  29. package/dist/chunk-H236SNEV.cjs.map +1 -0
  30. package/dist/chunk-JITYC4OS.cjs +66 -0
  31. package/dist/chunk-JITYC4OS.cjs.map +1 -0
  32. package/dist/chunk-JY7UUZQG.cjs +1513 -0
  33. package/dist/chunk-JY7UUZQG.cjs.map +1 -0
  34. package/dist/chunk-MVXHTAJ4.cjs +111 -0
  35. package/dist/chunk-MVXHTAJ4.cjs.map +1 -0
  36. package/dist/{chunk-4TTX6ZNS.cjs → chunk-ORNLCBNE.cjs} +24 -2
  37. package/dist/chunk-ORNLCBNE.cjs.map +1 -0
  38. package/dist/{chunk-L4CIFLCU.cjs → chunk-QG2U2JGX.cjs} +4 -4
  39. package/dist/{chunk-L4CIFLCU.cjs.map → chunk-QG2U2JGX.cjs.map} +1 -1
  40. package/dist/chunk-WVZLAAIZ.cjs +31 -0
  41. package/dist/chunk-WVZLAAIZ.cjs.map +1 -0
  42. package/dist/{chunk-WV7BCGCK.cjs → chunk-XGM4VVNV.cjs} +19 -19
  43. package/dist/{chunk-WV7BCGCK.cjs.map → chunk-XGM4VVNV.cjs.map} +1 -1
  44. package/dist/chunk-ZZZITHGK.cjs +119 -0
  45. package/dist/chunk-ZZZITHGK.cjs.map +1 -0
  46. package/dist/connect/docx.cjs +1 -1
  47. package/dist/connect/index.cjs +175 -175
  48. package/dist/connect/viewer.cjs +10 -7
  49. package/dist/connection/presentation/ClippingMediaViewer.js +3 -3
  50. package/dist/connection/presentation/ClippingMediaViewer.js.map +2 -2
  51. package/dist/connection/presentation/ClippingPdfViewer.d.ts +4 -3
  52. package/dist/connection/presentation/ClippingPdfViewer.js +48 -9
  53. package/dist/connection/presentation/ClippingPdfViewer.js.map +2 -2
  54. package/dist/connection/presentation/SpotlightLayer.d.ts +5 -0
  55. package/dist/connection/presentation/SpotlightLayer.js +19 -0
  56. package/dist/connection/presentation/SpotlightLayer.js.map +7 -0
  57. package/dist/connection/presentation/SpotlightStrip.d.ts +10 -0
  58. package/dist/connection/presentation/SpotlightStrip.js +237 -0
  59. package/dist/connection/presentation/SpotlightStrip.js.map +7 -0
  60. package/dist/connection/presentation/useViewerClipping.d.ts +4 -3
  61. package/dist/connection/presentation/useViewerClipping.js +8 -4
  62. package/dist/connection/presentation/useViewerClipping.js.map +2 -2
  63. package/dist/connection/viewer/ConnectedDocumentViewer.js +1 -1
  64. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  65. package/dist/connection/viewer/pdf/passageHighlights.d.ts +5 -0
  66. package/dist/connection/viewer/pdf/passageHighlights.js +14 -1
  67. package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
  68. package/dist/connection/viewer/useCleanView.d.ts +3 -1
  69. package/dist/connection/viewer/useCleanView.js +6 -3
  70. package/dist/connection/viewer/useCleanView.js.map +2 -2
  71. package/dist/document-tools/DocumentToolButtons.js +1 -1
  72. package/dist/document-tools/DocumentToolButtons.js.map +1 -1
  73. package/dist/document-tools/index.cjs +13 -13
  74. package/dist/embed/index.cjs +2 -2
  75. package/dist/index.cjs +239 -239
  76. package/dist/presentation/ClipCaptureOverlay.d.ts +7 -3
  77. package/dist/presentation/ClipCaptureOverlay.js +43 -14
  78. package/dist/presentation/ClipCaptureOverlay.js.map +2 -2
  79. package/dist/presentation/PresentControls.d.ts +8 -0
  80. package/dist/presentation/PresentControls.js +1 -0
  81. package/dist/presentation/PresentControls.js.map +2 -2
  82. package/dist/presentation/PresentationStage.d.ts +10 -2
  83. package/dist/presentation/PresentationStage.js +6 -3
  84. package/dist/presentation/PresentationStage.js.map +2 -2
  85. package/dist/presentation/PresenterView.js +1 -22
  86. package/dist/presentation/PresenterView.js.map +2 -2
  87. package/dist/presentation/SpotlightView.d.ts +19 -0
  88. package/dist/presentation/SpotlightView.js +180 -0
  89. package/dist/presentation/SpotlightView.js.map +7 -0
  90. package/dist/presentation/passage-clip.d.ts +17 -0
  91. package/dist/presentation/passage-clip.js +25 -0
  92. package/dist/presentation/passage-clip.js.map +7 -0
  93. package/dist/presentation/spotlight.d.ts +58 -0
  94. package/dist/presentation/spotlight.js +110 -0
  95. package/dist/presentation/spotlight.js.map +7 -0
  96. package/dist/presentation/store.d.ts +5 -0
  97. package/dist/presentation/store.js +19 -0
  98. package/dist/presentation/store.js.map +2 -2
  99. package/dist/presentation/usePointerActive.d.ts +2 -0
  100. package/dist/presentation/usePointerActive.js +28 -0
  101. package/dist/presentation/usePointerActive.js.map +7 -0
  102. package/dist/styles.css +1 -1
  103. package/dist/workflow-canvas/index.cjs +12 -12
  104. package/node_modules/@arbidocs/coedit/package.json +1 -1
  105. package/package.json +5 -5
  106. package/dist/ClippingMediaViewer-IEIBT74X.cjs.map +0 -1
  107. package/dist/ClippingPdfViewer-OGYLMVCE.cjs.map +0 -1
  108. package/dist/ConnectedPresentation-5DOJ35XL.cjs.map +0 -1
  109. package/dist/ConnectedSlidesTab-7YMEDGUU.cjs.map +0 -1
  110. package/dist/FilesViewerDialog-2QCCRWF2.cjs.map +0 -1
  111. package/dist/chunk-46P7IDBX.cjs.map +0 -1
  112. package/dist/chunk-4TTX6ZNS.cjs.map +0 -1
  113. package/dist/chunk-DWMWEALB.cjs.map +0 -1
  114. package/dist/chunk-JD2HX2BR.cjs.map +0 -1
  115. package/dist/chunk-WFMWKPGY.cjs.map +0 -1
  116. package/dist/chunk-XK4TVJKD.cjs +0 -73
  117. package/dist/chunk-XK4TVJKD.cjs.map +0 -1
@@ -1,12 +1,13 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
+ var chunkJY7UUZQG_cjs = require('./chunk-JY7UUZQG.cjs');
4
5
  var chunkWOOOMTTA_cjs = require('./chunk-WOOOMTTA.cjs');
5
- var chunk5GCCUXMT_cjs = require('./chunk-5GCCUXMT.cjs');
6
6
  var chunk2F57IO7S_cjs = require('./chunk-2F57IO7S.cjs');
7
7
  var chunkUFT22LAB_cjs = require('./chunk-UFT22LAB.cjs');
8
- var chunkWFMWKPGY_cjs = require('./chunk-WFMWKPGY.cjs');
9
- var chunk4TTX6ZNS_cjs = require('./chunk-4TTX6ZNS.cjs');
8
+ var chunkWVZLAAIZ_cjs = require('./chunk-WVZLAAIZ.cjs');
9
+ var chunkADPRIBSH_cjs = require('./chunk-ADPRIBSH.cjs');
10
+ var chunkORNLCBNE_cjs = require('./chunk-ORNLCBNE.cjs');
10
11
  var chunk7JLJH5CW_cjs = require('./chunk-7JLJH5CW.cjs');
11
12
  var chunkVZOOGA47_cjs = require('./chunk-VZOOGA47.cjs');
12
13
  var chunkTKHCIHE2_cjs = require('./chunk-TKHCIHE2.cjs');
@@ -15,234 +16,11 @@ var react = require('react');
15
16
  var lucideReact = require('lucide-react');
16
17
  var ui = require('@arbidocs/react/ui');
17
18
  var reactDom = require('react-dom');
18
- var viewers = require('@arbidocs/react/viewers');
19
19
  var jsxRuntime = require('react/jsx-runtime');
20
20
  var react$1 = require('@arbidocs/react');
21
21
  var documentTools = require('@arbidocs/react/document-tools');
22
+ var viewers = require('@arbidocs/react/viewers');
22
23
 
23
- function cropStyle(rect) {
24
- return {
25
- position: "absolute",
26
- width: `${100 / rect.w}%`,
27
- height: `${100 / rect.h}%`,
28
- left: `${-rect.x / rect.w * 100}%`,
29
- top: `${-rect.y / rect.h * 100}%`,
30
- maxWidth: "none"
31
- };
32
- }
33
- function MediaClip({
34
- clip,
35
- className,
36
- live
37
- }) {
38
- const url = chunkWOOOMTTA_cjs.useObjectUrl(clip.source);
39
- const videoRef = react.useRef(null);
40
- react.useEffect(() => {
41
- const video = videoRef.current;
42
- if (!video) return;
43
- const toStart = () => {
44
- video.currentTime = clip.start ?? 0;
45
- };
46
- if (video.readyState >= 1) toStart();
47
- else video.addEventListener("loadedmetadata", toStart, { once: true });
48
- return () => video.removeEventListener("loadedmetadata", toStart);
49
- }, [clip.start, url]);
50
- return /* @__PURE__ */ jsxRuntime.jsx(
51
- "div",
52
- {
53
- className: ui.cn("relative h-full w-full overflow-hidden bg-black", className),
54
- "data-testid": `clip-image-${clip.id}`,
55
- children: clip.kind === "video" ? /* @__PURE__ */ jsxRuntime.jsx(
56
- "video",
57
- {
58
- ref: videoRef,
59
- src: url,
60
- muted: !live,
61
- playsInline: true,
62
- preload: "auto",
63
- className: "pointer-events-none block select-none",
64
- style: cropStyle(clip.rect),
65
- ...live ? { [chunkWFMWKPGY_cjs.STAGE_VIDEO_ATTRIBUTE]: "" } : {}
66
- }
67
- ) : /* @__PURE__ */ jsxRuntime.jsx(
68
- "img",
69
- {
70
- src: url,
71
- alt: clip.caption,
72
- draggable: false,
73
- className: "pointer-events-none block select-none",
74
- style: cropStyle(clip.rect)
75
- }
76
- )
77
- }
78
- );
79
- }
80
- var WIDTH_STEP = 160;
81
- var SETTLE_MS = 150;
82
- var ClipImage = react.memo(function ClipImage2({
83
- clip,
84
- className,
85
- live = false
86
- }) {
87
- return clip.kind === "pdf" ? /* @__PURE__ */ jsxRuntime.jsx(PdfClip, { clip, className }) : /* @__PURE__ */ jsxRuntime.jsx(MediaClip, { clip, className, live });
88
- });
89
- var sameRect = (a, b) => a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
90
- function PdfClip({ clip, className }) {
91
- const canvasRef = react.useRef(null);
92
- const [size, setSize] = react.useState({ width: 0, height: 0 });
93
- const [rendered, setRendered] = react.useState(null);
94
- const [failed, setFailed] = react.useState(false);
95
- react.useEffect(() => {
96
- const canvas = canvasRef.current;
97
- const view = canvas?.ownerDocument.defaultView;
98
- if (!canvas || !view) return;
99
- const measure = () => {
100
- const box2 = canvas.getBoundingClientRect();
101
- const dpr = view.devicePixelRatio || 1;
102
- const width = Math.max(1, Math.round(box2.width * dpr));
103
- const height = Math.max(1, Math.round(box2.height * dpr));
104
- setSize((s) => s.width === width && s.height === height ? s : { width, height });
105
- };
106
- measure();
107
- const Observer = view.ResizeObserver ?? ResizeObserver;
108
- const observer = new Observer(measure);
109
- observer.observe(canvas);
110
- return () => observer.disconnect();
111
- }, []);
112
- react.useLayoutEffect(() => {
113
- const canvas = canvasRef.current;
114
- const context = canvas?.getContext("2d");
115
- if (!canvas || !context || !size.width) return;
116
- if (canvas.width !== size.width) canvas.width = size.width;
117
- if (canvas.height !== size.height) canvas.height = size.height;
118
- context.fillStyle = "#fff";
119
- context.fillRect(0, 0, size.width, size.height);
120
- if (!rendered) return;
121
- const { rect } = clip;
122
- const sx = size.width / rect.w;
123
- const sy = size.height / rect.h;
124
- try {
125
- context.drawImage(
126
- rendered.image,
127
- (rendered.rect.x - rect.x) * sx,
128
- (rendered.rect.y - rect.y) * sy,
129
- rendered.rect.w * sx,
130
- rendered.rect.h * sy
131
- );
132
- } catch {
133
- setRendered(null);
134
- }
135
- }, [size, rendered, clip]);
136
- const wanted = Math.ceil(size.width / WIDTH_STEP) * WIDTH_STEP;
137
- const stale = wanted > 0 && (!rendered || !sameRect(rendered.rect, clip.rect) || wanted > rendered.width || wanted < rendered.width / 2);
138
- react.useEffect(() => {
139
- if (!stale) return;
140
- const controller = new AbortController();
141
- const rect = clip.rect;
142
- const timer = setTimeout(() => {
143
- viewers.renderPdfRegion({
144
- file: clip.source,
145
- page: clip.page,
146
- rect,
147
- masks: clip.masks,
148
- width: wanted,
149
- signal: controller.signal
150
- }).then((image) => {
151
- if (controller.signal.aborted) return viewers.closePdfRegionImage(image);
152
- setFailed(false);
153
- setRendered({ image, rect, width: wanted });
154
- }).catch(() => !controller.signal.aborted && setFailed(true));
155
- }, SETTLE_MS);
156
- return () => {
157
- clearTimeout(timer);
158
- controller.abort();
159
- };
160
- }, [stale, wanted, clip.source, clip.page, clip.rect, clip.masks]);
161
- const previous = react.useRef(null);
162
- react.useEffect(() => {
163
- if (previous.current && previous.current !== rendered) {
164
- viewers.closePdfRegionImage(previous.current.image);
165
- }
166
- previous.current = rendered;
167
- }, [rendered]);
168
- return /* @__PURE__ */ jsxRuntime.jsxs(
169
- "div",
170
- {
171
- className: ui.cn("relative h-full w-full overflow-hidden bg-white", className),
172
- "data-testid": `clip-image-${clip.id}`,
173
- children: [
174
- /* @__PURE__ */ jsxRuntime.jsx(
175
- "canvas",
176
- {
177
- ref: canvasRef,
178
- className: "pointer-events-none block h-full w-full",
179
- role: "img",
180
- "aria-label": clip.caption,
181
- "aria-busy": !rendered
182
- }
183
- ),
184
- failed && !rendered && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center p-2 text-center text-xs text-neutral-500", children: "Couldn't draw this clip" })
185
- ]
186
- }
187
- );
188
- }
189
- var DRAG_THRESHOLD = 6;
190
- var DROP_ATTRIBUTE = "data-presentation-drop";
191
- function dropAt(doc, clipId, x, y) {
192
- const target = doc.elementFromPoint(x, y)?.closest(`[${DROP_ATTRIBUTE}]`);
193
- if (!target) return false;
194
- const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
195
- if (target.getAttribute(DROP_ATTRIBUTE) === "slide") {
196
- const index2 = Number(target.getAttribute("data-slide-index"));
197
- if (!Number.isInteger(index2)) return false;
198
- state.goTo(index2);
199
- state.place(clipId);
200
- return true;
201
- }
202
- const index = Number(target.getAttribute("data-slide-index"));
203
- if (target.hasAttribute("data-slide-index") && Number.isInteger(index)) state.goTo(index);
204
- const box2 = target.getBoundingClientRect();
205
- state.place(clipId, { x: (x - box2.left) / box2.width, y: (y - box2.top) / box2.height });
206
- return true;
207
- }
208
- function useClipDrag(clipId, onTap) {
209
- const press = react.useRef(null);
210
- const [ghost, setGhost] = react.useState(null);
211
- const end = () => {
212
- press.current = null;
213
- setGhost(null);
214
- chunk4TTX6ZNS_cjs.usePresentation.getState().setDragging(null);
215
- };
216
- return {
217
- ghost,
218
- handlers: {
219
- onPointerDown: (event) => {
220
- if (event.button !== 0) return;
221
- press.current = { x: event.clientX, y: event.clientY, dragging: false };
222
- },
223
- onPointerMove: (event) => {
224
- const p = press.current;
225
- if (!p) return;
226
- if (!p.dragging) {
227
- if (Math.hypot(event.clientX - p.x, event.clientY - p.y) < DRAG_THRESHOLD) return;
228
- p.dragging = true;
229
- event.currentTarget.setPointerCapture(event.pointerId);
230
- chunk4TTX6ZNS_cjs.usePresentation.getState().setDragging(clipId);
231
- }
232
- event.preventDefault();
233
- setGhost({ x: event.clientX, y: event.clientY });
234
- },
235
- onPointerUp: (event) => {
236
- const p = press.current;
237
- if (p?.dragging)
238
- dropAt(event.currentTarget.ownerDocument, clipId, event.clientX, event.clientY);
239
- else if (p) onTap();
240
- end();
241
- },
242
- onPointerCancel: end
243
- }
244
- };
245
- }
246
24
  var TILE_HEIGHT = 72;
247
25
  var TILE_WIDTH = { min: 56, max: 168 };
248
26
  function tileSize(aspect, height = TILE_HEIGHT) {
@@ -252,7 +30,7 @@ function tileSize(aspect, height = TILE_HEIGHT) {
252
30
  function Fitted({ clip, box: box2 }) {
253
31
  const wide = clip.aspect > box2.width / box2.height;
254
32
  const size = wide ? { width: box2.width, height: box2.width / clip.aspect } : { width: box2.height * clip.aspect, height: box2.height };
255
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none", style: size, children: /* @__PURE__ */ jsxRuntime.jsx(ClipImage, { clip }) });
33
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none", style: size, children: /* @__PURE__ */ jsxRuntime.jsx(chunkJY7UUZQG_cjs.ClipImage, { clip }) });
256
34
  }
257
35
  function Label({ clip }) {
258
36
  const [editing, setEditing] = react.useState(false);
@@ -265,7 +43,7 @@ function Label({ clip }) {
265
43
  "aria-label": "Clip label",
266
44
  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
45
  onBlur: (event) => {
268
- chunk4TTX6ZNS_cjs.usePresentation.getState().setCaption(clip.id, event.target.value);
46
+ chunkORNLCBNE_cjs.usePresentation.getState().setCaption(clip.id, event.target.value);
269
47
  setEditing(false);
270
48
  },
271
49
  onKeyDown: (event) => {
@@ -287,8 +65,8 @@ function Label({ clip }) {
287
65
  );
288
66
  }
289
67
  function TrayTile({ clip, onSlide }) {
290
- const { place, removeClip } = chunk4TTX6ZNS_cjs.usePresentation.getState();
291
- const drag = useClipDrag(clip.id, () => !onSlide && place(clip.id));
68
+ const { place, removeClip } = chunkORNLCBNE_cjs.usePresentation.getState();
69
+ const drag = chunkJY7UUZQG_cjs.useClipDrag(clip.id, () => !onSlide && place(clip.id));
292
70
  const itemRef = react.useRef(null);
293
71
  const size = tileSize(clip.aspect);
294
72
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -354,9 +132,9 @@ function TrayTile({ clip, onSlide }) {
354
132
  );
355
133
  }
356
134
  function ClipTray({ start }) {
357
- const all = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips);
135
+ const all = chunkORNLCBNE_cjs.usePresentation((s) => s.clips);
358
136
  const clips = react.useMemo(() => all.filter((clip) => !clip.plain), [all]);
359
- const slide = chunk4TTX6ZNS_cjs.usePresentation(chunk4TTX6ZNS_cjs.currentSlide);
137
+ const slide = chunkORNLCBNE_cjs.usePresentation(chunkORNLCBNE_cjs.currentSlide);
360
138
  const onSlide = new Set(slide?.items.map((item) => item.clipId));
361
139
  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
140
  "ul",
@@ -411,7 +189,7 @@ function CustomColor({
411
189
  "input",
412
190
  {
413
191
  type: "color",
414
- value: chunk4TTX6ZNS_cjs.isHexColor(value) ? value : "#1f2937",
192
+ value: chunkORNLCBNE_cjs.isHexColor(value) ? value : "#1f2937",
415
193
  onChange: (event) => onChange(event.target.value),
416
194
  "aria-label": label,
417
195
  className: "absolute inset-0 cursor-pointer opacity-0"
@@ -422,10 +200,10 @@ function CustomColor({
422
200
  );
423
201
  }
424
202
  function DesignMenu({ onChooseLogo }) {
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);
203
+ const theme = chunkORNLCBNE_cjs.usePresentation((s) => s.theme);
204
+ const setTheme = chunkORNLCBNE_cjs.usePresentation((s) => s.setTheme);
205
+ const customBackground = chunkORNLCBNE_cjs.isHexColor(theme.background);
206
+ const customAccent = !chunkORNLCBNE_cjs.ACCENTS.some((accent) => accent.color === theme.accent);
429
207
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
430
208
  /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
431
209
  ui.Button,
@@ -442,7 +220,7 @@ function DesignMenu({ onChooseLogo }) {
442
220
  ) }),
443
221
  /* @__PURE__ */ jsxRuntime.jsxs(ui.PopoverContent, { align: "end", className: "flex w-[21.5rem] flex-col gap-4 overflow-x-hidden p-4", children: [
444
222
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-7 gap-2", children: [
445
- chunk4TTX6ZNS_cjs.BACKGROUNDS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
223
+ chunkORNLCBNE_cjs.BACKGROUNDS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
446
224
  "button",
447
225
  {
448
226
  type: "button",
@@ -454,7 +232,7 @@ function DesignMenu({ onChooseLogo }) {
454
232
  "size-8 rounded-md border border-border shadow-sm",
455
233
  theme.background === preset.id && "ring-2 ring-primary ring-offset-1 ring-offset-background"
456
234
  ),
457
- style: { background: chunk4TTX6ZNS_cjs.backgroundCss(preset.id), containerType: "inline-size" },
235
+ style: { background: chunkORNLCBNE_cjs.backgroundCss(preset.id), containerType: "inline-size" },
458
236
  "data-testid": `design-background-${preset.id}`
459
237
  },
460
238
  preset.id
@@ -469,7 +247,7 @@ function DesignMenu({ onChooseLogo }) {
469
247
  }
470
248
  )
471
249
  ] }) }),
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(
250
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Typeface", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: Object.keys(chunkORNLCBNE_cjs.FONTS).map((font) => /* @__PURE__ */ jsxRuntime.jsxs(
473
251
  "button",
474
252
  {
475
253
  type: "button",
@@ -481,14 +259,14 @@ function DesignMenu({ onChooseLogo }) {
481
259
  ),
482
260
  "data-testid": `design-font-${font}`,
483
261
  children: [
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 })
262
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl leading-tight", style: { fontFamily: chunkORNLCBNE_cjs.FONTS[font].css }, children: "Aa" }),
263
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-muted-foreground", children: chunkORNLCBNE_cjs.FONTS[font].label })
486
264
  ]
487
265
  },
488
266
  font
489
267
  )) }) }),
490
268
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Accent", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
491
- chunk4TTX6ZNS_cjs.ACCENTS.map((accent) => /* @__PURE__ */ jsxRuntime.jsx(
269
+ chunkORNLCBNE_cjs.ACCENTS.map((accent) => /* @__PURE__ */ jsxRuntime.jsx(
492
270
  "button",
493
271
  {
494
272
  type: "button",
@@ -500,7 +278,7 @@ function DesignMenu({ onChooseLogo }) {
500
278
  "flex size-8 items-center justify-center rounded-full border border-black/10 shadow-sm",
501
279
  theme.accent === accent.color && "ring-2 ring-primary ring-offset-1 ring-offset-background"
502
280
  ),
503
- style: { background: chunk4TTX6ZNS_cjs.accentColor(accent.color) },
281
+ style: { background: chunkORNLCBNE_cjs.accentColor(accent.color) },
504
282
  children: theme.accent === accent.color && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5 text-black/70" })
505
283
  },
506
284
  accent.color
@@ -508,7 +286,7 @@ function DesignMenu({ onChooseLogo }) {
508
286
  /* @__PURE__ */ jsxRuntime.jsx(
509
287
  CustomColor,
510
288
  {
511
- value: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
289
+ value: chunkORNLCBNE_cjs.accentColor(theme.accent),
512
290
  selected: customAccent,
513
291
  label: "Your own accent colour",
514
292
  round: true,
@@ -571,13 +349,13 @@ var at = (box2) => ({
571
349
  height: `${box2.h * 100}%`
572
350
  });
573
351
  function LayoutThumb({ layout, className }) {
574
- const geometry = chunk4TTX6ZNS_cjs.slideGeometry({ layout, caption: "Title" }, { labels: false, logo: null });
352
+ const geometry = chunkORNLCBNE_cjs.slideGeometry({ layout, caption: "Title" }, { labels: false, logo: null });
575
353
  const { top, right = 0, bottom = 0, columns } = geometry.reserve;
576
354
  const room = {
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
355
+ x: chunkORNLCBNE_cjs.STAGE_MARGIN,
356
+ y: chunkORNLCBNE_cjs.STAGE_MARGIN + top,
357
+ w: 1 - 2 * chunkORNLCBNE_cjs.STAGE_MARGIN - right,
358
+ h: 1 - 2 * chunkORNLCBNE_cjs.STAGE_MARGIN - top - bottom
581
359
  };
582
360
  const blocks = layout === "title" || layout === "section" || layout === "free" ? [] : columns === 2 ? [
583
361
  { ...room, w: room.w / 2 - 0.02 },
@@ -628,10 +406,10 @@ function LayoutMenu({
628
406
  className,
629
407
  compact = false
630
408
  }) {
631
- const layout = chunk4TTX6ZNS_cjs.usePresentation(
632
- (s) => (index === void 0 ? chunk4TTX6ZNS_cjs.currentSlide(s) : s.slides[index])?.layout ?? "clips"
409
+ const layout = chunkORNLCBNE_cjs.usePresentation(
410
+ (s) => (index === void 0 ? chunkORNLCBNE_cjs.currentSlide(s) : s.slides[index])?.layout ?? "clips"
633
411
  );
634
- const setSlideLayout = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setSlideLayout);
412
+ const setSlideLayout = chunkORNLCBNE_cjs.usePresentation((s) => s.setSlideLayout);
635
413
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
636
414
  /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
637
415
  ui.Button,
@@ -644,7 +422,7 @@ function LayoutMenu({
644
422
  className
645
423
  ),
646
424
  title: "Slide layout",
647
- "aria-label": `Slide layout: ${chunk4TTX6ZNS_cjs.LAYOUT_INFO[layout].label}`,
425
+ "aria-label": `Slide layout: ${chunkORNLCBNE_cjs.LAYOUT_INFO[layout].label}`,
648
426
  "data-testid": "presentation-layout",
649
427
  children: [
650
428
  /* @__PURE__ */ jsxRuntime.jsx(LayoutThumb, { layout, className: compact ? "w-6" : "w-7" }),
@@ -652,7 +430,7 @@ function LayoutMenu({
652
430
  ]
653
431
  }
654
432
  ) }),
655
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuContent, { align: "start", className: "w-56", children: chunk4TTX6ZNS_cjs.SLIDE_LAYOUTS.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
433
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuContent, { align: "start", className: "w-56", children: chunkORNLCBNE_cjs.SLIDE_LAYOUTS.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
656
434
  ui.DropdownMenuItem,
657
435
  {
658
436
  onSelect: () => setSlideLayout(option, index),
@@ -660,7 +438,7 @@ function LayoutMenu({
660
438
  "data-testid": `presentation-layout-${option}`,
661
439
  children: [
662
440
  /* @__PURE__ */ jsxRuntime.jsx(LayoutThumb, { layout: option, className: "w-12" }),
663
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: chunk4TTX6ZNS_cjs.LAYOUT_INFO[option].label })
441
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: chunkORNLCBNE_cjs.LAYOUT_INFO[option].label })
664
442
  ]
665
443
  },
666
444
  option
@@ -668,11 +446,11 @@ function LayoutMenu({
668
446
  ] });
669
447
  }
670
448
  function Notice() {
671
- const notice = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notice);
449
+ const notice = chunkORNLCBNE_cjs.usePresentation((s) => s.notice);
672
450
  react.useEffect(() => {
673
451
  if (!notice) return;
674
452
  const timer = setTimeout(
675
- () => chunk4TTX6ZNS_cjs.usePresentation.getState().clearNotice(notice.id),
453
+ () => chunkORNLCBNE_cjs.usePresentation.getState().clearNotice(notice.id),
676
454
  notice.kind === "error" ? 8e3 : 3e3
677
455
  );
678
456
  return () => clearTimeout(timer);
@@ -693,7 +471,7 @@ function Notice() {
693
471
  type: "button",
694
472
  className: "ml-1 rounded p-0.5 text-muted-foreground hover:text-foreground",
695
473
  "aria-label": "Dismiss",
696
- onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().clearNotice(notice.id),
474
+ onClick: () => chunkORNLCBNE_cjs.usePresentation.getState().clearNotice(notice.id),
697
475
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" })
698
476
  }
699
477
  )
@@ -701,1274 +479,6 @@ function Notice() {
701
479
  }
702
480
  );
703
481
  }
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
- }
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";
831
- var SIZES = [
832
- { command: "fit", label: "Fit the slide", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "size-4" }) },
833
- { command: "fullWidth", label: "Full width", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoveHorizontal, { className: "size-4" }) },
834
- { command: "fullHeight", label: "Full height", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoveVertical, { className: "size-4" }) }
835
- ];
836
- var ALIGNMENTS = [
837
- { alignment: "left", label: "Left", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignStartVertical, { className: "size-4" }) },
838
- { alignment: "centre", label: "Centre", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenterVertical, { className: "size-4" }) },
839
- { alignment: "right", label: "Right", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignEndVertical, { className: "size-4" }) },
840
- { alignment: "top", label: "Top", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignStartHorizontal, { className: "size-4" }) },
841
- { alignment: "middle", label: "Middle", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenterHorizontal, { className: "size-4" }) },
842
- { alignment: "bottom", label: "Bottom", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignEndHorizontal, { className: "size-4" }) }
843
- ];
844
- function Action({
845
- label,
846
- onClick,
847
- children
848
- }) {
849
- return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: ACTION, title: label, "aria-label": label, onClick, children });
850
- }
851
- function ClipActionBar({
852
- clipId,
853
- at: at2,
854
- onRemoved,
855
- onEditImage,
856
- onCropImage
857
- }) {
858
- const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
859
- const clip = chunk4TTX6ZNS_cjs.usePresentation((state) => state.clips.find((entry) => entry.id === clipId));
860
- return /* @__PURE__ */ jsxRuntime.jsxs(
861
- "div",
862
- {
863
- role: "toolbar",
864
- "aria-label": "Clip",
865
- className: "absolute z-20 flex items-center gap-0.5 rounded-md border border-border bg-background p-0.5 shadow-md",
866
- style: { left: `${at2.x * 100}%`, top: `calc(${at2.y * 100}% - 40px)` },
867
- onPointerDown: (event) => event.stopPropagation(),
868
- "data-testid": "clip-action-bar",
869
- children: [
870
- /* @__PURE__ */ jsxRuntime.jsx(Action, { label: "Fit the slide", onClick: () => actions.applyFrame(clipId, "fit"), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "size-4" }) }),
871
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
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" }) }) }),
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: [
874
- icon,
875
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2", children: label })
876
- ] }, alignment)) })
877
- ] }),
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
- ] }),
928
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-0.5 h-5 w-px bg-border" }),
929
- /* @__PURE__ */ jsxRuntime.jsx(
930
- "button",
931
- {
932
- type: "button",
933
- className: ui.cn(ACTION, "text-destructive hover:bg-destructive/10"),
934
- title: "Remove from slide (Delete)",
935
- "aria-label": "Remove from slide",
936
- onClick: () => {
937
- actions.unplace(clipId);
938
- onRemoved();
939
- },
940
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-4" })
941
- }
942
- )
943
- ]
944
- }
945
- );
946
- }
947
- var boxStyle = (box2) => ({
948
- left: `${box2.x * 100}%`,
949
- top: `${box2.y * 100}%`,
950
- width: `${box2.w * 100}%`,
951
- height: `${box2.h * 100}%`
952
- });
953
- var textStyle = (box2, color) => ({
954
- ...boxStyle(box2),
955
- fontSize: `${box2.size * 100}cqw`,
956
- fontWeight: box2.weight,
957
- lineHeight: box2.leading,
958
- color,
959
- letterSpacing: box2.tone === "title" ? "-0.01em" : void 0
960
- });
961
- var PLACEHOLDER_COLOR = "rgba(255,255,255,0.32)";
962
- function Text({
963
- box: box2,
964
- lines,
965
- accent,
966
- placeholder,
967
- onEdit,
968
- testId
969
- }) {
970
- const empty = lines.length === 0;
971
- if (empty && !placeholder) return null;
972
- return /* @__PURE__ */ jsxRuntime.jsx(
973
- "div",
974
- {
975
- className: ui.cn(
976
- "absolute flex flex-col overflow-hidden",
977
- onEdit ? "pointer-events-auto cursor-text rounded-[0.3cqw] hover:outline hover:outline-1 hover:outline-white/25" : "pointer-events-none",
978
- box2.align === "center" && "text-center",
979
- box2.bullets && "gap-[0.6cqw]",
980
- box2.anchor === "middle" && "justify-center",
981
- box2.anchor === "bottom" && "justify-end"
982
- ),
983
- style: textStyle(box2, empty ? PLACEHOLDER_COLOR : chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone]),
984
- onPointerDown: onEdit ? (event) => event.stopPropagation() : void 0,
985
- onClick: onEdit,
986
- "data-testid": testId,
987
- children: (empty ? [placeholder] : lines).map(
988
- (line, index) => box2.bullets ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-[0.8em]", children: [
989
- /* @__PURE__ */ jsxRuntime.jsx(
990
- "span",
991
- {
992
- "aria-hidden": true,
993
- className: "inline-block size-[0.42em] shrink-0 -translate-y-[0.12em]",
994
- style: { background: empty ? "currentColor" : accent }
995
- }
996
- ),
997
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: line })
998
- ] }, index) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: line }, index)
999
- )
1000
- }
1001
- );
1002
- }
1003
- function TextField({
1004
- box: box2,
1005
- value,
1006
- placeholder,
1007
- multiline,
1008
- onChange,
1009
- onDone,
1010
- testId
1011
- }) {
1012
- return /* @__PURE__ */ jsxRuntime.jsx(
1013
- "textarea",
1014
- {
1015
- autoFocus: true,
1016
- value,
1017
- placeholder,
1018
- onChange: (event) => onChange(multiline ? event.target.value : event.target.value.replace(/\n/g, " ")),
1019
- onBlur: onDone,
1020
- onPointerDown: (event) => event.stopPropagation(),
1021
- onKeyDown: (event) => {
1022
- if (event.key === "Escape" || !multiline && event.key === "Enter") {
1023
- event.preventDefault();
1024
- event.currentTarget.blur();
1025
- }
1026
- },
1027
- className: ui.cn(
1028
- "pointer-events-auto absolute resize-none overflow-hidden rounded-[0.3cqw] bg-white/5 p-0 outline outline-1 outline-white/40 placeholder:text-white/30 focus:outline-white/60",
1029
- box2.align === "center" && "text-center"
1030
- ),
1031
- style: {
1032
- ...textStyle(box2, chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone]),
1033
- fontFamily: "inherit",
1034
- // Bulleted lines keep their indent while typed.
1035
- paddingLeft: box2.bullets ? "1.22em" : void 0
1036
- },
1037
- "aria-label": placeholder,
1038
- "data-testid": testId
1039
- }
1040
- );
1041
- }
1042
- function Logo({ image, box: box2 }) {
1043
- const url = chunkWOOOMTTA_cjs.useObjectUrl(image);
1044
- if (!url) return null;
1045
- return /* @__PURE__ */ jsxRuntime.jsx(
1046
- "img",
1047
- {
1048
- src: url,
1049
- alt: "",
1050
- className: "pointer-events-none absolute object-contain opacity-90",
1051
- style: { ...boxStyle(box2), objectPosition: box2.x < 0.5 ? "left bottom" : "right bottom" },
1052
- "data-testid": "stage-logo"
1053
- }
1054
- );
1055
- }
1056
- var SlideDecor = react.memo(function SlideDecor2({
1057
- slide,
1058
- theme,
1059
- labels,
1060
- logoImage,
1061
- editable,
1062
- editing,
1063
- dim
1064
- }) {
1065
- const [typing, setTyping] = react.useState(null);
1066
- const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, { labels, logo: theme.logo?.corner ?? null });
1067
- const title = slide.caption.trim();
1068
- const titled = slide.layout === "title" || slide.layout === "section";
1069
- const info = chunk4TTX6ZNS_cjs.LAYOUT_INFO[slide.layout];
1070
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("pointer-events-none absolute inset-0", dim && "opacity-30"), children: [
1071
- !geometry.title ? null : editing && typing === "title" ? /* @__PURE__ */ jsxRuntime.jsx(
1072
- TextField,
1073
- {
1074
- box: geometry.title,
1075
- value: slide.caption,
1076
- placeholder: "Title",
1077
- multiline: false,
1078
- onChange: editing.onTitle,
1079
- onDone: () => setTyping(null),
1080
- testId: "stage-slide-caption-input"
1081
- }
1082
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1083
- Text,
1084
- {
1085
- box: geometry.title,
1086
- lines: title ? [title] : [],
1087
- accent: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
1088
- placeholder: editable && (titled || editing) ? "Click to add a title" : void 0,
1089
- onEdit: editing ? () => setTyping("title") : void 0,
1090
- testId: "stage-slide-caption"
1091
- }
1092
- ),
1093
- geometry.rule && (title || editable && titled) && /* @__PURE__ */ jsxRuntime.jsx(
1094
- "div",
1095
- {
1096
- className: "absolute",
1097
- style: { ...boxStyle(geometry.rule), background: chunk4TTX6ZNS_cjs.accentColor(theme.accent) }
1098
- }
1099
- ),
1100
- geometry.text && (editing && typing === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
1101
- TextField,
1102
- {
1103
- box: geometry.text,
1104
- value: slide.points,
1105
- placeholder: info.text ?? "",
1106
- multiline: true,
1107
- onChange: editing.onPoints,
1108
- onDone: () => setTyping(null),
1109
- testId: "stage-slide-points-input"
1110
- }
1111
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1112
- Text,
1113
- {
1114
- box: geometry.text,
1115
- lines: chunk4TTX6ZNS_cjs.textLines(slide.points),
1116
- accent: chunk4TTX6ZNS_cjs.accentColor(theme.accent),
1117
- placeholder: editable ? info.text : void 0,
1118
- onEdit: editing ? () => setTyping("text") : void 0,
1119
- testId: "stage-slide-points"
1120
- }
1121
- )),
1122
- geometry.logo && logoImage && /* @__PURE__ */ jsxRuntime.jsx(Logo, { image: logoImage, box: geometry.logo })
1123
- ] });
1124
- });
1125
- var isEdge = (kind) => kind === "n" || kind === "e" || kind === "s" || kind === "w";
1126
- var EDGES = [
1127
- { edge: "n", left: "50%", top: "0%", cursor: "ns-resize", label: "top" },
1128
- { edge: "e", left: "100%", top: "50%", cursor: "ew-resize", label: "right" },
1129
- { edge: "s", left: "50%", top: "100%", cursor: "ns-resize", label: "bottom" },
1130
- { edge: "w", left: "0%", top: "50%", cursor: "ew-resize", label: "left" }
1131
- ];
1132
- var CORNERS = [
1133
- { corner: "nw", left: "0%", top: "0%", cursor: "nwse-resize" },
1134
- { corner: "ne", left: "100%", top: "0%", cursor: "nesw-resize" },
1135
- { corner: "sw", left: "0%", top: "100%", cursor: "nesw-resize" },
1136
- { corner: "se", left: "100%", top: "100%", cursor: "nwse-resize" }
1137
- ];
1138
- var EDGE_CSS = chunk4TTX6ZNS_cjs.clipEdgeCss();
1139
- var StageItem = react.memo(function StageItem2({
1140
- clip,
1141
- frame,
1142
- editable,
1143
- selected,
1144
- dim,
1145
- label,
1146
- host
1147
- }) {
1148
- const element = react.useRef(null);
1149
- const gesture = react.useRef(null);
1150
- const [reshape, setReshape] = react.useState(null);
1151
- const shown = reshape ? { ...clip, ...reshape.shape } : clip;
1152
- const box2 = reshape?.frame ?? frame;
1153
- const view = () => element.current?.ownerDocument.defaultView ?? window;
1154
- const apply = () => {
1155
- const g = gesture.current;
1156
- const el = element.current;
1157
- if (!g) return;
1158
- g.request = null;
1159
- const next = g.next;
1160
- if (!next || !el) return;
1161
- if (next.shape) {
1162
- setReshape({ frame: next.frame, shape: next.shape });
1163
- } else {
1164
- const dx = (next.frame.x - g.frame.x) * g.stage.width;
1165
- const dy = (next.frame.y - g.frame.y) * g.stage.height;
1166
- const scale = next.frame.w / g.frame.w;
1167
- el.style.transform = `translate3d(${dx}px, ${dy}px, 0) scale(${scale})`;
1168
- }
1169
- const key = next.guides.map((guide) => `${guide.axis}${guide.at}`).join();
1170
- if (key !== g.guidesKey) {
1171
- g.guidesKey = key;
1172
- host.guides(next.guides);
1173
- }
1174
- };
1175
- const start = (event, kind) => {
1176
- if (!editable || event.button !== 0) return;
1177
- const stage = host.stageBox();
1178
- if (!stage) return;
1179
- event.preventDefault();
1180
- event.stopPropagation();
1181
- host.select(clip.id);
1182
- event.currentTarget.setPointerCapture(event.pointerId);
1183
- gesture.current = {
1184
- kind,
1185
- pointer: { x: event.clientX, y: event.clientY },
1186
- frame,
1187
- shape: { rect: clip.rect, aspect: clip.aspect },
1188
- stage,
1189
- others: host.others(clip.id),
1190
- next: null,
1191
- request: null,
1192
- guidesKey: ""
1193
- };
1194
- };
1195
- const move = (event) => {
1196
- const g = gesture.current;
1197
- if (!g) return;
1198
- if (!g.next) {
1199
- host.dragging(true);
1200
- if (element.current) element.current.style.willChange = "transform";
1201
- }
1202
- const dx = (event.clientX - g.pointer.x) / g.stage.width;
1203
- const dy = (event.clientY - g.pointer.y) / g.stage.height;
1204
- const free = event.altKey;
1205
- if (isEdge(g.kind)) {
1206
- const result = chunk4TTX6ZNS_cjs.reshapeFrame(g.frame, g.shape, g.kind, dx, dy, g.others, free);
1207
- g.next = {
1208
- frame: result.frame,
1209
- shape: { rect: result.rect, aspect: result.aspect },
1210
- guides: result.guides
1211
- };
1212
- } else {
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);
1214
- }
1215
- g.request ??= view().requestAnimationFrame(apply);
1216
- };
1217
- const end = () => {
1218
- const g = gesture.current;
1219
- gesture.current = null;
1220
- if (!g) return;
1221
- if (g.request !== null) view().cancelAnimationFrame(g.request);
1222
- const el = element.current;
1223
- if (el) {
1224
- el.style.transform = "";
1225
- el.style.willChange = "";
1226
- }
1227
- if (!g.next) return;
1228
- setReshape(null);
1229
- host.dragging(false);
1230
- host.guides([]);
1231
- host.commit(clip.id, g.next.frame, g.next.shape);
1232
- };
1233
- return /* @__PURE__ */ jsxRuntime.jsxs(
1234
- "div",
1235
- {
1236
- ref: element,
1237
- className: ui.cn(
1238
- "absolute origin-top-left",
1239
- // Lifted off the background (a picture that is part of the slide's design is not).
1240
- !clip.plain && "rounded-[0.6cqw] shadow-[0_0.5cqw_1.6cqw_rgba(0,0,0,0.5)]",
1241
- editable && "cursor-move touch-none",
1242
- selected && "outline outline-2 outline-offset-2 outline-primary",
1243
- dim && "opacity-30"
1244
- ),
1245
- style: {
1246
- left: `${box2.x * 100}%`,
1247
- top: `${box2.y * 100}%`,
1248
- width: `${box2.w * 100}%`,
1249
- height: `${chunk4TTX6ZNS_cjs.frameHeight(box2, shown.aspect) * 100}%`
1250
- },
1251
- onPointerDown: (event) => start(event, "move"),
1252
- onPointerMove: move,
1253
- onPointerUp: end,
1254
- onPointerCancel: end,
1255
- "data-testid": `stage-item-${clip.id}`,
1256
- children: [
1257
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("absolute inset-0 overflow-hidden", !clip.plain && "rounded-[0.6cqw]"), children: [
1258
- /* @__PURE__ */ jsxRuntime.jsx(ClipImage, { clip: shown, live: !editable }),
1259
- clip.kind === "pdf" && !clip.plain && /* @__PURE__ */ jsxRuntime.jsx(
1260
- "div",
1261
- {
1262
- className: "pointer-events-none absolute inset-0",
1263
- style: { background: EDGE_CSS },
1264
- "data-testid": "stage-clip-edge"
1265
- }
1266
- ),
1267
- !clip.plain && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0 rounded-[0.6cqw] ring-1 ring-inset ring-white/15" })
1268
- ] }),
1269
- label && !clip.plain && // Under the clip, in the room the layout keeps (CAPTION_SPACE): never over it.
1270
- /* @__PURE__ */ jsxRuntime.jsx(
1271
- "div",
1272
- {
1273
- className: "pointer-events-none absolute left-0 top-full mt-[0.5cqw] max-w-full truncate text-[1.7cqw] leading-tight",
1274
- style: { color: chunk4TTX6ZNS_cjs.TEXT_COLORS.muted },
1275
- children: label
1276
- }
1277
- ),
1278
- selected && CORNERS.map(({ corner, left, top, cursor }) => /* @__PURE__ */ jsxRuntime.jsx(
1279
- "div",
1280
- {
1281
- className: "absolute flex size-6 -translate-x-1/2 -translate-y-1/2 items-center justify-center pointer-coarse:size-11",
1282
- style: { left, top, cursor, touchAction: "none" },
1283
- onPointerDown: (event) => start(event, corner),
1284
- "aria-label": `Resize from the ${corner} corner`,
1285
- "data-testid": `stage-item-resize-${corner}`,
1286
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none size-3 rounded-full border-2 border-primary bg-background" })
1287
- },
1288
- corner
1289
- )),
1290
- selected && EDGES.map(({ edge, left, top, cursor, label: side }) => /* @__PURE__ */ jsxRuntime.jsx(
1291
- "div",
1292
- {
1293
- className: "absolute flex size-6 -translate-x-1/2 -translate-y-1/2 items-center justify-center pointer-coarse:size-11",
1294
- style: { left, top, cursor, touchAction: "none" },
1295
- onPointerDown: (event) => start(event, edge),
1296
- "aria-label": `Show more or less at the ${side}`,
1297
- title: "Drag to show more or less of the page",
1298
- "data-testid": `stage-item-reshape-${edge}`,
1299
- children: /* @__PURE__ */ jsxRuntime.jsx(
1300
- "span",
1301
- {
1302
- className: ui.cn(
1303
- "pointer-events-none rounded-full border-2 border-primary bg-background",
1304
- edge === "n" || edge === "s" ? "h-2 w-4" : "h-4 w-2"
1305
- )
1306
- }
1307
- )
1308
- },
1309
- edge
1310
- ))
1311
- ]
1312
- }
1313
- );
1314
- });
1315
-
1316
- // src/presentation/box-style.ts
1317
- var cqw = (points) => `${chunk4TTX6ZNS_cjs.pointsToStage(points) * 100}cqw`;
1318
- function runStyle(run, font) {
1319
- return {
1320
- fontSize: cqw(run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE),
1321
- fontWeight: run.bold ? 700 : 400,
1322
- fontStyle: run.italic ? "italic" : void 0,
1323
- textDecoration: run.underline ? "underline" : void 0,
1324
- color: run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1325
- fontFamily: run.font ? `"${run.font}", ${font}` : font
1326
- };
1327
- }
1328
- var HANDLES = [
1329
- { handle: "nw", left: "0%", top: "0%", cursor: "nwse-resize" },
1330
- { handle: "n", left: "50%", top: "0%", cursor: "ns-resize" },
1331
- { handle: "ne", left: "100%", top: "0%", cursor: "nesw-resize" },
1332
- { handle: "e", left: "100%", top: "50%", cursor: "ew-resize" },
1333
- { handle: "se", left: "100%", top: "100%", cursor: "nwse-resize" },
1334
- { handle: "s", left: "50%", top: "100%", cursor: "ns-resize" },
1335
- { handle: "sw", left: "0%", top: "100%", cursor: "nesw-resize" },
1336
- { handle: "w", left: "0%", top: "50%", cursor: "ew-resize" }
1337
- ];
1338
- var withAlpha = (hex3, alpha = 1) => {
1339
- if (alpha >= 1) return hex3;
1340
- const n = parseInt(hex3.slice(1), 16);
1341
- return `rgba(${n >> 16 & 255}, ${n >> 8 & 255}, ${n & 255}, ${alpha})`;
1342
- };
1343
- function shapeStyle(box2) {
1344
- const { frame } = box2;
1345
- const line = box2.line;
1346
- const shorter = Math.min(frame.w, frame.h * 1 / chunk4TTX6ZNS_cjs.STAGE_ASPECT);
1347
- return {
1348
- background: box2.fill && box2.shape !== "line" ? withAlpha(box2.fill, box2.fillAlpha) : void 0,
1349
- border: line && box2.shape !== "line" ? `${cqw(line.width)} ${line.dash ? "dashed" : "solid"} ${line.color}` : void 0,
1350
- borderRadius: box2.shape === "ellipse" ? "50%" : box2.shape === "roundRect" ? `${shorter * 16.67}cqw` : void 0
1351
- };
1352
- }
1353
- function Paragraphs({
1354
- paragraphs,
1355
- font
1356
- }) {
1357
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: paragraphs.map((paragraph, index) => {
1358
- const first = paragraph.runs[0];
1359
- const size = first?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE;
1360
- const indent = (paragraph.level ?? 0) * 0.5 * size;
1361
- const empty = !paragraph.runs.some((run) => run.text);
1362
- return /* @__PURE__ */ jsxRuntime.jsxs(
1363
- "div",
1364
- {
1365
- className: "whitespace-pre-wrap break-words",
1366
- style: {
1367
- textAlign: paragraph.align ?? "left",
1368
- lineHeight: 1.2,
1369
- paddingLeft: cqw(indent + (paragraph.bullet ? size * 0.9 : 0)),
1370
- textIndent: paragraph.bullet ? cqw(-size * 0.9) : void 0,
1371
- // An empty line keeps its height.
1372
- fontSize: cqw(size)
1373
- },
1374
- children: [
1375
- paragraph.bullet && /* @__PURE__ */ jsxRuntime.jsx(
1376
- "span",
1377
- {
1378
- style: {
1379
- ...runStyle(first ?? { }, font),
1380
- display: "inline-block",
1381
- width: cqw(size * 0.9),
1382
- textIndent: 0
1383
- },
1384
- children: "\u2022"
1385
- }
1386
- ),
1387
- empty ? "\u200B" : paragraph.runs.map((run, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: runStyle(run, font), children: run.text }, i))
1388
- ]
1389
- },
1390
- index
1391
- );
1392
- }) });
1393
- }
1394
- var StageBox = react.memo(function StageBox2({
1395
- box: box2,
1396
- font,
1397
- editable,
1398
- selected,
1399
- host
1400
- }) {
1401
- const element = react.useRef(null);
1402
- const gesture = react.useRef(null);
1403
- const [typing, setTyping] = react.useState(false);
1404
- const [dragging, setDragging] = react.useState(false);
1405
- const { frame } = box2;
1406
- const view = () => element.current?.ownerDocument.defaultView ?? window;
1407
- const apply = () => {
1408
- const g = gesture.current;
1409
- const el = element.current;
1410
- if (!g || !el) return;
1411
- g.request = null;
1412
- if (!g.next) return;
1413
- if (g.handle === "move") {
1414
- el.style.translate = `${(g.next.x - g.frame.x) * g.stage.width}px ${(g.next.y - g.frame.y) * g.stage.height}px`;
1415
- } else {
1416
- el.style.left = `${g.next.x * 100}%`;
1417
- el.style.top = `${g.next.y * 100}%`;
1418
- el.style.width = `${g.next.w * 100}%`;
1419
- el.style.height = `${g.next.h * 100}%`;
1420
- }
1421
- };
1422
- const start = (event, handle) => {
1423
- if (!editable || typing || event.button !== 0) return;
1424
- const stage = host.stageBox();
1425
- if (!stage) return;
1426
- event.preventDefault();
1427
- event.stopPropagation();
1428
- host.select(box2.id);
1429
- event.currentTarget.setPointerCapture(event.pointerId);
1430
- gesture.current = {
1431
- handle,
1432
- pointer: { x: event.clientX, y: event.clientY },
1433
- frame,
1434
- stage,
1435
- next: null,
1436
- request: null,
1437
- wasSelected: selected
1438
- };
1439
- };
1440
- const move = (event) => {
1441
- const g = gesture.current;
1442
- if (!g) return;
1443
- const dx = (event.clientX - g.pointer.x) / g.stage.width;
1444
- const dy = (event.clientY - g.pointer.y) / g.stage.height;
1445
- if (!g.next) setDragging(true);
1446
- g.next = g.handle === "move" ? chunk4TTX6ZNS_cjs.moveBox(g.frame, dx, dy) : chunk4TTX6ZNS_cjs.stretchBox(g.frame, g.handle, dx, dy);
1447
- g.request ??= view().requestAnimationFrame(apply);
1448
- };
1449
- const end = () => {
1450
- const g = gesture.current;
1451
- gesture.current = null;
1452
- if (!g) return;
1453
- if (g.request !== null) view().cancelAnimationFrame(g.request);
1454
- if (!g.next) {
1455
- if (g.wasSelected && g.handle === "move" && hasText) setTyping(true);
1456
- return;
1457
- }
1458
- const el = element.current;
1459
- if (el) {
1460
- el.style.translate = "";
1461
- el.style.left = `${g.frame.x * 100}%`;
1462
- el.style.top = `${g.frame.y * 100}%`;
1463
- el.style.width = `${g.frame.w * 100}%`;
1464
- el.style.height = `${g.frame.h * 100}%`;
1465
- }
1466
- setDragging(false);
1467
- host.commit(box2.id, g.next);
1468
- };
1469
- const hasText = box2.shape !== "line";
1470
- const inset = cqw(box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET);
1471
- const run = chunk4TTX6ZNS_cjs.firstRun(box2);
1472
- const transform = box2.rotation ? `rotate(${box2.rotation}deg)` : void 0;
1473
- return /* @__PURE__ */ jsxRuntime.jsxs(
1474
- "div",
1475
- {
1476
- ref: element,
1477
- className: ui.cn(
1478
- "absolute",
1479
- editable ? "pointer-events-auto" : "pointer-events-none",
1480
- editable && !typing && "cursor-move touch-none",
1481
- editable && !selected && "hover:outline hover:outline-1 hover:outline-white/30",
1482
- selected && "outline outline-2 outline-offset-1 outline-primary"
1483
- ),
1484
- style: {
1485
- left: `${frame.x * 100}%`,
1486
- top: `${frame.y * 100}%`,
1487
- width: `${frame.w * 100}%`,
1488
- height: `${frame.h * 100}%`,
1489
- transform,
1490
- willChange: dragging ? "translate" : void 0
1491
- },
1492
- onPointerDown: (event) => start(event, "move"),
1493
- onPointerMove: move,
1494
- onPointerUp: end,
1495
- onPointerCancel: end,
1496
- onDoubleClick: () => editable && hasText && setTyping(true),
1497
- onKeyDown: (event) => {
1498
- if (selected && !typing && event.key === "Enter" && hasText) {
1499
- event.preventDefault();
1500
- setTyping(true);
1501
- }
1502
- },
1503
- tabIndex: editable ? 0 : void 0,
1504
- "data-testid": `stage-box-${box2.id}`,
1505
- children: [
1506
- box2.shape === "line" ? /* @__PURE__ */ jsxRuntime.jsx(
1507
- "svg",
1508
- {
1509
- className: "absolute inset-0 size-full overflow-visible",
1510
- preserveAspectRatio: "none",
1511
- "aria-hidden": true,
1512
- children: /* @__PURE__ */ jsxRuntime.jsx(
1513
- "line",
1514
- {
1515
- x1: "0%",
1516
- y1: box2.flipV ? "100%" : "0%",
1517
- x2: "100%",
1518
- y2: box2.flipV ? "0%" : "100%",
1519
- stroke: box2.line?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1520
- style: { strokeWidth: cqw(box2.line?.width ?? 1) },
1521
- strokeDasharray: box2.line?.dash ? "6 4" : void 0
1522
- }
1523
- )
1524
- }
1525
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1526
- "div",
1527
- {
1528
- className: ui.cn(
1529
- "absolute inset-0 box-border flex flex-col overflow-hidden",
1530
- box2.anchor === "middle" && "justify-center",
1531
- box2.anchor === "bottom" && "justify-end"
1532
- ),
1533
- style: { ...shapeStyle(box2), padding: inset },
1534
- children: typing ? /* @__PURE__ */ jsxRuntime.jsx(
1535
- "textarea",
1536
- {
1537
- autoFocus: true,
1538
- defaultValue: chunk4TTX6ZNS_cjs.boxText(box2),
1539
- className: "pointer-events-auto w-full flex-1 resize-none bg-transparent p-0 outline-none",
1540
- style: {
1541
- ...runStyle(run ?? { }, font),
1542
- lineHeight: 1.2,
1543
- textAlign: box2.paragraphs[0]?.align ?? "left"
1544
- },
1545
- onPointerDown: (event) => event.stopPropagation(),
1546
- onBlur: (event) => {
1547
- host.setText(box2.id, event.currentTarget.value);
1548
- setTyping(false);
1549
- },
1550
- onKeyDown: (event) => {
1551
- event.stopPropagation();
1552
- if (event.key === "Escape") event.currentTarget.blur();
1553
- },
1554
- "aria-label": "Text",
1555
- "data-testid": "stage-box-text-input"
1556
- }
1557
- ) : chunk4TTX6ZNS_cjs.boxText(box2) || !editable ? /* @__PURE__ */ jsxRuntime.jsx(Paragraphs, { paragraphs: box2.paragraphs, font }) : box2.shape === "text" && /* @__PURE__ */ jsxRuntime.jsx(
1558
- "span",
1559
- {
1560
- className: "text-white/40",
1561
- style: { fontSize: cqw(run?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) },
1562
- children: "Double-click to type"
1563
- }
1564
- )
1565
- }
1566
- ),
1567
- selected && !typing && !dragging && HANDLES.filter(
1568
- ({ handle }) => box2.shape !== "line" || handle === "e" || handle === "w" || handle === "n" || handle === "s"
1569
- ).map(({ handle, left, top, cursor }) => /* @__PURE__ */ jsxRuntime.jsx(
1570
- "div",
1571
- {
1572
- className: "absolute flex size-5 -translate-x-1/2 -translate-y-1/2 items-center justify-center pointer-coarse:size-11",
1573
- style: { left, top, cursor, touchAction: "none" },
1574
- onPointerDown: (event) => start(event, handle),
1575
- "aria-label": `Resize from ${handle}`,
1576
- "data-testid": `stage-box-resize-${handle}`,
1577
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none size-2.5 rounded-full border-2 border-primary bg-background" })
1578
- },
1579
- handle
1580
- ))
1581
- ]
1582
- }
1583
- );
1584
- });
1585
- var SIZE_STEPS = [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 44, 54, 66, 80, 96];
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;
1587
- var ALIGN_ICON = {
1588
- left: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { className: "size-4" }),
1589
- center: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenter, { className: "size-4" }),
1590
- right: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignRight, { className: "size-4" }),
1591
- justify: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { className: "size-4" })
1592
- };
1593
- function ColorAction({
1594
- label,
1595
- value,
1596
- onChange,
1597
- children
1598
- }) {
1599
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: ui.cn(ACTION, "relative cursor-pointer"), title: label, "aria-label": label, children: [
1600
- children,
1601
- /* @__PURE__ */ jsxRuntime.jsx(
1602
- "span",
1603
- {
1604
- className: "pointer-events-none absolute inset-x-1.5 bottom-0.5 h-0.5 rounded-full",
1605
- style: { background: value }
1606
- }
1607
- ),
1608
- /* @__PURE__ */ jsxRuntime.jsx(
1609
- "input",
1610
- {
1611
- type: "color",
1612
- value,
1613
- onChange: (event) => onChange(event.target.value),
1614
- className: "absolute inset-0 size-full cursor-pointer opacity-0",
1615
- "aria-label": label
1616
- }
1617
- )
1618
- ] });
1619
- }
1620
- function BoxActionBar({ box: box2, onRemoved }) {
1621
- const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
1622
- const run = chunk4TTX6ZNS_cjs.firstRun(box2);
1623
- const size = run?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE;
1624
- const align = box2.paragraphs[0]?.align ?? "left";
1625
- const update = (change) => actions.updateBox(box2.id, change);
1626
- const text = box2.shape !== "line";
1627
- const top = Math.max(0, box2.frame.y);
1628
- return /* @__PURE__ */ jsxRuntime.jsxs(
1629
- "div",
1630
- {
1631
- role: "toolbar",
1632
- "aria-label": "Text box",
1633
- className: "absolute z-20 flex items-center gap-0.5 rounded-md border border-border bg-background p-0.5 shadow-md",
1634
- style: {
1635
- left: `${Math.min(Math.max(0, box2.frame.x), 0.6) * 100}%`,
1636
- top: `calc(${top * 100}% - 40px)`
1637
- },
1638
- onPointerDown: (event) => event.stopPropagation(),
1639
- "data-testid": "box-action-bar",
1640
- children: [
1641
- text && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1642
- /* @__PURE__ */ jsxRuntime.jsx(
1643
- Action,
1644
- {
1645
- label: "Smaller",
1646
- onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, false) }))),
1647
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AArrowDown, { className: "size-4" })
1648
- }
1649
- ),
1650
- /* @__PURE__ */ jsxRuntime.jsx(
1651
- "span",
1652
- {
1653
- className: "w-7 text-center text-xs tabular-nums text-muted-foreground",
1654
- "data-testid": "box-text-size",
1655
- children: Math.round(size)
1656
- }
1657
- ),
1658
- /* @__PURE__ */ jsxRuntime.jsx(
1659
- Action,
1660
- {
1661
- label: "Larger",
1662
- onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, size: nextSize(r.size ?? size, true) }))),
1663
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AArrowUp, { className: "size-4" })
1664
- }
1665
- ),
1666
- /* @__PURE__ */ jsxRuntime.jsx(
1667
- Action,
1668
- {
1669
- label: "Bold",
1670
- onClick: () => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, bold: !run?.bold }))),
1671
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { className: ui.cn("size-4", run?.bold && "text-primary") })
1672
- }
1673
- ),
1674
- /* @__PURE__ */ jsxRuntime.jsx(
1675
- ColorAction,
1676
- {
1677
- label: "Text colour",
1678
- value: run?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body,
1679
- onChange: (color) => update((b) => chunk4TTX6ZNS_cjs.styleRuns(b, (r) => ({ ...r, color }))),
1680
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Baseline, { className: "size-4" })
1681
- }
1682
- )
1683
- ] }),
1684
- /* @__PURE__ */ jsxRuntime.jsx(
1685
- ColorAction,
1686
- {
1687
- label: box2.shape === "line" ? "Line colour" : "Fill",
1688
- value: (box2.shape === "line" ? box2.line?.color : box2.fill) ?? "#ffffff",
1689
- onChange: (color) => update(
1690
- (b) => b.shape === "line" ? { ...b, line: { width: b.line?.width ?? 2, ...b.line, color } } : { ...b, fill: color, shape: b.shape === "text" ? "rect" : b.shape }
1691
- ),
1692
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaintBucket, { className: "size-4" })
1693
- }
1694
- ),
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
- ] }),
1747
- /* @__PURE__ */ jsxRuntime.jsx(
1748
- "button",
1749
- {
1750
- type: "button",
1751
- className: ui.cn(ACTION, "text-destructive hover:bg-destructive/10"),
1752
- title: "Delete (Delete)",
1753
- "aria-label": "Delete",
1754
- onClick: () => {
1755
- actions.removeBox(box2.id);
1756
- onRemoved();
1757
- },
1758
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-4" })
1759
- }
1760
- )
1761
- ]
1762
- }
1763
- );
1764
- }
1765
- var GuideLayer = react.memo(
1766
- react.forwardRef(function GuideLayer2(_, ref) {
1767
- const [guides, setGuides] = react.useState([]);
1768
- react.useImperativeHandle(ref, () => ({ set: setGuides }), []);
1769
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: guides.map((guide) => /* @__PURE__ */ jsxRuntime.jsx(
1770
- "div",
1771
- {
1772
- className: "pointer-events-none absolute z-10 bg-primary",
1773
- style: guide.axis === "x" ? { left: `${guide.at * 100}%`, top: 0, bottom: 0, width: 1 } : { top: `${guide.at * 100}%`, left: 0, right: 0, height: 1 },
1774
- "data-testid": `stage-guide-${guide.axis}`
1775
- },
1776
- `${guide.axis}-${guide.at}`
1777
- )) });
1778
- })
1779
- );
1780
- function PresentationStage({
1781
- editable = false,
1782
- slideIndex,
1783
- selected = null,
1784
- onSelect,
1785
- onEditImage,
1786
- onCropImage,
1787
- textEditing,
1788
- overlay,
1789
- className
1790
- }) {
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);
1800
- const stageRef = react.useRef(null);
1801
- const guideLayer = react.useRef(null);
1802
- const dropping = chunk4TTX6ZNS_cjs.usePresentation((s) => editable && s.dragging !== null);
1803
- const [dragging, setDragging] = react.useState(false);
1804
- const latest = react.useRef({ slide, clips, index, onSelect });
1805
- latest.current = { slide, clips, index, onSelect };
1806
- const host = react.useMemo(
1807
- () => ({
1808
- stageBox: () => stageRef.current?.getBoundingClientRect() ?? null,
1809
- others: (clipId) => {
1810
- const { slide: current2, clips: all } = latest.current;
1811
- return (current2?.items ?? []).filter((item) => item.clipId !== clipId).map((item) => ({
1812
- frame: item.frame,
1813
- aspect: all.find((clip) => clip.id === item.clipId)?.aspect ?? 1
1814
- }));
1815
- },
1816
- select: (clipId) => {
1817
- chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(latest.current.index);
1818
- latest.current.onSelect?.(clipId);
1819
- },
1820
- guides: (guides) => guideLayer.current?.set(guides),
1821
- dragging: setDragging,
1822
- commit: (clipId, frame, shape) => {
1823
- const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
1824
- state.goTo(latest.current.index);
1825
- if (shape) state.reshapeClip(clipId, frame, shape.rect, shape.aspect);
1826
- else state.setFrame(clipId, frame);
1827
- }
1828
- }),
1829
- []
1830
- );
1831
- const boxHost = react.useMemo(
1832
- () => ({
1833
- stageBox: () => stageRef.current?.getBoundingClientRect() ?? null,
1834
- select: (boxId) => {
1835
- chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(latest.current.index);
1836
- latest.current.onSelect?.(boxId);
1837
- },
1838
- commit: (boxId, frame) => chunk4TTX6ZNS_cjs.usePresentation.getState().updateBox(boxId, (box2) => ({ ...box2, frame })),
1839
- setText: (boxId, text) => chunk4TTX6ZNS_cjs.usePresentation.getState().setBoxText(boxId, text)
1840
- }),
1841
- []
1842
- );
1843
- const font = chunk4TTX6ZNS_cjs.FONTS[theme.font].css;
1844
- const boxes = slide?.boxes ?? [];
1845
- const selectedBox = selected ? boxes.find((box2) => box2.id === selected) : void 0;
1846
- const renderBoxes = (front) => boxes.filter((box2) => !!box2.front === front).map((box2) => /* @__PURE__ */ jsxRuntime.jsx(
1847
- StageBox,
1848
- {
1849
- box: box2,
1850
- font,
1851
- editable,
1852
- selected: editable && selected === box2.id,
1853
- host: boxHost
1854
- },
1855
- box2.id
1856
- ));
1857
- const clipOf = (id) => clips.find((clip) => clip.id === id);
1858
- const selectedFrame = selected ? slide?.items.find((item) => item.clipId === selected)?.frame : void 0;
1859
- react.useEffect(() => {
1860
- const stage = stageRef.current;
1861
- const view = stage?.ownerDocument.defaultView;
1862
- if (!editable || !selected || !stage || !view) return;
1863
- let sum = { x: 0, y: 0 };
1864
- let request = null;
1865
- const onWheel = (event) => {
1866
- const item = event.target?.closest?.(
1867
- `[data-testid="stage-item-${selected}"]`
1868
- );
1869
- const clip = chunk4TTX6ZNS_cjs.usePresentation.getState().clips.find((entry) => entry.id === selected);
1870
- if (!item || !clip) return;
1871
- event.preventDefault();
1872
- const box2 = item.getBoundingClientRect();
1873
- const horizontal = event.shiftKey && !event.deltaX;
1874
- const deltaX = horizontal ? event.deltaY : event.deltaX;
1875
- const deltaY = horizontal ? 0 : event.deltaY;
1876
- sum = {
1877
- x: sum.x + deltaX / box2.width * clip.rect.w,
1878
- y: sum.y + deltaY / box2.height * clip.rect.h
1879
- };
1880
- request ??= view.requestAnimationFrame(() => {
1881
- request = null;
1882
- chunk4TTX6ZNS_cjs.usePresentation.getState().panClip(selected, sum.x, sum.y);
1883
- sum = { x: 0, y: 0 };
1884
- });
1885
- };
1886
- stage.addEventListener("wheel", onWheel, { passive: false });
1887
- return () => {
1888
- stage.removeEventListener("wheel", onWheel);
1889
- if (request !== null) view.cancelAnimationFrame(request);
1890
- };
1891
- }, [editable, selected]);
1892
- return /* @__PURE__ */ jsxRuntime.jsx(
1893
- "div",
1894
- {
1895
- className: ui.cn("relative h-full w-full", !editable && "overflow-hidden bg-black", className),
1896
- style: { containerType: "size" },
1897
- "data-testid": editable ? "presentation-stage-editor" : "presentation-stage",
1898
- children: /* @__PURE__ */ jsxRuntime.jsxs(
1899
- "div",
1900
- {
1901
- ref: stageRef,
1902
- className: ui.cn(
1903
- "absolute inset-0 m-auto",
1904
- editable ? "shadow-md" : "overflow-hidden",
1905
- dropping && "outline outline-2 outline-offset-2 outline-primary"
1906
- ),
1907
- style: {
1908
- width: "min(100cqw, calc(100cqh * 16 / 9))",
1909
- height: "min(100cqh, calc(100cqw * 9 / 16))",
1910
- containerType: "inline-size",
1911
- background: slide?.background ? chunk4TTX6ZNS_cjs.slideBackgroundCss(slide.background, media) : chunk4TTX6ZNS_cjs.backgroundCss(theme.background),
1912
- fontFamily: chunk4TTX6ZNS_cjs.FONTS[theme.font].css
1913
- },
1914
- onPointerDown: () => {
1915
- if (!editable) return;
1916
- chunk4TTX6ZNS_cjs.usePresentation.getState().goTo(index);
1917
- onSelect?.(null);
1918
- },
1919
- ...editable ? { [DROP_ATTRIBUTE]: "stage", "data-slide-index": index } : {},
1920
- "aria-label": `Slide ${index + 1}`,
1921
- children: [
1922
- blank && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-20 bg-black" }),
1923
- slide && /* @__PURE__ */ jsxRuntime.jsx(
1924
- SlideDecor,
1925
- {
1926
- slide,
1927
- theme,
1928
- labels: captions,
1929
- logoImage,
1930
- editable,
1931
- editing: textEditing
1932
- }
1933
- ),
1934
- renderBoxes(false),
1935
- slide?.items.map((item) => {
1936
- const clip = clipOf(item.clipId);
1937
- if (!clip) return null;
1938
- return /* @__PURE__ */ jsxRuntime.jsx(
1939
- StageItem,
1940
- {
1941
- clip,
1942
- frame: item.frame,
1943
- editable,
1944
- selected: editable && selected === clip.id,
1945
- dim: false,
1946
- label: captions ? chunk4TTX6ZNS_cjs.clipLabel(clip, columnValues) : "",
1947
- host
1948
- },
1949
- clip.id
1950
- );
1951
- }),
1952
- renderBoxes(true),
1953
- editable && /* @__PURE__ */ jsxRuntime.jsx(GuideLayer, { ref: guideLayer }),
1954
- editable && selectedFrame && selected && !dragging && /* @__PURE__ */ jsxRuntime.jsx(
1955
- ClipActionBar,
1956
- {
1957
- clipId: selected,
1958
- at: selectedFrame,
1959
- onRemoved: () => onSelect?.(null),
1960
- onEditImage: onEditImage && clipOf(selected)?.kind === "image" ? () => onEditImage(selected) : void 0,
1961
- onCropImage: onCropImage && clipOf(selected)?.kind === "image" ? () => onCropImage(selected) : void 0
1962
- }
1963
- ),
1964
- editable && selectedBox && /* @__PURE__ */ jsxRuntime.jsx(BoxActionBar, { box: selectedBox, onRemoved: () => onSelect?.(null) }),
1965
- overlay
1966
- ]
1967
- }
1968
- )
1969
- }
1970
- );
1971
- }
1972
482
  var SlideCard = react.memo(function SlideCard2({
1973
483
  index,
1974
484
  count,
@@ -1978,20 +488,20 @@ var SlideCard = react.memo(function SlideCard2({
1978
488
  onEditImage,
1979
489
  onCropImage
1980
490
  }) {
1981
- const empty = chunk4TTX6ZNS_cjs.usePresentation((s) => {
491
+ const empty = chunkORNLCBNE_cjs.usePresentation((s) => {
1982
492
  const slide = s.slides[index];
1983
493
  return !!slide && !slide.items.length && !slide.boxes.length && !slide.points.trim() && slide.layout !== "title" && slide.layout !== "section";
1984
494
  });
1985
- const notes = chunk4TTX6ZNS_cjs.usePresentation((s) => s.slides[index]?.notes ?? "");
495
+ const notes = chunkORNLCBNE_cjs.usePresentation((s) => s.slides[index]?.notes ?? "");
1986
496
  const textEditing = react.useMemo(
1987
497
  () => ({
1988
- onTitle: (title) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlideCaption(title, index),
1989
- onPoints: (points) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlidePoints(points, index)
498
+ onTitle: (title) => chunkORNLCBNE_cjs.usePresentation.getState().setSlideCaption(title, index),
499
+ onPoints: (points) => chunkORNLCBNE_cjs.usePresentation.getState().setSlidePoints(points, index)
1990
500
  }),
1991
501
  [index]
1992
502
  );
1993
503
  const select = react.useCallback((clipId) => onSelect(index, clipId), [onSelect, index]);
1994
- const actions = chunk4TTX6ZNS_cjs.usePresentation.getState();
504
+ const actions = chunkORNLCBNE_cjs.usePresentation.getState();
1995
505
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative flex gap-2", "data-testid": `slide-${index}`, children: [
1996
506
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-9 shrink-0 flex-col items-center gap-0.5", children: [
1997
507
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2083,7 +593,7 @@ var SlideCard = react.memo(function SlideCard2({
2083
593
  ),
2084
594
  children: [
2085
595
  /* @__PURE__ */ jsxRuntime.jsx(
2086
- PresentationStage,
596
+ chunkJY7UUZQG_cjs.PresentationStage,
2087
597
  {
2088
598
  editable: true,
2089
599
  slideIndex: index,
@@ -2101,7 +611,7 @@ var SlideCard = react.memo(function SlideCard2({
2101
611
  value: notes,
2102
612
  rows: notes.split("\n").length,
2103
613
  placeholder: "Speaker notes",
2104
- onChange: (event) => chunk4TTX6ZNS_cjs.usePresentation.getState().setSlideNotes(event.target.value, index),
614
+ onChange: (event) => chunkORNLCBNE_cjs.usePresentation.getState().setSlideNotes(event.target.value, index),
2105
615
  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",
2106
616
  "aria-label": `Speaker notes for slide ${index + 1}`,
2107
617
  "data-testid": `slide-notes-${index}`
@@ -2125,10 +635,10 @@ var INSERTS = [
2125
635
  ];
2126
636
  function InsertMenu({ onInserted }) {
2127
637
  const insert = (shape) => {
2128
- const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
638
+ const state = chunkORNLCBNE_cjs.usePresentation.getState();
2129
639
  const slide = state.slides[state.current];
2130
- const box2 = chunk4TTX6ZNS_cjs.newBox(shape, chunk4TTX6ZNS_cjs.accentColor(state.theme.accent));
2131
- const dark = chunk4TTX6ZNS_cjs.isLightBackground(slide?.background);
640
+ const box2 = chunkORNLCBNE_cjs.newBox(shape, chunkORNLCBNE_cjs.accentColor(state.theme.accent));
641
+ const dark = chunkORNLCBNE_cjs.isLightBackground(slide?.background);
2132
642
  const { id, ...rest } = dark ? {
2133
643
  ...box2,
2134
644
  paragraphs: box2.paragraphs.map((p) => ({
@@ -2171,7 +681,7 @@ function InsertSlide({ after, always }) {
2171
681
  "button",
2172
682
  {
2173
683
  type: "button",
2174
- onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().addSlide(void 0, after),
684
+ onClick: () => chunkORNLCBNE_cjs.usePresentation.getState().addSlide(void 0, after),
2175
685
  className: ui.cn(
2176
686
  "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",
2177
687
  !always && "opacity-0 group-hover/insert:opacity-100 pointer-coarse:opacity-100"
@@ -2194,11 +704,11 @@ function SlidesEditor({
2194
704
  onEditImage,
2195
705
  onCropImage
2196
706
  }) {
2197
- const ids = chunk4TTX6ZNS_cjs.usePresentation((s) => s.slides.map((slide) => slide.id).join(" "));
707
+ const ids = chunkORNLCBNE_cjs.usePresentation((s) => s.slides.map((slide) => slide.id).join(" "));
2198
708
  const slideIds = react.useMemo(() => ids.split(" "), [ids]);
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);
709
+ const current2 = chunkORNLCBNE_cjs.usePresentation((s) => s.current);
710
+ const captions = chunkORNLCBNE_cjs.usePresentation((s) => s.captions);
711
+ const presenting = chunkORNLCBNE_cjs.usePresentation((s) => s.presenting);
2202
712
  const [selection, setSelection] = react.useState(null);
2203
713
  const [view, setView] = react.useState(null);
2204
714
  const list = react.useRef(null);
@@ -2212,7 +722,7 @@ function SlidesEditor({
2212
722
  () => ({ clipId: selection?.clipId ?? null, clear: () => setSelection(null) }),
2213
723
  [selection]
2214
724
  );
2215
- chunkWFMWKPGY_cjs.usePresenterKeys(view, false, keySelection);
725
+ chunkADPRIBSH_cjs.usePresenterKeys(view, false, keySelection);
2216
726
  react.useEffect(() => {
2217
727
  const card = list.current?.querySelector(`[data-testid="slide-${current2}"]`);
2218
728
  card?.scrollIntoView?.({ block: "nearest", behavior: "smooth" });
@@ -2268,7 +778,7 @@ function SlidesEditor({
2268
778
  ui.DropdownMenuCheckboxItem,
2269
779
  {
2270
780
  checked: captions,
2271
- onCheckedChange: (on) => chunk4TTX6ZNS_cjs.usePresentation.getState().setCaptions(!!on),
781
+ onCheckedChange: (on) => chunkORNLCBNE_cjs.usePresentation.getState().setCaptions(!!on),
2272
782
  children: "Show source labels"
2273
783
  }
2274
784
  )
@@ -2281,7 +791,7 @@ function SlidesEditor({
2281
791
  size: "sm",
2282
792
  variant: "destructive",
2283
793
  className: "ml-0.5 h-8 rounded-full",
2284
- onClick: () => chunk4TTX6ZNS_cjs.usePresentation.getState().setPresenting(false),
794
+ onClick: () => chunkORNLCBNE_cjs.usePresentation.getState().setPresenting(false),
2285
795
  title: "Stop presenting (the presentation window closes)",
2286
796
  "data-testid": "presentation-stop-button",
2287
797
  children: [
@@ -2320,7 +830,7 @@ function SlidesEditor({
2320
830
  // src/presentation/draw-boxes.ts
2321
831
  var LINE_HEIGHT = 1.2;
2322
832
  function fontOf(run, themeFont, width) {
2323
- const size = chunk4TTX6ZNS_cjs.pointsToStage(run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) * width;
833
+ const size = chunkORNLCBNE_cjs.pointsToStage(run.size ?? chunkORNLCBNE_cjs.DEFAULT_TEXT_SIZE) * width;
2324
834
  const family = run.font ? `"${run.font}", ${themeFont}` : themeFont;
2325
835
  return `${run.italic ? "italic " : ""}${run.bold ? 700 : 400} ${size}px ${family}`;
2326
836
  }
@@ -2338,9 +848,9 @@ function drawBox(context, box2, width, height, themeFont) {
2338
848
  context.translate(frame.x * width + w / 2, frame.y * height + h / 2);
2339
849
  if (box2.rotation) context.rotate(box2.rotation * Math.PI / 180);
2340
850
  context.translate(-w / 2, -h / 2);
2341
- const lineWidth = box2.line ? Math.max(1, chunk4TTX6ZNS_cjs.pointsToStage(box2.line.width) * width) : 0;
851
+ const lineWidth = box2.line ? Math.max(1, chunkORNLCBNE_cjs.pointsToStage(box2.line.width) * width) : 0;
2342
852
  if (box2.shape === "line") {
2343
- context.strokeStyle = box2.line?.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
853
+ context.strokeStyle = box2.line?.color ?? chunkORNLCBNE_cjs.TEXT_COLORS.body;
2344
854
  context.lineWidth = lineWidth || 1;
2345
855
  if (box2.line?.dash) context.setLineDash([lineWidth * 3, lineWidth * 2]);
2346
856
  context.beginPath();
@@ -2365,12 +875,12 @@ function drawBox(context, box2, width, height, themeFont) {
2365
875
  context.stroke();
2366
876
  context.setLineDash([]);
2367
877
  }
2368
- const inset = chunk4TTX6ZNS_cjs.pointsToStage(box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET) * width;
878
+ const inset = chunkORNLCBNE_cjs.pointsToStage(box2.inset ?? chunkORNLCBNE_cjs.DEFAULT_INSET) * width;
2369
879
  const room = w - 2 * inset;
2370
880
  context.textBaseline = "alphabetic";
2371
881
  const lines = [];
2372
882
  for (const paragraph of box2.paragraphs) {
2373
- const size = chunk4TTX6ZNS_cjs.pointsToStage(paragraph.runs[0]?.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE) * width;
883
+ const size = chunkORNLCBNE_cjs.pointsToStage(paragraph.runs[0]?.size ?? chunkORNLCBNE_cjs.DEFAULT_TEXT_SIZE) * width;
2374
884
  const indent = (paragraph.level ?? 0) * 0.5 * size + (paragraph.bullet ? size * 0.9 : 0);
2375
885
  const words = [];
2376
886
  for (const run of paragraph.runs) {
@@ -2416,12 +926,12 @@ function drawBox(context, box2, width, height, themeFont) {
2416
926
  const baseline = y + line.size * (LINE_HEIGHT - 0.2);
2417
927
  if (line.bullet) {
2418
928
  context.font = fontOf(line.bullet, themeFont, width);
2419
- context.fillStyle = line.bullet.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
929
+ context.fillStyle = line.bullet.color ?? chunkORNLCBNE_cjs.TEXT_COLORS.body;
2420
930
  context.fillText("\u2022", inset + line.indent - line.size * 0.9, baseline);
2421
931
  }
2422
932
  for (const piece of line.pieces) {
2423
933
  context.font = fontOf(piece.run, themeFont, width);
2424
- context.fillStyle = piece.run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body;
934
+ context.fillStyle = piece.run.color ?? chunkORNLCBNE_cjs.TEXT_COLORS.body;
2425
935
  context.fillText(piece.text, x, baseline);
2426
936
  if (piece.run.underline) {
2427
937
  context.fillRect(x, baseline + line.size * 0.08, piece.width, Math.max(1, line.size * 0.05));
@@ -2438,7 +948,7 @@ var boxWords = (box2) => box2.paragraphs.map(
2438
948
  ).filter(Boolean);
2439
949
 
2440
950
  // src/presentation/render-slides.ts
2441
- var SLIDE_PIXELS = { width: 1920, height: Math.round(1920 / chunk4TTX6ZNS_cjs.STAGE_ASPECT) };
951
+ var SLIDE_PIXELS = { width: 1920, height: Math.round(1920 / chunkORNLCBNE_cjs.STAGE_ASPECT) };
2442
952
  async function videoFrame(source, seconds) {
2443
953
  const video = document.createElement("video");
2444
954
  video.muted = true;
@@ -2550,7 +1060,7 @@ async function drawRoundedClip(context, clip, box2, stageWidth, shadow = true) {
2550
1060
  outline2();
2551
1061
  context.clip();
2552
1062
  await drawClip(context, clip, box2);
2553
- if (clip.kind === "pdf") chunk4TTX6ZNS_cjs.paintClipEdge(context, box2, stageWidth);
1063
+ if (clip.kind === "pdf") chunkORNLCBNE_cjs.paintClipEdge(context, box2, stageWidth);
2554
1064
  context.restore();
2555
1065
  context.save();
2556
1066
  context.strokeStyle = "rgba(255,255,255,0.15)";
@@ -2582,7 +1092,7 @@ function wrapLines(context, text, width, max) {
2582
1092
  function drawText(context, box2, lines, theme, width, height) {
2583
1093
  const size = box2.size * width;
2584
1094
  const lineHeight = size * box2.leading;
2585
- context.font = `${box2.weight} ${size}px ${chunk4TTX6ZNS_cjs.FONTS[theme.font].css}`;
1095
+ context.font = `${box2.weight} ${size}px ${chunkORNLCBNE_cjs.FONTS[theme.font].css}`;
2586
1096
  context.textBaseline = "top";
2587
1097
  const indent = box2.bullets ? size * 1.22 : 0;
2588
1098
  const left = box2.x * width;
@@ -2604,10 +1114,10 @@ function drawText(context, box2, lines, theme, width, height) {
2604
1114
  for (const wrapped of paragraphs) {
2605
1115
  if (box2.bullets) {
2606
1116
  const square = size * 0.42;
2607
- context.fillStyle = chunk4TTX6ZNS_cjs.accentColor(theme.accent);
1117
+ context.fillStyle = chunkORNLCBNE_cjs.accentColor(theme.accent);
2608
1118
  context.fillRect(left, y + size * 0.5 - square / 2, square, square);
2609
1119
  }
2610
- context.fillStyle = chunk4TTX6ZNS_cjs.TEXT_COLORS[box2.tone];
1120
+ context.fillStyle = chunkORNLCBNE_cjs.TEXT_COLORS[box2.tone];
2611
1121
  context.textAlign = box2.align === "center" ? "center" : "left";
2612
1122
  for (const line of wrapped) {
2613
1123
  const x = box2.align === "center" ? left + box2.w * width / 2 : left + indent;
@@ -2643,11 +1153,11 @@ async function loadImage(file) {
2643
1153
  }
2644
1154
  }
2645
1155
  function slideWords(slide) {
2646
- const own = slide.layout === "free" ? [] : [slide.caption.trim(), ...chunk4TTX6ZNS_cjs.textLines(slide.points)];
1156
+ const own = slide.layout === "free" ? [] : [slide.caption.trim(), ...chunkORNLCBNE_cjs.textLines(slide.points)];
2647
1157
  return [...own, ...slide.boxes.flatMap(boxWords)].filter(Boolean);
2648
1158
  }
2649
1159
  function drawSlideText(context, slide, look, width, height) {
2650
- const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, {
1160
+ const geometry = chunkORNLCBNE_cjs.slideGeometry(slide, {
2651
1161
  labels: look.labels,
2652
1162
  logo: look.theme.logo?.corner ?? null
2653
1163
  });
@@ -2655,13 +1165,13 @@ function drawSlideText(context, slide, look, width, height) {
2655
1165
  if (title && geometry.title) {
2656
1166
  drawText(context, geometry.title, [title], look.theme, width, height);
2657
1167
  if (geometry.rule) {
2658
- context.fillStyle = chunk4TTX6ZNS_cjs.accentColor(look.theme.accent);
1168
+ context.fillStyle = chunkORNLCBNE_cjs.accentColor(look.theme.accent);
2659
1169
  const r = geometry.rule;
2660
1170
  context.fillRect(r.x * width, r.y * height, r.w * width, r.h * height);
2661
1171
  }
2662
1172
  }
2663
1173
  if (geometry.text) {
2664
- drawText(context, geometry.text, chunk4TTX6ZNS_cjs.textLines(slide.points), look.theme, width, height);
1174
+ drawText(context, geometry.text, chunkORNLCBNE_cjs.textLines(slide.points), look.theme, width, height);
2665
1175
  }
2666
1176
  return geometry;
2667
1177
  }
@@ -2673,13 +1183,13 @@ async function renderSlide(slide, clips, look) {
2673
1183
  const context = canvas.getContext("2d");
2674
1184
  if (!context) throw new Error("Could not draw the slides");
2675
1185
  if (slide.background) {
2676
- await chunk4TTX6ZNS_cjs.paintSlideBackground(context, width, height, slide.background, look.media);
1186
+ await chunkORNLCBNE_cjs.paintSlideBackground(context, width, height, slide.background, look.media);
2677
1187
  } else {
2678
- chunk4TTX6ZNS_cjs.paintBackground(context, width, height, look.theme.background);
1188
+ chunkORNLCBNE_cjs.paintBackground(context, width, height, look.theme.background);
2679
1189
  }
2680
1190
  const geometry = drawSlideText(context, slide, look, width, height);
2681
1191
  const text = slideWords(slide);
2682
- const font = chunk4TTX6ZNS_cjs.FONTS[look.theme.font].css;
1192
+ const font = chunkORNLCBNE_cjs.FONTS[look.theme.font].css;
2683
1193
  const drawBoxes = (front) => {
2684
1194
  for (const box2 of slide.boxes) {
2685
1195
  if (!!box2.front === front) drawBox(context, box2, width, height, font);
@@ -2693,16 +1203,16 @@ async function renderSlide(slide, clips, look) {
2693
1203
  x: item.frame.x * width,
2694
1204
  y: item.frame.y * height,
2695
1205
  width: item.frame.w * width,
2696
- height: chunk4TTX6ZNS_cjs.frameHeight(item.frame, clip.aspect) * height
1206
+ height: chunkORNLCBNE_cjs.frameHeight(item.frame, clip.aspect) * height
2697
1207
  };
2698
1208
  if (clip.plain) {
2699
1209
  await drawClip(context, clip, box2);
2700
1210
  continue;
2701
1211
  }
2702
1212
  await drawRoundedClip(context, clip, box2, width);
2703
- const label = chunk4TTX6ZNS_cjs.clipLabel(clip, look.columnValues);
1213
+ const label = chunkORNLCBNE_cjs.clipLabel(clip, look.columnValues);
2704
1214
  if (look.labels && label) {
2705
- context.fillStyle = chunk4TTX6ZNS_cjs.TEXT_COLORS.muted;
1215
+ context.fillStyle = chunkORNLCBNE_cjs.TEXT_COLORS.muted;
2706
1216
  context.font = `${Math.round(width * 0.017)}px ${font}`;
2707
1217
  context.textAlign = "left";
2708
1218
  context.textBaseline = "top";
@@ -2745,7 +1255,7 @@ function addBox(pptx, page, box2, themeFont) {
2745
1255
  if (box2.shape === "line") {
2746
1256
  page.addShape(pptx.ShapeType.line, {
2747
1257
  ...place,
2748
- line: line ?? { color: hex(chunk4TTX6ZNS_cjs.TEXT_COLORS.body), width: 1 }
1258
+ line: line ?? { color: hex(chunkORNLCBNE_cjs.TEXT_COLORS.body), width: 1 }
2749
1259
  });
2750
1260
  return;
2751
1261
  }
@@ -2762,9 +1272,9 @@ function addBox(pptx, page, box2, themeFont) {
2762
1272
  runs.push({
2763
1273
  text: run.text,
2764
1274
  options: {
2765
- fontSize: run.size ?? chunk4TTX6ZNS_cjs.DEFAULT_TEXT_SIZE,
1275
+ fontSize: run.size ?? chunkORNLCBNE_cjs.DEFAULT_TEXT_SIZE,
2766
1276
  fontFace: run.font ?? themeFont,
2767
- color: hex(run.color ?? chunk4TTX6ZNS_cjs.TEXT_COLORS.body),
1277
+ color: hex(run.color ?? chunkORNLCBNE_cjs.TEXT_COLORS.body),
2768
1278
  ...run.bold ? { bold: true } : {},
2769
1279
  ...run.italic ? { italic: true } : {},
2770
1280
  ...run.underline ? { underline: { style: "sng" } } : {},
@@ -2786,7 +1296,7 @@ function addBox(pptx, page, box2, themeFont) {
2786
1296
  // Its part in the slide (its title, its body), kept by name: read back when imported.
2787
1297
  ...box2.role ? { objectName: `ARBI ${box2.role}` } : {},
2788
1298
  valign: box2.anchor ?? "top",
2789
- margin: box2.inset ?? chunk4TTX6ZNS_cjs.DEFAULT_INSET,
1299
+ margin: box2.inset ?? chunkORNLCBNE_cjs.DEFAULT_INSET,
2790
1300
  lineSpacingMultiple: 1,
2791
1301
  fit: "none"
2792
1302
  });
@@ -2816,10 +1326,10 @@ var box = (b) => ({
2816
1326
  function textOptions(text, look) {
2817
1327
  return {
2818
1328
  ...box(text),
2819
- fontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
1329
+ fontFace: chunkORNLCBNE_cjs.FONTS[look.theme.font].pptx,
2820
1330
  fontSize: toPoints(text.size),
2821
1331
  bold: text.weight >= 600,
2822
- color: hex2(chunk4TTX6ZNS_cjs.TEXT_COLORS[text.tone]),
1332
+ color: hex2(chunkORNLCBNE_cjs.TEXT_COLORS[text.tone]),
2823
1333
  align: text.align,
2824
1334
  valign: text.anchor ?? "top",
2825
1335
  lineSpacingMultiple: text.leading,
@@ -2832,18 +1342,18 @@ async function buildPptx(deck, look) {
2832
1342
  pptx.layout = "LAYOUT_WIDE";
2833
1343
  pptx.title = deck.title;
2834
1344
  pptx.theme = {
2835
- headFontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
2836
- bodyFontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx
1345
+ headFontFace: chunkORNLCBNE_cjs.FONTS[look.theme.font].pptx,
1346
+ bodyFontFace: chunkORNLCBNE_cjs.FONTS[look.theme.font].pptx
2837
1347
  };
2838
1348
  const { width, height } = SLIDE_PIXELS;
2839
1349
  const background = await canvasImage(
2840
1350
  width,
2841
1351
  height,
2842
- (context) => chunk4TTX6ZNS_cjs.paintBackground(context, width, height, look.theme.background)
1352
+ (context) => chunkORNLCBNE_cjs.paintBackground(context, width, height, look.theme.background)
2843
1353
  );
2844
1354
  const logo = look.logo ? await loadImage(look.logo) : null;
2845
1355
  const logoData = logo ? await canvasImage(logo.width, logo.height, (context) => context.drawImage(logo, 0, 0)) : null;
2846
- const themeFont = chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx;
1356
+ const themeFont = chunkORNLCBNE_cjs.FONTS[look.theme.font].pptx;
2847
1357
  for (const slide of deck.slides) {
2848
1358
  const page = pptx.addSlide();
2849
1359
  if (slide.background?.color && !slide.background.gradient && !slide.background.image) {
@@ -2854,14 +1364,14 @@ async function buildPptx(deck, look) {
2854
1364
  data: await canvasImage(
2855
1365
  width,
2856
1366
  height,
2857
- (context) => chunk4TTX6ZNS_cjs.paintSlideBackground(context, width, height, own, look.media)
1367
+ (context) => chunkORNLCBNE_cjs.paintSlideBackground(context, width, height, own, look.media)
2858
1368
  )
2859
1369
  };
2860
1370
  } else {
2861
1371
  page.background = { data: background };
2862
1372
  }
2863
1373
  if (slide.notes?.trim()) page.addNotes(slide.notes);
2864
- const geometry = chunk4TTX6ZNS_cjs.slideGeometry(slide, {
1374
+ const geometry = chunkORNLCBNE_cjs.slideGeometry(slide, {
2865
1375
  labels: look.labels,
2866
1376
  logo: look.theme.logo?.corner ?? null
2867
1377
  });
@@ -2869,7 +1379,7 @@ async function buildPptx(deck, look) {
2869
1379
  for (const item of slide.items) {
2870
1380
  const clip = deck.clips.find((entry) => entry.id === item.clipId);
2871
1381
  if (!clip) continue;
2872
- const frame = { ...item.frame, h: chunk4TTX6ZNS_cjs.frameHeight(item.frame, clip.aspect) };
1382
+ const frame = { ...item.frame, h: chunkORNLCBNE_cjs.frameHeight(item.frame, clip.aspect) };
2873
1383
  if (clip.plain) {
2874
1384
  const source = clip.kind === "image" ? await createImageBitmap(clip.source) : null;
2875
1385
  const scale = source ? Math.min(1, 2400 / Math.max(1, clip.rect.w * source.width)) : 1.5;
@@ -2901,13 +1411,13 @@ async function buildPptx(deck, look) {
2901
1411
  altText: clip.caption,
2902
1412
  shadow: { type: "outer", blur: 10, offset: 3, angle: 90, color: "000000", opacity: 0.45 }
2903
1413
  });
2904
- const label = chunk4TTX6ZNS_cjs.clipLabel(clip, look.columnValues);
1414
+ const label = chunkORNLCBNE_cjs.clipLabel(clip, look.columnValues);
2905
1415
  if (look.labels && label) {
2906
1416
  page.addText(label, {
2907
1417
  ...box({ x: frame.x, y: frame.y + frame.h + 8e-3, w: frame.w, h: 0.045 }),
2908
- fontFace: chunk4TTX6ZNS_cjs.FONTS[look.theme.font].pptx,
1418
+ fontFace: chunkORNLCBNE_cjs.FONTS[look.theme.font].pptx,
2909
1419
  fontSize: toPoints(0.017),
2910
- color: hex2(chunk4TTX6ZNS_cjs.TEXT_COLORS.muted),
1420
+ color: hex2(chunkORNLCBNE_cjs.TEXT_COLORS.muted),
2911
1421
  margin: 0,
2912
1422
  valign: "top",
2913
1423
  fit: "shrink"
@@ -2920,12 +1430,12 @@ async function buildPptx(deck, look) {
2920
1430
  if (geometry.rule) {
2921
1431
  page.addShape(pptx.ShapeType.rect, {
2922
1432
  ...box(geometry.rule),
2923
- fill: { color: hex2(chunk4TTX6ZNS_cjs.accentColor(look.theme.accent)) },
2924
- line: { color: hex2(chunk4TTX6ZNS_cjs.accentColor(look.theme.accent)), width: 0 }
1433
+ fill: { color: hex2(chunkORNLCBNE_cjs.accentColor(look.theme.accent)) },
1434
+ line: { color: hex2(chunkORNLCBNE_cjs.accentColor(look.theme.accent)), width: 0 }
2925
1435
  });
2926
1436
  }
2927
1437
  }
2928
- const lines = chunk4TTX6ZNS_cjs.textLines(slide.points);
1438
+ const lines = chunkORNLCBNE_cjs.textLines(slide.points);
2929
1439
  if (geometry.text && lines.length) {
2930
1440
  const text = geometry.text;
2931
1441
  page.addText(
@@ -2959,7 +1469,7 @@ async function buildPptx(deck, look) {
2959
1469
  }
2960
1470
  }
2961
1471
  const deckFile = await pptx.write({ outputType: "blob" });
2962
- return accentBullets(deckFile, chunk4TTX6ZNS_cjs.accentColor(look.theme.accent));
1472
+ return accentBullets(deckFile, chunkORNLCBNE_cjs.accentColor(look.theme.accent));
2963
1473
  }
2964
1474
  async function accentBullets(deck, accent) {
2965
1475
  const { default: JSZip } = await import('jszip');
@@ -3490,7 +2000,7 @@ function renditionClip(deck, part, area, what) {
3490
2000
  fileName: fileName ?? "Presentation.pptx",
3491
2001
  page: part.page,
3492
2002
  rect,
3493
- aspect: frame.w * chunk4TTX6ZNS_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
2003
+ aspect: frame.w * chunkORNLCBNE_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3494
2004
  caption: "",
3495
2005
  plain: true
3496
2006
  });
@@ -3509,7 +2019,7 @@ function readParagraphs(body, chain, deck, defaults, fontScale, fallback = []) {
3509
2019
  defaults.color ? { color: defaults.color } : {},
3510
2020
  levelStyle(fallback, level, theme)
3511
2021
  ]);
3512
- const runStyle2 = (rPr) => {
2022
+ const runStyle = (rPr) => {
3513
2023
  const s = merge([readRunProps(rPr, theme), style]);
3514
2024
  const color = s.color ?? defaults.base;
3515
2025
  return {
@@ -3532,13 +2042,13 @@ function readParagraphs(body, chain, deck, defaults, fontScale, fallback = []) {
3532
2042
  for (const child of kids(p)) {
3533
2043
  if (child.localName === "r" || child.localName === "fld") {
3534
2044
  const text = kid(child, "t")?.textContent ?? "";
3535
- runs.push({ ...runStyle2(kid(child, "rPr")), text });
2045
+ runs.push({ ...runStyle(kid(child, "rPr")), text });
3536
2046
  } else if (child.localName === "br") {
3537
- paragraphs.push(shape(runs.length ? runs : [{ ...runStyle2(kid(child, "rPr")), text: "" }]));
2047
+ paragraphs.push(shape(runs.length ? runs : [{ ...runStyle(kid(child, "rPr")), text: "" }]));
3538
2048
  runs = [];
3539
2049
  }
3540
2050
  }
3541
- if (!runs.length) runs = [{ ...runStyle2(kid(p, "endParaRPr")), text: "" }];
2051
+ if (!runs.length) runs = [{ ...runStyle(kid(p, "endParaRPr")), text: "" }];
3542
2052
  paragraphs.push(shape(runs));
3543
2053
  }
3544
2054
  while (paragraphs.length > 1 && !paragraphs[paragraphs.length - 1].runs.some((run) => run.text.trim())) {
@@ -3629,7 +2139,7 @@ async function readShape(shape, transform, deck, part, inherit, built) {
3629
2139
  fileName: target?.target.split("/").pop() ?? "Picture",
3630
2140
  page: 1,
3631
2141
  rect,
3632
- aspect: frame.w * chunk4TTX6ZNS_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
2142
+ aspect: frame.w * chunkORNLCBNE_cjs.STAGE_ASPECT / Math.max(frame.h, 1e-6),
3633
2143
  caption: "",
3634
2144
  media: key,
3635
2145
  plain: true
@@ -3852,7 +2362,7 @@ async function importPptx(bytes, options = {}) {
3852
2362
  const cx = numAttr(size, "cx", 12192e3);
3853
2363
  const cy = numAttr(size, "cy", 6858e3);
3854
2364
  const deckAspect = cx / cy;
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 };
2365
+ const place = deckAspect < chunkORNLCBNE_cjs.STAGE_ASPECT ? { w: deckAspect / chunkORNLCBNE_cjs.STAGE_ASPECT, h: 1, x: (1 - deckAspect / chunkORNLCBNE_cjs.STAGE_ASPECT) / 2, y: 0 } : { w: 1, h: chunkORNLCBNE_cjs.STAGE_ASPECT / deckAspect, x: 0, y: (1 - chunkORNLCBNE_cjs.STAGE_ASPECT / deckAspect) / 2 };
3856
2366
  const slides = await slideParts(pkg);
3857
2367
  const firstLayout = slides.length ? await pkg.related(slides[0].part, "/slideLayout") : null;
3858
2368
  const firstMaster = firstLayout ? await pkg.related(firstLayout, "/slideMaster") : null;
@@ -3861,7 +2371,7 @@ async function importPptx(bytes, options = {}) {
3861
2371
  theme: firstMaster ? await readTheme(pkg, firstMaster) : { scheme: {}, map: {}, majorFont: "Calibri", minorFont: "Calibri", lineWidths: [] },
3862
2372
  slideSize: { cx, cy },
3863
2373
  place,
3864
- pointScale: chunk4TTX6ZNS_cjs.SLIDE_POINTS.h * place.h / (cy / EMU_PER_POINT),
2374
+ pointScale: chunkORNLCBNE_cjs.SLIDE_POINTS.h * place.h / (cy / EMU_PER_POINT),
3865
2375
  defaultText: kid(pres.documentElement, "defaultTextStyle"),
3866
2376
  options,
3867
2377
  clips: [],
@@ -3957,7 +2467,7 @@ async function importPptx(bytes, options = {}) {
3957
2467
  version: 1,
3958
2468
  title: options.title ?? (coreTitle?.trim() || "Presentation"),
3959
2469
  captions: false,
3960
- theme: chunk4TTX6ZNS_cjs.DEFAULT_THEME,
2470
+ theme: chunkORNLCBNE_cjs.DEFAULT_THEME,
3961
2471
  clips: deck.clips,
3962
2472
  slides: saved,
3963
2473
  ...Object.keys(deck.media).length ? { media: deck.media } : {}
@@ -4045,7 +2555,7 @@ async function presentationData(bytes) {
4045
2555
  if (isZipBytes(bytes)) return readPptxPresentationData(bytes);
4046
2556
  const isPdf = bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70;
4047
2557
  if (!isPdf) return new TextDecoder().decode(bytes);
4048
- const data = await documentTools.readPdfAttachment(bytes, chunk4TTX6ZNS_cjs.PRESENTATION_ATTACHMENT);
2558
+ const data = await documentTools.readPdfAttachment(bytes, chunkORNLCBNE_cjs.PRESENTATION_ATTACHMENT);
4049
2559
  if (!data) {
4050
2560
  throw new Error(
4051
2561
  "This PDF has no editable presentation in it (it may have been changed outside ARBI)."
@@ -4054,7 +2564,7 @@ async function presentationData(bytes) {
4054
2564
  return new TextDecoder().decode(data);
4055
2565
  }
4056
2566
  function current(withoutClips) {
4057
- const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
2567
+ const state = chunkORNLCBNE_cjs.usePresentation.getState();
4058
2568
  return withoutClips ? {
4059
2569
  ...state,
4060
2570
  clips: [],
@@ -4076,18 +2586,18 @@ function usePresentationFiles() {
4076
2586
  const state = current(withoutClips);
4077
2587
  const deck = await buildPptx({ title, slides: state.slides, clips: state.clips }, lookOf(state));
4078
2588
  const fingerprints = await slideFingerprints(deck);
4079
- const data = chunk4TTX6ZNS_cjs.serializePresentation({ ...state, title, fingerprints });
2589
+ const data = chunkORNLCBNE_cjs.serializePresentation({ ...state, title, fingerprints });
4080
2590
  return writePptxPresentationData(deck, JSON.stringify(data, null, 2));
4081
2591
  }, []);
4082
2592
  const save = react.useCallback(
4083
2593
  async (title, { asNew = false, template = false } = {}) => {
4084
2594
  if (!arbi || !workspaceId) throw new Error("Open a workspace to save the presentation.");
4085
- const state = chunk4TTX6ZNS_cjs.usePresentation.getState();
2595
+ const state = chunkORNLCBNE_cjs.usePresentation.getState();
4086
2596
  const versionOf = asNew || template ? null : state.savedId;
4087
2597
  const deck = await buildFile(title, template);
4088
- const file = new File([deck], chunk4TTX6ZNS_cjs.presentationFileName(title), { type: PPTX_TYPE });
2598
+ const file = new File([deck], chunkORNLCBNE_cjs.presentationFileName(title), { type: PPTX_TYPE });
4089
2599
  const result = await arbi.documents.upload([file], {
4090
- folder: template ? chunk4TTX6ZNS_cjs.TEMPLATES_FOLDER : chunk4TTX6ZNS_cjs.PRESENTATIONS_FOLDER,
2600
+ folder: template ? chunkORNLCBNE_cjs.TEMPLATES_FOLDER : chunkORNLCBNE_cjs.PRESENTATIONS_FOLDER,
4091
2601
  workspaceExtId: workspaceId,
4092
2602
  ...versionOf ? { versionOf } : {}
4093
2603
  });
@@ -4112,8 +2622,8 @@ function usePresentationFiles() {
4112
2622
  }
4113
2623
  const pdf = await documentTools.imagesToPdf(pages, { title });
4114
2624
  const result = await arbi.documents.upload(
4115
- [new File([pdf], `${chunk4TTX6ZNS_cjs.safeFileStem(title)}.pdf`, { type: "application/pdf" })],
4116
- { folder: chunk4TTX6ZNS_cjs.EXPORTS_FOLDER, workspaceExtId: workspaceId }
2625
+ [new File([pdf], `${chunkORNLCBNE_cjs.safeFileStem(title)}.pdf`, { type: "application/pdf" })],
2626
+ { folder: chunkORNLCBNE_cjs.EXPORTS_FOLDER, workspaceExtId: workspaceId }
4117
2627
  );
4118
2628
  const id = result.doc_ext_ids?.[0];
4119
2629
  if (!id) throw new Error("The PDF could not be saved.");
@@ -4128,10 +2638,10 @@ function usePresentationFiles() {
4128
2638
  return docs.filter((doc) => {
4129
2639
  const folder = doc.folder ?? "";
4130
2640
  if (!ui.isPresentationFileName(doc.file_name, folder)) return false;
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);
2641
+ return scope === "templates" ? folder === chunkORNLCBNE_cjs.TEMPLATES_FOLDER : folder.startsWith(chunkORNLCBNE_cjs.PRESENTATIONS_FOLDER) && folder !== chunkORNLCBNE_cjs.TEMPLATES_FOLDER && !folder.startsWith(chunkORNLCBNE_cjs.EXPORTS_FOLDER);
4132
2642
  }).map((doc) => ({
4133
2643
  id: doc.external_id,
4134
- title: chunk4TTX6ZNS_cjs.presentationTitle(doc.file_name ?? ""),
2644
+ title: chunkORNLCBNE_cjs.presentationTitle(doc.file_name ?? ""),
4135
2645
  updatedAt: doc.updated_at ?? doc.created_at ?? null
4136
2646
  })).sort((a, b) => (a.updatedAt ?? "") < (b.updatedAt ?? "") ? 1 : -1);
4137
2647
  },
@@ -4147,7 +2657,7 @@ function usePresentationFiles() {
4147
2657
  const openedVersion = version ?? doc?.current_version ?? null;
4148
2658
  if (text === null) {
4149
2659
  const imported = await importPptx(bytes, {
4150
- title: chunk4TTX6ZNS_cjs.presentationTitle(doc?.file_name ?? "Presentation.pptx"),
2660
+ title: chunkORNLCBNE_cjs.presentationTitle(doc?.file_name ?? "Presentation.pptx"),
4151
2661
  documentId: id,
4152
2662
  version: version ?? doc?.current_version,
4153
2663
  fileName: doc?.file_name ?? void 0
@@ -4159,7 +2669,7 @@ function usePresentationFiles() {
4159
2669
  openedVersion
4160
2670
  };
4161
2671
  }
4162
- let saved = chunk4TTX6ZNS_cjs.parsePresentation(text);
2672
+ let saved = chunkORNLCBNE_cjs.parsePresentation(text);
4163
2673
  let changedOutside;
4164
2674
  if (isZipBytes(bytes) && saved.slides.some((slide) => slide.fingerprint)) {
4165
2675
  const now = await slideFingerprints(bytes);
@@ -4190,7 +2700,7 @@ function usePresentationFiles() {
4190
2700
  const startFromTemplate = react.useCallback(
4191
2701
  async (id) => {
4192
2702
  const { saved } = await readSaved(id);
4193
- chunk4TTX6ZNS_cjs.usePresentation.getState().load({
2703
+ chunkORNLCBNE_cjs.usePresentation.getState().load({
4194
2704
  title: "Untitled presentation",
4195
2705
  savedId: null,
4196
2706
  captions: saved.captions,
@@ -4267,7 +2777,7 @@ function usePresentationFiles() {
4267
2777
  );
4268
2778
  const kept = [];
4269
2779
  const newIndex = opened.map((clip) => clip ? kept.push(clip) - 1 : -1);
4270
- chunk4TTX6ZNS_cjs.usePresentation.getState().load({
2780
+ chunkORNLCBNE_cjs.usePresentation.getState().load({
4271
2781
  title: saved.title,
4272
2782
  savedId: legacy ? null : id,
4273
2783
  version: legacy ? null : openedVersion,
@@ -4341,7 +2851,7 @@ function useGenerateImageLaunch() {
4341
2851
  throw new Error(failure || answer.trim() || "The image could not be generated.");
4342
2852
  const source = await (await arbi.documents.download(documentId)).blob();
4343
2853
  const fileName = `${prompt.split("\n")[0].slice(0, 60)}.png`;
4344
- chunk4TTX6ZNS_cjs.usePresentation.getState().addClip({
2854
+ chunkORNLCBNE_cjs.usePresentation.getState().addClip({
4345
2855
  kind: "image",
4346
2856
  documentId,
4347
2857
  fileName,
@@ -4350,7 +2860,7 @@ function useGenerateImageLaunch() {
4350
2860
  aspect: await aspectOf(source),
4351
2861
  masks: [],
4352
2862
  source,
4353
- caption: chunk4TTX6ZNS_cjs.mediaCaption(fileName)
2863
+ caption: chunkORNLCBNE_cjs.mediaCaption(fileName)
4354
2864
  });
4355
2865
  },
4356
2866
  [arbi, workspaceId]
@@ -4361,7 +2871,7 @@ function GenerateImageDialog({
4361
2871
  onOpenChange,
4362
2872
  referenceId
4363
2873
  }) {
4364
- const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
2874
+ const notify = chunkORNLCBNE_cjs.usePresentation((s) => s.notify);
4365
2875
  const { skills } = chunkUFT22LAB_cjs.useWorkflowDefinitions();
4366
2876
  const run = useGenerateImageLaunch();
4367
2877
  const workflows = react.useMemo(
@@ -4421,9 +2931,9 @@ function SavePresentationDialog({
4421
2931
  onOpenChange,
4422
2932
  mode = "save"
4423
2933
  }) {
4424
- const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
2934
+ const notify = chunkORNLCBNE_cjs.usePresentation((s) => s.notify);
4425
2935
  const { save, exportPdf } = usePresentationFiles();
4426
- const current2 = chunk4TTX6ZNS_cjs.usePresentation((s) => s.title);
2936
+ const current2 = chunkORNLCBNE_cjs.usePresentation((s) => s.title);
4427
2937
  const [title, setTitle] = react.useState(current2);
4428
2938
  const [busy, setBusy] = react.useState(false);
4429
2939
  const text = SAVE_TEXT[mode];
@@ -4493,7 +3003,7 @@ function OpenPresentationDialog({
4493
3003
  templates = false
4494
3004
  }) {
4495
3005
  const { confirm } = chunkTKHCIHE2_cjs.useBlocksEnvironment();
4496
- const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
3006
+ const notify = chunkORNLCBNE_cjs.usePresentation((s) => s.notify);
4497
3007
  const { list, startFromTemplate } = usePresentationFiles();
4498
3008
  const [entries, setEntries] = react.useState(null);
4499
3009
  const [opening, setOpening] = react.useState(null);
@@ -4508,7 +3018,7 @@ function OpenPresentationDialog({
4508
3018
  onOpened(entry.id);
4509
3019
  return;
4510
3020
  }
4511
- if (chunk4TTX6ZNS_cjs.usePresentation.getState().clips.length) {
3021
+ if (chunkORNLCBNE_cjs.usePresentation.getState().clips.length) {
4512
3022
  const ok = await confirm({
4513
3023
  title: "New from template",
4514
3024
  message: "Replace the presentation that is open? Save it first to keep it.",
@@ -4559,8 +3069,8 @@ function OpenPresentationDialog({
4559
3069
  }
4560
3070
  var IMAGE_FILE = /\.(png|jpe?g|gif|webp|svg)$/i;
4561
3071
  function ChooseLogoDialog({ open, onOpenChange }) {
4562
- const setTheme = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setTheme);
4563
- const corner = chunk4TTX6ZNS_cjs.usePresentation((s) => s.theme.logo?.corner ?? "br");
3072
+ const setTheme = chunkORNLCBNE_cjs.usePresentation((s) => s.setTheme);
3073
+ const corner = chunkORNLCBNE_cjs.usePresentation((s) => s.theme.logo?.corner ?? "br");
4564
3074
  const { data: documents } = react$1.useDocuments(void 0, { enabled: open });
4565
3075
  const [picked, setPicked] = react.useState("");
4566
3076
  const groups = react.useMemo(
@@ -4647,7 +3157,7 @@ function CropClipDialog({ clip, onOpenChange }) {
4647
3157
  w: Math.min(1, area.width / natural.width),
4648
3158
  h: Math.min(1, area.height / natural.height)
4649
3159
  };
4650
- chunk4TTX6ZNS_cjs.usePresentation.getState().cropClip(clip.id, rect, area.width / area.height);
3160
+ chunkORNLCBNE_cjs.usePresentation.getState().cropClip(clip.id, rect, area.width / area.height);
4651
3161
  onOpenChange(false);
4652
3162
  };
4653
3163
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4696,8 +3206,8 @@ function CropClipDialog({ clip, onOpenChange }) {
4696
3206
  var EMPTY = new Blob();
4697
3207
  var NONE = "none";
4698
3208
  function LabelColumnMenu({ columns }) {
4699
- const labelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.labelColumn);
4700
- const setLabelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.setLabelColumn);
3209
+ const labelColumn = chunkORNLCBNE_cjs.usePresentation((s) => s.labelColumn);
3210
+ const setLabelColumn = chunkORNLCBNE_cjs.usePresentation((s) => s.setLabelColumn);
4701
3211
  if (!columns.length) return null;
4702
3212
  const chosen = columns.find((column) => column.id === labelColumn);
4703
3213
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuSub, { children: [
@@ -4740,8 +3250,8 @@ function useLabelColumns(active) {
4740
3250
  const workspaceId = react$1.useArbiSessionState((s) => s.workspaceId);
4741
3251
  const { data: tags } = react$1.useTags(workspaceId, { enabled: active });
4742
3252
  const { data: documents } = react$1.useDocuments(workspaceId, { enabled: active });
4743
- const labelColumn = chunk4TTX6ZNS_cjs.usePresentation((s) => s.labelColumn);
4744
- const documentIds = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips.map((clip) => clip.documentId).join(" "));
3253
+ const labelColumn = chunkORNLCBNE_cjs.usePresentation((s) => s.labelColumn);
3254
+ const documentIds = chunkORNLCBNE_cjs.usePresentation((s) => s.clips.map((clip) => clip.documentId).join(" "));
4745
3255
  const columns = react.useMemo(
4746
3256
  () => (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)),
4747
3257
  [tags]
@@ -4756,23 +3266,23 @@ function useLabelColumns(active) {
4756
3266
  if (note2) values[doc.external_id] = note2;
4757
3267
  }
4758
3268
  }
4759
- chunk4TTX6ZNS_cjs.usePresentation.getState().setColumnValues(values);
3269
+ chunkORNLCBNE_cjs.usePresentation.getState().setColumnValues(values);
4760
3270
  }, [labelColumn, documentIds, documents]);
4761
3271
  return columns;
4762
3272
  }
4763
3273
  function usePresentationController(active) {
4764
3274
  const session = react$1.useArbiSessionStore();
4765
- const notify = chunk4TTX6ZNS_cjs.usePresentation((s) => s.notify);
3275
+ const notify = chunkORNLCBNE_cjs.usePresentation((s) => s.notify);
4766
3276
  const { save, canSave } = usePresentationFiles();
4767
3277
  const labelColumns = useLabelColumns(active);
4768
3278
  const [dialog, setDialog] = react.useState(null);
4769
3279
  const [reference, setReference] = react.useState(null);
4770
3280
  const [cropping, setCropping] = react.useState(null);
4771
- const cropClip = chunk4TTX6ZNS_cjs.usePresentation((s) => s.clips.find((c) => c.id === cropping) ?? null);
3281
+ const cropClip = chunkORNLCBNE_cjs.usePresentation((s) => s.clips.find((c) => c.id === cropping) ?? null);
4772
3282
  const [saving, setSaving] = react.useState(false);
4773
3283
  const close = (open) => !open && setDialog(null);
4774
3284
  const quickSave = react.useCallback(async () => {
4775
- const { savedId, title } = chunk4TTX6ZNS_cjs.usePresentation.getState();
3285
+ const { savedId, title } = chunkORNLCBNE_cjs.usePresentation.getState();
4776
3286
  if (!savedId) return setDialog("save");
4777
3287
  setSaving(true);
4778
3288
  try {
@@ -4806,7 +3316,7 @@ function usePresentationController(active) {
4806
3316
  {
4807
3317
  open: dialog === "open" || dialog === "fromTemplate",
4808
3318
  templates: dialog === "fromTemplate",
4809
- onOpened: (id) => chunkWFMWKPGY_cjs.editPresentation(session, id ? { kind: "open", documentId: id } : { kind: "new" }),
3319
+ onOpened: (id) => chunkWVZLAAIZ_cjs.editPresentation(session, id ? { kind: "open", documentId: id } : { kind: "new" }),
4810
3320
  onOpenChange: close
4811
3321
  }
4812
3322
  ),
@@ -4848,7 +3358,7 @@ function usePresentationController(active) {
4848
3358
  trayStart: canSave && /* @__PURE__ */ jsxRuntime.jsx(GenerateTile, { onClick: () => generate(null) }),
4849
3359
  onChooseLogo: canSave ? () => setDialog("logo") : void 0,
4850
3360
  onEditImage: (clipId) => {
4851
- const clip = chunk4TTX6ZNS_cjs.usePresentation.getState().clips.find((c) => c.id === clipId);
3361
+ const clip = chunkORNLCBNE_cjs.usePresentation.getState().clips.find((c) => c.id === clipId);
4852
3362
  if (clip) generate(clip.documentId);
4853
3363
  },
4854
3364
  onCropImage: setCropping
@@ -4856,9 +3366,8 @@ function usePresentationController(active) {
4856
3366
  return { editor, dialogs };
4857
3367
  }
4858
3368
 
4859
- exports.PresentationStage = PresentationStage;
4860
3369
  exports.SlidesEditor = SlidesEditor;
4861
3370
  exports.usePresentationController = usePresentationController;
4862
3371
  exports.usePresentationFiles = usePresentationFiles;
4863
- //# sourceMappingURL=chunk-DWMWEALB.cjs.map
4864
- //# sourceMappingURL=chunk-DWMWEALB.cjs.map
3372
+ //# sourceMappingURL=chunk-H236SNEV.cjs.map
3373
+ //# sourceMappingURL=chunk-H236SNEV.cjs.map