pptx-react-viewer 2.16.10 → 2.18.0

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 (136) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +14 -14
  3. package/dist/{AiChatPanel-XHKYPYPH.mjs → AiChatPanel-SSSBERWJ.mjs} +4 -4
  4. package/dist/AiChatPanel-SSSBERWJ.mjs.br +0 -0
  5. package/dist/AiChatPanel-SSSBERWJ.mjs.gz +0 -0
  6. package/dist/{AiChatPanel-EPMBL6EA.js → AiChatPanel-UN5DHPZY.js} +24 -24
  7. package/dist/AiChatPanel-UN5DHPZY.js.br +0 -0
  8. package/dist/AiChatPanel-UN5DHPZY.js.gz +0 -0
  9. package/dist/{Model3DScene-DUJOZA2B.js → Model3DScene-4RPYKC2I.js} +2 -2
  10. package/dist/Model3DScene-4RPYKC2I.js.br +0 -0
  11. package/dist/Model3DScene-4RPYKC2I.js.gz +0 -0
  12. package/dist/{Model3DScene-YMIAGRPG.mjs → Model3DScene-LYEESYAI.mjs} +1 -1
  13. package/dist/Model3DScene-LYEESYAI.mjs.br +0 -0
  14. package/dist/Model3DScene-LYEESYAI.mjs.gz +0 -0
  15. package/dist/{PowerPointViewer-Du7u4INi.d.ts → PowerPointViewer-Cf4YHjdF.d.ts} +2 -2
  16. package/dist/PowerPointViewer-Cf4YHjdF.d.ts.map +1 -0
  17. package/dist/{SurfaceChart3DScene-TNCHWQAK.js → SurfaceChart3DScene-ACPKCWLJ.js} +2 -2
  18. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.br +0 -0
  19. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.gz +0 -0
  20. package/dist/{SurfaceChart3DScene-Q47OEJXS.mjs → SurfaceChart3DScene-JR62SOYO.mjs} +1 -1
  21. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.br +0 -0
  22. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.gz +0 -0
  23. package/dist/{audience-content-store-BvqKy7Hf.d.ts → audience-content-store-CyS0oP6t.d.ts} +2 -2
  24. package/dist/{audience-content-store-BvqKy7Hf.d.ts.map → audience-content-store-CyS0oP6t.d.ts.map} +1 -1
  25. package/dist/{chunk-WK22Z7PK.js → chunk-4LWGAVAP.js} +526 -928
  26. package/dist/chunk-4LWGAVAP.js.br +0 -0
  27. package/dist/chunk-4LWGAVAP.js.gz +0 -0
  28. package/dist/{chunk-EL2YF26P.mjs → chunk-7XF6S4AM.mjs} +1 -1
  29. package/dist/chunk-7XF6S4AM.mjs.br +0 -0
  30. package/dist/chunk-7XF6S4AM.mjs.gz +0 -0
  31. package/dist/{chunk-FSVE6WUY.js → chunk-ASKYZ5ZY.js} +728 -523
  32. package/dist/chunk-ASKYZ5ZY.js.br +0 -0
  33. package/dist/chunk-ASKYZ5ZY.js.gz +0 -0
  34. package/dist/{chunk-VHME5BE6.mjs → chunk-BZOL6FXF.mjs} +326 -728
  35. package/dist/chunk-BZOL6FXF.mjs.br +0 -0
  36. package/dist/chunk-BZOL6FXF.mjs.gz +0 -0
  37. package/dist/{chunk-YWKUIUQX.mjs → chunk-GODW6RNR.mjs} +87648 -78804
  38. package/dist/chunk-GODW6RNR.mjs.br +0 -0
  39. package/dist/chunk-GODW6RNR.mjs.gz +0 -0
  40. package/dist/{chunk-ESC6IB2F.js → chunk-ICZDMFF2.js} +2147 -3399
  41. package/dist/chunk-ICZDMFF2.js.br +0 -0
  42. package/dist/chunk-ICZDMFF2.js.gz +0 -0
  43. package/dist/{chunk-PI5SFTDC.js → chunk-MAVLV56S.js} +3 -3
  44. package/dist/chunk-MAVLV56S.js.br +0 -0
  45. package/dist/chunk-MAVLV56S.js.gz +0 -0
  46. package/dist/{chunk-G3VAE7ZF.mjs → chunk-O7FTUUXP.mjs} +1212 -2464
  47. package/dist/chunk-O7FTUUXP.mjs.br +0 -0
  48. package/dist/chunk-O7FTUUXP.mjs.gz +0 -0
  49. package/dist/{chunk-J7EFC3GS.mjs → chunk-QUB5OSKY.mjs} +394 -189
  50. package/dist/chunk-QUB5OSKY.mjs.br +0 -0
  51. package/dist/chunk-QUB5OSKY.mjs.gz +0 -0
  52. package/dist/{chunk-DVZF4ARG.js → chunk-RTUGI4HQ.js} +49 -4
  53. package/dist/chunk-RTUGI4HQ.js.br +0 -0
  54. package/dist/chunk-RTUGI4HQ.js.gz +0 -0
  55. package/dist/{chunk-5IUEPQTK.mjs → chunk-SNL6LBRX.mjs} +49 -4
  56. package/dist/chunk-SNL6LBRX.mjs.br +0 -0
  57. package/dist/chunk-SNL6LBRX.mjs.gz +0 -0
  58. package/dist/{chunk-Y2KIB3QH.js → chunk-WVDM36ZM.js} +87730 -78843
  59. package/dist/chunk-WVDM36ZM.js.br +0 -0
  60. package/dist/chunk-WVDM36ZM.js.gz +0 -0
  61. package/dist/i18n.js +4 -4
  62. package/dist/i18n.js.br +0 -0
  63. package/dist/i18n.js.gz +0 -0
  64. package/dist/i18n.mjs +1 -1
  65. package/dist/i18n.mjs.br +0 -0
  66. package/dist/i18n.mjs.gz +0 -0
  67. package/dist/index.d.ts +702 -37
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +65 -41
  70. package/dist/index.js.br +0 -0
  71. package/dist/index.js.gz +0 -0
  72. package/dist/index.mjs +6 -6
  73. package/dist/index.mjs.br +0 -0
  74. package/dist/index.mjs.gz +0 -0
  75. package/dist/internals.d.ts +923 -54
  76. package/dist/internals.d.ts.map +1 -1
  77. package/dist/internals.js +79 -79
  78. package/dist/internals.js.br +0 -0
  79. package/dist/internals.js.gz +0 -0
  80. package/dist/internals.mjs +4 -4
  81. package/dist/internals.mjs.br +0 -0
  82. package/dist/internals.mjs.gz +0 -0
  83. package/dist/pptx-viewer.css +1 -1
  84. package/dist/pptx-viewer.css.br +0 -0
  85. package/dist/pptx-viewer.css.gz +0 -0
  86. package/dist/{types-DU35aAJK.d.ts → types-C_CTI-QE.d.ts} +3 -31
  87. package/dist/types-C_CTI-QE.d.ts.map +1 -0
  88. package/dist/{useViewerBuildingBlocks-Xddn6SFj.d.ts → useViewerBuildingBlocks-DItilDbP.d.ts} +47 -8
  89. package/dist/useViewerBuildingBlocks-DItilDbP.d.ts.map +1 -0
  90. package/dist/viewer/index.d.ts +593 -56
  91. package/dist/viewer/index.js +27 -27
  92. package/dist/viewer/index.js.br +0 -0
  93. package/dist/viewer/index.js.gz +0 -0
  94. package/dist/viewer/index.mjs +6 -6
  95. package/dist/viewer/index.mjs.br +0 -0
  96. package/dist/viewer/index.mjs.gz +0 -0
  97. package/package.json +2 -2
  98. package/dist/AiChatPanel-EPMBL6EA.js.br +0 -0
  99. package/dist/AiChatPanel-EPMBL6EA.js.gz +0 -0
  100. package/dist/AiChatPanel-XHKYPYPH.mjs.br +0 -0
  101. package/dist/AiChatPanel-XHKYPYPH.mjs.gz +0 -0
  102. package/dist/Model3DScene-DUJOZA2B.js.br +0 -0
  103. package/dist/Model3DScene-DUJOZA2B.js.gz +0 -0
  104. package/dist/Model3DScene-YMIAGRPG.mjs.br +0 -0
  105. package/dist/Model3DScene-YMIAGRPG.mjs.gz +0 -0
  106. package/dist/PowerPointViewer-Du7u4INi.d.ts.map +0 -1
  107. package/dist/SurfaceChart3DScene-Q47OEJXS.mjs.br +0 -0
  108. package/dist/SurfaceChart3DScene-Q47OEJXS.mjs.gz +0 -0
  109. package/dist/SurfaceChart3DScene-TNCHWQAK.js.br +0 -0
  110. package/dist/SurfaceChart3DScene-TNCHWQAK.js.gz +0 -0
  111. package/dist/chunk-5IUEPQTK.mjs.br +0 -0
  112. package/dist/chunk-5IUEPQTK.mjs.gz +0 -0
  113. package/dist/chunk-DVZF4ARG.js.br +0 -0
  114. package/dist/chunk-DVZF4ARG.js.gz +0 -0
  115. package/dist/chunk-EL2YF26P.mjs.br +0 -0
  116. package/dist/chunk-EL2YF26P.mjs.gz +0 -0
  117. package/dist/chunk-ESC6IB2F.js.br +0 -0
  118. package/dist/chunk-ESC6IB2F.js.gz +0 -0
  119. package/dist/chunk-FSVE6WUY.js.br +0 -0
  120. package/dist/chunk-FSVE6WUY.js.gz +0 -0
  121. package/dist/chunk-G3VAE7ZF.mjs.br +0 -0
  122. package/dist/chunk-G3VAE7ZF.mjs.gz +0 -0
  123. package/dist/chunk-J7EFC3GS.mjs.br +0 -0
  124. package/dist/chunk-J7EFC3GS.mjs.gz +0 -0
  125. package/dist/chunk-PI5SFTDC.js.br +0 -0
  126. package/dist/chunk-PI5SFTDC.js.gz +0 -0
  127. package/dist/chunk-VHME5BE6.mjs.br +0 -0
  128. package/dist/chunk-VHME5BE6.mjs.gz +0 -0
  129. package/dist/chunk-WK22Z7PK.js.br +0 -0
  130. package/dist/chunk-WK22Z7PK.js.gz +0 -0
  131. package/dist/chunk-Y2KIB3QH.js.br +0 -0
  132. package/dist/chunk-Y2KIB3QH.js.gz +0 -0
  133. package/dist/chunk-YWKUIUQX.mjs.br +0 -0
  134. package/dist/chunk-YWKUIUQX.mjs.gz +0 -0
  135. package/dist/types-DU35aAJK.d.ts.map +0 -1
  136. package/dist/useViewerBuildingBlocks-Xddn6SFj.d.ts.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkWK22Z7PK_js = require('./chunk-WK22Z7PK.js');
4
- var chunkDVZF4ARG_js = require('./chunk-DVZF4ARG.js');
5
- var chunkY2KIB3QH_js = require('./chunk-Y2KIB3QH.js');
3
+ var chunk4LWGAVAP_js = require('./chunk-4LWGAVAP.js');
4
+ var chunkRTUGI4HQ_js = require('./chunk-RTUGI4HQ.js');
5
+ var chunkWVDM36ZM_js = require('./chunk-WVDM36ZM.js');
6
6
  var react = require('react');
7
7
  var JSZip = require('jszip');
8
8
  var reactI18next = require('react-i18next');
@@ -14,7 +14,7 @@ var JSZip__default = /*#__PURE__*/_interopDefault(JSZip);
14
14
  function useVirtualizedSlides({
15
15
  totalItems,
16
16
  itemHeight,
17
- overscan = chunkY2KIB3QH_js.DEFAULT_VIRTUAL_OVERSCAN
17
+ overscan = chunkWVDM36ZM_js.DEFAULT_VIRTUAL_OVERSCAN
18
18
  }) {
19
19
  const scrollContainerRef = react.useRef(null);
20
20
  const [scrollTop, setScrollTop] = react.useState(0);
@@ -44,7 +44,7 @@ function useVirtualizedSlides({
44
44
  resizeObserver?.disconnect();
45
45
  };
46
46
  }, []);
47
- const range = chunkY2KIB3QH_js.computeVirtualRange(totalItems, itemHeight, scrollTop, viewportHeight, overscan);
47
+ const range = chunkWVDM36ZM_js.computeVirtualRange(totalItems, itemHeight, scrollTop, viewportHeight, overscan);
48
48
  const safeItemHeight = Math.max(itemHeight, 1);
49
49
  const scrollToIndex = react.useCallback(
50
50
  (index, behavior = "smooth") => {
@@ -85,7 +85,7 @@ function usePresenceTracking({
85
85
  }) {
86
86
  const [remoteUsers, setRemoteUsers] = react.useState([]);
87
87
  const projectorRef = react.useRef(null);
88
- projectorRef.current ??= chunkY2KIB3QH_js.createPresenceProjector();
88
+ projectorRef.current ??= chunkWVDM36ZM_js.createPresenceProjector();
89
89
  const projector = projectorRef.current;
90
90
  const lastBroadcastRef = react.useRef(0);
91
91
  const pendingBroadcastRef = react.useRef(null);
@@ -110,7 +110,7 @@ function usePresenceTracking({
110
110
  awareness.setLocalStateField("presence", state);
111
111
  lastBroadcastRef.current = Date.now();
112
112
  };
113
- if (elapsed >= chunkY2KIB3QH_js.BROADCAST_THROTTLE_MS) {
113
+ if (elapsed >= chunkWVDM36ZM_js.BROADCAST_THROTTLE_MS) {
114
114
  if (pendingBroadcastRef.current) {
115
115
  clearTimeout(pendingBroadcastRef.current);
116
116
  pendingBroadcastRef.current = null;
@@ -120,7 +120,7 @@ function usePresenceTracking({
120
120
  pendingBroadcastRef.current = setTimeout(() => {
121
121
  pendingBroadcastRef.current = null;
122
122
  flush();
123
- }, chunkY2KIB3QH_js.BROADCAST_THROTTLE_MS - elapsed);
123
+ }, chunkWVDM36ZM_js.BROADCAST_THROTTLE_MS - elapsed);
124
124
  }
125
125
  },
126
126
  [awareness, userName, userColor, userAvatar, role]
@@ -200,7 +200,7 @@ function useYjsProvider({ config }) {
200
200
  const departureRef = react.useRef(null);
201
201
  const gateRef = react.useRef(null);
202
202
  if (!gateRef.current) {
203
- gateRef.current = chunkY2KIB3QH_js.createSyncGate(() => setSynced(true));
203
+ gateRef.current = chunkWVDM36ZM_js.createSyncGate(() => setSynced(true));
204
204
  }
205
205
  const teardown = react.useCallback(() => {
206
206
  if (timeoutRef.current) {
@@ -220,7 +220,7 @@ function useYjsProvider({ config }) {
220
220
  const buildCleanup = react.useCallback(
221
221
  (provider, yDoc) => () => {
222
222
  announceDeparture();
223
- chunkY2KIB3QH_js.clearLocalAwareness(provider.awareness);
223
+ chunkWVDM36ZM_js.clearLocalAwareness(provider.awareness);
224
224
  provider.destroy();
225
225
  yDoc.destroy();
226
226
  setDoc(null);
@@ -245,9 +245,9 @@ function useYjsProvider({ config }) {
245
245
  if (config.authToken) {
246
246
  opts.password = config.authToken;
247
247
  }
248
- const roomId = chunkY2KIB3QH_js.validateRoomId(config.roomId);
248
+ const roomId = chunkWVDM36ZM_js.validateRoomId(config.roomId);
249
249
  const provider = new WebrtcProvider(roomId, yDoc, opts);
250
- departureRef.current = chunkY2KIB3QH_js.createDepartureChannel(roomId, provider.awareness);
250
+ departureRef.current = chunkWVDM36ZM_js.createDepartureChannel(roomId, provider.awareness);
251
251
  setDoc(yDoc);
252
252
  setAwareness(provider.awareness);
253
253
  setClientId(provider.awareness.clientID);
@@ -289,13 +289,13 @@ function useYjsProvider({ config }) {
289
289
  if (!config) {
290
290
  return;
291
291
  }
292
- const roomId = chunkY2KIB3QH_js.validateRoomId(config.roomId);
293
- const transport = config.transport ?? chunkY2KIB3QH_js.resolveTransportForServerUrl(config.serverUrl);
292
+ const roomId = chunkWVDM36ZM_js.validateRoomId(config.roomId);
293
+ const transport = config.transport ?? chunkWVDM36ZM_js.resolveTransportForServerUrl(config.serverUrl);
294
294
  if (transport === "webrtc") {
295
295
  await initWebrtc();
296
296
  return;
297
297
  }
298
- if (chunkY2KIB3QH_js.isMixedContentBlocked(config.serverUrl)) {
298
+ if (chunkWVDM36ZM_js.isMixedContentBlocked(config.serverUrl)) {
299
299
  console.warn(
300
300
  `[pptx-viewer] Refusing to connect: insecure ws:// server "${config.serverUrl}" is blocked from a secure (https) page. Use a wss:// URL.`
301
301
  );
@@ -309,7 +309,7 @@ function useYjsProvider({ config }) {
309
309
  const provider = new WebsocketProvider(config.serverUrl, roomId, yDoc, {
310
310
  params: config.authToken ? { token: config.authToken } : void 0
311
311
  });
312
- departureRef.current = chunkY2KIB3QH_js.createDepartureChannel(roomId, provider.awareness);
312
+ departureRef.current = chunkWVDM36ZM_js.createDepartureChannel(roomId, provider.awareness);
313
313
  let connected = false;
314
314
  const handleStatus = (event) => {
315
315
  if (event.status === "connected") {
@@ -349,7 +349,7 @@ function useYjsProvider({ config }) {
349
349
  provider.off("status", handleStatus);
350
350
  provider.off("sync", handleSynced);
351
351
  announceDeparture();
352
- chunkY2KIB3QH_js.clearLocalAwareness(provider.awareness);
352
+ chunkWVDM36ZM_js.clearLocalAwareness(provider.awareness);
353
353
  provider.destroy();
354
354
  yDoc.destroy();
355
355
  setDoc(null);
@@ -358,7 +358,7 @@ function useYjsProvider({ config }) {
358
358
  cleanupRef.current = null;
359
359
  setStatus("error");
360
360
  }
361
- }, chunkY2KIB3QH_js.CONNECTION_TIMEOUT_MS);
361
+ }, chunkWVDM36ZM_js.CONNECTION_TIMEOUT_MS);
362
362
  }
363
363
  setDoc(yDoc);
364
364
  setAwareness(provider.awareness);
@@ -367,7 +367,7 @@ function useYjsProvider({ config }) {
367
367
  provider.off("status", handleStatus);
368
368
  provider.off("sync", handleSynced);
369
369
  announceDeparture();
370
- chunkY2KIB3QH_js.clearLocalAwareness(provider.awareness);
370
+ chunkWVDM36ZM_js.clearLocalAwareness(provider.awareness);
371
371
  provider.destroy();
372
372
  yDoc.destroy();
373
373
  setDoc(null);
@@ -393,7 +393,7 @@ function useYjsProvider({ config }) {
393
393
  ]);
394
394
  react.useEffect(() => {
395
395
  init();
396
- const disposeTeardown = chunkY2KIB3QH_js.registerCollaborationTeardown({
396
+ const disposeTeardown = chunkWVDM36ZM_js.registerCollaborationTeardown({
397
397
  leave: teardown,
398
398
  rejoin: init
399
399
  });
@@ -414,7 +414,7 @@ function useCollaborativeState({
414
414
  canvasWidth,
415
415
  canvasHeight
416
416
  }) {
417
- const userColor = chunkY2KIB3QH_js.sanitizeColor(config?.userColor, "#6366f1");
417
+ const userColor = chunkWVDM36ZM_js.sanitizeColor(config?.userColor, "#6366f1");
418
418
  const { status, awareness, doc, clientId, synced, retry } = useYjsProvider({ config });
419
419
  const { remoteUsers, broadcastPresence } = usePresenceTracking({
420
420
  awareness,
@@ -490,6 +490,7 @@ function useEditorHistory(input) {
490
490
  maxHistoryEntries = DEFAULT_MAX_HISTORY_ENTRIES,
491
491
  hasActivePointerInteraction,
492
492
  pointerCommitNonce,
493
+ onDirty,
493
494
  setSlides,
494
495
  setCanvasSize,
495
496
  setActiveSlideIndex,
@@ -523,8 +524,8 @@ function useEditorHistory(input) {
523
524
  width: canvasSize.width,
524
525
  height: canvasSize.height,
525
526
  activeSlideIndex,
526
- slides: slides.map(chunkY2KIB3QH_js.cloneSlide),
527
- templateElementsBySlideId: chunkY2KIB3QH_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
527
+ slides: slides.map(chunkWVDM36ZM_js.cloneSlide),
528
+ templateElementsBySlideId: chunkWVDM36ZM_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
528
529
  ...actionLabel ? { actionLabel } : {}
529
530
  };
530
531
  },
@@ -537,9 +538,9 @@ function useEditorHistory(input) {
537
538
  width: snapshot.width,
538
539
  height: snapshot.height
539
540
  });
540
- setSlides(snapshot.slides.map(chunkY2KIB3QH_js.cloneSlide));
541
+ setSlides(snapshot.slides.map(chunkWVDM36ZM_js.cloneSlide));
541
542
  setTemplateElementsBySlideId(
542
- chunkY2KIB3QH_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
543
+ chunkWVDM36ZM_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
543
544
  );
544
545
  setActiveSlideIndex(Math.min(snapshot.activeSlideIndex, maxSlideIndex));
545
546
  setSelectedElementIds([]);
@@ -562,8 +563,13 @@ function useEditorHistory(input) {
562
563
  isApplyingHistoryRef.current = false;
563
564
  }, 0);
564
565
  }, []);
566
+ const onDirtyRef = react.useRef(onDirty);
567
+ react.useEffect(() => {
568
+ onDirtyRef.current = onDirty;
569
+ }, [onDirty]);
565
570
  const markDirty = react.useCallback(() => {
566
571
  setEditCommitNonce((previous) => previous + 1);
572
+ onDirtyRef.current?.();
567
573
  }, []);
568
574
  const handleUndo = react.useCallback(() => {
569
575
  const previousSnapshot = historyPastRef.current.pop();
@@ -573,8 +579,8 @@ function useEditorHistory(input) {
573
579
  const currentSnapshot = buildHistorySnapshot();
574
580
  historyFutureRef.current.push(currentSnapshot);
575
581
  isApplyingHistoryRef.current = true;
576
- const nextSnapshot = chunkWK22Z7PK_js.cloneHistorySnapshot(previousSnapshot);
577
- lastHistorySnapshotRef.current = chunkWK22Z7PK_js.cloneHistorySnapshot(nextSnapshot);
582
+ const nextSnapshot = chunk4LWGAVAP_js.cloneHistorySnapshot(previousSnapshot);
583
+ lastHistorySnapshotRef.current = chunk4LWGAVAP_js.cloneHistorySnapshot(nextSnapshot);
578
584
  lastHistorySerializedRef.current = JSON.stringify(nextSnapshot);
579
585
  applyHistorySnapshot(nextSnapshot);
580
586
  updateHistoryAvailability();
@@ -595,8 +601,8 @@ function useEditorHistory(input) {
595
601
  const currentSnapshot = buildHistorySnapshot();
596
602
  historyPastRef.current.push(currentSnapshot);
597
603
  isApplyingHistoryRef.current = true;
598
- const targetSnapshot = chunkWK22Z7PK_js.cloneHistorySnapshot(nextSnapshot);
599
- lastHistorySnapshotRef.current = chunkWK22Z7PK_js.cloneHistorySnapshot(targetSnapshot);
604
+ const targetSnapshot = chunk4LWGAVAP_js.cloneHistorySnapshot(nextSnapshot);
605
+ lastHistorySnapshotRef.current = chunk4LWGAVAP_js.cloneHistorySnapshot(targetSnapshot);
600
606
  lastHistorySerializedRef.current = JSON.stringify(targetSnapshot);
601
607
  applyHistorySnapshot(targetSnapshot);
602
608
  updateHistoryAvailability();
@@ -614,7 +620,7 @@ function useEditorHistory(input) {
614
620
  historyPastRef.current = [];
615
621
  historyFutureRef.current = [];
616
622
  if (initialSnapshot) {
617
- const clonedInitial = chunkWK22Z7PK_js.cloneHistorySnapshot(initialSnapshot);
623
+ const clonedInitial = chunk4LWGAVAP_js.cloneHistorySnapshot(initialSnapshot);
618
624
  lastHistorySnapshotRef.current = clonedInitial;
619
625
  lastHistorySerializedRef.current = JSON.stringify(clonedInitial);
620
626
  } else {
@@ -655,18 +661,19 @@ function useEditorHistory(input) {
655
661
  }
656
662
  const previousSnapshot = lastHistorySnapshotRef.current;
657
663
  if (!previousSnapshot) {
658
- lastHistorySnapshotRef.current = chunkWK22Z7PK_js.cloneHistorySnapshot(snapshot);
664
+ lastHistorySnapshotRef.current = chunk4LWGAVAP_js.cloneHistorySnapshot(snapshot);
659
665
  lastHistorySerializedRef.current = serialized;
660
666
  lastCheapHashRef.current = cheapHash;
661
667
  updateHistoryAvailability();
662
668
  return;
663
669
  }
664
- historyPastRef.current.push(chunkWK22Z7PK_js.cloneHistorySnapshot(previousSnapshot));
670
+ onDirtyRef.current?.();
671
+ historyPastRef.current.push(chunk4LWGAVAP_js.cloneHistorySnapshot(previousSnapshot));
665
672
  while (historyPastRef.current.length > Math.max(1, maxHistoryEntries)) {
666
673
  historyPastRef.current.shift();
667
674
  }
668
675
  historyFutureRef.current = [];
669
- lastHistorySnapshotRef.current = chunkWK22Z7PK_js.cloneHistorySnapshot(snapshot);
676
+ lastHistorySnapshotRef.current = chunk4LWGAVAP_js.cloneHistorySnapshot(snapshot);
670
677
  lastHistorySerializedRef.current = serialized;
671
678
  lastCheapHashRef.current = cheapHash;
672
679
  updateHistoryAvailability();
@@ -726,9 +733,9 @@ function useZoomViewport({
726
733
  const canvasStageRef = react.useRef(null);
727
734
  const canvasViewportRef = react.useRef(null);
728
735
  const renderScaleRef = react.useRef(1);
729
- const wheelBufferRef = react.useRef(chunkY2KIB3QH_js.createWheelStepBuffer());
736
+ const wheelBufferRef = react.useRef(chunkWVDM36ZM_js.createWheelStepBuffer());
730
737
  const storeRef = react.useRef(null);
731
- storeRef.current ??= chunkY2KIB3QH_js.createViewerZoomStore();
738
+ storeRef.current ??= chunkWVDM36ZM_js.createViewerZoomStore();
732
739
  const store = storeRef.current;
733
740
  const scale = useViewerStore(store, selectZoom);
734
741
  const setScale = react.useCallback(
@@ -789,7 +796,7 @@ function useZoomViewport({
789
796
  if (!wrapper || !canvasViewport) {
790
797
  return;
791
798
  }
792
- const boundedScale = chunkY2KIB3QH_js.clampZoomScale(nextScale);
799
+ const boundedScale = chunkWVDM36ZM_js.clampZoomScale(nextScale);
793
800
  const nextEditorScale = fitScale * boundedScale;
794
801
  const centerX = (bounds.minX + bounds.maxX) / 2;
795
802
  const centerY = (bounds.minY + bounds.maxY) / 2;
@@ -826,29 +833,29 @@ function useZoomViewport({
826
833
  selectedElements.forEach((element) => {
827
834
  minX = Math.min(minX, element.x);
828
835
  minY = Math.min(minY, element.y);
829
- maxX = Math.max(maxX, element.x + Math.max(element.width, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE));
830
- maxY = Math.max(maxY, element.y + Math.max(element.height, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE));
836
+ maxX = Math.max(maxX, element.x + Math.max(element.width, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE));
837
+ maxY = Math.max(maxY, element.y + Math.max(element.height, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE));
831
838
  });
832
839
  if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {
833
840
  return;
834
841
  }
835
842
  const selectionBounds = { minX, minY, maxX, maxY };
836
- const boundsWidth = Math.max(selectionBounds.maxX - selectionBounds.minX, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE);
837
- const boundsHeight = Math.max(selectionBounds.maxY - selectionBounds.minY, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE);
843
+ const boundsWidth = Math.max(selectionBounds.maxX - selectionBounds.minX, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE);
844
+ const boundsHeight = Math.max(selectionBounds.maxY - selectionBounds.minY, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE);
838
845
  const availableWidth = Math.max(
839
- effectiveEditorDimensions.width - chunkWK22Z7PK_js.ZOOM_TO_SELECTION_PADDING,
840
- chunkWK22Z7PK_js.MIN_ELEMENT_SIZE
846
+ effectiveEditorDimensions.width - chunk4LWGAVAP_js.ZOOM_TO_SELECTION_PADDING,
847
+ chunk4LWGAVAP_js.MIN_ELEMENT_SIZE
841
848
  );
842
849
  const availableHeight = Math.max(
843
- effectiveEditorDimensions.height - chunkWK22Z7PK_js.ZOOM_TO_SELECTION_PADDING,
844
- chunkWK22Z7PK_js.MIN_ELEMENT_SIZE
850
+ effectiveEditorDimensions.height - chunk4LWGAVAP_js.ZOOM_TO_SELECTION_PADDING,
851
+ chunk4LWGAVAP_js.MIN_ELEMENT_SIZE
845
852
  );
846
853
  const targetEditorScale = Math.min(
847
854
  availableWidth / boundsWidth,
848
855
  availableHeight / boundsHeight
849
856
  );
850
857
  const safeFitScale = fitScale > Number.EPSILON ? fitScale : Number.EPSILON;
851
- const nextScale = chunkY2KIB3QH_js.clampZoomScale(targetEditorScale / safeFitScale);
858
+ const nextScale = chunkWVDM36ZM_js.clampZoomScale(targetEditorScale / safeFitScale);
852
859
  setScale(nextScale);
853
860
  window.requestAnimationFrame(() => {
854
861
  window.requestAnimationFrame(() => {
@@ -865,14 +872,14 @@ function useZoomViewport({
865
872
  ]);
866
873
  const handleWheel = react.useCallback(
867
874
  (event) => {
868
- const mapped = chunkY2KIB3QH_js.mapEditingWheel(event, wheelBufferRef.current, true);
875
+ const mapped = chunkWVDM36ZM_js.mapEditingWheel(event, wheelBufferRef.current, true);
869
876
  if (mapped.intent !== "zoom") {
870
877
  return;
871
878
  }
872
879
  event.preventDefault();
873
880
  store.dispatch({
874
881
  type: "set-zoom",
875
- zoom: chunkY2KIB3QH_js.clampZoomScale(store.getState().zoom + mapped.deltaScale)
882
+ zoom: chunkWVDM36ZM_js.clampZoomScale(store.getState().zoom + mapped.deltaScale)
876
883
  });
877
884
  },
878
885
  [store]
@@ -960,7 +967,7 @@ function applyAnimationGroupSteps(group, onPlayActionSound, setPresentationEleme
960
967
  const command = step.command;
961
968
  const timer = window.setTimeout(
962
969
  () => {
963
- chunkWK22Z7PK_js.executeMediaCommand(command);
970
+ chunk4LWGAVAP_js.executeMediaCommand(command);
964
971
  },
965
972
  Math.max(0, step.delayMs)
966
973
  );
@@ -1097,7 +1104,7 @@ function scheduleEntranceAnimationTimers(slide, setPresentationAnimations, prese
1097
1104
  }))
1098
1105
  );
1099
1106
  entranceAnimations.forEach((animation, animationIndex) => {
1100
- const delay = chunkY2KIB3QH_js.computeEntranceAnimationDelay(animation.delayMs, animationIndex);
1107
+ const delay = chunkWVDM36ZM_js.computeEntranceAnimationDelay(animation.delayMs, animationIndex);
1101
1108
  const timer = window.setTimeout(() => {
1102
1109
  setPresentationAnimations(
1103
1110
  (previousAnimations) => previousAnimations.map(
@@ -1129,7 +1136,7 @@ function useAnimationPlayback(input) {
1129
1136
  (controller, group) => {
1130
1137
  driveBuildReveal(
1131
1138
  controller,
1132
- chunkY2KIB3QH_js.PresentationAnimationController.collectBuildStepIds(group),
1139
+ chunkWVDM36ZM_js.PresentationAnimationController.collectBuildStepIds(group),
1133
1140
  setPresentationElementStates,
1134
1141
  buildRafRef
1135
1142
  );
@@ -1192,7 +1199,7 @@ function useAnimationPlayback(input) {
1192
1199
  setHoverTriggerShapeIds(/* @__PURE__ */ new Set());
1193
1200
  return;
1194
1201
  }
1195
- const controller = chunkY2KIB3QH_js.PresentationAnimationController.fromSlide(slide);
1202
+ const controller = chunkWVDM36ZM_js.PresentationAnimationController.fromSlide(slide);
1196
1203
  controllerRef.current = controller;
1197
1204
  setPresentationKeyframesCss(controller.keyframesCss);
1198
1205
  setInteractiveTriggerShapeIds(controller.interactiveTriggerShapeIds);
@@ -1350,12 +1357,12 @@ function useAnimationPlayback(input) {
1350
1357
  presentationTimersRef
1351
1358
  };
1352
1359
  }
1353
- var PRESENTER_CHANNEL_NAME = chunkY2KIB3QH_js.PRESENTATION_CHANNEL_NAME;
1354
- var AUDIENCE_HASH = chunkY2KIB3QH_js.PRESENTATION_HASH;
1355
- var PRESENTER_MSG_ORIGIN = chunkY2KIB3QH_js.PRESENTATION_MESSAGE_ORIGIN;
1356
- var AUDIENCE_NONCE_KEY = chunkY2KIB3QH_js.PRESENTATION_NONCE_KEY;
1360
+ var PRESENTER_CHANNEL_NAME = chunkWVDM36ZM_js.PRESENTATION_CHANNEL_NAME;
1361
+ var AUDIENCE_HASH = chunkWVDM36ZM_js.PRESENTATION_HASH;
1362
+ var PRESENTER_MSG_ORIGIN = chunkWVDM36ZM_js.PRESENTATION_MESSAGE_ORIGIN;
1363
+ var AUDIENCE_NONCE_KEY = chunkWVDM36ZM_js.PRESENTATION_NONCE_KEY;
1357
1364
  function generateSessionId() {
1358
- return chunkY2KIB3QH_js.createPresentationSessionId();
1365
+ return chunkWVDM36ZM_js.createPresentationSessionId();
1359
1366
  }
1360
1367
  function parseAudienceNonce() {
1361
1368
  const hash = window.location.hash;
@@ -1391,7 +1398,7 @@ function usePresenterWindow(input) {
1391
1398
  }, []);
1392
1399
  const swapDisplays = react.useCallback(async () => {
1393
1400
  const audience = audienceWindowRef.current;
1394
- return audience && !audience.closed ? chunkY2KIB3QH_js.swapPresentationWindows(window, audience) : false;
1401
+ return audience && !audience.closed ? chunkWVDM36ZM_js.swapPresentationWindows(window, audience) : false;
1395
1402
  }, []);
1396
1403
  const syncSlideToAudience = react.useCallback(
1397
1404
  (slideIndex) => {
@@ -1455,7 +1462,7 @@ function usePresenterWindow(input) {
1455
1462
  pollTimerRef.current = null;
1456
1463
  }
1457
1464
  if (closingSessionId) {
1458
- void chunkY2KIB3QH_js.clearAudienceContent(closingSessionId);
1465
+ void chunkWVDM36ZM_js.clearAudienceContent(closingSessionId);
1459
1466
  }
1460
1467
  }, [getChannel]);
1461
1468
  const openAudienceWindow = react.useCallback(() => {
@@ -1473,10 +1480,10 @@ function usePresenterWindow(input) {
1473
1480
  audienceWindowRef.current = blankWin;
1474
1481
  const sessionId = generateSessionId();
1475
1482
  sessionIdRef.current = sessionId;
1476
- const audienceUrl = chunkY2KIB3QH_js.buildPresentationAudienceUrl(window.location.href, sessionId);
1477
- void chunkY2KIB3QH_js.resolveAudienceScreenPlacement(window).then((placement) => {
1483
+ const audienceUrl = chunkWVDM36ZM_js.buildPresentationAudienceUrl(window.location.href, sessionId);
1484
+ void chunkWVDM36ZM_js.resolveAudienceScreenPlacement(window).then((placement) => {
1478
1485
  if (placement && audienceWindowRef.current === blankWin && !blankWin.closed) {
1479
- chunkY2KIB3QH_js.placeAudienceWindow(blankWin, placement);
1486
+ chunkWVDM36ZM_js.placeAudienceWindow(blankWin, placement);
1480
1487
  }
1481
1488
  return void 0;
1482
1489
  });
@@ -1506,7 +1513,7 @@ function usePresenterWindow(input) {
1506
1513
  }
1507
1514
  };
1508
1515
  if (content) {
1509
- void chunkY2KIB3QH_js.storeAudienceContent(content, sessionId).then(() => navigateOrClose(true)).catch(() => navigateOrClose(false));
1516
+ void chunkWVDM36ZM_js.storeAudienceContent(content, sessionId).then(() => navigateOrClose(true)).catch(() => navigateOrClose(false));
1510
1517
  } else {
1511
1518
  navigateOrClose(true);
1512
1519
  }
@@ -1532,7 +1539,7 @@ function usePresenterWindow(input) {
1532
1539
  }
1533
1540
  const handleMessage = (event) => {
1534
1541
  const message = event.data;
1535
- if (chunkY2KIB3QH_js.isPresentationSessionMessage(message) && message.type === "audience-ready" && message.sessionId === sessionIdRef.current) {
1542
+ if (chunkWVDM36ZM_js.isPresentationSessionMessage(message) && message.type === "audience-ready" && message.sessionId === sessionIdRef.current) {
1536
1543
  syncStateToAudience(snapshotRef.current);
1537
1544
  }
1538
1545
  };
@@ -1561,7 +1568,7 @@ function usePresenterWindow(input) {
1561
1568
  react.useEffect(() => {
1562
1569
  const handleBeforeUnload = () => {
1563
1570
  if (sessionIdRef.current) {
1564
- void chunkY2KIB3QH_js.clearAudienceContent(sessionIdRef.current);
1571
+ void chunkWVDM36ZM_js.clearAudienceContent(sessionIdRef.current);
1565
1572
  }
1566
1573
  };
1567
1574
  window.addEventListener("beforeunload", handleBeforeUnload);
@@ -1623,7 +1630,7 @@ function useAudienceMode(input) {
1623
1630
  }
1624
1631
  channel.onmessage = (event) => {
1625
1632
  const data = event.data;
1626
- if (!chunkY2KIB3QH_js.isPresentationSessionMessage(data) || data.origin !== PRESENTER_MSG_ORIGIN) {
1633
+ if (!chunkWVDM36ZM_js.isPresentationSessionMessage(data) || data.origin !== PRESENTER_MSG_ORIGIN) {
1627
1634
  return;
1628
1635
  }
1629
1636
  if (expectedSessionId && data.sessionId !== expectedSessionId) {
@@ -1639,16 +1646,16 @@ function useAudienceMode(input) {
1639
1646
  }
1640
1647
  if (data.type === "presenter-exit") {
1641
1648
  if (expectedSessionId) {
1642
- void chunkY2KIB3QH_js.clearAudienceContent(expectedSessionId);
1649
+ void chunkWVDM36ZM_js.clearAudienceContent(expectedSessionId);
1643
1650
  }
1644
- if (chunkY2KIB3QH_js.endAudienceDisplay(window)) {
1651
+ if (chunkWVDM36ZM_js.endAudienceDisplay(window)) {
1645
1652
  handlers.onPresenterEnded?.();
1646
1653
  }
1647
1654
  }
1648
1655
  };
1649
1656
  if (expectedSessionId) {
1650
1657
  channel.postMessage({
1651
- origin: chunkY2KIB3QH_js.PRESENTATION_MESSAGE_ORIGIN,
1658
+ origin: chunkWVDM36ZM_js.PRESENTATION_MESSAGE_ORIGIN,
1652
1659
  type: "audience-ready",
1653
1660
  sessionId: expectedSessionId
1654
1661
  });
@@ -1662,7 +1669,7 @@ function useAudienceMode(input) {
1662
1669
  }, []);
1663
1670
  }
1664
1671
  function usePresentationKeyboard(input) {
1665
- const wheelBufferRef = react.useRef(chunkY2KIB3QH_js.createWheelStepBuffer());
1672
+ const wheelBufferRef = react.useRef(chunkWVDM36ZM_js.createWheelStepBuffer());
1666
1673
  const {
1667
1674
  mode,
1668
1675
  movePresentationSlide,
@@ -1675,6 +1682,7 @@ function usePresentationKeyboard(input) {
1675
1682
  onToggleInkMarkup,
1676
1683
  onToggleToolbar,
1677
1684
  onShowAllSlides,
1685
+ onToggleSubtitles,
1678
1686
  onToggleBlackScreen,
1679
1687
  onToggleWhiteScreen,
1680
1688
  rehearsing,
@@ -1682,14 +1690,14 @@ function usePresentationKeyboard(input) {
1682
1690
  presentationSlideIndex,
1683
1691
  setShowRehearsalSummary
1684
1692
  } = input;
1685
- const keyBufferRef = react.useRef(chunkY2KIB3QH_js.createPresentationKeyBuffer());
1693
+ const keyBufferRef = react.useRef(chunkWVDM36ZM_js.createPresentationKeyBuffer());
1686
1694
  react.useEffect(() => {
1687
- if (mode !== "present" || !chunkY2KIB3QH_js.acceptsPresentationInput()) {
1688
- keyBufferRef.current = chunkY2KIB3QH_js.createPresentationKeyBuffer();
1695
+ if (mode !== "present" || !chunkWVDM36ZM_js.acceptsPresentationInput()) {
1696
+ keyBufferRef.current = chunkWVDM36ZM_js.createPresentationKeyBuffer();
1689
1697
  return;
1690
1698
  }
1691
1699
  const handleKeyDown = (event) => {
1692
- const mapped = chunkY2KIB3QH_js.mapPresentationKey(event, keyBufferRef.current);
1700
+ const mapped = chunkWVDM36ZM_js.mapPresentationKey(event, keyBufferRef.current);
1693
1701
  if (mapped.action === "none") {
1694
1702
  return;
1695
1703
  }
@@ -1709,12 +1717,12 @@ function usePresentationKeyboard(input) {
1709
1717
  movePresentationSlide(-1);
1710
1718
  return;
1711
1719
  case "first": {
1712
- const first = chunkY2KIB3QH_js.firstShowSlideIndex(showSlideIndexes);
1720
+ const first = chunkWVDM36ZM_js.firstShowSlideIndex(showSlideIndexes);
1713
1721
  navigateToSlide(first ?? 0);
1714
1722
  return;
1715
1723
  }
1716
1724
  case "last": {
1717
- const last = chunkY2KIB3QH_js.lastShowSlideIndex(showSlideIndexes);
1725
+ const last = chunkWVDM36ZM_js.lastShowSlideIndex(showSlideIndexes);
1718
1726
  navigateToSlide(last ?? Math.max(0, slideCount - 1));
1719
1727
  return;
1720
1728
  }
@@ -1740,6 +1748,9 @@ function usePresentationKeyboard(input) {
1740
1748
  case "showAllSlides":
1741
1749
  onShowAllSlides?.();
1742
1750
  return;
1751
+ case "toggleSubtitles":
1752
+ onToggleSubtitles?.();
1753
+ return;
1743
1754
  case "toggleBlackScreen":
1744
1755
  onToggleBlackScreen?.();
1745
1756
  return;
@@ -1749,10 +1760,10 @@ function usePresentationKeyboard(input) {
1749
1760
  }
1750
1761
  };
1751
1762
  const handleWheel = (event) => {
1752
- if (mode !== "present" || !chunkY2KIB3QH_js.acceptsPresentationInput()) {
1763
+ if (mode !== "present" || !chunkWVDM36ZM_js.acceptsPresentationInput()) {
1753
1764
  return;
1754
1765
  }
1755
- const mapped = chunkY2KIB3QH_js.mapPresentationWheel(event, wheelBufferRef.current);
1766
+ const mapped = chunkWVDM36ZM_js.mapPresentationWheel(event, wheelBufferRef.current);
1756
1767
  if (mapped.intent === "next-slide") {
1757
1768
  event.preventDefault();
1758
1769
  movePresentationSlide(1);
@@ -1779,6 +1790,7 @@ function usePresentationKeyboard(input) {
1779
1790
  onToggleInkMarkup,
1780
1791
  onToggleToolbar,
1781
1792
  onShowAllSlides,
1793
+ onToggleSubtitles,
1782
1794
  onToggleBlackScreen,
1783
1795
  onToggleWhiteScreen,
1784
1796
  rehearsing,
@@ -1884,7 +1896,7 @@ function useRehearsalTimings(input) {
1884
1896
 
1885
1897
  // src/viewer/hooks/presentation-mode/presentation-actions.ts
1886
1898
  function handlePresentationActionImpl(action, deps) {
1887
- chunkY2KIB3QH_js.runPresentationAction(
1899
+ chunkWVDM36ZM_js.runPresentationAction(
1888
1900
  action,
1889
1901
  { slideCount: deps.slidesLength },
1890
1902
  {
@@ -1906,7 +1918,7 @@ function handlePresentationActionImpl(action, deps) {
1906
1918
  function executeSlideTransition(nextSlideIndex, deps) {
1907
1919
  const incomingSlide = deps.slides[nextSlideIndex];
1908
1920
  const transition = incomingSlide?.transition;
1909
- const durationMs = deps.playTransition ? chunkY2KIB3QH_js.resolveTransitionDurationMs(transition) : 0;
1921
+ const durationMs = deps.playTransition ? chunkWVDM36ZM_js.resolveTransitionDurationMs(transition) : 0;
1910
1922
  deps.clearPresentationTimers();
1911
1923
  deps.setPresentationSlideIndex(nextSlideIndex);
1912
1924
  deps.onSetActiveSlideIndex(nextSlideIndex);
@@ -1965,7 +1977,7 @@ function useSlideNavigation(input) {
1965
1977
  });
1966
1978
  const scheduleAutoAdvanceForSlide = react.useCallback(
1967
1979
  (slideIndex) => {
1968
- const delayMs = chunkY2KIB3QH_js.resolveAutoAdvanceDelayMs(slides[slideIndex], { useTimings });
1980
+ const delayMs = chunkWVDM36ZM_js.resolveAutoAdvanceDelayMs(slides[slideIndex], { useTimings });
1969
1981
  if (delayMs === void 0) {
1970
1982
  return;
1971
1983
  }
@@ -1988,7 +2000,7 @@ function useSlideNavigation(input) {
1988
2000
  if (availableSlideIndexes.length === 0) {
1989
2001
  return;
1990
2002
  }
1991
- const pastLastSlide = direction === 1 && !chunkY2KIB3QH_js.hasShowSlideAfter(presentationSlideIndex, availableSlideIndexes);
2003
+ const pastLastSlide = direction === 1 && !chunkWVDM36ZM_js.hasShowSlideAfter(presentationSlideIndex, availableSlideIndexes);
1992
2004
  if (rehearsing && pastLastSlide) {
1993
2005
  recordCurrentSlideTime(presentationSlideIndex);
1994
2006
  try {
@@ -2006,9 +2018,9 @@ function useSlideNavigation(input) {
2006
2018
  onAdvancePastLastSlide();
2007
2019
  return;
2008
2020
  }
2009
- const nextSlideIndex = direction === 1 ? chunkY2KIB3QH_js.nextShowSlideIndex(presentationSlideIndex, availableSlideIndexes, {
2021
+ const nextSlideIndex = direction === 1 ? chunkWVDM36ZM_js.nextShowSlideIndex(presentationSlideIndex, availableSlideIndexes, {
2010
2022
  loop: Boolean(loopContinuously) && !rehearsing
2011
- }) : chunkY2KIB3QH_js.previousShowSlideIndex(presentationSlideIndex, availableSlideIndexes);
2023
+ }) : chunkWVDM36ZM_js.previousShowSlideIndex(presentationSlideIndex, availableSlideIndexes);
2012
2024
  if (nextSlideIndex === void 0 || nextSlideIndex === presentationSlideIndex) {
2013
2025
  return;
2014
2026
  }
@@ -2153,22 +2165,22 @@ function useZoomNavigation(input) {
2153
2165
  };
2154
2166
  }
2155
2167
  function usePresenterConsole(slideIndex, active) {
2156
- const timerRef = react.useRef(chunkY2KIB3QH_js.createPresenterTimer());
2157
- const [snapshot, setSnapshot] = react.useState(() => chunkY2KIB3QH_js.createInitialPresentationSnapshot(slideIndex));
2168
+ const timerRef = react.useRef(chunkWVDM36ZM_js.createPresenterTimer());
2169
+ const [snapshot, setSnapshot] = react.useState(() => chunkWVDM36ZM_js.createInitialPresentationSnapshot(slideIndex));
2158
2170
  const patch = react.useCallback((value) => {
2159
- setSnapshot((current) => chunkY2KIB3QH_js.mergePresentationSnapshot(current, value));
2171
+ setSnapshot((current) => chunkWVDM36ZM_js.mergePresentationSnapshot(current, value));
2160
2172
  }, []);
2161
2173
  react.useEffect(() => patch({ slideIndex }), [patch, slideIndex]);
2162
2174
  react.useEffect(() => {
2163
2175
  if (!active) {
2164
2176
  return;
2165
2177
  }
2166
- timerRef.current = chunkY2KIB3QH_js.resetPresenterTimer();
2178
+ timerRef.current = chunkWVDM36ZM_js.resetPresenterTimer();
2167
2179
  patch({ paused: false, elapsedMs: 0 });
2168
2180
  const timer = window.setInterval(() => {
2169
2181
  patch({
2170
2182
  paused: timerRef.current.paused,
2171
- elapsedMs: chunkY2KIB3QH_js.presenterElapsed(timerRef.current)
2183
+ elapsedMs: chunkWVDM36ZM_js.presenterElapsed(timerRef.current)
2172
2184
  });
2173
2185
  }, 1e3);
2174
2186
  return () => window.clearInterval(timer);
@@ -2178,19 +2190,19 @@ function usePresenterConsole(slideIndex, active) {
2178
2190
  applyAudienceSnapshot: setSnapshot,
2179
2191
  setBlackout: (blackout) => patch({ blackout }),
2180
2192
  toggleTimer: () => {
2181
- timerRef.current = chunkY2KIB3QH_js.togglePresenterTimer(timerRef.current);
2193
+ timerRef.current = chunkWVDM36ZM_js.togglePresenterTimer(timerRef.current);
2182
2194
  patch({
2183
2195
  paused: timerRef.current.paused,
2184
- elapsedMs: chunkY2KIB3QH_js.presenterElapsed(timerRef.current)
2196
+ elapsedMs: chunkWVDM36ZM_js.presenterElapsed(timerRef.current)
2185
2197
  });
2186
2198
  },
2187
2199
  resetTimer: () => {
2188
- timerRef.current = chunkY2KIB3QH_js.resetPresenterTimer();
2200
+ timerRef.current = chunkWVDM36ZM_js.resetPresenterTimer();
2189
2201
  patch({ paused: false, elapsedMs: 0 });
2190
2202
  },
2191
2203
  stepZoom: (direction) => setSnapshot(
2192
- (current) => chunkY2KIB3QH_js.mergePresentationSnapshot(current, {
2193
- zoom: chunkY2KIB3QH_js.stepPresenterZoom(
2204
+ (current) => chunkWVDM36ZM_js.mergePresentationSnapshot(current, {
2205
+ zoom: chunkWVDM36ZM_js.stepPresenterZoom(
2194
2206
  current.zoom ?? { scale: 1, originX: 0.5, originY: 0.5 },
2195
2207
  direction
2196
2208
  )
@@ -2219,6 +2231,7 @@ function usePresentationMode(input) {
2219
2231
  onEraseAnnotations,
2220
2232
  onToggleInkMarkup,
2221
2233
  onToggleToolbar,
2234
+ onToggleSubtitles,
2222
2235
  onSaveRehearsalTimings,
2223
2236
  loopContinuously,
2224
2237
  showWithAnimation,
@@ -2235,7 +2248,7 @@ function usePresentationMode(input) {
2235
2248
  const [allSlidesOpen, setAllSlidesOpen] = react.useState(false);
2236
2249
  const [endOfShowVisible, setEndOfShowVisible] = react.useState(false);
2237
2250
  const [presentationStartTime, setPresentationStartTime] = react.useState(null);
2238
- const showGuard = react.useMemo(() => chunkY2KIB3QH_js.createPresenterShowGuard(), []);
2251
+ const showGuard = react.useMemo(() => chunkWVDM36ZM_js.createPresenterShowGuard(), []);
2239
2252
  const {
2240
2253
  presentationAnimations,
2241
2254
  presentationElementStates,
@@ -2314,7 +2327,7 @@ function usePresentationMode(input) {
2314
2327
  });
2315
2328
  const movePresentationSlide = react.useCallback(
2316
2329
  (direction, trigger = "explicit") => {
2317
- if (!chunkY2KIB3QH_js.acceptsPresentationInput()) {
2330
+ if (!chunkWVDM36ZM_js.acceptsPresentationInput()) {
2318
2331
  return;
2319
2332
  }
2320
2333
  if (endOfShowVisible) {
@@ -2426,6 +2439,7 @@ function usePresentationMode(input) {
2426
2439
  onToggleInkMarkup,
2427
2440
  onToggleToolbar,
2428
2441
  onShowAllSlides: openAllSlides,
2442
+ onToggleSubtitles,
2429
2443
  onToggleBlackScreen: () => presenterConsole.setBlackout(
2430
2444
  presenterConsole.snapshot.blackout === "black" ? "none" : "black"
2431
2445
  ),
@@ -2451,7 +2465,7 @@ function usePresentationMode(input) {
2451
2465
  if (mode !== "present") {
2452
2466
  return;
2453
2467
  }
2454
- return chunkY2KIB3QH_js.attachPresentationVisibilityPause({
2468
+ return chunkWVDM36ZM_js.attachPresentationVisibilityPause({
2455
2469
  root: containerRef.current ?? void 0,
2456
2470
  onHidden: () => clearPresentationTimersRef.current(),
2457
2471
  onVisible: () => scheduleAutoAdvanceRef.current(presentationSlideIndexRef.current)
@@ -2531,11 +2545,11 @@ function usePresentationMode(input) {
2531
2545
  if (!transitionOverlay || transitionOverlay.transition.type !== "morph") {
2532
2546
  return void 0;
2533
2547
  }
2534
- return chunkY2KIB3QH_js.buildMorphTransitionPlan(
2548
+ return chunkWVDM36ZM_js.buildMorphTransitionPlan(
2535
2549
  slides[transitionOverlay.outgoingSlideIndex],
2536
2550
  slides[transitionOverlay.incomingSlideIndex],
2537
2551
  transitionOverlay.durationMs,
2538
- chunkY2KIB3QH_js.morphOptionToMode(transitionOverlay.transition.morphOption)
2552
+ chunkWVDM36ZM_js.morphOptionToMode(transitionOverlay.transition.morphOption)
2539
2553
  );
2540
2554
  }, [transitionOverlay, slides]);
2541
2555
  const morphedElementStates = react.useMemo(() => {
@@ -2556,7 +2570,7 @@ function usePresentationMode(input) {
2556
2570
  if (!morphPlan) {
2557
2571
  return presentationKeyframesCss;
2558
2572
  }
2559
- const imageRules = chunkY2KIB3QH_js.buildMorphAnimationRules(morphPlan, "", "incoming", "image");
2573
+ const imageRules = chunkWVDM36ZM_js.buildMorphAnimationRules(morphPlan, "", "incoming", "image");
2560
2574
  return `${presentationKeyframesCss ?? ""}
2561
2575
  ${morphPlan.keyframesCss}
2562
2576
  ${imageRules}`;
@@ -2852,7 +2866,7 @@ function useFindReplace({
2852
2866
  const [findResults, setFindResults] = react.useState([]);
2853
2867
  const [findResultIndex, setFindResultIndex] = react.useState(-1);
2854
2868
  const performFind = react.useCallback(() => {
2855
- const results = chunkY2KIB3QH_js.findInSlides(slides, findQuery, { matchCase: findMatchCase });
2869
+ const results = chunkWVDM36ZM_js.findInSlides(slides, findQuery, { matchCase: findMatchCase });
2856
2870
  if (!findQuery) {
2857
2871
  setFindResults([]);
2858
2872
  setFindResultIndex(-1);
@@ -2886,7 +2900,7 @@ function useFindReplace({
2886
2900
  return;
2887
2901
  }
2888
2902
  onUpdateSlides(
2889
- (prevSlides) => chunkY2KIB3QH_js.applyFindReplacements(prevSlides, toReplace, replaceQuery).slides
2903
+ (prevSlides) => chunkWVDM36ZM_js.applyFindReplacements(prevSlides, toReplace, replaceQuery).slides
2890
2904
  );
2891
2905
  onMarkDirty();
2892
2906
  },
@@ -2908,13 +2922,15 @@ function useFindReplace({
2908
2922
  }, [findResults, applyReplacements, performFind]);
2909
2923
  react.useEffect(() => {
2910
2924
  const handler = (event) => {
2911
- if ((event.metaKey || event.ctrlKey) && event.key === "f") {
2912
- if (mode !== "edit") {
2913
- return;
2914
- }
2915
- event.preventDefault();
2916
- setFindReplaceOpen((prev) => !prev);
2925
+ const { action } = chunkWVDM36ZM_js.mapEditorKey(event, {
2926
+ canEdit: mode === "edit",
2927
+ isTextInputTarget: chunkWVDM36ZM_js.isEditorTextInputTarget(event.target)
2928
+ });
2929
+ if (action !== "find") {
2930
+ return;
2917
2931
  }
2932
+ event.preventDefault();
2933
+ setFindReplaceOpen((prev) => !prev);
2918
2934
  };
2919
2935
  window.addEventListener("keydown", handler);
2920
2936
  return () => window.removeEventListener("keydown", handler);
@@ -3354,9 +3370,28 @@ function useDerivedElementState(input) {
3354
3370
  }
3355
3371
  return templateElementsBySlideId[activeSlide.id] ?? [];
3356
3372
  }, [activeSlide, templateElementsBySlideId]);
3373
+ const activeMaster = slideMasters[activeMasterIndex];
3374
+ const activeLayout = react.useMemo(
3375
+ () => resolveActiveLayout(activeMaster, activeLayoutIndex),
3376
+ [activeMaster, activeLayoutIndex]
3377
+ );
3378
+ const masterViewElements2 = react.useMemo(
3379
+ () => computeMasterViewElements(activeMaster, activeLayout),
3380
+ [activeMaster, activeLayout]
3381
+ );
3382
+ const notesMasterElements = react.useMemo(() => notesMaster?.elements ?? [], [notesMaster]);
3383
+ const handoutMasterElements = react.useMemo(() => handoutMaster?.elements ?? [], [handoutMaster]);
3357
3384
  const elementLookup = react.useMemo(
3358
- () => buildElementLookup(templateElements, activeSlide?.elements ?? []),
3359
- [activeSlide, templateElements]
3385
+ () => buildElementLookup(
3386
+ [
3387
+ ...templateElements,
3388
+ ...masterViewElements2,
3389
+ ...notesMasterElements,
3390
+ ...handoutMasterElements
3391
+ ],
3392
+ activeSlide?.elements ?? []
3393
+ ),
3394
+ [activeSlide, templateElements, masterViewElements2, notesMasterElements, handoutMasterElements]
3360
3395
  );
3361
3396
  const selectedElement = react.useMemo(() => {
3362
3397
  if (!selectedElementId) {
@@ -3373,17 +3408,6 @@ function useDerivedElementState(input) {
3373
3408
  () => effectiveSelectedIds.map((id) => elementLookup.get(id)).filter(Boolean),
3374
3409
  [effectiveSelectedIds, elementLookup]
3375
3410
  );
3376
- const activeMaster = slideMasters[activeMasterIndex];
3377
- const activeLayout = react.useMemo(
3378
- () => resolveActiveLayout(activeMaster, activeLayoutIndex),
3379
- [activeMaster, activeLayoutIndex]
3380
- );
3381
- const masterViewElements = react.useMemo(
3382
- () => computeMasterViewElements(activeMaster, activeLayout),
3383
- [activeMaster, activeLayout]
3384
- );
3385
- const notesMasterElements = react.useMemo(() => notesMaster?.elements ?? [], [notesMaster]);
3386
- const handoutMasterElements = react.useMemo(() => handoutMaster?.elements ?? [], [handoutMaster]);
3387
3411
  return {
3388
3412
  activeSlide,
3389
3413
  templateElements,
@@ -3394,7 +3418,7 @@ function useDerivedElementState(input) {
3394
3418
  selectedElements,
3395
3419
  activeMaster,
3396
3420
  activeLayout,
3397
- masterViewElements,
3421
+ masterViewElements: masterViewElements2,
3398
3422
  notesMasterElements,
3399
3423
  handoutMasterElements
3400
3424
  };
@@ -3410,7 +3434,7 @@ function useViewerCoreState(_input) {
3410
3434
  const marqueeStateRef = react.useRef(null);
3411
3435
  const isDrawingRef = react.useRef(false);
3412
3436
  const justInteractedRef = react.useRef(false);
3413
- const livePatcher = react.useMemo(() => chunkY2KIB3QH_js.createCollaborationLivePatcher(), []);
3437
+ const livePatcher = react.useMemo(() => chunkWVDM36ZM_js.createCollaborationLivePatcher(), []);
3414
3438
  react.useEffect(() => () => livePatcher.dispose(), [livePatcher]);
3415
3439
  const slidesRef = react.useRef([]);
3416
3440
  const [mode, setMode] = react.useState("edit");
@@ -3419,9 +3443,10 @@ function useViewerCoreState(_input) {
3419
3443
  const [slides, setSlides] = react.useState([]);
3420
3444
  const [templateElementsBySlideId, setTemplateElementsBySlideId] = react.useState({});
3421
3445
  const [canvasSize, setCanvasSize] = react.useState({
3422
- width: chunkWK22Z7PK_js.DEFAULT_CANVAS_WIDTH,
3423
- height: chunkWK22Z7PK_js.DEFAULT_CANVAS_HEIGHT
3446
+ width: chunk4LWGAVAP_js.DEFAULT_CANVAS_WIDTH,
3447
+ height: chunk4LWGAVAP_js.DEFAULT_CANVAS_HEIGHT
3424
3448
  });
3449
+ const [slideSizeEmu, setSlideSizeEmu] = react.useState();
3425
3450
  const [activeSlideIndex, setActiveSlideIndex] = react.useState(0);
3426
3451
  const [selectedElementId, setSelectedElementId] = react.useState(null);
3427
3452
  const [selectedElementIds, setSelectedElementIds] = react.useState([]);
@@ -3440,7 +3465,7 @@ function useViewerCoreState(_input) {
3440
3465
  const resolved = typeof value === "function" ? value(inlineEditingTextRef.current) : value;
3441
3466
  inlineEditingTextRef.current = resolved;
3442
3467
  setInlineEditingTextBase(value);
3443
- chunkY2KIB3QH_js.publishLiveInlineText(
3468
+ chunkWVDM36ZM_js.publishLiveInlineText(
3444
3469
  livePatcher,
3445
3470
  slidesRef.current[activeSlideIndexRef.current],
3446
3471
  inlineEditingElementIdRef.current,
@@ -3520,6 +3545,8 @@ function useViewerCoreState(_input) {
3520
3545
  setTemplateElementsBySlideId,
3521
3546
  canvasSize,
3522
3547
  setCanvasSize,
3548
+ slideSizeEmu,
3549
+ setSlideSizeEmu,
3523
3550
  activeSlideIndex,
3524
3551
  setActiveSlideIndex,
3525
3552
  selectedElementId,
@@ -3724,6 +3751,7 @@ function useLoadContent({
3724
3751
  setTemplateElementsBySlideId,
3725
3752
  mediaDataUrls,
3726
3753
  setCanvasSize,
3754
+ setSlideSizeEmu,
3727
3755
  setHeaderFooter,
3728
3756
  setLayoutOptions,
3729
3757
  setSlideMasters,
@@ -3731,6 +3759,7 @@ function useLoadContent({
3731
3759
  setTableStyleMap,
3732
3760
  setThemeOptions,
3733
3761
  setCustomShows,
3762
+ setActiveCustomShowId,
3734
3763
  setSections,
3735
3764
  setPresentationProperties,
3736
3765
  setNotesMaster,
@@ -3775,7 +3804,7 @@ function useLoadContent({
3775
3804
  );
3776
3805
  }
3777
3806
  const previousHandler = handlerRef.current;
3778
- const handler = new chunkY2KIB3QH_js.PptxHandler();
3807
+ const handler = new chunkWVDM36ZM_js.PptxHandler();
3779
3808
  const parsed = await handler.load(buffer);
3780
3809
  if (cancelled || token !== renderTokenRef.current) {
3781
3810
  handler.dispose();
@@ -3787,7 +3816,7 @@ function useLoadContent({
3787
3816
  handlerRef.current = null;
3788
3817
  const mediaElements = [];
3789
3818
  for (const slide of parsed.slides) {
3790
- chunkY2KIB3QH_js.collectMediaElements(slide.elements, mediaElements);
3819
+ chunkWVDM36ZM_js.collectMediaElements(slide.elements, mediaElements);
3791
3820
  }
3792
3821
  for (const url of mediaDataUrls.values()) {
3793
3822
  if (url.startsWith("blob:")) {
@@ -3828,7 +3857,7 @@ function useLoadContent({
3828
3857
  }
3829
3858
  })
3830
3859
  );
3831
- const { paths: imagePaths, refs: imageRefs } = chunkY2KIB3QH_js.collectImagePaths(parsed.slides);
3860
+ const { paths: imagePaths, refs: imageRefs } = chunkWVDM36ZM_js.collectImagePaths(parsed.slides);
3832
3861
  let nextSlides = parsed.slides;
3833
3862
  if (imagePaths.size > 0) {
3834
3863
  const resolvedMap = /* @__PURE__ */ new Map();
@@ -3883,13 +3912,20 @@ function useLoadContent({
3883
3912
  }
3884
3913
  }
3885
3914
  handlerRef.current = handler;
3886
- const partition = chunkY2KIB3QH_js.partitionTemplateElements(nextSlides);
3915
+ const partition = chunkWVDM36ZM_js.partitionTemplateElements(nextSlides);
3887
3916
  setSlides(partition.slides);
3888
3917
  setTemplateElementsBySlideId(partition.templateElementsBySlideId);
3889
3918
  setCanvasSize({
3890
- width: parsed.width ?? chunkWK22Z7PK_js.DEFAULT_CANVAS_WIDTH,
3891
- height: parsed.height ?? chunkWK22Z7PK_js.DEFAULT_CANVAS_HEIGHT
3919
+ width: parsed.width ?? chunk4LWGAVAP_js.DEFAULT_CANVAS_WIDTH,
3920
+ height: parsed.height ?? chunk4LWGAVAP_js.DEFAULT_CANVAS_HEIGHT
3892
3921
  });
3922
+ setSlideSizeEmu(
3923
+ typeof parsed.widthEmu === "number" && typeof parsed.heightEmu === "number" && parsed.widthEmu > 0 && parsed.heightEmu > 0 ? {
3924
+ widthEmu: parsed.widthEmu,
3925
+ heightEmu: parsed.heightEmu,
3926
+ type: parsed.slideSizeType ?? ""
3927
+ } : void 0
3928
+ );
3893
3929
  setHeaderFooter(parsed.headerFooter ?? {});
3894
3930
  setLayoutOptions(parsed.layoutOptions ?? []);
3895
3931
  setSlideMasters(parsed.slideMasters ?? []);
@@ -3897,6 +3933,9 @@ function useLoadContent({
3897
3933
  setTableStyleMap(parsed.tableStyleMap);
3898
3934
  setThemeOptions(parsed.themeOptions ?? []);
3899
3935
  setCustomShows(parsed.customShows ?? []);
3936
+ setActiveCustomShowId(
3937
+ chunkWVDM36ZM_js.resolveAuthoredCustomShowId(parsed.presentationProperties, parsed.customShows) ?? null
3938
+ );
3900
3939
  setSections(parsed.sections ?? []);
3901
3940
  setPresentationProperties(parsed.presentationProperties ?? {});
3902
3941
  setNotesMaster(parsed.notesMaster);
@@ -3917,7 +3956,7 @@ function useLoadContent({
3917
3956
  setHasMacros(parsed.hasMacros === true);
3918
3957
  setHasDigitalSignatures(parsed.hasDigitalSignatures === true);
3919
3958
  setDigitalSignatureCount(parsed.digitalSignatureCount ?? 0);
3920
- setGuides(chunkY2KIB3QH_js.buildInitialGuides(parsed.presentationGuides, parsed.slides[0]?.guides));
3959
+ setGuides(chunkWVDM36ZM_js.buildInitialGuides(parsed.presentationGuides, parsed.slides[0]?.guides));
3921
3960
  setActiveSlideIndex(0);
3922
3961
  clearSelection();
3923
3962
  setIsDirty(false);
@@ -3925,7 +3964,7 @@ function useLoadContent({
3925
3964
  onContentApplied?.();
3926
3965
  } catch (err) {
3927
3966
  if (!cancelled && token === renderTokenRef.current) {
3928
- if (err instanceof chunkY2KIB3QH_js.EncryptedFileError) {
3967
+ if (err instanceof chunkWVDM36ZM_js.EncryptedFileError) {
3929
3968
  setIsEncrypted(true);
3930
3969
  } else {
3931
3970
  setError(err instanceof Error ? err.message : String(err));
@@ -3965,7 +4004,8 @@ function useAutosave(input) {
3965
4004
  filePath,
3966
4005
  serializeSlides,
3967
4006
  intervalSeconds = DEFAULT_AUTOSAVE_INTERVAL_SECONDS,
3968
- enabled = true
4007
+ enabled = true,
4008
+ getChangeSources
3969
4009
  } = input;
3970
4010
  const [autosaveStatus, setAutosaveStatus] = react.useState({
3971
4011
  state: "idle"
@@ -3974,6 +4014,8 @@ function useAutosave(input) {
3974
4014
  const filePathRef = react.useRef(filePath);
3975
4015
  const serializeRef = react.useRef(serializeSlides);
3976
4016
  const isSavingRef = react.useRef(false);
4017
+ const changeSourcesRef = react.useRef(getChangeSources);
4018
+ const lastSnapshotRef = react.useRef(void 0);
3977
4019
  react.useEffect(() => {
3978
4020
  isDirtyRef.current = isDirty;
3979
4021
  }, [isDirty]);
@@ -3983,14 +4025,22 @@ function useAutosave(input) {
3983
4025
  react.useEffect(() => {
3984
4026
  serializeRef.current = serializeSlides;
3985
4027
  }, [serializeSlides]);
3986
- const doAutosave = react.useCallback(async () => {
3987
- if (!filePathRef.current) {
3988
- return;
3989
- }
3990
- if (!isDirtyRef.current) {
3991
- return;
3992
- }
3993
- if (isSavingRef.current) {
4028
+ react.useEffect(() => {
4029
+ changeSourcesRef.current = getChangeSources;
4030
+ }, [getChangeSources]);
4031
+ const doAutosave = react.useCallback(async (options) => {
4032
+ const path = filePathRef.current;
4033
+ if (!path) {
4034
+ return;
4035
+ }
4036
+ const sources = changeSourcesRef.current?.() ?? [];
4037
+ if (!chunkWVDM36ZM_js.shouldWriteAutosaveSnapshot({
4038
+ filePath: path,
4039
+ isDirty: isDirtyRef.current,
4040
+ saving: isSavingRef.current,
4041
+ sources: options?.polled === true ? sources : [],
4042
+ lastSnapshot: lastSnapshotRef.current
4043
+ })) {
3994
4044
  return;
3995
4045
  }
3996
4046
  isSavingRef.current = true;
@@ -4002,7 +4052,8 @@ function useAutosave(input) {
4002
4052
  isSavingRef.current = false;
4003
4053
  return;
4004
4054
  }
4005
- await chunkY2KIB3QH_js.saveAutosaveSnapshot(filePathRef.current, data);
4055
+ await chunkWVDM36ZM_js.saveAutosaveSnapshot(path, data);
4056
+ lastSnapshotRef.current = chunkWVDM36ZM_js.autosaveSnapshotMark(path, sources);
4006
4057
  setAutosaveStatus({ state: "saved", timestamp: Date.now() });
4007
4058
  } catch (err) {
4008
4059
  setAutosaveStatus({
@@ -4028,13 +4079,13 @@ function useAutosave(input) {
4028
4079
  setAutosaveStatus((prev) => prev.state === "disabled" ? { state: "idle" } : prev);
4029
4080
  const ms = computeAutosaveIntervalMs(intervalSeconds);
4030
4081
  const id = setInterval(() => {
4031
- void doAutosave();
4082
+ void doAutosave({ polled: true });
4032
4083
  }, ms);
4033
4084
  return () => clearInterval(id);
4034
4085
  }, [enabled, filePath, intervalSeconds, doAutosave]);
4035
4086
  return {
4036
4087
  autosaveStatus,
4037
- triggerAutosave: doAutosave
4088
+ triggerAutosave: () => doAutosave()
4038
4089
  };
4039
4090
  }
4040
4091
  function useElementOperations(input) {
@@ -4045,6 +4096,7 @@ function useElementOperations(input) {
4045
4096
  selectedElementId,
4046
4097
  editTemplateMode,
4047
4098
  templateElements,
4099
+ masterView,
4048
4100
  history,
4049
4101
  setSlides,
4050
4102
  setTemplateElementsBySlideId,
@@ -4065,9 +4117,34 @@ function useElementOperations(input) {
4065
4117
  setInlineEditingElementId(null);
4066
4118
  setContextMenuState(null);
4067
4119
  }, [applySelection, setInlineEditingElementId, setContextMenuState]);
4120
+ const applyMasterViewWrite = react.useCallback(
4121
+ (write) => {
4122
+ if (!write || !masterView) {
4123
+ return false;
4124
+ }
4125
+ if (write.slideMasters) {
4126
+ masterView.setSlideMasters(write.slideMasters);
4127
+ }
4128
+ if (write.notesMaster) {
4129
+ masterView.setNotesMaster(write.notesMaster);
4130
+ }
4131
+ if (write.handoutMaster) {
4132
+ masterView.setHandoutMaster(write.handoutMaster);
4133
+ }
4134
+ history.markDirty();
4135
+ return true;
4136
+ },
4137
+ [history, masterView]
4138
+ );
4068
4139
  const updateElementById = react.useCallback(
4069
4140
  (elementId, updates) => {
4070
- if (chunkY2KIB3QH_js.isTemplateElementId(elementId)) {
4141
+ if (masterView?.target) {
4142
+ applyMasterViewWrite(
4143
+ chunkWVDM36ZM_js.updateMasterViewElement(masterView, masterView.target, elementId, updates)
4144
+ );
4145
+ return;
4146
+ }
4147
+ if (chunkWVDM36ZM_js.isTemplateElementId(elementId)) {
4071
4148
  const slideId = activeSlide?.id;
4072
4149
  if (slideId) {
4073
4150
  setTemplateElementsBySlideId((prev) => ({
@@ -4094,7 +4171,15 @@ function useElementOperations(input) {
4094
4171
  }
4095
4172
  history.markDirty();
4096
4173
  },
4097
- [activeSlide?.id, activeSlideIndex, history, setSlides, setTemplateElementsBySlideId]
4174
+ [
4175
+ activeSlide?.id,
4176
+ activeSlideIndex,
4177
+ applyMasterViewWrite,
4178
+ history,
4179
+ masterView,
4180
+ setSlides,
4181
+ setTemplateElementsBySlideId
4182
+ ]
4098
4183
  );
4099
4184
  const updateSelectedElement = react.useCallback(
4100
4185
  (updates) => {
@@ -4107,7 +4192,7 @@ function useElementOperations(input) {
4107
4192
  );
4108
4193
  const updateSelectedShapeStyle = react.useCallback(
4109
4194
  (updates) => {
4110
- if (!selectedElement || !chunkY2KIB3QH_js.hasShapeProperties(selectedElement)) {
4195
+ if (!selectedElement || !chunkWVDM36ZM_js.hasShapeProperties(selectedElement)) {
4111
4196
  return;
4112
4197
  }
4113
4198
  updateSelectedElement({
@@ -4118,17 +4203,17 @@ function useElementOperations(input) {
4118
4203
  );
4119
4204
  const updateSelectedTextStyle = react.useCallback(
4120
4205
  (updates) => {
4121
- if (!selectedElement || !chunkY2KIB3QH_js.hasTextProperties(selectedElement)) {
4206
+ if (!selectedElement || !chunkWVDM36ZM_js.hasTextProperties(selectedElement)) {
4122
4207
  return;
4123
4208
  }
4124
- const inlineSel = chunkY2KIB3QH_js.getInlineEditorSelection(selectedElement.textSegments);
4209
+ const inlineSel = chunkWVDM36ZM_js.getInlineEditorSelection(selectedElement.textSegments);
4125
4210
  if (inlineSel && selectedElement.textSegments) {
4126
- const { newSegments: newSegments2, newSelection } = chunkY2KIB3QH_js.applyStyleToSelectedSegments(
4211
+ const { newSegments: newSegments2, newSelection } = chunkWVDM36ZM_js.applyStyleToSelectedSegments(
4127
4212
  selectedElement.textSegments,
4128
4213
  inlineSel,
4129
4214
  updates
4130
4215
  );
4131
- chunkY2KIB3QH_js.setPendingSelectionRestore(newSelection);
4216
+ chunkWVDM36ZM_js.setPendingSelectionRestore(newSelection);
4132
4217
  updateSelectedElement({
4133
4218
  textSegments: newSegments2
4134
4219
  });
@@ -4148,12 +4233,12 @@ function useElementOperations(input) {
4148
4233
  );
4149
4234
  const updateSelectedTextCase = react.useCallback(
4150
4235
  (mode) => {
4151
- if (!selectedElement || !chunkY2KIB3QH_js.hasTextProperties(selectedElement)) {
4236
+ if (!selectedElement || !chunkWVDM36ZM_js.hasTextProperties(selectedElement)) {
4152
4237
  return;
4153
4238
  }
4154
- const inlineSel = chunkY2KIB3QH_js.getInlineEditorSelection(selectedElement.textSegments);
4239
+ const inlineSel = chunkWVDM36ZM_js.getInlineEditorSelection(selectedElement.textSegments);
4155
4240
  if (inlineSel && selectedElement.textSegments) {
4156
- const newSegments = chunkY2KIB3QH_js.applyCaseTransformToSegments(
4241
+ const newSegments = chunkWVDM36ZM_js.applyCaseTransformToSegments(
4157
4242
  selectedElement.textSegments,
4158
4243
  inlineSel,
4159
4244
  mode
@@ -4163,14 +4248,14 @@ function useElementOperations(input) {
4163
4248
  }
4164
4249
  const updates = {};
4165
4250
  if (selectedElement.textSegments && selectedElement.textSegments.length > 0) {
4166
- updates.textSegments = chunkY2KIB3QH_js.applyCaseTransformToSegments(
4251
+ updates.textSegments = chunkWVDM36ZM_js.applyCaseTransformToSegments(
4167
4252
  selectedElement.textSegments,
4168
4253
  null,
4169
4254
  mode
4170
4255
  );
4171
4256
  }
4172
4257
  if (typeof selectedElement.text === "string") {
4173
- updates.text = chunkY2KIB3QH_js.transformTextCase(selectedElement.text, mode);
4258
+ updates.text = chunkWVDM36ZM_js.transformTextCase(selectedElement.text, mode);
4174
4259
  }
4175
4260
  updateSelectedElement(updates);
4176
4261
  },
@@ -4182,9 +4267,20 @@ function useElementOperations(input) {
4182
4267
  },
4183
4268
  [setSlides]
4184
4269
  );
4185
- const activeElements = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
4270
+ const masterViewTarget = masterView?.target ?? null;
4271
+ const activeElements = masterViewTarget ? chunkWVDM36ZM_js.masterViewElements(masterView, masterViewTarget) : editTemplateMode ? templateElements : activeSlide?.elements ?? [];
4186
4272
  const updateActiveElements = react.useCallback(
4187
4273
  (updater) => {
4274
+ if (masterView?.target) {
4275
+ applyMasterViewWrite(
4276
+ chunkWVDM36ZM_js.replaceMasterViewElements(
4277
+ masterView,
4278
+ masterView.target,
4279
+ updater(chunkWVDM36ZM_js.masterViewElements(masterView, masterView.target))
4280
+ )
4281
+ );
4282
+ return;
4283
+ }
4188
4284
  if (editTemplateMode) {
4189
4285
  const slideId = activeSlide?.id;
4190
4286
  if (!slideId) {
@@ -4202,7 +4298,15 @@ function useElementOperations(input) {
4202
4298
  );
4203
4299
  }
4204
4300
  },
4205
- [editTemplateMode, activeSlide?.id, activeSlideIndex, setSlides, setTemplateElementsBySlideId]
4301
+ [
4302
+ applyMasterViewWrite,
4303
+ editTemplateMode,
4304
+ masterView,
4305
+ activeSlide?.id,
4306
+ activeSlideIndex,
4307
+ setSlides,
4308
+ setTemplateElementsBySlideId
4309
+ ]
4206
4310
  );
4207
4311
  const serializeSlides = react.useCallback(async () => {
4208
4312
  return null;
@@ -4225,7 +4329,7 @@ function useSectionOperations(input) {
4225
4329
  const { sections, setSections, slides, setSlides, markDirty } = input;
4226
4330
  const addSection2 = react.useCallback(
4227
4331
  (name, afterSlideIndex) => {
4228
- const result = chunkY2KIB3QH_js.addSection(sections, slides, name, afterSlideIndex);
4332
+ const result = chunkWVDM36ZM_js.addSection(sections, slides, name, afterSlideIndex);
4229
4333
  setSlides(result.slides);
4230
4334
  setSections(result.sections);
4231
4335
  markDirty();
@@ -4234,7 +4338,7 @@ function useSectionOperations(input) {
4234
4338
  );
4235
4339
  const renameSection2 = react.useCallback(
4236
4340
  (sectionId, newName) => {
4237
- const result = chunkY2KIB3QH_js.renameSection(sections, slides, sectionId, newName);
4341
+ const result = chunkWVDM36ZM_js.renameSection(sections, slides, sectionId, newName);
4238
4342
  setSections(result.sections);
4239
4343
  setSlides(result.slides);
4240
4344
  markDirty();
@@ -4243,7 +4347,7 @@ function useSectionOperations(input) {
4243
4347
  );
4244
4348
  const deleteSection2 = react.useCallback(
4245
4349
  (sectionId) => {
4246
- const result = chunkY2KIB3QH_js.deleteSection(sections, slides, sectionId);
4350
+ const result = chunkWVDM36ZM_js.deleteSection(sections, slides, sectionId);
4247
4351
  setSections(result.sections);
4248
4352
  setSlides(result.slides);
4249
4353
  markDirty();
@@ -4252,57 +4356,62 @@ function useSectionOperations(input) {
4252
4356
  );
4253
4357
  const moveSectionUp2 = react.useCallback(
4254
4358
  (sectionId) => {
4255
- setSections(chunkY2KIB3QH_js.moveSectionUp(sections, sectionId));
4359
+ setSections(chunkWVDM36ZM_js.moveSectionUp(sections, sectionId));
4256
4360
  markDirty();
4257
4361
  },
4258
4362
  [sections, setSections, markDirty]
4259
4363
  );
4260
4364
  const moveSectionDown2 = react.useCallback(
4261
4365
  (sectionId) => {
4262
- setSections(chunkY2KIB3QH_js.moveSectionDown(sections, sectionId));
4366
+ setSections(chunkWVDM36ZM_js.moveSectionDown(sections, sectionId));
4263
4367
  markDirty();
4264
4368
  },
4265
4369
  [sections, setSections, markDirty]
4266
4370
  );
4267
4371
  const moveSlidesToSection2 = react.useCallback(
4268
4372
  (slideIndexes, targetSectionId) => {
4269
- const result = chunkY2KIB3QH_js.moveSlidesToSection(sections, slides, slideIndexes, targetSectionId);
4373
+ const result = chunkWVDM36ZM_js.moveSlidesToSection(sections, slides, slideIndexes, targetSectionId);
4270
4374
  setSlides(result.slides);
4271
4375
  setSections(result.sections);
4272
4376
  markDirty();
4273
4377
  },
4274
4378
  [sections, slides, setSlides, setSections, markDirty]
4275
4379
  );
4380
+ const toggleSectionCollapse = react.useCallback(
4381
+ (sectionId) => {
4382
+ setSections(
4383
+ (prev) => prev.map((sec) => sec.id === sectionId ? { ...sec, collapsed: !sec.collapsed } : sec)
4384
+ );
4385
+ markDirty();
4386
+ },
4387
+ [setSections, markDirty]
4388
+ );
4276
4389
  return {
4277
4390
  addSection: addSection2,
4278
4391
  renameSection: renameSection2,
4279
4392
  deleteSection: deleteSection2,
4280
4393
  moveSectionUp: moveSectionUp2,
4281
4394
  moveSectionDown: moveSectionDown2,
4282
- moveSlidesToSection: moveSlidesToSection2
4395
+ moveSlidesToSection: moveSlidesToSection2,
4396
+ toggleSectionCollapse
4283
4397
  };
4284
4398
  }
4285
4399
 
4286
4400
  // src/viewer/hooks/pointer-move-handlers.ts
4287
4401
  function computeResizeGeometry(handle, startX, startY, startWidth, startHeight, dx, dy, snapToGrid, gridSpacingPx) {
4288
- const resized = chunkY2KIB3QH_js.applyResize(
4402
+ const resized = chunkWVDM36ZM_js.applyResize(
4289
4403
  { x: startX, y: startY, width: startWidth, height: startHeight },
4290
4404
  handle,
4291
4405
  dx,
4292
4406
  dy,
4293
4407
  1,
4294
- { minSize: chunkWK22Z7PK_js.MIN_ELEMENT_SIZE }
4408
+ { minSize: chunk4LWGAVAP_js.MIN_ELEMENT_SIZE }
4295
4409
  );
4296
4410
  const box = { x: resized.x, y: resized.y, width: resized.width, height: resized.height };
4297
4411
  if (!snapToGrid) {
4298
4412
  return box;
4299
4413
  }
4300
- return chunkY2KIB3QH_js.snapBoxToGrid(box, handle, gridSpacingPx, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE);
4301
- }
4302
- function computeAdjustmentValue(startAdjustment, dx, startWidth) {
4303
- const range = startWidth || 200;
4304
- const delta = dx / range;
4305
- return Math.max(0, Math.min(1, startAdjustment + delta));
4414
+ return chunkWVDM36ZM_js.snapBoxToGrid(box, handle, gridSpacingPx, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE);
4306
4415
  }
4307
4416
  function resolveLiveTarget(input) {
4308
4417
  const { livePatcher, editTemplateMode, activeSlide } = input;
@@ -4415,7 +4524,7 @@ function processDragMove(e, drag, editorScale, snapToGrid, snapToShape, gridSpac
4415
4524
  width: el.width,
4416
4525
  height: el.height
4417
4526
  }));
4418
- const snapResult = chunkY2KIB3QH_js.computeSnapToShape(
4527
+ const snapResult = chunkWVDM36ZM_js.computeSnapToShape(
4419
4528
  targetX,
4420
4529
  targetY,
4421
4530
  primaryEl.width,
@@ -4454,7 +4563,7 @@ function processDragMove(e, drag, editorScale, snapToGrid, snapToShape, gridSpac
4454
4563
  if (live) {
4455
4564
  for (const id of Object.keys(drag.startPositionsById)) {
4456
4565
  const start = drag.startPositionsById[id];
4457
- chunkY2KIB3QH_js.publishLiveGeometry(live.patcher, live.slideId, id, {
4566
+ chunkWVDM36ZM_js.publishLiveGeometry(live.patcher, live.slideId, id, {
4458
4567
  x: start.x + appliedDx,
4459
4568
  y: start.y + appliedDy
4460
4569
  });
@@ -4488,27 +4597,28 @@ function processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, live)
4488
4597
  if (rs.domEl) {
4489
4598
  rs.domEl.style.left = `${geo.x}px`;
4490
4599
  rs.domEl.style.top = `${geo.y}px`;
4491
- rs.domEl.style.width = `${Math.max(geo.width, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE)}px`;
4492
- rs.domEl.style.height = `${Math.max(geo.height, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE)}px`;
4600
+ rs.domEl.style.width = `${Math.max(geo.width, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE)}px`;
4601
+ rs.domEl.style.height = `${Math.max(geo.height, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE)}px`;
4493
4602
  }
4494
4603
  if (live) {
4495
- chunkY2KIB3QH_js.publishLiveGeometry(live.patcher, live.slideId, rs.elementId, {
4604
+ chunkWVDM36ZM_js.publishLiveGeometry(live.patcher, live.slideId, rs.elementId, {
4496
4605
  x: geo.x,
4497
4606
  y: geo.y,
4498
- width: Math.max(geo.width, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE),
4499
- height: Math.max(geo.height, chunkWK22Z7PK_js.MIN_ELEMENT_SIZE)
4607
+ width: Math.max(geo.width, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE),
4608
+ height: Math.max(geo.height, chunk4LWGAVAP_js.MIN_ELEMENT_SIZE)
4500
4609
  });
4501
4610
  }
4502
4611
  }
4503
4612
  function processAdjustmentMove(e, adj, editorScale, updateElementById) {
4504
4613
  const dx = (e.clientX - adj.startClientX) / editorScale;
4505
- const newValue = computeAdjustmentValue(adj.startAdjustment, dx, adj.startWidth);
4506
- if (!adj.moved && Math.abs(dx) > 2) {
4614
+ const dy = (e.clientY - adj.startClientY) / editorScale;
4615
+ const adjustments = chunkWVDM36ZM_js.getDraggedShapeAdjustments(adj, dx, dy);
4616
+ if (!adj.moved && Math.hypot(dx, dy) > 2) {
4507
4617
  adj.moved = true;
4508
4618
  }
4509
4619
  if (adj.moved) {
4510
4620
  updateElementById(adj.elementId, {
4511
- shapeAdjustments: { [adj.key]: newValue }
4621
+ shapeAdjustments: adjustments
4512
4622
  });
4513
4623
  }
4514
4624
  }
@@ -4577,13 +4687,13 @@ function processPointerUp(input) {
4577
4687
  if (i !== activeSlideIndex) {
4578
4688
  return s;
4579
4689
  }
4580
- const rerouted = chunkY2KIB3QH_js.rerouteConnectorsForMovedElements(s.elements, movedIds);
4690
+ const rerouted = chunkWVDM36ZM_js.rerouteConnectorsForMovedElements(s.elements, movedIds);
4581
4691
  if (rerouted.length === 0) {
4582
4692
  return s;
4583
4693
  }
4584
4694
  return {
4585
4695
  ...s,
4586
- elements: chunkY2KIB3QH_js.applyReroutedConnectors(s.elements, rerouted)
4696
+ elements: chunkWVDM36ZM_js.applyReroutedConnectors(s.elements, rerouted)
4587
4697
  };
4588
4698
  })
4589
4699
  );
@@ -4608,9 +4718,9 @@ function processPointerUp(input) {
4608
4718
  }
4609
4719
  function commitMarquee(marquee, editTemplateMode, templateElements, activeSlide, applySelection, clearSelection) {
4610
4720
  const sourceElements = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
4611
- const hitIds = chunkY2KIB3QH_js.computeMarqueeHitIds(marquee, sourceElements);
4721
+ const hitIds = chunkWVDM36ZM_js.computeMarqueeHitIds(marquee, sourceElements);
4612
4722
  if (marquee.additive) {
4613
- const merged = chunkY2KIB3QH_js.mergeAdditiveSelection(marquee.baseSelectionIds, hitIds);
4723
+ const merged = chunkWVDM36ZM_js.mergeAdditiveSelection(marquee.baseSelectionIds, hitIds);
4614
4724
  if (merged.length > 0) {
4615
4725
  applySelection(merged[0], merged);
4616
4726
  } else {
@@ -4633,8 +4743,8 @@ function commitDrag(drag, editTemplateMode, activeSlide, activeSlideIndex, setTe
4633
4743
  }
4634
4744
  return { ...el, x: start.x + dx, y: start.y + dy };
4635
4745
  });
4636
- const rerouted = chunkY2KIB3QH_js.rerouteConnectorsForMovedElements(movedElements, movedIds);
4637
- return chunkY2KIB3QH_js.applyReroutedConnectors(movedElements, rerouted);
4746
+ const rerouted = chunkWVDM36ZM_js.rerouteConnectorsForMovedElements(movedElements, movedIds);
4747
+ return chunkWVDM36ZM_js.applyReroutedConnectors(movedElements, rerouted);
4638
4748
  };
4639
4749
  if (editTemplateMode) {
4640
4750
  const slideId = activeSlide?.id;
@@ -4791,9 +4901,9 @@ function useCanvasInteractions(input) {
4791
4901
  return;
4792
4902
  }
4793
4903
  const el = elementLookup.get(editId);
4794
- if (el && chunkY2KIB3QH_js.hasTextProperties(el)) {
4904
+ if (el && chunkWVDM36ZM_js.hasTextProperties(el)) {
4795
4905
  const committedText = transformCommittedText ? transformCommittedText(inlineEditingText) : inlineEditingText;
4796
- const newSegments = chunkY2KIB3QH_js.remapTextToSegments(committedText, el.textSegments, el.textStyle);
4906
+ const newSegments = chunkWVDM36ZM_js.remapTextToSegments(committedText, el.textSegments, el.textStyle);
4797
4907
  ops.updateElementById(editId, {
4798
4908
  text: committedText,
4799
4909
  textSegments: newSegments
@@ -4804,7 +4914,7 @@ function useCanvasInteractions(input) {
4804
4914
  setInlineEditingText("");
4805
4915
  };
4806
4916
  const openEquationEditorForElement = (el) => {
4807
- if (!chunkY2KIB3QH_js.hasTextProperties(el)) {
4917
+ if (!chunkWVDM36ZM_js.hasTextProperties(el)) {
4808
4918
  return false;
4809
4919
  }
4810
4920
  const eqSeg = el.textSegments?.find((seg) => seg.equationXml);
@@ -4834,7 +4944,7 @@ function useCanvasInteractions(input) {
4834
4944
  justInteractedRef.current = false;
4835
4945
  } else {
4836
4946
  const el = elementLookup.get(elementId);
4837
- if (el && chunkY2KIB3QH_js.hasTextProperties(el) && !el.locks?.noTextEdit) {
4947
+ if (el && chunkWVDM36ZM_js.hasTextProperties(el) && chunkWVDM36ZM_js.canInteractWithElement(el, "textEdit")) {
4838
4948
  if (!openEquationEditorForElement(el)) {
4839
4949
  setInlineEditingElementId(elementId);
4840
4950
  setInlineEditingText(el.text ?? "");
@@ -4853,7 +4963,7 @@ function useCanvasInteractions(input) {
4853
4963
  if (openEquationEditorForElement(el)) {
4854
4964
  return;
4855
4965
  }
4856
- if (chunkY2KIB3QH_js.hasTextProperties(el)) {
4966
+ if (chunkWVDM36ZM_js.hasTextProperties(el) && chunkWVDM36ZM_js.canInteractWithElement(el, "textEdit")) {
4857
4967
  setInlineEditingElementId(elementId);
4858
4968
  setInlineEditingText(el.text ?? "");
4859
4969
  }
@@ -4876,9 +4986,13 @@ function useCanvasInteractions(input) {
4876
4986
  justSelectedRef.current = false;
4877
4987
  }
4878
4988
  const ids = !wasSelected ? [elementId] : effectiveSelectedIds.length ? effectiveSelectedIds : [elementId];
4989
+ const movableIds = chunkWVDM36ZM_js.filterInteractableIds(ids, (id) => elementLookup.get(id), "move");
4990
+ if (movableIds.length === 0) {
4991
+ return;
4992
+ }
4879
4993
  const startPositions = {};
4880
4994
  const domEls = /* @__PURE__ */ new Map();
4881
- for (const id of ids) {
4995
+ for (const id of movableIds) {
4882
4996
  const el = elementLookup.get(id);
4883
4997
  if (el) {
4884
4998
  startPositions[id] = { x: el.x, y: el.y };
@@ -4942,7 +5056,7 @@ function useCanvasInteractions(input) {
4942
5056
  const handleResizePointerDown = (elementId, e, handle) => {
4943
5057
  e.stopPropagation();
4944
5058
  const el = elementLookup.get(elementId);
4945
- if (!el) {
5059
+ if (!el || !chunkWVDM36ZM_js.canInteractWithElement(el, "resize")) {
4946
5060
  return;
4947
5061
  }
4948
5062
  resizeStateRef.current = {
@@ -4964,7 +5078,7 @@ function useCanvasInteractions(input) {
4964
5078
  };
4965
5079
  const handleRotate = (elementId, rotationDeg) => {
4966
5080
  const el = elementLookup.get(elementId);
4967
- if (!el || el.locks?.noRotation) {
5081
+ if (!el || !chunkWVDM36ZM_js.canInteractWithElement(el, "rotate")) {
4968
5082
  return;
4969
5083
  }
4970
5084
  ops.updateElementById(elementId, { rotation: rotationDeg });
@@ -4981,30 +5095,18 @@ function useCanvasInteractions(input) {
4981
5095
  const handleFormatText = (updates) => {
4982
5096
  ops.updateSelectedTextStyle(updates);
4983
5097
  };
4984
- const handleAdjustmentPointerDown = (elementId, e) => {
5098
+ const handleAdjustmentPointerDown = (elementId, e, descriptor) => {
4985
5099
  e.stopPropagation();
4986
5100
  const el = elementLookup.get(elementId);
4987
- if (!el || !("shapeType" in el) || !("shapeAdjustments" in el)) {
5101
+ if (!el || !chunkWVDM36ZM_js.canInteractWithElement(el, "adjustHandle")) {
4988
5102
  return;
4989
5103
  }
4990
- const adjEntries = Object.entries(
4991
- el.shapeAdjustments ?? {}
5104
+ shapeAdjustmentDragStateRef.current = chunkWVDM36ZM_js.beginShapeAdjustment(
5105
+ el,
5106
+ descriptor,
5107
+ e.clientX,
5108
+ e.clientY
4992
5109
  );
4993
- if (!adjEntries.length) {
4994
- return;
4995
- }
4996
- const [key, value] = adjEntries[0];
4997
- shapeAdjustmentDragStateRef.current = {
4998
- elementId,
4999
- key,
5000
- shapeType: el.shapeType ?? "rect",
5001
- startClientX: e.clientX,
5002
- startClientY: e.clientY,
5003
- startAdjustment: value,
5004
- startWidth: el.width,
5005
- startHeight: el.height,
5006
- moved: false
5007
- };
5008
5110
  };
5009
5111
  return {
5010
5112
  handleElementClick,
@@ -5046,7 +5148,7 @@ function createFileHandlers(deps) {
5046
5148
  h = Math.round(h * scale);
5047
5149
  }
5048
5150
  addElement({
5049
- id: chunkY2KIB3QH_js.generateElementId(),
5151
+ id: chunkWVDM36ZM_js.generateElementId(),
5050
5152
  type: "image",
5051
5153
  x: Math.round((canvasSize.width - w) / 2),
5052
5154
  y: Math.round((canvasSize.height - h) / 2),
@@ -5057,7 +5159,7 @@ function createFileHandlers(deps) {
5057
5159
  };
5058
5160
  img.onerror = () => {
5059
5161
  addElement({
5060
- id: chunkY2KIB3QH_js.generateElementId(),
5162
+ id: chunkWVDM36ZM_js.generateElementId(),
5061
5163
  type: "image",
5062
5164
  x: 100,
5063
5165
  y: 100,
@@ -5083,7 +5185,7 @@ function createFileHandlers(deps) {
5083
5185
  const elFilePath = file.path;
5084
5186
  const insertMediaElement = (mediaSourceUrl, width, height) => {
5085
5187
  addElement({
5086
- id: chunkY2KIB3QH_js.generateElementId(),
5188
+ id: chunkWVDM36ZM_js.generateElementId(),
5087
5189
  type: "media",
5088
5190
  mediaType,
5089
5191
  mediaMimeType: file.type || void 0,
@@ -5258,13 +5360,13 @@ function createStructuredElementHandlers(deps) {
5258
5360
  return;
5259
5361
  }
5260
5362
  addElement({
5261
- id: chunkY2KIB3QH_js.generateElementId(),
5363
+ id: chunkWVDM36ZM_js.generateElementId(),
5262
5364
  type: "smartArt",
5263
5365
  x: 100,
5264
5366
  y: 120,
5265
5367
  width: 600,
5266
5368
  height: 340,
5267
- smartArtData: chunkY2KIB3QH_js.buildSmartArtPresetData(
5369
+ smartArtData: chunkWVDM36ZM_js.buildSmartArtPresetData(
5268
5370
  layout,
5269
5371
  defaultItems,
5270
5372
  (i) => `node-${Date.now()}-${i}-${Math.random().toString(36).slice(2, 8)}`
@@ -5276,7 +5378,7 @@ function createStructuredElementHandlers(deps) {
5276
5378
  return;
5277
5379
  }
5278
5380
  addElement({
5279
- id: chunkY2KIB3QH_js.generateElementId(),
5381
+ id: chunkWVDM36ZM_js.generateElementId(),
5280
5382
  type: "shape",
5281
5383
  x: 120,
5282
5384
  y: 200,
@@ -5335,7 +5437,7 @@ function createStructuredElementHandlers(deps) {
5335
5437
  const displayText = value || fieldTexts[fieldType] || fieldType;
5336
5438
  const fieldGuid = `{${crypto.randomUUID().toUpperCase()}}`;
5337
5439
  addElement({
5338
- id: chunkY2KIB3QH_js.generateElementId(),
5440
+ id: chunkWVDM36ZM_js.generateElementId(),
5339
5441
  type: "shape",
5340
5442
  x: 120,
5341
5443
  y: 200,
@@ -5357,11 +5459,11 @@ function createStructuredElementHandlers(deps) {
5357
5459
  if (!activeSlide) {
5358
5460
  return;
5359
5461
  }
5360
- const preset = chunkY2KIB3QH_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
5462
+ const preset = chunkWVDM36ZM_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
5361
5463
  if (!preset) {
5362
5464
  return;
5363
5465
  }
5364
- const defaultPptxAction = chunkY2KIB3QH_js.elementActionToPptxAction({
5466
+ const defaultPptxAction = chunkWVDM36ZM_js.elementActionToPptxAction({
5365
5467
  trigger: "click",
5366
5468
  type: preset.defaultAction
5367
5469
  });
@@ -5370,7 +5472,7 @@ function createStructuredElementHandlers(deps) {
5370
5472
  defaultPptxAction.highlightClick = true;
5371
5473
  }
5372
5474
  addElement({
5373
- id: chunkY2KIB3QH_js.generateElementId(),
5475
+ id: chunkWVDM36ZM_js.generateElementId(),
5374
5476
  type: "shape",
5375
5477
  x: 150,
5376
5478
  y: 150,
@@ -5437,14 +5539,14 @@ function useInsertElements(input) {
5437
5539
  return;
5438
5540
  }
5439
5541
  addElement({
5440
- id: chunkY2KIB3QH_js.generateElementId(),
5542
+ id: chunkWVDM36ZM_js.generateElementId(),
5441
5543
  type: "text",
5442
5544
  x: 100,
5443
5545
  y: 100,
5444
5546
  width: 300,
5445
5547
  height: 60,
5446
5548
  text: "",
5447
- textStyle: { fontSize: chunkWK22Z7PK_js.DEFAULT_TEXT_FONT_SIZE }
5549
+ textStyle: { fontSize: chunk4LWGAVAP_js.DEFAULT_TEXT_FONT_SIZE }
5448
5550
  });
5449
5551
  };
5450
5552
  const handleAddShape = () => {
@@ -5452,7 +5554,7 @@ function useInsertElements(input) {
5452
5554
  return;
5453
5555
  }
5454
5556
  addElement({
5455
- id: chunkY2KIB3QH_js.generateElementId(),
5557
+ id: chunkWVDM36ZM_js.generateElementId(),
5456
5558
  type: "shape",
5457
5559
  x: 150,
5458
5560
  y: 150,
@@ -5471,15 +5573,15 @@ function useInsertElements(input) {
5471
5573
  return;
5472
5574
  }
5473
5575
  addElement({
5474
- ...chunkY2KIB3QH_js.newTableElement(chunkWK22Z7PK_js.DEFAULT_TABLE_ROWS, chunkWK22Z7PK_js.DEFAULT_TABLE_COLUMNS, 100, 200),
5475
- id: chunkY2KIB3QH_js.generateElementId()
5576
+ ...chunkWVDM36ZM_js.newTableElement(chunk4LWGAVAP_js.DEFAULT_TABLE_ROWS, chunk4LWGAVAP_js.DEFAULT_TABLE_COLUMNS, 100, 200),
5577
+ id: chunkWVDM36ZM_js.generateElementId()
5476
5578
  });
5477
5579
  };
5478
5580
  const handleAddChart = (chartKind) => {
5479
5581
  if (!activeSlide) {
5480
5582
  return;
5481
5583
  }
5482
- addElement(chunkY2KIB3QH_js.createDefaultChartElement(chartKind));
5584
+ addElement(chunkWVDM36ZM_js.createDefaultChartElement(chartKind));
5483
5585
  };
5484
5586
  const structured = createStructuredElementHandlers({
5485
5587
  activeSlide,
@@ -5549,7 +5651,7 @@ function useClipboardHandlers(input) {
5549
5651
  if (!selectedElement) {
5550
5652
  return;
5551
5653
  }
5552
- setClipboardPayload(chunkY2KIB3QH_js.buildElementClipboardPayload(selectedElement, editTemplateMode));
5654
+ setClipboardPayload(chunkWVDM36ZM_js.buildElementClipboardPayload(selectedElement, editTemplateMode));
5553
5655
  };
5554
5656
  const handleDelete = () => {
5555
5657
  const idsToDelete = effectiveSelectedIds;
@@ -5566,7 +5668,7 @@ function useClipboardHandlers(input) {
5566
5668
  handleDelete();
5567
5669
  };
5568
5670
  const insertClone = (source) => {
5569
- const clone = chunkY2KIB3QH_js.cloneElementForPaste(source, { intoTemplate: editTemplateMode });
5671
+ const clone = chunkWVDM36ZM_js.cloneElementForPaste(source, { intoTemplate: editTemplateMode });
5570
5672
  ops.updateActiveElements((els) => [...els, clone]);
5571
5673
  ops.applySelection(clone.id);
5572
5674
  history.markDirty();
@@ -5601,7 +5703,7 @@ function resolveShapePath(el) {
5601
5703
  return el.pathData;
5602
5704
  }
5603
5705
  if ("shapeType" in el && typeof el.shapeType === "string") {
5604
- const clipPath = chunkY2KIB3QH_js.getPresetShapeClipPath(el.shapeType);
5706
+ const clipPath = chunkWVDM36ZM_js.getPresetShapeClipPath(el.shapeType);
5605
5707
  if (clipPath) {
5606
5708
  const svgPath = clipPathToSvgPath(clipPath, el.width, el.height);
5607
5709
  if (svgPath) {
@@ -5652,7 +5754,7 @@ function clipPathToSvgPath(clipPath, width, height) {
5652
5754
  return parts.join(" ");
5653
5755
  }
5654
5756
  function transformPathToGlobal(pathData, el) {
5655
- const polys = chunkY2KIB3QH_js.svgPathToPolygons(pathData);
5757
+ const polys = chunkWVDM36ZM_js.svgPathToPolygons(pathData);
5656
5758
  if (polys.length === 0) {
5657
5759
  return pathData;
5658
5760
  }
@@ -5672,10 +5774,10 @@ function transformPathToGlobal(pathData, el) {
5672
5774
  y: pt.y * scaleY + el.y
5673
5775
  }))
5674
5776
  );
5675
- return chunkY2KIB3QH_js.polygonsToSvgPath(transformed);
5777
+ return chunkWVDM36ZM_js.polygonsToSvgPath(transformed);
5676
5778
  }
5677
5779
  function transformPathToLocal(pathData, x, y, _width, _height) {
5678
- const polys = chunkY2KIB3QH_js.svgPathToPolygons(pathData);
5780
+ const polys = chunkWVDM36ZM_js.svgPathToPolygons(pathData);
5679
5781
  if (polys.length === 0) {
5680
5782
  return pathData;
5681
5783
  }
@@ -5685,10 +5787,10 @@ function transformPathToLocal(pathData, x, y, _width, _height) {
5685
5787
  y: pt.y - y
5686
5788
  }))
5687
5789
  );
5688
- return chunkY2KIB3QH_js.polygonsToSvgPath(transformed);
5790
+ return chunkWVDM36ZM_js.polygonsToSvgPath(transformed);
5689
5791
  }
5690
5792
  function pathBounds(pathData) {
5691
- const polys = chunkY2KIB3QH_js.svgPathToPolygons(pathData);
5793
+ const polys = chunkWVDM36ZM_js.svgPathToPolygons(pathData);
5692
5794
  let minX = Infinity;
5693
5795
  let minY = Infinity;
5694
5796
  let maxX = -Infinity;
@@ -5747,7 +5849,7 @@ function useMergeShapesHandler(input) {
5747
5849
  let allFragments = [];
5748
5850
  let remaining = globalPaths[0];
5749
5851
  for (let i = 1; i < globalPaths.length; i++) {
5750
- const frags = chunkY2KIB3QH_js.mergeShapes("fragment", remaining, globalPaths[i]);
5852
+ const frags = chunkWVDM36ZM_js.mergeShapes("fragment", remaining, globalPaths[i]);
5751
5853
  if (Array.isArray(frags)) {
5752
5854
  allFragments = frags;
5753
5855
  }
@@ -5776,7 +5878,7 @@ function useMergeShapesHandler(input) {
5776
5878
  bounds.height
5777
5879
  );
5778
5880
  const newEl = {
5779
- id: chunkY2KIB3QH_js.generateElementId(),
5881
+ id: chunkWVDM36ZM_js.generateElementId(),
5780
5882
  type: "shape",
5781
5883
  x: bounds.x,
5782
5884
  y: bounds.y,
@@ -5814,7 +5916,7 @@ function useMergeShapesHandler(input) {
5814
5916
  } else {
5815
5917
  let resultPath = globalPaths[0];
5816
5918
  for (let i = 1; i < globalPaths.length; i++) {
5817
- const result = chunkY2KIB3QH_js.mergeShapes(operation, resultPath, globalPaths[i]);
5919
+ const result = chunkWVDM36ZM_js.mergeShapes(operation, resultPath, globalPaths[i]);
5818
5920
  if (typeof result === "string") {
5819
5921
  resultPath = result;
5820
5922
  }
@@ -5835,7 +5937,7 @@ function useMergeShapesHandler(input) {
5835
5937
  );
5836
5938
  const primary = targets[0];
5837
5939
  const newEl = {
5838
- id: chunkY2KIB3QH_js.generateElementId(),
5940
+ id: chunkWVDM36ZM_js.generateElementId(),
5839
5941
  type: "shape",
5840
5942
  x: bounds.x,
5841
5943
  y: bounds.y,
@@ -5898,7 +6000,7 @@ function useGroupAlignLayerHandlers(input) {
5898
6000
  if (ids.length < 2 || !activeSlide) {
5899
6001
  return;
5900
6002
  }
5901
- const { elements, groupId } = chunkY2KIB3QH_js.groupElements(ops.activeElements, ids, chunkY2KIB3QH_js.generateElementId());
6003
+ const { elements, groupId } = chunkWVDM36ZM_js.groupElements(ops.activeElements, ids, chunkWVDM36ZM_js.generateElementId());
5902
6004
  if (groupId === null) {
5903
6005
  return;
5904
6006
  }
@@ -5911,17 +6013,21 @@ function useGroupAlignLayerHandlers(input) {
5911
6013
  return;
5912
6014
  }
5913
6015
  const group = selectedElement;
5914
- const intoTemplate = chunkY2KIB3QH_js.isTemplateElementId(group.id);
5915
- const ungrouped = group.children.map((child) => ({
5916
- ...structuredClone(child),
5917
- // Keep child ids in the same store as the group so later edits route
5918
- // correctly: template groups yield template-prefixed child ids.
5919
- id: intoTemplate ? chunkY2KIB3QH_js.makeCloneId(true, child.id || group.id) : child.id || chunkY2KIB3QH_js.generateElementId(),
5920
- x: child.x + group.x,
5921
- y: child.y + group.y
5922
- }));
5923
- ops.updateActiveElements((els) => [...els.filter((el) => el.id !== group.id), ...ungrouped]);
5924
- setSelectedElementIds(ungrouped.map((el) => el.id));
6016
+ const intoTemplate = chunkWVDM36ZM_js.isTemplateElementId(group.id);
6017
+ const childIds = group.children.map(
6018
+ (child) => intoTemplate ? chunkWVDM36ZM_js.makeCloneId(true, child.id || group.id) : child.id || chunkWVDM36ZM_js.generateElementId()
6019
+ );
6020
+ const { elements, childIds: usedIds } = chunkWVDM36ZM_js.ungroupElements(
6021
+ ops.activeElements,
6022
+ group.id,
6023
+ childIds,
6024
+ { intoTemplate }
6025
+ );
6026
+ if (usedIds.length === 0) {
6027
+ return;
6028
+ }
6029
+ ops.updateActiveElements(() => elements);
6030
+ setSelectedElementIds(usedIds);
5925
6031
  history.markDirty();
5926
6032
  };
5927
6033
  const handleFlip = (direction) => {
@@ -5940,7 +6046,7 @@ function useGroupAlignLayerHandlers(input) {
5940
6046
  if (!edge) {
5941
6047
  return;
5942
6048
  }
5943
- const positions = chunkY2KIB3QH_js.alignElements(selectedElements, edge);
6049
+ const positions = chunkWVDM36ZM_js.alignElements(selectedElements, edge);
5944
6050
  for (const [id, pos] of positions) {
5945
6051
  const el = elementLookup.get(id);
5946
6052
  if (!el) {
@@ -5958,7 +6064,7 @@ function useGroupAlignLayerHandlers(input) {
5958
6064
  if (!distAxis) {
5959
6065
  return;
5960
6066
  }
5961
- const positions = chunkY2KIB3QH_js.distributeElements(selectedElements, distAxis);
6067
+ const positions = chunkWVDM36ZM_js.distributeElements(selectedElements, distAxis);
5962
6068
  for (const [id, pos] of positions) {
5963
6069
  const el = elementLookup.get(id);
5964
6070
  if (!el) {
@@ -5975,7 +6081,7 @@ function useGroupAlignLayerHandlers(input) {
5975
6081
  }
5976
6082
  const id = selectedElement.id;
5977
6083
  ops.updateActiveElements(
5978
- (els) => direction === "forward" ? chunkY2KIB3QH_js.bringForward(els, id) : direction === "backward" ? chunkY2KIB3QH_js.sendBackward(els, id) : els
6084
+ (els) => direction === "forward" ? chunkWVDM36ZM_js.bringForward(els, id) : direction === "backward" ? chunkWVDM36ZM_js.sendBackward(els, id) : els
5979
6085
  );
5980
6086
  history.markDirty();
5981
6087
  };
@@ -5985,7 +6091,7 @@ function useGroupAlignLayerHandlers(input) {
5985
6091
  }
5986
6092
  const id = selectedElement.id;
5987
6093
  ops.updateActiveElements(
5988
- (els) => direction === "front" ? chunkY2KIB3QH_js.bringToFront(els, id) : chunkY2KIB3QH_js.sendToBack(els, id)
6094
+ (els) => direction === "front" ? chunkWVDM36ZM_js.bringToFront(els, id) : chunkWVDM36ZM_js.sendToBack(els, id)
5989
6095
  );
5990
6096
  history.markDirty();
5991
6097
  };
@@ -6116,7 +6222,7 @@ function useSlideManagement(input) {
6116
6222
  theme
6117
6223
  } = input;
6118
6224
  const handleAddSlide = () => {
6119
- const newSlide = chunkY2KIB3QH_js.createBlankSlide(slides.length + 1);
6225
+ const newSlide = chunkWVDM36ZM_js.createBlankSlide(slides.length + 1);
6120
6226
  ops.updateSlides((prev) => {
6121
6227
  const next = [...prev];
6122
6228
  next.splice(activeSlideIndex + 1, 0, newSlide);
@@ -6179,7 +6285,7 @@ function useSlideManagement(input) {
6179
6285
  }
6180
6286
  const clone = {
6181
6287
  ...src,
6182
- id: chunkY2KIB3QH_js.makeSlideId(),
6288
+ id: chunkWVDM36ZM_js.makeSlideId(),
6183
6289
  elements: src.elements.map((el) => ({
6184
6290
  ...el,
6185
6291
  id: `${el.id}-dup-${Math.random().toString(36).slice(2, 6)}`
@@ -6211,7 +6317,7 @@ function useSlideManagement(input) {
6211
6317
  const handleInsertSlideFromLayout = (layoutPath, layoutName) => {
6212
6318
  const insertAt = activeSlideIndex + 1;
6213
6319
  const draft = {
6214
- ...chunkY2KIB3QH_js.createBlankSlide(slides.length + 1),
6320
+ ...chunkWVDM36ZM_js.createBlankSlide(slides.length + 1),
6215
6321
  layoutPath,
6216
6322
  ...layoutName ? { layoutName } : {}
6217
6323
  };
@@ -6244,9 +6350,9 @@ function useSlideManagement(input) {
6244
6350
  };
6245
6351
  const handleInsertSlideFromTemplate = (templateId) => {
6246
6352
  const insertAt = activeSlideIndex + 1;
6247
- const draft = chunkY2KIB3QH_js.buildSlideTemplateSlide(templateId, chunkY2KIB3QH_js.makeSlideId(), slides.length + 1, {
6353
+ const draft = chunkWVDM36ZM_js.buildSlideTemplateSlide(templateId, chunkWVDM36ZM_js.makeSlideId(), slides.length + 1, {
6248
6354
  ...canvasSize ? { slideWidth: canvasSize.width, slideHeight: canvasSize.height } : {},
6249
- scheme: chunkY2KIB3QH_js.templateSchemeFromTheme(theme?.colorScheme)
6355
+ scheme: chunkWVDM36ZM_js.templateSchemeFromTheme(theme?.colorScheme)
6250
6356
  });
6251
6357
  ops.updateSlides((prev) => insertSlideFromLayoutUpdater(prev, activeSlideIndex, draft));
6252
6358
  setActiveSlideIndex(insertAt);
@@ -6283,7 +6389,7 @@ function createTableMergeHandlers(input) {
6283
6389
  if (!nextCell || nextCell.hMerge || nextCell.vMerge) {
6284
6390
  return;
6285
6391
  }
6286
- const newTableData = chunkY2KIB3QH_js.mergeCells(
6392
+ const newTableData = chunkWVDM36ZM_js.mergeCells(
6287
6393
  [
6288
6394
  { row: rowIndex, col: columnIndex },
6289
6395
  { row: rowIndex, col: nextColIdx }
@@ -6291,7 +6397,7 @@ function createTableMergeHandlers(input) {
6291
6397
  td
6292
6398
  );
6293
6399
  const updates = { tableData: newTableData };
6294
- const newRawXml = chunkY2KIB3QH_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6400
+ const newRawXml = chunkWVDM36ZM_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6295
6401
  if (newRawXml) {
6296
6402
  updates.rawXml = newRawXml;
6297
6403
  }
@@ -6317,7 +6423,7 @@ function createTableMergeHandlers(input) {
6317
6423
  if (!targetNextCell || targetNextCell.hMerge || targetNextCell.vMerge) {
6318
6424
  return;
6319
6425
  }
6320
- const newTableData = chunkY2KIB3QH_js.mergeCells(
6426
+ const newTableData = chunkWVDM36ZM_js.mergeCells(
6321
6427
  [
6322
6428
  { row: rowIndex, col: columnIndex },
6323
6429
  { row: targetNextRowIdx, col: columnIndex }
@@ -6325,7 +6431,7 @@ function createTableMergeHandlers(input) {
6325
6431
  td
6326
6432
  );
6327
6433
  const updates = { tableData: newTableData };
6328
- const newRawXml = chunkY2KIB3QH_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6434
+ const newRawXml = chunkWVDM36ZM_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6329
6435
  if (newRawXml) {
6330
6436
  updates.rawXml = newRawXml;
6331
6437
  }
@@ -6340,9 +6446,9 @@ function createTableMergeHandlers(input) {
6340
6446
  return;
6341
6447
  }
6342
6448
  const td = selectedElement.tableData;
6343
- const newTableData = chunkY2KIB3QH_js.mergeCells(ts.selectedCells, td);
6449
+ const newTableData = chunkWVDM36ZM_js.mergeCells(ts.selectedCells, td);
6344
6450
  const updates = { tableData: newTableData };
6345
- const newRawXml = chunkY2KIB3QH_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6451
+ const newRawXml = chunkWVDM36ZM_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6346
6452
  if (newRawXml) {
6347
6453
  updates.rawXml = newRawXml;
6348
6454
  }
@@ -6359,9 +6465,9 @@ function createTableMergeHandlers(input) {
6359
6465
  }
6360
6466
  const { rowIndex, columnIndex } = ts;
6361
6467
  const td = selectedElement.tableData;
6362
- const newTableData = chunkY2KIB3QH_js.splitCell(rowIndex, columnIndex, td);
6468
+ const newTableData = chunkWVDM36ZM_js.splitCell(rowIndex, columnIndex, td);
6363
6469
  const updates = { tableData: newTableData };
6364
- const newRawXml = chunkY2KIB3QH_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6470
+ const newRawXml = chunkWVDM36ZM_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6365
6471
  if (newRawXml) {
6366
6472
  updates.rawXml = newRawXml;
6367
6473
  }
@@ -6405,7 +6511,7 @@ function createTableStructHandlers(input) {
6405
6511
  updates.tableData = { ...el.tableData, rows: newRows };
6406
6512
  }
6407
6513
  if (el.rawXml) {
6408
- const newRawXml = chunkY2KIB3QH_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
6514
+ const newRawXml = chunkWVDM36ZM_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
6409
6515
  if (newRawXml) {
6410
6516
  updates.rawXml = newRawXml;
6411
6517
  }
@@ -6429,7 +6535,7 @@ function createTableStructHandlers(input) {
6429
6535
  const { rowIndex, columnIndex: colIndex } = ts;
6430
6536
  const updates = {};
6431
6537
  if (selectedElement.rawXml) {
6432
- const newRawXml = chunkY2KIB3QH_js.updateCellTextStyleInRawXml(
6538
+ const newRawXml = chunkWVDM36ZM_js.updateCellTextStyleInRawXml(
6433
6539
  selectedElement,
6434
6540
  rowIndex,
6435
6541
  colIndex,
@@ -6493,9 +6599,9 @@ function createTableStructHandlers(input) {
6493
6599
  return;
6494
6600
  }
6495
6601
  const rowIdx = ts?.rowIndex ?? 0;
6496
- const newTableData = chunkY2KIB3QH_js.insertTableRow(selectedElement.tableData, rowIdx, position);
6602
+ const newTableData = chunkWVDM36ZM_js.insertTableRow(selectedElement.tableData, rowIdx, position);
6497
6603
  const updates = { tableData: newTableData };
6498
- const newRawXml = chunkY2KIB3QH_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6604
+ const newRawXml = chunkWVDM36ZM_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6499
6605
  if (newRawXml) {
6500
6606
  updates.rawXml = newRawXml;
6501
6607
  }
@@ -6508,12 +6614,12 @@ function createTableStructHandlers(input) {
6508
6614
  }
6509
6615
  const td = selectedElement.tableData;
6510
6616
  const rowIdx = ts?.rowIndex ?? 0;
6511
- const newTableData = chunkY2KIB3QH_js.deleteTableRow(td, rowIdx);
6617
+ const newTableData = chunkWVDM36ZM_js.deleteTableRow(td, rowIdx);
6512
6618
  if (newTableData === td) {
6513
6619
  return;
6514
6620
  }
6515
6621
  const updates = { tableData: newTableData };
6516
- const newRawXml = chunkY2KIB3QH_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6622
+ const newRawXml = chunkWVDM36ZM_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6517
6623
  if (newRawXml) {
6518
6624
  updates.rawXml = newRawXml;
6519
6625
  }
@@ -6525,9 +6631,9 @@ function createTableStructHandlers(input) {
6525
6631
  return;
6526
6632
  }
6527
6633
  const colIdx = ts?.columnIndex ?? 0;
6528
- const newTableData = chunkY2KIB3QH_js.insertTableColumn(selectedElement.tableData, colIdx, position);
6634
+ const newTableData = chunkWVDM36ZM_js.insertTableColumn(selectedElement.tableData, colIdx, position);
6529
6635
  const updates = { tableData: newTableData };
6530
- const newRawXml = chunkY2KIB3QH_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6636
+ const newRawXml = chunkWVDM36ZM_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6531
6637
  if (newRawXml) {
6532
6638
  updates.rawXml = newRawXml;
6533
6639
  }
@@ -6540,12 +6646,12 @@ function createTableStructHandlers(input) {
6540
6646
  }
6541
6647
  const td = selectedElement.tableData;
6542
6648
  const colIdx = ts?.columnIndex ?? 0;
6543
- const newTableData = chunkY2KIB3QH_js.deleteTableColumn(td, colIdx);
6649
+ const newTableData = chunkWVDM36ZM_js.deleteTableColumn(td, colIdx);
6544
6650
  if (newTableData === td) {
6545
6651
  return;
6546
6652
  }
6547
6653
  const updates = { tableData: newTableData };
6548
- const newRawXml = chunkY2KIB3QH_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6654
+ const newRawXml = chunkWVDM36ZM_js.rebuildTableStructureInRawXml(selectedElement, newTableData);
6549
6655
  if (newRawXml) {
6550
6656
  updates.rawXml = newRawXml;
6551
6657
  }
@@ -6581,8 +6687,8 @@ async function renderToCanvas(element, options = {}) {
6581
6687
  return html2canvasPro(element, {
6582
6688
  ...options,
6583
6689
  onclone: async (doc, clonedEl) => {
6584
- await chunkY2KIB3QH_js.normalizeColorsForCapture(doc, clonedEl);
6585
- chunkY2KIB3QH_js.preprocessCssForCapture(clonedEl);
6690
+ await chunkWVDM36ZM_js.normalizeColorsForCapture(doc, clonedEl);
6691
+ chunkWVDM36ZM_js.preprocessCssForCapture(clonedEl);
6586
6692
  if (typeof userOnClone === "function") {
6587
6693
  userOnClone(doc, clonedEl);
6588
6694
  }
@@ -6638,7 +6744,7 @@ async function exportSlideToPngBlob(slideElement, options = {}) {
6638
6744
  }
6639
6745
  async function exportSlideAsPng(slideElement, slideIndex, options = {}) {
6640
6746
  const blob = await exportSlideToPngBlob(slideElement, options);
6641
- chunkY2KIB3QH_js.downloadBlob(blob, `slide-${slideIndex + 1}.png`);
6747
+ chunkWVDM36ZM_js.downloadBlob(blob, `slide-${slideIndex + 1}.png`);
6642
6748
  }
6643
6749
  async function copySlideToClipboard(slideElement, options = {}) {
6644
6750
  const blob = await exportSlideToPngBlob(slideElement, options);
@@ -6660,15 +6766,15 @@ async function exportAllSlidesAsPdf(slideStageRef, totalSlides, setActiveSlide,
6660
6766
  continue;
6661
6767
  }
6662
6768
  const canvas = await renderElementToCanvas(stageEl, scale);
6663
- images.push(chunkY2KIB3QH_js.canvasToJpegData(canvas));
6769
+ images.push(chunkWVDM36ZM_js.canvasToJpegData(canvas));
6664
6770
  }
6665
6771
  onProgress?.(totalSlides, totalSlides);
6666
6772
  setActiveSlide(currentSlideIndex);
6667
6773
  if (images.length === 0) {
6668
- throw new Error(chunkDVZF4ARG_js.translationsEn["pptx.export.errorNoSlidesPdf"]);
6774
+ throw new Error(chunkRTUGI4HQ_js.translationsEn["pptx.export.errorNoSlidesPdf"]);
6669
6775
  }
6670
- const pdfBlobUrl = chunkWK22Z7PK_js.buildPdfFromImageData(images);
6671
- chunkY2KIB3QH_js.downloadDataUrl(pdfBlobUrl, filename);
6776
+ const pdfBlobUrl = chunk4LWGAVAP_js.buildPdfFromImageData(images);
6777
+ chunkWVDM36ZM_js.downloadDataUrl(pdfBlobUrl, filename);
6672
6778
  }
6673
6779
  async function captureAllSlidesAsPngDataUrls(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, options = {}) {
6674
6780
  const { scale = 2, onProgress } = options;
@@ -6714,10 +6820,10 @@ async function exportAllSlidesAsNotesPdf(slideStageRef, totalSlides, setActiveSl
6714
6820
  onProgress?.(totalSlides, totalSlides);
6715
6821
  setActiveSlide(currentSlideIndex);
6716
6822
  if (pages.length === 0) {
6717
- throw new Error(chunkDVZF4ARG_js.translationsEn["pptx.export.errorNoSlidesNotesPdf"]);
6823
+ throw new Error(chunkRTUGI4HQ_js.translationsEn["pptx.export.errorNoSlidesNotesPdf"]);
6718
6824
  }
6719
- const pdfDataUrl = chunkWK22Z7PK_js.buildNotesPdf(pages);
6720
- chunkY2KIB3QH_js.downloadDataUrl(pdfDataUrl, filename);
6825
+ const pdfDataUrl = chunk4LWGAVAP_js.buildNotesPdf(pages);
6826
+ chunkWVDM36ZM_js.downloadDataUrl(pdfDataUrl, filename);
6721
6827
  }
6722
6828
 
6723
6829
  // src/viewer/utils/export-video.ts
@@ -6748,7 +6854,7 @@ async function exportAllSlidesAsVideo(slideStageRef, totalSlides, setActiveSlide
6748
6854
  }
6749
6855
  setActiveSlide(currentSlideIndex);
6750
6856
  if (slideCanvases.length === 0) {
6751
- throw new Error(chunkDVZF4ARG_js.translationsEn["pptx.export.errorNoSlidesVideo"]);
6857
+ throw new Error(chunkRTUGI4HQ_js.translationsEn["pptx.export.errorNoSlidesVideo"]);
6752
6858
  }
6753
6859
  const firstCanvas = slideCanvases[0];
6754
6860
  const recordingCanvas = document.createElement("canvas");
@@ -6756,12 +6862,12 @@ async function exportAllSlidesAsVideo(slideStageRef, totalSlides, setActiveSlide
6756
6862
  recordingCanvas.height = firstCanvas.height;
6757
6863
  const ctx = recordingCanvas.getContext("2d");
6758
6864
  if (!ctx) {
6759
- throw new Error(chunkDVZF4ARG_js.translationsEn["pptx.export.errorNo2dContext"]);
6865
+ throw new Error(chunkRTUGI4HQ_js.translationsEn["pptx.export.errorNo2dContext"]);
6760
6866
  }
6761
6867
  const fps = 30;
6762
6868
  const stream = recordingCanvas.captureStream(fps);
6763
6869
  const recorder = new MediaRecorder(stream, {
6764
- mimeType: chunkY2KIB3QH_js.pickSupportedMimeType([...chunkY2KIB3QH_js.WEBM_MIME_CANDIDATES]),
6870
+ mimeType: chunkWVDM36ZM_js.pickSupportedMimeType([...chunkWVDM36ZM_js.WEBM_MIME_CANDIDATES]),
6765
6871
  videoBitsPerSecond: 5e6
6766
6872
  });
6767
6873
  const chunks = [];
@@ -6784,8 +6890,8 @@ async function exportAllSlidesAsVideo(slideStageRef, totalSlides, setActiveSlide
6784
6890
  const duration = slideTimingsMs?.[i] ?? slideDurationMs;
6785
6891
  ctx.clearRect(0, 0, recordingCanvas.width, recordingCanvas.height);
6786
6892
  ctx.drawImage(slideCanvases[i], 0, 0);
6787
- const frameInterval = chunkY2KIB3QH_js.fpsToFrameIntervalMs(fps);
6788
- const framesNeeded = chunkY2KIB3QH_js.segmentFrameCount(duration, fps);
6893
+ const frameInterval = chunkWVDM36ZM_js.fpsToFrameIntervalMs(fps);
6894
+ const framesNeeded = chunkWVDM36ZM_js.segmentFrameCount(duration, fps);
6789
6895
  for (let f = 0; f < framesNeeded; f++) {
6790
6896
  if (signal?.aborted) {
6791
6897
  recorder.stop();
@@ -6832,9 +6938,9 @@ async function exportAllSlidesAsGif(slideStageRef, totalSlides, setActiveSlide,
6832
6938
  }
6833
6939
  setActiveSlide(currentSlideIndex);
6834
6940
  if (frames.length === 0) {
6835
- throw new Error(chunkDVZF4ARG_js.translationsEn["pptx.export.errorNoSlidesGif"]);
6941
+ throw new Error(chunkRTUGI4HQ_js.translationsEn["pptx.export.errorNoSlidesGif"]);
6836
6942
  }
6837
- const gifBytes = chunkY2KIB3QH_js.encodeGif(frames, Math.round(slideDurationMs / 10));
6943
+ const gifBytes = chunkWVDM36ZM_js.encodeGif(frames, Math.round(slideDurationMs / 10));
6838
6944
  onProgress?.(totalSlides, totalSlides);
6839
6945
  const buf = new ArrayBuffer(gifBytes.length);
6840
6946
  new Uint8Array(buf).set(gifBytes);
@@ -6888,7 +6994,7 @@ function exportAllSlidesToSvg(data, options = {}) {
6888
6994
  continue;
6889
6995
  }
6890
6996
  onProgress?.(processedCount, data.slides.length);
6891
- let svg = chunkY2KIB3QH_js.SvgExporter.exportSlide(slide, data.width, data.height, svgOptions);
6997
+ let svg = chunkWVDM36ZM_js.SvgExporter.exportSlide(slide, data.width, data.height, svgOptions);
6892
6998
  if (embedFonts && fontFaces?.length) {
6893
6999
  svg = injectFontFaces(svg, fontFaces);
6894
7000
  }
@@ -6915,12 +7021,14 @@ function useExportSaveAs(input) {
6915
7021
  appProperties,
6916
7022
  customProperties,
6917
7023
  tagCollections,
7024
+ slideMasters,
6918
7025
  notesMaster,
6919
7026
  handoutMaster,
6920
7027
  guides,
6921
7028
  activeSlideIndexForGuides,
6922
7029
  theme,
6923
7030
  canvasSize,
7031
+ slideSizeEmu,
6924
7032
  modalControls,
6925
7033
  password
6926
7034
  } = input;
@@ -6944,13 +7052,13 @@ function useExportSaveAs(input) {
6944
7052
  setExportProgress(10);
6945
7053
  setExportStatusMessage("Adding presentation...");
6946
7054
  const pptxData = await serializeSlides();
6947
- const pptxFilename = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() ?? "presentation.pptx" : "presentation.pptx";
7055
+ const pptxFilename = chunkWVDM36ZM_js.savedPresentationFileName(filePath);
6948
7056
  if (pptxData) {
6949
7057
  pkgFolder.file(pptxFilename, pptxData);
6950
7058
  }
6951
7059
  setExportProgress(70);
6952
7060
  setExportStatusMessage("Writing README...");
6953
- const readme = chunkY2KIB3QH_js.generatePackageReadme(pptxFilename);
7061
+ const readme = chunkWVDM36ZM_js.generatePackageReadme(pptxFilename);
6954
7062
  pkgFolder.file("README.txt", readme);
6955
7063
  if (abortCtrl.signal.aborted) {
6956
7064
  throw new DOMException("Export cancelled", "AbortError");
@@ -6960,8 +7068,7 @@ function useExportSaveAs(input) {
6960
7068
  const zipBlob = await zip.generateAsync({ type: "blob" });
6961
7069
  setExportProgress(95);
6962
7070
  setExportStatusMessage("Downloading...");
6963
- const baseName = pptxFilename.replace(/\.[^.]+$/u, "");
6964
- chunkY2KIB3QH_js.downloadBlob(zipBlob, `${baseName}-package.zip`);
7071
+ chunkWVDM36ZM_js.downloadBlob(zipBlob, `${chunkWVDM36ZM_js.presentationBaseName(pptxFilename)}-package.zip`);
6965
7072
  setExportProgress(100);
6966
7073
  } catch (err) {
6967
7074
  if (err.name !== "AbortError") {
@@ -6977,16 +7084,15 @@ function useExportSaveAs(input) {
6977
7084
  if (!handler) {
6978
7085
  return;
6979
7086
  }
6980
- const ext = format === "ppsx" ? "ppsx" : format === "pptm" ? "pptm" : "pptx";
6981
- const baseName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop()?.replace(/\.[^.]+$/u, "") ?? "presentation" : "presentation";
7087
+ const downloadName = chunkWVDM36ZM_js.savedPresentationFileName(filePath, format);
6982
7088
  try {
6983
7089
  const data = await buildSaveAsData(handler, format);
6984
7090
  const blob = new Blob([data], {
6985
7091
  type: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
6986
7092
  });
6987
- chunkY2KIB3QH_js.downloadBlob(blob, `${baseName}.${ext}`);
7093
+ chunkWVDM36ZM_js.downloadBlob(blob, downloadName);
6988
7094
  } catch (err) {
6989
- console.error(`[PowerPointViewer] Save as .${ext} failed:`, err);
7095
+ console.error(`[PowerPointViewer] Save as .${format} failed:`, err);
6990
7096
  }
6991
7097
  };
6992
7098
  const buildSaveAsData = async (handler, format) => {
@@ -6997,15 +7103,18 @@ function useExportSaveAs(input) {
6997
7103
  const pptxGuides = guides.map((g) => ({
6998
7104
  id: g.id,
6999
7105
  orientation: g.axis === "h" ? "horz" : "vert",
7000
- positionEmu: chunkY2KIB3QH_js.guidePxToEmu(g.position)
7106
+ positionEmu: chunkWVDM36ZM_js.guidePxToEmu(g.position)
7001
7107
  }));
7002
7108
  return {
7003
7109
  ...slide,
7004
7110
  guides: pptxGuides.length > 0 ? pptxGuides : void 0
7005
7111
  };
7006
7112
  });
7007
- const slidesToSave = chunkY2KIB3QH_js.buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
7113
+ const slidesToSave = chunkWVDM36ZM_js.buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
7008
7114
  const saveOptions = {
7115
+ // Save As shares Save's slide-size decision; leaving it out here is how
7116
+ // a preset picked in the inspector reached one save path and not the other.
7117
+ slideSize: chunkWVDM36ZM_js.resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size,
7009
7118
  headerFooter,
7010
7119
  presentationProperties,
7011
7120
  customShows: customShows.length > 0 ? customShows : void 0,
@@ -7014,27 +7123,23 @@ function useExportSaveAs(input) {
7014
7123
  appProperties: appProperties ?? void 0,
7015
7124
  customProperties: customProperties.length > 0 ? customProperties : void 0,
7016
7125
  tags: tagCollections.length > 0 ? tagCollections : void 0,
7126
+ slideMasters,
7017
7127
  notesMaster,
7018
7128
  handoutMaster,
7019
7129
  outputFormat: format
7020
7130
  };
7021
- if (password) {
7022
- return handler.saveEncrypted(
7023
- slidesToSave,
7024
- password,
7025
- saveOptions
7026
- );
7027
- }
7028
- return handler.save(slidesToSave, saveOptions);
7131
+ return chunkWVDM36ZM_js.saveDeckWithPassword(handler, slidesToSave, saveOptions, password);
7029
7132
  };
7030
7133
  const handleExportJson = () => {
7031
7134
  const sourceName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() : void 0;
7135
+ const slideSize = chunkWVDM36ZM_js.resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size;
7032
7136
  const data = {
7033
- slides: chunkY2KIB3QH_js.buildSaveSlides(slides, templateElementsBySlideId),
7137
+ slides: chunkWVDM36ZM_js.buildSaveSlides(slides, templateElementsBySlideId),
7034
7138
  width: canvasSize.width,
7035
7139
  height: canvasSize.height,
7036
- widthEmu: chunkY2KIB3QH_js.guidePxToEmu(canvasSize.width),
7037
- heightEmu: chunkY2KIB3QH_js.guidePxToEmu(canvasSize.height),
7140
+ widthEmu: slideSize.widthEmu,
7141
+ heightEmu: slideSize.heightEmu,
7142
+ slideSizeType: slideSize.type === "" ? void 0 : slideSize.type,
7038
7143
  theme,
7039
7144
  headerFooter,
7040
7145
  presentationProperties,
@@ -7048,7 +7153,7 @@ function useExportSaveAs(input) {
7048
7153
  handoutMaster
7049
7154
  };
7050
7155
  try {
7051
- chunkY2KIB3QH_js.exportDeckJson(data, sourceName);
7156
+ chunkWVDM36ZM_js.exportDeckJson(data, sourceName);
7052
7157
  } catch (err) {
7053
7158
  console.error("[PowerPointViewer] JSON export failed:", err);
7054
7159
  }
@@ -7088,7 +7193,7 @@ function safeConfirm(message) {
7088
7193
  }
7089
7194
  }
7090
7195
  function downloadBlob2(blob, filename) {
7091
- chunkY2KIB3QH_js.downloadBlob(blob, chunkY2KIB3QH_js.sanitizeDownloadFilename(filename));
7196
+ chunkWVDM36ZM_js.downloadBlob(blob, chunkWVDM36ZM_js.sanitizeDownloadFilename(filename));
7092
7197
  }
7093
7198
 
7094
7199
  // src/viewer/hooks/useExportHandlers.ts
@@ -7111,12 +7216,14 @@ function useExportHandlers(input) {
7111
7216
  appProperties,
7112
7217
  customProperties,
7113
7218
  tagCollections,
7219
+ slideMasters,
7114
7220
  notesMaster,
7115
7221
  handoutMaster,
7116
7222
  guides,
7117
7223
  activeSlideIndexForGuides,
7118
7224
  theme,
7119
7225
  canvasSize,
7226
+ slideSizeEmu,
7120
7227
  password
7121
7228
  } = input;
7122
7229
  const [exportModalOpen, setExportModalOpen] = react.useState(false);
@@ -7152,12 +7259,14 @@ function useExportHandlers(input) {
7152
7259
  appProperties,
7153
7260
  customProperties,
7154
7261
  tagCollections,
7262
+ slideMasters,
7155
7263
  notesMaster,
7156
7264
  handoutMaster,
7157
7265
  guides,
7158
7266
  activeSlideIndexForGuides,
7159
7267
  theme,
7160
7268
  canvasSize,
7269
+ slideSizeEmu,
7161
7270
  modalControls,
7162
7271
  password
7163
7272
  });
@@ -7194,21 +7303,21 @@ function useExportHandlers(input) {
7194
7303
  {
7195
7304
  scale: 2,
7196
7305
  onProgress: (current, total) => {
7197
- setExportProgress(chunkY2KIB3QH_js.slideProgressPercent(current, total));
7198
- setExportStatusMessage(chunkY2KIB3QH_js.slideStatusLabel("Rendering", current, total));
7306
+ setExportProgress(chunkWVDM36ZM_js.slideProgressPercent(current, total));
7307
+ setExportStatusMessage(chunkWVDM36ZM_js.slideStatusLabel("Rendering", current, total));
7199
7308
  },
7200
7309
  signal: abortCtrl.signal
7201
7310
  }
7202
7311
  );
7203
- setExportProgress(chunkY2KIB3QH_js.EXPORT_ASSEMBLING_PERCENT);
7312
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_ASSEMBLING_PERCENT);
7204
7313
  setExportStatusMessage("Building PDF...");
7205
7314
  await new Promise((r) => {
7206
7315
  setTimeout(r, 100);
7207
7316
  });
7208
- setExportProgress(chunkY2KIB3QH_js.EXPORT_DONE_PERCENT);
7317
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_DONE_PERCENT);
7209
7318
  setExportStatusMessage("Done!");
7210
7319
  } catch (err) {
7211
- if (!chunkY2KIB3QH_js.isExportAbortError(err)) {
7320
+ if (!chunkWVDM36ZM_js.isExportAbortError(err)) {
7212
7321
  console.error("[PowerPointViewer] PDF export failed:", err);
7213
7322
  }
7214
7323
  } finally {
@@ -7238,21 +7347,21 @@ function useExportHandlers(input) {
7238
7347
  {
7239
7348
  scale: 2,
7240
7349
  onProgress: (current, total) => {
7241
- setExportProgress(chunkY2KIB3QH_js.slideProgressPercent(current, total));
7242
- setExportStatusMessage(chunkY2KIB3QH_js.slideStatusLabel("Rendering", current, total));
7350
+ setExportProgress(chunkWVDM36ZM_js.slideProgressPercent(current, total));
7351
+ setExportStatusMessage(chunkWVDM36ZM_js.slideStatusLabel("Rendering", current, total));
7243
7352
  },
7244
7353
  signal: abortCtrl.signal
7245
7354
  }
7246
7355
  );
7247
- setExportProgress(chunkY2KIB3QH_js.EXPORT_ASSEMBLING_PERCENT);
7356
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_ASSEMBLING_PERCENT);
7248
7357
  setExportStatusMessage("Building PDF...");
7249
7358
  await new Promise((r) => {
7250
7359
  setTimeout(r, 100);
7251
7360
  });
7252
- setExportProgress(chunkY2KIB3QH_js.EXPORT_DONE_PERCENT);
7361
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_DONE_PERCENT);
7253
7362
  setExportStatusMessage("Done!");
7254
7363
  } catch (err) {
7255
- if (!chunkY2KIB3QH_js.isExportAbortError(err)) {
7364
+ if (!chunkWVDM36ZM_js.isExportAbortError(err)) {
7256
7365
  console.error("[PowerPointViewer] Notes PDF export failed:", err);
7257
7366
  }
7258
7367
  } finally {
@@ -7293,22 +7402,22 @@ function useExportHandlers(input) {
7293
7402
  scale: 1,
7294
7403
  slideDurationMs: 3e3,
7295
7404
  onProgress: (current, total) => {
7296
- setExportProgress(chunkY2KIB3QH_js.slideProgressPercent(current, total, 45));
7297
- setExportStatusMessage(chunkY2KIB3QH_js.slideStatusLabel("Capturing", current, total));
7405
+ setExportProgress(chunkWVDM36ZM_js.slideProgressPercent(current, total, 45));
7406
+ setExportStatusMessage(chunkWVDM36ZM_js.slideStatusLabel("Capturing", current, total));
7298
7407
  },
7299
7408
  onRecordProgress: (current, total) => {
7300
- setExportProgress(chunkY2KIB3QH_js.recordProgressPercent(current, total));
7301
- setExportStatusMessage(chunkY2KIB3QH_js.slideStatusLabel("Recording", current, total));
7409
+ setExportProgress(chunkWVDM36ZM_js.recordProgressPercent(current, total));
7410
+ setExportStatusMessage(chunkWVDM36ZM_js.slideStatusLabel("Recording", current, total));
7302
7411
  },
7303
7412
  signal: abortCtrl.signal
7304
7413
  }
7305
7414
  );
7306
- setExportProgress(chunkY2KIB3QH_js.EXPORT_ASSEMBLING_PERCENT);
7415
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_ASSEMBLING_PERCENT);
7307
7416
  setExportStatusMessage("Saving file...");
7308
7417
  downloadBlob2(blob, "presentation.webm");
7309
- setExportProgress(chunkY2KIB3QH_js.EXPORT_DONE_PERCENT);
7418
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_DONE_PERCENT);
7310
7419
  } catch (err) {
7311
- if (!chunkY2KIB3QH_js.isExportAbortError(err)) {
7420
+ if (!chunkWVDM36ZM_js.isExportAbortError(err)) {
7312
7421
  console.error("[PowerPointViewer] Video export failed:", err);
7313
7422
  }
7314
7423
  } finally {
@@ -7336,18 +7445,18 @@ function useExportHandlers(input) {
7336
7445
  scale: 0.5,
7337
7446
  slideDurationMs: 2e3,
7338
7447
  onProgress: (current, total) => {
7339
- setExportProgress(chunkY2KIB3QH_js.slideProgressPercent(current, total));
7340
- setExportStatusMessage(chunkY2KIB3QH_js.slideStatusLabel("Encoding", current, total));
7448
+ setExportProgress(chunkWVDM36ZM_js.slideProgressPercent(current, total));
7449
+ setExportStatusMessage(chunkWVDM36ZM_js.slideStatusLabel("Encoding", current, total));
7341
7450
  },
7342
7451
  signal: abortCtrl.signal
7343
7452
  }
7344
7453
  );
7345
- setExportProgress(chunkY2KIB3QH_js.EXPORT_ASSEMBLING_PERCENT);
7454
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_ASSEMBLING_PERCENT);
7346
7455
  setExportStatusMessage("Saving file...");
7347
7456
  downloadBlob2(blob, "presentation.gif");
7348
- setExportProgress(chunkY2KIB3QH_js.EXPORT_DONE_PERCENT);
7457
+ setExportProgress(chunkWVDM36ZM_js.EXPORT_DONE_PERCENT);
7349
7458
  } catch (err) {
7350
- if (!chunkY2KIB3QH_js.isExportAbortError(err)) {
7459
+ if (!chunkWVDM36ZM_js.isExportAbortError(err)) {
7351
7460
  console.error("[PowerPointViewer] GIF export failed:", err);
7352
7461
  }
7353
7462
  } finally {
@@ -7388,7 +7497,7 @@ function openPrintWindow(title, bodyHtml, orientation, colorFilter, frameSlides)
7388
7497
  }
7389
7498
  printWindow.document.open();
7390
7499
  printWindow.document.write(
7391
- chunkY2KIB3QH_js.buildPrintHtmlDocument({ title, bodyHtml, orientation, colorFilter, frameSlides })
7500
+ chunkWVDM36ZM_js.buildPrintHtmlDocument({ title, bodyHtml, orientation, colorFilter, frameSlides })
7392
7501
  );
7393
7502
  printWindow.document.close();
7394
7503
  printWindow.focus();
@@ -7449,7 +7558,7 @@ function usePrintHandlers(input) {
7449
7558
  if (svgs.length === 0) {
7450
7559
  return;
7451
7560
  }
7452
- const printDoc = chunkY2KIB3QH_js.buildPrintDocument(svgs, pptxData.width, pptxData.height, {
7561
+ const printDoc = chunkWVDM36ZM_js.buildPrintDocument(svgs, pptxData.width, pptxData.height, {
7453
7562
  title: "Slides (Vector)",
7454
7563
  orientation: settings.orientation,
7455
7564
  colorFilter
@@ -7485,7 +7594,7 @@ function usePrintHandlers(input) {
7485
7594
  if (settings.printWhat === "outline") {
7486
7595
  openPrintWindow(
7487
7596
  "Outline",
7488
- `<div class="outline-page">${chunkY2KIB3QH_js.buildOutlineHtml(slideIndices, slides)}</div>`,
7597
+ `<div class="outline-page">${chunkWVDM36ZM_js.buildOutlineHtml(slideIndices, slides)}</div>`,
7489
7598
  settings.orientation,
7490
7599
  colorFilter,
7491
7600
  settings.frameSlides
@@ -7510,7 +7619,7 @@ function usePrintHandlers(input) {
7510
7619
  if (settings.printWhat === "slides") {
7511
7620
  openPrintWindow(
7512
7621
  "Slides",
7513
- chunkY2KIB3QH_js.buildSlidesHtml(slideImages, slideIndices),
7622
+ chunkWVDM36ZM_js.buildSlidesHtml(slideImages, slideIndices),
7514
7623
  settings.orientation,
7515
7624
  colorFilter,
7516
7625
  settings.frameSlides
@@ -7520,7 +7629,7 @@ function usePrintHandlers(input) {
7520
7629
  if (settings.printWhat === "notes") {
7521
7630
  openPrintWindow(
7522
7631
  "Notes Pages",
7523
- chunkY2KIB3QH_js.buildNotesHtml(slideImages, slideIndices, slides),
7632
+ chunkWVDM36ZM_js.buildNotesHtml(slideImages, slideIndices, slides),
7524
7633
  "portrait",
7525
7634
  colorFilter,
7526
7635
  settings.frameSlides
@@ -7531,7 +7640,7 @@ function usePrintHandlers(input) {
7531
7640
  const spp = settings.slidesPerPage;
7532
7641
  openPrintWindow(
7533
7642
  `Handout ${spp} per page`,
7534
- chunkY2KIB3QH_js.buildHandoutsHtml(slideImages, slideIndices, spp),
7643
+ chunkWVDM36ZM_js.buildHandoutsHtml(slideImages, slideIndices, spp),
7535
7644
  "portrait",
7536
7645
  colorFilter,
7537
7646
  settings.frameSlides
@@ -7595,8 +7704,8 @@ function useThemeHandlers(input) {
7595
7704
  return;
7596
7705
  }
7597
7706
  await handler.updateThemeColorScheme(colorScheme);
7598
- const previousMap = theme?.colorScheme ? chunkY2KIB3QH_js.buildThemeColorMap(theme.colorScheme) : {};
7599
- setSlides((prev) => chunkY2KIB3QH_js.reResolveSlideColors(prev, previousMap, colorScheme));
7707
+ const previousMap = theme?.colorScheme ? chunkWVDM36ZM_js.buildThemeColorMap(theme.colorScheme) : {};
7708
+ setSlides((prev) => chunkWVDM36ZM_js.reResolveSlideColors(prev, previousMap, colorScheme));
7600
7709
  setTheme((prev) => prev ? { ...prev, colorScheme } : { colorScheme });
7601
7710
  bumpHistory();
7602
7711
  history.markDirty();
@@ -7701,7 +7810,7 @@ function useThemeSwitching(input) {
7701
7810
  }
7702
7811
  try {
7703
7812
  await handler.applyTheme(preset.colorScheme, preset.fontScheme, preset.name);
7704
- const newData = chunkY2KIB3QH_js.applyThemeToData(data, preset.colorScheme, preset.fontScheme, preset.name);
7813
+ const newData = chunkWVDM36ZM_js.applyThemeToData(data, preset.colorScheme, preset.fontScheme, preset.name);
7705
7814
  onDataChange(newData);
7706
7815
  onThemeChanged?.(preset);
7707
7816
  } catch (error) {
@@ -7718,7 +7827,7 @@ function useThemeSwitching(input) {
7718
7827
  }
7719
7828
  try {
7720
7829
  await handler.applyTheme(colorScheme, fontScheme ?? {}, themeName);
7721
- const newData = chunkY2KIB3QH_js.applyThemeToData(data, colorScheme, fontScheme, themeName);
7830
+ const newData = chunkWVDM36ZM_js.applyThemeToData(data, colorScheme, fontScheme, themeName);
7722
7831
  onDataChange(newData);
7723
7832
  } catch (error) {
7724
7833
  console.error("Failed to switch to custom theme:", error);
@@ -7730,12 +7839,12 @@ function useThemeSwitching(input) {
7730
7839
  if (!data?.theme?.colorScheme) {
7731
7840
  return void 0;
7732
7841
  }
7733
- return chunkY2KIB3QH_js.THEME_PRESETS.find(
7734
- (p) => chunkY2KIB3QH_js.themeColorSchemesEqual(data.theme?.colorScheme, p.colorScheme)
7842
+ return chunkWVDM36ZM_js.THEME_PRESETS.find(
7843
+ (p) => chunkWVDM36ZM_js.themeColorSchemesEqual(data.theme?.colorScheme, p.colorScheme)
7735
7844
  );
7736
7845
  }, [data?.theme?.colorScheme]);
7737
7846
  return {
7738
- presets: chunkY2KIB3QH_js.THEME_PRESETS,
7847
+ presets: chunkWVDM36ZM_js.THEME_PRESETS,
7739
7848
  switchToPreset,
7740
7849
  switchToCustom,
7741
7850
  currentPreset
@@ -7810,7 +7919,7 @@ function usePropertyHandlers(input) {
7810
7919
  }
7811
7920
  try {
7812
7921
  const ab = await file.arrayBuffer();
7813
- const h = new chunkY2KIB3QH_js.PptxHandler();
7922
+ const h = new chunkWVDM36ZM_js.PptxHandler();
7814
7923
  const other = await h.load(ab);
7815
7924
  if (!other) {
7816
7925
  return;
@@ -7820,7 +7929,7 @@ function usePropertyHandlers(input) {
7820
7929
  width: canvasSize.width,
7821
7930
  height: canvasSize.height
7822
7931
  };
7823
- setCompareResult(chunkY2KIB3QH_js.comparePresentation(cur, other));
7932
+ setCompareResult(chunkWVDM36ZM_js.comparePresentation(cur, other));
7824
7933
  setIsComparePanelOpen(true);
7825
7934
  } catch (err) {
7826
7935
  console.warn("Compare failed:", err);
@@ -7837,7 +7946,7 @@ function usePropertyHandlers(input) {
7837
7946
  if (!diff || diff.status === "unchanged") {
7838
7947
  return;
7839
7948
  }
7840
- setSlides((prev) => chunkY2KIB3QH_js.applyAcceptSlide(prev, diff));
7949
+ setSlides((prev) => chunkWVDM36ZM_js.applyAcceptSlide(prev, diff));
7841
7950
  setIsDirty(true);
7842
7951
  },
7843
7952
  [compareResult, setSlides, setIsDirty]
@@ -7848,10 +7957,10 @@ function usePropertyHandlers(input) {
7848
7957
  if (!compareResult) {
7849
7958
  return;
7850
7959
  }
7851
- setSlides((prev) => chunkY2KIB3QH_js.applyAcceptAllSlides(prev, compareResult));
7960
+ setSlides((prev) => chunkWVDM36ZM_js.applyAcceptAllSlides(prev, compareResult));
7852
7961
  setIsDirty(true);
7853
7962
  }, [compareResult, setSlides, setIsDirty]);
7854
- const usedFontFamilies = react.useMemo(() => chunkY2KIB3QH_js.collectUsedFonts(slides), [slides]);
7963
+ const usedFontFamilies = react.useMemo(() => chunkWVDM36ZM_js.collectUsedFonts(slides), [slides]);
7855
7964
  return {
7856
7965
  handleUpdateNotes,
7857
7966
  handleUpdateSlide,
@@ -7970,7 +8079,7 @@ function useIsMobile(input) {
7970
8079
  const containerRef = input?.containerRef;
7971
8080
  const isTouchDevice = react.useSyncExternalStore(
7972
8081
  subscribeTouchCapability,
7973
- chunkY2KIB3QH_js.detectTouchDevice,
8082
+ chunkWVDM36ZM_js.detectTouchDevice,
7974
8083
  () => false
7975
8084
  // server snapshot
7976
8085
  );
@@ -7986,7 +8095,7 @@ function useIsMobile(input) {
7986
8095
  }
7987
8096
  return containerRef?.current?.clientHeight ?? window.innerHeight;
7988
8097
  });
7989
- const [orientation, setOrientation] = react.useState(chunkY2KIB3QH_js.detectOrientation);
8098
+ const [orientation, setOrientation] = react.useState(chunkWVDM36ZM_js.detectOrientation);
7990
8099
  const [isVirtualKeyboardOpen, setIsVirtualKeyboardOpen] = react.useState(false);
7991
8100
  const [initialViewportHeight] = react.useState(
7992
8101
  () => typeof window !== "undefined" ? window.innerHeight : 800
@@ -8030,7 +8139,7 @@ function useIsMobile(input) {
8030
8139
  return;
8031
8140
  }
8032
8141
  const handleOrientationChange = () => {
8033
- setOrientation(chunkY2KIB3QH_js.detectOrientation());
8142
+ setOrientation(chunkWVDM36ZM_js.detectOrientation());
8034
8143
  };
8035
8144
  if (screen.orientation) {
8036
8145
  screen.orientation.addEventListener("change", handleOrientationChange);
@@ -8060,9 +8169,9 @@ function useIsMobile(input) {
8060
8169
  window.addEventListener("resize", handleResize);
8061
8170
  return () => window.removeEventListener("resize", handleResize);
8062
8171
  }, [isTouchDevice, initialViewportHeight]);
8063
- const isMobile = chunkY2KIB3QH_js.isMobileViewport(containerWidth, containerHeight, isTouchDevice);
8064
- const isTablet = !isMobile && containerWidth >= chunkY2KIB3QH_js.MOBILE_BREAKPOINT && containerWidth < chunkY2KIB3QH_js.TABLET_BREAKPOINT;
8065
- const isDesktop = !isMobile && containerWidth >= chunkY2KIB3QH_js.TABLET_BREAKPOINT;
8172
+ const isMobile = chunkWVDM36ZM_js.isMobileViewport(containerWidth, containerHeight, isTouchDevice);
8173
+ const isTablet = !isMobile && containerWidth >= chunkWVDM36ZM_js.MOBILE_BREAKPOINT && containerWidth < chunkWVDM36ZM_js.TABLET_BREAKPOINT;
8174
+ const isDesktop = !isMobile && containerWidth >= chunkWVDM36ZM_js.TABLET_BREAKPOINT;
8066
8175
  return {
8067
8176
  isMobile,
8068
8177
  isTablet,
@@ -8103,7 +8212,8 @@ function useViewerDialogs(input) {
8103
8212
  preMasterMode,
8104
8213
  hasDigitalSignatures,
8105
8214
  isDirty,
8106
- history
8215
+ history,
8216
+ embeddedFontFamilies
8107
8217
  } = input;
8108
8218
  const [isSmartArtDialogOpen, setIsSmartArtDialogOpen] = react.useState(false);
8109
8219
  const [isEquationDialogOpen, setIsEquationDialogOpen] = react.useState(false);
@@ -8121,13 +8231,21 @@ function useViewerDialogs(input) {
8121
8231
  const [editingEquationOmml, setEditingEquationOmml] = react.useState(
8122
8232
  null
8123
8233
  );
8124
- const [embedFontsEnabled, setEmbedFontsEnabled] = react.useState(false);
8234
+ const embeddedFontKey = (embeddedFontFamilies ?? []).join("\0");
8235
+ const fontEmbedding = react.useMemo(
8236
+ () => chunkWVDM36ZM_js.describeFontEmbedding(embeddedFontKey ? embeddedFontKey.split("\0") : []),
8237
+ [embeddedFontKey]
8238
+ );
8239
+ const [embedFontsEnabled, setEmbedFontsEnabled] = react.useState(fontEmbedding.initialEnabled);
8240
+ react.useEffect(() => {
8241
+ setEmbedFontsEnabled(fontEmbedding.initialEnabled);
8242
+ }, [fontEmbedding]);
8125
8243
  const [isNarrowViewport, setIsNarrowViewport] = react.useState(
8126
- () => typeof window !== "undefined" ? chunkY2KIB3QH_js.isMobileViewport(window.innerWidth, window.innerHeight, viewportIsTouch()) : false
8244
+ () => typeof window !== "undefined" ? chunkWVDM36ZM_js.isMobileViewport(window.innerWidth, window.innerHeight, viewportIsTouch()) : false
8127
8245
  );
8128
8246
  react.useEffect(() => {
8129
8247
  const handleWindow = () => setIsNarrowViewport(
8130
- chunkY2KIB3QH_js.isMobileViewport(window.innerWidth, window.innerHeight, viewportIsTouch())
8248
+ chunkWVDM36ZM_js.isMobileViewport(window.innerWidth, window.innerHeight, viewportIsTouch())
8131
8249
  );
8132
8250
  let observer = null;
8133
8251
  let raf = 0;
@@ -8141,12 +8259,12 @@ function useViewerDialogs(input) {
8141
8259
  const entry = entries[0];
8142
8260
  if (entry) {
8143
8261
  setIsNarrowViewport(
8144
- chunkY2KIB3QH_js.isMobileViewport(entry.contentRect.width, entry.contentRect.height, viewportIsTouch())
8262
+ chunkWVDM36ZM_js.isMobileViewport(entry.contentRect.width, entry.contentRect.height, viewportIsTouch())
8145
8263
  );
8146
8264
  }
8147
8265
  });
8148
8266
  observer.observe(el);
8149
- setIsNarrowViewport(chunkY2KIB3QH_js.isMobileViewport(el.clientWidth, el.clientHeight, viewportIsTouch()));
8267
+ setIsNarrowViewport(chunkWVDM36ZM_js.isMobileViewport(el.clientWidth, el.clientHeight, viewportIsTouch()));
8150
8268
  };
8151
8269
  attach();
8152
8270
  window.addEventListener("resize", handleWindow);
@@ -8288,6 +8406,7 @@ function useViewerDialogs(input) {
8288
8406
  setEditingEquationOmml,
8289
8407
  embedFontsEnabled,
8290
8408
  setEmbedFontsEnabled,
8409
+ fontEmbedding,
8291
8410
  isNarrowViewport,
8292
8411
  handleEnterMasterView,
8293
8412
  handleCloseMasterView,
@@ -8304,20 +8423,20 @@ function useViewerDialogs(input) {
8304
8423
  }
8305
8424
  function computeGridSpacingPx(presentationGridSpacing) {
8306
8425
  if (presentationGridSpacing) {
8307
- const px = Math.round(presentationGridSpacing.cx / chunkWK22Z7PK_js.EMU_PER_PX);
8426
+ const px = Math.round(presentationGridSpacing.cx / chunk4LWGAVAP_js.EMU_PER_PX);
8308
8427
  if (px > 0) {
8309
8428
  return px;
8310
8429
  }
8311
8430
  }
8312
- return chunkWK22Z7PK_js.GRID_SIZE;
8431
+ return chunk4LWGAVAP_js.GRID_SIZE;
8313
8432
  }
8314
8433
  function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows) {
8315
8434
  const activeShow = activeCustomShowId ? customShows.find((show) => show.id === activeCustomShowId) : void 0;
8316
- return chunkY2KIB3QH_js.resolveShowSlideIndexes(slides, activeShow);
8435
+ return chunkWVDM36ZM_js.resolveShowSlideIndexes(slides, activeShow);
8317
8436
  }
8318
8437
  function computeSlideSectionGroups(slides, sections) {
8319
- return chunkY2KIB3QH_js.groupSlidesBySection(sections, slides).map((group) => ({
8320
- id: group.section?.id ?? (sections.length > 0 ? chunkWK22Z7PK_js.UNGROUPED_SECTION_ID : "default"),
8438
+ return chunkWVDM36ZM_js.groupSlidesBySection(sections, slides).map((group) => ({
8439
+ id: group.section?.id ?? (sections.length > 0 ? chunk4LWGAVAP_js.UNGROUPED_SECTION_ID : chunk4LWGAVAP_js.DEFAULT_SECTION_GROUP_ID),
8321
8440
  label: group.section?.name ?? (sections.length > 0 ? "Ungrouped Slides" : "Slides"),
8322
8441
  slideIndexes: group.slideIndexes,
8323
8442
  ...group.section?.color !== void 0 ? { color: group.section.color } : {},
@@ -8325,30 +8444,15 @@ function computeSlideSectionGroups(slides, sections) {
8325
8444
  }));
8326
8445
  }
8327
8446
  function computeMasterPseudoSlide(mode, activeLayout, activeMaster) {
8328
- if (mode !== "master") {
8447
+ if (mode !== "master" || !activeMaster) {
8329
8448
  return void 0;
8330
8449
  }
8331
- if (activeLayout) {
8332
- return {
8333
- id: activeLayout.path,
8334
- rId: "",
8335
- slideNumber: 0,
8336
- elements: activeLayout.elements ?? [],
8337
- backgroundColor: activeLayout.backgroundColor ?? activeMaster?.backgroundColor,
8338
- backgroundImage: activeLayout.backgroundImage ?? activeMaster?.backgroundImage
8339
- };
8340
- }
8341
- if (activeMaster) {
8342
- return {
8343
- id: activeMaster.path,
8344
- rId: "",
8345
- slideNumber: 0,
8346
- elements: activeMaster.elements ?? [],
8347
- backgroundColor: activeMaster.backgroundColor,
8348
- backgroundImage: activeMaster.backgroundImage
8349
- };
8350
- }
8351
- return void 0;
8450
+ const document2 = activeLayout ? { slideMasters: [{ ...activeMaster, layouts: [activeLayout] }] } : { slideMasters: [activeMaster] };
8451
+ return chunkWVDM36ZM_js.masterViewPseudoSlide(document2, {
8452
+ tab: "slides",
8453
+ masterIndex: 0,
8454
+ layoutIndex: activeLayout ? 0 : null
8455
+ });
8352
8456
  }
8353
8457
  function useDerivedSlideState(input) {
8354
8458
  const { t } = reactI18next.useTranslation();
@@ -8372,10 +8476,10 @@ function useDerivedSlideState(input) {
8372
8476
  );
8373
8477
  const slideSectionGroups = react.useMemo(
8374
8478
  () => computeSlideSectionGroups(slides, sections).map((group) => {
8375
- if (group.id === chunkWK22Z7PK_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
8479
+ if (group.id === chunk4LWGAVAP_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
8376
8480
  return { ...group, label: t("pptx.slides.ungroupedSlides") };
8377
8481
  }
8378
- if (group.id === "default" && group.label === "Slides") {
8482
+ if (group.id === chunk4LWGAVAP_js.DEFAULT_SECTION_GROUP_ID && group.label === "Slides") {
8379
8483
  return { ...group, label: t("pptx.sections.slides") };
8380
8484
  }
8381
8485
  return group;
@@ -8475,13 +8579,13 @@ function useAnnotationHandlers(input) {
8475
8579
  }, [annotations, setMode, setSlides, history]);
8476
8580
  const handleSetMode = react.useCallback(
8477
8581
  (nextMode) => {
8478
- if (mode === "present" && nextMode !== "present" && !chunkY2KIB3QH_js.mayLeaveSlideShow()) {
8582
+ if (mode === "present" && nextMode !== "present" && !chunkWVDM36ZM_js.mayLeaveSlideShow()) {
8479
8583
  return;
8480
8584
  }
8481
8585
  if (nextMode === "present") {
8482
8586
  presentation.enterPresentMode();
8483
8587
  } else if (mode === "present" && annotations.hasAnyAnnotations) {
8484
- chunkY2KIB3QH_js.stopAllPersistentAudio();
8588
+ chunkWVDM36ZM_js.stopAllPersistentAudio();
8485
8589
  pendingModeAfterAnnotationsRef.current = nextMode;
8486
8590
  if (promptKeepInkAnnotations) {
8487
8591
  setShowKeepAnnotationsDialog(true);
@@ -8490,7 +8594,7 @@ function useAnnotationHandlers(input) {
8490
8594
  }
8491
8595
  } else {
8492
8596
  if (mode === "present") {
8493
- chunkY2KIB3QH_js.stopAllPersistentAudio();
8597
+ chunkWVDM36ZM_js.stopAllPersistentAudio();
8494
8598
  }
8495
8599
  setMode(nextMode);
8496
8600
  }
@@ -8529,6 +8633,8 @@ function useSerialize(input) {
8529
8633
  slides,
8530
8634
  templateElementsBySlideId,
8531
8635
  activeSlideIndex,
8636
+ canvasSize,
8637
+ slideSizeEmu,
8532
8638
  guides,
8533
8639
  headerFooter,
8534
8640
  presentationProperties,
@@ -8538,12 +8644,15 @@ function useSerialize(input) {
8538
8644
  appProperties,
8539
8645
  customProperties,
8540
8646
  tagCollections,
8647
+ slideMasters,
8541
8648
  notesMaster,
8542
8649
  handoutMaster,
8543
8650
  handlerRef,
8544
8651
  inlineEditingElementIdRef,
8545
8652
  inlineEditingTextRef,
8546
- password
8653
+ password,
8654
+ embedFonts = true,
8655
+ purpose
8547
8656
  } = input;
8548
8657
  return react.useCallback(async () => {
8549
8658
  const handler = handlerRef.current;
@@ -8556,13 +8665,13 @@ function useSerialize(input) {
8556
8665
  let processedSlide = slide;
8557
8666
  if (pendingEditId) {
8558
8667
  const updatedElements = slide.elements.map((el) => {
8559
- if (el.id !== pendingEditId || !chunkY2KIB3QH_js.hasTextProperties(el)) {
8668
+ if (el.id !== pendingEditId || !chunkWVDM36ZM_js.hasTextProperties(el)) {
8560
8669
  return el;
8561
8670
  }
8562
8671
  return {
8563
8672
  ...el,
8564
8673
  text: pendingEditText,
8565
- textSegments: chunkY2KIB3QH_js.remapTextToSegments(pendingEditText, el.textSegments, el.textStyle)
8674
+ textSegments: chunkWVDM36ZM_js.remapTextToSegments(pendingEditText, el.textSegments, el.textStyle)
8566
8675
  };
8567
8676
  });
8568
8677
  if (updatedElements.some((el, i) => el !== slide.elements[i])) {
@@ -8575,15 +8684,19 @@ function useSerialize(input) {
8575
8684
  const pptxGuides = guides.map((g) => ({
8576
8685
  id: g.id,
8577
8686
  orientation: g.axis === "h" ? "horz" : "vert",
8578
- positionEmu: chunkY2KIB3QH_js.guidePxToEmu(g.position)
8687
+ positionEmu: chunkWVDM36ZM_js.guidePxToEmu(g.position)
8579
8688
  }));
8580
8689
  return {
8581
8690
  ...processedSlide,
8582
8691
  guides: pptxGuides.length > 0 ? pptxGuides : void 0
8583
8692
  };
8584
8693
  });
8585
- const slidesToSave = chunkY2KIB3QH_js.buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
8694
+ const slidesToSave = chunkWVDM36ZM_js.buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
8586
8695
  const saveOptions = {
8696
+ // Without this the Slide Size card edited a viewer-only pixel value and
8697
+ // the saved `p:sldSz` never moved: passing `slideSize` is the only way a
8698
+ // slide-size edit reaches the file.
8699
+ slideSize: chunkWVDM36ZM_js.resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size,
8587
8700
  headerFooter,
8588
8701
  presentationProperties,
8589
8702
  customShows: customShows.length > 0 ? customShows : void 0,
@@ -8592,16 +8705,17 @@ function useSerialize(input) {
8592
8705
  appProperties,
8593
8706
  customProperties: customProperties.length > 0 ? customProperties : void 0,
8594
8707
  tags: tagCollections.length > 0 ? tagCollections : void 0,
8708
+ slideMasters,
8595
8709
  notesMaster,
8596
- handoutMaster
8710
+ handoutMaster,
8711
+ ...chunkWVDM36ZM_js.embeddedFontSaveOptions(embedFonts)
8597
8712
  };
8598
- if (password) {
8599
- return handler.saveEncrypted(slidesToSave, password, saveOptions);
8600
- }
8601
- return handler.save(slidesToSave, saveOptions);
8713
+ return chunkWVDM36ZM_js.saveDeckWithPassword(handler, slidesToSave, saveOptions, { password, purpose });
8602
8714
  }, [
8603
8715
  slides,
8604
8716
  templateElementsBySlideId,
8717
+ canvasSize,
8718
+ slideSizeEmu,
8605
8719
  headerFooter,
8606
8720
  presentationProperties,
8607
8721
  customShows,
@@ -8610,6 +8724,7 @@ function useSerialize(input) {
8610
8724
  appProperties,
8611
8725
  customProperties,
8612
8726
  tagCollections,
8727
+ slideMasters,
8613
8728
  notesMaster,
8614
8729
  handoutMaster,
8615
8730
  guides,
@@ -8617,7 +8732,9 @@ function useSerialize(input) {
8617
8732
  handlerRef,
8618
8733
  inlineEditingElementIdRef,
8619
8734
  inlineEditingTextRef,
8620
- password
8735
+ password,
8736
+ embedFonts,
8737
+ purpose
8621
8738
  ]);
8622
8739
  }
8623
8740
 
@@ -8733,7 +8850,8 @@ function usePresentationSetup(input) {
8733
8850
  history,
8734
8851
  endWithBlackSlide = true,
8735
8852
  promptKeepInkAnnotations = true,
8736
- popupToolbarEnabled = true
8853
+ popupToolbarEnabled = true,
8854
+ onToggleSubtitles
8737
8855
  } = input;
8738
8856
  const actionSoundHandlerRef = react.useRef(null);
8739
8857
  const [, setShowKeepAnnotationsDialog] = react.useState(false);
@@ -8751,7 +8869,7 @@ function usePresentationSetup(input) {
8751
8869
  containerRef,
8752
8870
  content,
8753
8871
  onSetMode: (nextMode) => {
8754
- if (mode === "present" && nextMode !== "present" && !chunkY2KIB3QH_js.mayLeaveSlideShow()) {
8872
+ if (mode === "present" && nextMode !== "present" && !chunkWVDM36ZM_js.mayLeaveSlideShow()) {
8755
8873
  return;
8756
8874
  }
8757
8875
  if (mode === "present" && nextMode !== "present" && annotations.hasAnyAnnotations && promptKeepInkAnnotations) {
@@ -8759,7 +8877,7 @@ function usePresentationSetup(input) {
8759
8877
  setShowKeepAnnotationsDialog(true);
8760
8878
  } else {
8761
8879
  if (mode === "present" && nextMode !== "present") {
8762
- chunkY2KIB3QH_js.stopAllPersistentAudio();
8880
+ chunkWVDM36ZM_js.stopAllPersistentAudio();
8763
8881
  stopAnimationSound();
8764
8882
  }
8765
8883
  setMode(nextMode);
@@ -8812,11 +8930,12 @@ function usePresentationSetup(input) {
8812
8930
  onEraseAnnotations: () => annotations.clearAnnotations(),
8813
8931
  onToggleInkMarkup: () => annotations.setInkMarkupVisible(!annotations.inkMarkupVisible),
8814
8932
  onToggleToolbar: () => annotations.setToolbarVisible(!annotations.toolbarVisible),
8933
+ onToggleSubtitles,
8815
8934
  onSaveRehearsalTimings: (timings) => {
8816
- setSlides((prev) => chunkY2KIB3QH_js.applyRehearsalTimings(prev, timings));
8935
+ setSlides((prev) => chunkWVDM36ZM_js.applyRehearsalTimings(prev, timings));
8817
8936
  history.markDirty();
8818
8937
  },
8819
- loopContinuously: chunkY2KIB3QH_js.shouldLoopContinuously(presentationProperties),
8938
+ loopContinuously: chunkWVDM36ZM_js.shouldLoopContinuously(presentationProperties),
8820
8939
  showWithAnimation: presentationProperties.showWithAnimation,
8821
8940
  useTimings: presentationProperties.advanceMode !== "manual",
8822
8941
  endWithBlackSlide
@@ -8843,6 +8962,33 @@ function useEditorOperations(input) {
8843
8962
  handlerRef,
8844
8963
  transformCommittedText
8845
8964
  } = input;
8965
+ const masterView = react.useMemo(
8966
+ () => ({
8967
+ target: mode === "master" ? {
8968
+ tab: state.masterViewTab,
8969
+ masterIndex: state.activeMasterIndex,
8970
+ layoutIndex: state.activeLayoutIndex
8971
+ } : null,
8972
+ slideMasters: state.slideMasters,
8973
+ notesMaster: state.notesMaster,
8974
+ handoutMaster: state.handoutMaster,
8975
+ setSlideMasters: state.setSlideMasters,
8976
+ setNotesMaster: state.setNotesMaster,
8977
+ setHandoutMaster: state.setHandoutMaster
8978
+ }),
8979
+ [
8980
+ mode,
8981
+ state.masterViewTab,
8982
+ state.activeMasterIndex,
8983
+ state.activeLayoutIndex,
8984
+ state.slideMasters,
8985
+ state.notesMaster,
8986
+ state.handoutMaster,
8987
+ state.setSlideMasters,
8988
+ state.setNotesMaster,
8989
+ state.setHandoutMaster
8990
+ ]
8991
+ );
8846
8992
  const ops = useElementOperations({
8847
8993
  activeSlide,
8848
8994
  activeSlideIndex,
@@ -8850,6 +8996,7 @@ function useEditorOperations(input) {
8850
8996
  selectedElementId,
8851
8997
  editTemplateMode: state.editTemplateMode,
8852
8998
  templateElements: state.templateElements,
8999
+ masterView,
8853
9000
  history,
8854
9001
  setSlides: state.setSlides,
8855
9002
  setTemplateElementsBySlideId: state.setTemplateElementsBySlideId,
@@ -8981,7 +9128,7 @@ function useEditorOperations(input) {
8981
9128
  const { formatPainterActive, setFormatPainterActive, elementLookup } = state;
8982
9129
  react.useEffect(() => {
8983
9130
  if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
8984
- copiedFormatRef.current = chunkY2KIB3QH_js.copyFormatFromElement(selectedElement);
9131
+ copiedFormatRef.current = chunkWVDM36ZM_js.copyFormatFromElement(selectedElement);
8985
9132
  } else if (!formatPainterActive) {
8986
9133
  copiedFormatRef.current = null;
8987
9134
  }
@@ -9007,12 +9154,12 @@ function useEditorOperations(input) {
9007
9154
  e.stopPropagation();
9008
9155
  const element = elementLookup.get(elementId);
9009
9156
  if (element) {
9010
- const updated = chunkY2KIB3QH_js.applyFormatToElement(element, copiedFormatRef.current);
9157
+ const updated = chunkWVDM36ZM_js.applyFormatToElement(element, copiedFormatRef.current);
9011
9158
  const updates = {};
9012
- if (chunkY2KIB3QH_js.hasShapeProperties(updated)) {
9159
+ if (chunkWVDM36ZM_js.hasShapeProperties(updated)) {
9013
9160
  updates.shapeStyle = updated.shapeStyle;
9014
9161
  }
9015
- if (chunkY2KIB3QH_js.hasTextProperties(updated)) {
9162
+ if (chunkWVDM36ZM_js.hasTextProperties(updated)) {
9016
9163
  updates.textStyle = updated.textStyle;
9017
9164
  }
9018
9165
  ops.updateElementById(elementId, updates);
@@ -9060,6 +9207,7 @@ function useIOHandlers(input) {
9060
9207
  zoom,
9061
9208
  handlerRef,
9062
9209
  serializeSlides,
9210
+ serializeForRecovery,
9063
9211
  setContent,
9064
9212
  onContentChange,
9065
9213
  password
@@ -9082,12 +9230,14 @@ function useIOHandlers(input) {
9082
9230
  appProperties: state.appProperties ?? null,
9083
9231
  customProperties: state.customProperties,
9084
9232
  tagCollections: state.tagCollections,
9233
+ slideMasters: state.slideMasters,
9085
9234
  notesMaster: state.notesMaster,
9086
9235
  handoutMaster: state.handoutMaster,
9087
9236
  guides: state.guides,
9088
9237
  activeSlideIndexForGuides: state.activeSlideIndex,
9089
9238
  theme: state.theme,
9090
9239
  canvasSize,
9240
+ slideSizeEmu: state.slideSizeEmu,
9091
9241
  password
9092
9242
  });
9093
9243
  const printHandlers = usePrintHandlers({
@@ -9098,7 +9248,9 @@ function useIOHandlers(input) {
9098
9248
  });
9099
9249
  const themeHandlers = useThemeHandlers({
9100
9250
  handlerRef,
9101
- serializeSlides,
9251
+ // Theme apply re-serialises and re-parses through `setContent`, so these
9252
+ // bytes go back into our own loader: plaintext, never the protected save.
9253
+ serializeSlides: serializeForRecovery,
9102
9254
  setContent,
9103
9255
  onContentChange,
9104
9256
  setTheme: state.setTheme,
@@ -9161,7 +9313,7 @@ function collectReferencedFontFamilies(slides) {
9161
9313
  const families = /* @__PURE__ */ new Set();
9162
9314
  for (const slide of slides) {
9163
9315
  for (const el of slide.elements) {
9164
- if (chunkY2KIB3QH_js.hasTextProperties(el) && el.textSegments) {
9316
+ if (chunkWVDM36ZM_js.hasTextProperties(el) && el.textSegments) {
9165
9317
  for (const seg of el.textSegments) {
9166
9318
  if (seg.style.fontFamily) {
9167
9319
  families.add(seg.style.fontFamily);
@@ -9291,6 +9443,8 @@ function useContentLifecycle(input) {
9291
9443
  content,
9292
9444
  filePath,
9293
9445
  autosaveEnabled = true,
9446
+ autosaveIntervalSeconds,
9447
+ embedFonts = true,
9294
9448
  slides,
9295
9449
  state,
9296
9450
  history,
@@ -9308,6 +9462,7 @@ function useContentLifecycle(input) {
9308
9462
  setTemplateElementsBySlideId: state.setTemplateElementsBySlideId,
9309
9463
  mediaDataUrls: state.mediaDataUrls,
9310
9464
  setCanvasSize: state.setCanvasSize,
9465
+ setSlideSizeEmu: state.setSlideSizeEmu,
9311
9466
  setHeaderFooter: state.setHeaderFooter,
9312
9467
  setLayoutOptions: state.setLayoutOptions,
9313
9468
  setSlideMasters: state.setSlideMasters,
@@ -9315,6 +9470,7 @@ function useContentLifecycle(input) {
9315
9470
  setTableStyleMap: state.setTableStyleMap,
9316
9471
  setThemeOptions: state.setThemeOptions,
9317
9472
  setCustomShows: state.setCustomShows,
9473
+ setActiveCustomShowId: state.setActiveCustomShowId,
9318
9474
  setSections: state.setSections,
9319
9475
  setPresentationProperties: state.setPresentationProperties,
9320
9476
  setNotesMaster: state.setNotesMaster,
@@ -9340,10 +9496,12 @@ function useContentLifecycle(input) {
9340
9496
  actionSoundHandlerRef.current = handlerRef.current;
9341
9497
  }, [handlerRef, actionSoundHandlerRef, state.loading]);
9342
9498
  useFontInjection({ embeddedFonts: state.embeddedFonts, slides });
9343
- const serializeSlides = useSerialize({
9499
+ const serializeInput = {
9344
9500
  slides,
9345
9501
  templateElementsBySlideId: state.templateElementsBySlideId,
9346
9502
  activeSlideIndex: state.activeSlideIndex,
9503
+ canvasSize: state.canvasSize,
9504
+ slideSizeEmu: state.slideSizeEmu,
9347
9505
  guides: state.guides,
9348
9506
  headerFooter: state.headerFooter,
9349
9507
  presentationProperties: state.presentationProperties,
@@ -9353,33 +9511,69 @@ function useContentLifecycle(input) {
9353
9511
  appProperties: state.appProperties,
9354
9512
  customProperties: state.customProperties,
9355
9513
  tagCollections: state.tagCollections,
9514
+ slideMasters: state.slideMasters,
9356
9515
  notesMaster: state.notesMaster,
9357
9516
  handoutMaster: state.handoutMaster,
9358
9517
  handlerRef,
9359
9518
  inlineEditingElementIdRef: state.inlineEditingElementIdRef,
9360
9519
  inlineEditingTextRef: state.inlineEditingTextRef,
9361
- password
9362
- });
9520
+ password,
9521
+ embedFonts
9522
+ };
9523
+ const serializeSlides = useSerialize(serializeInput);
9524
+ const serializeForRecovery = useSerialize({ ...serializeInput, purpose: "recovery-snapshot" });
9363
9525
  const { autosaveStatus } = useAutosave({
9364
9526
  isDirty: state.isDirty,
9365
9527
  filePath,
9366
- serializeSlides,
9367
- enabled: autosaveEnabled
9528
+ serializeSlides: serializeForRecovery,
9529
+ enabled: autosaveEnabled,
9530
+ ...autosaveIntervalSeconds === void 0 ? {} : { intervalSeconds: autosaveIntervalSeconds },
9531
+ // Everything `serializeForRecovery` reads that changes by REASSIGNMENT,
9532
+ // so a poll that finds all of them unchanged can skip re-serializing a
9533
+ // deck it has already snapshotted. The two refs are read by `.current`
9534
+ // because an inline edit in progress lives there and nowhere else yet.
9535
+ getChangeSources: () => [
9536
+ slides,
9537
+ state.templateElementsBySlideId,
9538
+ state.guides,
9539
+ state.headerFooter,
9540
+ state.presentationProperties,
9541
+ state.customShows,
9542
+ state.sections,
9543
+ state.coreProperties,
9544
+ state.appProperties,
9545
+ state.customProperties,
9546
+ state.tagCollections,
9547
+ state.notesMaster,
9548
+ state.handoutMaster,
9549
+ state.embeddedFonts,
9550
+ embedFonts,
9551
+ password,
9552
+ state.inlineEditingElementIdRef.current,
9553
+ state.inlineEditingTextRef.current
9554
+ ]
9368
9555
  });
9369
- return { handlerRef, serializeSlides, autosaveStatus };
9556
+ return { handlerRef, serializeSlides, serializeForRecovery, autosaveStatus };
9370
9557
  }
9371
9558
  function useKeyboardShortcuts(input) {
9372
9559
  const inputRef = react.useRef(input);
9373
9560
  inputRef.current = input;
9374
9561
  const handleKeyDown = react.useCallback((e) => {
9375
9562
  const current = inputRef.current;
9376
- const { action, dx, dy } = chunkY2KIB3QH_js.mapEditorKey(e, {
9563
+ const { action, dx, dy } = chunkWVDM36ZM_js.mapEditorKey(e, {
9377
9564
  canEdit: current.canEdit,
9378
- isPresenting: current.mode !== "edit",
9565
+ // The Slide Master view is an editing surface, not a viewing one.
9566
+ // Gating on `mode !== 'edit'` alone made `mapEditorKey` return
9567
+ // NO_ACTION there, so Delete, the arrow-key nudges and the clipboard
9568
+ // keys were all inert over a master shape even though the write path
9569
+ // behind them routes to the owning part correctly. Svelte and
9570
+ // vanilla, which render the master into their ordinary editable
9571
+ // stage, never had the gap.
9572
+ isPresenting: current.mode !== "edit" && current.mode !== "master",
9379
9573
  hasSelection: current.hasSelection,
9380
9574
  isEditingText: Boolean(current.inlineEditingElementId || current.tableEditorState?.isEditing),
9381
9575
  isDrawing: current.activeTool !== "select",
9382
- isTextInputTarget: chunkY2KIB3QH_js.isEditorTextInputTarget(e.target)
9576
+ isTextInputTarget: chunkWVDM36ZM_js.isEditorTextInputTarget(e.target)
9383
9577
  });
9384
9578
  if (action === null) {
9385
9579
  return;
@@ -9422,6 +9616,9 @@ function useKeyboardShortcuts(input) {
9422
9616
  case "toggleShortcuts":
9423
9617
  current.onToggleShortcuts?.();
9424
9618
  break;
9619
+ case "find":
9620
+ current.onFind?.();
9621
+ break;
9425
9622
  case "nudge":
9426
9623
  current.onNudge(dx ?? 0, dy ?? 0);
9427
9624
  break;
@@ -9530,6 +9727,7 @@ function useViewerIntegration(input) {
9530
9727
  content,
9531
9728
  filePath,
9532
9729
  autosaveEnabled,
9730
+ autosaveIntervalSeconds,
9533
9731
  canEdit,
9534
9732
  mode,
9535
9733
  slides,
@@ -9580,19 +9778,24 @@ function useViewerIntegration(input) {
9580
9778
  });
9581
9779
  const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = react.useState(false);
9582
9780
  const [loadVersion, setLoadVersion] = react.useState(0);
9583
- const { handlerRef, serializeSlides, autosaveStatus } = useContentLifecycle({
9584
- content,
9585
- filePath,
9586
- autosaveEnabled,
9587
- slides,
9588
- state,
9589
- history,
9590
- ops: editorOps.ops,
9591
- actionSoundHandlerRef,
9592
- setIsEncryptedDialogOpen,
9593
- password: dialogs.presentationPassword ?? void 0,
9594
- onContentApplied: () => setLoadVersion((v) => v + 1)
9595
- });
9781
+ const { handlerRef, serializeSlides, serializeForRecovery, autosaveStatus } = useContentLifecycle(
9782
+ {
9783
+ content,
9784
+ filePath,
9785
+ autosaveEnabled,
9786
+ autosaveIntervalSeconds,
9787
+ // The File > Fonts toggle, finally reaching a save call.
9788
+ embedFonts: dialogs.embedFontsEnabled,
9789
+ slides,
9790
+ state,
9791
+ history,
9792
+ ops: editorOps.ops,
9793
+ actionSoundHandlerRef,
9794
+ setIsEncryptedDialogOpen,
9795
+ password: dialogs.presentationPassword ?? void 0,
9796
+ onContentApplied: () => setLoadVersion((v) => v + 1)
9797
+ }
9798
+ );
9596
9799
  const { exportHandlers, printHandlers, themeHandlers, propertyHandlers } = useIOHandlers({
9597
9800
  state,
9598
9801
  slides,
@@ -9604,6 +9807,7 @@ function useViewerIntegration(input) {
9604
9807
  zoom,
9605
9808
  handlerRef,
9606
9809
  serializeSlides,
9810
+ serializeForRecovery,
9607
9811
  setContent,
9608
9812
  onContentChange,
9609
9813
  password: dialogs.presentationPassword ?? void 0
@@ -9673,7 +9877,7 @@ function useViewerIntegration(input) {
9673
9877
  return zoom.scale;
9674
9878
  },
9675
9879
  setZoom(level) {
9676
- zoom.setScale(chunkY2KIB3QH_js.clampZoomScale(level));
9880
+ zoom.setScale(chunkWVDM36ZM_js.clampZoomScale(level));
9677
9881
  },
9678
9882
  zoomIn() {
9679
9883
  zoom.handleZoomIn();
@@ -9888,7 +10092,7 @@ function useReducedMotion() {
9888
10092
  }
9889
10093
  function useViewerOptions() {
9890
10094
  const storeRef = react.useRef(null);
9891
- storeRef.current ??= chunkY2KIB3QH_js.createViewerOptionsStore();
10095
+ storeRef.current ??= chunkWVDM36ZM_js.createViewerOptionsStore();
9892
10096
  const store = storeRef.current;
9893
10097
  const options = react.useSyncExternalStore(
9894
10098
  (onStoreChange) => store.subscribe(onStoreChange),
@@ -9897,9 +10101,9 @@ function useViewerOptions() {
9897
10101
  );
9898
10102
  return { optionsStore: store, options };
9899
10103
  }
9900
- var KNOWN_TAB_IDS = new Set(chunkY2KIB3QH_js.TOOLBAR_TABS.map((tab) => tab.id));
10104
+ var KNOWN_TAB_IDS = new Set(chunkWVDM36ZM_js.TOOLBAR_TABS.map((tab) => tab.id));
9901
10105
  function computeToolbarVisibility(hiddenActions) {
9902
- const isHidden = (id) => chunkY2KIB3QH_js.isActionHidden(id, hiddenActions);
10106
+ const isHidden = (id) => chunkWVDM36ZM_js.isActionHidden(id, hiddenActions);
9903
10107
  const isTabVisible = (id) => !KNOWN_TAB_IDS.has(id) || !isHidden(id);
9904
10108
  return { isHidden, isTabVisible };
9905
10109
  }
@@ -9984,12 +10188,12 @@ function useYjsDocumentSync({
9984
10188
  return;
9985
10189
  }
9986
10190
  try {
9987
- const handler = new chunkY2KIB3QH_js.PptxHandler();
10191
+ const handler = new chunkWVDM36ZM_js.PptxHandler();
9988
10192
  await handler.load(sourceBytes.buffer);
9989
- const currentSlides = chunkY2KIB3QH_js.readSlidesFromYDoc(
10193
+ const currentSlides = chunkWVDM36ZM_js.readSlidesFromYDoc(
9990
10194
  doc
9991
10195
  );
9992
- const slidesToSave = chunkY2KIB3QH_js.buildSaveSlides(currentSlides, templateElementsBySlideId);
10196
+ const slidesToSave = chunkWVDM36ZM_js.buildSaveSlides(currentSlides, templateElementsBySlideId);
9993
10197
  const bytes = await handler.save(slidesToSave);
9994
10198
  config.onWriteBack(bytes);
9995
10199
  } catch {
@@ -10004,7 +10208,7 @@ function useYjsDocumentSync({
10004
10208
  if (!doc || !isConnected) {
10005
10209
  return;
10006
10210
  }
10007
- const docSlides = chunkY2KIB3QH_js.readSlidesFromYDoc(
10211
+ const docSlides = chunkWVDM36ZM_js.readSlidesFromYDoc(
10008
10212
  doc
10009
10213
  );
10010
10214
  if (docSlides.length === 0) {
@@ -10026,11 +10230,11 @@ function useYjsDocumentSync({
10026
10230
  lastSyncedRef.current = serialized;
10027
10231
  void (async () => {
10028
10232
  const factories = await getFactories();
10029
- chunkY2KIB3QH_js.reconcileSlidesInYDoc(
10233
+ chunkWVDM36ZM_js.reconcileSlidesInYDoc(
10030
10234
  slides,
10031
10235
  doc,
10032
10236
  factories,
10033
- chunkY2KIB3QH_js.LOCAL_SYNC_ORIGIN
10237
+ chunkWVDM36ZM_js.LOCAL_SYNC_ORIGIN
10034
10238
  );
10035
10239
  scheduleWriteBack();
10036
10240
  })();
@@ -10044,10 +10248,10 @@ function useYjsDocumentSync({
10044
10248
  return;
10045
10249
  }
10046
10250
  const handleChange = (_events, transaction) => {
10047
- if (transaction?.origin === chunkY2KIB3QH_js.LOCAL_SYNC_ORIGIN) {
10251
+ if (transaction?.origin === chunkWVDM36ZM_js.LOCAL_SYNC_ORIGIN) {
10048
10252
  return;
10049
10253
  }
10050
- const remoteSlides = chunkY2KIB3QH_js.readSlidesFromYDoc(
10254
+ const remoteSlides = chunkWVDM36ZM_js.readSlidesFromYDoc(
10051
10255
  doc
10052
10256
  );
10053
10257
  if (remoteSlides.length === 0) {
@@ -10063,7 +10267,7 @@ function useYjsDocumentSync({
10063
10267
  isApplyingRemoteRef.current = false;
10064
10268
  scheduleWriteBack();
10065
10269
  };
10066
- const unobserve = chunkY2KIB3QH_js.observeYDocSlides(
10270
+ const unobserve = chunkWVDM36ZM_js.observeYDocSlides(
10067
10271
  doc,
10068
10272
  handleChange
10069
10273
  );
@@ -10101,7 +10305,7 @@ function useBroadcastFollower({
10101
10305
  if (!broadcaster) {
10102
10306
  return;
10103
10307
  }
10104
- if (!chunkY2KIB3QH_js.shouldAutoFollowBroadcaster({
10308
+ if (!chunkWVDM36ZM_js.shouldAutoFollowBroadcaster({
10105
10309
  localRole: collab.config.role,
10106
10310
  broadcasterRole: broadcaster.role
10107
10311
  })) {
@@ -10242,11 +10446,16 @@ function useLayoutSwitching(input) {
10242
10446
  },
10243
10447
  [handler, activeSlideIndex, ops, history, onTemplateElementsChanged]
10244
10448
  );
10449
+ const loadLayoutPreviews = react.useCallback(
10450
+ async () => handler ? handler.getLayoutPreviews() : [],
10451
+ [handler]
10452
+ );
10245
10453
  return {
10246
10454
  availableLayouts,
10247
10455
  isLoading,
10248
10456
  loadAvailableLayouts,
10249
10457
  applyLayout,
10458
+ loadLayoutPreviews,
10250
10459
  currentLayoutPath
10251
10460
  };
10252
10461
  }
@@ -10267,10 +10476,10 @@ function useTouchGestures(input) {
10267
10476
  if (!el || !enabled) {
10268
10477
  return;
10269
10478
  }
10270
- const recognizer = chunkY2KIB3QH_js.createTouchGestureRecognizer({
10479
+ const recognizer = chunkWVDM36ZM_js.createTouchGestureRecognizer({
10271
10480
  getScale: () => scaleRef.current,
10272
- minScale: chunkY2KIB3QH_js.MIN_ZOOM_SCALE,
10273
- maxScale: chunkY2KIB3QH_js.MAX_ZOOM_SCALE,
10481
+ minScale: chunkWVDM36ZM_js.MIN_ZOOM_SCALE,
10482
+ maxScale: chunkWVDM36ZM_js.MAX_ZOOM_SCALE,
10274
10483
  callbacks: {
10275
10484
  onPinchZoom: (newScale) => callbacksRef.current.onPinchZoom?.(newScale),
10276
10485
  onSwipe: (direction) => callbacksRef.current.onSwipe?.(direction),
@@ -10310,7 +10519,7 @@ function scrollFocusedIntoView(keyboardInset) {
10310
10519
  return;
10311
10520
  }
10312
10521
  const rect = active.getBoundingClientRect();
10313
- const delta = chunkY2KIB3QH_js.computeScrollDelta(
10522
+ const delta = chunkWVDM36ZM_js.computeScrollDelta(
10314
10523
  { top: rect.top, bottom: rect.bottom },
10315
10524
  window.innerHeight,
10316
10525
  keyboardInset
@@ -10330,8 +10539,8 @@ function useKeyboardInsets(enabled = true) {
10330
10539
  return;
10331
10540
  }
10332
10541
  const update = () => {
10333
- const metrics = chunkY2KIB3QH_js.readViewportMetrics(window);
10334
- const inset = metrics ? chunkY2KIB3QH_js.computeKeyboardInset(metrics) : 0;
10542
+ const metrics = chunkWVDM36ZM_js.readViewportMetrics(window);
10543
+ const inset = metrics ? chunkWVDM36ZM_js.computeKeyboardInset(metrics) : 0;
10335
10544
  setKeyboardInset(inset);
10336
10545
  if (inset > 0) {
10337
10546
  window.requestAnimationFrame(() => scrollFocusedIntoView(inset));
@@ -10342,8 +10551,8 @@ function useKeyboardInsets(enabled = true) {
10342
10551
  vv.addEventListener("scroll", update);
10343
10552
  const onFocusIn = () => {
10344
10553
  window.requestAnimationFrame(() => {
10345
- const metrics = chunkY2KIB3QH_js.readViewportMetrics(window);
10346
- const inset = metrics ? chunkY2KIB3QH_js.computeKeyboardInset(metrics) : 0;
10554
+ const metrics = chunkWVDM36ZM_js.readViewportMetrics(window);
10555
+ const inset = metrics ? chunkWVDM36ZM_js.computeKeyboardInset(metrics) : 0;
10347
10556
  if (inset > 0) {
10348
10557
  scrollFocusedIntoView(inset);
10349
10558
  }
@@ -10356,7 +10565,7 @@ function useKeyboardInsets(enabled = true) {
10356
10565
  document.removeEventListener("focusin", onFocusIn);
10357
10566
  };
10358
10567
  }, [enabled]);
10359
- return { keyboardInset, isKeyboardOpen: chunkY2KIB3QH_js.isKeyboardOpen(keyboardInset) };
10568
+ return { keyboardInset, isKeyboardOpen: chunkWVDM36ZM_js.isKeyboardOpen(keyboardInset) };
10360
10569
  }
10361
10570
 
10362
10571
  // src/viewer/hooks/useViewerBuildingBlocks-canvas-props.ts
@@ -10383,7 +10592,7 @@ function buildCanvasProps(input) {
10383
10592
  } = input;
10384
10593
  const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
10385
10594
  const effectiveTemplateElements = mode === "master" ? s.activeLayout ? s.activeMaster?.elements ?? [] : [] : templateElements;
10386
- const fieldContext = chunkY2KIB3QH_js.buildFieldSubstitutionContext({
10595
+ const fieldContext = chunkWVDM36ZM_js.buildFieldSubstitutionContext({
10387
10596
  headerFooter: s.headerFooter,
10388
10597
  customProperties: s.customProperties,
10389
10598
  slide: activeSlide
@@ -10393,13 +10602,13 @@ function buildCanvasProps(input) {
10393
10602
  if (mode === "present") {
10394
10603
  presentation.handlePresentationAction(action);
10395
10604
  } else if (action.url) {
10396
- chunkY2KIB3QH_js.safeOpenUrl(action.url);
10605
+ chunkWVDM36ZM_js.safeOpenUrl(action.url);
10397
10606
  }
10398
10607
  };
10399
10608
  const handleHyperlinkClick = (url) => {
10400
- if (chunkY2KIB3QH_js.isPpactionUrl(url)) {
10609
+ if (chunkWVDM36ZM_js.isPpactionUrl(url)) {
10401
10610
  if (mode === "present") {
10402
- const parsed = chunkY2KIB3QH_js.parsePpactionUrl(url);
10611
+ const parsed = chunkWVDM36ZM_js.parsePpactionUrl(url);
10403
10612
  if (parsed) {
10404
10613
  presentation.handlePresentationAction({
10405
10614
  action: parsed.action,
@@ -10409,7 +10618,7 @@ function buildCanvasProps(input) {
10409
10618
  }
10410
10619
  return;
10411
10620
  }
10412
- chunkY2KIB3QH_js.safeOpenUrl(url);
10621
+ chunkWVDM36ZM_js.safeOpenUrl(url);
10413
10622
  };
10414
10623
  return {
10415
10624
  activeSlide: effectiveSlide,
@@ -10505,41 +10714,7 @@ function buildCanvasProps(input) {
10505
10714
 
10506
10715
  // src/viewer/hooks/useScopedLayoutOptions.ts
10507
10716
  function scopeLayoutOptionsToActiveSlide(options, activeSlide) {
10508
- if (!activeSlide?.layoutPath) {
10509
- return options;
10510
- }
10511
- const hasAnyMasterInfo = options.some((o) => o.masterPath);
10512
- if (!hasAnyMasterInfo) {
10513
- return options;
10514
- }
10515
- const activeOption = options.find((o) => o.path === activeSlide.layoutPath);
10516
- const activeMaster = activeOption?.masterPath;
10517
- if (!activeMaster) {
10518
- return options;
10519
- }
10520
- const scoped = options.filter((o) => o.masterPath === activeMaster);
10521
- const seen = /* @__PURE__ */ new Map();
10522
- for (const opt of scoped) {
10523
- const isActive = opt.path === activeSlide.layoutPath;
10524
- const existing = seen.get(opt.name);
10525
- if (!existing || isActive) {
10526
- seen.set(opt.name, opt);
10527
- }
10528
- }
10529
- const chosen = new Set(Array.from(seen.values()).map((o) => o.path));
10530
- const result = [];
10531
- const usedNames = /* @__PURE__ */ new Set();
10532
- for (const opt of scoped) {
10533
- if (!chosen.has(opt.path)) {
10534
- continue;
10535
- }
10536
- if (usedNames.has(opt.name)) {
10537
- continue;
10538
- }
10539
- usedNames.add(opt.name);
10540
- result.push(opt);
10541
- }
10542
- return result;
10717
+ return chunkWVDM36ZM_js.scopeLayoutOptionsToSlide(options, activeSlide?.layoutPath);
10543
10718
  }
10544
10719
 
10545
10720
  // src/viewer/hooks/useViewerBuildingBlocks-toolbar-handlers.ts
@@ -10552,7 +10727,7 @@ function buildToolbarAnimationHandlers(input) {
10552
10727
  const current = activeSlide.animations ?? [];
10553
10728
  if (group === "motionPath") {
10554
10729
  propertyHandlers.handleUpdateSlide({
10555
- animations: chunkY2KIB3QH_js.applyMotionPathPreset(current, selectedElement.id, preset)
10730
+ animations: chunkWVDM36ZM_js.applyMotionPathPreset(current, selectedElement.id, preset)
10556
10731
  });
10557
10732
  return;
10558
10733
  }
@@ -10747,7 +10922,7 @@ function buildToolbarProps(input) {
10747
10922
  onOpenFile,
10748
10923
  onOpenRecentFile,
10749
10924
  onCreatePresentation: (templateId) => {
10750
- s.setSlides(chunkY2KIB3QH_js.createBackstagePresentation(templateId));
10925
+ s.setSlides(chunkWVDM36ZM_js.createBackstagePresentation(templateId));
10751
10926
  s.setActiveSlideIndex(0);
10752
10927
  s.setSelectedElementId(null);
10753
10928
  s.setSelectedElementIds([]);
@@ -10772,9 +10947,11 @@ function buildToolbarProps(input) {
10772
10947
  isOverflowMenuOpen: s.isOverflowMenuOpen,
10773
10948
  onSetOverflowMenuOpen: s.setIsOverflowMenuOpen,
10774
10949
  layoutOptions: scopedLayoutOptions,
10950
+ currentLayoutPath: activeSlide?.layoutPath,
10951
+ loadLayoutPreviews: input.loadLayoutPreviews,
10775
10952
  onInsertSlideFromLayout: slideOps.handleInsertSlideFromLayout,
10776
10953
  onInsertSlideFromTemplate: slideOps.handleInsertSlideFromTemplate,
10777
- templateScheme: chunkY2KIB3QH_js.templateSchemeFromTheme(s.theme?.colorScheme),
10954
+ templateScheme: chunkWVDM36ZM_js.templateSchemeFromTheme(s.theme?.colorScheme),
10778
10955
  customShows: s.customShows,
10779
10956
  activeCustomShowId: s.activeCustomShowId,
10780
10957
  onSetActiveCustomShowId: s.setActiveCustomShowId,
@@ -10788,6 +10965,15 @@ function buildToolbarProps(input) {
10788
10965
  onToggleVersionHistory: () => propertyHandlers.setIsVersionHistoryOpen((p) => !p),
10789
10966
  onOpenPasswordProtection: () => dialogs.setIsPasswordDialogOpen(true),
10790
10967
  onOpenDocumentProperties: () => dialogs.setIsDocPropsDialogOpen(true),
10968
+ // Design > Slide Size: the size control is the inspector's SLIDE SIZE
10969
+ // card, which the deck (no-selection) panel renders. Drop the selection so
10970
+ // that panel is what the pane shows, then open it.
10971
+ onOpenSlideSize: () => {
10972
+ s.setSelectedElementId(null);
10973
+ s.setSelectedElementIds([]);
10974
+ s.setSidebarPanelMode("properties");
10975
+ s.setIsInspectorPaneOpen(true);
10976
+ },
10791
10977
  onOpenFontEmbedding: () => dialogs.setIsFontEmbeddingOpen(true),
10792
10978
  onOpenDigitalSignatures: () => dialogs.setIsDigitalSigDialogOpen(true),
10793
10979
  onEnterPresenterView,
@@ -10806,7 +10992,7 @@ function buildToolbarProps(input) {
10806
10992
  isCommentsPanelOpen: s.isInspectorPaneOpen,
10807
10993
  slideCommentCount: activeSlide?.comments?.length ?? 0,
10808
10994
  formatPainterActive: s.formatPainterActive,
10809
- canActivateFormatPainter: chunkY2KIB3QH_js.hasCopyableFormat(selectedElement),
10995
+ canActivateFormatPainter: chunkWVDM36ZM_js.hasCopyableFormat(selectedElement),
10810
10996
  onToggleFormatPainter: () => s.setFormatPainterActive((p) => !p),
10811
10997
  isSelectionPaneOpen: s.isSelectionPaneOpen,
10812
10998
  onToggleSelectionPane: () => s.setIsSelectionPaneOpen((p) => !p),
@@ -10823,6 +11009,20 @@ function buildToolbarProps(input) {
10823
11009
  activeSlide,
10824
11010
  onTransitionChange: handleTransitionChange,
10825
11011
  onApplyTransitionToAll: handleApplyTransitionToAll,
11012
+ // No `onResetSlide` here: this building-blocks surface supplies no
11013
+ // `onApplyLayout` either, so there is no layout to reset to. The mounted
11014
+ // viewer (`ViewerToolbarSection`) wires both.
11015
+ onSelectAll: () => {
11016
+ const allIds = activeSlide?.elements.map((element) => element.id) ?? [];
11017
+ if (allIds.length > 0) {
11018
+ ops.applySelection(allIds[0], allIds);
11019
+ }
11020
+ },
11021
+ presentationProperties: s.presentationProperties,
11022
+ onPresentationPropertiesChange: (updates) => {
11023
+ s.setPresentationProperties((prev) => ({ ...prev, ...updates }));
11024
+ history.markDirty();
11025
+ },
10826
11026
  hiddenActions
10827
11027
  };
10828
11028
  }
@@ -10900,7 +11100,12 @@ function useViewerBuildingBlocksCore(input) {
10900
11100
  setMode: state.setMode,
10901
11101
  setActiveSlideIndex: state.setActiveSlideIndex,
10902
11102
  setSlides: state.setSlides,
10903
- history
11103
+ history,
11104
+ // PowerPoint's bare `J` during a show toggles live captions.
11105
+ onToggleSubtitles: () => state.setPresentationProperties((prev) => ({
11106
+ ...prev,
11107
+ showSubtitles: !prev.showSubtitles
11108
+ }))
10904
11109
  });
10905
11110
  return {
10906
11111
  state,
@@ -11075,7 +11280,7 @@ function useViewerBuildingBlocks(input) {
11075
11280
  }, [incomingContent]);
11076
11281
  const onOpenFile = react.useCallback(() => {
11077
11282
  void (async () => {
11078
- const picked = await chunkY2KIB3QH_js.openPptxFile();
11283
+ const picked = await chunkWVDM36ZM_js.openPptxFile();
11079
11284
  if (picked) {
11080
11285
  setContent(picked.buffer);
11081
11286
  }
@@ -11083,7 +11288,7 @@ function useViewerBuildingBlocks(input) {
11083
11288
  }, []);
11084
11289
  const onOpenRecentFile = react.useCallback((key) => {
11085
11290
  void (async () => {
11086
- const bytes = await chunkY2KIB3QH_js.readBackstageRecentFile(key);
11291
+ const bytes = await chunkWVDM36ZM_js.readBackstageRecentFile(key);
11087
11292
  if (bytes) {
11088
11293
  setContent(bytes);
11089
11294
  }