pptx-react-viewer 4.49.0 → 4.51.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 (124) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/README.md +38 -4
  3. package/dist/{AiChatPanel-S4WNQCY4.js → AiChatPanel-EV22O7UO.js} +19 -20
  4. package/dist/AiChatPanel-EV22O7UO.js.br +0 -0
  5. package/dist/AiChatPanel-EV22O7UO.js.gz +0 -0
  6. package/dist/{AiChatPanel-NKTBHT5B.mjs → AiChatPanel-R323KNGN.mjs} +1 -2
  7. package/dist/AiChatPanel-R323KNGN.mjs.br +0 -0
  8. package/dist/AiChatPanel-R323KNGN.mjs.gz +0 -0
  9. package/dist/{chunk-Z62JFXMZ.mjs → chunk-ACFR4LFQ.mjs} +577 -1028
  10. package/dist/chunk-ACFR4LFQ.mjs.br +0 -0
  11. package/dist/chunk-ACFR4LFQ.mjs.gz +0 -0
  12. package/dist/chunk-DDJ634MV.js.br +0 -0
  13. package/dist/chunk-DDJ634MV.js.gz +0 -0
  14. package/dist/{chunk-YKLL2Z33.mjs → chunk-ETJ752B5.mjs} +597 -1871
  15. package/dist/chunk-ETJ752B5.mjs.br +0 -0
  16. package/dist/chunk-ETJ752B5.mjs.gz +0 -0
  17. package/dist/chunk-QIUK53JR.mjs.br +0 -0
  18. package/dist/chunk-QIUK53JR.mjs.gz +0 -0
  19. package/dist/{chunk-ME5QRTVS.js → chunk-V3XADJ2O.js} +763 -1214
  20. package/dist/chunk-V3XADJ2O.js.br +0 -0
  21. package/dist/chunk-V3XADJ2O.js.gz +0 -0
  22. package/dist/{chunk-2ZXXHNNR.js → chunk-VI5DQRQZ.js} +2052 -3325
  23. package/dist/chunk-VI5DQRQZ.js.br +0 -0
  24. package/dist/chunk-VI5DQRQZ.js.gz +0 -0
  25. package/dist/{chunk-JAI42EXQ.js → chunk-Z22RD3E2.js} +41 -12
  26. package/dist/chunk-Z22RD3E2.js.br +0 -0
  27. package/dist/chunk-Z22RD3E2.js.gz +0 -0
  28. package/dist/{chunk-PFV626ED.mjs → chunk-ZCGYPCZM.mjs} +37 -8
  29. package/dist/chunk-ZCGYPCZM.mjs.br +0 -0
  30. package/dist/chunk-ZCGYPCZM.mjs.gz +0 -0
  31. package/dist/i18n/de.cjs +1138 -221
  32. package/dist/i18n/de.cjs.br +0 -0
  33. package/dist/i18n/de.cjs.gz +0 -0
  34. package/dist/i18n/de.mjs +1138 -221
  35. package/dist/i18n/de.mjs.br +0 -0
  36. package/dist/i18n/de.mjs.gz +0 -0
  37. package/dist/i18n/es.cjs +1138 -221
  38. package/dist/i18n/es.cjs.br +0 -0
  39. package/dist/i18n/es.cjs.gz +0 -0
  40. package/dist/i18n/es.mjs +1138 -221
  41. package/dist/i18n/es.mjs.br +0 -0
  42. package/dist/i18n/es.mjs.gz +0 -0
  43. package/dist/i18n/fr.cjs +1138 -221
  44. package/dist/i18n/fr.cjs.br +0 -0
  45. package/dist/i18n/fr.cjs.gz +0 -0
  46. package/dist/i18n/fr.mjs +1138 -221
  47. package/dist/i18n/fr.mjs.br +0 -0
  48. package/dist/i18n/fr.mjs.gz +0 -0
  49. package/dist/i18n/zh-CN.cjs +1138 -221
  50. package/dist/i18n/zh-CN.cjs.br +0 -0
  51. package/dist/i18n/zh-CN.cjs.gz +0 -0
  52. package/dist/i18n/zh-CN.mjs +1138 -221
  53. package/dist/i18n/zh-CN.mjs.br +0 -0
  54. package/dist/i18n/zh-CN.mjs.gz +0 -0
  55. package/dist/index.d.ts +56 -27
  56. package/dist/index.js +28 -24
  57. package/dist/index.js.br +0 -0
  58. package/dist/index.js.gz +0 -0
  59. package/dist/index.mjs +3 -3
  60. package/dist/index.mjs.br +0 -0
  61. package/dist/index.mjs.gz +0 -0
  62. package/dist/internals.d.ts +105 -94
  63. package/dist/internals.js +81 -81
  64. package/dist/internals.js.br +0 -0
  65. package/dist/internals.js.gz +0 -0
  66. package/dist/internals.mjs +2 -2
  67. package/dist/internals.mjs.br +0 -0
  68. package/dist/internals.mjs.gz +0 -0
  69. package/dist/pptx-viewer-canvas.css +1 -1
  70. package/dist/pptx-viewer-canvas.css.br +0 -0
  71. package/dist/pptx-viewer-canvas.css.gz +0 -0
  72. package/dist/pptx-viewer.css +1 -1
  73. package/dist/pptx-viewer.css.br +0 -0
  74. package/dist/pptx-viewer.css.gz +0 -0
  75. package/dist/viewer/index.d.ts +58 -24
  76. package/dist/viewer/index.js +23 -19
  77. package/dist/viewer/index.js.br +0 -0
  78. package/dist/viewer/index.js.gz +0 -0
  79. package/dist/viewer/index.mjs +3 -3
  80. package/dist/viewer/index.mjs.br +0 -0
  81. package/dist/viewer/index.mjs.gz +0 -0
  82. package/dist/{y-webrtc-2H7UYAQD.mjs → y-webrtc-HRGGVQZH.mjs} +1 -1
  83. package/dist/y-webrtc-HRGGVQZH.mjs.br +0 -0
  84. package/dist/y-webrtc-HRGGVQZH.mjs.gz +0 -0
  85. package/dist/{y-webrtc-DVPQNFLL.js → y-webrtc-QVVT5PCK.js} +124 -124
  86. package/dist/y-webrtc-QVVT5PCK.js.br +0 -0
  87. package/dist/y-webrtc-QVVT5PCK.js.gz +0 -0
  88. package/dist/{y-websocket-WORVRRQS.mjs → y-websocket-46M6UFI7.mjs} +1 -1
  89. package/dist/y-websocket-46M6UFI7.mjs.br +0 -0
  90. package/dist/y-websocket-46M6UFI7.mjs.gz +0 -0
  91. package/dist/{y-websocket-TN4OKPXQ.js → y-websocket-EDOMWMAD.js} +78 -78
  92. package/dist/y-websocket-EDOMWMAD.js.br +0 -0
  93. package/dist/y-websocket-EDOMWMAD.js.gz +0 -0
  94. package/package.json +3 -3
  95. package/dist/AiChatPanel-NKTBHT5B.mjs.br +0 -0
  96. package/dist/AiChatPanel-NKTBHT5B.mjs.gz +0 -0
  97. package/dist/AiChatPanel-S4WNQCY4.js.br +0 -0
  98. package/dist/AiChatPanel-S4WNQCY4.js.gz +0 -0
  99. package/dist/chunk-2ZXXHNNR.js.br +0 -0
  100. package/dist/chunk-2ZXXHNNR.js.gz +0 -0
  101. package/dist/chunk-3VVZGHHY.mjs.br +0 -0
  102. package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
  103. package/dist/chunk-JAI42EXQ.js.br +0 -0
  104. package/dist/chunk-JAI42EXQ.js.gz +0 -0
  105. package/dist/chunk-ME5QRTVS.js.br +0 -0
  106. package/dist/chunk-ME5QRTVS.js.gz +0 -0
  107. package/dist/chunk-NUNDT6EL.js.br +0 -0
  108. package/dist/chunk-NUNDT6EL.js.gz +0 -0
  109. package/dist/chunk-PFV626ED.mjs.br +0 -0
  110. package/dist/chunk-PFV626ED.mjs.gz +0 -0
  111. package/dist/chunk-YKLL2Z33.mjs.br +0 -0
  112. package/dist/chunk-YKLL2Z33.mjs.gz +0 -0
  113. package/dist/chunk-Z62JFXMZ.mjs.br +0 -0
  114. package/dist/chunk-Z62JFXMZ.mjs.gz +0 -0
  115. package/dist/y-webrtc-2H7UYAQD.mjs.br +0 -0
  116. package/dist/y-webrtc-2H7UYAQD.mjs.gz +0 -0
  117. package/dist/y-webrtc-DVPQNFLL.js.br +0 -0
  118. package/dist/y-webrtc-DVPQNFLL.js.gz +0 -0
  119. package/dist/y-websocket-TN4OKPXQ.js.br +0 -0
  120. package/dist/y-websocket-TN4OKPXQ.js.gz +0 -0
  121. package/dist/y-websocket-WORVRRQS.mjs.br +0 -0
  122. package/dist/y-websocket-WORVRRQS.mjs.gz +0 -0
  123. package/dist/{chunk-NUNDT6EL.js → chunk-DDJ634MV.js} +436 -436
  124. package/dist/{chunk-3VVZGHHY.mjs → chunk-QIUK53JR.mjs} +436 -436
@@ -1,12 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkJAI42EXQ_js = require('./chunk-JAI42EXQ.js');
3
+ var chunkZ22RD3E2_js = require('./chunk-Z22RD3E2.js');
4
4
  var pptx = require('ooxml-ui/pptx');
5
5
  var React17 = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var pptx$1 = require('ooxml-core/pptx');
8
8
  var i18n = require('ooxml-ui/pptx/i18n');
9
- var reactI18next = require('react-i18next');
10
9
  var reactDom = require('react-dom');
11
10
  var lu = require('react-icons/lu');
12
11
 
@@ -80,240 +79,59 @@ function useVirtualizedSlides({
80
79
  scrollToIndex
81
80
  };
82
81
  }
82
+ function useController(controller) {
83
+ return React17.useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
84
+ }
85
+
86
+ // src/viewer/hooks/collaboration/collaboration-modules.ts
87
+ var collabModules = {
88
+ loadYjs: () => import('yjs'),
89
+ loadWebsocket: () => import('./y-websocket-EDOMWMAD.js'),
90
+ loadWebrtc: () => import('./y-webrtc-QVVT5PCK.js')
91
+ };
92
+
93
+ // src/viewer/hooks/collaboration/useYjsProvider.ts
83
94
  function useYjsProvider({ config: inputConfig }) {
84
95
  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]
96
+ const [controller] = React17.useState(
97
+ () => pptx.createCollaborationSessionController({ modules: collabModules, registerTeardown: false })
126
98
  );
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;
99
+ const state = useController(controller);
100
+ const signalingKey = config?.signaling?.join("\n");
101
+ React17.useEffect(() => {
191
102
  if (!config) {
103
+ controller.stop();
192
104
  return;
193
105
  }
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
- }
106
+ void controller.start(config);
107
+ const disposeTeardown = pptx.registerCollaborationTeardown({
108
+ leave: () => controller.stop(),
109
+ rejoin: () => void controller.retry()
110
+ });
111
+ return () => {
112
+ disposeTeardown();
113
+ controller.stop();
114
+ };
293
115
  }, [
116
+ controller,
294
117
  config?.roomId,
295
118
  config?.serverUrl,
296
119
  config?.authToken,
297
120
  config?.transport,
298
- announceDeparture,
299
- initWebrtc,
300
- teardown
121
+ signalingKey,
122
+ Boolean(config)
301
123
  ]);
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 };
124
+ const session = state.active ? controller.getSession() : null;
125
+ return {
126
+ status: state.status,
127
+ awareness: session?.awareness ?? null,
128
+ doc: session?.doc ?? null,
129
+ clientId: state.clientId,
130
+ synced: state.synced,
131
+ retry: () => {
132
+ void controller.retry();
133
+ }
134
+ };
317
135
  }
318
136
  function usePresenceTracking({
319
137
  awareness,
@@ -762,15 +580,11 @@ function serializeHistoryDocument(snapshot) {
762
580
  )
763
581
  });
764
582
  }
765
- function recordExplicitSlideUpdate(past, future, previous, before, label, maxDepth) {
583
+ function recordExplicitSlideUpdate(history, previous, before, label) {
766
584
  if (previous && serializeHistoryDocument(previous) !== serializeHistoryDocument(before)) {
767
- past.push(chunkJAI42EXQ_js.cloneHistorySnapshot(previous));
585
+ history.record(chunkZ22RD3E2_js.cloneHistorySnapshot(previous), previous.actionLabel);
768
586
  }
769
- past.push({ ...chunkJAI42EXQ_js.cloneHistorySnapshot(before), actionLabel: label });
770
- while (past.length > Math.max(1, maxDepth)) {
771
- past.shift();
772
- }
773
- future.length = 0;
587
+ history.record({ ...chunkZ22RD3E2_js.cloneHistorySnapshot(before), actionLabel: label }, label);
774
588
  }
775
589
  var POLL_INTERVAL_MS = 16;
776
590
  function usePointerReleaseWakeup(hasActivePointerInteraction) {
@@ -806,7 +620,6 @@ function usePointerReleaseWakeup(hasActivePointerInteraction) {
806
620
  }
807
621
 
808
622
  // src/viewer/hooks/useEditorHistory.ts
809
- var DEFAULT_MAX_HISTORY_ENTRIES = 120;
810
623
  function useEditorHistory(input) {
811
624
  const {
812
625
  slides,
@@ -815,7 +628,7 @@ function useEditorHistory(input) {
815
628
  templateElementsBySlideId,
816
629
  loading,
817
630
  error,
818
- maxHistoryEntries = DEFAULT_MAX_HISTORY_ENTRIES,
631
+ maxHistoryEntries,
819
632
  hasActivePointerInteraction,
820
633
  pointerCommitNonce,
821
634
  onDirty,
@@ -826,38 +639,31 @@ function useEditorHistory(input) {
826
639
  setSelectedElementId,
827
640
  setSelectedElementIds
828
641
  } = input;
829
- const historyPastRef = React17.useRef([]);
830
- const historyFutureRef = React17.useRef([]);
642
+ const [history] = React17.useState(() => pptx.createEditorHistoryController());
643
+ const historyState = useController(history);
831
644
  const lastHistorySnapshotRef = React17.useRef(null);
832
645
  const lastHistorySerializedRef = React17.useRef("");
833
646
  const lastCheapHashRef = React17.useRef("");
834
647
  const isApplyingHistoryRef = React17.useRef(false);
835
648
  const trackingHeldRef = React17.useRef(false);
836
649
  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
650
  const [editCommitNonce, setEditCommitNonce] = React17.useState(0);
842
651
  const { pointerReleaseNonce, deferUntilPointerReleased } = usePointerReleaseWakeup(
843
652
  hasActivePointerInteraction
844
653
  );
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
- }, []);
654
+ React17.useEffect(() => {
655
+ if (maxHistoryEntries !== void 0) {
656
+ history.setMaxDepth(maxHistoryEntries);
657
+ }
658
+ }, [history, maxHistoryEntries]);
853
659
  const buildHistorySnapshot = React17.useCallback(
854
660
  (actionLabel) => {
855
661
  return {
856
662
  width: canvasSize.width,
857
663
  height: canvasSize.height,
858
664
  activeSlideIndex,
859
- slides: slides.map(chunkJAI42EXQ_js.cloneSlide),
860
- templateElementsBySlideId: chunkJAI42EXQ_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
665
+ slides: slides.map(chunkZ22RD3E2_js.cloneSlide),
666
+ templateElementsBySlideId: chunkZ22RD3E2_js.cloneTemplateElementsBySlideId(templateElementsBySlideId),
861
667
  ...actionLabel ? { actionLabel } : {}
862
668
  };
863
669
  },
@@ -870,9 +676,9 @@ function useEditorHistory(input) {
870
676
  width: snapshot.width,
871
677
  height: snapshot.height
872
678
  });
873
- setSlides(snapshot.slides.map(chunkJAI42EXQ_js.cloneSlide));
679
+ setSlides(snapshot.slides.map(chunkZ22RD3E2_js.cloneSlide));
874
680
  setTemplateElementsBySlideId(
875
- chunkJAI42EXQ_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
681
+ chunkZ22RD3E2_js.cloneTemplateElementsBySlideId(snapshot.templateElementsBySlideId)
876
682
  );
877
683
  setActiveSlideIndex(Math.min(snapshot.activeSlideIndex, maxSlideIndex));
878
684
  setSelectedElementIds([]);
@@ -904,64 +710,50 @@ function useEditorHistory(input) {
904
710
  onDirtyRef.current?.();
905
711
  }, []);
906
712
  const handleUndo = React17.useCallback(() => {
907
- const previousSnapshot = historyPastRef.current.pop();
908
- if (!previousSnapshot) {
713
+ if (!history.getSnapshot().canUndo) {
714
+ return;
715
+ }
716
+ const result = history.undo(buildHistorySnapshot());
717
+ if (!result) {
909
718
  return;
910
719
  }
911
- const currentSnapshot = buildHistorySnapshot(previousSnapshot.actionLabel);
912
- historyFutureRef.current.push(currentSnapshot);
913
720
  isApplyingHistoryRef.current = true;
914
- const nextSnapshot = chunkJAI42EXQ_js.cloneHistorySnapshot(previousSnapshot);
915
- lastHistorySnapshotRef.current = chunkJAI42EXQ_js.cloneHistorySnapshot(nextSnapshot);
721
+ const nextSnapshot = chunkZ22RD3E2_js.cloneHistorySnapshot(result.snapshot);
722
+ lastHistorySnapshotRef.current = chunkZ22RD3E2_js.cloneHistorySnapshot(nextSnapshot);
916
723
  lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
917
724
  applyHistorySnapshot(nextSnapshot);
918
- updateHistoryAvailability();
919
725
  unlockHistoryTracking();
920
726
  markDirty();
921
- }, [
922
- applyHistorySnapshot,
923
- buildHistorySnapshot,
924
- markDirty,
925
- unlockHistoryTracking,
926
- updateHistoryAvailability
927
- ]);
727
+ }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
928
728
  const handleRedo = React17.useCallback(() => {
929
- const nextSnapshot = historyFutureRef.current.pop();
930
- if (!nextSnapshot) {
729
+ if (!history.getSnapshot().canRedo) {
730
+ return;
731
+ }
732
+ const result = history.redo(buildHistorySnapshot());
733
+ if (!result) {
931
734
  return;
932
735
  }
933
- const currentSnapshot = buildHistorySnapshot(nextSnapshot.actionLabel);
934
- historyPastRef.current.push(currentSnapshot);
935
736
  isApplyingHistoryRef.current = true;
936
- const targetSnapshot = chunkJAI42EXQ_js.cloneHistorySnapshot(nextSnapshot);
937
- lastHistorySnapshotRef.current = chunkJAI42EXQ_js.cloneHistorySnapshot(targetSnapshot);
737
+ const targetSnapshot = chunkZ22RD3E2_js.cloneHistorySnapshot(result.snapshot);
738
+ lastHistorySnapshotRef.current = chunkZ22RD3E2_js.cloneHistorySnapshot(targetSnapshot);
938
739
  lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
939
740
  applyHistorySnapshot(targetSnapshot);
940
- updateHistoryAvailability();
941
741
  unlockHistoryTracking();
942
742
  markDirty();
943
- }, [
944
- applyHistorySnapshot,
945
- buildHistorySnapshot,
946
- markDirty,
947
- unlockHistoryTracking,
948
- updateHistoryAvailability
949
- ]);
743
+ }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
950
744
  const resetHistory = React17.useCallback(
951
745
  (initialSnapshot) => {
952
- historyPastRef.current = [];
953
- historyFutureRef.current = [];
746
+ history.clear();
954
747
  if (initialSnapshot) {
955
- const clonedInitial = chunkJAI42EXQ_js.cloneHistorySnapshot(initialSnapshot);
748
+ const clonedInitial = chunkZ22RD3E2_js.cloneHistorySnapshot(initialSnapshot);
956
749
  lastHistorySnapshotRef.current = clonedInitial;
957
750
  lastHistorySerializedRef.current = serializeHistoryDocument(clonedInitial);
958
751
  } else {
959
752
  lastHistorySnapshotRef.current = null;
960
753
  lastHistorySerializedRef.current = "";
961
754
  }
962
- updateHistoryAvailability();
963
755
  },
964
- [updateHistoryAvailability]
756
+ [history]
965
757
  );
966
758
  React17.useEffect(() => {
967
759
  return () => {
@@ -1004,19 +796,13 @@ function useEditorHistory(input) {
1004
796
  lastHistorySnapshotRef.current = snapshot;
1005
797
  lastHistorySerializedRef.current = serialized;
1006
798
  lastCheapHashRef.current = cheapHash;
1007
- updateHistoryAvailability();
1008
799
  return;
1009
800
  }
1010
801
  onDirtyRef.current?.();
1011
- historyPastRef.current.push(previousSnapshot);
1012
- while (historyPastRef.current.length > Math.max(1, maxHistoryEntries)) {
1013
- historyPastRef.current.shift();
1014
- }
1015
- historyFutureRef.current = [];
802
+ history.record(previousSnapshot, previousSnapshot.actionLabel);
1016
803
  lastHistorySnapshotRef.current = snapshot;
1017
804
  lastHistorySerializedRef.current = serialized;
1018
805
  lastCheapHashRef.current = cheapHash;
1019
- updateHistoryAvailability();
1020
806
  }, [
1021
807
  activeSlideIndex,
1022
808
  buildHistorySnapshot,
@@ -1026,30 +812,21 @@ function useEditorHistory(input) {
1026
812
  editCommitNonce,
1027
813
  error,
1028
814
  hasActivePointerInteraction,
815
+ history,
1029
816
  loading,
1030
- maxHistoryEntries,
1031
817
  pointerCommitNonce,
1032
818
  pointerReleaseNonce,
1033
- slides,
1034
- updateHistoryAvailability
819
+ slides
1035
820
  ]);
1036
821
  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);
822
+ const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(chunkZ22RD3E2_js.cloneSlide) };
823
+ const after = { ...before, slides: nextSlides.map(chunkZ22RD3E2_js.cloneSlide) };
824
+ recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
825
+ lastHistorySnapshotRef.current = chunkZ22RD3E2_js.cloneHistorySnapshot(after);
1048
826
  lastHistorySerializedRef.current = serializeHistoryDocument(after);
1049
827
  isApplyingHistoryRef.current = false;
1050
828
  setSlides(nextSlides);
1051
829
  onDirtyRef.current?.();
1052
- updateHistoryAvailability();
1053
830
  };
1054
831
  const holdTracking = React17.useCallback((held) => {
1055
832
  trackingHeldRef.current = held;
@@ -1057,10 +834,10 @@ function useEditorHistory(input) {
1057
834
  return {
1058
835
  commitSlides,
1059
836
  holdTracking,
1060
- canUndo,
1061
- canRedo,
1062
- undoLabel,
1063
- redoLabel,
837
+ canUndo: historyState.canUndo,
838
+ canRedo: historyState.canRedo,
839
+ undoLabel: historyState.undoLabel,
840
+ redoLabel: historyState.redoLabel,
1064
841
  handleUndo,
1065
842
  handleRedo,
1066
843
  resetHistory,
@@ -1230,22 +1007,22 @@ function useZoomViewport({
1230
1007
  selectedElements.forEach((element) => {
1231
1008
  minX = Math.min(minX, element.x);
1232
1009
  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));
1010
+ maxX = Math.max(maxX, element.x + Math.max(element.width, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE));
1011
+ maxY = Math.max(maxY, element.y + Math.max(element.height, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE));
1235
1012
  });
1236
1013
  if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {
1237
1014
  return;
1238
1015
  }
1239
1016
  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);
1017
+ const boundsWidth = Math.max(selectionBounds.maxX - selectionBounds.minX, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE);
1018
+ const boundsHeight = Math.max(selectionBounds.maxY - selectionBounds.minY, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE);
1242
1019
  const availableWidth = Math.max(
1243
- effectiveEditorDimensions.width - chunkJAI42EXQ_js.ZOOM_TO_SELECTION_PADDING,
1244
- chunkJAI42EXQ_js.MIN_ELEMENT_SIZE
1020
+ effectiveEditorDimensions.width - chunkZ22RD3E2_js.ZOOM_TO_SELECTION_PADDING,
1021
+ chunkZ22RD3E2_js.MIN_ELEMENT_SIZE
1245
1022
  );
1246
1023
  const availableHeight = Math.max(
1247
- effectiveEditorDimensions.height - chunkJAI42EXQ_js.ZOOM_TO_SELECTION_PADDING,
1248
- chunkJAI42EXQ_js.MIN_ELEMENT_SIZE
1024
+ effectiveEditorDimensions.height - chunkZ22RD3E2_js.ZOOM_TO_SELECTION_PADDING,
1025
+ chunkZ22RD3E2_js.MIN_ELEMENT_SIZE
1249
1026
  );
1250
1027
  const targetEditorScale = Math.min(
1251
1028
  availableWidth / boundsWidth,
@@ -2203,9 +1980,6 @@ function executeSlideTransition(nextSlideIndex, deps) {
2203
1980
  }
2204
1981
 
2205
1982
  // 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
1983
  function useSlideNavigation(input) {
2210
1984
  const {
2211
1985
  slides,
@@ -2255,50 +2029,71 @@ function useSlideNavigation(input) {
2255
2029
  );
2256
2030
  const movePresentationSlide = React17.useCallback(
2257
2031
  (direction, trigger = "explicit") => {
2258
- if (direction === 1 && playNextAnimationGroup()) {
2259
- return;
2260
- }
2261
- if (isClickAdvanceBlocked(slides[presentationSlideIndex], direction, trigger)) {
2032
+ const showOrder = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
2033
+ const current = presentationSlideIndex;
2034
+ const transitionTo = (index, options = {}) => executeSlideTransition(index, {
2035
+ slides,
2036
+ currentSlideIndex: current,
2037
+ onPlayActionSound,
2038
+ onStopActionSound,
2039
+ setPresentationSlideVisible,
2040
+ clearPresentationTimers,
2041
+ setPresentationSlideIndex,
2042
+ onSetActiveSlideIndex,
2043
+ seedSlideAnimations,
2044
+ startSlideAnimations,
2045
+ scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
2046
+ presentationTimersRef,
2047
+ setTransitionOverlay,
2048
+ // PowerPoint plays a slide's transition only when advancing into it,
2049
+ // and replays the LEAVING slide's transition in reverse when stepping
2050
+ // back (a morph glides its shapes back to where they came from).
2051
+ playTransition: true,
2052
+ ...options
2053
+ });
2054
+ if (direction === -1) {
2055
+ const step2 = pptx.resolveShowBackward({
2056
+ currentIndex: current,
2057
+ showOrder,
2058
+ endOfShow: false,
2059
+ seededCompleted: false
2060
+ });
2061
+ if (step2.kind === "go") {
2062
+ transitionTo(step2.index, { reverse: true, seedCompleted: true });
2063
+ }
2262
2064
  return;
2263
2065
  }
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,
2066
+ const step = pptx.resolveShowForward({
2067
+ currentIndex: current,
2068
+ currentSlide: slides[current],
2069
+ showOrder,
2070
+ endOfShow: false,
2071
+ fromClick: trigger === "click",
2072
+ loop: Boolean(loopContinuously) && !rehearsing,
2073
+ endWithBlackSlide: true,
2074
+ zoomExcursion: zoomExcursionRef.current,
2075
+ advanceBuild: playNextAnimationGroup
2076
+ });
2077
+ if (step.kind === "go") {
2078
+ if (step.zoomReturn) {
2079
+ zoomExcursionRef.current = step.zoomReturn.excursion;
2080
+ transitionTo(step.index, {
2284
2081
  scheduleAutoAdvanceForSlide,
2285
- presentationTimersRef,
2286
- setTransitionOverlay,
2287
- playTransition: true,
2288
- transitionOverride: pptx.buildZoomTransitionOverride(
2289
- consumedExcursion?.transitionDurationMs
2290
- )
2082
+ transitionOverride: step.zoomReturn.transitionOverride
2291
2083
  });
2292
2084
  return;
2293
2085
  }
2086
+ if (rehearsing) {
2087
+ recordCurrentSlideTime(current);
2088
+ }
2089
+ transitionTo(step.index);
2090
+ return;
2294
2091
  }
2295
- const availableSlideIndexes = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
2296
- if (availableSlideIndexes.length === 0) {
2092
+ if (step.kind !== "end-screen" && step.kind !== "exit") {
2297
2093
  return;
2298
2094
  }
2299
- const pastLastSlide = direction === 1 && !pptx.hasShowSlideAfter(presentationSlideIndex, availableSlideIndexes);
2300
- if (rehearsing && pastLastSlide) {
2301
- recordCurrentSlideTime(presentationSlideIndex);
2095
+ if (rehearsing) {
2096
+ recordCurrentSlideTime(current);
2302
2097
  try {
2303
2098
  if (document.fullscreenElement) {
2304
2099
  void document.exitFullscreen().catch(() => {
@@ -2310,41 +2105,7 @@ function useSlideNavigation(input) {
2310
2105
  setShowRehearsalSummary(true);
2311
2106
  return;
2312
2107
  }
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
- });
2108
+ onAdvancePastLastSlide?.();
2348
2109
  },
2349
2110
  [
2350
2111
  clearPresentationTimers,
@@ -4204,6 +3965,7 @@ function useViewerCoreState(_input) {
4204
3965
  const marqueeStateRef = React17.useRef(null);
4205
3966
  const isDrawingRef = React17.useRef(false);
4206
3967
  const justInteractedRef = React17.useRef(false);
3968
+ const gestureControllerRef = React17.useRef(null);
4207
3969
  const livePatcher = React17.useMemo(() => pptx.createCollaborationLivePatcher(), []);
4208
3970
  React17.useEffect(() => () => livePatcher.dispose(), [livePatcher]);
4209
3971
  const [mode, setMode] = React17.useState("edit");
@@ -4212,18 +3974,19 @@ function useViewerCoreState(_input) {
4212
3974
  const { slides, setSlides, slidesRef } = useSlideState();
4213
3975
  const [templateElementsBySlideId, setTemplateElementsBySlideId] = React17.useState({});
4214
3976
  const [canvasSize, setCanvasSize] = React17.useState({
4215
- width: chunkJAI42EXQ_js.DEFAULT_CANVAS_WIDTH,
4216
- height: chunkJAI42EXQ_js.DEFAULT_CANVAS_HEIGHT
3977
+ width: chunkZ22RD3E2_js.DEFAULT_CANVAS_WIDTH,
3978
+ height: chunkZ22RD3E2_js.DEFAULT_CANVAS_HEIGHT
4217
3979
  });
4218
3980
  const [slideSizeEmu, setSlideSizeEmu] = React17.useState();
4219
3981
  const [activeSlideIndex, setActiveSlideIndex] = React17.useState(0);
4220
3982
  const [selectedElementId, setSelectedElementId] = React17.useState(null);
4221
3983
  const [selectedElementIds, setSelectedElementIds] = React17.useState([]);
4222
3984
  const [isDirty, setIsDirty] = React17.useState(false);
3985
+ const autosaveDraftSinkRef = React17.useRef(null);
4223
3986
  const publishInlineText = React17.useCallback(
4224
3987
  (elementId, text) => {
4225
- pptx.publishLiveInlineText(
4226
- livePatcher,
3988
+ pptx.reportInlineTextDraft(
3989
+ { livePatcher, autosave: autosaveDraftSinkRef.current },
4227
3990
  slidesRef.current[activeSlideIndexRef.current],
4228
3991
  elementId,
4229
3992
  text
@@ -4289,6 +4052,7 @@ function useViewerCoreState(_input) {
4289
4052
  imageInputRef,
4290
4053
  mediaInputRef,
4291
4054
  activeSlideIndexRef,
4055
+ autosaveDraftSinkRef,
4292
4056
  ...inlineEditing,
4293
4057
  ...editPointsMode,
4294
4058
  dragStateRef,
@@ -4297,6 +4061,7 @@ function useViewerCoreState(_input) {
4297
4061
  marqueeStateRef,
4298
4062
  isDrawingRef,
4299
4063
  justInteractedRef,
4064
+ gestureControllerRef,
4300
4065
  livePatcher,
4301
4066
  mode,
4302
4067
  setMode,
@@ -4686,12 +4451,12 @@ function useLoadContent({
4686
4451
  }
4687
4452
  resources.commit();
4688
4453
  handlerRef.current = handler;
4689
- const partition = chunkJAI42EXQ_js.partitionTemplateElements(nextSlides);
4454
+ const partition = chunkZ22RD3E2_js.partitionTemplateElements(nextSlides);
4690
4455
  setSlides(partition.slides);
4691
4456
  setTemplateElementsBySlideId(partition.templateElementsBySlideId);
4692
4457
  setCanvasSize({
4693
- width: parsed.width ?? chunkJAI42EXQ_js.DEFAULT_CANVAS_WIDTH,
4694
- height: parsed.height ?? chunkJAI42EXQ_js.DEFAULT_CANVAS_HEIGHT
4458
+ width: parsed.width ?? chunkZ22RD3E2_js.DEFAULT_CANVAS_WIDTH,
4459
+ height: parsed.height ?? chunkZ22RD3E2_js.DEFAULT_CANVAS_HEIGHT
4695
4460
  });
4696
4461
  setSlideSizeEmu(
4697
4462
  typeof parsed.widthEmu === "number" && typeof parsed.heightEmu === "number" && parsed.widthEmu > 0 && parsed.heightEmu > 0 ? {
@@ -4783,96 +4548,43 @@ function useLoadContent({
4783
4548
  return { handlerRef };
4784
4549
  }
4785
4550
  function useAutosave(input) {
4786
- const { isDirty, filePath, serializeSlides, enabled = true, getChangeSources } = input;
4551
+ const { isDirty, filePath, enabled = true } = input;
4787
4552
  const intervalMs = pptx.resolveAutosaveIntervalMs({
4788
4553
  hostIntervalMs: input.intervalMs,
4789
4554
  optionsIntervalSeconds: input.intervalSeconds
4790
4555
  });
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]);
4556
+ const live = React17.useRef(input);
4557
+ live.current = input;
4558
+ const [controller] = React17.useState(
4559
+ () => pptx.createAutosaveController({
4560
+ getActivation: () => ({ active: live.current.enabled ?? true }),
4561
+ getFilePath: () => live.current.filePath,
4562
+ getIntervalMs: () => pptx.resolveAutosaveIntervalMs({
4563
+ hostIntervalMs: live.current.intervalMs,
4564
+ optionsIntervalSeconds: live.current.intervalSeconds
4565
+ }),
4566
+ serialize: () => live.current.serializeSlides(),
4567
+ getStorage: () => live.current.storage,
4568
+ onSaved: (data) => live.current.onSaved?.(data),
4569
+ writeSnapshot: pptx.saveAutosaveSnapshot,
4570
+ // serializeSlides already overlays the live inline draft from its refs.
4571
+ getInlineEditingId: () => live.current.getInlineEditingId?.()
4572
+ })
4573
+ );
4574
+ if (input.inlineDraftSinkRef) {
4575
+ input.inlineDraftSinkRef.current = controller;
4576
+ }
4577
+ const { status } = useController(controller);
4815
4578
  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
- }, []);
4579
+ controller.refresh();
4580
+ }, [controller, enabled, filePath, intervalMs]);
4855
4581
  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]);
4582
+ controller.observe(isDirty, live.current.getChangeSources?.() ?? []);
4583
+ });
4584
+ React17.useEffect(() => () => controller.markClean(), [controller]);
4873
4585
  return {
4874
- autosaveStatus,
4875
- triggerAutosave: () => doAutosave()
4586
+ autosaveStatus: status,
4587
+ triggerAutosave: () => controller.saveNow()
4876
4588
  };
4877
4589
  }
4878
4590
 
@@ -5150,7 +4862,7 @@ function useElementOperations(input) {
5150
4862
  );
5151
4863
  return;
5152
4864
  }
5153
- if (chunkJAI42EXQ_js.isTemplateElementId(elementId)) {
4865
+ if (chunkZ22RD3E2_js.isTemplateElementId(elementId)) {
5154
4866
  const slideId = activeSlide?.id;
5155
4867
  if (slideId) {
5156
4868
  setTemplateElementsBySlideId((prev) => ({
@@ -5387,45 +5099,238 @@ function syncSelectionHandleOverlay(elementNode, elementId, geometry) {
5387
5099
  }
5388
5100
  }
5389
5101
 
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);
5102
+ // src/viewer/hooks/canvas-gestures.ts
5103
+ var animationFrames = {
5104
+ request: (callback) => requestAnimationFrame(callback),
5105
+ cancel: (handle) => cancelAnimationFrame(handle)
5106
+ };
5107
+ function createCanvasGestures(getInput, frames = animationFrames) {
5108
+ let armed = null;
5109
+ let pending = null;
5110
+ let frameHandle = 0;
5111
+ let lastSnapLinesKey = "";
5112
+ const liveTarget = () => {
5113
+ const { livePatcher, editTemplateMode, activeSlide } = getInput();
5114
+ return livePatcher && !editTemplateMode && livePatcher.isActive() ? { patcher: livePatcher, slideId: activeSlide?.id } : void 0;
5115
+ };
5116
+ function showSnapLines(lines) {
5117
+ const next = lines.map((line) => ({
5118
+ axis: line.axis === "v" ? "x" : "y",
5119
+ position: line.position
5120
+ }));
5121
+ const key = JSON.stringify(next);
5122
+ if (key !== lastSnapLinesKey) {
5123
+ lastSnapLinesKey = key;
5124
+ getInput().setSnapLines(next);
5125
+ }
5396
5126
  }
5397
- const box = { x: resized.x, y: resized.y, width: resized.width, height: resized.height };
5398
- if (!snapToGrid) {
5399
- return box;
5127
+ function paintMove(drag, transform) {
5128
+ const start = drag.startPositionsById[transform.id];
5129
+ if (!start) {
5130
+ return;
5131
+ }
5132
+ drag.lastDx = transform.x - start.x;
5133
+ drag.lastDy = transform.y - start.y;
5134
+ const live = liveTarget();
5135
+ for (const [id, from] of Object.entries(drag.startPositionsById)) {
5136
+ const x = from.x + drag.lastDx;
5137
+ const y = from.y + drag.lastDy;
5138
+ const domEl = drag.domEls.get(id);
5139
+ if (domEl) {
5140
+ domEl.style.left = `${x}px`;
5141
+ domEl.style.top = `${y}px`;
5142
+ syncSelectionHandleOverlay(domEl, id, { x, y });
5143
+ }
5144
+ if (live) {
5145
+ pptx.publishLiveGeometry(live.patcher, live.slideId, id, { x, y });
5146
+ }
5147
+ }
5148
+ }
5149
+ function paintResize(resize, transform) {
5150
+ const { x, y } = transform;
5151
+ const width = Math.max(transform.width, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE);
5152
+ const height = Math.max(transform.height, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE);
5153
+ resize.lastX = x;
5154
+ resize.lastY = y;
5155
+ resize.lastWidth = transform.width;
5156
+ resize.lastHeight = transform.height;
5157
+ if (resize.domEl) {
5158
+ Object.assign(resize.domEl.style, {
5159
+ left: `${x}px`,
5160
+ top: `${y}px`,
5161
+ width: `${width}px`,
5162
+ height: `${height}px`
5163
+ });
5164
+ syncSelectionHandleOverlay(resize.domEl, resize.elementId, { x, y, width, height });
5165
+ }
5166
+ const live = liveTarget();
5167
+ if (live) {
5168
+ pptx.publishLiveGeometry(live.patcher, live.slideId, resize.elementId, { x, y, width, height });
5169
+ }
5170
+ }
5171
+ function paintPending() {
5172
+ const frame = pending;
5173
+ pending = null;
5174
+ frameHandle = 0;
5175
+ if (!frame || !armed) {
5176
+ return;
5177
+ }
5178
+ if (armed.kind === "move") {
5179
+ armed.drag.moved = true;
5180
+ showSnapLines(frame.lines);
5181
+ paintMove(armed.drag, frame.transform);
5182
+ } else {
5183
+ armed.resize.moved = true;
5184
+ paintResize(armed.resize, frame.transform);
5185
+ }
5186
+ }
5187
+ function flushFrame() {
5188
+ if (frameHandle !== 0) {
5189
+ frames.cancel(frameHandle);
5190
+ }
5191
+ paintPending();
5192
+ }
5193
+ const controller = pptx.createGestureController({
5194
+ getScale: () => getInput().editorScale,
5195
+ // Axis-aligned, as the canvas has always moved and resized (no rotation).
5196
+ getElementBox: (id) => {
5197
+ const el = getInput().elementLookup.get(id);
5198
+ return el ? { x: el.x, y: el.y, width: el.width, height: el.height } : void 0;
5199
+ },
5200
+ getSiblings: () => {
5201
+ const { editTemplateMode, templateElements, activeSlide } = getInput();
5202
+ const source = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
5203
+ return source.map(({ id, x, y, width, height }) => ({ id, x, y, width, height }));
5204
+ },
5205
+ getSnapToGrid: () => getInput().snapToGrid,
5206
+ getGridSize: () => getInput().gridSpacingPx,
5207
+ getSnapToShape: () => getInput().snapToShape,
5208
+ getGuides: () => getInput().guides.map(({ axis, position }) => ({ axis, position })),
5209
+ getMinSize: () => chunkZ22RD3E2_js.MIN_ELEMENT_SIZE,
5210
+ getSnapExcludeIds: () => armed?.kind === "move" ? Object.keys(armed.drag.startPositionsById) : [],
5211
+ getStageOrigin: () => {
5212
+ const rect = getInput().canvasStageRef.current?.getBoundingClientRect();
5213
+ return { left: rect?.left ?? 0, top: rect?.top ?? 0 };
5214
+ },
5215
+ onStart: () => void 0,
5216
+ onPreview: (transform, lines) => {
5217
+ pending = { transform, lines };
5218
+ if (frameHandle === 0) {
5219
+ frameHandle = frames.request(paintPending);
5220
+ }
5221
+ },
5222
+ onEnd: (transform, moved) => {
5223
+ flushFrame();
5224
+ const ended = armed;
5225
+ armed = null;
5226
+ if (ended) {
5227
+ finishGesture(ended, moved ? transform : null);
5228
+ }
5229
+ }
5230
+ });
5231
+ function finishGesture(ended, transform) {
5232
+ const input = getInput();
5233
+ if (transform) {
5234
+ if (ended.kind === "move") {
5235
+ commitMove(input, ended.drag);
5236
+ } else {
5237
+ commitResize(input, ended.resize);
5238
+ }
5239
+ input.justInteractedRef.current = true;
5240
+ input.livePatcher?.flush();
5241
+ }
5242
+ input.dragStateRef.current = null;
5243
+ input.resizeStateRef.current = null;
5244
+ lastSnapLinesKey = "";
5245
+ input.setSnapLines([]);
5246
+ if (transform) {
5247
+ input.markDirty();
5248
+ }
5249
+ input.setPointerCommitNonce((n) => n + 1);
5400
5250
  }
5401
- return pptx.snapBoxToGrid(box, handle, gridSpacingPx, chunkJAI42EXQ_js.MIN_ELEMENT_SIZE);
5251
+ return {
5252
+ begin(kind, id, pointer) {
5253
+ if (controller.isActive()) {
5254
+ return;
5255
+ }
5256
+ const input = getInput();
5257
+ const drag = input.dragStateRef.current;
5258
+ const resize = input.resizeStateRef.current;
5259
+ armed = kind === "move" && drag ? { kind, drag } : kind === "resize" && resize ? { kind, resize } : null;
5260
+ if (!armed) {
5261
+ return;
5262
+ }
5263
+ lastSnapLinesKey = "";
5264
+ const handle = armed.kind === "resize" ? armed.resize.handle : void 0;
5265
+ controller.begin(kind, id, pointer, handle);
5266
+ if (!controller.isActive()) {
5267
+ armed = null;
5268
+ }
5269
+ },
5270
+ isActive: () => controller.isActive(),
5271
+ dispose: () => {
5272
+ if (frameHandle !== 0) {
5273
+ frames.cancel(frameHandle);
5274
+ frameHandle = 0;
5275
+ }
5276
+ pending = null;
5277
+ armed = null;
5278
+ controller.dispose();
5279
+ }
5280
+ };
5402
5281
  }
5403
- function resolveLiveTarget(input) {
5404
- const { livePatcher, editTemplateMode, activeSlide } = input;
5405
- if (!livePatcher || editTemplateMode || !livePatcher.isActive()) {
5406
- return void 0;
5282
+ function commitMove(input, drag) {
5283
+ const { lastDx: dx, lastDy: dy } = drag;
5284
+ const movedIds = new Set(Object.keys(drag.startPositionsById));
5285
+ const moveElements = (elements) => {
5286
+ const moved = elements.map((el) => {
5287
+ const start = drag.startPositionsById[el.id];
5288
+ return start ? { ...el, x: start.x + dx, y: start.y + dy } : el;
5289
+ });
5290
+ return chunkZ22RD3E2_js.applyReroutedConnectors(moved, chunkZ22RD3E2_js.rerouteConnectorsForMovedElements(moved, movedIds));
5291
+ };
5292
+ if (input.editTemplateMode) {
5293
+ const slideId = input.activeSlide?.id;
5294
+ if (slideId) {
5295
+ input.setTemplateElementsBySlideId((prev) => ({
5296
+ ...prev,
5297
+ [slideId]: moveElements(prev[slideId] ?? [])
5298
+ }));
5299
+ }
5300
+ return;
5407
5301
  }
5408
- return { patcher: livePatcher, slideId: activeSlide?.id };
5302
+ input.updateSlides(
5303
+ (prev) => prev.map(
5304
+ (s, i) => i !== input.activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) }
5305
+ )
5306
+ );
5409
5307
  }
5410
- function processPointerMove(e, input, tracker) {
5308
+ function commitResize(input, resize) {
5309
+ input.updateElementById(resize.elementId, {
5310
+ x: resize.lastX,
5311
+ y: resize.lastY,
5312
+ width: resize.lastWidth,
5313
+ height: resize.lastHeight
5314
+ });
5315
+ const movedIds = /* @__PURE__ */ new Set([resize.elementId]);
5316
+ input.updateSlides(
5317
+ (prev) => prev.map((s, i) => {
5318
+ if (i !== input.activeSlideIndex) {
5319
+ return s;
5320
+ }
5321
+ const rerouted = chunkZ22RD3E2_js.rerouteConnectorsForMovedElements(s.elements, movedIds);
5322
+ return rerouted.length === 0 ? s : { ...s, elements: chunkZ22RD3E2_js.applyReroutedConnectors(s.elements, rerouted) };
5323
+ })
5324
+ );
5325
+ }
5326
+ function processPointerMove(e, input) {
5411
5327
  const {
5412
5328
  editorScale,
5413
5329
  canvasStageRef,
5414
5330
  canvasSize,
5415
- snapToGrid,
5416
- snapToShape,
5417
- gridSpacingPx,
5418
- editTemplateMode,
5419
- templateElements,
5420
- activeSlide,
5421
- guides,
5422
- elementLookup,
5423
5331
  marqueeStateRef,
5424
- dragStateRef,
5425
- resizeStateRef,
5426
5332
  shapeAdjustmentDragStateRef,
5427
5333
  setMarqueeSelectionState,
5428
- setSnapLines,
5429
5334
  updateElementById
5430
5335
  } = input;
5431
5336
  const marquee = marqueeStateRef.current;
@@ -5440,31 +5345,6 @@ function processPointerMove(e, input, tracker) {
5440
5345
  );
5441
5346
  return;
5442
5347
  }
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
5348
  const adj = shapeAdjustmentDragStateRef.current;
5469
5349
  if (adj) {
5470
5350
  processAdjustmentMove(e, adj, editorScale, updateElementById);
@@ -5480,129 +5360,6 @@ function processMarqueeMove(e, marquee, canvasStageRef, canvasSize, editorScale,
5480
5360
  marquee.currentY = Math.max(0, Math.min(canvasSize.height, (e.clientY - rect.top) / editorScale));
5481
5361
  setMarqueeSelectionState({ ...marquee });
5482
5362
  }
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
5363
  function processAdjustmentMove(e, adj, editorScale, updateElementById) {
5607
5364
  const dx = (e.clientX - adj.startClientX) / editorScale;
5608
5365
  const dy = (e.clientY - adj.startClientY) / editorScale;
@@ -5621,26 +5378,20 @@ function processPointerUp(input) {
5621
5378
  editTemplateMode,
5622
5379
  templateElements,
5623
5380
  activeSlide,
5624
- activeSlideIndex,
5625
5381
  marqueeStateRef,
5626
5382
  dragStateRef,
5627
5383
  resizeStateRef,
5628
5384
  shapeAdjustmentDragStateRef,
5629
5385
  justInteractedRef,
5386
+ gestureRef,
5630
5387
  setMarqueeSelectionState,
5631
- setSnapLines,
5632
- setTemplateElementsBySlideId,
5633
5388
  setPointerCommitNonce,
5634
5389
  applySelection,
5635
5390
  clearSelection,
5636
- updateSlides,
5637
- updateElementById,
5638
5391
  markDirty,
5639
5392
  livePatcher
5640
5393
  } = input;
5641
5394
  const marquee = marqueeStateRef.current;
5642
- const drag = dragStateRef.current;
5643
- const rs = resizeStateRef.current;
5644
5395
  const adj = shapeAdjustmentDragStateRef.current;
5645
5396
  if (marquee) {
5646
5397
  commitMarquee(
@@ -5651,62 +5402,22 @@ function processPointerUp(input) {
5651
5402
  applySelection,
5652
5403
  clearSelection
5653
5404
  );
5654
- marqueeStateRef.current = null;
5655
- setMarqueeSelectionState(null);
5656
- }
5657
- if (drag?.moved) {
5658
- commitDrag(
5659
- drag,
5660
- editTemplateMode,
5661
- activeSlide,
5662
- activeSlideIndex,
5663
- setTemplateElementsBySlideId,
5664
- updateSlides
5665
- );
5666
5405
  }
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
- );
5406
+ if (!gestureRef?.current?.isActive()) {
5407
+ dragStateRef.current = null;
5408
+ resizeStateRef.current = null;
5692
5409
  }
5693
- const wasMoved = drag?.moved || rs?.moved || adj?.moved;
5694
- if (wasMoved) {
5410
+ if (adj?.moved) {
5695
5411
  justInteractedRef.current = true;
5696
- }
5697
- if (wasMoved) {
5698
5412
  livePatcher?.flush();
5699
5413
  }
5700
5414
  marqueeStateRef.current = null;
5701
- dragStateRef.current = null;
5702
- resizeStateRef.current = null;
5703
5415
  shapeAdjustmentDragStateRef.current = null;
5704
5416
  setMarqueeSelectionState(null);
5705
- setSnapLines([]);
5706
- if (wasMoved) {
5417
+ if (adj?.moved) {
5707
5418
  markDirty();
5708
5419
  }
5709
- if (drag || rs || adj || marquee) {
5420
+ if (adj || marquee) {
5710
5421
  setPointerCommitNonce((n) => n + 1);
5711
5422
  }
5712
5423
  }
@@ -5726,35 +5437,6 @@ function commitMarquee(marquee, editTemplateMode, templateElements, activeSlide,
5726
5437
  clearSelection();
5727
5438
  }
5728
5439
  }
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
5440
 
5759
5441
  // src/viewer/hooks/usePointerHandlers.ts
5760
5442
  function usePointerHandlers(input) {
@@ -5764,41 +5446,42 @@ function usePointerHandlers(input) {
5764
5446
  canvasSize,
5765
5447
  activeSlide,
5766
5448
  activeSlideIndex,
5767
- gridSpacingPx,
5768
- dragStateRef,
5769
- resizeStateRef,
5770
5449
  shapeAdjustmentDragStateRef,
5771
5450
  marqueeStateRef,
5772
5451
  editTemplateMode,
5773
- snapToGrid,
5774
- snapToShape,
5775
- guides,
5776
5452
  templateElements,
5777
- elementLookup,
5778
5453
  setMarqueeSelectionState,
5779
- setSnapLines,
5780
- setTemplateElementsBySlideId,
5781
5454
  setPointerCommitNonce,
5782
5455
  applySelection,
5783
5456
  clearSelection,
5784
- updateSlides,
5785
5457
  updateElementById,
5786
5458
  markDirty,
5787
- livePatcher
5459
+ livePatcher,
5460
+ gestureRef
5788
5461
  } = input;
5462
+ const inputRef = React17.useRef(input);
5463
+ inputRef.current = input;
5464
+ const gestures = React17.useMemo(() => createCanvasGestures(() => inputRef.current), []);
5789
5465
  React17.useEffect(() => {
5790
- const tracker = {
5791
- rafId: 0,
5792
- pendingMoveEvent: null,
5793
- lastSnapLinesKey: ""
5466
+ if (gestureRef) {
5467
+ gestureRef.current = gestures;
5468
+ }
5469
+ return () => {
5470
+ gestures.dispose();
5471
+ if (gestureRef?.current === gestures) {
5472
+ gestureRef.current = null;
5473
+ }
5794
5474
  };
5475
+ }, [gestures, gestureRef]);
5476
+ React17.useEffect(() => {
5477
+ const tracker = { rafId: 0, pendingMoveEvent: null };
5795
5478
  const handlePointerMove = (e) => {
5796
5479
  tracker.pendingMoveEvent = e;
5797
5480
  if (tracker.rafId === 0) {
5798
5481
  tracker.rafId = requestAnimationFrame(() => {
5799
5482
  tracker.rafId = 0;
5800
5483
  if (tracker.pendingMoveEvent) {
5801
- processPointerMove(tracker.pendingMoveEvent, input, tracker);
5484
+ processPointerMove(tracker.pendingMoveEvent, input);
5802
5485
  tracker.pendingMoveEvent = null;
5803
5486
  }
5804
5487
  });
@@ -5826,31 +5509,22 @@ function usePointerHandlers(input) {
5826
5509
  }, [
5827
5510
  editorScale,
5828
5511
  canvasStageRef,
5829
- dragStateRef,
5830
- resizeStateRef,
5831
5512
  shapeAdjustmentDragStateRef,
5832
5513
  marqueeStateRef,
5833
5514
  editTemplateMode,
5834
- snapToGrid,
5835
- snapToShape,
5836
- guides,
5837
5515
  templateElements,
5838
5516
  setMarqueeSelectionState,
5839
- setSnapLines,
5840
- elementLookup,
5841
- setTemplateElementsBySlideId,
5842
5517
  setPointerCommitNonce,
5843
5518
  activeSlide,
5844
5519
  activeSlideIndex,
5845
5520
  canvasSize.width,
5846
5521
  canvasSize.height,
5847
- gridSpacingPx,
5848
5522
  applySelection,
5849
5523
  clearSelection,
5850
- updateSlides,
5851
5524
  updateElementById,
5852
5525
  markDirty,
5853
- livePatcher
5526
+ livePatcher,
5527
+ gestureRef
5854
5528
  ]);
5855
5529
  }
5856
5530
  function mouseDownStartsSelectionDrag(event) {
@@ -5876,6 +5550,7 @@ function useCanvasInteractions(input) {
5876
5550
  shapeAdjustmentDragStateRef,
5877
5551
  marqueeStateRef,
5878
5552
  justInteractedRef,
5553
+ gestureRef,
5879
5554
  setInlineEditingElementId,
5880
5555
  setInlineEditingText,
5881
5556
  setContextMenuState,
@@ -5901,25 +5576,7 @@ function useCanvasInteractions(input) {
5901
5576
  const scale = editorScale || 1;
5902
5577
  return rect ? { x: (e.clientX - rect.left) / scale, y: (e.clientY - rect.top) / scale } : null;
5903
5578
  };
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
- };
5579
+ const resolvePressTarget = (elementId, e) => slideElements ? pptx.resolveGroupPressTarget(slideElements, elementId, slidePoint(e), effectiveSelectedIds) : elementId;
5923
5580
  const handleInlineEditCommit = () => {
5924
5581
  const editId = inlineEditingElementId;
5925
5582
  if (!editId) {
@@ -6019,9 +5676,7 @@ function useCanvasInteractions(input) {
6019
5676
  }
6020
5677
  };
6021
5678
  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;
5679
+ const elementId = mode === "present" || !slideElements ? pressedId : pptx.resolveGroupDoubleClickTarget(slideElements, pressedId, slidePoint(e));
6025
5680
  if (elementId !== pressedId) {
6026
5681
  ops.applySelection(elementId);
6027
5682
  }
@@ -6084,6 +5739,7 @@ function useCanvasInteractions(input) {
6084
5739
  lastDy: 0
6085
5740
  };
6086
5741
  setSnapLines([]);
5742
+ gestureRef?.current?.begin("move", movableIds[0], e);
6087
5743
  };
6088
5744
  const handleElementContextMenu = (elementId, e) => {
6089
5745
  if (mode === "present") {
@@ -6156,6 +5812,7 @@ function useCanvasInteractions(input) {
6156
5812
  lastWidth: el.width,
6157
5813
  lastHeight: el.height
6158
5814
  };
5815
+ gestureRef?.current?.begin("resize", elementId, e);
6159
5816
  };
6160
5817
  const handleRotate = (elementId, rotationDeg) => {
6161
5818
  const el = elementLookup.get(elementId);
@@ -6497,7 +6154,7 @@ function createStructuredElementHandlers(deps) {
6497
6154
  return;
6498
6155
  }
6499
6156
  const resolved = resolveHyperlinkEditResult(data);
6500
- if (resolved.url && !chunkJAI42EXQ_js.isUrlSafe(resolved.url)) {
6157
+ if (resolved.url && !chunkZ22RD3E2_js.isUrlSafe(resolved.url)) {
6501
6158
  return;
6502
6159
  }
6503
6160
  const actionClick = {
@@ -6543,7 +6200,7 @@ function createStructuredElementHandlers(deps) {
6543
6200
  if (!activeSlide) {
6544
6201
  return;
6545
6202
  }
6546
- const preset = chunkJAI42EXQ_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
6203
+ const preset = chunkZ22RD3E2_js.ACTION_BUTTON_PRESETS.find((p) => p.shapeType === shapeType);
6547
6204
  if (!preset) {
6548
6205
  return;
6549
6206
  }
@@ -6630,7 +6287,7 @@ function useInsertElements(input) {
6630
6287
  width: 300,
6631
6288
  height: 60,
6632
6289
  text: "",
6633
- textStyle: { fontSize: chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE }
6290
+ textStyle: { fontSize: chunkZ22RD3E2_js.DEFAULT_TEXT_FONT_SIZE }
6634
6291
  });
6635
6292
  };
6636
6293
  const handleAddShape = () => {
@@ -6652,7 +6309,7 @@ function useInsertElements(input) {
6652
6309
  }
6653
6310
  });
6654
6311
  };
6655
- const handleAddTable = (rows = chunkJAI42EXQ_js.DEFAULT_TABLE_ROWS, columns = chunkJAI42EXQ_js.DEFAULT_TABLE_COLUMNS) => {
6312
+ const handleAddTable = (rows = chunkZ22RD3E2_js.DEFAULT_TABLE_ROWS, columns = chunkZ22RD3E2_js.DEFAULT_TABLE_COLUMNS) => {
6656
6313
  if (!activeSlide) {
6657
6314
  return;
6658
6315
  }
@@ -6661,11 +6318,11 @@ function useInsertElements(input) {
6661
6318
  id: pptx.generateElementId()
6662
6319
  });
6663
6320
  };
6664
- const handleAddChart = (chartKind) => {
6321
+ const handleAddChart = (chartKind, options) => {
6665
6322
  if (!activeSlide) {
6666
6323
  return;
6667
6324
  }
6668
- addElement(pptx.createDefaultChartElement(chartKind));
6325
+ addElement(pptx.createDefaultChartElement(chartKind, void 0, options));
6669
6326
  };
6670
6327
  const structured = createStructuredElementHandlers({
6671
6328
  activeSlide,
@@ -6826,7 +6483,7 @@ function useGroupAlignLayerHandlers(input) {
6826
6483
  history
6827
6484
  } = input;
6828
6485
  const updateElementsOwning = (elementId, updater) => {
6829
- if (editTemplateMode && !chunkJAI42EXQ_js.isTemplateElementId(elementId)) {
6486
+ if (editTemplateMode && !chunkZ22RD3E2_js.isTemplateElementId(elementId)) {
6830
6487
  ops.updateSlides(
6831
6488
  (prev) => prev.map(
6832
6489
  (slide, index) => index === activeSlideIndex ? { ...slide, elements: updater(slide.elements) } : slide
@@ -6860,9 +6517,9 @@ function useGroupAlignLayerHandlers(input) {
6860
6517
  return;
6861
6518
  }
6862
6519
  const group = selectedElement;
6863
- const intoTemplate = chunkJAI42EXQ_js.isTemplateElementId(group.id);
6520
+ const intoTemplate = chunkZ22RD3E2_js.isTemplateElementId(group.id);
6864
6521
  const childIds = group.children.map(
6865
- (child) => intoTemplate ? chunkJAI42EXQ_js.makeCloneId(true, child.id || group.id) : child.id || pptx.generateElementId()
6522
+ (child) => intoTemplate ? chunkZ22RD3E2_js.makeCloneId(true, child.id || group.id) : child.id || pptx.generateElementId()
6866
6523
  );
6867
6524
  const { elements, childIds: usedIds } = pptx.ungroupElements(
6868
6525
  ops.activeElements,
@@ -7298,7 +6955,7 @@ function createTableMergeHandlers(input) {
7298
6955
  if (!nextCell || nextCell.hMerge || nextCell.vMerge) {
7299
6956
  return;
7300
6957
  }
7301
- const newTableData = chunkJAI42EXQ_js.mergeCells(
6958
+ const newTableData = chunkZ22RD3E2_js.mergeCells(
7302
6959
  [
7303
6960
  { row: rowIndex, col: columnIndex },
7304
6961
  { row: rowIndex, col: nextColIdx }
@@ -7306,7 +6963,7 @@ function createTableMergeHandlers(input) {
7306
6963
  td
7307
6964
  );
7308
6965
  const updates = { tableData: newTableData };
7309
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
6966
+ const newRawXml = chunkZ22RD3E2_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7310
6967
  if (newRawXml) {
7311
6968
  updates.rawXml = newRawXml;
7312
6969
  }
@@ -7332,7 +6989,7 @@ function createTableMergeHandlers(input) {
7332
6989
  if (!targetNextCell || targetNextCell.hMerge || targetNextCell.vMerge) {
7333
6990
  return;
7334
6991
  }
7335
- const newTableData = chunkJAI42EXQ_js.mergeCells(
6992
+ const newTableData = chunkZ22RD3E2_js.mergeCells(
7336
6993
  [
7337
6994
  { row: rowIndex, col: columnIndex },
7338
6995
  { row: targetNextRowIdx, col: columnIndex }
@@ -7340,7 +6997,7 @@ function createTableMergeHandlers(input) {
7340
6997
  td
7341
6998
  );
7342
6999
  const updates = { tableData: newTableData };
7343
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7000
+ const newRawXml = chunkZ22RD3E2_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7344
7001
  if (newRawXml) {
7345
7002
  updates.rawXml = newRawXml;
7346
7003
  }
@@ -7355,9 +7012,9 @@ function createTableMergeHandlers(input) {
7355
7012
  return;
7356
7013
  }
7357
7014
  const td = selectedElement.tableData;
7358
- const newTableData = chunkJAI42EXQ_js.mergeCells(ts.selectedCells, td);
7015
+ const newTableData = chunkZ22RD3E2_js.mergeCells(ts.selectedCells, td);
7359
7016
  const updates = { tableData: newTableData };
7360
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7017
+ const newRawXml = chunkZ22RD3E2_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7361
7018
  if (newRawXml) {
7362
7019
  updates.rawXml = newRawXml;
7363
7020
  }
@@ -7374,9 +7031,9 @@ function createTableMergeHandlers(input) {
7374
7031
  }
7375
7032
  const { rowIndex, columnIndex } = ts;
7376
7033
  const td = selectedElement.tableData;
7377
- const newTableData = chunkJAI42EXQ_js.splitCell(rowIndex, columnIndex, td);
7034
+ const newTableData = chunkZ22RD3E2_js.splitCell(rowIndex, columnIndex, td);
7378
7035
  const updates = { tableData: newTableData };
7379
- const newRawXml = chunkJAI42EXQ_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7036
+ const newRawXml = chunkZ22RD3E2_js.updateMergeAttrsInRawXml(selectedElement, newTableData);
7380
7037
  if (newRawXml) {
7381
7038
  updates.rawXml = newRawXml;
7382
7039
  }
@@ -7411,7 +7068,7 @@ function createTableStructHandlers(input) {
7411
7068
  updates.tableData = pptx.setCellText(el, rowIndex, colIndex, text).tableData;
7412
7069
  }
7413
7070
  if (el.rawXml) {
7414
- const newRawXml = chunkJAI42EXQ_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
7071
+ const newRawXml = chunkZ22RD3E2_js.updateCellTextInRawXml(el, rowIndex, colIndex, text);
7415
7072
  if (newRawXml) {
7416
7073
  updates.rawXml = newRawXml;
7417
7074
  }
@@ -7435,7 +7092,7 @@ function createTableStructHandlers(input) {
7435
7092
  const { rowIndex, columnIndex: colIndex } = ts;
7436
7093
  const updates = {};
7437
7094
  if (selectedElement.rawXml) {
7438
- const newRawXml = chunkJAI42EXQ_js.updateCellTextStyleInRawXml(
7095
+ const newRawXml = chunkZ22RD3E2_js.updateCellTextStyleInRawXml(
7439
7096
  selectedElement,
7440
7097
  rowIndex,
7441
7098
  colIndex,
@@ -7613,7 +7270,7 @@ function useExportSaveAs(input) {
7613
7270
  const sourceName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() : void 0;
7614
7271
  const slideSize = pptx.resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size;
7615
7272
  const data = {
7616
- slides: chunkJAI42EXQ_js.buildSaveSlides(slides, templateElementsBySlideId),
7273
+ slides: chunkZ22RD3E2_js.buildSaveSlides(slides, templateElementsBySlideId),
7617
7274
  width: canvasSize.width,
7618
7275
  height: canvasSize.height,
7619
7276
  widthEmu: slideSize.widthEmu,
@@ -7775,7 +7432,7 @@ async function captureAllSlidesAsPngDataUrls(slideStageRef, totalSlides, setActi
7775
7432
  }
7776
7433
  function tilesToPdfPage(tilesResult) {
7777
7434
  return tilesResult.tiles.map((tile) => ({
7778
- image: chunkJAI42EXQ_js.canvasToJpegData(tile.canvas),
7435
+ image: chunkZ22RD3E2_js.canvasToJpegData(tile.canvas),
7779
7436
  placement: pptx.placeTileOnPage(
7780
7437
  tile,
7781
7438
  tilesResult.fullWidth,
@@ -7808,7 +7465,7 @@ async function exportAllSlidesAsPdf(slideStageRef, totalSlides, setActiveSlide,
7808
7465
  if (pages.length === 0) {
7809
7466
  throw new Error(i18n.translationsEn["pptx.export.errorNoSlidesPdf"]);
7810
7467
  }
7811
- const pdfBlobUrl = chunkJAI42EXQ_js.buildPdfFromTiledImageData(pages);
7468
+ const pdfBlobUrl = chunkZ22RD3E2_js.buildPdfFromTiledImageData(pages);
7812
7469
  pptx.downloadDataUrl(pdfBlobUrl, filename);
7813
7470
  }
7814
7471
  async function exportAllSlidesAsNotesPdf(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, slideNotes, filename = "presentation-notes.pdf", options = {}) {
@@ -7838,7 +7495,7 @@ async function exportAllSlidesAsNotesPdf(slideStageRef, totalSlides, setActiveSl
7838
7495
  if (pages.length === 0) {
7839
7496
  throw new Error(i18n.translationsEn["pptx.export.errorNoSlidesNotesPdf"]);
7840
7497
  }
7841
- const pdfDataUrl = chunkJAI42EXQ_js.buildNotesPdf(pages);
7498
+ const pdfDataUrl = chunkZ22RD3E2_js.buildNotesPdf(pages);
7842
7499
  pptx.downloadDataUrl(pdfDataUrl, filename);
7843
7500
  }
7844
7501
  async function exportAllSlidesAsVideo(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, options = {}) {
@@ -8451,7 +8108,7 @@ function useViewerOptionsContext() {
8451
8108
  function usePrintHandlers(input) {
8452
8109
  const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, pptxData } = input;
8453
8110
  const [isPrintDialogOpen, setIsPrintDialogOpen] = React17.useState(false);
8454
- const { t } = reactI18next.useTranslation();
8111
+ const { t } = chunkZ22RD3E2_js.useTranslation();
8455
8112
  const viewerOptions = useViewerOptionsContext();
8456
8113
  const includeHiddenSlides = viewerOptions.advanced.printHiddenSlides;
8457
8114
  const printRasterScale = (viewerOptions.advanced.printHighQuality ? 4 : 3) * pptx.resolveImageResolutionScale(viewerOptions);
@@ -8720,8 +8377,19 @@ function useThemeHandlers(input) {
8720
8377
  return;
8721
8378
  }
8722
8379
  await handler.updateThemeFontScheme(fontScheme);
8380
+ const previousFonts = theme?.fontScheme;
8381
+ bumpHistory();
8382
+ setSlides((prev) => pptx$1.reResolveSlideFonts(prev, previousFonts, fontScheme));
8383
+ setTemplateElementsBySlideId(
8384
+ (prev) => Object.fromEntries(
8385
+ Object.entries(prev).map(([slideId, elements]) => [
8386
+ slideId,
8387
+ pptx$1.reResolveElementFonts(elements, previousFonts, fontScheme)
8388
+ ])
8389
+ )
8390
+ );
8723
8391
  setTheme((prev) => prev ? { ...prev, fontScheme } : { fontScheme });
8724
- await refreshContentAfterThemeChange();
8392
+ history.markDirty();
8725
8393
  };
8726
8394
  const handleUpdateThemeName = async (name) => {
8727
8395
  const handler = handlerRef.current;
@@ -8743,20 +8411,7 @@ function useThemeHandlers(input) {
8743
8411
  }
8744
8412
  await refreshContentAfterThemeChange();
8745
8413
  };
8746
- const handleApplyThemeData = async (colorScheme, fontScheme, themeName) => {
8747
- const handler = handlerRef.current;
8748
- if (!handler) {
8749
- return;
8750
- }
8751
- await handler.applyTheme(colorScheme, fontScheme, themeName);
8752
- setTheme((prev) => ({
8753
- ...prev,
8754
- colorScheme,
8755
- fontScheme,
8756
- ...themeName && { name: themeName }
8757
- }));
8758
- await refreshContentAfterThemeChange();
8759
- };
8414
+ const handleApplyThemeData = (colorScheme, fontScheme, themeName) => applyThemeEditorEdit(input, { colorScheme, fontScheme, name: themeName ?? theme?.name ?? "" });
8760
8415
  const handleSetTemplateBackground = (path, backgroundColor) => {
8761
8416
  const handler = handlerRef.current;
8762
8417
  if (!handler) {
@@ -8941,7 +8596,7 @@ function usePropertyHandlers(input) {
8941
8596
  width: canvasSize.width,
8942
8597
  height: canvasSize.height
8943
8598
  };
8944
- setCompareResult(chunkJAI42EXQ_js.comparePresentation(cur, other));
8599
+ setCompareResult(chunkZ22RD3E2_js.comparePresentation(cur, other));
8945
8600
  setIsComparePanelOpen(true);
8946
8601
  } catch (err) {
8947
8602
  console.warn("Compare failed:", err);
@@ -9110,6 +8765,7 @@ function useViewerDialogs(input) {
9110
8765
  embeddedFontFamilies
9111
8766
  } = input;
9112
8767
  const [isSmartArtDialogOpen, setIsSmartArtDialogOpen] = React17.useState(false);
8768
+ const [isChartDialogOpen, setIsChartDialogOpen] = React17.useState(false);
9113
8769
  const [isEquationDialogOpen, setIsEquationDialogOpen] = React17.useState(false);
9114
8770
  const [isHyperlinkDialogOpen, setIsHyperlinkDialogOpen] = React17.useState(false);
9115
8771
  const [isPasswordDialogOpen, setIsPasswordDialogOpen] = React17.useState(false);
@@ -9254,6 +8910,8 @@ function useViewerDialogs(input) {
9254
8910
  return {
9255
8911
  isSmartArtDialogOpen,
9256
8912
  setIsSmartArtDialogOpen,
8913
+ isChartDialogOpen,
8914
+ setIsChartDialogOpen,
9257
8915
  isEquationDialogOpen,
9258
8916
  setIsEquationDialogOpen,
9259
8917
  isHyperlinkDialogOpen,
@@ -9294,7 +8952,7 @@ function useViewerDialogs(input) {
9294
8952
  };
9295
8953
  }
9296
8954
  function computeGridSpacingPx(documentGridSpacing) {
9297
- return pptx.computeGridSpacingPx(documentGridSpacing, chunkJAI42EXQ_js.GRID_SIZE);
8955
+ return pptx.computeGridSpacingPx(documentGridSpacing, chunkZ22RD3E2_js.GRID_SIZE);
9298
8956
  }
9299
8957
  function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, presentationProperties) {
9300
8958
  const activeShow = activeCustomShowId ? customShows.find((show) => show.id === activeCustomShowId) : void 0;
@@ -9303,7 +8961,7 @@ function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, pre
9303
8961
  }
9304
8962
  function computeSlideSectionGroups(slides, sections) {
9305
8963
  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),
8964
+ id: group.section?.id ?? (sections.length > 0 ? chunkZ22RD3E2_js.UNGROUPED_SECTION_ID : chunkZ22RD3E2_js.DEFAULT_SECTION_GROUP_ID),
9307
8965
  label: group.section?.name ?? (sections.length > 0 ? "Ungrouped Slides" : "Slides"),
9308
8966
  slideIndexes: group.slideIndexes,
9309
8967
  ...group.section?.color !== void 0 ? { color: group.section.color } : {},
@@ -9322,7 +8980,7 @@ function computeMasterPseudoSlide(mode, activeLayout, activeMaster) {
9322
8980
  });
9323
8981
  }
9324
8982
  function useDerivedSlideState(input) {
9325
- const { t } = reactI18next.useTranslation();
8983
+ const { t } = chunkZ22RD3E2_js.useTranslation();
9326
8984
  const {
9327
8985
  slides,
9328
8986
  sections,
@@ -9348,10 +9006,10 @@ function useDerivedSlideState(input) {
9348
9006
  );
9349
9007
  const slideSectionGroups = React17.useMemo(
9350
9008
  () => computeSlideSectionGroups(slides, sections).map((group) => {
9351
- if (group.id === chunkJAI42EXQ_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
9009
+ if (group.id === chunkZ22RD3E2_js.UNGROUPED_SECTION_ID && group.label === "Ungrouped Slides") {
9352
9010
  return { ...group, label: t("pptx.slides.ungroupedSlides") };
9353
9011
  }
9354
- if (group.id === chunkJAI42EXQ_js.DEFAULT_SECTION_GROUP_ID && group.label === "Slides") {
9012
+ if (group.id === chunkZ22RD3E2_js.DEFAULT_SECTION_GROUP_ID && group.label === "Slides") {
9355
9013
  return { ...group, label: t("pptx.sections.slides") };
9356
9014
  }
9357
9015
  return group;
@@ -9458,7 +9116,7 @@ function useAnnotationHandlers(input) {
9458
9116
  if (nextMode === "present") {
9459
9117
  presentation.enterPresentMode();
9460
9118
  } else if (mode === "present" && annotations.hasAnyAnnotations) {
9461
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9119
+ chunkZ22RD3E2_js.stopAllPersistentAudio();
9462
9120
  if (promptKeepInkAnnotations) {
9463
9121
  pendingModeAfterAnnotationsRef.current = nextMode;
9464
9122
  setShowKeepAnnotationsDialog(true);
@@ -9468,7 +9126,7 @@ function useAnnotationHandlers(input) {
9468
9126
  }
9469
9127
  } else {
9470
9128
  if (mode === "present") {
9471
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9129
+ chunkZ22RD3E2_js.stopAllPersistentAudio();
9472
9130
  }
9473
9131
  setMode(nextMode);
9474
9132
  }
@@ -9635,7 +9293,7 @@ function useSerialize(input) {
9635
9293
  guides: pptxGuides.length > 0 ? pptxGuides : void 0
9636
9294
  };
9637
9295
  });
9638
- const slidesToSave = chunkJAI42EXQ_js.buildSaveSlides(slidesWithGuides, pending.templateElementsBySlideId);
9296
+ const slidesToSave = chunkZ22RD3E2_js.buildSaveSlides(slidesWithGuides, pending.templateElementsBySlideId);
9639
9297
  const saveOptions = pptx.buildDeckSaveOptions({
9640
9298
  // Without this the Slide Size card edited a viewer-only pixel value and
9641
9299
  // the saved `p:sldSz` never moved: passing `slideSize` is the only way a
@@ -9699,84 +9357,35 @@ function useSerialize(input) {
9699
9357
  }
9700
9358
  function useRecoveryDetection(input) {
9701
9359
  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;
9360
+ const live = React17.useRef(input);
9361
+ live.current = input;
9362
+ const [controller] = React17.useState(
9363
+ () => pptx.createAutosaveRecoveryController({
9364
+ getStorage: () => live.current.storage,
9365
+ load: (bytes) => live.current.onRestore?.(bytes),
9366
+ onOffered: (record) => {
9367
+ live.current.onOffered?.(record);
9368
+ live.current.openVersionHistory?.();
9369
+ },
9370
+ probe: pptx.probeAutosaveRecovery,
9371
+ discardRecord: pptx.discardAutosaveRecovery
9372
+ })
9373
+ );
9374
+ const { prompt, discarding } = useController(controller);
9715
9375
  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;
9376
+ controller.check({ filePath, fileName, loading, error, slideCount, autosaveAllowed });
9377
+ }, [controller, filePath, fileName, loading, error, slideCount, autosaveAllowed]);
9378
+ return {
9379
+ prompt,
9380
+ discarding,
9381
+ restore: () => {
9382
+ void controller.restore().catch(() => {
9383
+ });
9384
+ },
9385
+ discard: () => {
9386
+ void controller.discard();
9764
9387
  }
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 };
9388
+ };
9780
9389
  }
9781
9390
  function usePresentationSetup(input) {
9782
9391
  const {
@@ -9828,7 +9437,7 @@ function usePresentationSetup(input) {
9828
9437
  return;
9829
9438
  }
9830
9439
  if (mode === "present" && nextMode !== "present") {
9831
- chunkJAI42EXQ_js.stopAllPersistentAudio();
9440
+ chunkZ22RD3E2_js.stopAllPersistentAudio();
9832
9441
  stopAnimationSound();
9833
9442
  const exitHandler = exitModeHandlerRef.current;
9834
9443
  if (exitHandler) {
@@ -9949,7 +9558,7 @@ function useCanvasImagePaste(input) {
9949
9558
  );
9950
9559
  }
9951
9560
  function formatPatchFor(element, format) {
9952
- const updated = chunkJAI42EXQ_js.applyFormatToElement(element, format);
9561
+ const updated = chunkZ22RD3E2_js.applyFormatToElement(element, format);
9953
9562
  const updates = {};
9954
9563
  if (pptx$1.hasShapeProperties(updated)) {
9955
9564
  updates.shapeStyle = updated.shapeStyle;
@@ -9972,7 +9581,7 @@ function useFormatPainterEditing(input) {
9972
9581
  const prevFormatPainterRef = React17.useRef(false);
9973
9582
  React17.useEffect(() => {
9974
9583
  if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
9975
- copiedFormatRef.current = chunkJAI42EXQ_js.copyFormatFromElement(selectedElement);
9584
+ copiedFormatRef.current = chunkZ22RD3E2_js.copyFormatFromElement(selectedElement);
9976
9585
  } else if (!formatPainterActive) {
9977
9586
  copiedFormatRef.current = null;
9978
9587
  }
@@ -10250,6 +9859,7 @@ function useEditorOperations(input) {
10250
9859
  shapeAdjustmentDragStateRef: state.shapeAdjustmentDragStateRef,
10251
9860
  marqueeStateRef: state.marqueeStateRef,
10252
9861
  justInteractedRef: state.justInteractedRef,
9862
+ gestureRef: state.gestureControllerRef,
10253
9863
  setInlineEditingElementId: state.setInlineEditingElementId,
10254
9864
  setInlineEditingText: state.setInlineEditingText,
10255
9865
  setContextMenuState: state.setContextMenuState,
@@ -10782,6 +10392,8 @@ function useContentLifecycle(input) {
10782
10392
  // deck it has already snapshotted. The two refs are read by `.current`
10783
10393
  // because an inline edit in progress lives there and nowhere else yet.
10784
10394
  onSaved: input.onAutosave,
10395
+ inlineDraftSinkRef: state.autosaveDraftSinkRef,
10396
+ getInlineEditingId: () => state.inlineEditingElementIdRef.current,
10785
10397
  getChangeSources: () => [
10786
10398
  slides,
10787
10399
  state.templateElementsBySlideId,
@@ -10811,138 +10423,27 @@ function useKeyboardShortcuts(input) {
10811
10423
  inputRef.current = input;
10812
10424
  const handleKeyDown = React17.useCallback((e) => {
10813
10425
  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(
10426
+ pptx.dispatchEditorKey(
10825
10427
  e,
10826
10428
  {
10827
10429
  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.
10430
+ ...current.canPaste === void 0 ? {} : { canPaste: current.canPaste },
10431
+ // The Slide Master view is an editing surface, not a viewing one, so
10432
+ // only the other modes count as "not editing" for the editor keymap.
10836
10433
  isPresenting: current.mode !== "edit" && current.mode !== "master",
10434
+ // F5 is only inert while the show itself runs: a read-only viewer can
10435
+ // still start a show (it has a "From Beginning" button too).
10436
+ isShowRunning: current.mode === "present",
10437
+ canStartShow: !current.customization || pptx.isFeatureEnabled(current.customization, "presentMode"),
10837
10438
  hasSelection: current.hasSelection,
10838
10439
  isEditingText: Boolean(
10839
10440
  current.inlineEditingElementId || current.tableEditorState?.isEditing
10840
10441
  ),
10841
10442
  isDrawing: current.activeTool !== "select",
10842
- isTextInputTarget: pptx.isEditorTextInputTarget(e.target),
10843
- isControlTarget: pptx.isEditorControlTarget(e.target)
10443
+ keyboard: current.customization?.keyboard
10844
10444
  },
10845
- current.customization?.keyboard
10445
+ toEditorKeyHandlers(current)
10846
10446
  );
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
10447
  }, []);
10947
10448
  React17.useEffect(() => {
10948
10449
  window.addEventListener("keydown", handleKeyDown);
@@ -10951,6 +10452,43 @@ function useKeyboardShortcuts(input) {
10951
10452
  };
10952
10453
  }, [handleKeyDown]);
10953
10454
  }
10455
+ function toEditorKeyHandlers(current) {
10456
+ return {
10457
+ startShowFromBeginning: current.onStartShowFromBeginning,
10458
+ startShowFromCurrent: current.onStartShowFromCurrent,
10459
+ escape: current.onEscape,
10460
+ delete: current.onDelete,
10461
+ undo: current.onUndo,
10462
+ redo: current.onRedo,
10463
+ copy: current.onCopy,
10464
+ cut: current.onCut,
10465
+ paste: current.onPaste,
10466
+ duplicate: current.onDuplicate,
10467
+ selectAll: current.onSelectAll,
10468
+ group: current.onGroup,
10469
+ ungroup: current.onUngroup,
10470
+ toggleShortcuts: current.onToggleShortcuts,
10471
+ find: current.onFind,
10472
+ nudge: current.onNudge,
10473
+ prevSlide: current.onPrevSlide,
10474
+ nextSlide: current.onNextSlide,
10475
+ alignLeft: current.onAlignLeft,
10476
+ alignCenter: current.onAlignCenter,
10477
+ alignRight: current.onAlignRight,
10478
+ alignJustify: current.onAlignJustify,
10479
+ increaseFontSize: current.onIncreaseFontSize,
10480
+ decreaseFontSize: current.onDecreaseFontSize,
10481
+ copyFormat: current.onCopyFormat,
10482
+ pasteFormat: current.onPasteFormat,
10483
+ newSlide: current.onNewSlide,
10484
+ hyperlink: current.onHyperlink,
10485
+ findReplace: current.onFindReplace,
10486
+ clearFormatting: current.onClearFormatting,
10487
+ cycleSelectionNext: current.onCycleSelectionNext,
10488
+ cycleSelectionPrev: current.onCycleSelectionPrev,
10489
+ pasteSpecial: current.onPasteSpecial
10490
+ };
10491
+ }
10954
10492
  var CLEAR_FORMATTING_PATCH = {
10955
10493
  bold: false,
10956
10494
  italic: false,
@@ -11216,7 +10754,8 @@ function useViewerIntegration(input) {
11216
10754
  updateSlides: editorOps.ops.updateSlides,
11217
10755
  updateElementById: editorOps.ops.updateElementById,
11218
10756
  markDirty: history.markDirty,
11219
- livePatcher: state.livePatcher
10757
+ livePatcher: state.livePatcher,
10758
+ gestureRef: state.gestureControllerRef
11220
10759
  });
11221
10760
  const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = React17.useState(false);
11222
10761
  const [loadVersion, setLoadVersion] = React17.useState(0);
@@ -11664,7 +11203,7 @@ function useCollaborationWriteBack(input) {
11664
11203
  getSourceBytes: () => latest.current.getSourceBytes?.() ?? null,
11665
11204
  getSaveOptions: () => latest.current.getSaveOptions?.(),
11666
11205
  getTemplateElements: () => latest.current.templateElementsBySlideId,
11667
- mergeTemplateElements: chunkJAI42EXQ_js.buildSaveSlides,
11206
+ mergeTemplateElements: chunkZ22RD3E2_js.buildSaveSlides,
11668
11207
  onWriteBackStatus: () => latest.current.onWriteBackStatus?.(
11669
11208
  pptx.writeBackReport(latest.current.config, created.getState())
11670
11209
  )
@@ -12223,8 +11762,8 @@ function useTouchGestures(input) {
12223
11762
  }
12224
11763
  const recognizer = pptx.createTouchGestureRecognizer({
12225
11764
  getScale: () => scaleRef.current,
12226
- minScale: chunkJAI42EXQ_js.MIN_ZOOM_SCALE,
12227
- maxScale: chunkJAI42EXQ_js.MAX_ZOOM_SCALE,
11765
+ minScale: chunkZ22RD3E2_js.MIN_ZOOM_SCALE,
11766
+ maxScale: chunkZ22RD3E2_js.MAX_ZOOM_SCALE,
12228
11767
  callbacks: {
12229
11768
  onPinchZoom: (newScale) => callbacksRef.current.onPinchZoom?.(newScale),
12230
11769
  onSwipe: (direction) => callbacksRef.current.onSwipe?.(direction),
@@ -12348,7 +11887,7 @@ function buildCanvasProps(input) {
12348
11887
  if (pptx.shouldConfirmExternalHyperlink(viewerOptions, url) && !window.confirm(buildHyperlinkConfirmMessage(url))) {
12349
11888
  return;
12350
11889
  }
12351
- chunkJAI42EXQ_js.safeOpenUrl(url, target);
11890
+ chunkZ22RD3E2_js.safeOpenUrl(url, target);
12352
11891
  };
12353
11892
  const handleActionClick = (elementId, action) => {
12354
11893
  if (mode === "present") {
@@ -12363,9 +11902,9 @@ function buildCanvasProps(input) {
12363
11902
  }
12364
11903
  };
12365
11904
  const handleHyperlinkClick = (url, target) => {
12366
- if (chunkJAI42EXQ_js.isPpactionUrl(url)) {
11905
+ if (chunkZ22RD3E2_js.isPpactionUrl(url)) {
12367
11906
  if (mode === "present") {
12368
- const parsed = chunkJAI42EXQ_js.parsePpactionUrl(url);
11907
+ const parsed = chunkZ22RD3E2_js.parsePpactionUrl(url);
12369
11908
  if (parsed) {
12370
11909
  presentation.handlePresentationAction({
12371
11910
  action: parsed.action,
@@ -12653,6 +12192,7 @@ function buildToolbarProps(input) {
12653
12192
  onAddShape: insertHandlers.handleAddShape,
12654
12193
  onAddTable: insertHandlers.handleAddTable,
12655
12194
  onAddChart: insertHandlers.handleAddChart,
12195
+ onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
12656
12196
  onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
12657
12197
  onAddEquation: () => {
12658
12198
  dialogs.setEditingEquationOmml(null);
@@ -12792,7 +12332,7 @@ function buildToolbarProps(input) {
12792
12332
  markDirty: history.markDirty
12793
12333
  }),
12794
12334
  formatPainterActive: s.formatPainterActive,
12795
- canActivateFormatPainter: chunkJAI42EXQ_js.hasCopyableFormat(selectedElement),
12335
+ canActivateFormatPainter: chunkZ22RD3E2_js.hasCopyableFormat(selectedElement),
12796
12336
  onToggleFormatPainter: () => s.setFormatPainterActive((p) => !p),
12797
12337
  isSelectionPaneOpen: s.isSelectionPaneOpen,
12798
12338
  onToggleSelectionPane: () => s.setIsSelectionPaneOpen((p) => !p),
@@ -13483,7 +13023,7 @@ function useViewerBuildingBlocks(input) {
13483
13023
  } = input;
13484
13024
  const collaborationConfig = pptx.resolveCollaborationConfig(input.collaboration);
13485
13025
  const [collaborationReadOnly, setCollaborationReadOnly] = React17.useState(Boolean(collaborationConfig));
13486
- const { t } = reactI18next.useTranslation();
13026
+ const { t } = chunkZ22RD3E2_js.useTranslation();
13487
13027
  const [content, setContent] = React17.useState(incomingContent ?? null);
13488
13028
  const [loadOrigin, setLoadOrigin] = React17.useState("bootstrap");
13489
13029
  React17.useEffect(() => {
@@ -13670,23 +13210,23 @@ function ColorChangedImage({
13670
13210
  className,
13671
13211
  alt
13672
13212
  }) {
13673
- const tolerance = tolerancePct ?? chunkJAI42EXQ_js.DEFAULT_COLOR_CHANGE_TOLERANCE;
13674
- const cacheKey = chunkJAI42EXQ_js.buildCacheKey(
13213
+ const tolerance = tolerancePct ?? chunkZ22RD3E2_js.DEFAULT_COLOR_CHANGE_TOLERANCE;
13214
+ const cacheKey = chunkZ22RD3E2_js.buildCacheKey(
13675
13215
  src,
13676
13216
  clrChange.clrFrom,
13677
13217
  clrChange.clrTo,
13678
13218
  tolerance,
13679
13219
  Boolean(clrChange.clrToTransparent)
13680
13220
  );
13681
- const cached = chunkJAI42EXQ_js.getCachedResult(cacheKey);
13221
+ const cached = chunkZ22RD3E2_js.getCachedResult(cacheKey);
13682
13222
  const [processedSrc, setProcessedSrc] = React17.useState(cached ?? null);
13683
13223
  React17.useEffect(() => {
13684
- if (chunkJAI42EXQ_js.getCachedResult(cacheKey)) {
13685
- setProcessedSrc(chunkJAI42EXQ_js.getCachedResult(cacheKey) ?? null);
13224
+ if (chunkZ22RD3E2_js.getCachedResult(cacheKey)) {
13225
+ setProcessedSrc(chunkZ22RD3E2_js.getCachedResult(cacheKey) ?? null);
13686
13226
  return;
13687
13227
  }
13688
13228
  let cancelled = false;
13689
- chunkJAI42EXQ_js.applyColorChange(
13229
+ chunkZ22RD3E2_js.applyColorChange(
13690
13230
  src,
13691
13231
  clrChange.clrFrom,
13692
13232
  clrChange.clrTo,
@@ -13694,7 +13234,7 @@ function ColorChangedImage({
13694
13234
  Boolean(clrChange.clrToTransparent)
13695
13235
  ).then((result) => {
13696
13236
  if (!cancelled) {
13697
- chunkJAI42EXQ_js.setCachedResult(cacheKey, result.dataUrl);
13237
+ chunkZ22RD3E2_js.setCachedResult(cacheKey, result.dataUrl);
13698
13238
  setProcessedSrc(result.dataUrl);
13699
13239
  }
13700
13240
  return void 0;
@@ -13786,7 +13326,7 @@ function TiledImageLayer({
13786
13326
  cancelled = true;
13787
13327
  };
13788
13328
  }, [src]);
13789
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...chunkJAI42EXQ_js.getImageTilingStyle(element, nativeSize), ...style } });
13329
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...chunkZ22RD3E2_js.getImageTilingStyle(element, nativeSize), ...style } });
13790
13330
  }
13791
13331
  function renderImageEffectDefinitions(element, excludeDuotone = false) {
13792
13332
  return pptx.getImageSvgFilters(element).filter((definition) => !excludeDuotone || definition.id !== `duotone-${element.id}`).map((definition) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -13855,7 +13395,7 @@ function renderImg(el, style, filter, alt, opacity) {
13855
13395
  ...filter ? { filter } : {},
13856
13396
  ...opacity !== void 0 ? { opacity } : {}
13857
13397
  };
13858
- if (chunkJAI42EXQ_js.isImageTiled(el)) {
13398
+ if (chunkZ22RD3E2_js.isImageTiled(el)) {
13859
13399
  const tileSrc = imgSrc(el);
13860
13400
  if (!tileSrc) {
13861
13401
  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 +13417,9 @@ function renderImg(el, style, filter, alt, opacity) {
13877
13417
  pptx$1.isImageLikeElement(el) ? el.imageEffects?.colorWash : void 0
13878
13418
  );
13879
13419
  const clrChange = "imageEffects" in el ? el.imageEffects?.clrChange : void 0;
13880
- const duotoneColors = chunkJAI42EXQ_js.getDuotoneColors(el);
13420
+ const duotoneColors = chunkZ22RD3E2_js.getDuotoneColors(el);
13881
13421
  const useDuotoneCanvas = Boolean(duotoneColors && !clrChange);
13882
- const filterForImg = useDuotoneCanvas ? chunkJAI42EXQ_js.getImageEffectsFilter(el, { excludeDuotone: true }) : filter;
13422
+ const filterForImg = useDuotoneCanvas ? chunkZ22RD3E2_js.getImageEffectsFilter(el, { excludeDuotone: true }) : filter;
13883
13423
  const canvasEffectStyles = {
13884
13424
  ...filterForImg ? { filter: filterForImg } : {},
13885
13425
  ...opacity !== void 0 ? { opacity } : {}
@@ -13955,10 +13495,10 @@ function SlideBackgroundImageLayer({
13955
13495
  style: { zIndex: 0 },
13956
13496
  children: renderImg(
13957
13497
  backgroundElement,
13958
- chunkJAI42EXQ_js.getImageRenderStyle(backgroundElement),
13959
- chunkJAI42EXQ_js.getImageEffectsFilter(backgroundElement),
13498
+ chunkZ22RD3E2_js.getImageRenderStyle(backgroundElement),
13499
+ chunkZ22RD3E2_js.getImageEffectsFilter(backgroundElement),
13960
13500
  "",
13961
- chunkJAI42EXQ_js.getImageEffectsOpacity(backgroundElement)
13501
+ chunkZ22RD3E2_js.getImageEffectsOpacity(backgroundElement)
13962
13502
  )
13963
13503
  }
13964
13504
  );
@@ -14229,7 +13769,7 @@ function ChartElementView({
14229
13769
  onUpdateElement,
14230
13770
  animationState
14231
13771
  }) {
14232
- const { t } = reactI18next.useTranslation();
13772
+ const { t } = chunkZ22RD3E2_js.useTranslation();
14233
13773
  const wrapperRef = React17.useRef(null);
14234
13774
  const { selection, setSelection } = useChartPartSelection();
14235
13775
  const [titleDraft, setTitleDraft] = React17.useState(null);
@@ -14244,7 +13784,7 @@ function ChartElementView({
14244
13784
  pptx.getBarFacePicturePixelSampleVersion
14245
13785
  );
14246
13786
  const viewModel = React17.useMemo(() => {
14247
- return canEdit ? chunkJAI42EXQ_js.buildReactChartViewModel(element) : null;
13787
+ return canEdit ? chunkZ22RD3E2_js.buildReactChartViewModel(element) : null;
14248
13788
  }, [canEdit, element, barFacePictureSampleVersion]);
14249
13789
  React17.useEffect(pptx.ensureChartInteractionStyles, []);
14250
13790
  React17.useEffect(() => {
@@ -14349,9 +13889,9 @@ function ChartElementView({
14349
13889
  textStyle: animationState?.textStyle,
14350
13890
  onSelect: chart3D.onSelect,
14351
13891
  onDrag: chart3D.onDrag,
14352
- children: chunkJAI42EXQ_js.renderChartElement(renderedElement, (key) => t(key))
13892
+ children: chunkZ22RD3E2_js.renderChartElement(renderedElement, (key) => t(key))
14353
13893
  }
14354
- ) : chunkJAI42EXQ_js.renderChartElement(renderedElement, (key) => t(key)),
13894
+ ) : chunkZ22RD3E2_js.renderChartElement(renderedElement, (key) => t(key)),
14355
13895
  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
13896
  titleDraft !== null && /* @__PURE__ */ jsxRuntime.jsx(
14357
13897
  "input",
@@ -14379,7 +13919,7 @@ function ChartElementView({
14379
13919
  );
14380
13920
  }
14381
13921
  function useActionAffordance(element, canInteract) {
14382
- const { t } = reactI18next.useTranslation();
13922
+ const { t } = chunkZ22RD3E2_js.useTranslation();
14383
13923
  pptx.ensureActionAffordanceStyles();
14384
13924
  return React17.useMemo(
14385
13925
  () => pptx.resolveElementActionAffordance(element, {
@@ -14512,6 +14052,50 @@ var EDGE_HANDLES = [
14512
14052
  sizeClass: "w-2 h-5 max-md:w-3 max-md:h-8 rounded-sm"
14513
14053
  }
14514
14054
  ];
14055
+ var wholeDegrees = (deg) => Math.round((deg % 360 + 360) % 360) % 360;
14056
+ function startRotateKnobGesture(options) {
14057
+ const { button, elementId, rotation, onRotate } = options;
14058
+ const scope = button.closest("[data-pptx-viewport]") ?? document;
14059
+ const wrapper = scope.querySelector(pptx.elementIdSelector(elementId));
14060
+ if (!wrapper) {
14061
+ return;
14062
+ }
14063
+ const rect = wrapper.getBoundingClientRect();
14064
+ const base = options.nonRotationTransform ? ` ${options.nonRotationTransform}` : "";
14065
+ const paint = (deg) => {
14066
+ const transform = `rotate(${deg}deg)${base}`;
14067
+ wrapper.style.transform = transform;
14068
+ syncSelectionHandleOverlay(wrapper, elementId, { transform });
14069
+ };
14070
+ if (options.pointerId !== void 0) {
14071
+ button.setPointerCapture?.(options.pointerId);
14072
+ }
14073
+ const gesture = pptx.createGestureController({
14074
+ getScale: () => 1,
14075
+ getElementBox: () => ({
14076
+ x: rect.left,
14077
+ y: rect.top,
14078
+ width: rect.width,
14079
+ height: rect.height,
14080
+ rotation
14081
+ }),
14082
+ getSiblings: () => [],
14083
+ getStageOrigin: () => ({ left: 0, top: 0 }),
14084
+ onStart: () => void 0,
14085
+ onPreview: (transform) => paint(wholeDegrees(transform.rotation)),
14086
+ onEnd: (transform) => {
14087
+ const deg = transform ? wholeDegrees(transform.rotation) : rotation;
14088
+ if (deg !== rotation) {
14089
+ onRotate?.(elementId, deg);
14090
+ }
14091
+ }
14092
+ });
14093
+ gesture.begin("rotate", elementId, {
14094
+ clientX: options.pointer.clientX,
14095
+ clientY: options.pointer.clientY,
14096
+ shiftKey: false
14097
+ });
14098
+ }
14515
14099
  var appearance = { fill: "var(--color-primary)", borderColor: "#ffffff" };
14516
14100
  var cornerSize = "var(--pptx-react-corner-default, 12px)";
14517
14101
  var edgeLength = "var(--pptx-react-edge-length-default, 20px)";
@@ -14613,7 +14197,7 @@ function ResizeHandles({
14613
14197
  nonRotationTransform,
14614
14198
  onRotate
14615
14199
  }) {
14616
- const { t } = reactI18next.useTranslation();
14200
+ const { t } = chunkZ22RD3E2_js.useTranslation();
14617
14201
  const rotateRef = useRotateHandlePlacement(elementId, Boolean(onRotate));
14618
14202
  const peStyle = forcePointerEvents ? { ...HANDLE_TOUCH_ACTION, pointerEvents: "auto" } : HANDLE_TOUCH_ACTION;
14619
14203
  const resizeStyle = { ...HANDLE_TOUCH_ACTION, pointerEvents: "none" };
@@ -14625,50 +14209,15 @@ function ResizeHandles({
14625
14209
  e.currentTarget.setPointerCapture?.(e.pointerId);
14626
14210
  onResizePointerDown(elementId, e, handle);
14627
14211
  };
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
- };
14212
+ const startRotate = (button, pointer) => startRotateKnobGesture({
14213
+ button,
14214
+ elementId,
14215
+ pointer,
14216
+ pointerId: pointer.pointerId,
14217
+ rotation: rotation ?? 0,
14218
+ ...nonRotationTransform ? { nonRotationTransform } : {},
14219
+ ...onRotate ? { onRotate } : {}
14220
+ });
14672
14221
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14673
14222
  [...CORNER_HANDLES, ...EDGE_HANDLES].map(({ handle, posClass, cursor }) => {
14674
14223
  const corner = handle.length === 2;
@@ -14681,7 +14230,7 @@ function ResizeHandles({
14681
14230
  "aria-label": t("pptx.selectionOverlay.resize", { handle }),
14682
14231
  "data-pptx-handle-kind": "resize",
14683
14232
  "data-pptx-compact": true,
14684
- className: chunkJAI42EXQ_js.cn(
14233
+ className: chunkZ22RD3E2_js.cn(
14685
14234
  "absolute z-10 group border-0 bg-transparent p-0",
14686
14235
  RESIZE_DEFAULT_CLASSES,
14687
14236
  posClass,
@@ -14707,7 +14256,7 @@ function ResizeHandles({
14707
14256
  "div",
14708
14257
  {
14709
14258
  "data-pptx-handle-hit": true,
14710
- className: chunkJAI42EXQ_js.cn(
14259
+ className: chunkZ22RD3E2_js.cn(
14711
14260
  "absolute -inset-px pointer-events-auto [--pptx-handle-hit-inset:-1px]",
14712
14261
  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
14262
  ),
@@ -14728,7 +14277,7 @@ function ResizeHandles({
14728
14277
  "aria-label": t("pptx.selectionOverlay.rotate"),
14729
14278
  "data-pptx-handle-kind": "rotate",
14730
14279
  "data-pptx-compact": true,
14731
- className: chunkJAI42EXQ_js.cn(
14280
+ className: chunkZ22RD3E2_js.cn(
14732
14281
  "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
14282
  ROTATE_DEFAULT_CLASSES
14734
14283
  ),
@@ -14739,7 +14288,7 @@ function ResizeHandles({
14739
14288
  },
14740
14289
  onPointerDown: (e) => {
14741
14290
  e.stopPropagation();
14742
- startRotate(e.currentTarget, e, e.pointerId);
14291
+ startRotate(e.currentTarget, e);
14743
14292
  },
14744
14293
  onMouseDown: (e) => {
14745
14294
  e.stopPropagation();
@@ -14805,10 +14354,10 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14805
14354
  const svgHeight = Math.max(el.height, 1);
14806
14355
  const ss = shapeEl?.shapeStyle;
14807
14356
  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(
14357
+ const strokeColor = chunkZ22RD3E2_js.normalizeHexColor(ss?.strokeColor, chunkZ22RD3E2_js.DEFAULT_STROKE_COLOR);
14358
+ const strokePaint = chunkZ22RD3E2_js.colorWithOpacity(strokeColor, ss?.strokeOpacity);
14359
+ const dashType = chunkZ22RD3E2_js.normalizeStrokeDashType(ss?.strokeDash);
14360
+ const dashArray = chunkZ22RD3E2_js.getSvgStrokeDasharray(
14812
14361
  dashType,
14813
14362
  Math.max(strokeWidth, 1),
14814
14363
  ss?.customDashSegments
@@ -14819,14 +14368,14 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14819
14368
  const markerSeed = el.id.replace(/[^a-zA-Z0-9_-]/gu, "_");
14820
14369
  const startMarkerId = `${markerSeed}-sel-start`;
14821
14370
  const endMarkerId = `${markerSeed}-sel-end`;
14822
- const compoundOffsets = chunkJAI42EXQ_js.getCompoundLineOffsets(compoundLine, strokeWidth);
14823
- const compoundWidths = chunkJAI42EXQ_js.getCompoundLineWidths(compoundLine, strokeWidth);
14371
+ const compoundOffsets = chunkZ22RD3E2_js.getCompoundLineOffsets(compoundLine, strokeWidth);
14372
+ const compoundWidths = chunkZ22RD3E2_js.getCompoundLineWidths(compoundLine, strokeWidth);
14824
14373
  const strokeCap = pptx.svgLineCap(ss?.lineCap);
14825
14374
  const textEl = pptx$1.hasTextProperties(el) ? el : void 0;
14826
14375
  const connectorText = textEl?.text?.trim() ?? "";
14827
14376
  const connectorTextSegments = textEl?.textSegments;
14828
14377
  const connectorTextStyle = textEl?.textStyle;
14829
- const pathGeometry = shapeEl ? chunkJAI42EXQ_js.getConnectorPathGeometry(shapeEl) : {
14378
+ const pathGeometry = shapeEl ? chunkZ22RD3E2_js.getConnectorPathGeometry(shapeEl) : {
14830
14379
  pathData: `M 0 0 L ${viewWidth} ${viewHeight}`,
14831
14380
  startX: 0,
14832
14381
  startY: 0,
@@ -14835,16 +14384,16 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14835
14384
  };
14836
14385
  const hitTargetWidth = Math.max(strokeWidth * 3, 14);
14837
14386
  const selColor = selClr === "blue-400" ? "#60a5fa" : "#3b82f6";
14838
- const lineShadow = chunkJAI42EXQ_js.buildLineShadowCss(el);
14839
- const lineGlow = chunkJAI42EXQ_js.buildLineGlowFilter(el);
14387
+ const lineShadow = chunkZ22RD3E2_js.buildLineShadowCss(el);
14388
+ const lineGlow = chunkZ22RD3E2_js.buildLineGlowFilter(el);
14840
14389
  return /* @__PURE__ */ jsxRuntime.jsxs(
14841
14390
  "div",
14842
14391
  {
14843
14392
  "data-pptx-element": "true",
14844
14393
  "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),
14394
+ role: chunkZ22RD3E2_js.getAriaRole(el, { actionable: false }),
14395
+ "aria-label": chunkZ22RD3E2_js.getAriaLabel(el),
14396
+ "aria-roledescription": chunkZ22RD3E2_js.getAriaRoleDescription(el),
14848
14397
  "aria-selected": isSelected ? true : void 0,
14849
14398
  className: "absolute",
14850
14399
  style: {
@@ -14877,14 +14426,14 @@ var ConnectorElementRendererMemo = /* @__PURE__ */ React17__default.default.memo
14877
14426
  style: { overflow: "visible", pointerEvents: "none" },
14878
14427
  children: [
14879
14428
  /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
14880
- chunkJAI42EXQ_js.renderConnectorMarker(
14429
+ chunkZ22RD3E2_js.renderConnectorMarker(
14881
14430
  startMarkerId,
14882
14431
  startArrow,
14883
14432
  strokePaint,
14884
14433
  ss?.connectorStartArrowWidth,
14885
14434
  ss?.connectorStartArrowLength
14886
14435
  ),
14887
- chunkJAI42EXQ_js.renderConnectorMarker(
14436
+ chunkZ22RD3E2_js.renderConnectorMarker(
14888
14437
  endMarkerId,
14889
14438
  endArrow,
14890
14439
  strokePaint,
@@ -15093,14 +14642,14 @@ function getElementInteractionProps({
15093
14642
  };
15094
14643
  }
15095
14644
  function renderDagDuotoneFilterForElement(el) {
15096
- if (!chunkJAI42EXQ_js.hasDagDuotoneEffect(el)) {
14645
+ if (!chunkZ22RD3E2_js.hasDagDuotoneEffect(el)) {
15097
14646
  return null;
15098
14647
  }
15099
14648
  const duotone = el.shapeStyle?.dagDuotone;
15100
14649
  if (!duotone) {
15101
14650
  return null;
15102
14651
  }
15103
- return chunkJAI42EXQ_js.renderDagDuotoneSvgFilter(el.id, duotone.color1, duotone.color2);
14652
+ return chunkZ22RD3E2_js.renderDagDuotoneSvgFilter(el.id, duotone.color1, duotone.color2);
15104
14653
  }
15105
14654
  function getContainerStyle({
15106
14655
  el,
@@ -15127,10 +14676,10 @@ function getContainerStyle({
15127
14676
  top: isFullscreenMedia ? fs.top : el.y,
15128
14677
  width: isFullscreenMedia ? fs.width : painted.width,
15129
14678
  ...heightStyle,
15130
- transform: isFullscreenMedia ? fs.transform : chunkJAI42EXQ_js.getElementTransform(el),
14679
+ transform: isFullscreenMedia ? fs.transform : chunkZ22RD3E2_js.getElementTransform(el),
15131
14680
  transformOrigin: "center",
15132
14681
  overflow: overflowValue,
15133
- clipPath: isPicture ? void 0 : isImg && !has3DExtrusion ? chunkJAI42EXQ_js.getCropShapeClipPath(el) : void 0,
14682
+ clipPath: isPicture ? void 0 : isImg && !has3DExtrusion ? chunkZ22RD3E2_js.getCropShapeClipPath(el) : void 0,
15134
14683
  zIndex: isFullscreenMedia ? fs.zIndex : zIndex,
15135
14684
  visibility: animationState?.visible === false ? "hidden" : "visible",
15136
14685
  animation: animationState?.cssAnimation,
@@ -15167,9 +14716,9 @@ function getContainerStyle({
15167
14716
  function shapeParams(element) {
15168
14717
  const style = pptx$1.hasShapeProperties(element) ? element.shapeStyle : void 0;
15169
14718
  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);
14719
+ const strokeColor = chunkZ22RD3E2_js.normalizeHexColor(style?.strokeColor, chunkZ22RD3E2_js.DEFAULT_STROKE_COLOR);
14720
+ const fillColor = chunkZ22RD3E2_js.normalizeHexColor(style?.fillColor, chunkZ22RD3E2_js.DEFAULT_FILL_COLOR);
14721
+ const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkZ22RD3E2_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
15173
14722
  return { hf: hasFill, fc: fillColor, sw: strokeWidth, sc: strokeColor };
15174
14723
  }
15175
14724
  var Extrusion3DOverlayMemo = /* @__PURE__ */ React17__default.default.memo(
@@ -15277,7 +14826,7 @@ function ShapeEffectOverlay({
15277
14826
  const fillOverlayStyle = overlay ? {
15278
14827
  position: "absolute",
15279
14828
  inset: 0,
15280
- ...pptx$1.isImageLikeElement(element) ? chunkJAI42EXQ_js.getImageSurfaceMaskStyle(element) : {},
14829
+ ...pptx$1.isImageLikeElement(element) ? chunkZ22RD3E2_js.getImageSurfaceMaskStyle(element) : {},
15281
14830
  background: overlay.color,
15282
14831
  mixBlendMode: overlay.blendMode,
15283
14832
  pointerEvents: "none"
@@ -15484,10 +15033,10 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15484
15033
  const backgroundAnimationState = pptx.getBackgroundAnimationState(el, presentationElementStates);
15485
15034
  const effectPlacement = pptx.getShapeEffectLayerPlacement(el);
15486
15035
  const visualAnimationState = backgroundAnimationState ?? animationState;
15487
- const isTxt = chunkJAI42EXQ_js.isEditableTextElement(el) && allow.textEditable;
15036
+ const isTxt = chunkZ22RD3E2_js.isEditableTextElement(el) && allow.textEditable;
15488
15037
  const txtSE = pptx$1.hasTextProperties(el) ? el.textStyle : void 0;
15489
15038
  const textStyleOverrideCss = pptx.buildTextStyleOverrideCss(el.id, visualAnimationState?.textStyle);
15490
- const ss = chunkJAI42EXQ_js.getShapeVisualStyle(
15039
+ const ss = chunkZ22RD3E2_js.getShapeVisualStyle(
15491
15040
  el,
15492
15041
  hf,
15493
15042
  fc,
@@ -15496,9 +15045,9 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15496
15045
  visualAnimationState?.animatesFill,
15497
15046
  visualAnimationState?.animatesStroke
15498
15047
  );
15499
- const ts = chunkJAI42EXQ_js.getTextStyleForElement(el, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR);
15048
+ const ts = chunkZ22RD3E2_js.getTextStyleForElement(el, chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR);
15500
15049
  const isImg = el.type === "picture" || el.type === "image";
15501
- const vs = chunkJAI42EXQ_js.renderVectorShape(
15050
+ const vs = chunkZ22RD3E2_js.renderVectorShape(
15502
15051
  el,
15503
15052
  isImg ? false : hf,
15504
15053
  fc,
@@ -15508,10 +15057,10 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15508
15057
  visualAnimationState?.animatesStroke
15509
15058
  );
15510
15059
  const isModel3D = el.type === "model3d";
15511
- const isConn = chunkJAI42EXQ_js.isConnectorOrLineElement(el);
15060
+ const isConn = chunkZ22RD3E2_js.isConnectorOrLineElement(el);
15512
15061
  const shapeStyle3d = pptx$1.hasShapeProperties(el) ? el.shapeStyle : void 0;
15513
15062
  const extrusionData = React17.useMemo(
15514
- () => chunkJAI42EXQ_js.build3DExtrusionData(shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height),
15063
+ () => chunkZ22RD3E2_js.build3DExtrusionData(shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height),
15515
15064
  [shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height]
15516
15065
  );
15517
15066
  const actionAffordance = useActionAffordance(el, canInteract);
@@ -15601,7 +15150,7 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15601
15150
  "aria-hidden": aria.hidden ? true : void 0,
15602
15151
  "aria-selected": isSelected ? true : void 0,
15603
15152
  tabIndex: isFocusable ? 0 : -1,
15604
- className: chunkJAI42EXQ_js.cn(
15153
+ className: chunkZ22RD3E2_js.cn(
15605
15154
  "absolute",
15606
15155
  "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500",
15607
15156
  cur,
@@ -15674,9 +15223,9 @@ var ElementRenderer = /* @__PURE__ */ React17__default.default.memo(
15674
15223
  txtSE,
15675
15224
  txtS: ts,
15676
15225
  vecShape: backgroundAnimationState && !isImg ? null : vs,
15677
- imgStyle: chunkJAI42EXQ_js.getImageRenderStyle(el),
15678
- imgFilter: chunkJAI42EXQ_js.getImageEffectsFilter(el),
15679
- imgOpacity: chunkJAI42EXQ_js.getImageEffectsOpacity(el),
15226
+ imgStyle: chunkZ22RD3E2_js.getImageRenderStyle(el),
15227
+ imgFilter: chunkZ22RD3E2_js.getImageEffectsFilter(el),
15228
+ imgOpacity: chunkZ22RD3E2_js.getImageEffectsOpacity(el),
15680
15229
  imgAlt: imageAltText,
15681
15230
  isTxtEl: isTxt,
15682
15231
  media: mediaDataUrls,
@@ -15813,10 +15362,10 @@ function renderStrokeView(view, pressureSensitive, replayStyle, key) {
15813
15362
  }
15814
15363
  function renderInk(el, options) {
15815
15364
  const replay = options?.replay ?? false;
15816
- const strokes = chunkJAI42EXQ_js.buildInkGroupStrokes(el, { color: "#000", width: 3 });
15365
+ const strokes = chunkZ22RD3E2_js.buildInkGroupStrokes(el, { color: "#000", width: 3 });
15817
15366
  strokes.some((s) => s.circles || s.nibMarks);
15818
15367
  const pressureSensitive = options?.pressureSensitive;
15819
- const replayStyles = replay ? chunkJAI42EXQ_js.getInkReplayStyles(el, options?.replayConfig) : null;
15368
+ const replayStyles = replay ? chunkZ22RD3E2_js.getInkReplayStyles(el, options?.replayConfig) : null;
15820
15369
  return /* @__PURE__ */ jsxRuntime.jsxs(
15821
15370
  "svg",
15822
15371
  {
@@ -15824,7 +15373,7 @@ function renderInk(el, options) {
15824
15373
  viewBox: `0 0 ${Math.max(el.width, 1)} ${Math.max(el.height, 1)}`,
15825
15374
  preserveAspectRatio: "none",
15826
15375
  children: [
15827
- replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJAI42EXQ_js.INK_REPLAY_KEYFRAMES }),
15376
+ replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkZ22RD3E2_js.INK_REPLAY_KEYFRAMES }),
15828
15377
  strokes.map(
15829
15378
  (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-ink-${i}`)
15830
15379
  )
@@ -15835,7 +15384,7 @@ function renderInk(el, options) {
15835
15384
  function renderGroup(children, parentGroupFill) {
15836
15385
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full h-full pointer-events-none", children: pptx.filterRenderedElements(children).map((c, childIndex) => {
15837
15386
  const { hf, fc, sw, sc } = shapeParams(c);
15838
- const baseSs = chunkJAI42EXQ_js.getShapeVisualStyle(c, hf, fc, sw, sc);
15387
+ const baseSs = chunkZ22RD3E2_js.getShapeVisualStyle(c, hf, fc, sw, sc);
15839
15388
  const inheritedFill = pptx.resolveGroupChildFill(c, parentGroupFill);
15840
15389
  const ss = inheritedFill ? {
15841
15390
  ...baseSs,
@@ -15846,9 +15395,9 @@ function renderGroup(children, parentGroupFill) {
15846
15395
  backgroundPosition: inheritedFill.backgroundPosition
15847
15396
  } : baseSs;
15848
15397
  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);
15398
+ const vs = chunkZ22RD3E2_js.renderVectorShape(c, isI ? false : hf, fc, sw, sc);
15399
+ const ts = chunkZ22RD3E2_js.getTextStyleForElement(c, chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR);
15400
+ const isTxt = chunkZ22RD3E2_js.isEditableTextElement(c);
15852
15401
  return /* @__PURE__ */ jsxRuntime.jsxs(
15853
15402
  "div",
15854
15403
  {
@@ -15857,9 +15406,9 @@ function renderGroup(children, parentGroupFill) {
15857
15406
  style: {
15858
15407
  left: c.x,
15859
15408
  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),
15409
+ width: Math.max(c.width, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE),
15410
+ height: Math.max(c.height, chunkZ22RD3E2_js.MIN_ELEMENT_SIZE),
15411
+ transform: chunkZ22RD3E2_js.getElementTransform(c),
15863
15412
  transformOrigin: "center",
15864
15413
  ...ss,
15865
15414
  ...isI ? {
@@ -15884,8 +15433,8 @@ function renderGroup(children, parentGroupFill) {
15884
15433
  // A nested group: recurse, chaining the inherited fill so a
15885
15434
  // `grpFill` shape under a fill-less sub-group still paints.
15886
15435
  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(
15436
+ ) : isI && ("svgData" in c && c.svgData || "imageData" in c && c.imageData) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkZ22RD3E2_js.getImageSurfaceStyle(c), children: [
15437
+ chunkZ22RD3E2_js.isImageTiled(c) ? /* @__PURE__ */ jsxRuntime.jsx(
15889
15438
  TiledImageLayer,
15890
15439
  {
15891
15440
  element: c,
@@ -15898,7 +15447,7 @@ function renderGroup(children, parentGroupFill) {
15898
15447
  src: "svgData" in c && c.svgData ? c.svgData : c.imageData,
15899
15448
  alt: i18n.translationsEn["pptx.ink.groupChildAlt"],
15900
15449
  className: "pointer-events-none select-none",
15901
- style: chunkJAI42EXQ_js.getImageRenderStyle(c),
15450
+ style: chunkZ22RD3E2_js.getImageRenderStyle(c),
15902
15451
  draggable: false
15903
15452
  }
15904
15453
  ),
@@ -15910,7 +15459,7 @@ function renderGroup(children, parentGroupFill) {
15910
15459
  {
15911
15460
  className: "relative z-10 w-full h-full pointer-events-none whitespace-pre-wrap break-words leading-[1.3]",
15912
15461
  style: ts,
15913
- children: chunkJAI42EXQ_js.renderTextSegments(c, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR)
15462
+ children: chunkZ22RD3E2_js.renderTextSegments(c, chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR)
15914
15463
  }
15915
15464
  ) : null
15916
15465
  ] })
@@ -15924,8 +15473,8 @@ function renderContentPart(el, options) {
15924
15473
  if (el.inkStrokes && el.inkStrokes.length > 0) {
15925
15474
  const replay = options?.replay ?? false;
15926
15475
  const pressureSensitive = options?.pressureSensitive ?? true;
15927
- const strokes = chunkJAI42EXQ_js.buildContentPartStrokes(el);
15928
- const replayStyles = replay ? chunkJAI42EXQ_js.getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
15476
+ const strokes = chunkZ22RD3E2_js.buildContentPartStrokes(el);
15477
+ const replayStyles = replay ? chunkZ22RD3E2_js.getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
15929
15478
  return /* @__PURE__ */ jsxRuntime.jsxs(
15930
15479
  "svg",
15931
15480
  {
@@ -15933,7 +15482,7 @@ function renderContentPart(el, options) {
15933
15482
  viewBox: `0 0 ${Math.max(el.width, 1)} ${Math.max(el.height, 1)}`,
15934
15483
  preserveAspectRatio: "none",
15935
15484
  children: [
15936
- replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkJAI42EXQ_js.INK_REPLAY_KEYFRAMES }),
15485
+ replay && /* @__PURE__ */ jsxRuntime.jsx("style", { children: chunkZ22RD3E2_js.INK_REPLAY_KEYFRAMES }),
15937
15486
  strokes.map(
15938
15487
  (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-cp-ink-${i}`)
15939
15488
  )
@@ -16160,9 +15709,9 @@ function useInlineListEditor(element, rootRef, onChange, onModelReplacement) {
16160
15709
  collaboration: connected,
16161
15710
  model: pptx.createInlineListModelObserver(element),
16162
15711
  activationSelection,
16163
- children: seed && !connected ? chunkJAI42EXQ_js.renderTextSegments(
15712
+ children: seed && !connected ? chunkZ22RD3E2_js.renderTextSegments(
16164
15713
  element,
16165
- chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
15714
+ chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR,
16166
15715
  void 0,
16167
15716
  void 0,
16168
15717
  void 0,
@@ -16398,8 +15947,8 @@ function InlineTextEditor({
16398
15947
  pending.endOffset
16399
15948
  );
16400
15949
  });
16401
- const warpStyle = chunkJAI42EXQ_js.getTextWarpStyle(textStyleRaw);
16402
- const compensationTransform = chunkJAI42EXQ_js.getTextCompensationTransform(element);
15950
+ const warpStyle = chunkZ22RD3E2_js.getTextWarpStyle(textStyleRaw);
15951
+ const compensationTransform = chunkZ22RD3E2_js.getTextCompensationTransform(element);
16403
15952
  const warpTransform = warpStyle?.transform;
16404
15953
  const mergedTransform = [compensationTransform, warpTransform].filter(Boolean).join(" ") || void 0;
16405
15954
  const wrapperStyle = {
@@ -16487,7 +16036,7 @@ function InlineTextEditor({
16487
16036
  const text = e.clipboardData.getData("text/plain");
16488
16037
  document.execCommand("insertText", false, text);
16489
16038
  },
16490
- children: list.seed ? list.children : seed.hasRichSegments ? chunkJAI42EXQ_js.renderTextSegments(element, chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR) : seed.initialText
16039
+ children: list.seed ? list.children : seed.hasRichSegments ? chunkZ22RD3E2_js.renderTextSegments(element, chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR) : seed.initialText
16491
16040
  },
16492
16041
  list.seed?.paragraphs[0].token ?? "plain"
16493
16042
  );
@@ -16652,7 +16201,7 @@ function OleActionFooter({
16652
16201
  info,
16653
16202
  showActions
16654
16203
  }) {
16655
- const { t } = reactI18next.useTranslation();
16204
+ const { t } = chunkZ22RD3E2_js.useTranslation();
16656
16205
  if (!showActions || !info.canDownload || !el.oleEmbeddedData) {
16657
16206
  return null;
16658
16207
  }
@@ -16761,7 +16310,7 @@ function SmartArtInlineNodeEditor({
16761
16310
  onCommit,
16762
16311
  onCancel
16763
16312
  }) {
16764
- const { t } = reactI18next.useTranslation();
16313
+ const { t } = chunkZ22RD3E2_js.useTranslation();
16765
16314
  const ref = React17__default.default.useRef(null);
16766
16315
  const [value, setValue] = React17__default.default.useState(initialText);
16767
16316
  const settled = React17__default.default.useRef(false);
@@ -17388,7 +16937,7 @@ function SmartArtRendererImpl({
17388
16937
  onUpdateElement,
17389
16938
  animationState
17390
16939
  }) {
17391
- const { t } = reactI18next.useTranslation();
16940
+ const { t } = chunkZ22RD3E2_js.useTranslation();
17392
16941
  if (element.type !== "smartArt" || !element.smartArtData) {
17393
16942
  return /* @__PURE__ */ jsxRuntime.jsx(
17394
16943
  "div",
@@ -17634,7 +17183,7 @@ function groupIntoParagraphs(element, fieldContext) {
17634
17183
  element,
17635
17184
  fieldContext ? (seg) => {
17636
17185
  if (seg.fieldType) {
17637
- const substituted = chunkJAI42EXQ_js.substituteFieldText(
17186
+ const substituted = chunkZ22RD3E2_js.substituteFieldText(
17638
17187
  seg.text,
17639
17188
  seg.fieldType,
17640
17189
  fieldContext,
@@ -17669,13 +17218,13 @@ function getSegmentTspanProps(segment, element, fallbackColor) {
17669
17218
  if (s.strikethrough) {
17670
17219
  decos.push("line-through");
17671
17220
  }
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);
17221
+ const fill = s.hyperlink ? chunkZ22RD3E2_js.normalizeHexColor(s.color || element.textStyle?.color, chunkZ22RD3E2_js.HYPERLINK_COLOR) : chunkZ22RD3E2_js.normalizeHexColor(s.color || element.textStyle?.color, fallbackColor);
17673
17222
  return {
17674
17223
  fill,
17675
- fontSize: s.fontSize ?? element.textStyle?.fontSize ?? chunkJAI42EXQ_js.DEFAULT_TEXT_FONT_SIZE,
17224
+ fontSize: s.fontSize ?? element.textStyle?.fontSize ?? chunkZ22RD3E2_js.DEFAULT_TEXT_FONT_SIZE,
17676
17225
  fontWeight: pptx.resolveFontWeight(s.fontFamily || element.textStyle?.fontFamily, s.bold),
17677
17226
  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,
17227
+ fontFamily: s.fontFamily || element.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(s.fontFamily || element.textStyle?.fontFamily || "") : chunkZ22RD3E2_js.DEFAULT_FONT_FAMILY,
17679
17228
  textDecoration: decos.length > 0 ? decos.join(" ") : void 0
17680
17229
  };
17681
17230
  }
@@ -17683,8 +17232,8 @@ function resolveSegmentFont(segment, element) {
17683
17232
  const s = segment.style || {};
17684
17233
  const family = s.fontFamily || element.textStyle?.fontFamily;
17685
17234
  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,
17235
+ fontFamily: family ? pptx$1.getSubstituteFontFamily(family) : chunkZ22RD3E2_js.DEFAULT_FONT_FAMILY,
17236
+ fontSizePx: s.fontSize ?? element.textStyle?.fontSize ?? chunkZ22RD3E2_js.DEFAULT_TEXT_FONT_SIZE,
17688
17237
  bold: s.bold ?? element.textStyle?.bold,
17689
17238
  italic: s.italic ?? element.textStyle?.italic
17690
17239
  };
@@ -17768,9 +17317,9 @@ function WarpedText({
17768
17317
  const warpAdj2 = textEl.textStyle?.textWarpAdj2;
17769
17318
  const align = textEl.textStyle?.align ?? "center";
17770
17319
  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);
17320
+ const baseFontSize = textEl.textStyle?.fontSize ?? chunkZ22RD3E2_js.DEFAULT_TEXT_FONT_SIZE;
17321
+ const baseFontFamily = textEl.textStyle?.fontFamily ? pptx$1.getSubstituteFontFamily(textEl.textStyle.fontFamily) : chunkZ22RD3E2_js.DEFAULT_FONT_FAMILY;
17322
+ const baseFill = chunkZ22RD3E2_js.normalizeHexColor(textEl.textStyle?.color, fallbackColor);
17774
17323
  if (pptx.hasGlyphEnvelope(preset)) {
17775
17324
  const perLine = pptx.buildGlyphEnvelopeBlock(
17776
17325
  preset,
@@ -17872,7 +17421,7 @@ function WarpedText({
17872
17421
  var GLYPH_BY_SHAPE = /* @__PURE__ */ buildGlyphByShape();
17873
17422
  function buildGlyphByShape() {
17874
17423
  const glyphs = Object.fromEntries(
17875
- chunkJAI42EXQ_js.ACTION_BUTTON_PRESETS.map((p) => [p.shapeType, p.iconPath])
17424
+ chunkZ22RD3E2_js.ACTION_BUTTON_PRESETS.map((p) => [p.shapeType, p.iconPath])
17876
17425
  );
17877
17426
  glyphs["actionButtonForwardOrNext"] = glyphs["actionButtonForwardNext"];
17878
17427
  glyphs["actionButtonBackOrPrevious"] = glyphs["actionButtonBackPrevious"];
@@ -17946,9 +17495,9 @@ function renderTextElementBody(options) {
17946
17495
  const useSvgWarp = pptx.shouldUseSvgWarp(
17947
17496
  pptx$1.hasTextProperties(el) ? el.textStyle?.textWarpPreset : void 0
17948
17497
  );
17949
- const scene3dStyle = pptx$1.hasTextProperties(el) ? chunkJAI42EXQ_js.buildTextBody3DSceneStyle(el.textStyle, { width: el.width, height: el.height }) : void 0;
17498
+ const scene3dStyle = pptx$1.hasTextProperties(el) ? chunkZ22RD3E2_js.buildTextBody3DSceneStyle(el.textStyle, { width: el.width, height: el.height }) : void 0;
17950
17499
  const rotationTransform = pptx.getTextBodyRotationTransform(el);
17951
- const composedTransform = [rotationTransform, chunkJAI42EXQ_js.getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
17500
+ const composedTransform = [rotationTransform, chunkZ22RD3E2_js.getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
17952
17501
  const transformStyle = {
17953
17502
  transform: composedTransform,
17954
17503
  // A COM-measured homography (`scene3dStyle.transformOrigin === '0 0'`)
@@ -17978,18 +17527,18 @@ function renderTextElementBody(options) {
17978
17527
  shouldRenderText && (useSvgWarp ? /* @__PURE__ */ jsxRuntime.jsx(
17979
17528
  "div",
17980
17529
  {
17981
- className: chunkJAI42EXQ_js.cn(
17530
+ className: chunkZ22RD3E2_js.cn(
17982
17531
  "relative z-10 w-full h-full",
17983
17532
  onHyperlinkClick ? "" : "pointer-events-none"
17984
17533
  ),
17985
- style: { ...chunkJAI42EXQ_js.getTextLayoutStyle(el), ...transformStyle },
17534
+ style: { ...chunkZ22RD3E2_js.getTextLayoutStyle(el), ...transformStyle },
17986
17535
  children: /* @__PURE__ */ jsxRuntime.jsx(
17987
17536
  WarpedText,
17988
17537
  {
17989
17538
  element: el,
17990
17539
  width: el.width,
17991
17540
  height: el.height,
17992
- fallbackColor: chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
17541
+ fallbackColor: chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR,
17993
17542
  findHighlights: findHl,
17994
17543
  fieldContext
17995
17544
  }
@@ -17998,19 +17547,19 @@ function renderTextElementBody(options) {
17998
17547
  ) : /* @__PURE__ */ jsxRuntime.jsx(
17999
17548
  "div",
18000
17549
  {
18001
- className: chunkJAI42EXQ_js.cn(
17550
+ className: chunkZ22RD3E2_js.cn(
18002
17551
  "relative z-10 w-full h-full whitespace-pre-wrap break-words leading-[1.3]",
18003
17552
  onHyperlinkClick ? "" : "pointer-events-none"
18004
17553
  ),
18005
17554
  style: {
18006
- ...chunkJAI42EXQ_js.getTextLayoutStyle(el),
17555
+ ...chunkZ22RD3E2_js.getTextLayoutStyle(el),
18007
17556
  ...txtS,
18008
- ...chunkJAI42EXQ_js.getTextWarpStyle(txtSE),
17557
+ ...chunkZ22RD3E2_js.getTextWarpStyle(txtSE),
18009
17558
  ...transformStyle
18010
17559
  },
18011
- children: chunkJAI42EXQ_js.renderTextSegments(
17560
+ children: chunkZ22RD3E2_js.renderTextSegments(
18012
17561
  el,
18013
- chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR,
17562
+ chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR,
18014
17563
  void 0,
18015
17564
  findHl,
18016
17565
  onHyperlinkClick,
@@ -18031,7 +17580,7 @@ function ZoomElementRenderer({
18031
17580
  onZoomClick,
18032
17581
  sourceSlideIndex
18033
17582
  }) {
18034
- const { t } = reactI18next.useTranslation();
17583
+ const { t } = chunkZ22RD3E2_js.useTranslation();
18035
17584
  const summaryView = pptx.buildSummaryZoomView(
18036
17585
  element,
18037
17586
  (index) => {
@@ -18329,7 +17878,7 @@ function renderBody(options) {
18329
17878
  );
18330
17879
  }
18331
17880
  if (isImg) {
18332
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkJAI42EXQ_js.getImageSurfaceStyle(el), children: [
17881
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", style: chunkZ22RD3E2_js.getImageSurfaceStyle(el), children: [
18333
17882
  renderImg(el, imgStyle, imgFilter, imgAlt, imgOpacity),
18334
17883
  vecShape ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0", children: vecShape }) : null
18335
17884
  ] });
@@ -18346,7 +17895,7 @@ function renderBody(options) {
18346
17895
  textDirection: txtSE?.textDirection,
18347
17896
  textStyle: txtS,
18348
17897
  textStyleRaw: txtSE,
18349
- layoutStyle: chunkJAI42EXQ_js.getTextLayoutStyle(el),
17898
+ layoutStyle: chunkZ22RD3E2_js.getTextLayoutStyle(el),
18350
17899
  element: el,
18351
17900
  onCommit,
18352
17901
  onCancel,
@@ -18357,7 +17906,7 @@ function renderBody(options) {
18357
17906
  ] });
18358
17907
  }
18359
17908
  if (el.type === "table") {
18360
- return chunkJAI42EXQ_js.renderTableElement(el, txtS, {
17909
+ return chunkZ22RD3E2_js.renderTableElement(el, txtS, {
18361
17910
  editable: isSel,
18362
17911
  selectedCell: isSel ? tableSt : null,
18363
17912
  onSelectCell: onCellSel,
@@ -18390,7 +17939,7 @@ function renderBody(options) {
18390
17939
  );
18391
17940
  }
18392
17941
  if (el.type === "media") {
18393
- return chunkJAI42EXQ_js.renderMediaElement(el, media, {
17942
+ return chunkZ22RD3E2_js.renderMediaElement(el, media, {
18394
17943
  // Present mode autoplays every media element on the active slide,
18395
17944
  // not only ones persisted with their own `autoPlay` flag (matching
18396
17945
  // the other four bindings' unconditional `presenting`-gated
@@ -18442,27 +17991,27 @@ function renderBody(options) {
18442
17991
  }
18443
17992
  return renderGroup(el.children, pptx.getGroupChildParentFill(el));
18444
17993
  }
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) });
17994
+ if (chunkZ22RD3E2_js.shouldRenderFallbackLabel(el, isTxtEl)) {
17995
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: chunkZ22RD3E2_js.getElementLabel(el) });
18447
17996
  }
18448
17997
  return renderTextElementBody(options);
18449
17998
  }
18450
17999
  function defaultTextColorForFill(fillColor) {
18451
18000
  const hex = String(fillColor ?? "").replace(/^#/u, "");
18452
18001
  if (!/^[0-9a-f]{6}$/iu.test(hex)) {
18453
- return chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR;
18002
+ return chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR;
18454
18003
  }
18455
18004
  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
18005
  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";
18006
+ return luminance > 0.179 ? chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR : "#ffffff";
18458
18007
  }
18459
18008
  function getStaticElementVisualState(element, parentGroupFill) {
18460
18009
  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);
18010
+ const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(chunkZ22RD3E2_js.buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
18011
+ const fill = chunkZ22RD3E2_js.normalizeHexColor(style?.fillColor, chunkZ22RD3E2_js.DEFAULT_FILL_COLOR);
18463
18012
  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);
18013
+ const stroke = chunkZ22RD3E2_js.normalizeHexColor(style?.strokeColor, chunkZ22RD3E2_js.DEFAULT_STROKE_COLOR);
18014
+ const baseVisualStyle = chunkZ22RD3E2_js.getShapeVisualStyle(element, hasFill, fill, strokeWidth, stroke);
18466
18015
  const inheritedFill = pptx.resolveGroupChildFill(element, parentGroupFill);
18467
18016
  const visualStyle = inheritedFill ? {
18468
18017
  ...baseVisualStyle,
@@ -18472,9 +18021,9 @@ function getStaticElementVisualState(element, parentGroupFill) {
18472
18021
  backgroundSize: inheritedFill.backgroundSize,
18473
18022
  backgroundPosition: inheritedFill.backgroundPosition
18474
18023
  } : baseVisualStyle;
18475
- const textStyle = chunkJAI42EXQ_js.getTextStyleForElement(
18024
+ const textStyle = chunkZ22RD3E2_js.getTextStyleForElement(
18476
18025
  element,
18477
- element.type === "shape" && hasFill ? defaultTextColorForFill(fill) : chunkJAI42EXQ_js.DEFAULT_TEXT_COLOR
18026
+ element.type === "shape" && hasFill ? defaultTextColorForFill(fill) : chunkZ22RD3E2_js.DEFAULT_TEXT_COLOR
18478
18027
  );
18479
18028
  const isImage = element.type === "picture" || element.type === "image";
18480
18029
  const letsTextOverflow = pptx$1.hasTextProperties(element) && element.textStyle?.autoFitMode === "shrink" && (element.type === "text" || element.locks?.txBox === true);
@@ -18499,7 +18048,7 @@ function getStaticElementInteractionState(element, hasActionHandler, exposeEleme
18499
18048
  return { action, isActionable, contractRole };
18500
18049
  }
18501
18050
  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";
18051
+ const overflowClass = visual.isImage || visual.strokeWidth > 0 || element.type === "group" || chunkZ22RD3E2_js.isConnectorOrLineElement(element) || visual.isCallout || visual.letsTextOverflow ? "" : "overflow-hidden";
18503
18052
  const pointerClass = isActionable ? "pointer-events-auto cursor-pointer" : "pointer-events-none";
18504
18053
  return `${positioned ? "absolute" : "relative"} ${overflowClass} ${pointerClass}`;
18505
18054
  }
@@ -18582,7 +18131,7 @@ function StaticElementRendererImpl({
18582
18131
  top: positioned ? element.y : void 0,
18583
18132
  width: positioned ? Math.max(element.width, 1) : "100%",
18584
18133
  height: positioned ? Math.max(element.height, 1) : "100%",
18585
- transform: positioned ? chunkJAI42EXQ_js.getElementTransform(element) : void 0,
18134
+ transform: positioned ? chunkZ22RD3E2_js.getElementTransform(element) : void 0,
18586
18135
  transformOrigin: "center",
18587
18136
  zIndex,
18588
18137
  ...visualStyle,
@@ -18625,18 +18174,18 @@ function StaticElementRendererImpl({
18625
18174
  spellCheck: false,
18626
18175
  txtSE: pptx$1.hasTextProperties(element) ? element.textStyle : void 0,
18627
18176
  txtS: textStyle,
18628
- vecShape: chunkJAI42EXQ_js.renderVectorShape(
18177
+ vecShape: chunkZ22RD3E2_js.renderVectorShape(
18629
18178
  element,
18630
18179
  isImage ? false : hasFill,
18631
18180
  fill,
18632
18181
  strokeWidth,
18633
18182
  stroke
18634
18183
  ),
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),
18184
+ imgStyle: imageAnimation ? { ...chunkZ22RD3E2_js.getImageRenderStyle(element), animation: imageAnimation } : chunkZ22RD3E2_js.getImageRenderStyle(element),
18185
+ imgFilter: chunkZ22RD3E2_js.getImageEffectsFilter(element),
18186
+ imgOpacity: chunkZ22RD3E2_js.getImageEffectsOpacity(element),
18638
18187
  imgAlt: "",
18639
- isTxtEl: chunkJAI42EXQ_js.isEditableTextElement(element),
18188
+ isTxtEl: chunkZ22RD3E2_js.isEditableTextElement(element),
18640
18189
  media: mediaDataUrls,
18641
18190
  tableSt: null,
18642
18191
  isSel: false,
@@ -18684,7 +18233,7 @@ function SlideLayer({
18684
18233
  style: {
18685
18234
  width: safeWidth,
18686
18235
  height: safeHeight,
18687
- backgroundColor: slide.backgroundColor ? chunkJAI42EXQ_js.normalizeHexColor(slide.backgroundColor, "#ffffff") : "#ffffff",
18236
+ backgroundColor: slide.backgroundColor ? chunkZ22RD3E2_js.normalizeHexColor(slide.backgroundColor, "#ffffff") : "#ffffff",
18688
18237
  backgroundImage: slide.backgroundImage ? `url(${slide.backgroundImage})` : slide.backgroundGradient ? slide.backgroundGradient : void 0,
18689
18238
  backgroundSize: slide.backgroundImage ? "cover" : void 0,
18690
18239
  backgroundPosition: slide.backgroundImage ? "center" : void 0
@@ -19206,7 +18755,6 @@ exports.Rendering3DFlagsContext = Rendering3DFlagsContext;
19206
18755
  exports.ResizeHandles = ResizeHandles;
19207
18756
  exports.SlideBackgroundImageLayer = SlideBackgroundImageLayer;
19208
18757
  exports.SlideLayer = SlideLayer;
19209
- exports.SmartArtRenderer = SmartArtRenderer;
19210
18758
  exports.StaticElementRenderer = StaticElementRenderer;
19211
18759
  exports.ViewerOptionsContext = ViewerOptionsContext;
19212
18760
  exports.ViewerOptionsStoreContext = ViewerOptionsStoreContext;
@@ -19240,6 +18788,7 @@ exports.useCollaborativeState = useCollaborativeState;
19240
18788
  exports.useComments = useComments;
19241
18789
  exports.useCompatibilityToastsState = useCompatibilityToastsState;
19242
18790
  exports.useContentLifecycle = useContentLifecycle;
18791
+ exports.useController = useController;
19243
18792
  exports.useDerivedElementState = useDerivedElementState;
19244
18793
  exports.useDerivedSlideState = useDerivedSlideState;
19245
18794
  exports.useDialogCustomShows = useDialogCustomShows;