pptx-react-viewer 4.49.0 → 4.50.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 (123) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/dist/{AiChatPanel-NKTBHT5B.mjs → AiChatPanel-VJV5OEG2.mjs} +1 -1
  3. package/dist/AiChatPanel-VJV5OEG2.mjs.br +0 -0
  4. package/dist/AiChatPanel-VJV5OEG2.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-S4WNQCY4.js → AiChatPanel-WYAL24DX.js} +9 -9
  6. package/dist/AiChatPanel-WYAL24DX.js.br +0 -0
  7. package/dist/AiChatPanel-WYAL24DX.js.gz +0 -0
  8. package/dist/{chunk-2ZXXHNNR.js → chunk-4OF7X5EE.js} +1669 -3046
  9. package/dist/chunk-4OF7X5EE.js.br +0 -0
  10. package/dist/chunk-4OF7X5EE.js.gz +0 -0
  11. package/dist/{chunk-YKLL2Z33.mjs → chunk-5JJQLK7N.mjs} +452 -1829
  12. package/dist/chunk-5JJQLK7N.mjs.br +0 -0
  13. package/dist/chunk-5JJQLK7N.mjs.gz +0 -0
  14. package/dist/{chunk-PFV626ED.mjs → chunk-77IXTLKU.mjs} +3 -4
  15. package/dist/chunk-77IXTLKU.mjs.br +0 -0
  16. package/dist/chunk-77IXTLKU.mjs.gz +0 -0
  17. package/dist/{chunk-ME5QRTVS.js → chunk-D5NXYXPP.js} +740 -1188
  18. package/dist/chunk-D5NXYXPP.js.br +0 -0
  19. package/dist/chunk-D5NXYXPP.js.gz +0 -0
  20. package/dist/chunk-DDJ634MV.js.br +0 -0
  21. package/dist/chunk-DDJ634MV.js.gz +0 -0
  22. package/dist/{chunk-JAI42EXQ.js → chunk-JWNBTFZZ.js} +0 -6
  23. package/dist/chunk-JWNBTFZZ.js.br +0 -0
  24. package/dist/chunk-JWNBTFZZ.js.gz +0 -0
  25. package/dist/{chunk-Z62JFXMZ.mjs → chunk-QHGEPW5G.mjs} +563 -1011
  26. package/dist/chunk-QHGEPW5G.mjs.br +0 -0
  27. package/dist/chunk-QHGEPW5G.mjs.gz +0 -0
  28. package/dist/chunk-QIUK53JR.mjs.br +0 -0
  29. package/dist/chunk-QIUK53JR.mjs.gz +0 -0
  30. package/dist/i18n/de.cjs +1138 -221
  31. package/dist/i18n/de.cjs.br +0 -0
  32. package/dist/i18n/de.cjs.gz +0 -0
  33. package/dist/i18n/de.mjs +1138 -221
  34. package/dist/i18n/de.mjs.br +0 -0
  35. package/dist/i18n/de.mjs.gz +0 -0
  36. package/dist/i18n/es.cjs +1138 -221
  37. package/dist/i18n/es.cjs.br +0 -0
  38. package/dist/i18n/es.cjs.gz +0 -0
  39. package/dist/i18n/es.mjs +1138 -221
  40. package/dist/i18n/es.mjs.br +0 -0
  41. package/dist/i18n/es.mjs.gz +0 -0
  42. package/dist/i18n/fr.cjs +1138 -221
  43. package/dist/i18n/fr.cjs.br +0 -0
  44. package/dist/i18n/fr.cjs.gz +0 -0
  45. package/dist/i18n/fr.mjs +1138 -221
  46. package/dist/i18n/fr.mjs.br +0 -0
  47. package/dist/i18n/fr.mjs.gz +0 -0
  48. package/dist/i18n/zh-CN.cjs +1138 -221
  49. package/dist/i18n/zh-CN.cjs.br +0 -0
  50. package/dist/i18n/zh-CN.cjs.gz +0 -0
  51. package/dist/i18n/zh-CN.mjs +1138 -221
  52. package/dist/i18n/zh-CN.mjs.br +0 -0
  53. package/dist/i18n/zh-CN.mjs.gz +0 -0
  54. package/dist/index.d.ts +5 -15
  55. package/dist/index.js +24 -24
  56. package/dist/index.js.br +0 -0
  57. package/dist/index.js.gz +0 -0
  58. package/dist/index.mjs +3 -3
  59. package/dist/index.mjs.br +0 -0
  60. package/dist/index.mjs.gz +0 -0
  61. package/dist/internals.d.ts +105 -94
  62. package/dist/internals.js +81 -81
  63. package/dist/internals.js.br +0 -0
  64. package/dist/internals.js.gz +0 -0
  65. package/dist/internals.mjs +2 -2
  66. package/dist/internals.mjs.br +0 -0
  67. package/dist/internals.mjs.gz +0 -0
  68. package/dist/pptx-viewer-canvas.css +1 -1
  69. package/dist/pptx-viewer-canvas.css.br +0 -0
  70. package/dist/pptx-viewer-canvas.css.gz +0 -0
  71. package/dist/pptx-viewer.css +1 -1
  72. package/dist/pptx-viewer.css.br +0 -0
  73. package/dist/pptx-viewer.css.gz +0 -0
  74. package/dist/viewer/index.d.ts +7 -12
  75. package/dist/viewer/index.js +19 -19
  76. package/dist/viewer/index.js.br +0 -0
  77. package/dist/viewer/index.js.gz +0 -0
  78. package/dist/viewer/index.mjs +3 -3
  79. package/dist/viewer/index.mjs.br +0 -0
  80. package/dist/viewer/index.mjs.gz +0 -0
  81. package/dist/{y-webrtc-2H7UYAQD.mjs → y-webrtc-HRGGVQZH.mjs} +1 -1
  82. package/dist/y-webrtc-HRGGVQZH.mjs.br +0 -0
  83. package/dist/y-webrtc-HRGGVQZH.mjs.gz +0 -0
  84. package/dist/{y-webrtc-DVPQNFLL.js → y-webrtc-QVVT5PCK.js} +124 -124
  85. package/dist/y-webrtc-QVVT5PCK.js.br +0 -0
  86. package/dist/y-webrtc-QVVT5PCK.js.gz +0 -0
  87. package/dist/{y-websocket-WORVRRQS.mjs → y-websocket-46M6UFI7.mjs} +1 -1
  88. package/dist/y-websocket-46M6UFI7.mjs.br +0 -0
  89. package/dist/y-websocket-46M6UFI7.mjs.gz +0 -0
  90. package/dist/{y-websocket-TN4OKPXQ.js → y-websocket-EDOMWMAD.js} +78 -78
  91. package/dist/y-websocket-EDOMWMAD.js.br +0 -0
  92. package/dist/y-websocket-EDOMWMAD.js.gz +0 -0
  93. package/package.json +3 -3
  94. package/dist/AiChatPanel-NKTBHT5B.mjs.br +0 -0
  95. package/dist/AiChatPanel-NKTBHT5B.mjs.gz +0 -0
  96. package/dist/AiChatPanel-S4WNQCY4.js.br +0 -0
  97. package/dist/AiChatPanel-S4WNQCY4.js.gz +0 -0
  98. package/dist/chunk-2ZXXHNNR.js.br +0 -0
  99. package/dist/chunk-2ZXXHNNR.js.gz +0 -0
  100. package/dist/chunk-3VVZGHHY.mjs.br +0 -0
  101. package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
  102. package/dist/chunk-JAI42EXQ.js.br +0 -0
  103. package/dist/chunk-JAI42EXQ.js.gz +0 -0
  104. package/dist/chunk-ME5QRTVS.js.br +0 -0
  105. package/dist/chunk-ME5QRTVS.js.gz +0 -0
  106. package/dist/chunk-NUNDT6EL.js.br +0 -0
  107. package/dist/chunk-NUNDT6EL.js.gz +0 -0
  108. package/dist/chunk-PFV626ED.mjs.br +0 -0
  109. package/dist/chunk-PFV626ED.mjs.gz +0 -0
  110. package/dist/chunk-YKLL2Z33.mjs.br +0 -0
  111. package/dist/chunk-YKLL2Z33.mjs.gz +0 -0
  112. package/dist/chunk-Z62JFXMZ.mjs.br +0 -0
  113. package/dist/chunk-Z62JFXMZ.mjs.gz +0 -0
  114. package/dist/y-webrtc-2H7UYAQD.mjs.br +0 -0
  115. package/dist/y-webrtc-2H7UYAQD.mjs.gz +0 -0
  116. package/dist/y-webrtc-DVPQNFLL.js.br +0 -0
  117. package/dist/y-webrtc-DVPQNFLL.js.gz +0 -0
  118. package/dist/y-websocket-TN4OKPXQ.js.br +0 -0
  119. package/dist/y-websocket-TN4OKPXQ.js.gz +0 -0
  120. package/dist/y-websocket-WORVRRQS.mjs.br +0 -0
  121. package/dist/y-websocket-WORVRRQS.mjs.gz +0 -0
  122. package/dist/{chunk-NUNDT6EL.js → chunk-DDJ634MV.js} +436 -436
  123. package/dist/{chunk-3VVZGHHY.mjs → chunk-QIUK53JR.mjs} +436 -436
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkJAI42EXQ_js = require('./chunk-JAI42EXQ.js');
3
+ var chunkJWNBTFZZ_js = require('./chunk-JWNBTFZZ.js');
4
4
  var pptx = require('ooxml-ui/pptx');
5
5
  var React17 = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -80,240 +80,59 @@ function useVirtualizedSlides({
80
80
  scrollToIndex
81
81
  };
82
82
  }
83
+ function useController(controller) {
84
+ return React17.useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
85
+ }
86
+
87
+ // src/viewer/hooks/collaboration/collaboration-modules.ts
88
+ var collabModules = {
89
+ loadYjs: () => import('yjs'),
90
+ loadWebsocket: () => import('./y-websocket-EDOMWMAD.js'),
91
+ loadWebrtc: () => import('./y-webrtc-QVVT5PCK.js')
92
+ };
93
+
94
+ // src/viewer/hooks/collaboration/useYjsProvider.ts
83
95
  function useYjsProvider({ config: inputConfig }) {
84
96
  const config = inputConfig?.externalSession ? void 0 : inputConfig;
85
- const [status, setStatus] = React17.useState("disconnected");
86
- const [awareness, setAwareness] = React17.useState(null);
87
- const [doc, setDoc] = React17.useState(null);
88
- const [clientId, setClientId] = React17.useState(null);
89
- const [synced, setSynced] = React17.useState(false);
90
- const cleanupRef = React17.useRef(null);
91
- const generationRef = React17.useRef(0);
92
- const timeoutRef = React17.useRef(null);
93
- const departureRef = React17.useRef(null);
94
- const gateRef = React17.useRef(null);
95
- if (!gateRef.current) {
96
- gateRef.current = pptx.createSyncGate(() => setSynced(true));
97
- }
98
- const teardown = React17.useCallback(() => {
99
- generationRef.current += 1;
100
- if (timeoutRef.current) {
101
- clearTimeout(timeoutRef.current);
102
- timeoutRef.current = null;
103
- }
104
- gateRef.current?.reset();
105
- setSynced(false);
106
- cleanupRef.current?.();
107
- cleanupRef.current = null;
108
- }, []);
109
- const announceDeparture = React17.useCallback(() => {
110
- departureRef.current?.announce();
111
- departureRef.current?.dispose();
112
- departureRef.current = null;
113
- }, []);
114
- const buildCleanup = React17.useCallback(
115
- (provider, yDoc) => () => {
116
- announceDeparture();
117
- pptx.clearLocalAwareness(provider.awareness);
118
- provider.destroy();
119
- yDoc.destroy();
120
- setDoc(null);
121
- setAwareness(null);
122
- setClientId(null);
123
- setStatus("disconnected");
124
- },
125
- [announceDeparture]
97
+ const [controller] = React17.useState(
98
+ () => pptx.createCollaborationSessionController({ modules: collabModules, registerTeardown: false })
126
99
  );
127
- const initWebrtc = React17.useCallback(async () => {
128
- const generation = generationRef.current;
129
- if (!config) {
130
- return;
131
- }
132
- setStatus("connecting");
133
- try {
134
- const [Y, { WebrtcProvider }] = await Promise.all([import('yjs'), import('./y-webrtc-DVPQNFLL.js')]);
135
- if (generation !== generationRef.current) {
136
- return;
137
- }
138
- const yDoc = new Y.Doc();
139
- const opts = {};
140
- if (config.signaling && config.signaling.length > 0) {
141
- opts.signaling = config.signaling;
142
- }
143
- if (config.authToken) {
144
- opts.password = config.authToken;
145
- }
146
- const roomId = pptx.validateRoomId(config.roomId);
147
- const provider = new WebrtcProvider(roomId, yDoc, opts);
148
- departureRef.current = pptx.createDepartureChannel(roomId, provider.awareness);
149
- setDoc(yDoc);
150
- setAwareness(provider.awareness);
151
- setClientId(provider.awareness.clientID);
152
- setStatus("connected");
153
- const handleSynced = (event) => {
154
- if (event?.synced !== false) {
155
- gateRef.current?.open();
156
- }
157
- };
158
- provider.on("synced", handleSynced);
159
- gateRef.current?.arm();
160
- const handleStatus = (event) => {
161
- if (event.connected === false) {
162
- setStatus("disconnected");
163
- gateRef.current?.reset();
164
- setSynced(false);
165
- gateRef.current?.arm();
166
- } else if (event.connected) {
167
- setStatus("connected");
168
- }
169
- };
170
- provider.on("status", handleStatus);
171
- const baseCleanup = buildCleanup(provider, yDoc);
172
- cleanupRef.current = () => {
173
- provider.off("synced", handleSynced);
174
- provider.off("status", handleStatus);
175
- baseCleanup();
176
- };
177
- } catch (err) {
178
- if (generation !== generationRef.current) {
179
- return;
180
- }
181
- console.warn(
182
- "[pptx-viewer] WebRTC collaboration packages not available:",
183
- err instanceof Error ? err.message : err
184
- );
185
- setStatus("error");
186
- }
187
- }, [config?.roomId, config?.authToken, config?.signaling, buildCleanup]);
188
- const init = React17.useCallback(async () => {
189
- teardown();
190
- const generation = generationRef.current;
100
+ const state = useController(controller);
101
+ const signalingKey = config?.signaling?.join("\n");
102
+ React17.useEffect(() => {
191
103
  if (!config) {
104
+ controller.stop();
192
105
  return;
193
106
  }
194
- const roomId = pptx.validateRoomId(config.roomId);
195
- const transport = config.transport ?? pptx.resolveTransportForServerUrl(config.serverUrl);
196
- if (transport === "webrtc") {
197
- await initWebrtc();
198
- return;
199
- }
200
- if (pptx.isMixedContentBlocked(config.serverUrl)) {
201
- console.warn(
202
- `[pptx-viewer] Refusing to connect: insecure ws:// server "${config.serverUrl}" is blocked from a secure (https) page. Use a wss:// URL.`
203
- );
204
- setStatus("error");
205
- return;
206
- }
207
- setStatus("connecting");
208
- try {
209
- const [Y, { WebsocketProvider }] = await Promise.all([import('yjs'), import('./y-websocket-TN4OKPXQ.js')]);
210
- if (generation !== generationRef.current) {
211
- return;
212
- }
213
- const yDoc = new Y.Doc();
214
- const provider = new WebsocketProvider(config.serverUrl, roomId, yDoc, {
215
- params: config.authToken ? { token: config.authToken } : void 0
216
- });
217
- departureRef.current = pptx.createDepartureChannel(roomId, provider.awareness);
218
- let connected = false;
219
- const handleStatus = (event) => {
220
- if (event.status === "connected") {
221
- connected = true;
222
- if (timeoutRef.current) {
223
- clearTimeout(timeoutRef.current);
224
- timeoutRef.current = null;
225
- }
226
- setStatus("connected");
227
- gateRef.current?.arm();
228
- } else if (event.status === "disconnected") {
229
- setStatus("disconnected");
230
- gateRef.current?.reset();
231
- setSynced(false);
232
- gateRef.current?.arm();
233
- }
234
- };
235
- const handleSynced = (isSynced) => {
236
- if (isSynced) {
237
- gateRef.current?.open();
238
- }
239
- };
240
- provider.on("status", handleStatus);
241
- provider.on("sync", handleSynced);
242
- if (provider.wsconnected) {
243
- connected = true;
244
- setStatus("connected");
245
- gateRef.current?.arm();
246
- }
247
- if (provider.synced) {
248
- gateRef.current?.open();
249
- }
250
- if (!connected) {
251
- timeoutRef.current = setTimeout(() => {
252
- timeoutRef.current = null;
253
- if (!connected) {
254
- provider.off("status", handleStatus);
255
- provider.off("sync", handleSynced);
256
- announceDeparture();
257
- pptx.clearLocalAwareness(provider.awareness);
258
- provider.destroy();
259
- yDoc.destroy();
260
- setDoc(null);
261
- setAwareness(null);
262
- setClientId(null);
263
- cleanupRef.current = null;
264
- setStatus("error");
265
- }
266
- }, pptx.CONNECTION_TIMEOUT_MS);
267
- }
268
- setDoc(yDoc);
269
- setAwareness(provider.awareness);
270
- setClientId(provider.awareness.clientID);
271
- cleanupRef.current = () => {
272
- provider.off("status", handleStatus);
273
- provider.off("sync", handleSynced);
274
- announceDeparture();
275
- pptx.clearLocalAwareness(provider.awareness);
276
- provider.destroy();
277
- yDoc.destroy();
278
- setDoc(null);
279
- setAwareness(null);
280
- setClientId(null);
281
- setStatus("disconnected");
282
- };
283
- } catch (err) {
284
- if (generation !== generationRef.current) {
285
- return;
286
- }
287
- console.warn(
288
- "[pptx-viewer] Collaboration packages not available:",
289
- err instanceof Error ? err.message : err
290
- );
291
- setStatus("error");
292
- }
107
+ void controller.start(config);
108
+ const disposeTeardown = pptx.registerCollaborationTeardown({
109
+ leave: () => controller.stop(),
110
+ rejoin: () => void controller.retry()
111
+ });
112
+ return () => {
113
+ disposeTeardown();
114
+ controller.stop();
115
+ };
293
116
  }, [
117
+ controller,
294
118
  config?.roomId,
295
119
  config?.serverUrl,
296
120
  config?.authToken,
297
121
  config?.transport,
298
- announceDeparture,
299
- initWebrtc,
300
- teardown
122
+ signalingKey,
123
+ Boolean(config)
301
124
  ]);
302
- React17.useEffect(() => {
303
- init();
304
- const disposeTeardown = pptx.registerCollaborationTeardown({
305
- leave: teardown,
306
- rejoin: init
307
- });
308
- return () => {
309
- disposeTeardown();
310
- teardown();
311
- };
312
- }, [init, teardown]);
313
- const retry = React17.useCallback(() => {
314
- init();
315
- }, [init]);
316
- return { status, awareness, doc, clientId, synced, retry };
125
+ const session = state.active ? controller.getSession() : null;
126
+ return {
127
+ status: state.status,
128
+ awareness: session?.awareness ?? null,
129
+ doc: session?.doc ?? null,
130
+ clientId: state.clientId,
131
+ synced: state.synced,
132
+ retry: () => {
133
+ void controller.retry();
134
+ }
135
+ };
317
136
  }
318
137
  function usePresenceTracking({
319
138
  awareness,
@@ -762,15 +581,11 @@ function serializeHistoryDocument(snapshot) {
762
581
  )
763
582
  });
764
583
  }
765
- function recordExplicitSlideUpdate(past, future, previous, before, label, maxDepth) {
584
+ function recordExplicitSlideUpdate(history, previous, before, label) {
766
585
  if (previous && serializeHistoryDocument(previous) !== serializeHistoryDocument(before)) {
767
- past.push(chunkJAI42EXQ_js.cloneHistorySnapshot(previous));
768
- }
769
- past.push({ ...chunkJAI42EXQ_js.cloneHistorySnapshot(before), actionLabel: label });
770
- while (past.length > Math.max(1, maxDepth)) {
771
- past.shift();
586
+ history.record(chunkJWNBTFZZ_js.cloneHistorySnapshot(previous), previous.actionLabel);
772
587
  }
773
- future.length = 0;
588
+ history.record({ ...chunkJWNBTFZZ_js.cloneHistorySnapshot(before), actionLabel: label }, label);
774
589
  }
775
590
  var POLL_INTERVAL_MS = 16;
776
591
  function usePointerReleaseWakeup(hasActivePointerInteraction) {
@@ -806,7 +621,6 @@ function usePointerReleaseWakeup(hasActivePointerInteraction) {
806
621
  }
807
622
 
808
623
  // src/viewer/hooks/useEditorHistory.ts
809
- var DEFAULT_MAX_HISTORY_ENTRIES = 120;
810
624
  function useEditorHistory(input) {
811
625
  const {
812
626
  slides,
@@ -815,7 +629,7 @@ function useEditorHistory(input) {
815
629
  templateElementsBySlideId,
816
630
  loading,
817
631
  error,
818
- maxHistoryEntries = DEFAULT_MAX_HISTORY_ENTRIES,
632
+ maxHistoryEntries,
819
633
  hasActivePointerInteraction,
820
634
  pointerCommitNonce,
821
635
  onDirty,
@@ -826,38 +640,31 @@ function useEditorHistory(input) {
826
640
  setSelectedElementId,
827
641
  setSelectedElementIds
828
642
  } = input;
829
- const historyPastRef = React17.useRef([]);
830
- const historyFutureRef = React17.useRef([]);
643
+ const [history] = React17.useState(() => pptx.createEditorHistoryController());
644
+ const historyState = useController(history);
831
645
  const lastHistorySnapshotRef = React17.useRef(null);
832
646
  const lastHistorySerializedRef = React17.useRef("");
833
647
  const lastCheapHashRef = React17.useRef("");
834
648
  const isApplyingHistoryRef = React17.useRef(false);
835
649
  const trackingHeldRef = React17.useRef(false);
836
650
  const unlockHistoryTimerRef = React17.useRef(null);
837
- const [canUndo, setCanUndo] = React17.useState(false);
838
- const [canRedo, setCanRedo] = React17.useState(false);
839
- const [undoLabel, setUndoLabel] = React17.useState(void 0);
840
- const [redoLabel, setRedoLabel] = React17.useState(void 0);
841
651
  const [editCommitNonce, setEditCommitNonce] = React17.useState(0);
842
652
  const { pointerReleaseNonce, deferUntilPointerReleased } = usePointerReleaseWakeup(
843
653
  hasActivePointerInteraction
844
654
  );
845
- const updateHistoryAvailability = React17.useCallback(() => {
846
- setCanUndo(historyPastRef.current.length > 0);
847
- setCanRedo(historyFutureRef.current.length > 0);
848
- const pastTop = historyPastRef.current[historyPastRef.current.length - 1];
849
- setUndoLabel(pastTop?.actionLabel);
850
- const futureTop = historyFutureRef.current[historyFutureRef.current.length - 1];
851
- setRedoLabel(futureTop?.actionLabel);
852
- }, []);
655
+ React17.useEffect(() => {
656
+ if (maxHistoryEntries !== void 0) {
657
+ history.setMaxDepth(maxHistoryEntries);
658
+ }
659
+ }, [history, maxHistoryEntries]);
853
660
  const buildHistorySnapshot = React17.useCallback(
854
661
  (actionLabel) => {
855
662
  return {
856
663
  width: canvasSize.width,
857
664
  height: canvasSize.height,
858
665
  activeSlideIndex,
859
- slides: slides.map(chunkJAI42EXQ_js.cloneSlide),
860
- templateElementsBySlideId: chunkJAI42EXQ_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
666
+ slides: slides.map(chunkJWNBTFZZ_js.cloneSlide),
667
+ templateElementsBySlideId: chunkJWNBTFZZ_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
861
668
  ...actionLabel ? { actionLabel } : {}
862
669
  };
863
670
  },
@@ -870,9 +677,9 @@ function useEditorHistory(input) {
870
677
  width: snapshot.width,
871
678
  height: snapshot.height
872
679
  });
873
- setSlides(snapshot.slides.map(chunkJAI42EXQ_js.cloneSlide));
680
+ setSlides(snapshot.slides.map(chunkJWNBTFZZ_js.cloneSlide));
874
681
  setTemplateElementsBySlideId(
875
- chunkJAI42EXQ_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
682
+ chunkJWNBTFZZ_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
876
683
  );
877
684
  setActiveSlideIndex(Math.min(snapshot.activeSlideIndex, maxSlideIndex));
878
685
  setSelectedElementIds([]);
@@ -904,64 +711,50 @@ function useEditorHistory(input) {
904
711
  onDirtyRef.current?.();
905
712
  }, []);
906
713
  const handleUndo = React17.useCallback(() => {
907
- const previousSnapshot = historyPastRef.current.pop();
908
- if (!previousSnapshot) {
714
+ if (!history.getSnapshot().canUndo) {
715
+ return;
716
+ }
717
+ const result = history.undo(buildHistorySnapshot());
718
+ if (!result) {
909
719
  return;
910
720
  }
911
- const currentSnapshot = buildHistorySnapshot(previousSnapshot.actionLabel);
912
- historyFutureRef.current.push(currentSnapshot);
913
721
  isApplyingHistoryRef.current = true;
914
- const nextSnapshot = chunkJAI42EXQ_js.cloneHistorySnapshot(previousSnapshot);
915
- lastHistorySnapshotRef.current = chunkJAI42EXQ_js.cloneHistorySnapshot(nextSnapshot);
722
+ const nextSnapshot = chunkJWNBTFZZ_js.cloneHistorySnapshot(result.snapshot);
723
+ lastHistorySnapshotRef.current = chunkJWNBTFZZ_js.cloneHistorySnapshot(nextSnapshot);
916
724
  lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
917
725
  applyHistorySnapshot(nextSnapshot);
918
- updateHistoryAvailability();
919
726
  unlockHistoryTracking();
920
727
  markDirty();
921
- }, [
922
- applyHistorySnapshot,
923
- buildHistorySnapshot,
924
- markDirty,
925
- unlockHistoryTracking,
926
- updateHistoryAvailability
927
- ]);
728
+ }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
928
729
  const handleRedo = React17.useCallback(() => {
929
- const nextSnapshot = historyFutureRef.current.pop();
930
- if (!nextSnapshot) {
730
+ if (!history.getSnapshot().canRedo) {
731
+ return;
732
+ }
733
+ const result = history.redo(buildHistorySnapshot());
734
+ if (!result) {
931
735
  return;
932
736
  }
933
- const currentSnapshot = buildHistorySnapshot(nextSnapshot.actionLabel);
934
- historyPastRef.current.push(currentSnapshot);
935
737
  isApplyingHistoryRef.current = true;
936
- const targetSnapshot = chunkJAI42EXQ_js.cloneHistorySnapshot(nextSnapshot);
937
- lastHistorySnapshotRef.current = chunkJAI42EXQ_js.cloneHistorySnapshot(targetSnapshot);
738
+ const targetSnapshot = chunkJWNBTFZZ_js.cloneHistorySnapshot(result.snapshot);
739
+ lastHistorySnapshotRef.current = chunkJWNBTFZZ_js.cloneHistorySnapshot(targetSnapshot);
938
740
  lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
939
741
  applyHistorySnapshot(targetSnapshot);
940
- updateHistoryAvailability();
941
742
  unlockHistoryTracking();
942
743
  markDirty();
943
- }, [
944
- applyHistorySnapshot,
945
- buildHistorySnapshot,
946
- markDirty,
947
- unlockHistoryTracking,
948
- updateHistoryAvailability
949
- ]);
744
+ }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
950
745
  const resetHistory = React17.useCallback(
951
746
  (initialSnapshot) => {
952
- historyPastRef.current = [];
953
- historyFutureRef.current = [];
747
+ history.clear();
954
748
  if (initialSnapshot) {
955
- const clonedInitial = chunkJAI42EXQ_js.cloneHistorySnapshot(initialSnapshot);
749
+ const clonedInitial = chunkJWNBTFZZ_js.cloneHistorySnapshot(initialSnapshot);
956
750
  lastHistorySnapshotRef.current = clonedInitial;
957
751
  lastHistorySerializedRef.current = serializeHistoryDocument(clonedInitial);
958
752
  } else {
959
753
  lastHistorySnapshotRef.current = null;
960
754
  lastHistorySerializedRef.current = "";
961
755
  }
962
- updateHistoryAvailability();
963
756
  },
964
- [updateHistoryAvailability]
757
+ [history]
965
758
  );
966
759
  React17.useEffect(() => {
967
760
  return () => {
@@ -1004,19 +797,13 @@ function useEditorHistory(input) {
1004
797
  lastHistorySnapshotRef.current = snapshot;
1005
798
  lastHistorySerializedRef.current = serialized;
1006
799
  lastCheapHashRef.current = cheapHash;
1007
- updateHistoryAvailability();
1008
800
  return;
1009
801
  }
1010
802
  onDirtyRef.current?.();
1011
- historyPastRef.current.push(previousSnapshot);
1012
- while (historyPastRef.current.length > Math.max(1, maxHistoryEntries)) {
1013
- historyPastRef.current.shift();
1014
- }
1015
- historyFutureRef.current = [];
803
+ history.record(previousSnapshot, previousSnapshot.actionLabel);
1016
804
  lastHistorySnapshotRef.current = snapshot;
1017
805
  lastHistorySerializedRef.current = serialized;
1018
806
  lastCheapHashRef.current = cheapHash;
1019
- updateHistoryAvailability();
1020
807
  }, [
1021
808
  activeSlideIndex,
1022
809
  buildHistorySnapshot,
@@ -1026,30 +813,21 @@ function useEditorHistory(input) {
1026
813
  editCommitNonce,
1027
814
  error,
1028
815
  hasActivePointerInteraction,
816
+ history,
1029
817
  loading,
1030
- maxHistoryEntries,
1031
818
  pointerCommitNonce,
1032
819
  pointerReleaseNonce,
1033
- slides,
1034
- updateHistoryAvailability
820
+ slides
1035
821
  ]);
1036
822
  const commitSlides = (nextSlides, label, beforeSlides = slides) => {
1037
- const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(chunkJAI42EXQ_js.cloneSlide) };
1038
- const after = { ...before, slides: nextSlides.map(chunkJAI42EXQ_js.cloneSlide) };
1039
- recordExplicitSlideUpdate(
1040
- historyPastRef.current,
1041
- historyFutureRef.current,
1042
- lastHistorySnapshotRef.current,
1043
- before,
1044
- label,
1045
- maxHistoryEntries
1046
- );
1047
- lastHistorySnapshotRef.current = chunkJAI42EXQ_js.cloneHistorySnapshot(after);
823
+ const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(chunkJWNBTFZZ_js.cloneSlide) };
824
+ const after = { ...before, slides: nextSlides.map(chunkJWNBTFZZ_js.cloneSlide) };
825
+ recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
826
+ lastHistorySnapshotRef.current = chunkJWNBTFZZ_js.cloneHistorySnapshot(after);
1048
827
  lastHistorySerializedRef.current = serializeHistoryDocument(after);
1049
828
  isApplyingHistoryRef.current = false;
1050
829
  setSlides(nextSlides);
1051
830
  onDirtyRef.current?.();
1052
- updateHistoryAvailability();
1053
831
  };
1054
832
  const holdTracking = React17.useCallback((held) => {
1055
833
  trackingHeldRef.current = held;
@@ -1057,10 +835,10 @@ function useEditorHistory(input) {
1057
835
  return {
1058
836
  commitSlides,
1059
837
  holdTracking,
1060
- canUndo,
1061
- canRedo,
1062
- undoLabel,
1063
- redoLabel,
838
+ canUndo: historyState.canUndo,
839
+ canRedo: historyState.canRedo,
840
+ undoLabel: historyState.undoLabel,
841
+ redoLabel: historyState.redoLabel,
1064
842
  handleUndo,
1065
843
  handleRedo,
1066
844
  resetHistory,
@@ -1230,22 +1008,22 @@ function useZoomViewport({
1230
1008
  selectedElements.forEach((element) => {
1231
1009
  minX = Math.min(minX, element.x);
1232
1010
  minY = Math.min(minY, element.y);
1233
- maxX = Math.max(maxX, element.x + Math.max(element.width, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE));
1234
- maxY = Math.max(maxY, element.y + Math.max(element.height, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE));
1011
+ maxX = Math.max(maxX, element.x + Math.max(element.width, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE));
1012
+ maxY = Math.max(maxY, element.y + Math.max(element.height, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE));
1235
1013
  });
1236
1014
  if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {
1237
1015
  return;
1238
1016
  }
1239
1017
  const selectionBounds = { minX, minY, maxX, maxY };
1240
- const boundsWidth = Math.max(selectionBounds.maxX - selectionBounds.minX, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
1241
- const boundsHeight = Math.max(selectionBounds.maxY - selectionBounds.minY, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
1018
+ const boundsWidth = Math.max(selectionBounds.maxX - selectionBounds.minX, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE);
1019
+ const boundsHeight = Math.max(selectionBounds.maxY - selectionBounds.minY, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE);
1242
1020
  const availableWidth = Math.max(
1243
- effectiveEditorDimensions.width - chunkJAI42EXQ_js.ZOOM_TO_SELECTION_PADDING,
1244
- chunkJAI42EXQ_js.MIN_ELEMENT_SIZE
1021
+ effectiveEditorDimensions.width - chunkJWNBTFZZ_js.ZOOM_TO_SELECTION_PADDING,
1022
+ chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE
1245
1023
  );
1246
1024
  const availableHeight = Math.max(
1247
- effectiveEditorDimensions.height - chunkJAI42EXQ_js.ZOOM_TO_SELECTION_PADDING,
1248
- chunkJAI42EXQ_js.MIN_ELEMENT_SIZE
1025
+ effectiveEditorDimensions.height - chunkJWNBTFZZ_js.ZOOM_TO_SELECTION_PADDING,
1026
+ chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE
1249
1027
  );
1250
1028
  const targetEditorScale = Math.min(
1251
1029
  availableWidth / boundsWidth,
@@ -2203,9 +1981,6 @@ function executeSlideTransition(nextSlideIndex, deps) {
2203
1981
  }
2204
1982
 
2205
1983
  // src/viewer/hooks/presentation-mode/useSlideNavigation.ts
2206
- function isClickAdvanceBlocked(slide, direction, trigger) {
2207
- return trigger === "click" && direction === 1 && slide?.transition?.advanceOnClick === false;
2208
- }
2209
1984
  function useSlideNavigation(input) {
2210
1985
  const {
2211
1986
  slides,
@@ -2255,50 +2030,71 @@ function useSlideNavigation(input) {
2255
2030
  );
2256
2031
  const movePresentationSlide = React17.useCallback(
2257
2032
  (direction, trigger = "explicit") => {
2258
- if (direction === 1 && playNextAnimationGroup()) {
2259
- return;
2260
- }
2261
- if (isClickAdvanceBlocked(slides[presentationSlideIndex], direction, trigger)) {
2033
+ const showOrder = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
2034
+ const current = presentationSlideIndex;
2035
+ const transitionTo = (index, options = {}) => executeSlideTransition(index, {
2036
+ slides,
2037
+ currentSlideIndex: current,
2038
+ onPlayActionSound,
2039
+ onStopActionSound,
2040
+ setPresentationSlideVisible,
2041
+ clearPresentationTimers,
2042
+ setPresentationSlideIndex,
2043
+ onSetActiveSlideIndex,
2044
+ seedSlideAnimations,
2045
+ startSlideAnimations,
2046
+ scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
2047
+ presentationTimersRef,
2048
+ setTransitionOverlay,
2049
+ // PowerPoint plays a slide's transition only when advancing into it,
2050
+ // and replays the LEAVING slide's transition in reverse when stepping
2051
+ // back (a morph glides its shapes back to where they came from).
2052
+ playTransition: true,
2053
+ ...options
2054
+ });
2055
+ if (direction === -1) {
2056
+ const step2 = pptx.resolveShowBackward({
2057
+ currentIndex: current,
2058
+ showOrder,
2059
+ endOfShow: false,
2060
+ seededCompleted: false
2061
+ });
2062
+ if (step2.kind === "go") {
2063
+ transitionTo(step2.index, { reverse: true, seedCompleted: true });
2064
+ }
2262
2065
  return;
2263
2066
  }
2264
- if (direction === 1) {
2265
- const consumedExcursion = zoomExcursionRef.current;
2266
- const step = pptx.resolveForwardSlideWithZoomReturn(
2267
- presentationSlideIndex,
2268
- void 0,
2269
- consumedExcursion
2270
- );
2271
- if (step.returnedToZoom && step.nextSlideIndex !== void 0) {
2272
- zoomExcursionRef.current = step.excursion;
2273
- executeSlideTransition(step.nextSlideIndex, {
2274
- slides,
2275
- currentSlideIndex: presentationSlideIndex,
2276
- onPlayActionSound,
2277
- onStopActionSound,
2278
- setPresentationSlideVisible,
2279
- clearPresentationTimers,
2280
- setPresentationSlideIndex,
2281
- onSetActiveSlideIndex,
2282
- seedSlideAnimations,
2283
- startSlideAnimations,
2067
+ const step = pptx.resolveShowForward({
2068
+ currentIndex: current,
2069
+ currentSlide: slides[current],
2070
+ showOrder,
2071
+ endOfShow: false,
2072
+ fromClick: trigger === "click",
2073
+ loop: Boolean(loopContinuously) && !rehearsing,
2074
+ endWithBlackSlide: true,
2075
+ zoomExcursion: zoomExcursionRef.current,
2076
+ advanceBuild: playNextAnimationGroup
2077
+ });
2078
+ if (step.kind === "go") {
2079
+ if (step.zoomReturn) {
2080
+ zoomExcursionRef.current = step.zoomReturn.excursion;
2081
+ transitionTo(step.index, {
2284
2082
  scheduleAutoAdvanceForSlide,
2285
- presentationTimersRef,
2286
- setTransitionOverlay,
2287
- playTransition: true,
2288
- transitionOverride: pptx.buildZoomTransitionOverride(
2289
- consumedExcursion?.transitionDurationMs
2290
- )
2083
+ transitionOverride: step.zoomReturn.transitionOverride
2291
2084
  });
2292
2085
  return;
2293
2086
  }
2087
+ if (rehearsing) {
2088
+ recordCurrentSlideTime(current);
2089
+ }
2090
+ transitionTo(step.index);
2091
+ return;
2294
2092
  }
2295
- const availableSlideIndexes = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
2296
- if (availableSlideIndexes.length === 0) {
2093
+ if (step.kind !== "end-screen" && step.kind !== "exit") {
2297
2094
  return;
2298
2095
  }
2299
- const pastLastSlide = direction === 1 && !pptx.hasShowSlideAfter(presentationSlideIndex, availableSlideIndexes);
2300
- if (rehearsing && pastLastSlide) {
2301
- recordCurrentSlideTime(presentationSlideIndex);
2096
+ if (rehearsing) {
2097
+ recordCurrentSlideTime(current);
2302
2098
  try {
2303
2099
  if (document.fullscreenElement) {
2304
2100
  void document.exitFullscreen().catch(() => {
@@ -2310,41 +2106,7 @@ function useSlideNavigation(input) {
2310
2106
  setShowRehearsalSummary(true);
2311
2107
  return;
2312
2108
  }
2313
- if (!loopContinuously && !rehearsing && pastLastSlide && onAdvancePastLastSlide) {
2314
- onAdvancePastLastSlide();
2315
- return;
2316
- }
2317
- const nextSlideIndex = direction === 1 ? pptx.nextShowSlideIndex(presentationSlideIndex, availableSlideIndexes, {
2318
- loop: Boolean(loopContinuously) && !rehearsing
2319
- }) : pptx.previousShowSlideIndex(presentationSlideIndex, availableSlideIndexes);
2320
- if (nextSlideIndex === void 0 || nextSlideIndex === presentationSlideIndex) {
2321
- return;
2322
- }
2323
- if (rehearsing && direction === 1) {
2324
- recordCurrentSlideTime(presentationSlideIndex);
2325
- }
2326
- executeSlideTransition(nextSlideIndex, {
2327
- slides,
2328
- currentSlideIndex: presentationSlideIndex,
2329
- onPlayActionSound,
2330
- onStopActionSound,
2331
- setPresentationSlideVisible,
2332
- clearPresentationTimers,
2333
- setPresentationSlideIndex,
2334
- onSetActiveSlideIndex,
2335
- seedSlideAnimations,
2336
- startSlideAnimations,
2337
- scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
2338
- presentationTimersRef,
2339
- setTransitionOverlay,
2340
- // PowerPoint plays a slide's transition only when advancing into it,
2341
- // and replays the LEAVING slide's transition in reverse when stepping
2342
- // back (a morph glides its shapes back to where they came from).
2343
- playTransition: true,
2344
- reverse: direction === -1,
2345
- // Stepping back onto a slide shows it with its builds already played.
2346
- seedCompleted: direction === -1
2347
- });
2109
+ onAdvancePastLastSlide?.();
2348
2110
  },
2349
2111
  [
2350
2112
  clearPresentationTimers,
@@ -4204,6 +3966,7 @@ function useViewerCoreState(_input) {
4204
3966
  const marqueeStateRef = React17.useRef(null);
4205
3967
  const isDrawingRef = React17.useRef(false);
4206
3968
  const justInteractedRef = React17.useRef(false);
3969
+ const gestureControllerRef = React17.useRef(null);
4207
3970
  const livePatcher = React17.useMemo(() => pptx.createCollaborationLivePatcher(), []);
4208
3971
  React17.useEffect(() => () => livePatcher.dispose(), [livePatcher]);
4209
3972
  const [mode, setMode] = React17.useState("edit");
@@ -4212,18 +3975,19 @@ function useViewerCoreState(_input) {
4212
3975
  const { slides, setSlides, slidesRef } = useSlideState();
4213
3976
  const [templateElementsBySlideId, setTemplateElementsBySlideId] = React17.useState({});
4214
3977
  const [canvasSize, setCanvasSize] = React17.useState({
4215
- width: chunkJAI42EXQ_js.DEFAULT_CANVAS_WIDTH,
4216
- height: chunkJAI42EXQ_js.DEFAULT_CANVAS_HEIGHT
3978
+ width: chunkJWNBTFZZ_js.DEFAULT_CANVAS_WIDTH,
3979
+ height: chunkJWNBTFZZ_js.DEFAULT_CANVAS_HEIGHT
4217
3980
  });
4218
3981
  const [slideSizeEmu, setSlideSizeEmu] = React17.useState();
4219
3982
  const [activeSlideIndex, setActiveSlideIndex] = React17.useState(0);
4220
3983
  const [selectedElementId, setSelectedElementId] = React17.useState(null);
4221
3984
  const [selectedElementIds, setSelectedElementIds] = React17.useState([]);
4222
3985
  const [isDirty, setIsDirty] = React17.useState(false);
3986
+ const autosaveDraftSinkRef = React17.useRef(null);
4223
3987
  const publishInlineText = React17.useCallback(
4224
3988
  (elementId, text) => {
4225
- pptx.publishLiveInlineText(
4226
- livePatcher,
3989
+ pptx.reportInlineTextDraft(
3990
+ { livePatcher, autosave: autosaveDraftSinkRef.current },
4227
3991
  slidesRef.current[activeSlideIndexRef.current],
4228
3992
  elementId,
4229
3993
  text
@@ -4289,6 +4053,7 @@ function useViewerCoreState(_input) {
4289
4053
  imageInputRef,
4290
4054
  mediaInputRef,
4291
4055
  activeSlideIndexRef,
4056
+ autosaveDraftSinkRef,
4292
4057
  ...inlineEditing,
4293
4058
  ...editPointsMode,
4294
4059
  dragStateRef,
@@ -4297,6 +4062,7 @@ function useViewerCoreState(_input) {
4297
4062
  marqueeStateRef,
4298
4063
  isDrawingRef,
4299
4064
  justInteractedRef,
4065
+ gestureControllerRef,
4300
4066
  livePatcher,
4301
4067
  mode,
4302
4068
  setMode,
@@ -4686,12 +4452,12 @@ function useLoadContent({
4686
4452
  }
4687
4453
  resources.commit();
4688
4454
  handlerRef.current = handler;
4689
- const partition = chunkJAI42EXQ_js.partitionTemplateElements(nextSlides);
4455
+ const partition = chunkJWNBTFZZ_js.partitionTemplateElements(nextSlides);
4690
4456
  setSlides(partition.slides);
4691
4457
  setTemplateElementsBySlideId(partition.templateElementsBySlideId);
4692
4458
  setCanvasSize({
4693
- width: parsed.width ?? chunkJAI42EXQ_js.DEFAULT_CANVAS_WIDTH,
4694
- height: parsed.height ?? chunkJAI42EXQ_js.DEFAULT_CANVAS_HEIGHT
4459
+ width: parsed.width ?? chunkJWNBTFZZ_js.DEFAULT_CANVAS_WIDTH,
4460
+ height: parsed.height ?? chunkJWNBTFZZ_js.DEFAULT_CANVAS_HEIGHT
4695
4461
  });
4696
4462
  setSlideSizeEmu(
4697
4463
  typeof parsed.widthEmu === "number" && typeof parsed.heightEmu === "number" && parsed.widthEmu > 0 && parsed.heightEmu > 0 ? {
@@ -4783,96 +4549,43 @@ function useLoadContent({
4783
4549
  return { handlerRef };
4784
4550
  }
4785
4551
  function useAutosave(input) {
4786
- const { isDirty, filePath, serializeSlides, enabled = true, getChangeSources } = input;
4552
+ const { isDirty, filePath, enabled = true } = input;
4787
4553
  const intervalMs = pptx.resolveAutosaveIntervalMs({
4788
4554
  hostIntervalMs: input.intervalMs,
4789
4555
  optionsIntervalSeconds: input.intervalSeconds
4790
4556
  });
4791
- const [autosaveStatus, setAutosaveStatus] = React17.useState({
4792
- state: "idle"
4793
- });
4794
- const isDirtyRef = React17.useRef(isDirty);
4795
- const filePathRef = React17.useRef(filePath);
4796
- const serializeRef = React17.useRef(serializeSlides);
4797
- const storageRef = React17.useRef(input.storage);
4798
- storageRef.current = input.storage;
4799
- const isSavingRef = React17.useRef(false);
4800
- const changeSourcesRef = React17.useRef(getChangeSources);
4801
- const lastSnapshotRef = React17.useRef(void 0);
4802
- const onSavedRef = React17.useRef(input.onSaved);
4803
- React17.useEffect(() => {
4804
- onSavedRef.current = input.onSaved;
4805
- }, [input.onSaved]);
4806
- React17.useEffect(() => {
4807
- isDirtyRef.current = isDirty;
4808
- }, [isDirty]);
4809
- React17.useEffect(() => {
4810
- filePathRef.current = filePath;
4811
- }, [filePath]);
4812
- React17.useEffect(() => {
4813
- serializeRef.current = serializeSlides;
4814
- }, [serializeSlides]);
4557
+ const live = React17.useRef(input);
4558
+ live.current = input;
4559
+ const [controller] = React17.useState(
4560
+ () => pptx.createAutosaveController({
4561
+ getActivation: () => ({ active: live.current.enabled ?? true }),
4562
+ getFilePath: () => live.current.filePath,
4563
+ getIntervalMs: () => pptx.resolveAutosaveIntervalMs({
4564
+ hostIntervalMs: live.current.intervalMs,
4565
+ optionsIntervalSeconds: live.current.intervalSeconds
4566
+ }),
4567
+ serialize: () => live.current.serializeSlides(),
4568
+ getStorage: () => live.current.storage,
4569
+ onSaved: (data) => live.current.onSaved?.(data),
4570
+ writeSnapshot: pptx.saveAutosaveSnapshot,
4571
+ // serializeSlides already overlays the live inline draft from its refs.
4572
+ getInlineEditingId: () => live.current.getInlineEditingId?.()
4573
+ })
4574
+ );
4575
+ if (input.inlineDraftSinkRef) {
4576
+ input.inlineDraftSinkRef.current = controller;
4577
+ }
4578
+ const { status } = useController(controller);
4815
4579
  React17.useEffect(() => {
4816
- changeSourcesRef.current = getChangeSources;
4817
- }, [getChangeSources]);
4818
- const doAutosave = React17.useCallback(async (options) => {
4819
- const path = filePathRef.current;
4820
- if (!path) {
4821
- return;
4822
- }
4823
- const sources = changeSourcesRef.current?.() ?? [];
4824
- if (!pptx.shouldWriteAutosaveSnapshot({
4825
- filePath: path,
4826
- isDirty: isDirtyRef.current,
4827
- saving: isSavingRef.current,
4828
- sources: options?.polled === true ? sources : [],
4829
- lastSnapshot: lastSnapshotRef.current
4830
- })) {
4831
- return;
4832
- }
4833
- isSavingRef.current = true;
4834
- setAutosaveStatus({ state: "saving" });
4835
- try {
4836
- const data = await serializeRef.current();
4837
- if (!data) {
4838
- setAutosaveStatus({ state: "idle" });
4839
- isSavingRef.current = false;
4840
- return;
4841
- }
4842
- await pptx.saveAutosaveSnapshot(path, data, storageRef.current);
4843
- lastSnapshotRef.current = pptx.autosaveSnapshotMark(path, sources);
4844
- setAutosaveStatus({ state: "saved", timestamp: Date.now() });
4845
- onSavedRef.current?.(data);
4846
- } catch (err) {
4847
- setAutosaveStatus({
4848
- state: "error",
4849
- message: err instanceof Error ? err.message : "Autosave failed"
4850
- });
4851
- } finally {
4852
- isSavingRef.current = false;
4853
- }
4854
- }, []);
4580
+ controller.refresh();
4581
+ }, [controller, enabled, filePath, intervalMs]);
4855
4582
  React17.useEffect(() => {
4856
- if (!enabled) {
4857
- setAutosaveStatus({ state: "disabled", reason: "autosave_toggle_off" });
4858
- return;
4859
- }
4860
- if (!filePath) {
4861
- setAutosaveStatus({
4862
- state: "disabled",
4863
- reason: "no_file_path"
4864
- });
4865
- return;
4866
- }
4867
- setAutosaveStatus((prev) => prev.state === "disabled" ? { state: "idle" } : prev);
4868
- const id = setInterval(() => {
4869
- void doAutosave({ polled: true });
4870
- }, intervalMs);
4871
- return () => clearInterval(id);
4872
- }, [enabled, filePath, intervalMs, doAutosave]);
4583
+ controller.observe(isDirty, live.current.getChangeSources?.() ?? []);
4584
+ });
4585
+ React17.useEffect(() => () => controller.markClean(), [controller]);
4873
4586
  return {
4874
- autosaveStatus,
4875
- triggerAutosave: () => doAutosave()
4587
+ autosaveStatus: status,
4588
+ triggerAutosave: () => controller.saveNow()
4876
4589
  };
4877
4590
  }
4878
4591
 
@@ -5150,7 +4863,7 @@ function useElementOperations(input) {
5150
4863
  );
5151
4864
  return;
5152
4865
  }
5153
- if (chunkJAI42EXQ_js.isTemplateElementId(elementId)) {
4866
+ if (chunkJWNBTFZZ_js.isTemplateElementId(elementId)) {
5154
4867
  const slideId = activeSlide?.id;
5155
4868
  if (slideId) {
5156
4869
  setTemplateElementsBySlideId((prev) => ({
@@ -5387,45 +5100,238 @@ function syncSelectionHandleOverlay(elementNode, elementId, geometry) {
5387
5100
  }
5388
5101
  }
5389
5102
 
5390
- // src/viewer/hooks/pointer-move-handlers.ts
5391
- function computeResizeGeometry(handle, startX, startY, startWidth, startHeight, dx, dy, snapToGrid, gridSpacingPx, lockAspect = false) {
5392
- const startBox = { x: startX, y: startY, width: startWidth, height: startHeight };
5393
- let resized = pptx.applyResize(startBox, handle, dx, dy, 1, { minSize: chunkJAI42EXQ_js.MIN_ELEMENT_SIZE });
5394
- if (lockAspect) {
5395
- resized = pptx.lockResizeAspect(resized, startBox, handle, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
5103
+ // src/viewer/hooks/canvas-gestures.ts
5104
+ var animationFrames = {
5105
+ request: (callback) => requestAnimationFrame(callback),
5106
+ cancel: (handle) => cancelAnimationFrame(handle)
5107
+ };
5108
+ function createCanvasGestures(getInput, frames = animationFrames) {
5109
+ let armed = null;
5110
+ let pending = null;
5111
+ let frameHandle = 0;
5112
+ let lastSnapLinesKey = "";
5113
+ const liveTarget = () => {
5114
+ const { livePatcher, editTemplateMode, activeSlide } = getInput();
5115
+ return livePatcher && !editTemplateMode && livePatcher.isActive() ? { patcher: livePatcher, slideId: activeSlide?.id } : void 0;
5116
+ };
5117
+ function showSnapLines(lines) {
5118
+ const next = lines.map((line) => ({
5119
+ axis: line.axis === "v" ? "x" : "y",
5120
+ position: line.position
5121
+ }));
5122
+ const key = JSON.stringify(next);
5123
+ if (key !== lastSnapLinesKey) {
5124
+ lastSnapLinesKey = key;
5125
+ getInput().setSnapLines(next);
5126
+ }
5396
5127
  }
5397
- const box = { x: resized.x, y: resized.y, width: resized.width, height: resized.height };
5398
- if (!snapToGrid) {
5399
- return box;
5128
+ function paintMove(drag, transform) {
5129
+ const start = drag.startPositionsById[transform.id];
5130
+ if (!start) {
5131
+ return;
5132
+ }
5133
+ drag.lastDx = transform.x - start.x;
5134
+ drag.lastDy = transform.y - start.y;
5135
+ const live = liveTarget();
5136
+ for (const [id, from] of Object.entries(drag.startPositionsById)) {
5137
+ const x = from.x + drag.lastDx;
5138
+ const y = from.y + drag.lastDy;
5139
+ const domEl = drag.domEls.get(id);
5140
+ if (domEl) {
5141
+ domEl.style.left = `${x}px`;
5142
+ domEl.style.top = `${y}px`;
5143
+ syncSelectionHandleOverlay(domEl, id, { x, y });
5144
+ }
5145
+ if (live) {
5146
+ pptx.publishLiveGeometry(live.patcher, live.slideId, id, { x, y });
5147
+ }
5148
+ }
5149
+ }
5150
+ function paintResize(resize, transform) {
5151
+ const { x, y } = transform;
5152
+ const width = Math.max(transform.width, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE);
5153
+ const height = Math.max(transform.height, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE);
5154
+ resize.lastX = x;
5155
+ resize.lastY = y;
5156
+ resize.lastWidth = transform.width;
5157
+ resize.lastHeight = transform.height;
5158
+ if (resize.domEl) {
5159
+ Object.assign(resize.domEl.style, {
5160
+ left: `${x}px`,
5161
+ top: `${y}px`,
5162
+ width: `${width}px`,
5163
+ height: `${height}px`
5164
+ });
5165
+ syncSelectionHandleOverlay(resize.domEl, resize.elementId, { x, y, width, height });
5166
+ }
5167
+ const live = liveTarget();
5168
+ if (live) {
5169
+ pptx.publishLiveGeometry(live.patcher, live.slideId, resize.elementId, { x, y, width, height });
5170
+ }
5400
5171
  }
5401
- return pptx.snapBoxToGrid(box, handle, gridSpacingPx, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
5172
+ function paintPending() {
5173
+ const frame = pending;
5174
+ pending = null;
5175
+ frameHandle = 0;
5176
+ if (!frame || !armed) {
5177
+ return;
5178
+ }
5179
+ if (armed.kind === "move") {
5180
+ armed.drag.moved = true;
5181
+ showSnapLines(frame.lines);
5182
+ paintMove(armed.drag, frame.transform);
5183
+ } else {
5184
+ armed.resize.moved = true;
5185
+ paintResize(armed.resize, frame.transform);
5186
+ }
5187
+ }
5188
+ function flushFrame() {
5189
+ if (frameHandle !== 0) {
5190
+ frames.cancel(frameHandle);
5191
+ }
5192
+ paintPending();
5193
+ }
5194
+ const controller = pptx.createGestureController({
5195
+ getScale: () => getInput().editorScale,
5196
+ // Axis-aligned, as the canvas has always moved and resized (no rotation).
5197
+ getElementBox: (id) => {
5198
+ const el = getInput().elementLookup.get(id);
5199
+ return el ? { x: el.x, y: el.y, width: el.width, height: el.height } : void 0;
5200
+ },
5201
+ getSiblings: () => {
5202
+ const { editTemplateMode, templateElements, activeSlide } = getInput();
5203
+ const source = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
5204
+ return source.map(({ id, x, y, width, height }) => ({ id, x, y, width, height }));
5205
+ },
5206
+ getSnapToGrid: () => getInput().snapToGrid,
5207
+ getGridSize: () => getInput().gridSpacingPx,
5208
+ getSnapToShape: () => getInput().snapToShape,
5209
+ getGuides: () => getInput().guides.map(({ axis, position }) => ({ axis, position })),
5210
+ getMinSize: () => chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE,
5211
+ getSnapExcludeIds: () => armed?.kind === "move" ? Object.keys(armed.drag.startPositionsById) : [],
5212
+ getStageOrigin: () => {
5213
+ const rect = getInput().canvasStageRef.current?.getBoundingClientRect();
5214
+ return { left: rect?.left ?? 0, top: rect?.top ?? 0 };
5215
+ },
5216
+ onStart: () => void 0,
5217
+ onPreview: (transform, lines) => {
5218
+ pending = { transform, lines };
5219
+ if (frameHandle === 0) {
5220
+ frameHandle = frames.request(paintPending);
5221
+ }
5222
+ },
5223
+ onEnd: (transform, moved) => {
5224
+ flushFrame();
5225
+ const ended = armed;
5226
+ armed = null;
5227
+ if (ended) {
5228
+ finishGesture(ended, moved ? transform : null);
5229
+ }
5230
+ }
5231
+ });
5232
+ function finishGesture(ended, transform) {
5233
+ const input = getInput();
5234
+ if (transform) {
5235
+ if (ended.kind === "move") {
5236
+ commitMove(input, ended.drag);
5237
+ } else {
5238
+ commitResize(input, ended.resize);
5239
+ }
5240
+ input.justInteractedRef.current = true;
5241
+ input.livePatcher?.flush();
5242
+ }
5243
+ input.dragStateRef.current = null;
5244
+ input.resizeStateRef.current = null;
5245
+ lastSnapLinesKey = "";
5246
+ input.setSnapLines([]);
5247
+ if (transform) {
5248
+ input.markDirty();
5249
+ }
5250
+ input.setPointerCommitNonce((n) => n + 1);
5251
+ }
5252
+ return {
5253
+ begin(kind, id, pointer) {
5254
+ if (controller.isActive()) {
5255
+ return;
5256
+ }
5257
+ const input = getInput();
5258
+ const drag = input.dragStateRef.current;
5259
+ const resize = input.resizeStateRef.current;
5260
+ armed = kind === "move" && drag ? { kind, drag } : kind === "resize" && resize ? { kind, resize } : null;
5261
+ if (!armed) {
5262
+ return;
5263
+ }
5264
+ lastSnapLinesKey = "";
5265
+ const handle = armed.kind === "resize" ? armed.resize.handle : void 0;
5266
+ controller.begin(kind, id, pointer, handle);
5267
+ if (!controller.isActive()) {
5268
+ armed = null;
5269
+ }
5270
+ },
5271
+ isActive: () => controller.isActive(),
5272
+ dispose: () => {
5273
+ if (frameHandle !== 0) {
5274
+ frames.cancel(frameHandle);
5275
+ frameHandle = 0;
5276
+ }
5277
+ pending = null;
5278
+ armed = null;
5279
+ controller.dispose();
5280
+ }
5281
+ };
5402
5282
  }
5403
- function resolveLiveTarget(input) {
5404
- const { livePatcher, editTemplateMode, activeSlide } = input;
5405
- if (!livePatcher || editTemplateMode || !livePatcher.isActive()) {
5406
- return void 0;
5283
+ function commitMove(input, drag) {
5284
+ const { lastDx: dx, lastDy: dy } = drag;
5285
+ const movedIds = new Set(Object.keys(drag.startPositionsById));
5286
+ const moveElements = (elements) => {
5287
+ const moved = elements.map((el) => {
5288
+ const start = drag.startPositionsById[el.id];
5289
+ return start ? { ...el, x: start.x + dx, y: start.y + dy } : el;
5290
+ });
5291
+ return chunkJWNBTFZZ_js.applyReroutedConnectors(moved, chunkJWNBTFZZ_js.rerouteConnectorsForMovedElements(moved, movedIds));
5292
+ };
5293
+ if (input.editTemplateMode) {
5294
+ const slideId = input.activeSlide?.id;
5295
+ if (slideId) {
5296
+ input.setTemplateElementsBySlideId((prev) => ({
5297
+ ...prev,
5298
+ [slideId]: moveElements(prev[slideId] ?? [])
5299
+ }));
5300
+ }
5301
+ return;
5407
5302
  }
5408
- return { patcher: livePatcher, slideId: activeSlide?.id };
5303
+ input.updateSlides(
5304
+ (prev) => prev.map(
5305
+ (s, i) => i !== input.activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) }
5306
+ )
5307
+ );
5409
5308
  }
5410
- function processPointerMove(e, input, tracker) {
5309
+ function commitResize(input, resize) {
5310
+ input.updateElementById(resize.elementId, {
5311
+ x: resize.lastX,
5312
+ y: resize.lastY,
5313
+ width: resize.lastWidth,
5314
+ height: resize.lastHeight
5315
+ });
5316
+ const movedIds = /* @__PURE__ */ new Set([resize.elementId]);
5317
+ input.updateSlides(
5318
+ (prev) => prev.map((s, i) => {
5319
+ if (i !== input.activeSlideIndex) {
5320
+ return s;
5321
+ }
5322
+ const rerouted = chunkJWNBTFZZ_js.rerouteConnectorsForMovedElements(s.elements, movedIds);
5323
+ return rerouted.length === 0 ? s : { ...s, elements: chunkJWNBTFZZ_js.applyReroutedConnectors(s.elements, rerouted) };
5324
+ })
5325
+ );
5326
+ }
5327
+ function processPointerMove(e, input) {
5411
5328
  const {
5412
5329
  editorScale,
5413
5330
  canvasStageRef,
5414
5331
  canvasSize,
5415
- snapToGrid,
5416
- snapToShape,
5417
- gridSpacingPx,
5418
- editTemplateMode,
5419
- templateElements,
5420
- activeSlide,
5421
- guides,
5422
- elementLookup,
5423
5332
  marqueeStateRef,
5424
- dragStateRef,
5425
- resizeStateRef,
5426
5333
  shapeAdjustmentDragStateRef,
5427
5334
  setMarqueeSelectionState,
5428
- setSnapLines,
5429
5335
  updateElementById
5430
5336
  } = input;
5431
5337
  const marquee = marqueeStateRef.current;
@@ -5440,31 +5346,6 @@ function processPointerMove(e, input, tracker) {
5440
5346
  );
5441
5347
  return;
5442
5348
  }
5443
- const drag = dragStateRef.current;
5444
- if (drag) {
5445
- processDragMove(
5446
- e,
5447
- drag,
5448
- editorScale,
5449
- snapToGrid,
5450
- snapToShape,
5451
- gridSpacingPx,
5452
- editTemplateMode,
5453
- templateElements,
5454
- activeSlide,
5455
- guides,
5456
- elementLookup,
5457
- tracker,
5458
- setSnapLines,
5459
- resolveLiveTarget(input)
5460
- );
5461
- return;
5462
- }
5463
- const rs = resizeStateRef.current;
5464
- if (rs) {
5465
- processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, resolveLiveTarget(input));
5466
- return;
5467
- }
5468
5349
  const adj = shapeAdjustmentDragStateRef.current;
5469
5350
  if (adj) {
5470
5351
  processAdjustmentMove(e, adj, editorScale, updateElementById);
@@ -5480,129 +5361,6 @@ function processMarqueeMove(e, marquee, canvasStageRef, canvasSize, editorScale,
5480
5361
  marquee.currentY = Math.max(0, Math.min(canvasSize.height, (e.clientY - rect.top) / editorScale));
5481
5362
  setMarqueeSelectionState({ ...marquee });
5482
5363
  }
5483
- function processDragMove(e, drag, editorScale, snapToGrid, snapToShape, gridSpacingPx, editTemplateMode, templateElements, activeSlide, guides, elementLookup, tracker, setSnapLines, live) {
5484
- const dx = (e.clientX - drag.startClientX) / editorScale;
5485
- const dy = (e.clientY - drag.startClientY) / editorScale;
5486
- if (!drag.moved && (Math.abs(dx) > 2 || Math.abs(dy) > 2)) {
5487
- drag.moved = true;
5488
- }
5489
- if (!drag.moved) {
5490
- return;
5491
- }
5492
- let appliedDx = dx;
5493
- let appliedDy = dy;
5494
- const draggedIds = Object.keys(drag.startPositionsById);
5495
- const primaryId = draggedIds[0];
5496
- const primaryStart = primaryId ? drag.startPositionsById[primaryId] : void 0;
5497
- const primaryEl = primaryId ? elementLookup.get(primaryId) : void 0;
5498
- if (primaryStart && primaryEl) {
5499
- let targetX = primaryStart.x + appliedDx;
5500
- let targetY = primaryStart.y + appliedDy;
5501
- if (snapToGrid) {
5502
- targetX = Math.round(targetX / gridSpacingPx) * gridSpacingPx;
5503
- targetY = Math.round(targetY / gridSpacingPx) * gridSpacingPx;
5504
- }
5505
- if (snapToShape) {
5506
- const siblingSource = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
5507
- const siblings = siblingSource.map((el) => ({
5508
- id: el.id,
5509
- x: el.x,
5510
- y: el.y,
5511
- width: el.width,
5512
- height: el.height
5513
- }));
5514
- const snapResult = chunkJAI42EXQ_js.computeSnapToShape(
5515
- targetX,
5516
- targetY,
5517
- primaryEl.width,
5518
- primaryEl.height,
5519
- siblings,
5520
- new Set(draggedIds),
5521
- guides.map((g) => ({ axis: g.axis, position: g.position }))
5522
- );
5523
- targetX = snapResult.x;
5524
- targetY = snapResult.y;
5525
- const newSnapLines = snapResult.lines.map((line) => ({
5526
- axis: line.axis === "v" ? "x" : "y",
5527
- position: line.position
5528
- }));
5529
- const newKey = JSON.stringify(newSnapLines);
5530
- if (newKey !== tracker.lastSnapLinesKey) {
5531
- tracker.lastSnapLinesKey = newKey;
5532
- setSnapLines(newSnapLines);
5533
- }
5534
- } else if (tracker.lastSnapLinesKey !== "[]") {
5535
- tracker.lastSnapLinesKey = "[]";
5536
- setSnapLines([]);
5537
- }
5538
- appliedDx = targetX - primaryStart.x;
5539
- appliedDy = targetY - primaryStart.y;
5540
- }
5541
- drag.lastDx = appliedDx;
5542
- drag.lastDy = appliedDy;
5543
- for (const [id, domEl] of drag.domEls) {
5544
- const start = drag.startPositionsById[id];
5545
- if (start) {
5546
- const x = start.x + appliedDx;
5547
- const y = start.y + appliedDy;
5548
- domEl.style.left = `${x}px`;
5549
- domEl.style.top = `${y}px`;
5550
- syncSelectionHandleOverlay(domEl, id, { x, y });
5551
- }
5552
- }
5553
- if (live) {
5554
- for (const id of Object.keys(drag.startPositionsById)) {
5555
- const start = drag.startPositionsById[id];
5556
- pptx.publishLiveGeometry(live.patcher, live.slideId, id, {
5557
- x: start.x + appliedDx,
5558
- y: start.y + appliedDy
5559
- });
5560
- }
5561
- }
5562
- }
5563
- function processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, live) {
5564
- const dx = (e.clientX - rs.startClientX) / editorScale;
5565
- const dy = (e.clientY - rs.startClientY) / editorScale;
5566
- if (!rs.moved && (Math.abs(dx) > 2 || Math.abs(dy) > 2)) {
5567
- rs.moved = true;
5568
- }
5569
- if (!rs.moved) {
5570
- return;
5571
- }
5572
- const geo = computeResizeGeometry(
5573
- rs.handle,
5574
- rs.startX,
5575
- rs.startY,
5576
- rs.startWidth,
5577
- rs.startHeight,
5578
- dx,
5579
- dy,
5580
- snapToGrid,
5581
- gridSpacingPx,
5582
- e.shiftKey
5583
- );
5584
- rs.lastX = geo.x;
5585
- rs.lastY = geo.y;
5586
- rs.lastWidth = geo.width;
5587
- rs.lastHeight = geo.height;
5588
- const width = Math.max(geo.width, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
5589
- const height = Math.max(geo.height, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
5590
- if (rs.domEl) {
5591
- rs.domEl.style.left = `${geo.x}px`;
5592
- rs.domEl.style.top = `${geo.y}px`;
5593
- rs.domEl.style.width = `${width}px`;
5594
- rs.domEl.style.height = `${height}px`;
5595
- syncSelectionHandleOverlay(rs.domEl, rs.elementId, { x: geo.x, y: geo.y, width, height });
5596
- }
5597
- if (live) {
5598
- pptx.publishLiveGeometry(live.patcher, live.slideId, rs.elementId, {
5599
- x: geo.x,
5600
- y: geo.y,
5601
- width,
5602
- height
5603
- });
5604
- }
5605
- }
5606
5364
  function processAdjustmentMove(e, adj, editorScale, updateElementById) {
5607
5365
  const dx = (e.clientX - adj.startClientX) / editorScale;
5608
5366
  const dy = (e.clientY - adj.startClientY) / editorScale;
@@ -5621,26 +5379,20 @@ function processPointerUp(input) {
5621
5379
  editTemplateMode,
5622
5380
  templateElements,
5623
5381
  activeSlide,
5624
- activeSlideIndex,
5625
5382
  marqueeStateRef,
5626
5383
  dragStateRef,
5627
5384
  resizeStateRef,
5628
5385
  shapeAdjustmentDragStateRef,
5629
5386
  justInteractedRef,
5387
+ gestureRef,
5630
5388
  setMarqueeSelectionState,
5631
- setSnapLines,
5632
- setTemplateElementsBySlideId,
5633
5389
  setPointerCommitNonce,
5634
5390
  applySelection,
5635
5391
  clearSelection,
5636
- updateSlides,
5637
- updateElementById,
5638
5392
  markDirty,
5639
5393
  livePatcher
5640
5394
  } = input;
5641
5395
  const marquee = marqueeStateRef.current;
5642
- const drag = dragStateRef.current;
5643
- const rs = resizeStateRef.current;
5644
5396
  const adj = shapeAdjustmentDragStateRef.current;
5645
5397
  if (marquee) {
5646
5398
  commitMarquee(
@@ -5651,62 +5403,22 @@ function processPointerUp(input) {
5651
5403
  applySelection,
5652
5404
  clearSelection
5653
5405
  );
5654
- marqueeStateRef.current = null;
5655
- setMarqueeSelectionState(null);
5656
5406
  }
5657
- if (drag?.moved) {
5658
- commitDrag(
5659
- drag,
5660
- editTemplateMode,
5661
- activeSlide,
5662
- activeSlideIndex,
5663
- setTemplateElementsBySlideId,
5664
- updateSlides
5665
- );
5407
+ if (!gestureRef?.current?.isActive()) {
5408
+ dragStateRef.current = null;
5409
+ resizeStateRef.current = null;
5666
5410
  }
5667
- if (rs?.moved) {
5668
- const resizedId = rs.elementId;
5669
- const resizeUpdates = {
5670
- x: rs.lastX,
5671
- y: rs.lastY,
5672
- width: rs.lastWidth,
5673
- height: rs.lastHeight
5674
- };
5675
- updateElementById(resizedId, resizeUpdates);
5676
- const movedIds = /* @__PURE__ */ new Set([resizedId]);
5677
- updateSlides(
5678
- (prev) => prev.map((s, i) => {
5679
- if (i !== activeSlideIndex) {
5680
- return s;
5681
- }
5682
- const rerouted = chunkJAI42EXQ_js.rerouteConnectorsForMovedElements(s.elements, movedIds);
5683
- if (rerouted.length === 0) {
5684
- return s;
5685
- }
5686
- return {
5687
- ...s,
5688
- elements: chunkJAI42EXQ_js.applyReroutedConnectors(s.elements, rerouted)
5689
- };
5690
- })
5691
- );
5692
- }
5693
- const wasMoved = drag?.moved || rs?.moved || adj?.moved;
5694
- if (wasMoved) {
5411
+ if (adj?.moved) {
5695
5412
  justInteractedRef.current = true;
5696
- }
5697
- if (wasMoved) {
5698
5413
  livePatcher?.flush();
5699
5414
  }
5700
5415
  marqueeStateRef.current = null;
5701
- dragStateRef.current = null;
5702
- resizeStateRef.current = null;
5703
5416
  shapeAdjustmentDragStateRef.current = null;
5704
5417
  setMarqueeSelectionState(null);
5705
- setSnapLines([]);
5706
- if (wasMoved) {
5418
+ if (adj?.moved) {
5707
5419
  markDirty();
5708
5420
  }
5709
- if (drag || rs || adj || marquee) {
5421
+ if (adj || marquee) {
5710
5422
  setPointerCommitNonce((n) => n + 1);
5711
5423
  }
5712
5424
  }
@@ -5726,35 +5438,6 @@ function commitMarquee(marquee, editTemplateMode, templateElements, activeSlide,
5726
5438
  clearSelection();
5727
5439
  }
5728
5440
  }
5729
- function commitDrag(drag, editTemplateMode, activeSlide, activeSlideIndex, setTemplateElementsBySlideId, updateSlides) {
5730
- const dx = drag.lastDx, dy = drag.lastDy;
5731
- const movedIds = new Set(Object.keys(drag.startPositionsById));
5732
- const moveElements = (elements) => {
5733
- const movedElements = elements.map((el) => {
5734
- const start = drag.startPositionsById[el.id];
5735
- if (!start) {
5736
- return el;
5737
- }
5738
- return { ...el, x: start.x + dx, y: start.y + dy };
5739
- });
5740
- const rerouted = chunkJAI42EXQ_js.rerouteConnectorsForMovedElements(movedElements, movedIds);
5741
- return chunkJAI42EXQ_js.applyReroutedConnectors(movedElements, rerouted);
5742
- };
5743
- if (editTemplateMode) {
5744
- const slideId = activeSlide?.id;
5745
- if (!slideId) {
5746
- return;
5747
- }
5748
- setTemplateElementsBySlideId((prev) => ({
5749
- ...prev,
5750
- [slideId]: moveElements(prev[slideId] ?? [])
5751
- }));
5752
- return;
5753
- }
5754
- updateSlides(
5755
- (prev) => prev.map((s, i) => i !== activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) })
5756
- );
5757
- }
5758
5441
 
5759
5442
  // src/viewer/hooks/usePointerHandlers.ts
5760
5443
  function usePointerHandlers(input) {
@@ -5764,41 +5447,42 @@ function usePointerHandlers(input) {
5764
5447
  canvasSize,
5765
5448
  activeSlide,
5766
5449
  activeSlideIndex,
5767
- gridSpacingPx,
5768
- dragStateRef,
5769
- resizeStateRef,
5770
5450
  shapeAdjustmentDragStateRef,
5771
5451
  marqueeStateRef,
5772
5452
  editTemplateMode,
5773
- snapToGrid,
5774
- snapToShape,
5775
- guides,
5776
5453
  templateElements,
5777
- elementLookup,
5778
5454
  setMarqueeSelectionState,
5779
- setSnapLines,
5780
- setTemplateElementsBySlideId,
5781
5455
  setPointerCommitNonce,
5782
5456
  applySelection,
5783
5457
  clearSelection,
5784
- updateSlides,
5785
5458
  updateElementById,
5786
5459
  markDirty,
5787
- livePatcher
5460
+ livePatcher,
5461
+ gestureRef
5788
5462
  } = input;
5463
+ const inputRef = React17.useRef(input);
5464
+ inputRef.current = input;
5465
+ const gestures = React17.useMemo(() => createCanvasGestures(() => inputRef.current), []);
5789
5466
  React17.useEffect(() => {
5790
- const tracker = {
5791
- rafId: 0,
5792
- pendingMoveEvent: null,
5793
- lastSnapLinesKey: ""
5467
+ if (gestureRef) {
5468
+ gestureRef.current = gestures;
5469
+ }
5470
+ return () => {
5471
+ gestures.dispose();
5472
+ if (gestureRef?.current === gestures) {
5473
+ gestureRef.current = null;
5474
+ }
5794
5475
  };
5476
+ }, [gestures, gestureRef]);
5477
+ React17.useEffect(() => {
5478
+ const tracker = { rafId: 0, pendingMoveEvent: null };
5795
5479
  const handlePointerMove = (e) => {
5796
5480
  tracker.pendingMoveEvent = e;
5797
5481
  if (tracker.rafId === 0) {
5798
5482
  tracker.rafId = requestAnimationFrame(() => {
5799
5483
  tracker.rafId = 0;
5800
5484
  if (tracker.pendingMoveEvent) {
5801
- processPointerMove(tracker.pendingMoveEvent, input, tracker);
5485
+ processPointerMove(tracker.pendingMoveEvent, input);
5802
5486
  tracker.pendingMoveEvent = null;
5803
5487
  }
5804
5488
  });
@@ -5826,31 +5510,22 @@ function usePointerHandlers(input) {
5826
5510
  }, [
5827
5511
  editorScale,
5828
5512
  canvasStageRef,
5829
- dragStateRef,
5830
- resizeStateRef,
5831
5513
  shapeAdjustmentDragStateRef,
5832
5514
  marqueeStateRef,
5833
5515
  editTemplateMode,
5834
- snapToGrid,
5835
- snapToShape,
5836
- guides,
5837
5516
  templateElements,
5838
5517
  setMarqueeSelectionState,
5839
- setSnapLines,
5840
- elementLookup,
5841
- setTemplateElementsBySlideId,
5842
5518
  setPointerCommitNonce,
5843
5519
  activeSlide,
5844
5520
  activeSlideIndex,
5845
5521
  canvasSize.width,
5846
5522
  canvasSize.height,
5847
- gridSpacingPx,
5848
5523
  applySelection,
5849
5524
  clearSelection,
5850
- updateSlides,
5851
5525
  updateElementById,
5852
5526
  markDirty,
5853
- livePatcher
5527
+ livePatcher,
5528
+ gestureRef
5854
5529
  ]);
5855
5530
  }
5856
5531
  function mouseDownStartsSelectionDrag(event) {
@@ -5876,6 +5551,7 @@ function useCanvasInteractions(input) {
5876
5551
  shapeAdjustmentDragStateRef,
5877
5552
  marqueeStateRef,
5878
5553
  justInteractedRef,
5554
+ gestureRef,
5879
5555
  setInlineEditingElementId,
5880
5556
  setInlineEditingText,
5881
5557
  setContextMenuState,
@@ -5901,25 +5577,7 @@ function useCanvasInteractions(input) {
5901
5577
  const scale = editorScale || 1;
5902
5578
  return rect ? { x: (e.clientX - rect.left) / scale, y: (e.clientY - rect.top) / scale } : null;
5903
5579
  };
5904
- const drillChain = (elementId, e) => {
5905
- if (!slideElements) {
5906
- return null;
5907
- }
5908
- const top = slideElements.find((el) => el.id === elementId);
5909
- const point = slidePoint(e);
5910
- if (!top || !point || !pptx.isEnterableGroup(top)) {
5911
- return null;
5912
- }
5913
- return pptx.memberChainAtPoint(slideElements, elementId, point);
5914
- };
5915
- const resolvePressTarget = (elementId, e) => {
5916
- const chain = drillChain(elementId, e);
5917
- if (!chain || !slideElements) {
5918
- return elementId;
5919
- }
5920
- const selectedPath = selectedElementId ? pptx.findElementPath(slideElements, selectedElementId) : null;
5921
- return pptx.drillSelectionForClick(chain, selectedPath) ?? elementId;
5922
- };
5580
+ const resolvePressTarget = (elementId, e) => slideElements ? pptx.resolveGroupPressTarget(slideElements, elementId, slidePoint(e), effectiveSelectedIds) : elementId;
5923
5581
  const handleInlineEditCommit = () => {
5924
5582
  const editId = inlineEditingElementId;
5925
5583
  if (!editId) {
@@ -6019,9 +5677,7 @@ function useCanvasInteractions(input) {
6019
5677
  }
6020
5678
  };
6021
5679
  const handleElementDoubleClick = (pressedId, e) => {
6022
- const chain = mode === "present" ? null : drillChain(pressedId, e);
6023
- const innermost = chain ? pptx.drillSelectionForDoubleClick(chain) : null;
6024
- const elementId = innermost && pptx.canInteractWithElement(elementLookup.get(innermost), "select") ? innermost : pressedId;
5680
+ const elementId = mode === "present" || !slideElements ? pressedId : pptx.resolveGroupDoubleClickTarget(slideElements, pressedId, slidePoint(e));
6025
5681
  if (elementId !== pressedId) {
6026
5682
  ops.applySelection(elementId);
6027
5683
  }
@@ -6084,6 +5740,7 @@ function useCanvasInteractions(input) {
6084
5740
  lastDy: 0
6085
5741
  };
6086
5742
  setSnapLines([]);
5743
+ gestureRef?.current?.begin("move", movableIds[0], e);
6087
5744
  };
6088
5745
  const handleElementContextMenu = (elementId, e) => {
6089
5746
  if (mode === "present") {
@@ -6156,6 +5813,7 @@ function useCanvasInteractions(input) {
6156
5813
  lastWidth: el.width,
6157
5814
  lastHeight: el.height
6158
5815
  };
5816
+ gestureRef?.current?.begin("resize", elementId, e);
6159
5817
  };
6160
5818
  const handleRotate = (elementId, rotationDeg) => {
6161
5819
  const el = elementLookup.get(elementId);
@@ -6497,7 +6155,7 @@ function createStructuredElementHandlers(deps) {
6497
6155
  return;
6498
6156
  }
6499
6157
  const resolved = resolveHyperlinkEditResult(data);
6500
- if (resolved.url && !chunkJAI42EXQ_js.isUrlSafe(resolved.url)) {
6158
+ if (resolved.url && !chunkJWNBTFZZ_js.isUrlSafe(resolved.url)) {
6501
6159
  return;
6502
6160
  }
6503
6161
  const actionClick = {
@@ -6543,7 +6201,7 @@ function createStructuredElementHandlers(deps) {
6543
6201
  if (!activeSlide) {
6544
6202
  return;
6545
6203
  }
6546
- const preset = chunkJAI42EXQ_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
6204
+ const preset = chunkJWNBTFZZ_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
6547
6205
  if (!preset) {
6548
6206
  return;
6549
6207
  }
@@ -6630,7 +6288,7 @@ function useInsertElements(input) {
6630
6288
  width: 300,
6631
6289
  height: 60,
6632
6290
  text: "",
6633
- textStyle: { fontSize: chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE }
6291
+ textStyle: { fontSize: chunkJWNBTFZZ_js.DEFAULT_TEXT_FONT_SIZE }
6634
6292
  });
6635
6293
  };
6636
6294
  const handleAddShape = () => {
@@ -6652,7 +6310,7 @@ function useInsertElements(input) {
6652
6310
  }
6653
6311
  });
6654
6312
  };
6655
- const handleAddTable = (rows = chunkJAI42EXQ_js.DEFAULT_TABLE_ROWS, columns = chunkJAI42EXQ_js.DEFAULT_TABLE_COLUMNS) => {
6313
+ const handleAddTable = (rows = chunkJWNBTFZZ_js.DEFAULT_TABLE_ROWS, columns = chunkJWNBTFZZ_js.DEFAULT_TABLE_COLUMNS) => {
6656
6314
  if (!activeSlide) {
6657
6315
  return;
6658
6316
  }
@@ -6661,11 +6319,11 @@ function useInsertElements(input) {
6661
6319
  id: pptx.generateElementId()
6662
6320
  });
6663
6321
  };
6664
- const handleAddChart = (chartKind) => {
6322
+ const handleAddChart = (chartKind, options) => {
6665
6323
  if (!activeSlide) {
6666
6324
  return;
6667
6325
  }
6668
- addElement(pptx.createDefaultChartElement(chartKind));
6326
+ addElement(pptx.createDefaultChartElement(chartKind, void 0, options));
6669
6327
  };
6670
6328
  const structured = createStructuredElementHandlers({
6671
6329
  activeSlide,
@@ -6826,7 +6484,7 @@ function useGroupAlignLayerHandlers(input) {
6826
6484
  history
6827
6485
  } = input;
6828
6486
  const updateElementsOwning = (elementId, updater) => {
6829
- if (editTemplateMode && !chunkJAI42EXQ_js.isTemplateElementId(elementId)) {
6487
+ if (editTemplateMode && !chunkJWNBTFZZ_js.isTemplateElementId(elementId)) {
6830
6488
  ops.updateSlides(
6831
6489
  (prev) => prev.map(
6832
6490
  (slide, index) => index === activeSlideIndex ? { ...slide, elements: updater(slide.elements) } : slide
@@ -6860,9 +6518,9 @@ function useGroupAlignLayerHandlers(input) {
6860
6518
  return;
6861
6519
  }
6862
6520
  const group = selectedElement;
6863
- const intoTemplate = chunkJAI42EXQ_js.isTemplateElementId(group.id);
6521
+ const intoTemplate = chunkJWNBTFZZ_js.isTemplateElementId(group.id);
6864
6522
  const childIds = group.children.map(
6865
- (child) => intoTemplate ? chunkJAI42EXQ_js.makeCloneId(true, child.id || group.id) : child.id || pptx.generateElementId()
6523
+ (child) => intoTemplate ? chunkJWNBTFZZ_js.makeCloneId(true, child.id || group.id) : child.id || pptx.generateElementId()
6866
6524
  );
6867
6525
  const { elements, childIds: usedIds } = pptx.ungroupElements(
6868
6526
  ops.activeElements,
@@ -7298,7 +6956,7 @@ function createTableMergeHandlers(input) {
7298
6956
  if (!nextCell || nextCell.hMerge || nextCell.vMerge) {
7299
6957
  return;
7300
6958
  }
7301
- const newTableData = chunkJAI42EXQ_js.mergeCells(
6959
+ const newTableData = chunkJWNBTFZZ_js.mergeCells(
7302
6960
  [
7303
6961
  { row: rowIndex, col: columnIndex },
7304
6962
  { row: rowIndex, col: nextColIdx }
@@ -7306,7 +6964,7 @@ function createTableMergeHandlers(input) {
7306
6964
  td
7307
6965
  );
7308
6966
  const updates = { tableData: newTableData };
7309
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6967
+ const newRawXml = chunkJWNBTFZZ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7310
6968
  if (newRawXml) {
7311
6969
  updates.rawXml = newRawXml;
7312
6970
  }
@@ -7332,7 +6990,7 @@ function createTableMergeHandlers(input) {
7332
6990
  if (!targetNextCell || targetNextCell.hMerge || targetNextCell.vMerge) {
7333
6991
  return;
7334
6992
  }
7335
- const newTableData = chunkJAI42EXQ_js.mergeCells(
6993
+ const newTableData = chunkJWNBTFZZ_js.mergeCells(
7336
6994
  [
7337
6995
  { row: rowIndex, col: columnIndex },
7338
6996
  { row: targetNextRowIdx, col: columnIndex }
@@ -7340,7 +6998,7 @@ function createTableMergeHandlers(input) {
7340
6998
  td
7341
6999
  );
7342
7000
  const updates = { tableData: newTableData };
7343
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7001
+ const newRawXml = chunkJWNBTFZZ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7344
7002
  if (newRawXml) {
7345
7003
  updates.rawXml = newRawXml;
7346
7004
  }
@@ -7355,9 +7013,9 @@ function createTableMergeHandlers(input) {
7355
7013
  return;
7356
7014
  }
7357
7015
  const td = selectedElement.tableData;
7358
- const newTableData = chunkJAI42EXQ_js.mergeCells(ts.selectedCells, td);
7016
+ const newTableData = chunkJWNBTFZZ_js.mergeCells(ts.selectedCells, td);
7359
7017
  const updates = { tableData: newTableData };
7360
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7018
+ const newRawXml = chunkJWNBTFZZ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7361
7019
  if (newRawXml) {
7362
7020
  updates.rawXml = newRawXml;
7363
7021
  }
@@ -7374,9 +7032,9 @@ function createTableMergeHandlers(input) {
7374
7032
  }
7375
7033
  const { rowIndex, columnIndex } = ts;
7376
7034
  const td = selectedElement.tableData;
7377
- const newTableData = chunkJAI42EXQ_js.splitCell(rowIndex, columnIndex, td);
7035
+ const newTableData = chunkJWNBTFZZ_js.splitCell(rowIndex, columnIndex, td);
7378
7036
  const updates = { tableData: newTableData };
7379
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7037
+ const newRawXml = chunkJWNBTFZZ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7380
7038
  if (newRawXml) {
7381
7039
  updates.rawXml = newRawXml;
7382
7040
  }
@@ -7411,7 +7069,7 @@ function createTableStructHandlers(input) {
7411
7069
  updates.tableData = pptx.setCellText(el, rowIndex, colIndex, text).tableData;
7412
7070
  }
7413
7071
  if (el.rawXml) {
7414
- const newRawXml = chunkJAI42EXQ_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
7072
+ const newRawXml = chunkJWNBTFZZ_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
7415
7073
  if (newRawXml) {
7416
7074
  updates.rawXml = newRawXml;
7417
7075
  }
@@ -7435,7 +7093,7 @@ function createTableStructHandlers(input) {
7435
7093
  const { rowIndex, columnIndex: colIndex } = ts;
7436
7094
  const updates = {};
7437
7095
  if (selectedElement.rawXml) {
7438
- const newRawXml = chunkJAI42EXQ_js.updateCellTextStyleInRawXml(
7096
+ const newRawXml = chunkJWNBTFZZ_js.updateCellTextStyleInRawXml(
7439
7097
  selectedElement,
7440
7098
  rowIndex,
7441
7099
  colIndex,
@@ -7613,7 +7271,7 @@ function useExportSaveAs(input) {
7613
7271
  const sourceName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() : void 0;
7614
7272
  const slideSize = pptx.resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size;
7615
7273
  const data = {
7616
- slides: chunkJAI42EXQ_js.buildSaveSlides(slides, templateElementsBySlideId),
7274
+ slides: chunkJWNBTFZZ_js.buildSaveSlides(slides, templateElementsBySlideId),
7617
7275
  width: canvasSize.width,
7618
7276
  height: canvasSize.height,
7619
7277
  widthEmu: slideSize.widthEmu,
@@ -7775,7 +7433,7 @@ async function captureAllSlidesAsPngDataUrls(slideStageRef, totalSlides, setActi
7775
7433
  }
7776
7434
  function tilesToPdfPage(tilesResult) {
7777
7435
  return tilesResult.tiles.map((tile) => ({
7778
- image: chunkJAI42EXQ_js.canvasToJpegData(tile.canvas),
7436
+ image: chunkJWNBTFZZ_js.canvasToJpegData(tile.canvas),
7779
7437
  placement: pptx.placeTileOnPage(
7780
7438
  tile,
7781
7439
  tilesResult.fullWidth,
@@ -7808,7 +7466,7 @@ async function exportAllSlidesAsPdf(slideStageRef, totalSlides, setActiveSlide,
7808
7466
  if (pages.length === 0) {
7809
7467
  throw new Error(i18n.translationsEn["pptx.export.errorNoSlidesPdf"]);
7810
7468
  }
7811
- const pdfBlobUrl = chunkJAI42EXQ_js.buildPdfFromTiledImageData(pages);
7469
+ const pdfBlobUrl = chunkJWNBTFZZ_js.buildPdfFromTiledImageData(pages);
7812
7470
  pptx.downloadDataUrl(pdfBlobUrl, filename);
7813
7471
  }
7814
7472
  async function exportAllSlidesAsNotesPdf(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, slideNotes, filename = "presentation-notes.pdf", options = {}) {
@@ -7838,7 +7496,7 @@ async function exportAllSlidesAsNotesPdf(slideStageRef, totalSlides, setActiveSl
7838
7496
  if (pages.length === 0) {
7839
7497
  throw new Error(i18n.translationsEn["pptx.export.errorNoSlidesNotesPdf"]);
7840
7498
  }
7841
- const pdfDataUrl = chunkJAI42EXQ_js.buildNotesPdf(pages);
7499
+ const pdfDataUrl = chunkJWNBTFZZ_js.buildNotesPdf(pages);
7842
7500
  pptx.downloadDataUrl(pdfDataUrl, filename);
7843
7501
  }
7844
7502
  async function exportAllSlidesAsVideo(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, options = {}) {
@@ -8941,7 +8599,7 @@ function usePropertyHandlers(input) {
8941
8599
  width: canvasSize.width,
8942
8600
  height: canvasSize.height
8943
8601
  };
8944
- setCompareResult(chunkJAI42EXQ_js.comparePresentation(cur, other));
8602
+ setCompareResult(chunkJWNBTFZZ_js.comparePresentation(cur, other));
8945
8603
  setIsComparePanelOpen(true);
8946
8604
  } catch (err) {
8947
8605
  console.warn("Compare failed:", err);
@@ -9110,6 +8768,7 @@ function useViewerDialogs(input) {
9110
8768
  embeddedFontFamilies
9111
8769
  } = input;
9112
8770
  const [isSmartArtDialogOpen, setIsSmartArtDialogOpen] = React17.useState(false);
8771
+ const [isChartDialogOpen, setIsChartDialogOpen] = React17.useState(false);
9113
8772
  const [isEquationDialogOpen, setIsEquationDialogOpen] = React17.useState(false);
9114
8773
  const [isHyperlinkDialogOpen, setIsHyperlinkDialogOpen] = React17.useState(false);
9115
8774
  const [isPasswordDialogOpen, setIsPasswordDialogOpen] = React17.useState(false);
@@ -9254,6 +8913,8 @@ function useViewerDialogs(input) {
9254
8913
  return {
9255
8914
  isSmartArtDialogOpen,
9256
8915
  setIsSmartArtDialogOpen,
8916
+ isChartDialogOpen,
8917
+ setIsChartDialogOpen,
9257
8918
  isEquationDialogOpen,
9258
8919
  setIsEquationDialogOpen,
9259
8920
  isHyperlinkDialogOpen,
@@ -9294,7 +8955,7 @@ function useViewerDialogs(input) {
9294
8955
  };
9295
8956
  }
9296
8957
  function computeGridSpacingPx(documentGridSpacing) {
9297
- return pptx.computeGridSpacingPx(documentGridSpacing, chunkJAI42EXQ_js.GRID_SIZE);
8958
+ return pptx.computeGridSpacingPx(documentGridSpacing, chunkJWNBTFZZ_js.GRID_SIZE);
9298
8959
  }
9299
8960
  function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, presentationProperties) {
9300
8961
  const activeShow = activeCustomShowId ? customShows.find((show) => show.id === activeCustomShowId) : void 0;
@@ -9303,7 +8964,7 @@ function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, pre
9303
8964
  }
9304
8965
  function computeSlideSectionGroups(slides, sections) {
9305
8966
  return pptx.groupSlidesBySection(sections, slides).map((group) => ({
9306
- id: group.section?.id ?? (sections.length > 0 ? chunkJAI42EXQ_js.UNGROUPED_SECTION_ID : chunkJAI42EXQ_js.DEFAULT_SECTION_GROUP_ID),
8967
+ id: group.section?.id ?? (sections.length > 0 ? chunkJWNBTFZZ_js.UNGROUPED_SECTION_ID : chunkJWNBTFZZ_js.DEFAULT_SECTION_GROUP_ID),
9307
8968
  label: group.section?.name ?? (sections.length > 0 ? "Ungrouped Slides" : "Slides"),
9308
8969
  slideIndexes: group.slideIndexes,
9309
8970
  ...group.section?.color !== void 0 ? { color: group.section.color } : {},
@@ -9348,10 +9009,10 @@ function useDerivedSlideState(input) {
9348
9009
  );
9349
9010
  const slideSectionGroups = React17.useMemo(
9350
9011
  () => computeSlideSectionGroups(slides, sections).map((group) => {
9351
- if (group.id === chunkJAI42EXQ_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
9012
+ if (group.id === chunkJWNBTFZZ_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
9352
9013
  return { ...group, label: t("pptx.slides.ungroupedSlides") };
9353
9014
  }
9354
- if (group.id === chunkJAI42EXQ_js.DEFAULT_SECTION_GROUP_ID && group.label === "Slides") {
9015
+ if (group.id === chunkJWNBTFZZ_js.DEFAULT_SECTION_GROUP_ID && group.label === "Slides") {
9355
9016
  return { ...group, label: t("pptx.sections.slides") };
9356
9017
  }
9357
9018
  return group;
@@ -9458,7 +9119,7 @@ function useAnnotationHandlers(input) {
9458
9119
  if (nextMode === "present") {
9459
9120
  presentation.enterPresentMode();
9460
9121
  } else if (mode === "present" && annotations.hasAnyAnnotations) {
9461
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9122
+ chunkJWNBTFZZ_js.stopAllPersistentAudio();
9462
9123
  if (promptKeepInkAnnotations) {
9463
9124
  pendingModeAfterAnnotationsRef.current = nextMode;
9464
9125
  setShowKeepAnnotationsDialog(true);
@@ -9468,7 +9129,7 @@ function useAnnotationHandlers(input) {
9468
9129
  }
9469
9130
  } else {
9470
9131
  if (mode === "present") {
9471
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9132
+ chunkJWNBTFZZ_js.stopAllPersistentAudio();
9472
9133
  }
9473
9134
  setMode(nextMode);
9474
9135
  }
@@ -9635,7 +9296,7 @@ function useSerialize(input) {
9635
9296
  guides: pptxGuides.length > 0 ? pptxGuides : void 0
9636
9297
  };
9637
9298
  });
9638
- const slidesToSave = chunkJAI42EXQ_js.buildSaveSlides(slidesWithGuides, pending.templateElementsBySlideId);
9299
+ const slidesToSave = chunkJWNBTFZZ_js.buildSaveSlides(slidesWithGuides, pending.templateElementsBySlideId);
9639
9300
  const saveOptions = pptx.buildDeckSaveOptions({
9640
9301
  // Without this the Slide Size card edited a viewer-only pixel value and
9641
9302
  // the saved `p:sldSz` never moved: passing `slideSize` is the only way a
@@ -9699,84 +9360,35 @@ function useSerialize(input) {
9699
9360
  }
9700
9361
  function useRecoveryDetection(input) {
9701
9362
  const { filePath, fileName, loading, error, slideCount, autosaveAllowed = true } = input;
9702
- const recoveryCheckedRef = React17.useRef(false);
9703
- const recordRef = React17.useRef(null);
9704
- const actionPendingRef = React17.useRef(false);
9705
- const [prompt, setPrompt] = React17.useState(null);
9706
- const [discarding, setDiscarding] = React17.useState(false);
9707
- const onRestore = input.onRestore;
9708
- const storageRef = React17.useRef(input.storage);
9709
- storageRef.current = input.storage;
9710
- const onOfferedRef = React17.useRef(input.onOffered);
9711
- React17.useEffect(() => {
9712
- onOfferedRef.current = input.onOffered;
9713
- }, [input.onOffered]);
9714
- const openVersionHistory = input.openVersionHistory;
9363
+ const live = React17.useRef(input);
9364
+ live.current = input;
9365
+ const [controller] = React17.useState(
9366
+ () => pptx.createAutosaveRecoveryController({
9367
+ getStorage: () => live.current.storage,
9368
+ load: (bytes) => live.current.onRestore?.(bytes),
9369
+ onOffered: (record) => {
9370
+ live.current.onOffered?.(record);
9371
+ live.current.openVersionHistory?.();
9372
+ },
9373
+ probe: pptx.probeAutosaveRecovery,
9374
+ discardRecord: pptx.discardAutosaveRecovery
9375
+ })
9376
+ );
9377
+ const { prompt, discarding } = useController(controller);
9715
9378
  React17.useEffect(() => {
9716
- if (!pptx.shouldProbeAutosaveRecovery({
9717
- alreadyChecked: recoveryCheckedRef.current,
9718
- filePath,
9719
- loading,
9720
- error,
9721
- slideCount,
9722
- autosaveAllowed
9723
- })) {
9724
- return;
9725
- }
9726
- recoveryCheckedRef.current = true;
9727
- void (async () => {
9728
- const offer = await pptx.probeAutosaveRecovery(
9729
- filePath,
9730
- Date.now(),
9731
- fileName,
9732
- storageRef.current
9733
- );
9734
- if (!offer) {
9735
- return;
9736
- }
9737
- recordRef.current = offer.record;
9738
- setPrompt(offer.prompt);
9739
- onOfferedRef.current?.(offer.record);
9740
- openVersionHistory?.();
9741
- })();
9742
- }, [filePath, fileName, loading, error, slideCount, autosaveAllowed, openVersionHistory]);
9743
- const restore = React17.useCallback(() => {
9744
- if (actionPendingRef.current) {
9745
- return;
9746
- }
9747
- actionPendingRef.current = true;
9748
- const record = recordRef.current;
9749
- setPrompt(null);
9750
- if (record && onRestore) {
9751
- onRestore(pptx.acceptAutosaveRecovery(record));
9752
- pptx.acknowledgeAutosaveRecovery(record);
9753
- }
9754
- recordRef.current = null;
9755
- }, [onRestore]);
9756
- const discard = React17.useCallback(() => {
9757
- if (actionPendingRef.current) {
9758
- return;
9759
- }
9760
- const record = recordRef.current;
9761
- if (!record) {
9762
- setPrompt(null);
9763
- return;
9379
+ controller.check({ filePath, fileName, loading, error, slideCount, autosaveAllowed });
9380
+ }, [controller, filePath, fileName, loading, error, slideCount, autosaveAllowed]);
9381
+ return {
9382
+ prompt,
9383
+ discarding,
9384
+ restore: () => {
9385
+ void controller.restore().catch(() => {
9386
+ });
9387
+ },
9388
+ discard: () => {
9389
+ void controller.discard();
9764
9390
  }
9765
- actionPendingRef.current = true;
9766
- setDiscarding(true);
9767
- void (async () => {
9768
- try {
9769
- await pptx.discardAutosaveRecovery(record, storageRef.current);
9770
- recordRef.current = null;
9771
- setPrompt(null);
9772
- } catch {
9773
- } finally {
9774
- actionPendingRef.current = false;
9775
- setDiscarding(false);
9776
- }
9777
- })();
9778
- }, []);
9779
- return { prompt, restore, discard, discarding };
9391
+ };
9780
9392
  }
9781
9393
  function usePresentationSetup(input) {
9782
9394
  const {
@@ -9828,7 +9440,7 @@ function usePresentationSetup(input) {
9828
9440
  return;
9829
9441
  }
9830
9442
  if (mode === "present" && nextMode !== "present") {
9831
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9443
+ chunkJWNBTFZZ_js.stopAllPersistentAudio();
9832
9444
  stopAnimationSound();
9833
9445
  const exitHandler = exitModeHandlerRef.current;
9834
9446
  if (exitHandler) {
@@ -9949,7 +9561,7 @@ function useCanvasImagePaste(input) {
9949
9561
  );
9950
9562
  }
9951
9563
  function formatPatchFor(element, format) {
9952
- const updated = chunkJAI42EXQ_js.applyFormatToElement(element, format);
9564
+ const updated = chunkJWNBTFZZ_js.applyFormatToElement(element, format);
9953
9565
  const updates = {};
9954
9566
  if (pptx$1.hasShapeProperties(updated)) {
9955
9567
  updates.shapeStyle = updated.shapeStyle;
@@ -9972,7 +9584,7 @@ function useFormatPainterEditing(input) {
9972
9584
  const prevFormatPainterRef = React17.useRef(false);
9973
9585
  React17.useEffect(() => {
9974
9586
  if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
9975
- copiedFormatRef.current = chunkJAI42EXQ_js.copyFormatFromElement(selectedElement);
9587
+ copiedFormatRef.current = chunkJWNBTFZZ_js.copyFormatFromElement(selectedElement);
9976
9588
  } else if (!formatPainterActive) {
9977
9589
  copiedFormatRef.current = null;
9978
9590
  }
@@ -10250,6 +9862,7 @@ function useEditorOperations(input) {
10250
9862
  shapeAdjustmentDragStateRef: state.shapeAdjustmentDragStateRef,
10251
9863
  marqueeStateRef: state.marqueeStateRef,
10252
9864
  justInteractedRef: state.justInteractedRef,
9865
+ gestureRef: state.gestureControllerRef,
10253
9866
  setInlineEditingElementId: state.setInlineEditingElementId,
10254
9867
  setInlineEditingText: state.setInlineEditingText,
10255
9868
  setContextMenuState: state.setContextMenuState,
@@ -10782,6 +10395,8 @@ function useContentLifecycle(input) {
10782
10395
  // deck it has already snapshotted. The two refs are read by `.current`
10783
10396
  // because an inline edit in progress lives there and nowhere else yet.
10784
10397
  onSaved: input.onAutosave,
10398
+ inlineDraftSinkRef: state.autosaveDraftSinkRef,
10399
+ getInlineEditingId: () => state.inlineEditingElementIdRef.current,
10785
10400
  getChangeSources: () => [
10786
10401
  slides,
10787
10402
  state.templateElementsBySlideId,
@@ -10811,138 +10426,27 @@ function useKeyboardShortcuts(input) {
10811
10426
  inputRef.current = input;
10812
10427
  const handleKeyDown = React17.useCallback((e) => {
10813
10428
  const current = inputRef.current;
10814
- const startAction = current.customization && !pptx.isFeatureEnabled(current.customization, "presentMode") ? null : pptx.mapSlideShowStartKey(e, { isPresenting: current.mode === "present" });
10815
- if (startAction !== null) {
10816
- e.preventDefault();
10817
- if (startAction === "fromBeginning") {
10818
- current.onStartShowFromBeginning();
10819
- } else {
10820
- current.onStartShowFromCurrent();
10821
- }
10822
- return;
10823
- }
10824
- const { action, dx, dy } = pptx.mapCustomizedEditorKey(
10429
+ pptx.dispatchEditorKey(
10825
10430
  e,
10826
10431
  {
10827
10432
  canEdit: current.canEdit,
10828
- canPaste: current.canPaste,
10829
- // The Slide Master view is an editing surface, not a viewing one.
10830
- // Gating on `mode !== 'edit'` alone made `mapEditorKey` return
10831
- // NO_ACTION there, so Delete, the arrow-key nudges and the clipboard
10832
- // keys were all inert over a master shape even though the write path
10833
- // behind them routes to the owning part correctly. Svelte and
10834
- // vanilla, which render the master into their ordinary editable
10835
- // stage, never had the gap.
10433
+ ...current.canPaste === void 0 ? {} : { canPaste: current.canPaste },
10434
+ // The Slide Master view is an editing surface, not a viewing one, so
10435
+ // only the other modes count as "not editing" for the editor keymap.
10836
10436
  isPresenting: current.mode !== "edit" && current.mode !== "master",
10437
+ // F5 is only inert while the show itself runs: a read-only viewer can
10438
+ // still start a show (it has a "From Beginning" button too).
10439
+ isShowRunning: current.mode === "present",
10440
+ canStartShow: !current.customization || pptx.isFeatureEnabled(current.customization, "presentMode"),
10837
10441
  hasSelection: current.hasSelection,
10838
10442
  isEditingText: Boolean(
10839
10443
  current.inlineEditingElementId || current.tableEditorState?.isEditing
10840
10444
  ),
10841
10445
  isDrawing: current.activeTool !== "select",
10842
- isTextInputTarget: pptx.isEditorTextInputTarget(e.target),
10843
- isControlTarget: pptx.isEditorControlTarget(e.target)
10446
+ keyboard: current.customization?.keyboard
10844
10447
  },
10845
- current.customization?.keyboard
10448
+ toEditorKeyHandlers(current)
10846
10449
  );
10847
- if (action === null) {
10848
- return;
10849
- }
10850
- e.preventDefault();
10851
- switch (action) {
10852
- case "escape":
10853
- current.onEscape();
10854
- break;
10855
- case "delete":
10856
- current.onDelete();
10857
- break;
10858
- case "undo":
10859
- current.onUndo();
10860
- break;
10861
- case "redo":
10862
- current.onRedo();
10863
- break;
10864
- case "copy":
10865
- current.onCopy();
10866
- break;
10867
- case "cut":
10868
- current.onCut();
10869
- break;
10870
- case "paste":
10871
- current.onPaste();
10872
- break;
10873
- case "duplicate":
10874
- current.onDuplicate();
10875
- break;
10876
- case "selectAll":
10877
- current.onSelectAll();
10878
- break;
10879
- case "group":
10880
- current.onGroup?.();
10881
- break;
10882
- case "ungroup":
10883
- current.onUngroup?.();
10884
- break;
10885
- case "toggleShortcuts":
10886
- current.onToggleShortcuts?.();
10887
- break;
10888
- case "find":
10889
- current.onFind?.();
10890
- break;
10891
- case "nudge":
10892
- current.onNudge(dx ?? 0, dy ?? 0);
10893
- break;
10894
- case "prevSlide":
10895
- current.onPrevSlide?.();
10896
- break;
10897
- case "nextSlide":
10898
- current.onNextSlide?.();
10899
- break;
10900
- case "alignLeft":
10901
- current.onAlignLeft?.();
10902
- break;
10903
- case "alignCenter":
10904
- current.onAlignCenter?.();
10905
- break;
10906
- case "alignRight":
10907
- current.onAlignRight?.();
10908
- break;
10909
- case "alignJustify":
10910
- current.onAlignJustify?.();
10911
- break;
10912
- case "increaseFontSize":
10913
- current.onIncreaseFontSize?.();
10914
- break;
10915
- case "decreaseFontSize":
10916
- current.onDecreaseFontSize?.();
10917
- break;
10918
- case "copyFormat":
10919
- current.onCopyFormat?.();
10920
- break;
10921
- case "pasteFormat":
10922
- current.onPasteFormat?.();
10923
- break;
10924
- case "newSlide":
10925
- current.onNewSlide?.();
10926
- break;
10927
- case "hyperlink":
10928
- current.onHyperlink?.();
10929
- break;
10930
- case "findReplace":
10931
- current.onFindReplace?.();
10932
- break;
10933
- case "clearFormatting":
10934
- current.onClearFormatting?.();
10935
- break;
10936
- case "cycleSelectionNext":
10937
- current.onCycleSelectionNext?.();
10938
- break;
10939
- case "cycleSelectionPrev":
10940
- current.onCycleSelectionPrev?.();
10941
- break;
10942
- case "pasteSpecial":
10943
- current.onPasteSpecial?.();
10944
- break;
10945
- }
10946
10450
  }, []);
10947
10451
  React17.useEffect(() => {
10948
10452
  window.addEventListener("keydown", handleKeyDown);
@@ -10951,6 +10455,43 @@ function useKeyboardShortcuts(input) {
10951
10455
  };
10952
10456
  }, [handleKeyDown]);
10953
10457
  }
10458
+ function toEditorKeyHandlers(current) {
10459
+ return {
10460
+ startShowFromBeginning: current.onStartShowFromBeginning,
10461
+ startShowFromCurrent: current.onStartShowFromCurrent,
10462
+ escape: current.onEscape,
10463
+ delete: current.onDelete,
10464
+ undo: current.onUndo,
10465
+ redo: current.onRedo,
10466
+ copy: current.onCopy,
10467
+ cut: current.onCut,
10468
+ paste: current.onPaste,
10469
+ duplicate: current.onDuplicate,
10470
+ selectAll: current.onSelectAll,
10471
+ group: current.onGroup,
10472
+ ungroup: current.onUngroup,
10473
+ toggleShortcuts: current.onToggleShortcuts,
10474
+ find: current.onFind,
10475
+ nudge: current.onNudge,
10476
+ prevSlide: current.onPrevSlide,
10477
+ nextSlide: current.onNextSlide,
10478
+ alignLeft: current.onAlignLeft,
10479
+ alignCenter: current.onAlignCenter,
10480
+ alignRight: current.onAlignRight,
10481
+ alignJustify: current.onAlignJustify,
10482
+ increaseFontSize: current.onIncreaseFontSize,
10483
+ decreaseFontSize: current.onDecreaseFontSize,
10484
+ copyFormat: current.onCopyFormat,
10485
+ pasteFormat: current.onPasteFormat,
10486
+ newSlide: current.onNewSlide,
10487
+ hyperlink: current.onHyperlink,
10488
+ findReplace: current.onFindReplace,
10489
+ clearFormatting: current.onClearFormatting,
10490
+ cycleSelectionNext: current.onCycleSelectionNext,
10491
+ cycleSelectionPrev: current.onCycleSelectionPrev,
10492
+ pasteSpecial: current.onPasteSpecial
10493
+ };
10494
+ }
10954
10495
  var CLEAR_FORMATTING_PATCH = {
10955
10496
  bold: false,
10956
10497
  italic: false,
@@ -11216,7 +10757,8 @@ function useViewerIntegration(input) {
11216
10757
  updateSlides: editorOps.ops.updateSlides,
11217
10758
  updateElementById: editorOps.ops.updateElementById,
11218
10759
  markDirty: history.markDirty,
11219
- livePatcher: state.livePatcher
10760
+ livePatcher: state.livePatcher,
10761
+ gestureRef: state.gestureControllerRef
11220
10762
  });
11221
10763
  const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = React17.useState(false);
11222
10764
  const [loadVersion, setLoadVersion] = React17.useState(0);
@@ -11664,7 +11206,7 @@ function useCollaborationWriteBack(input) {
11664
11206
  getSourceBytes: () => latest.current.getSourceBytes?.() ?? null,
11665
11207
  getSaveOptions: () => latest.current.getSaveOptions?.(),
11666
11208
  getTemplateElements: () => latest.current.templateElementsBySlideId,
11667
- mergeTemplateElements: chunkJAI42EXQ_js.buildSaveSlides,
11209
+ mergeTemplateElements: chunkJWNBTFZZ_js.buildSaveSlides,
11668
11210
  onWriteBackStatus: () => latest.current.onWriteBackStatus?.(
11669
11211
  pptx.writeBackReport(latest.current.config, created.getState())
11670
11212
  )
@@ -12223,8 +11765,8 @@ function useTouchGestures(input) {
12223
11765
  }
12224
11766
  const recognizer = pptx.createTouchGestureRecognizer({
12225
11767
  getScale: () => scaleRef.current,
12226
- minScale: chunkJAI42EXQ_js.MIN_ZOOM_SCALE,
12227
- maxScale: chunkJAI42EXQ_js.MAX_ZOOM_SCALE,
11768
+ minScale: chunkJWNBTFZZ_js.MIN_ZOOM_SCALE,
11769
+ maxScale: chunkJWNBTFZZ_js.MAX_ZOOM_SCALE,
12228
11770
  callbacks: {
12229
11771
  onPinchZoom: (newScale) => callbacksRef.current.onPinchZoom?.(newScale),
12230
11772
  onSwipe: (direction) => callbacksRef.current.onSwipe?.(direction),
@@ -12348,7 +11890,7 @@ function buildCanvasProps(input) {
12348
11890
  if (pptx.shouldConfirmExternalHyperlink(viewerOptions, url) && !window.confirm(buildHyperlinkConfirmMessage(url))) {
12349
11891
  return;
12350
11892
  }
12351
- chunkJAI42EXQ_js.safeOpenUrl(url, target);
11893
+ chunkJWNBTFZZ_js.safeOpenUrl(url, target);
12352
11894
  };
12353
11895
  const handleActionClick = (elementId, action) => {
12354
11896
  if (mode === "present") {
@@ -12363,9 +11905,9 @@ function buildCanvasProps(input) {
12363
11905
  }
12364
11906
  };
12365
11907
  const handleHyperlinkClick = (url, target) => {
12366
- if (chunkJAI42EXQ_js.isPpactionUrl(url)) {
11908
+ if (chunkJWNBTFZZ_js.isPpactionUrl(url)) {
12367
11909
  if (mode === "present") {
12368
- const parsed = chunkJAI42EXQ_js.parsePpactionUrl(url);
11910
+ const parsed = chunkJWNBTFZZ_js.parsePpactionUrl(url);
12369
11911
  if (parsed) {
12370
11912
  presentation.handlePresentationAction({
12371
11913
  action: parsed.action,
@@ -12653,6 +12195,7 @@ function buildToolbarProps(input) {
12653
12195
  onAddShape: insertHandlers.handleAddShape,
12654
12196
  onAddTable: insertHandlers.handleAddTable,
12655
12197
  onAddChart: insertHandlers.handleAddChart,
12198
+ onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
12656
12199
  onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
12657
12200
  onAddEquation: () => {
12658
12201
  dialogs.setEditingEquationOmml(null);
@@ -12792,7 +12335,7 @@ function buildToolbarProps(input) {
12792
12335
  markDirty: history.markDirty
12793
12336
  }),
12794
12337
  formatPainterActive: s.formatPainterActive,
12795
- canActivateFormatPainter: chunkJAI42EXQ_js.hasCopyableFormat(selectedElement),
12338
+ canActivateFormatPainter: chunkJWNBTFZZ_js.hasCopyableFormat(selectedElement),
12796
12339
  onToggleFormatPainter: () => s.setFormatPainterActive((p) => !p),
12797
12340
  isSelectionPaneOpen: s.isSelectionPaneOpen,
12798
12341
  onToggleSelectionPane: () => s.setIsSelectionPaneOpen((p) => !p),
@@ -13670,23 +13213,23 @@ function ColorChangedImage({
13670
13213
  className,
13671
13214
  alt
13672
13215
  }) {
13673
- const tolerance = tolerancePct ?? chunkJAI42EXQ_js.DEFAULT_COLOR_CHANGE_TOLERANCE;
13674
- const cacheKey = chunkJAI42EXQ_js.buildCacheKey(
13216
+ const tolerance = tolerancePct ?? chunkJWNBTFZZ_js.DEFAULT_COLOR_CHANGE_TOLERANCE;
13217
+ const cacheKey = chunkJWNBTFZZ_js.buildCacheKey(
13675
13218
  src,
13676
13219
  clrChange.clrFrom,
13677
13220
  clrChange.clrTo,
13678
13221
  tolerance,
13679
13222
  Boolean(clrChange.clrToTransparent)
13680
13223
  );
13681
- const cached = chunkJAI42EXQ_js.getCachedResult(cacheKey);
13224
+ const cached = chunkJWNBTFZZ_js.getCachedResult(cacheKey);
13682
13225
  const [processedSrc, setProcessedSrc] = React17.useState(cached ?? null);
13683
13226
  React17.useEffect(() => {
13684
- if (chunkJAI42EXQ_js.getCachedResult(cacheKey)) {
13685
- setProcessedSrc(chunkJAI42EXQ_js.getCachedResult(cacheKey) ?? null);
13227
+ if (chunkJWNBTFZZ_js.getCachedResult(cacheKey)) {
13228
+ setProcessedSrc(chunkJWNBTFZZ_js.getCachedResult(cacheKey) ?? null);
13686
13229
  return;
13687
13230
  }
13688
13231
  let cancelled = false;
13689
- chunkJAI42EXQ_js.applyColorChange(
13232
+ chunkJWNBTFZZ_js.applyColorChange(
13690
13233
  src,
13691
13234
  clrChange.clrFrom,
13692
13235
  clrChange.clrTo,
@@ -13694,7 +13237,7 @@ function ColorChangedImage({
13694
13237
  Boolean(clrChange.clrToTransparent)
13695
13238
  ).then((result) => {
13696
13239
  if (!cancelled) {
13697
- chunkJAI42EXQ_js.setCachedResult(cacheKey, result.dataUrl);
13240
+ chunkJWNBTFZZ_js.setCachedResult(cacheKey, result.dataUrl);
13698
13241
  setProcessedSrc(result.dataUrl);
13699
13242
  }
13700
13243
  return void 0;
@@ -13786,7 +13329,7 @@ function TiledImageLayer({
13786
13329
  cancelled = true;
13787
13330
  };
13788
13331
  }, [src]);
13789
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...chunkJAI42EXQ_js.getImageTilingStyle(element, nativeSize), ...style } });
13332
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...chunkJWNBTFZZ_js.getImageTilingStyle(element, nativeSize), ...style } });
13790
13333
  }
13791
13334
  function renderImageEffectDefinitions(element, excludeDuotone = false) {
13792
13335
  return pptx.getImageSvgFilters(element).filter((definition) => !excludeDuotone || definition.id !== `duotone-${element.id}`).map((definition) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -13855,7 +13398,7 @@ function renderImg(el, style, filter, alt, opacity) {
13855
13398
  ...filter ? { filter } : {},
13856
13399
  ...opacity !== void 0 ? { opacity } : {}
13857
13400
  };
13858
- if (chunkJAI42EXQ_js.isImageTiled(el)) {
13401
+ if (chunkJWNBTFZZ_js.isImageTiled(el)) {
13859
13402
  const tileSrc = imgSrc(el);
13860
13403
  if (!tileSrc) {
13861
13404
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-gray-500 bg-gray-100", children: "Image" });
@@ -13877,9 +13420,9 @@ function renderImg(el, style, filter, alt, opacity) {
13877
13420
  pptx$1.isImageLikeElement(el) ? el.imageEffects?.colorWash : void 0
13878
13421
  );
13879
13422
  const clrChange = "imageEffects" in el ? el.imageEffects?.clrChange : void 0;
13880
- const duotoneColors = chunkJAI42EXQ_js.getDuotoneColors(el);
13423
+ const duotoneColors = chunkJWNBTFZZ_js.getDuotoneColors(el);
13881
13424
  const useDuotoneCanvas = Boolean(duotoneColors && !clrChange);
13882
- const filterForImg = useDuotoneCanvas ? chunkJAI42EXQ_js.getImageEffectsFilter(el, { excludeDuotone: true }) : filter;
13425
+ const filterForImg = useDuotoneCanvas ? chunkJWNBTFZZ_js.getImageEffectsFilter(el, { excludeDuotone: true }) : filter;
13883
13426
  const canvasEffectStyles = {
13884
13427
  ...filterForImg ? { filter: filterForImg } : {},
13885
13428
  ...opacity !== void 0 ? { opacity } : {}
@@ -13955,10 +13498,10 @@ function SlideBackgroundImageLayer({
13955
13498
  style: { zIndex: 0 },
13956
13499
  children: renderImg(
13957
13500
  backgroundElement,
13958
- chunkJAI42EXQ_js.getImageRenderStyle(backgroundElement),
13959
- chunkJAI42EXQ_js.getImageEffectsFilter(backgroundElement),
13501
+ chunkJWNBTFZZ_js.getImageRenderStyle(backgroundElement),
13502
+ chunkJWNBTFZZ_js.getImageEffectsFilter(backgroundElement),
13960
13503
  "",
13961
- chunkJAI42EXQ_js.getImageEffectsOpacity(backgroundElement)
13504
+ chunkJWNBTFZZ_js.getImageEffectsOpacity(backgroundElement)
13962
13505
  )
13963
13506
  }
13964
13507
  );
@@ -14244,7 +13787,7 @@ function ChartElementView({
14244
13787
  pptx.getBarFacePicturePixelSampleVersion
14245
13788
  );
14246
13789
  const viewModel = React17.useMemo(() => {
14247
- return canEdit ? chunkJAI42EXQ_js.buildReactChartViewModel(element) : null;
13790
+ return canEdit ? chunkJWNBTFZZ_js.buildReactChartViewModel(element) : null;
14248
13791
  }, [canEdit, element, barFacePictureSampleVersion]);
14249
13792
  React17.useEffect(pptx.ensureChartInteractionStyles, []);
14250
13793
  React17.useEffect(() => {
@@ -14349,9 +13892,9 @@ function ChartElementView({
14349
13892
  textStyle: animationState?.textStyle,
14350
13893
  onSelect: chart3D.onSelect,
14351
13894
  onDrag: chart3D.onDrag,
14352
- children: chunkJAI42EXQ_js.renderChartElement(renderedElement, (key) => t(key))
13895
+ children: chunkJWNBTFZZ_js.renderChartElement(renderedElement, (key) => t(key))
14353
13896
  }
14354
- ) : chunkJAI42EXQ_js.renderChartElement(renderedElement, (key) => t(key)),
13897
+ ) : chunkJWNBTFZZ_js.renderChartElement(renderedElement, (key) => t(key)),
14355
13898
  dragValue !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1 right-1 z-10 rounded bg-primary/90 px-1.5 py-0.5 text-[10px] font-medium text-white pointer-events-none", children: pptx.formatAxisValue(dragValue) }),
14356
13899
  titleDraft !== null && /* @__PURE__ */ jsxRuntime.jsx(
14357
13900
  "input",
@@ -14512,6 +14055,50 @@ var EDGE_HANDLES = [
14512
14055
  sizeClass: "w-2 h-5 max-md:w-3 max-md:h-8 rounded-sm"
14513
14056
  }
14514
14057
  ];
14058
+ var wholeDegrees = (deg) => Math.round((deg % 360 + 360) % 360) % 360;
14059
+ function startRotateKnobGesture(options) {
14060
+ const { button, elementId, rotation, onRotate } = options;
14061
+ const scope = button.closest("[data-pptx-viewport]") ?? document;
14062
+ const wrapper = scope.querySelector(pptx.elementIdSelector(elementId));
14063
+ if (!wrapper) {
14064
+ return;
14065
+ }
14066
+ const rect = wrapper.getBoundingClientRect();
14067
+ const base = options.nonRotationTransform ? ` ${options.nonRotationTransform}` : "";
14068
+ const paint = (deg) => {
14069
+ const transform = `rotate(${deg}deg)${base}`;
14070
+ wrapper.style.transform = transform;
14071
+ syncSelectionHandleOverlay(wrapper, elementId, { transform });
14072
+ };
14073
+ if (options.pointerId !== void 0) {
14074
+ button.setPointerCapture?.(options.pointerId);
14075
+ }
14076
+ const gesture = pptx.createGestureController({
14077
+ getScale: () => 1,
14078
+ getElementBox: () => ({
14079
+ x: rect.left,
14080
+ y: rect.top,
14081
+ width: rect.width,
14082
+ height: rect.height,
14083
+ rotation
14084
+ }),
14085
+ getSiblings: () => [],
14086
+ getStageOrigin: () => ({ left: 0, top: 0 }),
14087
+ onStart: () => void 0,
14088
+ onPreview: (transform) => paint(wholeDegrees(transform.rotation)),
14089
+ onEnd: (transform) => {
14090
+ const deg = transform ? wholeDegrees(transform.rotation) : rotation;
14091
+ if (deg !== rotation) {
14092
+ onRotate?.(elementId, deg);
14093
+ }
14094
+ }
14095
+ });
14096
+ gesture.begin("rotate", elementId, {
14097
+ clientX: options.pointer.clientX,
14098
+ clientY: options.pointer.clientY,
14099
+ shiftKey: false
14100
+ });
14101
+ }
14515
14102
  var appearance = { fill: "var(--color-primary)", borderColor: "#ffffff" };
14516
14103
  var cornerSize = "var(--pptx-react-corner-default, 12px)";
14517
14104
  var edgeLength = "var(--pptx-react-edge-length-default, 20px)";
@@ -14625,50 +14212,15 @@ function ResizeHandles({
14625
14212
  e.currentTarget.setPointerCapture?.(e.pointerId);
14626
14213
  onResizePointerDown(elementId, e, handle);
14627
14214
  };
14628
- const startRotate = (btn, pointer, pointerId) => {
14629
- const scope = btn.closest("[data-pptx-viewport]") ?? document;
14630
- const wrapper = scope.querySelector(pptx.elementIdSelector(elementId));
14631
- if (!wrapper) {
14632
- return;
14633
- }
14634
- const rect = wrapper.getBoundingClientRect();
14635
- const cx = rect.left + rect.width / 2;
14636
- const cy = rect.top + rect.height / 2;
14637
- const base = nonRotationTransform ? ` ${nonRotationTransform}` : "";
14638
- const startDeg = rotation ?? 0;
14639
- const dragRotation = pptx.createRotationDrag(
14640
- { x: cx, y: cy },
14641
- { x: pointer.clientX, y: pointer.clientY },
14642
- startDeg
14643
- );
14644
- let last = startDeg;
14645
- if (pointerId !== void 0) {
14646
- btn.setPointerCapture?.(pointerId);
14647
- }
14648
- const apply = (clientX, clientY, shift) => {
14649
- let deg = dragRotation({ x: clientX, y: clientY });
14650
- if (shift) {
14651
- deg = Math.round(deg / 15) * 15;
14652
- }
14653
- deg = Math.round((deg % 360 + 360) % 360);
14654
- last = deg;
14655
- const transform = `rotate(${deg}deg)${base}`;
14656
- wrapper.style.transform = transform;
14657
- syncSelectionHandleOverlay(wrapper, elementId, { transform });
14658
- };
14659
- const onPointerMove = (ev) => apply(ev.clientX, ev.clientY, ev.shiftKey);
14660
- const end = () => {
14661
- window.removeEventListener("pointermove", onPointerMove);
14662
- window.removeEventListener("pointerup", end);
14663
- window.removeEventListener("pointercancel", end);
14664
- if (last !== startDeg) {
14665
- onRotate?.(elementId, last);
14666
- }
14667
- };
14668
- window.addEventListener("pointermove", onPointerMove);
14669
- window.addEventListener("pointerup", end);
14670
- window.addEventListener("pointercancel", end);
14671
- };
14215
+ const startRotate = (button, pointer) => startRotateKnobGesture({
14216
+ button,
14217
+ elementId,
14218
+ pointer,
14219
+ pointerId: pointer.pointerId,
14220
+ rotation: rotation ?? 0,
14221
+ ...nonRotationTransform ? { nonRotationTransform } : {},
14222
+ ...onRotate ? { onRotate } : {}
14223
+ });
14672
14224
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14673
14225
  [...CORNER_HANDLES, ...EDGE_HANDLES].map(({ handle, posClass, cursor }) => {
14674
14226
  const corner = handle.length === 2;
@@ -14681,7 +14233,7 @@ function ResizeHandles({
14681
14233
  "aria-label": t("pptx.selectionOverlay.resize", { handle }),
14682
14234
  "data-pptx-handle-kind": "resize",
14683
14235
  "data-pptx-compact": true,
14684
- className: chunkJAI42EXQ_js.cn(
14236
+ className: chunkJWNBTFZZ_js.cn(
14685
14237
  "absolute z-10 group border-0 bg-transparent p-0",
14686
14238
  RESIZE_DEFAULT_CLASSES,
14687
14239
  posClass,
@@ -14707,7 +14259,7 @@ function ResizeHandles({
14707
14259
  "div",
14708
14260
  {
14709
14261
  "data-pptx-handle-hit": true,
14710
- className: chunkJAI42EXQ_js.cn(
14262
+ className: chunkJWNBTFZZ_js.cn(
14711
14263
  "absolute -inset-px pointer-events-auto [--pptx-handle-hit-inset:-1px]",
14712
14264
  corner ? "max-md:-inset-1.5 max-md:[--pptx-handle-hit-inset:-6px]" : "max-md:-inset-2 max-md:[--pptx-handle-hit-inset:-8px]"
14713
14265
  ),
@@ -14728,7 +14280,7 @@ function ResizeHandles({
14728
14280
  "aria-label": t("pptx.selectionOverlay.rotate"),
14729
14281
  "data-pptx-handle-kind": "rotate",
14730
14282
  "data-pptx-compact": true,
14731
- className: chunkJAI42EXQ_js.cn(
14283
+ className: chunkJWNBTFZZ_js.cn(
14732
14284
  "absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2 z-20 border-0 bg-transparent p-0 cursor-grab active:cursor-grabbing",
14733
14285
  ROTATE_DEFAULT_CLASSES
14734
14286
  ),
@@ -14739,7 +14291,7 @@ function ResizeHandles({
14739
14291
  },
14740
14292
  onPointerDown: (e) => {
14741
14293
  e.stopPropagation();
14742
- startRotate(e.currentTarget, e, e.pointerId);
14294
+ startRotate(e.currentTarget, e);
14743
14295
  },
14744
14296
  onMouseDown: (e) => {
14745
14297
  e.stopPropagation();
@@ -14805,10 +14357,10 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14805
14357
  const svgHeight = Math.max(el.height, 1);
14806
14358
  const ss = shapeEl?.shapeStyle;
14807
14359
  const strokeWidth = Math.max(0, ss?.strokeWidth ?? 2);
14808
- const strokeColor = chunkJAI42EXQ_js.normalizeHexColor(ss?.strokeColor, chunkJAI42EXQ_js.DEFAULT_STROKE_COLOR);
14809
- const strokePaint = chunkJAI42EXQ_js.colorWithOpacity(strokeColor, ss?.strokeOpacity);
14810
- const dashType = chunkJAI42EXQ_js.normalizeStrokeDashType(ss?.strokeDash);
14811
- const dashArray = chunkJAI42EXQ_js.getSvgStrokeDasharray(
14360
+ const strokeColor = chunkJWNBTFZZ_js.normalizeHexColor(ss?.strokeColor, chunkJWNBTFZZ_js.DEFAULT_STROKE_COLOR);
14361
+ const strokePaint = chunkJWNBTFZZ_js.colorWithOpacity(strokeColor, ss?.strokeOpacity);
14362
+ const dashType = chunkJWNBTFZZ_js.normalizeStrokeDashType(ss?.strokeDash);
14363
+ const dashArray = chunkJWNBTFZZ_js.getSvgStrokeDasharray(
14812
14364
  dashType,
14813
14365
  Math.max(strokeWidth, 1),
14814
14366
  ss?.customDashSegments
@@ -14819,14 +14371,14 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14819
14371
  const markerSeed = el.id.replace(/[^a-zA-Z0-9_-]/gu, "_");
14820
14372
  const startMarkerId = `${markerSeed}-sel-start`;
14821
14373
  const endMarkerId = `${markerSeed}-sel-end`;
14822
- const compoundOffsets = chunkJAI42EXQ_js.getCompoundLineOffsets(compoundLine, strokeWidth);
14823
- const compoundWidths = chunkJAI42EXQ_js.getCompoundLineWidths(compoundLine, strokeWidth);
14374
+ const compoundOffsets = chunkJWNBTFZZ_js.getCompoundLineOffsets(compoundLine, strokeWidth);
14375
+ const compoundWidths = chunkJWNBTFZZ_js.getCompoundLineWidths(compoundLine, strokeWidth);
14824
14376
  const strokeCap = pptx.svgLineCap(ss?.lineCap);
14825
14377
  const textEl = pptx$1.hasTextProperties(el) ? el : void 0;
14826
14378
  const connectorText = textEl?.text?.trim() ?? "";
14827
14379
  const connectorTextSegments = textEl?.textSegments;
14828
14380
  const connectorTextStyle = textEl?.textStyle;
14829
- const pathGeometry = shapeEl ? chunkJAI42EXQ_js.getConnectorPathGeometry(shapeEl) : {
14381
+ const pathGeometry = shapeEl ? chunkJWNBTFZZ_js.getConnectorPathGeometry(shapeEl) : {
14830
14382
  pathData: `M 0 0 L ${viewWidth} ${viewHeight}`,
14831
14383
  startX: 0,
14832
14384
  startY: 0,
@@ -14835,16 +14387,16 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14835
14387
  };
14836
14388
  const hitTargetWidth = Math.max(strokeWidth * 3, 14);
14837
14389
  const selColor = selClr === "blue-400" ? "#60a5fa" : "#3b82f6";
14838
- const lineShadow = chunkJAI42EXQ_js.buildLineShadowCss(el);
14839
- const lineGlow = chunkJAI42EXQ_js.buildLineGlowFilter(el);
14390
+ const lineShadow = chunkJWNBTFZZ_js.buildLineShadowCss(el);
14391
+ const lineGlow = chunkJWNBTFZZ_js.buildLineGlowFilter(el);
14840
14392
  return /* @__PURE__ */ jsxRuntime.jsxs(
14841
14393
  "div",
14842
14394
  {
14843
14395
  "data-pptx-element": "true",
14844
14396
  "data-element-id": el.id,
14845
- role: chunkJAI42EXQ_js.getAriaRole(el, { actionable: false }),
14846
- "aria-label": chunkJAI42EXQ_js.getAriaLabel(el),
14847
- "aria-roledescription": chunkJAI42EXQ_js.getAriaRoleDescription(el),
14397
+ role: chunkJWNBTFZZ_js.getAriaRole(el, { actionable: false }),
14398
+ "aria-label": chunkJWNBTFZZ_js.getAriaLabel(el),
14399
+ "aria-roledescription": chunkJWNBTFZZ_js.getAriaRoleDescription(el),
14848
14400
  "aria-selected": isSelected ? true : void 0,
14849
14401
  className: "absolute",
14850
14402
  style: {
@@ -14877,14 +14429,14 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14877
14429
  style: { overflow: "visible", pointerEvents: "none" },
14878
14430
  children: [
14879
14431
  /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
14880
- chunkJAI42EXQ_js.renderConnectorMarker(
14432
+ chunkJWNBTFZZ_js.renderConnectorMarker(
14881
14433
  startMarkerId,
14882
14434
  startArrow,
14883
14435
  strokePaint,
14884
14436
  ss?.connectorStartArrowWidth,
14885
14437
  ss?.connectorStartArrowLength
14886
14438
  ),
14887
- chunkJAI42EXQ_js.renderConnectorMarker(
14439
+ chunkJWNBTFZZ_js.renderConnectorMarker(
14888
14440
  endMarkerId,
14889
14441
  endArrow,
14890
14442
  strokePaint,
@@ -15093,14 +14645,14 @@ function getElementInteractionProps({
15093
14645
  };
15094
14646
  }
15095
14647
  function renderDagDuotoneFilterForElement(el) {
15096
- if (!chunkJAI42EXQ_js.hasDagDuotoneEffect(el)) {
14648
+ if (!chunkJWNBTFZZ_js.hasDagDuotoneEffect(el)) {
15097
14649
  return null;
15098
14650
  }
15099
14651
  const duotone = el.shapeStyle?.dagDuotone;
15100
14652
  if (!duotone) {
15101
14653
  return null;
15102
14654
  }
15103
- return chunkJAI42EXQ_js.renderDagDuotoneSvgFilter(el.id, duotone.color1, duotone.color2);
14655
+ return chunkJWNBTFZZ_js.renderDagDuotoneSvgFilter(el.id, duotone.color1, duotone.color2);
15104
14656
  }
15105
14657
  function getContainerStyle({
15106
14658
  el,
@@ -15127,10 +14679,10 @@ function getContainerStyle({
15127
14679
  top: isFullscreenMedia ? fs.top : el.y,
15128
14680
  width: isFullscreenMedia ? fs.width : painted.width,
15129
14681
  ...heightStyle,
15130
- transform: isFullscreenMedia ? fs.transform : chunkJAI42EXQ_js.getElementTransform(el),
14682
+ transform: isFullscreenMedia ? fs.transform : chunkJWNBTFZZ_js.getElementTransform(el),
15131
14683
  transformOrigin: "center",
15132
14684
  overflow: overflowValue,
15133
- clipPath: isPicture ? void 0 : isImg && !has3DExtrusion ? chunkJAI42EXQ_js.getCropShapeClipPath(el) : void 0,
14685
+ clipPath: isPicture ? void 0 : isImg && !has3DExtrusion ? chunkJWNBTFZZ_js.getCropShapeClipPath(el) : void 0,
15134
14686
  zIndex: isFullscreenMedia ? fs.zIndex : zIndex,
15135
14687
  visibility: animationState?.visible === false ? "hidden" : "visible",
15136
14688
  animation: animationState?.cssAnimation,
@@ -15167,9 +14719,9 @@ function getContainerStyle({
15167
14719
  function shapeParams(element) {
15168
14720
  const style = pptx$1.hasShapeProperties(element) ? element.shapeStyle : void 0;
15169
14721
  const strokeWidth = pptx.paintedStrokeWidth(style);
15170
- const strokeColor = chunkJAI42EXQ_js.normalizeHexColor(style?.strokeColor, chunkJAI42EXQ_js.DEFAULT_STROKE_COLOR);
15171
- const fillColor = chunkJAI42EXQ_js.normalizeHexColor(style?.fillColor, chunkJAI42EXQ_js.DEFAULT_FILL_COLOR);
15172
- const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkJAI42EXQ_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
14722
+ const strokeColor = chunkJWNBTFZZ_js.normalizeHexColor(style?.strokeColor, chunkJWNBTFZZ_js.DEFAULT_STROKE_COLOR);
14723
+ const fillColor = chunkJWNBTFZZ_js.normalizeHexColor(style?.fillColor, chunkJWNBTFZZ_js.DEFAULT_FILL_COLOR);
14724
+ const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkJWNBTFZZ_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
15173
14725
  return { hf: hasFill, fc: fillColor, sw: strokeWidth, sc: strokeColor };
15174
14726
  }
15175
14727
  var Extrusion3DOverlayMemo = /* @__PURE__ */ React17__default.default.memo(
@@ -15277,7 +14829,7 @@ function ShapeEffectOverlay({
15277
14829
  const fillOverlayStyle = overlay ? {
15278
14830
  position: "absolute",
15279
14831
  inset: 0,
15280
- ...pptx$1.isImageLikeElement(element) ? chunkJAI42EXQ_js.getImageSurfaceMaskStyle(element) : {},
14832
+ ...pptx$1.isImageLikeElement(element) ? chunkJWNBTFZZ_js.getImageSurfaceMaskStyle(element) : {},
15281
14833
  background: overlay.color,
15282
14834
  mixBlendMode: overlay.blendMode,
15283
14835
  pointerEvents: "none"
@@ -15484,10 +15036,10 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15484
15036
  const backgroundAnimationState = pptx.getBackgroundAnimationState(el, presentationElementStates);
15485
15037
  const effectPlacement = pptx.getShapeEffectLayerPlacement(el);
15486
15038
  const visualAnimationState = backgroundAnimationState ?? animationState;
15487
- const isTxt = chunkJAI42EXQ_js.isEditableTextElement(el) && allow.textEditable;
15039
+ const isTxt = chunkJWNBTFZZ_js.isEditableTextElement(el) && allow.textEditable;
15488
15040
  const txtSE = pptx$1.hasTextProperties(el) ? el.textStyle : void 0;
15489
15041
  const textStyleOverrideCss = pptx.buildTextStyleOverrideCss(el.id, visualAnimationState?.textStyle);
15490
- const ss = chunkJAI42EXQ_js.getShapeVisualStyle(
15042
+ const ss = chunkJWNBTFZZ_js.getShapeVisualStyle(
15491
15043
  el,
15492
15044
  hf,
15493
15045
  fc,
@@ -15496,9 +15048,9 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15496
15048
  visualAnimationState?.animatesFill,
15497
15049
  visualAnimationState?.animatesStroke
15498
15050
  );
15499
- const ts = chunkJAI42EXQ_js.getTextStyleForElement(el, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR);
15051
+ const ts = chunkJWNBTFZZ_js.getTextStyleForElement(el, chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR);
15500
15052
  const isImg = el.type === "picture" || el.type === "image";
15501
- const vs = chunkJAI42EXQ_js.renderVectorShape(
15053
+ const vs = chunkJWNBTFZZ_js.renderVectorShape(
15502
15054
  el,
15503
15055
  isImg ? false : hf,
15504
15056
  fc,
@@ -15508,10 +15060,10 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15508
15060
  visualAnimationState?.animatesStroke
15509
15061
  );
15510
15062
  const isModel3D = el.type === "model3d";
15511
- const isConn = chunkJAI42EXQ_js.isConnectorOrLineElement(el);
15063
+ const isConn = chunkJWNBTFZZ_js.isConnectorOrLineElement(el);
15512
15064
  const shapeStyle3d = pptx$1.hasShapeProperties(el) ? el.shapeStyle : void 0;
15513
15065
  const extrusionData = React17.useMemo(
15514
- () => chunkJAI42EXQ_js.build3DExtrusionData(shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height),
15066
+ () => chunkJWNBTFZZ_js.build3DExtrusionData(shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height),
15515
15067
  [shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height]
15516
15068
  );
15517
15069
  const actionAffordance = useActionAffordance(el, canInteract);
@@ -15601,7 +15153,7 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15601
15153
  "aria-hidden": aria.hidden ? true : void 0,
15602
15154
  "aria-selected": isSelected ? true : void 0,
15603
15155
  tabIndex: isFocusable ? 0 : -1,
15604
- className: chunkJAI42EXQ_js.cn(
15156
+ className: chunkJWNBTFZZ_js.cn(
15605
15157
  "absolute",
15606
15158
  "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500",
15607
15159
  cur,
@@ -15674,9 +15226,9 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15674
15226
  txtSE,
15675
15227
  txtS: ts,
15676
15228
  vecShape: backgroundAnimationState && !isImg ? null : vs,
15677
- imgStyle: chunkJAI42EXQ_js.getImageRenderStyle(el),
15678
- imgFilter: chunkJAI42EXQ_js.getImageEffectsFilter(el),
15679
- imgOpacity: chunkJAI42EXQ_js.getImageEffectsOpacity(el),
15229
+ imgStyle: chunkJWNBTFZZ_js.getImageRenderStyle(el),
15230
+ imgFilter: chunkJWNBTFZZ_js.getImageEffectsFilter(el),
15231
+ imgOpacity: chunkJWNBTFZZ_js.getImageEffectsOpacity(el),
15680
15232
  imgAlt: imageAltText,
15681
15233
  isTxtEl: isTxt,
15682
15234
  media: mediaDataUrls,
@@ -15813,10 +15365,10 @@ function renderStrokeView(view, pressureSensitive, replayStyle, key) {
15813
15365
  }
15814
15366
  function renderInk(el, options) {
15815
15367
  const replay = options?.replay ?? false;
15816
- const strokes = chunkJAI42EXQ_js.buildInkGroupStrokes(el, { color: "#000", width: 3 });
15368
+ const strokes = chunkJWNBTFZZ_js.buildInkGroupStrokes(el, { color: "#000", width: 3 });
15817
15369
  strokes.some((s) => s.circles || s.nibMarks);
15818
15370
  const pressureSensitive = options?.pressureSensitive;
15819
- const replayStyles = replay ? chunkJAI42EXQ_js.getInkReplayStyles(el, options?.replayConfig) : null;
15371
+ const replayStyles = replay ? chunkJWNBTFZZ_js.getInkReplayStyles(el, options?.replayConfig) : null;
15820
15372
  return /* @__PURE__ */ jsxRuntime.jsxs(
15821
15373
  "svg",
15822
15374
  {
@@ -15824,7 +15376,7 @@ function renderInk(el, options) {
15824
15376
  viewBox: `0 0 ${Math.max(el.width, 1)} ${Math.max(el.height, 1)}`,
15825
15377
  preserveAspectRatio: "none",
15826
15378
  children: [
15827
- replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJAI42EXQ_js.INK_REPLAY_KEYFRAMES }),
15379
+ replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJWNBTFZZ_js.INK_REPLAY_KEYFRAMES }),
15828
15380
  strokes.map(
15829
15381
  (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-ink-${i}`)
15830
15382
  )
@@ -15835,7 +15387,7 @@ function renderInk(el, options) {
15835
15387
  function renderGroup(children, parentGroupFill) {
15836
15388
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full h-full pointer-events-none", children: pptx.filterRenderedElements(children).map((c, childIndex) => {
15837
15389
  const { hf, fc, sw, sc } = shapeParams(c);
15838
- const baseSs = chunkJAI42EXQ_js.getShapeVisualStyle(c, hf, fc, sw, sc);
15390
+ const baseSs = chunkJWNBTFZZ_js.getShapeVisualStyle(c, hf, fc, sw, sc);
15839
15391
  const inheritedFill = pptx.resolveGroupChildFill(c, parentGroupFill);
15840
15392
  const ss = inheritedFill ? {
15841
15393
  ...baseSs,
@@ -15846,9 +15398,9 @@ function renderGroup(children, parentGroupFill) {
15846
15398
  backgroundPosition: inheritedFill.backgroundPosition
15847
15399
  } : baseSs;
15848
15400
  const isI = c.type === "picture" || c.type === "image";
15849
- const vs = chunkJAI42EXQ_js.renderVectorShape(c, isI ? false : hf, fc, sw, sc);
15850
- const ts = chunkJAI42EXQ_js.getTextStyleForElement(c, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR);
15851
- const isTxt = chunkJAI42EXQ_js.isEditableTextElement(c);
15401
+ const vs = chunkJWNBTFZZ_js.renderVectorShape(c, isI ? false : hf, fc, sw, sc);
15402
+ const ts = chunkJWNBTFZZ_js.getTextStyleForElement(c, chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR);
15403
+ const isTxt = chunkJWNBTFZZ_js.isEditableTextElement(c);
15852
15404
  return /* @__PURE__ */ jsxRuntime.jsxs(
15853
15405
  "div",
15854
15406
  {
@@ -15857,9 +15409,9 @@ function renderGroup(children, parentGroupFill) {
15857
15409
  style: {
15858
15410
  left: c.x,
15859
15411
  top: c.y,
15860
- width: Math.max(c.width, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE),
15861
- height: Math.max(c.height, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE),
15862
- transform: chunkJAI42EXQ_js.getElementTransform(c),
15412
+ width: Math.max(c.width, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE),
15413
+ height: Math.max(c.height, chunkJWNBTFZZ_js.MIN_ELEMENT_SIZE),
15414
+ transform: chunkJWNBTFZZ_js.getElementTransform(c),
15863
15415
  transformOrigin: "center",
15864
15416
  ...ss,
15865
15417
  ...isI ? {
@@ -15884,8 +15436,8 @@ function renderGroup(children, parentGroupFill) {
15884
15436
  // A nested group: recurse, chaining the inherited fill so a
15885
15437
  // `grpFill` shape under a fill-less sub-group still paints.
15886
15438
  renderGroup(c.children, pptx.getGroupChildParentFill(c, parentGroupFill))
15887
- ) : isI && ("svgData" in c && c.svgData || "imageData" in c && c.imageData) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkJAI42EXQ_js.getImageSurfaceStyle(c), children: [
15888
- chunkJAI42EXQ_js.isImageTiled(c) ? /* @__PURE__ */ jsxRuntime.jsx(
15439
+ ) : isI && ("svgData" in c && c.svgData || "imageData" in c && c.imageData) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkJWNBTFZZ_js.getImageSurfaceStyle(c), children: [
15440
+ chunkJWNBTFZZ_js.isImageTiled(c) ? /* @__PURE__ */ jsxRuntime.jsx(
15889
15441
  TiledImageLayer,
15890
15442
  {
15891
15443
  element: c,
@@ -15898,7 +15450,7 @@ function renderGroup(children, parentGroupFill) {
15898
15450
  src: "svgData" in c && c.svgData ? c.svgData : c.imageData,
15899
15451
  alt: i18n.translationsEn["pptx.ink.groupChildAlt"],
15900
15452
  className: "pointer-events-none select-none",
15901
- style: chunkJAI42EXQ_js.getImageRenderStyle(c),
15453
+ style: chunkJWNBTFZZ_js.getImageRenderStyle(c),
15902
15454
  draggable: false
15903
15455
  }
15904
15456
  ),
@@ -15910,7 +15462,7 @@ function renderGroup(children, parentGroupFill) {
15910
15462
  {
15911
15463
  className: "relative z-10 w-full h-full pointer-events-none whitespace-pre-wrap break-words leading-[1.3]",
15912
15464
  style: ts,
15913
- children: chunkJAI42EXQ_js.renderTextSegments(c, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR)
15465
+ children: chunkJWNBTFZZ_js.renderTextSegments(c, chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR)
15914
15466
  }
15915
15467
  ) : null
15916
15468
  ] })
@@ -15924,8 +15476,8 @@ function renderContentPart(el, options) {
15924
15476
  if (el.inkStrokes && el.inkStrokes.length > 0) {
15925
15477
  const replay = options?.replay ?? false;
15926
15478
  const pressureSensitive = options?.pressureSensitive ?? true;
15927
- const strokes = chunkJAI42EXQ_js.buildContentPartStrokes(el);
15928
- const replayStyles = replay ? chunkJAI42EXQ_js.getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
15479
+ const strokes = chunkJWNBTFZZ_js.buildContentPartStrokes(el);
15480
+ const replayStyles = replay ? chunkJWNBTFZZ_js.getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
15929
15481
  return /* @__PURE__ */ jsxRuntime.jsxs(
15930
15482
  "svg",
15931
15483
  {
@@ -15933,7 +15485,7 @@ function renderContentPart(el, options) {
15933
15485
  viewBox: `0 0 ${Math.max(el.width, 1)} ${Math.max(el.height, 1)}`,
15934
15486
  preserveAspectRatio: "none",
15935
15487
  children: [
15936
- replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJAI42EXQ_js.INK_REPLAY_KEYFRAMES }),
15488
+ replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJWNBTFZZ_js.INK_REPLAY_KEYFRAMES }),
15937
15489
  strokes.map(
15938
15490
  (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-cp-ink-${i}`)
15939
15491
  )
@@ -16160,9 +15712,9 @@ function useInlineListEditor(element, rootRef, onChange, onModelReplacement) {
16160
15712
  collaboration: connected,
16161
15713
  model: pptx.createInlineListModelObserver(element),
16162
15714
  activationSelection,
16163
- children: seed && !connected ? chunkJAI42EXQ_js.renderTextSegments(
15715
+ children: seed && !connected ? chunkJWNBTFZZ_js.renderTextSegments(
16164
15716
  element,
16165
- chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
15717
+ chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR,
16166
15718
  void 0,
16167
15719
  void 0,
16168
15720
  void 0,
@@ -16398,8 +15950,8 @@ function InlineTextEditor({
16398
15950
  pending.endOffset
16399
15951
  );
16400
15952
  });
16401
- const warpStyle = chunkJAI42EXQ_js.getTextWarpStyle(textStyleRaw);
16402
- const compensationTransform = chunkJAI42EXQ_js.getTextCompensationTransform(element);
15953
+ const warpStyle = chunkJWNBTFZZ_js.getTextWarpStyle(textStyleRaw);
15954
+ const compensationTransform = chunkJWNBTFZZ_js.getTextCompensationTransform(element);
16403
15955
  const warpTransform = warpStyle?.transform;
16404
15956
  const mergedTransform = [compensationTransform, warpTransform].filter(Boolean).join(" ") || void 0;
16405
15957
  const wrapperStyle = {
@@ -16487,7 +16039,7 @@ function InlineTextEditor({
16487
16039
  const text = e.clipboardData.getData("text/plain");
16488
16040
  document.execCommand("insertText", false, text);
16489
16041
  },
16490
- children: list.seed ? list.children : seed.hasRichSegments ? chunkJAI42EXQ_js.renderTextSegments(element, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR) : seed.initialText
16042
+ children: list.seed ? list.children : seed.hasRichSegments ? chunkJWNBTFZZ_js.renderTextSegments(element, chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR) : seed.initialText
16491
16043
  },
16492
16044
  list.seed?.paragraphs[0].token ?? "plain"
16493
16045
  );
@@ -17634,7 +17186,7 @@ function groupIntoParagraphs(element, fieldContext) {
17634
17186
  element,
17635
17187
  fieldContext ? (seg) => {
17636
17188
  if (seg.fieldType) {
17637
- const substituted = chunkJAI42EXQ_js.substituteFieldText(
17189
+ const substituted = chunkJWNBTFZZ_js.substituteFieldText(
17638
17190
  seg.text,
17639
17191
  seg.fieldType,
17640
17192
  fieldContext,
@@ -17669,13 +17221,13 @@ function getSegmentTspanProps(segment, element, fallbackColor) {
17669
17221
  if (s.strikethrough) {
17670
17222
  decos.push("line-through");
17671
17223
  }
17672
- const fill = s.hyperlink ? chunkJAI42EXQ_js.normalizeHexColor(s.color || element.textStyle?.color, chunkJAI42EXQ_js.HYPERLINK_COLOR) : chunkJAI42EXQ_js.normalizeHexColor(s.color || element.textStyle?.color, fallbackColor);
17224
+ const fill = s.hyperlink ? chunkJWNBTFZZ_js.normalizeHexColor(s.color || element.textStyle?.color, chunkJWNBTFZZ_js.HYPERLINK_COLOR) : chunkJWNBTFZZ_js.normalizeHexColor(s.color || element.textStyle?.color, fallbackColor);
17673
17225
  return {
17674
17226
  fill,
17675
- fontSize: s.fontSize ?? element.textStyle?.fontSize ?? chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE,
17227
+ fontSize: s.fontSize ?? element.textStyle?.fontSize ?? chunkJWNBTFZZ_js.DEFAULT_TEXT_FONT_SIZE,
17676
17228
  fontWeight: pptx.resolveFontWeight(s.fontFamily || element.textStyle?.fontFamily, s.bold),
17677
17229
  fontStyle: pptx.resolveFontItalic(s.fontFamily || element.textStyle?.fontFamily, s.italic) ? "italic" : void 0,
17678
- fontFamily: s.fontFamily || element.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(s.fontFamily || element.textStyle?.fontFamily || "") : chunkJAI42EXQ_js.DEFAULT_FONT_FAMILY,
17230
+ fontFamily: s.fontFamily || element.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(s.fontFamily || element.textStyle?.fontFamily || "") : chunkJWNBTFZZ_js.DEFAULT_FONT_FAMILY,
17679
17231
  textDecoration: decos.length > 0 ? decos.join(" ") : void 0
17680
17232
  };
17681
17233
  }
@@ -17683,8 +17235,8 @@ function resolveSegmentFont(segment, element) {
17683
17235
  const s = segment.style || {};
17684
17236
  const family = s.fontFamily || element.textStyle?.fontFamily;
17685
17237
  return {
17686
- fontFamily: family ? pptx$1.getSubstituteFontFamily(family) : chunkJAI42EXQ_js.DEFAULT_FONT_FAMILY,
17687
- fontSizePx: s.fontSize ?? element.textStyle?.fontSize ?? chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE,
17238
+ fontFamily: family ? pptx$1.getSubstituteFontFamily(family) : chunkJWNBTFZZ_js.DEFAULT_FONT_FAMILY,
17239
+ fontSizePx: s.fontSize ?? element.textStyle?.fontSize ?? chunkJWNBTFZZ_js.DEFAULT_TEXT_FONT_SIZE,
17688
17240
  bold: s.bold ?? element.textStyle?.bold,
17689
17241
  italic: s.italic ?? element.textStyle?.italic
17690
17242
  };
@@ -17768,9 +17320,9 @@ function WarpedText({
17768
17320
  const warpAdj2 = textEl.textStyle?.textWarpAdj2;
17769
17321
  const align = textEl.textStyle?.align ?? "center";
17770
17322
  const { startOffset, textAnchor } = getAlignmentProps(align);
17771
- const baseFontSize = textEl.textStyle?.fontSize ?? chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE;
17772
- const baseFontFamily = textEl.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(textEl.textStyle.fontFamily) : chunkJAI42EXQ_js.DEFAULT_FONT_FAMILY;
17773
- const baseFill = chunkJAI42EXQ_js.normalizeHexColor(textEl.textStyle?.color, fallbackColor);
17323
+ const baseFontSize = textEl.textStyle?.fontSize ?? chunkJWNBTFZZ_js.DEFAULT_TEXT_FONT_SIZE;
17324
+ const baseFontFamily = textEl.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(textEl.textStyle.fontFamily) : chunkJWNBTFZZ_js.DEFAULT_FONT_FAMILY;
17325
+ const baseFill = chunkJWNBTFZZ_js.normalizeHexColor(textEl.textStyle?.color, fallbackColor);
17774
17326
  if (pptx.hasGlyphEnvelope(preset)) {
17775
17327
  const perLine = pptx.buildGlyphEnvelopeBlock(
17776
17328
  preset,
@@ -17872,7 +17424,7 @@ function WarpedText({
17872
17424
  var GLYPH_BY_SHAPE = /* @__PURE__ */ buildGlyphByShape();
17873
17425
  function buildGlyphByShape() {
17874
17426
  const glyphs = Object.fromEntries(
17875
- chunkJAI42EXQ_js.ACTION_BUTTON_PRESETS.map((p) => [p.shapeType, p.iconPath])
17427
+ chunkJWNBTFZZ_js.ACTION_BUTTON_PRESETS.map((p) => [p.shapeType, p.iconPath])
17876
17428
  );
17877
17429
  glyphs["actionButtonForwardOrNext"] = glyphs["actionButtonForwardNext"];
17878
17430
  glyphs["actionButtonBackOrPrevious"] = glyphs["actionButtonBackPrevious"];
@@ -17946,9 +17498,9 @@ function renderTextElementBody(options) {
17946
17498
  const useSvgWarp = pptx.shouldUseSvgWarp(
17947
17499
  pptx$1.hasTextProperties(el) ? el.textStyle?.textWarpPreset : void 0
17948
17500
  );
17949
- const scene3dStyle = pptx$1.hasTextProperties(el) ? chunkJAI42EXQ_js.buildTextBody3DSceneStyle(el.textStyle, { width: el.width, height: el.height }) : void 0;
17501
+ const scene3dStyle = pptx$1.hasTextProperties(el) ? chunkJWNBTFZZ_js.buildTextBody3DSceneStyle(el.textStyle, { width: el.width, height: el.height }) : void 0;
17950
17502
  const rotationTransform = pptx.getTextBodyRotationTransform(el);
17951
- const composedTransform = [rotationTransform, chunkJAI42EXQ_js.getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
17503
+ const composedTransform = [rotationTransform, chunkJWNBTFZZ_js.getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
17952
17504
  const transformStyle = {
17953
17505
  transform: composedTransform,
17954
17506
  // A COM-measured homography (`scene3dStyle.transformOrigin === '0 0'`)
@@ -17978,18 +17530,18 @@ function renderTextElementBody(options) {
17978
17530
  shouldRenderText && (useSvgWarp ? /* @__PURE__ */ jsxRuntime.jsx(
17979
17531
  "div",
17980
17532
  {
17981
- className: chunkJAI42EXQ_js.cn(
17533
+ className: chunkJWNBTFZZ_js.cn(
17982
17534
  "relative z-10 w-full h-full",
17983
17535
  onHyperlinkClick ? "" : "pointer-events-none"
17984
17536
  ),
17985
- style: { ...chunkJAI42EXQ_js.getTextLayoutStyle(el), ...transformStyle },
17537
+ style: { ...chunkJWNBTFZZ_js.getTextLayoutStyle(el), ...transformStyle },
17986
17538
  children: /* @__PURE__ */ jsxRuntime.jsx(
17987
17539
  WarpedText,
17988
17540
  {
17989
17541
  element: el,
17990
17542
  width: el.width,
17991
17543
  height: el.height,
17992
- fallbackColor: chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
17544
+ fallbackColor: chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR,
17993
17545
  findHighlights: findHl,
17994
17546
  fieldContext
17995
17547
  }
@@ -17998,19 +17550,19 @@ function renderTextElementBody(options) {
17998
17550
  ) : /* @__PURE__ */ jsxRuntime.jsx(
17999
17551
  "div",
18000
17552
  {
18001
- className: chunkJAI42EXQ_js.cn(
17553
+ className: chunkJWNBTFZZ_js.cn(
18002
17554
  "relative z-10 w-full h-full whitespace-pre-wrap break-words leading-[1.3]",
18003
17555
  onHyperlinkClick ? "" : "pointer-events-none"
18004
17556
  ),
18005
17557
  style: {
18006
- ...chunkJAI42EXQ_js.getTextLayoutStyle(el),
17558
+ ...chunkJWNBTFZZ_js.getTextLayoutStyle(el),
18007
17559
  ...txtS,
18008
- ...chunkJAI42EXQ_js.getTextWarpStyle(txtSE),
17560
+ ...chunkJWNBTFZZ_js.getTextWarpStyle(txtSE),
18009
17561
  ...transformStyle
18010
17562
  },
18011
- children: chunkJAI42EXQ_js.renderTextSegments(
17563
+ children: chunkJWNBTFZZ_js.renderTextSegments(
18012
17564
  el,
18013
- chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
17565
+ chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR,
18014
17566
  void 0,
18015
17567
  findHl,
18016
17568
  onHyperlinkClick,
@@ -18329,7 +17881,7 @@ function renderBody(options) {
18329
17881
  );
18330
17882
  }
18331
17883
  if (isImg) {
18332
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkJAI42EXQ_js.getImageSurfaceStyle(el), children: [
17884
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkJWNBTFZZ_js.getImageSurfaceStyle(el), children: [
18333
17885
  renderImg(el, imgStyle, imgFilter, imgAlt, imgOpacity),
18334
17886
  vecShape ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0", children: vecShape }) : null
18335
17887
  ] });
@@ -18346,7 +17898,7 @@ function renderBody(options) {
18346
17898
  textDirection: txtSE?.textDirection,
18347
17899
  textStyle: txtS,
18348
17900
  textStyleRaw: txtSE,
18349
- layoutStyle: chunkJAI42EXQ_js.getTextLayoutStyle(el),
17901
+ layoutStyle: chunkJWNBTFZZ_js.getTextLayoutStyle(el),
18350
17902
  element: el,
18351
17903
  onCommit,
18352
17904
  onCancel,
@@ -18357,7 +17909,7 @@ function renderBody(options) {
18357
17909
  ] });
18358
17910
  }
18359
17911
  if (el.type === "table") {
18360
- return chunkJAI42EXQ_js.renderTableElement(el, txtS, {
17912
+ return chunkJWNBTFZZ_js.renderTableElement(el, txtS, {
18361
17913
  editable: isSel,
18362
17914
  selectedCell: isSel ? tableSt : null,
18363
17915
  onSelectCell: onCellSel,
@@ -18390,7 +17942,7 @@ function renderBody(options) {
18390
17942
  );
18391
17943
  }
18392
17944
  if (el.type === "media") {
18393
- return chunkJAI42EXQ_js.renderMediaElement(el, media, {
17945
+ return chunkJWNBTFZZ_js.renderMediaElement(el, media, {
18394
17946
  // Present mode autoplays every media element on the active slide,
18395
17947
  // not only ones persisted with their own `autoPlay` flag (matching
18396
17948
  // the other four bindings' unconditional `presenting`-gated
@@ -18442,27 +17994,27 @@ function renderBody(options) {
18442
17994
  }
18443
17995
  return renderGroup(el.children, pptx.getGroupChildParentFill(el));
18444
17996
  }
18445
- if (chunkJAI42EXQ_js.shouldRenderFallbackLabel(el, isTxtEl)) {
18446
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: chunkJAI42EXQ_js.getElementLabel(el) });
17997
+ if (chunkJWNBTFZZ_js.shouldRenderFallbackLabel(el, isTxtEl)) {
17998
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: chunkJWNBTFZZ_js.getElementLabel(el) });
18447
17999
  }
18448
18000
  return renderTextElementBody(options);
18449
18001
  }
18450
18002
  function defaultTextColorForFill(fillColor) {
18451
18003
  const hex = String(fillColor ?? "").replace(/^#/u, "");
18452
18004
  if (!/^[0-9a-f]{6}$/iu.test(hex)) {
18453
- return chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR;
18005
+ return chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR;
18454
18006
  }
18455
18007
  const channels = [0, 2, 4].map((offset) => Number.parseInt(hex.slice(offset, offset + 2), 16) / 255).map((channel) => channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4);
18456
18008
  const luminance = channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
18457
- return luminance > 0.179 ? chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR : "#ffffff";
18009
+ return luminance > 0.179 ? chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR : "#ffffff";
18458
18010
  }
18459
18011
  function getStaticElementVisualState(element, parentGroupFill) {
18460
18012
  const style = pptx$1.hasShapeProperties(element) ? element.shapeStyle : void 0;
18461
- const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkJAI42EXQ_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
18462
- const fill = chunkJAI42EXQ_js.normalizeHexColor(style?.fillColor, chunkJAI42EXQ_js.DEFAULT_FILL_COLOR);
18013
+ const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkJWNBTFZZ_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
18014
+ const fill = chunkJWNBTFZZ_js.normalizeHexColor(style?.fillColor, chunkJWNBTFZZ_js.DEFAULT_FILL_COLOR);
18463
18015
  const strokeWidth = pptx.paintedStrokeWidth(style);
18464
- const stroke = chunkJAI42EXQ_js.normalizeHexColor(style?.strokeColor, chunkJAI42EXQ_js.DEFAULT_STROKE_COLOR);
18465
- const baseVisualStyle = chunkJAI42EXQ_js.getShapeVisualStyle(element, hasFill, fill, strokeWidth, stroke);
18016
+ const stroke = chunkJWNBTFZZ_js.normalizeHexColor(style?.strokeColor, chunkJWNBTFZZ_js.DEFAULT_STROKE_COLOR);
18017
+ const baseVisualStyle = chunkJWNBTFZZ_js.getShapeVisualStyle(element, hasFill, fill, strokeWidth, stroke);
18466
18018
  const inheritedFill = pptx.resolveGroupChildFill(element, parentGroupFill);
18467
18019
  const visualStyle = inheritedFill ? {
18468
18020
  ...baseVisualStyle,
@@ -18472,9 +18024,9 @@ function getStaticElementVisualState(element, parentGroupFill) {
18472
18024
  backgroundSize: inheritedFill.backgroundSize,
18473
18025
  backgroundPosition: inheritedFill.backgroundPosition
18474
18026
  } : baseVisualStyle;
18475
- const textStyle = chunkJAI42EXQ_js.getTextStyleForElement(
18027
+ const textStyle = chunkJWNBTFZZ_js.getTextStyleForElement(
18476
18028
  element,
18477
- element.type === "shape" && hasFill ? defaultTextColorForFill(fill) : chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR
18029
+ element.type === "shape" && hasFill ? defaultTextColorForFill(fill) : chunkJWNBTFZZ_js.DEFAULT_TEXT_COLOR
18478
18030
  );
18479
18031
  const isImage = element.type === "picture" || element.type === "image";
18480
18032
  const letsTextOverflow = pptx$1.hasTextProperties(element) && element.textStyle?.autoFitMode === "shrink" && (element.type === "text" || element.locks?.txBox === true);
@@ -18499,7 +18051,7 @@ function getStaticElementInteractionState(element, hasActionHandler, exposeEleme
18499
18051
  return { action, isActionable, contractRole };
18500
18052
  }
18501
18053
  function getStaticElementWrapperClassName(element, visual, positioned, isActionable) {
18502
- const overflowClass = visual.isImage || visual.strokeWidth > 0 || element.type === "group" || chunkJAI42EXQ_js.isConnectorOrLineElement(element) || visual.isCallout || visual.letsTextOverflow ? "" : "overflow-hidden";
18054
+ const overflowClass = visual.isImage || visual.strokeWidth > 0 || element.type === "group" || chunkJWNBTFZZ_js.isConnectorOrLineElement(element) || visual.isCallout || visual.letsTextOverflow ? "" : "overflow-hidden";
18503
18055
  const pointerClass = isActionable ? "pointer-events-auto cursor-pointer" : "pointer-events-none";
18504
18056
  return `${positioned ? "absolute" : "relative"} ${overflowClass} ${pointerClass}`;
18505
18057
  }
@@ -18582,7 +18134,7 @@ function StaticElementRendererImpl({
18582
18134
  top: positioned ? element.y : void 0,
18583
18135
  width: positioned ? Math.max(element.width, 1) : "100%",
18584
18136
  height: positioned ? Math.max(element.height, 1) : "100%",
18585
- transform: positioned ? chunkJAI42EXQ_js.getElementTransform(element) : void 0,
18137
+ transform: positioned ? chunkJWNBTFZZ_js.getElementTransform(element) : void 0,
18586
18138
  transformOrigin: "center",
18587
18139
  zIndex,
18588
18140
  ...visualStyle,
@@ -18625,18 +18177,18 @@ function StaticElementRendererImpl({
18625
18177
  spellCheck: false,
18626
18178
  txtSE: pptx$1.hasTextProperties(element) ? element.textStyle : void 0,
18627
18179
  txtS: textStyle,
18628
- vecShape: chunkJAI42EXQ_js.renderVectorShape(
18180
+ vecShape: chunkJWNBTFZZ_js.renderVectorShape(
18629
18181
  element,
18630
18182
  isImage ? false : hasFill,
18631
18183
  fill,
18632
18184
  strokeWidth,
18633
18185
  stroke
18634
18186
  ),
18635
- imgStyle: imageAnimation ? { ...chunkJAI42EXQ_js.getImageRenderStyle(element), animation: imageAnimation } : chunkJAI42EXQ_js.getImageRenderStyle(element),
18636
- imgFilter: chunkJAI42EXQ_js.getImageEffectsFilter(element),
18637
- imgOpacity: chunkJAI42EXQ_js.getImageEffectsOpacity(element),
18187
+ imgStyle: imageAnimation ? { ...chunkJWNBTFZZ_js.getImageRenderStyle(element), animation: imageAnimation } : chunkJWNBTFZZ_js.getImageRenderStyle(element),
18188
+ imgFilter: chunkJWNBTFZZ_js.getImageEffectsFilter(element),
18189
+ imgOpacity: chunkJWNBTFZZ_js.getImageEffectsOpacity(element),
18638
18190
  imgAlt: "",
18639
- isTxtEl: chunkJAI42EXQ_js.isEditableTextElement(element),
18191
+ isTxtEl: chunkJWNBTFZZ_js.isEditableTextElement(element),
18640
18192
  media: mediaDataUrls,
18641
18193
  tableSt: null,
18642
18194
  isSel: false,
@@ -18684,7 +18236,7 @@ function SlideLayer({
18684
18236
  style: {
18685
18237
  width: safeWidth,
18686
18238
  height: safeHeight,
18687
- backgroundColor: slide.backgroundColor ? chunkJAI42EXQ_js.normalizeHexColor(slide.backgroundColor, "#ffffff") : "#ffffff",
18239
+ backgroundColor: slide.backgroundColor ? chunkJWNBTFZZ_js.normalizeHexColor(slide.backgroundColor, "#ffffff") : "#ffffff",
18688
18240
  backgroundImage: slide.backgroundImage ? `url(${slide.backgroundImage})` : slide.backgroundGradient ? slide.backgroundGradient : void 0,
18689
18241
  backgroundSize: slide.backgroundImage ? "cover" : void 0,
18690
18242
  backgroundPosition: slide.backgroundImage ? "center" : void 0
@@ -19206,7 +18758,6 @@ exports.Rendering3DFlagsContext = Rendering3DFlagsContext;
19206
18758
  exports.ResizeHandles = ResizeHandles;
19207
18759
  exports.SlideBackgroundImageLayer = SlideBackgroundImageLayer;
19208
18760
  exports.SlideLayer = SlideLayer;
19209
- exports.SmartArtRenderer = SmartArtRenderer;
19210
18761
  exports.StaticElementRenderer = StaticElementRenderer;
19211
18762
  exports.ViewerOptionsContext = ViewerOptionsContext;
19212
18763
  exports.ViewerOptionsStoreContext = ViewerOptionsStoreContext;
@@ -19240,6 +18791,7 @@ exports.useCollaborativeState = useCollaborativeState;
19240
18791
  exports.useComments = useComments;
19241
18792
  exports.useCompatibilityToastsState = useCompatibilityToastsState;
19242
18793
  exports.useContentLifecycle = useContentLifecycle;
18794
+ exports.useController = useController;
19243
18795
  exports.useDerivedElementState = useDerivedElementState;
19244
18796
  exports.useDerivedSlideState = useDerivedSlideState;
19245
18797
  exports.useDialogCustomShows = useDialogCustomShows;