pptx-react-viewer 3.21.0 → 4.1.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 (188) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/{AiChatPanel-UD756KAU.mjs → AiChatPanel-C3ACRWOY.mjs} +4 -4
  3. package/dist/AiChatPanel-C3ACRWOY.mjs.br +0 -0
  4. package/dist/AiChatPanel-C3ACRWOY.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-B3QM7MIC.js → AiChatPanel-GQNSKMP6.js} +25 -25
  6. package/dist/AiChatPanel-GQNSKMP6.js.br +0 -0
  7. package/dist/AiChatPanel-GQNSKMP6.js.gz +0 -0
  8. package/dist/{Area3DChartScene-435BFPLY.js → Area3DChartScene-3I6KB2DN.js} +2 -2
  9. package/dist/{Area3DChartScene-435BFPLY.js.br → Area3DChartScene-3I6KB2DN.js.br} +0 -0
  10. package/dist/Area3DChartScene-3I6KB2DN.js.gz +0 -0
  11. package/dist/{Area3DChartScene-MQKUWVMS.mjs → Area3DChartScene-4TPNRYXS.mjs} +1 -1
  12. package/dist/Area3DChartScene-4TPNRYXS.mjs.br +0 -0
  13. package/dist/Area3DChartScene-4TPNRYXS.mjs.gz +0 -0
  14. package/dist/{Bar3DChartScene-D4GMQGPN.mjs → Bar3DChartScene-V45IUIT7.mjs} +1 -1
  15. package/dist/Bar3DChartScene-V45IUIT7.mjs.br +0 -0
  16. package/dist/Bar3DChartScene-V45IUIT7.mjs.gz +0 -0
  17. package/dist/{Bar3DChartScene-KEYLVYJA.js → Bar3DChartScene-ZSCATOYF.js} +2 -2
  18. package/dist/Bar3DChartScene-ZSCATOYF.js.br +0 -0
  19. package/dist/Bar3DChartScene-ZSCATOYF.js.gz +0 -0
  20. package/dist/{Line3DChartScene-B3AWFXE4.mjs → Line3DChartScene-DCQJEZK6.mjs} +1 -1
  21. package/dist/Line3DChartScene-DCQJEZK6.mjs.br +0 -0
  22. package/dist/Line3DChartScene-DCQJEZK6.mjs.gz +0 -0
  23. package/dist/{Line3DChartScene-JYGXLE56.js → Line3DChartScene-DK55LQ2D.js} +2 -2
  24. package/dist/{Line3DChartScene-JYGXLE56.js.br → Line3DChartScene-DK55LQ2D.js.br} +0 -0
  25. package/dist/Line3DChartScene-DK55LQ2D.js.gz +0 -0
  26. package/dist/{Model3DScene-JF5J6N6W.js → Model3DScene-2WNP4XBP.js} +2 -2
  27. package/dist/Model3DScene-2WNP4XBP.js.br +0 -0
  28. package/dist/Model3DScene-2WNP4XBP.js.gz +0 -0
  29. package/dist/{Model3DScene-4TG4YRVM.mjs → Model3DScene-SA5XMR2D.mjs} +1 -1
  30. package/dist/Model3DScene-SA5XMR2D.mjs.br +0 -0
  31. package/dist/Model3DScene-SA5XMR2D.mjs.gz +0 -0
  32. package/dist/{PieChart3DScene-4BQ6PR7P.mjs → PieChart3DScene-HC2ZWL42.mjs} +1 -1
  33. package/dist/PieChart3DScene-HC2ZWL42.mjs.br +0 -0
  34. package/dist/PieChart3DScene-HC2ZWL42.mjs.gz +0 -0
  35. package/dist/{PieChart3DScene-CCQWSH3W.js → PieChart3DScene-Q75D66HS.js} +2 -2
  36. package/dist/{PieChart3DScene-CCQWSH3W.js.br → PieChart3DScene-Q75D66HS.js.br} +0 -0
  37. package/dist/PieChart3DScene-Q75D66HS.js.gz +0 -0
  38. package/dist/{SmartArt3DScene-QZGIABOK.mjs → SmartArt3DScene-D4VNNPHS.mjs} +124 -19
  39. package/dist/SmartArt3DScene-D4VNNPHS.mjs.br +0 -0
  40. package/dist/SmartArt3DScene-D4VNNPHS.mjs.gz +0 -0
  41. package/dist/{SmartArt3DScene-T236GYUT.js → SmartArt3DScene-NHD7CZJ5.js} +123 -18
  42. package/dist/SmartArt3DScene-NHD7CZJ5.js.br +0 -0
  43. package/dist/SmartArt3DScene-NHD7CZJ5.js.gz +0 -0
  44. package/dist/{SurfaceChart3DScene-FRQC5HBG.mjs → SurfaceChart3DScene-JRMX4PN5.mjs} +1 -1
  45. package/dist/SurfaceChart3DScene-JRMX4PN5.mjs.br +0 -0
  46. package/dist/SurfaceChart3DScene-JRMX4PN5.mjs.gz +0 -0
  47. package/dist/{SurfaceChart3DScene-UVZPT6OD.js → SurfaceChart3DScene-ODS5E6ZG.js} +2 -2
  48. package/dist/{SurfaceChart3DScene-UVZPT6OD.js.br → SurfaceChart3DScene-ODS5E6ZG.js.br} +0 -0
  49. package/dist/SurfaceChart3DScene-ODS5E6ZG.js.gz +0 -0
  50. package/dist/{chunk-EJMDD4VV.mjs → chunk-25CABWCR.mjs} +131 -329
  51. package/dist/chunk-25CABWCR.mjs.br +0 -0
  52. package/dist/chunk-25CABWCR.mjs.gz +0 -0
  53. package/dist/{chunk-BXMPXKV5.mjs → chunk-3B6YIH4K.mjs} +626 -133
  54. package/dist/chunk-3B6YIH4K.mjs.br +0 -0
  55. package/dist/chunk-3B6YIH4K.mjs.gz +0 -0
  56. package/dist/{chunk-BFPIMU6Q.js → chunk-A6JKOHSV.js} +2143 -1644
  57. package/dist/chunk-A6JKOHSV.js.br +0 -0
  58. package/dist/chunk-A6JKOHSV.js.gz +0 -0
  59. package/dist/{chunk-TOOKJUPG.mjs → chunk-GRAARMUW.mjs} +1 -1
  60. package/dist/chunk-GRAARMUW.mjs.br +0 -0
  61. package/dist/chunk-GRAARMUW.mjs.gz +0 -0
  62. package/dist/{chunk-H7QPQ4OR.js → chunk-MQHMMB6V.js} +5 -5
  63. package/dist/chunk-MQHMMB6V.js.br +0 -0
  64. package/dist/chunk-MQHMMB6V.js.gz +0 -0
  65. package/dist/{chunk-M6QJKPU2.js → chunk-NR4MQJM5.js} +1961 -2161
  66. package/dist/chunk-NR4MQJM5.js.br +0 -0
  67. package/dist/chunk-NR4MQJM5.js.gz +0 -0
  68. package/dist/{chunk-M24DEOP6.js → chunk-NXGUR2DO.js} +2 -0
  69. package/dist/chunk-NXGUR2DO.js.br +0 -0
  70. package/dist/chunk-NXGUR2DO.js.gz +0 -0
  71. package/dist/{chunk-R664EPDC.mjs → chunk-PC7H3C5W.mjs} +2 -0
  72. package/dist/chunk-PC7H3C5W.mjs.br +0 -0
  73. package/dist/chunk-PC7H3C5W.mjs.gz +0 -0
  74. package/dist/{chunk-SUZIFHXI.js → chunk-PUALTXTU.js} +182 -182
  75. package/dist/chunk-PUALTXTU.js.br +0 -0
  76. package/dist/chunk-PUALTXTU.js.gz +0 -0
  77. package/dist/{chunk-TMTQJAGK.mjs → chunk-Q6QJOD56.mjs} +2307 -552
  78. package/dist/chunk-Q6QJOD56.mjs.br +0 -0
  79. package/dist/chunk-Q6QJOD56.mjs.gz +0 -0
  80. package/dist/{chunk-T6V342NP.js → chunk-SK2CZQ6P.js} +2313 -551
  81. package/dist/chunk-SK2CZQ6P.js.br +0 -0
  82. package/dist/chunk-SK2CZQ6P.js.gz +0 -0
  83. package/dist/{chunk-HZEOZUUH.mjs → chunk-WLWAYLL6.mjs} +2 -2
  84. package/dist/chunk-WLWAYLL6.mjs.br +0 -0
  85. package/dist/chunk-WLWAYLL6.mjs.gz +0 -0
  86. package/dist/i18n/de.cjs +2 -0
  87. package/dist/i18n/de.cjs.br +0 -0
  88. package/dist/i18n/de.cjs.gz +0 -0
  89. package/dist/i18n/de.mjs +2 -0
  90. package/dist/i18n/de.mjs.br +0 -0
  91. package/dist/i18n/de.mjs.gz +0 -0
  92. package/dist/i18n/es.cjs +2 -0
  93. package/dist/i18n/es.cjs.br +0 -0
  94. package/dist/i18n/es.cjs.gz +0 -0
  95. package/dist/i18n/es.mjs +2 -0
  96. package/dist/i18n/es.mjs.br +0 -0
  97. package/dist/i18n/es.mjs.gz +0 -0
  98. package/dist/i18n/fr.cjs +2 -0
  99. package/dist/i18n/fr.cjs.br +0 -0
  100. package/dist/i18n/fr.cjs.gz +0 -0
  101. package/dist/i18n/fr.mjs +2 -0
  102. package/dist/i18n/fr.mjs.br +0 -0
  103. package/dist/i18n/fr.mjs.gz +0 -0
  104. package/dist/i18n/zh-CN.cjs +2 -0
  105. package/dist/i18n/zh-CN.cjs.br +0 -0
  106. package/dist/i18n/zh-CN.cjs.gz +0 -0
  107. package/dist/i18n/zh-CN.mjs +2 -0
  108. package/dist/i18n/zh-CN.mjs.br +0 -0
  109. package/dist/i18n/zh-CN.mjs.gz +0 -0
  110. package/dist/i18n.js +4 -4
  111. package/dist/i18n.js.br +0 -0
  112. package/dist/i18n.js.gz +0 -0
  113. package/dist/i18n.mjs +1 -1
  114. package/dist/i18n.mjs.br +0 -0
  115. package/dist/i18n.mjs.gz +0 -0
  116. package/dist/index.d.ts +586 -7
  117. package/dist/index.js +52 -48
  118. package/dist/index.js.br +0 -0
  119. package/dist/index.js.gz +0 -0
  120. package/dist/index.mjs +6 -6
  121. package/dist/index.mjs.br +0 -0
  122. package/dist/index.mjs.gz +0 -0
  123. package/dist/internals.d.ts +447 -13
  124. package/dist/internals.js +105 -105
  125. package/dist/internals.js.br +0 -0
  126. package/dist/internals.js.gz +0 -0
  127. package/dist/internals.mjs +4 -4
  128. package/dist/internals.mjs.br +0 -0
  129. package/dist/internals.mjs.gz +0 -0
  130. package/dist/viewer/index.js +32 -32
  131. package/dist/viewer/index.js.br +0 -0
  132. package/dist/viewer/index.js.gz +0 -0
  133. package/dist/viewer/index.mjs +6 -6
  134. package/dist/viewer/index.mjs.br +0 -0
  135. package/dist/viewer/index.mjs.gz +0 -0
  136. package/package.json +2 -2
  137. package/dist/AiChatPanel-B3QM7MIC.js.br +0 -0
  138. package/dist/AiChatPanel-B3QM7MIC.js.gz +0 -0
  139. package/dist/AiChatPanel-UD756KAU.mjs.br +0 -0
  140. package/dist/AiChatPanel-UD756KAU.mjs.gz +0 -0
  141. package/dist/Area3DChartScene-435BFPLY.js.gz +0 -0
  142. package/dist/Area3DChartScene-MQKUWVMS.mjs.br +0 -0
  143. package/dist/Area3DChartScene-MQKUWVMS.mjs.gz +0 -0
  144. package/dist/Bar3DChartScene-D4GMQGPN.mjs.br +0 -0
  145. package/dist/Bar3DChartScene-D4GMQGPN.mjs.gz +0 -0
  146. package/dist/Bar3DChartScene-KEYLVYJA.js.br +0 -0
  147. package/dist/Bar3DChartScene-KEYLVYJA.js.gz +0 -0
  148. package/dist/Line3DChartScene-B3AWFXE4.mjs.br +0 -0
  149. package/dist/Line3DChartScene-B3AWFXE4.mjs.gz +0 -0
  150. package/dist/Line3DChartScene-JYGXLE56.js.gz +0 -0
  151. package/dist/Model3DScene-4TG4YRVM.mjs.br +0 -0
  152. package/dist/Model3DScene-4TG4YRVM.mjs.gz +0 -0
  153. package/dist/Model3DScene-JF5J6N6W.js.br +0 -0
  154. package/dist/Model3DScene-JF5J6N6W.js.gz +0 -0
  155. package/dist/PieChart3DScene-4BQ6PR7P.mjs.br +0 -0
  156. package/dist/PieChart3DScene-4BQ6PR7P.mjs.gz +0 -0
  157. package/dist/PieChart3DScene-CCQWSH3W.js.gz +0 -0
  158. package/dist/SmartArt3DScene-QZGIABOK.mjs.br +0 -0
  159. package/dist/SmartArt3DScene-QZGIABOK.mjs.gz +0 -0
  160. package/dist/SmartArt3DScene-T236GYUT.js.br +0 -0
  161. package/dist/SmartArt3DScene-T236GYUT.js.gz +0 -0
  162. package/dist/SurfaceChart3DScene-FRQC5HBG.mjs.br +0 -0
  163. package/dist/SurfaceChart3DScene-FRQC5HBG.mjs.gz +0 -0
  164. package/dist/SurfaceChart3DScene-UVZPT6OD.js.gz +0 -0
  165. package/dist/chunk-BFPIMU6Q.js.br +0 -0
  166. package/dist/chunk-BFPIMU6Q.js.gz +0 -0
  167. package/dist/chunk-BXMPXKV5.mjs.br +0 -0
  168. package/dist/chunk-BXMPXKV5.mjs.gz +0 -0
  169. package/dist/chunk-EJMDD4VV.mjs.br +0 -0
  170. package/dist/chunk-EJMDD4VV.mjs.gz +0 -0
  171. package/dist/chunk-H7QPQ4OR.js.br +0 -0
  172. package/dist/chunk-H7QPQ4OR.js.gz +0 -0
  173. package/dist/chunk-HZEOZUUH.mjs.br +0 -0
  174. package/dist/chunk-HZEOZUUH.mjs.gz +0 -0
  175. package/dist/chunk-M24DEOP6.js.br +0 -0
  176. package/dist/chunk-M24DEOP6.js.gz +0 -0
  177. package/dist/chunk-M6QJKPU2.js.br +0 -0
  178. package/dist/chunk-M6QJKPU2.js.gz +0 -0
  179. package/dist/chunk-R664EPDC.mjs.br +0 -0
  180. package/dist/chunk-R664EPDC.mjs.gz +0 -0
  181. package/dist/chunk-SUZIFHXI.js.br +0 -0
  182. package/dist/chunk-SUZIFHXI.js.gz +0 -0
  183. package/dist/chunk-T6V342NP.js.br +0 -0
  184. package/dist/chunk-T6V342NP.js.gz +0 -0
  185. package/dist/chunk-TMTQJAGK.mjs.br +0 -0
  186. package/dist/chunk-TMTQJAGK.mjs.gz +0 -0
  187. package/dist/chunk-TOOKJUPG.mjs.br +0 -0
  188. package/dist/chunk-TOOKJUPG.mjs.gz +0 -0
@@ -12,7 +12,7 @@ var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
12
12
 
13
13
  // ../core/dist/index.mjs
14
14
 
15
- // ../../node_modules/.bun/emf-converter@2.0.2/node_modules/emf-converter/dist/index.mjs
15
+ // ../../node_modules/.bun/emf-converter@3.0.1/node_modules/emf-converter/dist/index.mjs
16
16
  function colorRefToHex(r, g2, b) {
17
17
  const toHex4 = (v) => v.toString(16).padStart(2, "0");
18
18
  return `#${toHex4(r & 255)}${toHex4(g2 & 255)}${toHex4(b & 255)}`;
@@ -238,6 +238,26 @@ var emfLog = (...args) => {
238
238
  };
239
239
  var emfWarn = (...args) => {
240
240
  };
241
+ var nodeCanvasModule;
242
+ async function ensureNodeCanvasModule() {
243
+ if (nodeCanvasModule !== void 0) {
244
+ return nodeCanvasModule;
245
+ }
246
+ if (typeof OffscreenCanvas !== "undefined" || typeof document !== "undefined") {
247
+ nodeCanvasModule = null;
248
+ return nodeCanvasModule;
249
+ }
250
+ if (typeof process === "undefined" || !process.versions?.node) {
251
+ nodeCanvasModule = null;
252
+ return nodeCanvasModule;
253
+ }
254
+ try {
255
+ nodeCanvasModule = await import('@napi-rs/canvas');
256
+ } catch {
257
+ nodeCanvasModule = null;
258
+ }
259
+ return nodeCanvasModule;
260
+ }
241
261
  var DEFAULT_DPI_SCALE = 1;
242
262
  function createCanvas(width, height, maxWidth, maxHeight, dpiScale = DEFAULT_DPI_SCALE, maxCanvasDimension = MAX_CANVAS_DIMENSION) {
243
263
  const effectiveScale = Math.max(1, Math.min(dpiScale, 4));
@@ -274,30 +294,44 @@ function createCanvas(width, height, maxWidth, maxHeight, dpiScale = DEFAULT_DPI
274
294
  emfLog(
275
295
  `createCanvas: using OffscreenCanvas ${w}\xD7${h2}, scale=(${scaleX.toFixed(3)},${scaleY.toFixed(3)})`
276
296
  );
277
- const canvas2 = new OffscreenCanvas(w, h2);
278
- const ctx2 = canvas2.getContext("2d");
279
- if (!ctx2) {
297
+ const canvas = new OffscreenCanvas(w, h2);
298
+ const ctx = canvas.getContext("2d");
299
+ if (!ctx) {
280
300
  emfWarn('createCanvas: OffscreenCanvas.getContext("2d") returned null');
281
301
  return null;
282
302
  }
283
- return { canvas: canvas2, ctx: ctx2, scaleX, scaleY };
303
+ return { canvas, ctx, scaleX, scaleY };
284
304
  }
285
- if (typeof document === "undefined") {
286
- emfWarn("createCanvas: no OffscreenCanvas and no document \u2014 cannot create canvas");
287
- return null;
305
+ if (typeof document !== "undefined") {
306
+ emfLog(
307
+ `createCanvas: using HTMLCanvasElement ${w}\xD7${h2}, scale=(${scaleX.toFixed(3)},${scaleY.toFixed(3)})`
308
+ );
309
+ const canvas = document.createElement("canvas");
310
+ canvas.width = w;
311
+ canvas.height = h2;
312
+ const ctx = canvas.getContext("2d");
313
+ if (!ctx) {
314
+ emfWarn('createCanvas: HTMLCanvasElement.getContext("2d") returned null');
315
+ return null;
316
+ }
317
+ return { canvas, ctx, scaleX, scaleY };
288
318
  }
289
- emfLog(
290
- `createCanvas: using HTMLCanvasElement ${w}\xD7${h2}, scale=(${scaleX.toFixed(3)},${scaleY.toFixed(3)})`
291
- );
292
- const canvas = document.createElement("canvas");
293
- canvas.width = w;
294
- canvas.height = h2;
295
- const ctx = canvas.getContext("2d");
296
- if (!ctx) {
297
- emfWarn('createCanvas: HTMLCanvasElement.getContext("2d") returned null');
298
- return null;
319
+ if (nodeCanvasModule) {
320
+ emfLog(
321
+ `createCanvas: using @napi-rs/canvas ${w}\xD7${h2}, scale=(${scaleX.toFixed(3)},${scaleY.toFixed(3)})`
322
+ );
323
+ const canvas = nodeCanvasModule.createCanvas(w, h2);
324
+ const ctx = canvas.getContext("2d");
325
+ if (!ctx) {
326
+ emfWarn('createCanvas: @napi-rs/canvas getContext("2d") returned null');
327
+ return null;
328
+ }
329
+ return { canvas, ctx, scaleX, scaleY };
299
330
  }
300
- return { canvas, ctx, scaleX, scaleY };
331
+ emfWarn(
332
+ "createCanvas: no OffscreenCanvas, no document, and no @napi-rs/canvas, cannot create canvas"
333
+ );
334
+ return null;
301
335
  } catch (err) {
302
336
  return null;
303
337
  }
@@ -326,6 +360,14 @@ function createTempCanvas(width, height) {
326
360
  }
327
361
  return { canvas, ctx };
328
362
  }
363
+ if (nodeCanvasModule) {
364
+ const canvas = nodeCanvasModule.createCanvas(width, height);
365
+ const ctx = canvas.getContext("2d");
366
+ if (!ctx) {
367
+ return null;
368
+ }
369
+ return { canvas, ctx };
370
+ }
329
371
  return null;
330
372
  }
331
373
  function rop2Paint(rop2) {
@@ -559,8 +601,31 @@ async function exportCanvasToPngDataUrl(canvas) {
559
601
  );
560
602
  return canvas.toDataURL("image/png");
561
603
  }
604
+ if (nodeCanvasModule && canvas instanceof nodeCanvasModule.Canvas) {
605
+ emfLog(
606
+ `exportCanvasToPngDataUrl: using @napi-rs/canvas toDataURLAsync (${canvas.width}\xD7${canvas.height})`
607
+ );
608
+ return canvas.toDataURLAsync();
609
+ }
562
610
  return null;
563
611
  }
612
+ async function decodeDeferredImageBytes(bytes, mime) {
613
+ if (nodeCanvasModule) {
614
+ const image = await nodeCanvasModule.loadImage(new Uint8Array(bytes));
615
+ return { drawable: image, width: image.width, height: image.height, close: () => {
616
+ } };
617
+ }
618
+ if (typeof createImageBitmap !== "function") {
619
+ return null;
620
+ }
621
+ const blob = mime !== void 0 ? new Blob([bytes], { type: mime }) : new Blob([bytes]);
622
+ const bitmap = await createImageBitmap(blob);
623
+ return { drawable: bitmap, width: bitmap.width, height: bitmap.height, close: () => bitmap.close() };
624
+ }
625
+ function canvasDrawImage(ctx, image, dx, dy, dw, dh) {
626
+ const draw = ctx.drawImage;
627
+ draw.call(ctx, image, dx, dy, dw, dh);
628
+ }
564
629
  function parseEmfHeader(view) {
565
630
  emfLog("parseEmfHeader: byteLength =", view.byteLength);
566
631
  if (view.byteLength < 88) {
@@ -1462,7 +1527,8 @@ function handleBitBlt(rCtx, offset, dataOff, recSize) {
1462
1527
  const temp = createTempCanvas(imageData.width, imageData.height);
1463
1528
  if (temp) {
1464
1529
  temp.ctx.putImageData(imageData, 0, 0);
1465
- ctx.drawImage(
1530
+ canvasDrawImage(
1531
+ ctx,
1466
1532
  temp.canvas,
1467
1533
  gmx(rCtx, dstX),
1468
1534
  gmy(rCtx, dstY),
@@ -1497,7 +1563,8 @@ function handleStretchDibits(rCtx, offset, dataOff, recSize) {
1497
1563
  const temp = createTempCanvas(imageData.width, imageData.height);
1498
1564
  if (temp) {
1499
1565
  temp.ctx.putImageData(imageData, 0, 0);
1500
- ctx.drawImage(
1566
+ canvasDrawImage(
1567
+ ctx,
1501
1568
  temp.canvas,
1502
1569
  gmx(rCtx, dstX),
1503
1570
  gmy(rCtx, dstY),
@@ -4814,12 +4881,16 @@ async function processDeferredImages(ctx, deferredImages, recursionDepth = 0) {
4814
4881
  if (img.isMetafile) {
4815
4882
  if (recursionDepth >= MAX_METAFILE_RECURSION) {
4816
4883
  emfWarn(
4817
- ` Deferred image [${idx}]: skipping embedded metafile \u2014 recursion depth ${recursionDepth} >= ${MAX_METAFILE_RECURSION}`
4884
+ ` Deferred image [${idx}]: skipping embedded metafile, recursion depth ${recursionDepth} >= ${MAX_METAFILE_RECURSION}`
4818
4885
  );
4819
4886
  continue;
4820
4887
  }
4821
4888
  emfLog(` Deferred image [${idx}]: recursively converting embedded metafile...`);
4822
- const metafileDataUrl = await convertEmfToDataUrl(plainBuffer, void 0, recursionDepth + 1) ?? await convertWmfToDataUrl(plainBuffer, void 0, recursionDepth + 1);
4889
+ const metafileDataUrl = await convertMetafileToDataUrl(
4890
+ plainBuffer,
4891
+ void 0,
4892
+ recursionDepth + 1
4893
+ );
4823
4894
  if (metafileDataUrl) {
4824
4895
  emfLog(
4825
4896
  ` Deferred image [${idx}]: metafile converted, dataUrl length=${metafileDataUrl.length}`
@@ -4832,26 +4903,28 @@ async function processDeferredImages(ctx, deferredImages, recursionDepth = 0) {
4832
4903
  for (let i2 = 0; i2 < byteString.length; i2++) {
4833
4904
  ia[i2] = byteString.charCodeAt(i2);
4834
4905
  }
4835
- const metaBlob = new Blob([ab], { type: mime });
4836
- emfLog(
4837
- ` Deferred image [${idx}]: creating ImageBitmap from ${metaBlob.size} byte blob (${mime})...`
4838
- );
4839
- const bitmap = await createImageBitmap(metaBlob);
4840
- emfLog(` Deferred image [${idx}]: ImageBitmap created ${bitmap.width}\xD7${bitmap.height}`);
4841
- ctx.drawImage(bitmap, img.dx, img.dy, img.dw, img.dh);
4842
- bitmap.close();
4906
+ emfLog(` Deferred image [${idx}]: decoding ${ab.byteLength} byte image (${mime})...`);
4907
+ const decoded = await decodeDeferredImageBytes(ab, mime);
4908
+ if (decoded) {
4909
+ emfLog(` Deferred image [${idx}]: decoded ${decoded.width}\xD7${decoded.height}`);
4910
+ canvasDrawImage(ctx, decoded.drawable, img.dx, img.dy, img.dw, img.dh);
4911
+ decoded.close();
4912
+ } else {
4913
+ emfWarn(` Deferred image [${idx}]: no image decoder available`);
4914
+ }
4843
4915
  } else {
4844
4916
  emfWarn(` Deferred image [${idx}]: metafile conversion returned null`);
4845
4917
  }
4846
4918
  } else {
4847
- emfLog(
4848
- ` Deferred image [${idx}]: creating ImageBitmap from ${plainBuffer.byteLength} byte blob...`
4849
- );
4850
- const blob = new Blob([plainBuffer]);
4851
- const bitmap = await createImageBitmap(blob);
4852
- emfLog(` Deferred image [${idx}]: ImageBitmap created ${bitmap.width}\xD7${bitmap.height}`);
4853
- ctx.drawImage(bitmap, img.dx, img.dy, img.dw, img.dh);
4854
- bitmap.close();
4919
+ emfLog(` Deferred image [${idx}]: decoding ${plainBuffer.byteLength} byte image...`);
4920
+ const decoded = await decodeDeferredImageBytes(plainBuffer);
4921
+ if (decoded) {
4922
+ emfLog(` Deferred image [${idx}]: decoded ${decoded.width}\xD7${decoded.height}`);
4923
+ canvasDrawImage(ctx, decoded.drawable, img.dx, img.dy, img.dw, img.dh);
4924
+ decoded.close();
4925
+ } else {
4926
+ emfWarn(` Deferred image [${idx}]: no image decoder available`);
4927
+ }
4855
4928
  }
4856
4929
  } catch (imgErr) {
4857
4930
  imgErr instanceof Error ? imgErr.message : String(imgErr);
@@ -4864,10 +4937,35 @@ async function processDeferredImages(ctx, deferredImages, recursionDepth = 0) {
4864
4937
  }
4865
4938
  ctx.setTransform(1, 0, 0, 1, 0, 0);
4866
4939
  }
4867
- async function convertEmfToDataUrl(buffer, options, recursionDepth = 0) {
4940
+ async function convertMetafileToDataUrl(buffer, options, recursionDepth = 0) {
4941
+ await ensureNodeCanvasModule();
4868
4942
  if (recursionDepth > MAX_METAFILE_RECURSION) {
4869
4943
  return null;
4870
4944
  }
4945
+ emfLog(`convertMetafileToDataUrl: input buffer ${buffer.byteLength} bytes`);
4946
+ if (buffer.byteLength >= 16) {
4947
+ const hdrBytes = new Uint8Array(buffer, 0, 16);
4948
+ emfLog(
4949
+ `convertMetafileToDataUrl: first 16 bytes: [${Array.from(hdrBytes).map((b) => b.toString(16).padStart(2, "0")).join(" ")}]`
4950
+ );
4951
+ }
4952
+ const view = new DataView(buffer);
4953
+ let emfHeader = null;
4954
+ try {
4955
+ emfHeader = parseEmfHeader(view);
4956
+ } catch (err) {
4957
+ emfWarn(
4958
+ "convertMetafileToDataUrl: parseEmfHeader threw during detection:",
4959
+ err instanceof Error ? err.message : err
4960
+ );
4961
+ emfHeader = null;
4962
+ }
4963
+ if (emfHeader) {
4964
+ return convertEmfInternal(buffer, view, emfHeader, options, recursionDepth);
4965
+ }
4966
+ return convertWmfInternal(buffer, view);
4967
+ }
4968
+ async function convertEmfInternal(buffer, view, header, options, recursionDepth) {
4871
4969
  const opts = {};
4872
4970
  const dpiScale = opts.dpiScale ?? DEFAULT_DPI_SCALE;
4873
4971
  const effectiveMaxWidth = opts.maxWidth;
@@ -4878,30 +4976,18 @@ async function convertEmfToDataUrl(buffer, options, recursionDepth = 0) {
4878
4976
  fontFamilyMap: opts.fontFamilyMap
4879
4977
  };
4880
4978
  try {
4881
- emfLog("=== convertEmfToDataUrl START ===");
4979
+ emfLog("=== convertEmfInternal START ===");
4882
4980
  emfLog(
4883
4981
  `Input buffer: ${buffer.byteLength} bytes, maxWidth=${effectiveMaxWidth}, maxHeight=${effectiveMaxHeight}, dpiScale=${dpiScale}`
4884
4982
  );
4885
- if (buffer.byteLength >= 16) {
4886
- const hdrBytes = new Uint8Array(buffer, 0, 16);
4887
- emfLog(
4888
- `First 16 bytes: [${Array.from(hdrBytes).map((b) => b.toString(16).padStart(2, "0")).join(" ")}]`
4889
- );
4890
- }
4891
- const view = new DataView(buffer);
4892
- const header = parseEmfHeader(view);
4893
- if (!header) {
4894
- emfLog("convertEmfToDataUrl: parseEmfHeader returned null \u2014 returning null");
4895
- return null;
4896
- }
4897
4983
  const renderBounds = getRenderableEmfBounds(header);
4898
4984
  if (!renderBounds) {
4899
- emfLog("convertEmfToDataUrl: getRenderableEmfBounds returned null \u2014 returning null");
4985
+ emfLog("convertEmfInternal: getRenderableEmfBounds returned null, returning null");
4900
4986
  return null;
4901
4987
  }
4902
4988
  const logicalW = renderBounds.right - renderBounds.left;
4903
4989
  const logicalH = renderBounds.bottom - renderBounds.top;
4904
- emfLog(`convertEmfToDataUrl: logicalSize=${logicalW}\xD7${logicalH}`);
4990
+ emfLog(`convertEmfInternal: logicalSize=${logicalW}\xD7${logicalH}`);
4905
4991
  const setup = createCanvas(
4906
4992
  logicalW,
4907
4993
  logicalH,
@@ -4911,15 +4997,15 @@ async function convertEmfToDataUrl(buffer, options, recursionDepth = 0) {
4911
4997
  opts.maxCanvasDimension
4912
4998
  );
4913
4999
  if (!setup) {
4914
- emfLog("convertEmfToDataUrl: createCanvas returned null \u2014 returning null");
5000
+ emfLog("convertEmfInternal: createCanvas returned null, returning null");
4915
5001
  return null;
4916
5002
  }
4917
5003
  const { canvas, ctx } = setup;
4918
5004
  emfLog(
4919
- `convertEmfToDataUrl: canvas created ${canvas.width}\xD7${canvas.height} (dpiScale=${dpiScale})`
5005
+ `convertEmfInternal: canvas created ${canvas.width}\xD7${canvas.height} (dpiScale=${dpiScale})`
4920
5006
  );
4921
5007
  ctx.save();
4922
- emfLog("convertEmfToDataUrl: starting replayEmfRecords...");
5008
+ emfLog("convertEmfInternal: starting replayEmfRecords...");
4923
5009
  const deferredImages = replayEmfRecords(
4924
5010
  view,
4925
5011
  ctx,
@@ -4929,30 +5015,25 @@ async function convertEmfToDataUrl(buffer, options, recursionDepth = 0) {
4929
5015
  dpiScale,
4930
5016
  replayOptions
4931
5017
  );
4932
- emfLog(
4933
- `convertEmfToDataUrl: replayEmfRecords returned ${deferredImages.length} deferred images`
4934
- );
5018
+ emfLog(`convertEmfInternal: replayEmfRecords returned ${deferredImages.length} deferred images`);
4935
5019
  ctx.restore();
4936
- await processDeferredImages(ctx, deferredImages);
4937
- emfLog("convertEmfToDataUrl: exporting canvas to PNG data URL...");
5020
+ await processDeferredImages(ctx, deferredImages, recursionDepth);
5021
+ emfLog("convertEmfInternal: exporting canvas to PNG data URL...");
4938
5022
  const result = await exportCanvasToPngDataUrl(canvas);
4939
5023
  if (result) {
4940
- emfLog(`convertEmfToDataUrl: SUCCESS \u2014 data URL length=${result.length}`);
5024
+ emfLog(`convertEmfInternal: SUCCESS, data URL length=${result.length}`);
4941
5025
  } else {
4942
- emfWarn("convertEmfToDataUrl: exportCanvasToPngDataUrl returned null");
5026
+ emfWarn("convertEmfInternal: exportCanvasToPngDataUrl returned null");
4943
5027
  }
4944
- emfLog("=== convertEmfToDataUrl END ===");
5028
+ emfLog("=== convertEmfInternal END ===");
4945
5029
  return result;
4946
5030
  } catch (err) {
4947
- emfWarn("convertEmfToDataUrl: EXCEPTION:", err instanceof Error ? err.message : err);
4948
- console.warn("[pptx-editor] EMF conversion failed:", err instanceof Error ? err.message : err);
5031
+ emfWarn("convertEmfInternal: EXCEPTION:", err instanceof Error ? err.message : err);
5032
+ console.warn("[emf-converter] EMF conversion failed:", err instanceof Error ? err.message : err);
4949
5033
  return null;
4950
5034
  }
4951
5035
  }
4952
- async function convertWmfToDataUrl(buffer, options, recursionDepth = 0) {
4953
- if (recursionDepth > MAX_METAFILE_RECURSION) {
4954
- return null;
4955
- }
5036
+ async function convertWmfInternal(buffer, view, options, recursionDepth) {
4956
5037
  const opts = {};
4957
5038
  const dpiScale = opts.dpiScale ?? DEFAULT_DPI_SCALE;
4958
5039
  const effectiveMaxWidth = opts.maxWidth;
@@ -4963,20 +5044,19 @@ async function convertWmfToDataUrl(buffer, options, recursionDepth = 0) {
4963
5044
  };
4964
5045
  try {
4965
5046
  emfLog(
4966
- "=== convertWmfToDataUrl START ===",
5047
+ "=== convertWmfInternal START ===",
4967
5048
  `buffer=${buffer.byteLength} bytes, dpiScale=${dpiScale}`
4968
5049
  );
4969
- const view = new DataView(buffer);
4970
5050
  const header = parseWmfHeader(view);
4971
5051
  if (!header) {
4972
- emfLog("convertWmfToDataUrl: parseWmfHeader returned null");
5052
+ emfLog("convertWmfInternal: parseWmfHeader returned null");
4973
5053
  return null;
4974
5054
  }
4975
5055
  const logicalW = header.boundsRight - header.boundsLeft;
4976
5056
  const logicalH = header.boundsBottom - header.boundsTop;
4977
- emfLog(`convertWmfToDataUrl: logicalSize=${logicalW}\xD7${logicalH}`);
5057
+ emfLog(`convertWmfInternal: logicalSize=${logicalW}\xD7${logicalH}`);
4978
5058
  if (logicalW <= 0 || logicalH <= 0) {
4979
- emfLog("convertWmfToDataUrl: invalid dimensions \u2014 returning null");
5059
+ emfLog("convertWmfInternal: invalid dimensions, returning null");
4980
5060
  return null;
4981
5061
  }
4982
5062
  const setup = createCanvas(
@@ -4995,12 +5075,12 @@ async function convertWmfToDataUrl(buffer, options, recursionDepth = 0) {
4995
5075
  replayWmfRecords(view, ctx, header, canvas.width, canvas.height, replayOptions);
4996
5076
  ctx.restore();
4997
5077
  const result = await exportCanvasToPngDataUrl(canvas);
4998
- emfLog(`convertWmfToDataUrl: result=${result ? `dataUrl len=${result.length}` : "null"}`);
4999
- emfLog("=== convertWmfToDataUrl END ===");
5078
+ emfLog(`convertWmfInternal: result=${result ? `dataUrl len=${result.length}` : "null"}`);
5079
+ emfLog("=== convertWmfInternal END ===");
5000
5080
  return result;
5001
5081
  } catch (err) {
5002
- emfWarn("convertWmfToDataUrl: EXCEPTION:", err instanceof Error ? err.message : err);
5003
- console.warn("[pptx-editor] WMF conversion failed:", err instanceof Error ? err.message : err);
5082
+ emfWarn("convertWmfInternal: EXCEPTION:", err instanceof Error ? err.message : err);
5083
+ console.warn("[emf-converter] WMF conversion failed:", err instanceof Error ? err.message : err);
5004
5084
  return null;
5005
5085
  }
5006
5086
  }
@@ -30992,7 +31072,7 @@ function directChildOrder(xml) {
30992
31072
  function extractElementOrders(xml, elementName) {
30993
31073
  const orders = [];
30994
31074
  const pattern = new RegExp(
30995
- `<([A-Za-z_][\\w.-]*:)?${elementName}\\b[^>]*>([\\s\\S]*?)<\\/\\1${elementName}\\s*>`,
31075
+ `<([A-Za-z_][\\w.-]*:)?${elementName}(?=[\\s/>])[^>]*>([\\s\\S]*?)<\\/\\1${elementName}\\s*>`,
30996
31076
  "gu"
30997
31077
  );
30998
31078
  for (const match of xml.matchAll(pattern)) {
@@ -31956,11 +32036,11 @@ function parseRunSolidFillColor(rPr) {
31956
32036
  if (!rPr) {
31957
32037
  return void 0;
31958
32038
  }
31959
- const solidFill3 = rPr["a:solidFill"];
31960
- if (!solidFill3) {
32039
+ const solidFill32 = rPr["a:solidFill"];
32040
+ if (!solidFill32) {
31961
32041
  return void 0;
31962
32042
  }
31963
- const srgb = solidFill3["a:srgbClr"];
32043
+ const srgb = solidFill32["a:srgbClr"];
31964
32044
  if (srgb?.["@_val"]) {
31965
32045
  return String(srgb["@_val"]);
31966
32046
  }
@@ -31970,11 +32050,11 @@ function parseRunSolidFillColorXml(rPr) {
31970
32050
  if (!rPr) {
31971
32051
  return void 0;
31972
32052
  }
31973
- const solidFill3 = rPr["a:solidFill"];
31974
- if (!solidFill3) {
32053
+ const solidFill32 = rPr["a:solidFill"];
32054
+ if (!solidFill32) {
31975
32055
  return void 0;
31976
32056
  }
31977
- return extractColorChoiceXml(solidFill3);
32057
+ return extractColorChoiceXml(solidFill32);
31978
32058
  }
31979
32059
  var init_text_run_properties_parser = __esm({
31980
32060
  "src/core/utils/text-run-properties-parser.ts"() {
@@ -37373,6 +37453,20 @@ function itemAspect(plan, index, nodeCount, presLayoutVars) {
37373
37453
  }
37374
37454
  return void 0;
37375
37455
  }
37456
+ function itemCrossAxisFraction(plan, index) {
37457
+ const item = itemNode(plan.node);
37458
+ if (!item) {
37459
+ return void 0;
37460
+ }
37461
+ const role = roleOf(item);
37462
+ const arrangerRole = roleOf(plan.node);
37463
+ const rawHeight = firstConstraintDeclaredBy(index, role, "h", arrangerRole);
37464
+ if (!rawHeight || rawHeight.referenceType !== "w") {
37465
+ return void 0;
37466
+ }
37467
+ const width = resolveConstraintDeclaredBy(index, role, "w", arrangerRole);
37468
+ return typeof width === "number" && width > 0 ? width : void 0;
37469
+ }
37376
37470
  function ordered(nodes, flow) {
37377
37471
  return flow.reverse ? [...nodes].reverse() : nodes;
37378
37472
  }
@@ -37760,6 +37854,7 @@ function arrangeLinear(plan, flow, nodes, box, palette, style, elementId, index
37760
37854
  const horizontal = flow.orientation === "horizontal";
37761
37855
  const usableMain = (horizontal ? w : h2) - INSET * 2;
37762
37856
  const usableCross = (horizontal ? h2 : w) - INSET * 2;
37857
+ const crossAxisFraction = horizontal ? void 0 : itemCrossAxisFraction(plan, index);
37763
37858
  const { mainExtent, gap } = resolveMainAxisLayout(
37764
37859
  constraints,
37765
37860
  index,
@@ -37775,7 +37870,7 @@ function arrangeLinear(plan, flow, nodes, box, palette, style, elementId, index
37775
37870
  const itemTemplate = itemNode(plan.node);
37776
37871
  const itemShape = findCompositeItemShape(itemTemplate);
37777
37872
  const naturalAspect = resolveItemSelfAspect(itemTemplate);
37778
- const crossExtent = aspect ? Math.min(usableCross, Math.max(12, mainExtent * aspect)) : typeof naturalAspect === "number" ? Math.min(
37873
+ const crossExtent = crossAxisFraction ? Math.min(usableCross, Math.max(12, usableCross * crossAxisFraction)) : aspect ? Math.min(usableCross, Math.max(12, mainExtent * aspect)) : typeof naturalAspect === "number" ? Math.min(
37779
37874
  usableCross,
37780
37875
  Math.max(12, mainExtent * (horizontal ? naturalAspect : 1 / naturalAspect))
37781
37876
  ) : usableCross;
@@ -46327,8 +46422,8 @@ function parseLineStyle(container, elementName, xmlLookup, colorParser) {
46327
46422
  if (spPr) {
46328
46423
  const lnNode = xmlLookup.getChildByLocalName(spPr, "ln");
46329
46424
  if (lnNode) {
46330
- const solidFill3 = xmlLookup.getChildByLocalName(lnNode, "solidFill");
46331
- const lineColor = colorParser.parseColor(solidFill3);
46425
+ const solidFill32 = xmlLookup.getChildByLocalName(lnNode, "solidFill");
46426
+ const lineColor = colorParser.parseColor(solidFill32);
46332
46427
  if (lineColor) {
46333
46428
  result.color = lineColor;
46334
46429
  }
@@ -47031,8 +47126,8 @@ function parseShapeProps(spPrNode, xmlLookup, colorParser) {
47031
47126
  }
47032
47127
  const result = {};
47033
47128
  let hasProps = false;
47034
- const solidFill3 = xmlLookup.getChildByLocalName(spPrNode, "solidFill");
47035
- const fillColor = colorParser.parseColor(solidFill3);
47129
+ const solidFill32 = xmlLookup.getChildByLocalName(spPrNode, "solidFill");
47130
+ const fillColor = colorParser.parseColor(solidFill32);
47036
47131
  if (fillColor) {
47037
47132
  result.fillColor = fillColor;
47038
47133
  hasProps = true;
@@ -48514,8 +48609,8 @@ function parseTxPr(txPrNode, xmlLookup, colorParser, target, resolveTypeface) {
48514
48609
  const raw = String(latin["@_typeface"]);
48515
48610
  target.fontFamily = resolveTypeface ? resolveTypeface(raw) : raw;
48516
48611
  }
48517
- const solidFill3 = xmlLookup.getChildByLocalName(defRPr, "solidFill");
48518
- const fontColor = colorParser.parseColor(solidFill3);
48612
+ const solidFill32 = xmlLookup.getChildByLocalName(defRPr, "solidFill");
48613
+ const fontColor = colorParser.parseColor(solidFill32);
48519
48614
  if (fontColor) {
48520
48615
  target.fontColor = fontColor;
48521
48616
  }
@@ -49016,13 +49111,13 @@ function extractCxSeriesColor(ser, xmlLookup, colorParser) {
49016
49111
  if (!spPr) {
49017
49112
  return void 0;
49018
49113
  }
49019
- const solidFill3 = xmlLookup.getChildByLocalName(spPr, "solidFill");
49020
- if (solidFill3) {
49021
- const resolved = colorParser?.parseColor(solidFill3);
49114
+ const solidFill32 = xmlLookup.getChildByLocalName(spPr, "solidFill");
49115
+ if (solidFill32) {
49116
+ const resolved = colorParser?.parseColor(solidFill32);
49022
49117
  if (resolved) {
49023
49118
  return resolved;
49024
49119
  }
49025
- const srgb = xmlLookup.getChildByLocalName(solidFill3, "srgbClr");
49120
+ const srgb = xmlLookup.getChildByLocalName(solidFill32, "srgbClr");
49026
49121
  const val2 = String(srgb?.["@_val"] || "").trim();
49027
49122
  return val2.length === 6 ? `#${val2}` : void 0;
49028
49123
  }
@@ -65872,9 +65967,9 @@ var init_effect_dag_specific_helpers = __esm({
65872
65967
  }
65873
65968
  });
65874
65969
  function fillOverlayColorHost(fillOverlay, context) {
65875
- const solidFill3 = fillOverlay["a:solidFill"];
65876
- if (solidFill3) {
65877
- return solidFill3;
65970
+ const solidFill32 = fillOverlay["a:solidFill"];
65971
+ if (solidFill32) {
65972
+ return solidFill32;
65878
65973
  }
65879
65974
  const gradFill = fillOverlay["a:gradFill"];
65880
65975
  if (!gradFill) {
@@ -67404,20 +67499,20 @@ var init_PptxShapeStyleExtractor = __esm({
67404
67499
  extractShapeStyle(spPr, styleNode) {
67405
67500
  const style = {};
67406
67501
  const shapeProps = spPr || {};
67407
- const solidFill3 = drawingChild(shapeProps, "solidFill");
67502
+ const solidFill32 = drawingChild(shapeProps, "solidFill");
67408
67503
  const gradFill = drawingChild(shapeProps, "gradFill");
67409
67504
  const pattFill = drawingChild(shapeProps, "pattFill");
67410
67505
  const noFill = hasDrawingChild(shapeProps, "noFill");
67411
67506
  const blipFill = drawingChild(shapeProps, "blipFill");
67412
- if (solidFill3) {
67507
+ if (solidFill32) {
67413
67508
  style.fillMode = "solid";
67414
- style.fillColor = this.context.parseColor(solidFill3);
67415
- style.fillOpacity = this.context.extractColorOpacity(solidFill3);
67416
- const solidFillColorXml = extractColorChoiceXml(solidFill3);
67509
+ style.fillColor = this.context.parseColor(solidFill32);
67510
+ style.fillOpacity = this.context.extractColorOpacity(solidFill32);
67511
+ const solidFillColorXml = extractColorChoiceXml(solidFill32);
67417
67512
  if (solidFillColorXml) {
67418
67513
  style.fillColorXml = solidFillColorXml;
67419
67514
  }
67420
- const solidFillColorRef = themeColorRefFromColorChoice(solidFill3);
67515
+ const solidFillColorRef = themeColorRefFromColorChoice(solidFill32);
67421
67516
  if (solidFillColorRef) {
67422
67517
  style.fillColorRef = solidFillColorRef;
67423
67518
  }
@@ -67643,11 +67738,11 @@ function parseTintShadeVal(value) {
67643
67738
  const fraction = parseOoxmlPercent(value);
67644
67739
  return fraction === void 0 || fraction === 0 ? void 0 : Math.round(fraction * 1e5);
67645
67740
  }
67646
- function parseSolidFillStyle(solidFill3) {
67647
- if (!solidFill3) {
67741
+ function parseSolidFillStyle(solidFill32) {
67742
+ if (!solidFill32) {
67648
67743
  return void 0;
67649
67744
  }
67650
- const schemeClr = solidFill3["a:schemeClr"];
67745
+ const schemeClr = solidFill32["a:schemeClr"];
67651
67746
  if (!schemeClr) {
67652
67747
  return void 0;
67653
67748
  }
@@ -67690,13 +67785,13 @@ function parseBorderSide(side) {
67690
67785
  border.dash = dashVal;
67691
67786
  has = true;
67692
67787
  }
67693
- const solidFill3 = ln["a:solidFill"];
67694
- const fill = parseSolidFillStyle(solidFill3);
67788
+ const solidFill32 = ln["a:solidFill"];
67789
+ const fill = parseSolidFillStyle(solidFill32);
67695
67790
  if (fill) {
67696
67791
  border.fill = fill;
67697
67792
  has = true;
67698
67793
  } else {
67699
- const srgb = solidFill3?.["a:srgbClr"];
67794
+ const srgb = solidFill32?.["a:srgbClr"];
67700
67795
  const hex4 = srgb ? String(srgb["@_val"] || "").trim() : "";
67701
67796
  if (hex4) {
67702
67797
  border.color = hex4.startsWith("#") ? hex4 : `#${hex4}`;
@@ -71256,10 +71351,6 @@ var init_compatibility_child_sets = __esm({
71256
71351
  ]);
71257
71352
  GRAPHIC_FRAME_LIMITATIONS = {
71258
71353
  unknown: ["UNSUPPORTED_GRAPHIC_FRAME", "The graphic-frame payload is preserved but unsupported."],
71259
- smartArt: [
71260
- "PARTIAL_SMARTART_SUPPORT",
71261
- "SmartArt is parsed and preserved, but some DiagramML behavior is not editable."
71262
- ],
71263
71354
  ole: [
71264
71355
  "PARTIAL_OLE_SUPPORT",
71265
71356
  "The OLE payload renders as a preview image and can be downloaded or opened in a new tab, but cannot be edited in place."
@@ -80149,8 +80240,8 @@ function parseTypedTextStyle(txPrNode, localName28, colorParser) {
80149
80240
  if (typeface) {
80150
80241
  style.fontFamily = String(typeface);
80151
80242
  }
80152
- const solidFill3 = nodesOf(defRPr, "solidFill", localName28)[0];
80153
- const color2 = literalColor(solidFill3, localName28, colorParser);
80243
+ const solidFill32 = nodesOf(defRPr, "solidFill", localName28)[0];
80244
+ const color2 = literalColor(solidFill32, localName28, colorParser);
80154
80245
  if (color2) {
80155
80246
  style.color = color2;
80156
80247
  }
@@ -94975,8 +95066,8 @@ function parseTableBackground(tblBg) {
94975
95066
  return void 0;
94976
95067
  }
94977
95068
  const fillNode = tblBg["a:fill"];
94978
- const solidFill3 = fillNode?.["a:solidFill"] ?? tblBg["a:solidFill"];
94979
- const schemeClr = solidFill3?.["a:schemeClr"];
95069
+ const solidFill32 = fillNode?.["a:solidFill"] ?? tblBg["a:solidFill"];
95070
+ const schemeClr = solidFill32?.["a:schemeClr"];
94980
95071
  const schemeColor = schemeClr ? String(schemeClr["@_val"] || "").trim() || void 0 : void 0;
94981
95072
  const fill = schemeColor ? { schemeColor } : void 0;
94982
95073
  const hasEffectLst = Boolean(tblBg["a:effectLst"]);
@@ -95772,9 +95863,9 @@ var init_PptxHandlerRuntimeImageEffects = __esm({
95772
95863
  }
95773
95864
  rawCopy[key2] = fillOverlay[key2];
95774
95865
  }
95775
- const solidFill3 = fillOverlay["a:solidFill"];
95776
- const resolvedColor = solidFill3 ? this.parseColor(solidFill3) : void 0;
95777
- const resolvedOpacity = solidFill3 ? this.extractColorOpacity(solidFill3) ?? 1 : void 0;
95866
+ const solidFill32 = fillOverlay["a:solidFill"];
95867
+ const resolvedColor = solidFill32 ? this.parseColor(solidFill32) : void 0;
95868
+ const resolvedOpacity = solidFill32 ? this.extractColorOpacity(solidFill32) ?? 1 : void 0;
95778
95869
  const gradFill = fillOverlay["a:gradFill"];
95779
95870
  const resolvedGradient = gradFill ? this.resolveFillOverlayGradient(gradFill) : void 0;
95780
95871
  const pattFill = fillOverlay["a:pattFill"];
@@ -96143,7 +96234,7 @@ var init_PptxHandlerRuntimeMediaData = __esm({
96143
96234
  try {
96144
96235
  if (ext === "emf" || ext === "wmf") {
96145
96236
  const binaryBuffer = await imageFile2.async("arraybuffer");
96146
- const converted = ext === "emf" ? await convertEmfToDataUrl(binaryBuffer) : await convertWmfToDataUrl(binaryBuffer);
96237
+ const converted = await convertMetafileToDataUrl(binaryBuffer);
96147
96238
  if (converted) {
96148
96239
  this.imageDataCache.set(imagePath, converted);
96149
96240
  return converted;
@@ -97143,8 +97234,8 @@ var init_PptxHandlerRuntimePresentationProps = __esm({
97143
97234
  if (hasNoFill) {
97144
97235
  return "none";
97145
97236
  }
97146
- const solidFill3 = this.xmlLookupService.getChildByLocalName(shapeProperties, "solidFill");
97147
- return solidFill3 ? this.parseColor(solidFill3) : void 0;
97237
+ const solidFill32 = this.xmlLookupService.getChildByLocalName(shapeProperties, "solidFill");
97238
+ return solidFill32 ? this.parseColor(solidFill32) : void 0;
97148
97239
  }
97149
97240
  /**
97150
97241
  * Extract chart style metadata from chart XML.
@@ -100083,14 +100174,14 @@ var init_PptxHandlerRuntimeTextRunStyleExtraction = __esm({
100083
100174
  if (csTypeface) {
100084
100175
  style.complexScriptFont = csTypeface;
100085
100176
  }
100086
- const solidFill3 = xmlChild(runProperties2, "a:solidFill");
100087
- if (solidFill3) {
100088
- style.color = this.parseColor(solidFill3);
100089
- const colorXml2 = extractColorChoiceXml(solidFill3);
100177
+ const solidFill32 = xmlChild(runProperties2, "a:solidFill");
100178
+ if (solidFill32) {
100179
+ style.color = this.parseColor(solidFill32);
100180
+ const colorXml2 = extractColorChoiceXml(solidFill32);
100090
100181
  if (colorXml2) {
100091
100182
  style.colorXml = colorXml2;
100092
100183
  }
100093
- const colorRef = themeColorRefFromColorChoice(solidFill3);
100184
+ const colorRef = themeColorRefFromColorChoice(solidFill32);
100094
100185
  if (colorRef) {
100095
100186
  style.colorRef = colorRef;
100096
100187
  }
@@ -116417,11 +116508,11 @@ var init_PptxHandlerRuntimeBackgroundParsing = __esm({
116417
116508
  }
116418
116509
  const bgPr = xmlChild(bg, "p:bgPr");
116419
116510
  if (bgPr) {
116420
- const solidFill3 = xmlChild(bgPr, "a:solidFill");
116421
- if (solidFill3) {
116511
+ const solidFill32 = xmlChild(bgPr, "a:solidFill");
116512
+ if (solidFill32) {
116422
116513
  return this.blendBackgroundColorOntoWhite(
116423
- this.parseColor(solidFill3),
116424
- this.extractColorOpacity(solidFill3)
116514
+ this.parseColor(solidFill32),
116515
+ this.extractColorOpacity(solidFill32)
116425
116516
  );
116426
116517
  }
116427
116518
  const pattFill = xmlChild(bgPr, "a:pattFill");
@@ -116514,11 +116605,11 @@ var init_PptxHandlerRuntimeBackgroundParsing = __esm({
116514
116605
  if (idx === 0) {
116515
116606
  return void 0;
116516
116607
  }
116517
- const solidFill3 = xmlChild(bgRef, "a:solidFill");
116518
- if (solidFill3) {
116608
+ const solidFill32 = xmlChild(bgRef, "a:solidFill");
116609
+ if (solidFill32) {
116519
116610
  return this.blendBackgroundColorOntoWhite(
116520
- this.parseColor(solidFill3),
116521
- this.extractColorOpacity(solidFill3)
116611
+ this.parseColor(solidFill32),
116612
+ this.extractColorOpacity(solidFill32)
116522
116613
  );
116523
116614
  }
116524
116615
  const overrideColor = this.blendBackgroundColorOntoWhite(
@@ -117336,13 +117427,13 @@ var init_PptxHandlerRuntimePlaceholderStyles = __esm({
117336
117427
  if (defRPr["@_i"] !== void 0) {
117337
117428
  style.italic = defRPr["@_i"] === "1";
117338
117429
  }
117339
- const solidFill3 = defRPr["a:solidFill"];
117340
- const color2 = this.parseColor(solidFill3);
117430
+ const solidFill32 = defRPr["a:solidFill"];
117431
+ const color2 = this.parseColor(solidFill32);
117341
117432
  if (color2) {
117342
117433
  style.color = color2;
117343
117434
  }
117344
- if (solidFill3) {
117345
- style.colorChoiceXml = solidFill3;
117435
+ if (solidFill32) {
117436
+ style.colorChoiceXml = solidFill32;
117346
117437
  }
117347
117438
  const latin = defRPr["a:latin"];
117348
117439
  if (latin?.["@_typeface"]) {
@@ -120076,8 +120167,8 @@ var init_PptxHandlerRuntimeSmartArtXmlUtils = __esm({
120076
120167
  }
120077
120168
  const chrome = {};
120078
120169
  if (bg) {
120079
- const solidFill3 = this.xmlLookupService.getChildByLocalName(bg, "solidFill");
120080
- const bgColor = this.parseColor(solidFill3);
120170
+ const solidFill32 = this.xmlLookupService.getChildByLocalName(bg, "solidFill");
120171
+ const bgColor = this.parseColor(solidFill32);
120081
120172
  if (bgColor) {
120082
120173
  chrome.backgroundColor = bgColor;
120083
120174
  } else {
@@ -120091,8 +120182,8 @@ var init_PptxHandlerRuntimeSmartArtXmlUtils = __esm({
120091
120182
  if (whole) {
120092
120183
  const lnNode = this.xmlLookupService.getChildByLocalName(whole, "ln");
120093
120184
  if (lnNode) {
120094
- const solidFill3 = this.xmlLookupService.getChildByLocalName(lnNode, "solidFill");
120095
- const outlineColor = this.parseColor(solidFill3);
120185
+ const solidFill32 = this.xmlLookupService.getChildByLocalName(lnNode, "solidFill");
120186
+ const outlineColor = this.parseColor(solidFill32);
120096
120187
  if (outlineColor) {
120097
120188
  chrome.outlineColor = outlineColor;
120098
120189
  }
@@ -120204,11 +120295,11 @@ function extractDrawingShapeFill(spPr, deps) {
120204
120295
  }
120205
120296
  return result;
120206
120297
  }
120207
- const solidFill3 = deps.getChild(spPr, "solidFill");
120208
- if (solidFill3) {
120209
- result.fillColor = deps.parseColor(solidFill3) ?? void 0;
120298
+ const solidFill32 = deps.getChild(spPr, "solidFill");
120299
+ if (solidFill32) {
120300
+ result.fillColor = deps.parseColor(solidFill32) ?? void 0;
120210
120301
  }
120211
- const gradFill = !solidFill3 ? deps.getChild(spPr, "gradFill") : void 0;
120302
+ const gradFill = !solidFill32 ? deps.getChild(spPr, "gradFill") : void 0;
120212
120303
  if (gradFill) {
120213
120304
  const stops = deps.extractGradientStops(gradFill).map((stop) => ({
120214
120305
  color: stop.color,
@@ -120222,7 +120313,7 @@ function extractDrawingShapeFill(spPr, deps) {
120222
120313
  result.fillColor ??= stops[Math.floor(stops.length / 2)]?.color;
120223
120314
  }
120224
120315
  }
120225
- const pattFill = !solidFill3 && !gradFill ? deps.getChild(spPr, "pattFill") : void 0;
120316
+ const pattFill = !solidFill32 && !gradFill ? deps.getChild(spPr, "pattFill") : void 0;
120226
120317
  if (pattFill) {
120227
120318
  const preset = String(pattFill["@_prst"] || "").trim();
120228
120319
  if (preset) {
@@ -120238,7 +120329,7 @@ function extractDrawingShapeFill(spPr, deps) {
120238
120329
  }
120239
120330
  result.fillColor ??= fg ?? bg;
120240
120331
  }
120241
- const blipFill = !solidFill3 && !gradFill && !pattFill ? deps.getChild(spPr, "blipFill") : void 0;
120332
+ const blipFill = !solidFill32 && !gradFill && !pattFill ? deps.getChild(spPr, "blipFill") : void 0;
120242
120333
  if (blipFill) {
120243
120334
  const blip = deps.getChild(blipFill, "blip");
120244
120335
  const embed = String(
@@ -148640,8 +148731,8 @@ function getOmmlMathColor(node) {
148640
148731
  }
148641
148732
  const drawingRunProperties = node["a:rPr"];
148642
148733
  if (drawingRunProperties && typeof drawingRunProperties === "object") {
148643
- const solidFill3 = drawingRunProperties["a:solidFill"];
148644
- const srgbColor = solidFill3 && typeof solidFill3 === "object" ? solidFill3["a:srgbClr"] : void 0;
148734
+ const solidFill22 = drawingRunProperties["a:solidFill"];
148735
+ const srgbColor = solidFill22 && typeof solidFill22 === "object" ? solidFill22["a:srgbClr"] : void 0;
148645
148736
  const value = srgbColor?.["@_val"];
148646
148737
  if (typeof value === "string" && /^[0-9a-f]{6}$/iu.test(value)) {
148647
148738
  return `#${value.toUpperCase()}`;
@@ -154399,6 +154490,102 @@ function buildCartesianHorizontalAxis(chartData, categoryLabels, layout, kind, p
154399
154490
  displayChartData: datePlan || categoryPlan ? chartDataInCategoryOrder(chartData, sourceIndices2) : chartData
154400
154491
  };
154401
154492
  }
154493
+ function estimatedGlyphAdvanceRatio(glyph) {
154494
+ if (/\p{Mark}/u.test(glyph)) {
154495
+ return 0;
154496
+ }
154497
+ if (/\s/u.test(glyph)) {
154498
+ return 0.33;
154499
+ }
154500
+ if (/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Extended_Pictographic}]/u.test(
154501
+ glyph
154502
+ )) {
154503
+ return 1;
154504
+ }
154505
+ if (/[A-Z]/u.test(glyph)) {
154506
+ return 0.65;
154507
+ }
154508
+ if (/[a-z0-9]/u.test(glyph)) {
154509
+ return 0.55;
154510
+ }
154511
+ if (/[,.;:!?()\u005b\u005d{}'"`\-_/\\]/u.test(glyph)) {
154512
+ return 0.35;
154513
+ }
154514
+ return 0.6;
154515
+ }
154516
+ function estimatedTextWidth(glyphs, fontSize) {
154517
+ return glyphs.reduce((sum, glyph) => sum + estimatedGlyphAdvanceRatio(glyph) * fontSize, 0);
154518
+ }
154519
+ function estimateTextWidth(text22, fontSize) {
154520
+ return estimatedTextWidth(Array.from(text22), fontSize);
154521
+ }
154522
+ var HANGING_PUNCTUATION_RE = /^[\u3001\u3002\uff0c\uff0e\uff01\uff1f\uff1b\uff1a\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\uff09\uff3d\uff5d\u2019\u201d\u00bb\u203a]$/u;
154523
+ var BREAKABLE_GLYPH_RE = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Extended_Pictographic}]$/u;
154524
+ function estimatedWrapUnits(text22) {
154525
+ const units = [];
154526
+ let unbreakableRun = "";
154527
+ const flushRun = () => {
154528
+ if (unbreakableRun.length > 0) {
154529
+ units.push(unbreakableRun);
154530
+ unbreakableRun = "";
154531
+ }
154532
+ };
154533
+ for (const glyph of Array.from(text22)) {
154534
+ if (/\s/u.test(glyph) || BREAKABLE_GLYPH_RE.test(glyph)) {
154535
+ flushRun();
154536
+ units.push(glyph);
154537
+ } else {
154538
+ unbreakableRun += glyph;
154539
+ }
154540
+ }
154541
+ flushRun();
154542
+ return units;
154543
+ }
154544
+ function wrapTextByEstimatedWidth(text22, maxWidth, fontSize, options = {}) {
154545
+ if (!text22 || text22.trim().length === 0) {
154546
+ return [];
154547
+ }
154548
+ if (!(maxWidth > 0) || !(fontSize > 0)) {
154549
+ return [];
154550
+ }
154551
+ const lines = [];
154552
+ for (const paragraph of text22.split(/\r?\n/u)) {
154553
+ if (paragraph.trim().length === 0) {
154554
+ if (options.keepBlankLines) {
154555
+ lines.push("");
154556
+ }
154557
+ continue;
154558
+ }
154559
+ let current = "";
154560
+ let pendingWhitespace = false;
154561
+ for (const unit of estimatedWrapUnits(paragraph)) {
154562
+ if (/^\s+$/u.test(unit)) {
154563
+ pendingWhitespace = current.length > 0;
154564
+ continue;
154565
+ }
154566
+ const separator = pendingWhitespace && current.length > 0 ? " " : "";
154567
+ const candidate = `${current}${separator}${unit}`;
154568
+ if (current.length === 0 || estimatedTextWidth(Array.from(candidate), fontSize) <= maxWidth) {
154569
+ current = candidate;
154570
+ pendingWhitespace = false;
154571
+ continue;
154572
+ }
154573
+ if (HANGING_PUNCTUATION_RE.test(unit)) {
154574
+ current += unit;
154575
+ pendingWhitespace = false;
154576
+ continue;
154577
+ }
154578
+ lines.push(current);
154579
+ current = unit;
154580
+ pendingWhitespace = false;
154581
+ }
154582
+ const completed = current.trimEnd();
154583
+ if (completed.length > 0) {
154584
+ lines.push(completed);
154585
+ }
154586
+ }
154587
+ return lines;
154588
+ }
154402
154589
  function valueToX(val2, range, leftX, rightX) {
154403
154590
  const usable = rightX - leftX;
154404
154591
  let ratio;
@@ -154448,6 +154635,12 @@ function buildSideCategoryLabels(categoryLabels, layout) {
154448
154635
  dominantBaseline: "central"
154449
154636
  }));
154450
154637
  }
154638
+ function widestCategoryLabelWidth(categoryLabels, fontSize) {
154639
+ return categoryLabels.reduce(
154640
+ (max, label) => Math.max(max, estimateTextWidth(label, fontSize)),
154641
+ 0
154642
+ );
154643
+ }
154451
154644
  function categoryTotals2(series, catCount) {
154452
154645
  return Array.from(
154453
154646
  { length: catCount },
@@ -154462,7 +154655,9 @@ function barFill(chartData, series, seriesIndex, pointIndex) {
154462
154655
  return resolveDataPointFill(series, pointIndex, paletteColor2(seriesIndex, palette)) ?? seriesColor2(series, seriesIndex, palette);
154463
154656
  }
154464
154657
  function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
154465
- const layout = computePlotLayout(element.width, element.height, chartData, true), catCount = Math.max(categoryLabels.length, 1), series = chartData.series, grouping = chartData.grouping ?? "clustered", isStacked = grouping === "stacked" || grouping === "percentStacked", isPercent = grouping === "percentStacked", range = isPercent ? { min: 0, max: 100, span: 100 } : isStacked ? computeStackedValueRange(series, catCount, layout.plotWidth) : computeValueRangeForChart(series, chartData.axes, layout.plotWidth), { gridlines, axisLabels } = buildTransposedValueAxis(range, layout), zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight), zeroLine = range.min < 0 && range.max > 0 ? {
154658
+ const layout = computePlotLayout(element.width, element.height, chartData, true, {
154659
+ leftCategoryLabelWidth: widestCategoryLabelWidth(categoryLabels, DEFAULT_CHART_TEXT_PX)
154660
+ }), catCount = Math.max(categoryLabels.length, 1), series = chartData.series, grouping = chartData.grouping ?? "clustered", isStacked = grouping === "stacked" || grouping === "percentStacked", isPercent = grouping === "percentStacked", range = isPercent ? { min: 0, max: 100, span: 100 } : isStacked ? computeStackedValueRange(series, catCount, layout.plotWidth) : computeValueRangeForChart(series, chartData.axes, layout.plotWidth), { gridlines, axisLabels } = buildTransposedValueAxis(range, layout), zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight), zeroLine = range.min < 0 && range.max > 0 ? {
154466
154661
  kind: "line",
154467
154662
  x1: zeroX,
154468
154663
  y1: layout.plotTop,
@@ -157659,9 +157854,12 @@ function categoryAxisBand(chartData) {
157659
157854
  ), fontPx = axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX, offset = 4 + 8 * ((axis?.labelOffset ?? 100) / 100);
157660
157855
  return Math.max(24, offset + fontPx * 1.2);
157661
157856
  }
157857
+ function leftAxisBand(leftCategoryLabelWidth) {
157858
+ return Math.max(40, (leftCategoryLabelWidth ?? 0) + 4);
157859
+ }
157662
157860
  function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, options) {
157663
157861
  const svgWidth = Math.max(1, elementWidth), svgHeight = Math.max(1, elementHeight);
157664
- let plotLeft = hasAxes ? 48 : 8, plotTop = 8, plotRight = svgWidth - 8, plotBottom = svgHeight - (hasAxes ? categoryAxisBand(chartData) : 8);
157862
+ let plotLeft = hasAxes ? 8 + leftAxisBand(options?.leftCategoryLabelWidth) : 8, plotTop = 8, plotRight = svgWidth - 8, plotBottom = svgHeight - (hasAxes ? categoryAxisBand(chartData) : 8);
157665
157863
  if (hasAxes && options?.categoryAxisAtTop) {
157666
157864
  plotBottom = svgHeight - 8;
157667
157865
  plotTop += categoryAxisBand(chartData);
@@ -157700,7 +157898,7 @@ function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, opti
157700
157898
  plotRight = manual.x + manual.width;
157701
157899
  plotBottom = manual.y + manual.height;
157702
157900
  if (hasAxes && plotLayout.layoutTarget !== "inner") {
157703
- plotLeft += 40;
157901
+ plotLeft += leftAxisBand(options?.leftCategoryLabelWidth);
157704
157902
  plotBottom -= categoryAxisBand(chartData) - 8;
157705
157903
  }
157706
157904
  }
@@ -158283,7 +158481,7 @@ function regionViewBounds(viewedRegionType, regionValues) {
158283
158481
  };
158284
158482
  }
158285
158483
  function scalePathD(d, scale2, dx, dy) {
158286
- const tokens = d.trim().split(/[\s,]+/u);
158484
+ const tokens = d.match(/[A-Za-z]|-?\d+(?:\.\d+)?/gu) ?? [];
158287
158485
  const out = [];
158288
158486
  let i2 = 0;
158289
158487
  while (i2 < tokens.length) {
@@ -158298,7 +158496,7 @@ function scalePathD(d, scale2, dx, dy) {
158298
158496
  continue;
158299
158497
  }
158300
158498
  const xRaw = parseFloat(tok);
158301
- const yRaw = parseFloat(tokens[i2 + 1] ?? "0");
158499
+ const yRaw = parseFloat(tokens[i2 + 1] ?? "");
158302
158500
  if (!Number.isNaN(xRaw) && !Number.isNaN(yRaw)) {
158303
158501
  out.push(`${(xRaw * scale2 + dx).toFixed(2)},${(yRaw * scale2 + dy).toFixed(2)}`);
158304
158502
  i2 += 2;
@@ -173051,6 +173249,8 @@ var translationsEn = {
173051
173249
  "pptx.collaboration.userCount": "{{count}} user(s)",
173052
173250
  "pptx.collaboration.youLabel": "{{name}} (you)",
173053
173251
  "pptx.collaboration.usersConnected": "{{count}} user(s) connected",
173252
+ "pptx.collaboration.editable": "Editable",
173253
+ "pptx.collaboration.shellStatusLabel": "Collaboration status",
173054
173254
  "pptx.collaboration.moreUsers": "{{count}} more user(s)",
173055
173255
  "pptx.collaboration.onePersonHere": "1 person here",
173056
173256
  "pptx.collaboration.peopleHere": "{{count}} people here",
@@ -178931,11 +179131,16 @@ function buildParagraphs(element, fieldContext, segmentOverrides, options) {
178931
179131
  }
178932
179132
  var sessions = /* @__PURE__ */ new WeakMap();
178933
179133
  var nextSession = 0;
178934
- function createInlineListSeed(element) {
178935
- if (!hasTextProperties(element) || !element.textSegments?.some((segment) => resolveParagraphBullet(segment))) {
179134
+ function createInlineListSeed(element, options) {
179135
+ if (!hasTextProperties(element) || !options?.includePlain && !element.textSegments?.some((segment) => resolveParagraphBullet(segment))) {
178936
179136
  return void 0;
178937
179137
  }
178938
- const segments = structuredClone(element.textSegments);
179138
+ const textStyle = element.textStyle;
179139
+ const segments = element.textSegments?.length ? structuredClone(element.textSegments) : (element.text ?? "").split("\n").flatMap((text22, index) => [
179140
+ ...index > 0 ? [{ text: "\n", style: {}, isParagraphBreak: true }] : [],
179141
+ { text: text22, style: structuredClone(textStyle ?? {}) }
179142
+ ]);
179143
+ element = { ...element, textSegments: structuredClone(segments) };
178939
179144
  const paragraphs2 = [{ segments: [] }];
178940
179145
  const indices = [[]];
178941
179146
  for (const [index, segment] of segments.entries()) {
@@ -179163,6 +179368,54 @@ function clearSingleTextDecoration(node, blockRoot) {
179163
179368
  ancestor = ancestor.parentElement;
179164
179369
  }
179165
179370
  }
179371
+ var snapshots = /* @__PURE__ */ new WeakMap();
179372
+ function recordInlineListProvenance(seed, root, snapshot, blocks, origins, unchanged22) {
179373
+ const session = inlineListSession(seed);
179374
+ const paragraphs2 = /* @__PURE__ */ new Map();
179375
+ const hidden = [];
179376
+ const segments = snapshot.textSegments ?? [];
179377
+ let paragraphIndex = 0;
179378
+ let start = 0;
179379
+ const record2 = (end, terminator) => {
179380
+ const block = blocks[paragraphIndex++];
179381
+ if (!block) return;
179382
+ paragraphs2.set(block, start < end ? start : terminator ?? null);
179383
+ const body = segments.slice(start, end);
179384
+ const content = body.filter((segment, index) => index !== 0 || !isBulletMarkerSegment(segment));
179385
+ const onlyEmptyCarrier = content.length === 1 && content[0].text === "" && !content[0].isLineBreak;
179386
+ for (let index = start; index < end; index++) {
179387
+ const segment = segments[index];
179388
+ const marker = index === start && isBulletMarkerSegment(segment);
179389
+ if (!marker && (segment.text !== "" || segment.isLineBreak)) continue;
179390
+ const node = marker || onlyEmptyCarrier ? block : unchanged22 ? inlineListDescendants(block).find((child27) => session.runNodes.get(child27) === index) : origins[index];
179391
+ hidden.push({ node, kind: marker ? "marker" : "empty", index });
179392
+ }
179393
+ };
179394
+ for (const [index, segment] of segments.entries()) {
179395
+ if (!isParagraphSeparatorSegment(segment)) continue;
179396
+ record2(index, index);
179397
+ start = index + 1;
179398
+ }
179399
+ record2(segments.length);
179400
+ snapshots.set(snapshot, { seed, root, paragraphs: paragraphs2, hidden });
179401
+ }
179402
+ function readInlineListProvenance(snapshot, previous) {
179403
+ const current = snapshots.get(snapshot);
179404
+ const before = previous && snapshots.get(previous);
179405
+ if (!current || previous && (!before || before.seed !== current.seed || before.root !== current.root)) {
179406
+ return void 0;
179407
+ }
179408
+ const matches2 = (a, b) => a.node !== void 0 && a.node === b.node && a.kind === b.kind;
179409
+ return {
179410
+ paragraphSources: [...current.paragraphs.keys()].map(
179411
+ (node) => before?.paragraphs.get(node) ?? null
179412
+ ),
179413
+ hiddenSources: current.hidden.map((origin) => {
179414
+ const old = before?.hidden.filter((candidate) => matches2(origin, candidate));
179415
+ return old?.length === 1 && current.hidden.filter((candidate) => matches2(origin, candidate)).length === 1 ? old[0].index : null;
179416
+ })
179417
+ };
179418
+ }
179166
179419
  function inlineListStyleDelta(node, baseline = "", inheritedColor) {
179167
179420
  const style = {};
179168
179421
  const original = node.ownerDocument.createElement("span").style;
@@ -179221,6 +179474,11 @@ function bodyOnly(segment) {
179221
179474
  }
179222
179475
  function readInlineListRuns(session, block, bodyStyle) {
179223
179476
  const runs = [];
179477
+ const origins = [];
179478
+ const push2 = (segment, node) => {
179479
+ runs.push(segment);
179480
+ origins.push(node);
179481
+ };
179224
179482
  let unsupported = false;
179225
179483
  let unchanged22 = true;
179226
179484
  let placeholder = false;
@@ -179234,10 +179492,10 @@ function readInlineListRuns(session, block, bodyStyle) {
179234
179492
  const style2 = { ...inherited, ...parentDelta };
179235
179493
  for (const [index2, text22] of node.nodeValue.split("\n").entries()) {
179236
179494
  if (index2 > 0) {
179237
- runs.push({ text: "\n", style: { ...style2 }, isLineBreak: true });
179495
+ push2({ text: "\n", style: { ...style2 }, isLineBreak: true }, node);
179238
179496
  }
179239
179497
  if (text22) {
179240
- runs.push({ text: text22, style: { ...style2 } });
179498
+ push2({ text: text22, style: { ...style2 } }, node);
179241
179499
  }
179242
179500
  }
179243
179501
  }
@@ -179269,7 +179527,7 @@ function readInlineListRuns(session, block, bodyStyle) {
179269
179527
  const oldChildren = originalIndex === void 0 ? void 0 : session.runChildren.get(originalIndex);
179270
179528
  const intact = originalIndex !== void 0 && node.innerHTML === session.runHtml.get(originalIndex) && children13.length === oldChildren?.length && children13.every((child27, childIndex) => child27 === oldChildren[childIndex]);
179271
179529
  if (intact && original) {
179272
- runs.push({ ...bodyOnly(original), style });
179530
+ push2({ ...bodyOnly(original), style }, node);
179273
179531
  unchanged22 &&= index === originalIndex && Object.keys(delta).length === 0;
179274
179532
  return;
179275
179533
  }
@@ -179283,7 +179541,7 @@ function readInlineListRuns(session, block, bodyStyle) {
179283
179541
  return;
179284
179542
  }
179285
179543
  if (node.tagName === "BR") {
179286
- runs.push({ text: "\n", style, isLineBreak: true });
179544
+ push2({ text: "\n", style, isLineBreak: true }, node);
179287
179545
  placeholder = original?.isLineBreak !== true;
179288
179546
  return;
179289
179547
  }
@@ -179293,9 +179551,9 @@ function readInlineListRuns(session, block, bodyStyle) {
179293
179551
  };
179294
179552
  walk2(block, bodyStyle);
179295
179553
  if (runs.length === 1 && runs[0].isLineBreak && placeholder) {
179296
- return { runs: [{ text: "", style: runs[0].style }], unchanged: false };
179554
+ return { runs: [{ text: "", style: runs[0].style }], origins: [block], unchanged: false };
179297
179555
  }
179298
- return unsupported ? void 0 : { runs, unchanged: unchanged22 };
179556
+ return unsupported ? void 0 : { runs, origins, unchanged: unchanged22 };
179299
179557
  }
179300
179558
  function hasOnlyCaretPlaceholder(element) {
179301
179559
  const content = Array.from(element.childNodes).filter((child27) => {
@@ -179367,6 +179625,7 @@ function readInlineListSnapshot(seed, root) {
179367
179625
  return fallback("unsupported-paragraph-structure");
179368
179626
  }
179369
179627
  const segments = [];
179628
+ const origins = [];
179370
179629
  const text22 = [];
179371
179630
  const sequence = createAutoNumberSequence();
179372
179631
  let unchanged22 = blocks.length === seed.paragraphs.length;
@@ -179387,7 +179646,7 @@ function readInlineListSnapshot(seed, root) {
179387
179646
  return fallback("unsupported-run-structure");
179388
179647
  }
179389
179648
  const { runs } = body;
179390
- const bodyText = runs.map((run) => run.text).join("");
179649
+ const bodyText = runs.map((run) => run.isLineBreak ? "\n" : run.text).join("");
179391
179650
  text22.push(bodyText);
179392
179651
  unchanged22 &&= original === position2 && token2 === seed.paragraphs[position2].token && body.unchanged && bodyText === seed.paragraphs[position2].runs.map((run) => run.text).join("") && runs.every(
179393
179652
  (run, index) => JSON.stringify(run.style) === JSON.stringify(seed.paragraphs[position2].runs[index]?.style)
@@ -179397,6 +179656,7 @@ function readInlineListSnapshot(seed, root) {
179397
179656
  text: "",
179398
179657
  style: structuredClone(carrier?.paragraphInsertionStyle ?? carrier?.style ?? {})
179399
179658
  });
179659
+ body.origins.push(block);
179400
179660
  }
179401
179661
  if (carrier) {
179402
179662
  if (original !== void 0) {
@@ -179444,14 +179704,18 @@ function readInlineListSnapshot(seed, root) {
179444
179704
  delete first[key2];
179445
179705
  }
179446
179706
  runs.unshift(marker);
179707
+ body.origins.unshift(block);
179447
179708
  }
179448
179709
  if (position2 > 0) {
179449
179710
  segments.push({ text: "\n", style: {}, isParagraphBreak: true });
179711
+ origins.push(void 0);
179450
179712
  }
179451
179713
  segments.push(...runs);
179714
+ origins.push(...body.origins);
179452
179715
  }
179453
179716
  const textSegments = unchanged22 ? structuredClone(session.originalSegments) : segments;
179454
179717
  const snapshot = { elementId: seed.elementId, text: text22.join("\n"), textSegments };
179718
+ recordInlineListProvenance(seed, root, snapshot, blocks, origins, unchanged22);
179455
179719
  return {
179456
179720
  kind: "supported",
179457
179721
  snapshot,
@@ -179460,6 +179724,12 @@ function readInlineListSnapshot(seed, root) {
179460
179724
  })
179461
179725
  };
179462
179726
  }
179727
+ function readInlineListNativeSnapshot(seed, root, previous) {
179728
+ const read = readInlineListSnapshot(seed, root);
179729
+ if (read.kind !== "supported") return read;
179730
+ const provenance = readInlineListProvenance(read.snapshot, previous);
179731
+ return provenance ? { ...read, ...provenance } : { kind: "unsupported", reason: "unknown-native-baseline", text: read.snapshot.text };
179732
+ }
179463
179733
  function paragraphBodies(segments) {
179464
179734
  const paragraphs2 = [""];
179465
179735
  let first = true;
@@ -179469,7 +179739,7 @@ function paragraphBodies(segments) {
179469
179739
  first = true;
179470
179740
  } else {
179471
179741
  if (!first || !isBulletMarkerSegment(segment)) {
179472
- paragraphs2[paragraphs2.length - 1] += segment.text;
179742
+ paragraphs2[paragraphs2.length - 1] += segment.isLineBreak ? "\n" : segment.text;
179473
179743
  }
179474
179744
  first = false;
179475
179745
  }
@@ -179489,7 +179759,7 @@ function modelPoint(segments, offset, end) {
179489
179759
  }
179490
179760
  continue;
179491
179761
  }
179492
- const next = position2 + segment.text.length;
179762
+ const next = position2 + (first || segment.isLineBreak ? 1 : segment.text.length);
179493
179763
  if (!first && !segment.isLineBreak) {
179494
179764
  last = { index, offset: segment.text.length };
179495
179765
  if (end ? offset <= next : offset < next || offset === position2 && next === position2) {
@@ -179501,18 +179771,30 @@ function modelPoint(segments, offset, end) {
179501
179771
  return last;
179502
179772
  }
179503
179773
  function readInlineListSelection(seed, root, selection = root.ownerDocument.defaultView?.getSelection() ?? null) {
179774
+ return readInlineListRange(seed, root, selection?.rangeCount ? selection.getRangeAt(0) : null);
179775
+ }
179776
+ function readInlineListRange(seed, root, range) {
179504
179777
  const read = readInlineListSnapshot(seed, root);
179505
179778
  if (read.kind !== "supported") {
179506
179779
  return { kind: "unsupported", reason: read.reason };
179507
179780
  }
179508
179781
  const { snapshot } = read;
179509
- if (!selection?.rangeCount) {
179782
+ if (!range) {
179510
179783
  return { kind: "supported", snapshot, selection: null };
179511
179784
  }
179512
- const range = selection.getRangeAt(0);
179513
179785
  if (!root.contains(range.startContainer) || !root.contains(range.endContainer)) {
179514
179786
  return { kind: "unsupported", reason: "selection-outside-session" };
179515
179787
  }
179788
+ try {
179789
+ const checked = root.ownerDocument.createRange();
179790
+ checked.setStart(range.startContainer, range.startOffset);
179791
+ checked.setEnd(range.endContainer, range.endOffset);
179792
+ if (checked.startContainer !== range.startContainer || checked.startOffset !== range.startOffset || checked.endContainer !== range.endContainer || checked.endOffset !== range.endOffset) {
179793
+ return { kind: "unsupported", reason: "invalid-selection-boundary" };
179794
+ }
179795
+ } catch {
179796
+ return { kind: "unsupported", reason: "invalid-selection-boundary" };
179797
+ }
179516
179798
  const blocks = Array.from(root.children);
179517
179799
  const bodies = paragraphBodies(snapshot.textSegments);
179518
179800
  if (blocks.some(
@@ -185735,6 +186017,26 @@ function presenceToCursors(presence, activeSlideIndex) {
185735
186017
  }
185736
186018
  return cursors;
185737
186019
  }
186020
+ function resolveCollaborationShellEditability(input) {
186021
+ return input.authorizedCanEdit && (!input.configured || !input.readOnly && !input.sourcePending && !input.sourceError);
186022
+ }
186023
+ function resolveCollaborationShellState(input) {
186024
+ const status = input.configured ? input.status : "disconnected";
186025
+ const remoteUsers = input.configured ? input.remoteUsers : [];
186026
+ return {
186027
+ canEdit: resolveCollaborationShellEditability(input),
186028
+ status,
186029
+ remoteUsers,
186030
+ connectedCount: remoteUsers.length + (status === "connected" ? 1 : 0)
186031
+ };
186032
+ }
186033
+ function describeCollaborationShellState(state, translate) {
186034
+ return [
186035
+ translate(`pptx.collaboration.status.${state.status}`),
186036
+ translate("pptx.collaboration.usersConnected", { count: state.connectedCount }),
186037
+ translate(state.canEdit ? "pptx.collaboration.editable" : "pptx.toolbar.readOnly")
186038
+ ].join(" \xB7 ");
186039
+ }
185738
186040
  function observeExternalCollaborationSession(session, onSnapshot) {
185739
186041
  let active2 = true;
185740
186042
  let subscribing = true;
@@ -185930,6 +186232,9 @@ function buildSegmentAttrs(seg) {
185930
186232
  if (seg.paragraphInsertionStyle) {
185931
186233
  a.pi = JSON.stringify(seg.paragraphInsertionStyle);
185932
186234
  }
186235
+ if (seg.paragraphProperties) {
186236
+ a.pp = JSON.stringify(seg.paragraphProperties);
186237
+ }
185933
186238
  if (typeof seg.fieldType === "string") {
185934
186239
  a.ft = seg.fieldType;
185935
186240
  }
@@ -186042,6 +186347,12 @@ function decodeDelta(delta) {
186042
186347
  } catch {
186043
186348
  }
186044
186349
  }
186350
+ if (a.pp) {
186351
+ try {
186352
+ seg.paragraphProperties = JSON.parse(a.pp);
186353
+ } catch {
186354
+ }
186355
+ }
186045
186356
  if (a.ft) {
186046
186357
  seg.fieldType = a.ft;
186047
186358
  }
@@ -186104,6 +186415,22 @@ function decodeDelta(delta) {
186104
186415
  function decodeTextBody(ytext) {
186105
186416
  return decodeDelta(ytext.toDelta());
186106
186417
  }
186418
+ function inlineListBodyText(segments) {
186419
+ let first = true;
186420
+ let text22 = "";
186421
+ for (const segment of segments ?? []) {
186422
+ if (isParagraphSeparatorSegment(segment)) {
186423
+ text22 += "\n";
186424
+ first = true;
186425
+ } else {
186426
+ if (!first || !isBulletMarkerSegment(segment)) {
186427
+ text22 += segment.isLineBreak ? "\n" : segment.text;
186428
+ }
186429
+ first = false;
186430
+ }
186431
+ }
186432
+ return text22;
186433
+ }
186107
186434
  var YDOC_SLIDES_KEY = "pptx:slides";
186108
186435
  var SCALAR_ELEMENT_KEYS = /* @__PURE__ */ new Set([
186109
186436
  "id",
@@ -186357,6 +186684,9 @@ function readElementFromYMap(ymap, assets) {
186357
186684
  }
186358
186685
  });
186359
186686
  readAssetFields(ymap, assets, element);
186687
+ if (Array.isArray(element.textSegments) && element.textSegments.length > 0) {
186688
+ element.text = inlineListBodyText(element.textSegments);
186689
+ }
186360
186690
  return element;
186361
186691
  }
186362
186692
  function writeSlideToYMap(slide, ymap, factories, assets) {
@@ -186420,6 +186750,32 @@ function observeYDocSlides(ydoc, onChange) {
186420
186750
  arr.observeDeep(onChange);
186421
186751
  return () => arr.unobserveDeep(onChange);
186422
186752
  }
186753
+ var leases = /* @__PURE__ */ new WeakMap();
186754
+ function registerCollaborationTextLease(target, ownsModel) {
186755
+ const lease = { ownsModel };
186756
+ leases.set(target, lease);
186757
+ return () => {
186758
+ if (leases.get(target) === lease) {
186759
+ leases.delete(target);
186760
+ }
186761
+ };
186762
+ }
186763
+ function hasCollaborationTextLease(target, candidate) {
186764
+ const lease = leases.get(target);
186765
+ if (!lease) {
186766
+ return false;
186767
+ }
186768
+ try {
186769
+ if (lease.ownsModel(candidate) && leases.get(target) === lease) {
186770
+ return true;
186771
+ }
186772
+ } catch {
186773
+ }
186774
+ if (leases.get(target) === lease) {
186775
+ leases.delete(target);
186776
+ }
186777
+ return false;
186778
+ }
186423
186779
  function isYTextEditable(value) {
186424
186780
  return isYTextLike(value) && typeof value.delete === "function" && typeof value.format === "function";
186425
186781
  }
@@ -186542,8 +186898,11 @@ var LOCAL_SYNC_ORIGIN = "pptx-viewer:local-sync";
186542
186898
  function jsonEqual(a, b) {
186543
186899
  return a === b || JSON.stringify(a) === JSON.stringify(b);
186544
186900
  }
186545
- function reconcileScalars(ymap, rec, keys) {
186901
+ function reconcileScalars(ymap, rec, keys, skipKey) {
186546
186902
  for (const key2 of keys) {
186903
+ if (key2 === skipKey) {
186904
+ continue;
186905
+ }
186547
186906
  const next = rec[key2];
186548
186907
  const current = ymap.get(key2);
186549
186908
  if (next === void 0) {
@@ -186592,9 +186951,12 @@ function reconcileElementTextBody(ymap, rec, factories) {
186592
186951
  }
186593
186952
  function reconcileElementYMap(ymap, element, factories, assets) {
186594
186953
  const rec = element;
186595
- reconcileScalars(ymap, rec, SCALAR_ELEMENT_KEYS);
186954
+ const ownsText = hasCollaborationTextLease(ymap, element);
186955
+ reconcileScalars(ymap, rec, SCALAR_ELEMENT_KEYS, ownsText ? "text" : void 0);
186596
186956
  reconcileComplexFields(ymap, rec, COMPLEX_ELEMENT_FIELDS);
186597
- reconcileElementTextBody(ymap, rec, factories);
186957
+ if (!ownsText) {
186958
+ reconcileElementTextBody(ymap, rec, factories);
186959
+ }
186598
186960
  reconcileAssetFields(rec.id, rec, ymap, assets);
186599
186961
  }
186600
186962
  function mapIdAt(arr, index) {
@@ -186708,8 +187070,13 @@ function observeExternalCollaborationReadiness(session, options) {
186708
187070
  }
186709
187071
  };
186710
187072
  const suspend = () => {
187073
+ const preserveAcceptedEdits = active2 && established && options.gate.isOpen();
186711
187074
  options.gate.reset();
186712
187075
  options.livePatcher?.configure(null, null);
187076
+ if (preserveAcceptedEdits) {
187077
+ lastAdopted = void 0;
187078
+ adopt(readSlidesFromYDoc(session.doc));
187079
+ }
186713
187080
  options.onSuspend?.();
186714
187081
  notifyReadOnly();
186715
187082
  };
@@ -186966,6 +187333,576 @@ function applyLivePatch(doc, factories, patch, textPatchLimit) {
186966
187333
  reconcileElementTextBody(ymap, { textSegments: segments }, factories);
186967
187334
  }
186968
187335
  }
187336
+ function initializeCollaborationText(doc, element, factories, isCurrent) {
187337
+ const needsSeed = () => {
187338
+ const body = element.get("textBody");
187339
+ return (body === void 0 || isYTextEditable(body) && body.toDelta().length === 0) && typeof element.get("text") === "string";
187340
+ };
187341
+ if (!isCurrent() || !needsSeed()) {
187342
+ return;
187343
+ }
187344
+ doc.transact(() => {
187345
+ if (!isCurrent() || !needsSeed()) {
187346
+ return;
187347
+ }
187348
+ let textStyle;
187349
+ try {
187350
+ const raw = element.get(COMPLEX_ELEMENT_FIELDS.textStyle);
187351
+ if (typeof raw === "string") {
187352
+ textStyle = JSON.parse(raw);
187353
+ }
187354
+ } catch {
187355
+ }
187356
+ const seed = createInlineListSeed(
187357
+ {
187358
+ id: element.get("id"),
187359
+ type: element.get("type"),
187360
+ text: element.get("text"),
187361
+ textStyle
187362
+ },
187363
+ { includePlain: true }
187364
+ );
187365
+ const segments = seed && inlineListSession(seed)?.originalSegments;
187366
+ if (!segments) {
187367
+ return;
187368
+ }
187369
+ const previous = element.get("textBody");
187370
+ const text22 = isYTextEditable(previous) ? previous : factories.createText();
187371
+ encodeTextBody(segments, text22);
187372
+ if (text22 !== previous) {
187373
+ element.set("textBody", text22);
187374
+ }
187375
+ }, LOCAL_SYNC_ORIGIN);
187376
+ }
187377
+ var textBoundary = (text22, index) => !(text22.charCodeAt(index - 1) >= 55296 && text22.charCodeAt(index - 1) <= 56319 && text22.charCodeAt(index) >= 56320 && text22.charCodeAt(index) <= 57343);
187378
+ function textSessionReplacementSpan(before, after, { from, to }) {
187379
+ const suffix = before.length - to;
187380
+ const afterEnd = after.length - suffix;
187381
+ return Number.isInteger(from) && Number.isInteger(to) && from >= 0 && to >= from && to <= before.length && afterEnd >= from && before.slice(0, from) === after.slice(0, from) && before.slice(to) === after.slice(afterEnd) && textBoundary(before, from) && textBoundary(before, to) && textBoundary(after, from) && textBoundary(after, afterEnd) ? { prefix: from, suffix } : void 0;
187382
+ }
187383
+ function textSessionRetainedIndices(before, after, edit) {
187384
+ let indices;
187385
+ if (edit && "retainedIndices" in edit) {
187386
+ indices = Array.from(edit.retainedIndices);
187387
+ } else {
187388
+ const explicit = edit && textSessionReplacementSpan(before, after, edit);
187389
+ if (edit && !explicit) {
187390
+ return void 0;
187391
+ }
187392
+ const prefix = explicit?.prefix ?? commonPrefixLength3(before, after);
187393
+ const suffix = explicit?.suffix ?? commonSuffixLength3(before, after, prefix);
187394
+ indices = Array.from(
187395
+ { length: after.length },
187396
+ (_, index) => index < prefix ? index : index >= after.length - suffix ? before.length - (after.length - index) : null
187397
+ );
187398
+ }
187399
+ if (indices.length !== after.length) {
187400
+ return void 0;
187401
+ }
187402
+ let last = -1;
187403
+ for (const [index, retained] of indices.entries()) {
187404
+ if (retained === null) {
187405
+ continue;
187406
+ }
187407
+ if (!Number.isInteger(retained) || retained <= last || retained >= before.length || before[retained] !== after[index] || (!textBoundary(before, retained) || !textBoundary(after, index)) && indices[index - 1] !== retained - 1 || (!textBoundary(before, retained + 1) || !textBoundary(after, index + 1)) && indices[index + 1] !== retained + 1) {
187408
+ return void 0;
187409
+ }
187410
+ last = retained;
187411
+ }
187412
+ return indices;
187413
+ }
187414
+ function textSessionPlan(before, after, edit) {
187415
+ const retainedIndices = textSessionRetainedIndices(before, after, edit);
187416
+ if (!retainedIndices) {
187417
+ return void 0;
187418
+ }
187419
+ const sources = edit && "retainedIndices" in edit ? edit.paragraphSources : void 0;
187420
+ if (sources === void 0) {
187421
+ return { retainedIndices };
187422
+ }
187423
+ const paragraphSources = Array.from(sources);
187424
+ if (paragraphSources.length !== after.length || paragraphSources.some(
187425
+ (source) => source !== null && (!Number.isInteger(source) || source < 0 || source >= before.length)
187426
+ )) {
187427
+ return void 0;
187428
+ }
187429
+ return { retainedIndices, paragraphSources };
187430
+ }
187431
+ function textSessionAttributesEqual(a, b) {
187432
+ return Object.keys(a).length === Object.keys(b).length && Object.keys(a).every((key2) => a[key2] === b[key2]);
187433
+ }
187434
+ function textSessionDeltaSupported(delta) {
187435
+ return delta.every(
187436
+ (op2) => typeof op2.insert === "string" && Object.values(op2.attributes ?? {}).every((value) => typeof value === "string")
187437
+ );
187438
+ }
187439
+ function textSessionUnits(delta) {
187440
+ const units = [];
187441
+ for (const op2 of delta) {
187442
+ if (typeof op2.insert !== "string") {
187443
+ return void 0;
187444
+ }
187445
+ const attributes = {};
187446
+ for (const [key2, value] of Object.entries(op2.attributes ?? {})) {
187447
+ if (typeof value !== "string") {
187448
+ return void 0;
187449
+ }
187450
+ attributes[key2] = value;
187451
+ }
187452
+ for (let index = 0; index < op2.insert.length; index++) {
187453
+ units.push({ text: op2.insert[index], attributes });
187454
+ }
187455
+ }
187456
+ return units;
187457
+ }
187458
+ function textSessionAttributePatch(before, after, current) {
187459
+ const patch = {};
187460
+ for (const key2 of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
187461
+ if (before[key2] !== after[key2]) {
187462
+ patch[key2] = key2 === "s" ? mergeTextSessionObjectAttribute(before[key2], after[key2], current[key2]) : after[key2] ?? null;
187463
+ }
187464
+ }
187465
+ return patch;
187466
+ }
187467
+ function isObject(value) {
187468
+ return typeof value === "object" && value !== null && !Array.isArray(value);
187469
+ }
187470
+ function mergeObjectChanges(before, after, current) {
187471
+ const merged = new Map(Object.entries(current));
187472
+ for (const key2 of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
187473
+ const oldValue = Object.hasOwn(before, key2) ? before[key2] : void 0;
187474
+ const nextValue = Object.hasOwn(after, key2) ? after[key2] : void 0;
187475
+ if (JSON.stringify(oldValue) === JSON.stringify(nextValue)) {
187476
+ continue;
187477
+ }
187478
+ const liveValue = merged.get(key2);
187479
+ if ((oldValue === void 0 || isObject(oldValue)) && (nextValue === void 0 || isObject(nextValue)) && isObject(liveValue)) {
187480
+ const nested = mergeObjectChanges(oldValue ?? {}, nextValue ?? {}, liveValue);
187481
+ if (Object.keys(nested).length > 0) {
187482
+ merged.set(key2, nested);
187483
+ } else {
187484
+ merged.delete(key2);
187485
+ }
187486
+ } else if (nextValue === void 0) {
187487
+ merged.delete(key2);
187488
+ } else {
187489
+ merged.set(key2, nextValue);
187490
+ }
187491
+ }
187492
+ return Object.fromEntries(merged);
187493
+ }
187494
+ function mergeTextSessionObjectAttribute(before, after, current) {
187495
+ try {
187496
+ const oldValue = before ? JSON.parse(before) : {};
187497
+ const nextValue = after ? JSON.parse(after) : {};
187498
+ const liveValue = current ? JSON.parse(current) : {};
187499
+ if (isObject(oldValue) && isObject(nextValue) && isObject(liveValue)) {
187500
+ const merged = mergeObjectChanges(oldValue, nextValue, liveValue);
187501
+ return Object.keys(merged).length ? JSON.stringify(merged) : null;
187502
+ }
187503
+ } catch {
187504
+ }
187505
+ return after ?? null;
187506
+ }
187507
+ var paragraphKeys = ["bi", "pl", "pr", "pi", "pp"];
187508
+ function readParagraphAttributes(previous, source, readCurrent) {
187509
+ const carrier = readCurrent(source);
187510
+ if (carrier) return carrier;
187511
+ if (previous[source].attributes.pb === "1") return {};
187512
+ let start = source;
187513
+ while (start > 0 && previous[start - 1].attributes.pb !== "1") start--;
187514
+ for (let index = start; index < previous.length && previous[index].attributes.pb !== "1"; index++) {
187515
+ const current = readCurrent(index);
187516
+ if (current) return current;
187517
+ }
187518
+ return {};
187519
+ }
187520
+ function textSessionParagraphPatches(previous, desired, sources, readCurrent) {
187521
+ const patches = /* @__PURE__ */ new Map();
187522
+ const cache = /* @__PURE__ */ new Map();
187523
+ for (const [index, source] of (sources ?? []).entries()) {
187524
+ if (source === null) {
187525
+ continue;
187526
+ }
187527
+ const after = desired[index].attributes;
187528
+ let byAttributes = cache.get(source);
187529
+ if (!byAttributes) {
187530
+ byAttributes = /* @__PURE__ */ new Map();
187531
+ cache.set(source, byAttributes);
187532
+ }
187533
+ let patch = byAttributes.get(after);
187534
+ if (!patch) {
187535
+ const before = previous[source].attributes;
187536
+ const current = readParagraphAttributes(previous, source, readCurrent);
187537
+ patch = {};
187538
+ for (const key2 of paragraphKeys) {
187539
+ patch[key2] = before[key2] === after[key2] ? current[key2] ?? null : key2 === "pl" ? after[key2] ?? null : mergeTextSessionObjectAttribute(before[key2], after[key2], current[key2]);
187540
+ }
187541
+ byAttributes.set(after, patch);
187542
+ }
187543
+ patches.set(index, patch);
187544
+ }
187545
+ return patches;
187546
+ }
187547
+ function textSessionInsertionAttributes(attributes, paragraph) {
187548
+ const result = { ...attributes };
187549
+ for (const [key2, value] of Object.entries(paragraph ?? {})) {
187550
+ if (value === null) {
187551
+ delete result[key2];
187552
+ } else {
187553
+ result[key2] = value;
187554
+ }
187555
+ }
187556
+ return result;
187557
+ }
187558
+ function applyTextSessionPlan(text22, positions2, previous, desired, indices, emptyBoundary, paragraphSources) {
187559
+ const range = (unit) => {
187560
+ const start = positions2.resolve(unit.start);
187561
+ const end = positions2.resolve(unit.end);
187562
+ return start !== null && end !== null && end > start ? { start, end } : void 0;
187563
+ };
187564
+ const sourceUnits = paragraphSources && textSessionUnits(text22.toDelta());
187565
+ if (paragraphSources && !sourceUnits) {
187566
+ return void 0;
187567
+ }
187568
+ const paragraphPatches = textSessionParagraphPatches(
187569
+ previous,
187570
+ desired,
187571
+ paragraphSources,
187572
+ (source) => {
187573
+ const current = range(previous[source]);
187574
+ return current ? sourceUnits?.[current.start]?.attributes : void 0;
187575
+ }
187576
+ );
187577
+ const batches = [];
187578
+ for (let index = 0; index < indices.length; ) {
187579
+ if (indices[index] !== null) {
187580
+ index++;
187581
+ continue;
187582
+ }
187583
+ const from = index;
187584
+ while (index < indices.length && indices[index] === null) {
187585
+ index++;
187586
+ }
187587
+ const oldStart = from === 0 ? 0 : indices[from - 1] + 1;
187588
+ const boundary = previous[oldStart]?.start ?? previous.at(-1)?.end ?? emptyBoundary;
187589
+ if (positions2.resolve(boundary) === null) {
187590
+ return void 0;
187591
+ }
187592
+ batches.push({ from, to: index, boundary });
187593
+ }
187594
+ const retained = new Set(indices);
187595
+ const deletedRanges = previous.filter((_, index) => !retained.has(index)).map(range).filter((value) => value !== void 0).sort((a, b) => a.start - b.start);
187596
+ const deletions = [];
187597
+ for (const next of deletedRanges) {
187598
+ const last = deletions.at(-1);
187599
+ if (last && last.end === next.start) {
187600
+ last.end = next.end;
187601
+ } else {
187602
+ deletions.push(next);
187603
+ }
187604
+ }
187605
+ for (const deletion of deletions.reverse()) {
187606
+ text22.delete(deletion.start, deletion.end - deletion.start);
187607
+ }
187608
+ if (positions2.refresh?.() === false) {
187609
+ return void 0;
187610
+ }
187611
+ const inserted = /* @__PURE__ */ new Map();
187612
+ let precedingInsert;
187613
+ for (const batch of batches) {
187614
+ const boundary = positions2.resolve(batch.boundary);
187615
+ const minimum = precedingInsert ? positions2.resolve(precedingInsert.end) : 0;
187616
+ if (boundary === null || minimum === null) {
187617
+ return void 0;
187618
+ }
187619
+ const start = Math.max(boundary, minimum);
187620
+ let offset = start;
187621
+ for (let index = batch.from; index < batch.to; ) {
187622
+ let end = index + 1;
187623
+ while (end < batch.to && desired[end].attributes === desired[index].attributes && paragraphPatches.get(end) === paragraphPatches.get(index)) {
187624
+ end++;
187625
+ }
187626
+ text22.insert(
187627
+ offset,
187628
+ desired.slice(index, end).map((unit) => unit.text).join(""),
187629
+ textSessionInsertionAttributes(desired[index].attributes, paragraphPatches.get(index))
187630
+ );
187631
+ offset += end - index;
187632
+ index = end;
187633
+ }
187634
+ if (positions2.refresh?.() === false) {
187635
+ return void 0;
187636
+ }
187637
+ for (let index = batch.from; index < batch.to; index++) {
187638
+ const position2 = start + index - batch.from;
187639
+ inserted.set(index, {
187640
+ ...desired[index],
187641
+ start: positions2.capture(position2, 0),
187642
+ end: positions2.capture(position2 + 1, -1)
187643
+ });
187644
+ }
187645
+ precedingInsert = inserted.get(batch.to - 1);
187646
+ }
187647
+ const liveUnits = textSessionUnits(text22.toDelta());
187648
+ const formats = [];
187649
+ for (const [index, oldIndex] of indices.entries()) {
187650
+ if (oldIndex === null) {
187651
+ continue;
187652
+ }
187653
+ const unit = previous[oldIndex];
187654
+ const paragraph = paragraphPatches.get(index);
187655
+ if (!paragraph && textSessionAttributesEqual(unit.attributes, desired[index].attributes)) {
187656
+ continue;
187657
+ }
187658
+ const current = range(unit);
187659
+ if (!current) {
187660
+ continue;
187661
+ }
187662
+ const patch = {
187663
+ ...textSessionAttributePatch(
187664
+ unit.attributes,
187665
+ desired[index].attributes,
187666
+ liveUnits?.[current.start]?.attributes ?? {}
187667
+ ),
187668
+ ...paragraph
187669
+ };
187670
+ for (const key2 of Object.keys(patch)) {
187671
+ if (patch[key2] === (liveUnits?.[current.start]?.attributes[key2] ?? null)) {
187672
+ delete patch[key2];
187673
+ }
187674
+ }
187675
+ if (Object.keys(patch).length > 0) {
187676
+ const last = formats.at(-1);
187677
+ if (last && last.end === current.start && JSON.stringify(last.patch) === JSON.stringify(patch)) {
187678
+ last.end = current.end;
187679
+ } else {
187680
+ formats.push({ ...current, patch });
187681
+ }
187682
+ }
187683
+ }
187684
+ for (const format of formats) {
187685
+ text22.format(format.start, format.end - format.start, format.patch);
187686
+ }
187687
+ return indices.map((oldIndex, index) => ({
187688
+ ...oldIndex === null ? inserted.get(index) : previous[oldIndex],
187689
+ attributes: desired[index].attributes
187690
+ }));
187691
+ }
187692
+ function createCollaborationTextSession({
187693
+ text: text22,
187694
+ positions: positions2,
187695
+ transact,
187696
+ isCurrent
187697
+ }) {
187698
+ if (!isCurrent() || positions2.refresh?.() === false) {
187699
+ positions2.dispose?.();
187700
+ return void 0;
187701
+ }
187702
+ const observe = (delta) => textSessionUnits(delta)?.map((unit, index) => ({
187703
+ ...unit,
187704
+ start: positions2.capture(index, 0),
187705
+ end: positions2.capture(index + 1, -1)
187706
+ }));
187707
+ let baseline = observe(text22.toDelta());
187708
+ if (!baseline) {
187709
+ positions2.dispose?.();
187710
+ return void 0;
187711
+ }
187712
+ let emptyBoundary = positions2.capture(0, 0);
187713
+ let version = 0;
187714
+ let disposed = false;
187715
+ let snapshots2 = /* @__PURE__ */ new WeakMap();
187716
+ const dispose = () => {
187717
+ if (disposed) {
187718
+ return;
187719
+ }
187720
+ disposed = true;
187721
+ baseline = [];
187722
+ snapshots2 = /* @__PURE__ */ new WeakMap();
187723
+ positions2.dispose?.();
187724
+ };
187725
+ const active2 = () => {
187726
+ if (!disposed && (!isCurrent() || positions2.refresh?.() === false || !textSessionDeltaSupported(text22.toDelta()))) {
187727
+ dispose();
187728
+ }
187729
+ return !disposed;
187730
+ };
187731
+ return {
187732
+ bookmark(index, association) {
187733
+ if (!active2() || !Number.isInteger(index) || index < 0 || index > baseline.length) {
187734
+ return () => null;
187735
+ }
187736
+ const units = baseline;
187737
+ const position2 = association < 0 && index > 0 ? units[index - 1].end : units[index]?.start ?? units[index - 1]?.end ?? emptyBoundary;
187738
+ return () => active2() ? positions2.resolve(position2) : null;
187739
+ },
187740
+ applyLocalDelta(delta, edit) {
187741
+ if (!active2()) {
187742
+ return false;
187743
+ }
187744
+ const desired = textSessionUnits(delta);
187745
+ if (!desired) {
187746
+ return false;
187747
+ }
187748
+ const previous = baseline;
187749
+ const before = previous.map((unit) => unit.text).join("");
187750
+ const after = desired.map((unit) => unit.text).join("");
187751
+ const plan = textSessionPlan(before, after, edit);
187752
+ if (!plan) {
187753
+ return false;
187754
+ }
187755
+ const { retainedIndices: indices, paragraphSources } = plan;
187756
+ if (previous.length === desired.length && indices.every((retained, index) => retained === index) && (!paragraphSources || paragraphSources.every((source, index) => source === null || source === index)) && desired.every(
187757
+ (unit, index) => textSessionAttributesEqual(previous[index].attributes, unit.attributes)
187758
+ )) {
187759
+ return true;
187760
+ }
187761
+ let next;
187762
+ transact(() => {
187763
+ if (!active2()) {
187764
+ return;
187765
+ }
187766
+ next = applyTextSessionPlan(
187767
+ text22,
187768
+ positions2,
187769
+ previous,
187770
+ desired,
187771
+ indices,
187772
+ emptyBoundary,
187773
+ paragraphSources
187774
+ );
187775
+ });
187776
+ if (!next || !active2()) {
187777
+ return false;
187778
+ }
187779
+ baseline = next;
187780
+ version++;
187781
+ return true;
187782
+ },
187783
+ readMerged() {
187784
+ if (!active2()) {
187785
+ return void 0;
187786
+ }
187787
+ const delta = text22.toDelta();
187788
+ const units = observe(delta);
187789
+ if (!units) {
187790
+ dispose();
187791
+ return void 0;
187792
+ }
187793
+ const snapshot = { delta };
187794
+ snapshots2.set(snapshot, { units, boundary: positions2.capture(0, 0), version });
187795
+ return snapshot;
187796
+ },
187797
+ adoptMerged(snapshot) {
187798
+ const observed = snapshots2.get(snapshot);
187799
+ if (!active2() || !observed || observed.version !== version) {
187800
+ return false;
187801
+ }
187802
+ baseline = observed.units;
187803
+ emptyBoundary = observed.boundary;
187804
+ version++;
187805
+ return true;
187806
+ },
187807
+ dispose
187808
+ };
187809
+ }
187810
+ function createCollaborationTextTarget({
187811
+ doc,
187812
+ factories,
187813
+ slideId,
187814
+ elementId,
187815
+ isWritable,
187816
+ onChange,
187817
+ ownsModel
187818
+ }) {
187819
+ const element = findElementYMap(doc, slideId, elementId);
187820
+ if (element && factories.createTextPositions) {
187821
+ initializeCollaborationText(
187822
+ doc,
187823
+ element,
187824
+ factories,
187825
+ () => isWritable() && findElementYMap(doc, slideId, elementId) === element
187826
+ );
187827
+ }
187828
+ const text22 = element?.get("textBody");
187829
+ if (!element || !isYTextEditable(text22) || !factories.createTextPositions || !isWritable()) {
187830
+ return void 0;
187831
+ }
187832
+ const positions2 = factories.createTextPositions(text22);
187833
+ let disposed = false;
187834
+ let applying = false;
187835
+ const isCurrent = () => !disposed && isWritable() && findElementYMap(doc, slideId, elementId) === element && element.get("textBody") === text22;
187836
+ const session = createCollaborationTextSession({
187837
+ text: text22,
187838
+ positions: positions2,
187839
+ isCurrent,
187840
+ transact: (callback) => doc.transact(() => {
187841
+ callback();
187842
+ if (isCurrent()) {
187843
+ const segments = decodeDelta(text22.toDelta());
187844
+ const value = inlineListBodyText(segments);
187845
+ if (element.get("text") !== value) {
187846
+ element.set("text", value);
187847
+ }
187848
+ }
187849
+ }, LOCAL_SYNC_ORIGIN)
187850
+ });
187851
+ if (!session) {
187852
+ return void 0;
187853
+ }
187854
+ const slides = doc.getArray(YDOC_SLIDES_KEY);
187855
+ let previous = JSON.stringify(text22.toDelta());
187856
+ const changed = () => {
187857
+ if (disposed || applying) {
187858
+ return;
187859
+ }
187860
+ const next = isCurrent() ? JSON.stringify(text22.toDelta()) : void 0;
187861
+ if (next !== previous) {
187862
+ previous = next ?? "";
187863
+ onChange?.();
187864
+ }
187865
+ };
187866
+ slides.observeDeep(changed);
187867
+ const releaseLease = ownsModel ? registerCollaborationTextLease(element, ownsModel) : () => {
187868
+ };
187869
+ const readMerged = () => {
187870
+ const snapshot = session.readMerged();
187871
+ if (!snapshot) {
187872
+ return void 0;
187873
+ }
187874
+ const segments = decodeDelta([...snapshot.delta]);
187875
+ return Object.assign(snapshot, {
187876
+ inline: { elementId, text: inlineListBodyText(segments), textSegments: segments }
187877
+ });
187878
+ };
187879
+ return {
187880
+ readMerged,
187881
+ adoptMerged: session.adoptMerged,
187882
+ applyLocalDelta(delta, edit) {
187883
+ if (!isCurrent()) {
187884
+ return false;
187885
+ }
187886
+ applying = true;
187887
+ try {
187888
+ return session.applyLocalDelta(delta, edit);
187889
+ } finally {
187890
+ applying = false;
187891
+ changed();
187892
+ }
187893
+ },
187894
+ bookmark: session.bookmark,
187895
+ dispose() {
187896
+ if (!disposed) {
187897
+ disposed = true;
187898
+ releaseLease();
187899
+ slides.unobserveDeep(changed);
187900
+ session.dispose();
187901
+ onChange?.();
187902
+ }
187903
+ }
187904
+ };
187905
+ }
186969
187906
  var LIVE_PATCH_THROTTLE_MS = 50;
186970
187907
  function createCollaborationLivePatcher(options = {}) {
186971
187908
  const throttleMs = options.throttleMs ?? LIVE_PATCH_THROTTLE_MS;
@@ -186975,6 +187912,17 @@ function createCollaborationLivePatcher(options = {}) {
186975
187912
  let timer = null;
186976
187913
  let lastWriteAt = Number.NEGATIVE_INFINITY;
186977
187914
  let immediate = false;
187915
+ const textSessions = /* @__PURE__ */ new Map();
187916
+ const textOwners = /* @__PURE__ */ new Map();
187917
+ const keyFor3 = (slideId, elementId) => `${slideId ?? ""}\0${elementId}`;
187918
+ const retireTextSessions = () => {
187919
+ const retiring = [...textSessions.values()];
187920
+ textSessions.clear();
187921
+ textOwners.clear();
187922
+ for (const session of retiring) {
187923
+ session.dispose();
187924
+ }
187925
+ };
186978
187926
  const cancelTimer = () => {
186979
187927
  if (timer !== null) {
186980
187928
  clearTimeout(timer);
@@ -187022,7 +187970,7 @@ function createCollaborationLivePatcher(options = {}) {
187022
187970
  if (!doc || !factories || !elementId) {
187023
187971
  return null;
187024
187972
  }
187025
- const key2 = `${slideId ?? ""}\0${elementId}`;
187973
+ const key2 = keyFor3(slideId, elementId);
187026
187974
  let entry2 = pending.get(key2);
187027
187975
  if (!entry2) {
187028
187976
  entry2 = { slideId, elementId };
@@ -187031,6 +187979,53 @@ function createCollaborationLivePatcher(options = {}) {
187031
187979
  return entry2;
187032
187980
  };
187033
187981
  return {
187982
+ beginTextEdit(slideId, elementId, onChange, ownsModel) {
187983
+ if (!doc || !factories) {
187984
+ return void 0;
187985
+ }
187986
+ const activeDoc = doc;
187987
+ const activeFactories = factories;
187988
+ const key2 = keyFor3(slideId, elementId);
187989
+ const owner = {};
187990
+ textOwners.set(key2, owner);
187991
+ const isWritable = () => doc === activeDoc && factories === activeFactories && textOwners.get(key2) === owner;
187992
+ textSessions.get(key2)?.dispose();
187993
+ if (!isWritable()) {
187994
+ return void 0;
187995
+ }
187996
+ const queued = pending.get(key2);
187997
+ if (queued) {
187998
+ delete queued.text;
187999
+ }
188000
+ const target = createCollaborationTextTarget({
188001
+ doc,
188002
+ factories,
188003
+ slideId,
188004
+ elementId,
188005
+ onChange,
188006
+ ownsModel,
188007
+ isWritable
188008
+ });
188009
+ if (!target || textOwners.get(key2) !== owner) {
188010
+ target?.dispose();
188011
+ if (textOwners.get(key2) === owner) {
188012
+ textOwners.delete(key2);
188013
+ }
188014
+ return void 0;
188015
+ }
188016
+ const dispose = target.dispose;
188017
+ target.dispose = () => {
188018
+ dispose();
188019
+ if (textSessions.get(key2) === target) {
188020
+ textSessions.delete(key2);
188021
+ }
188022
+ if (textOwners.get(key2) === owner) {
188023
+ textOwners.delete(key2);
188024
+ }
188025
+ };
188026
+ textSessions.set(key2, target);
188027
+ return target;
188028
+ },
187034
188029
  configure(nextDoc, nextFactories, nextImmediate = false) {
187035
188030
  if (nextDoc === doc && nextFactories === factories && nextImmediate === immediate) {
187036
188031
  return;
@@ -187041,6 +188036,7 @@ function createCollaborationLivePatcher(options = {}) {
187041
188036
  factories = nextFactories;
187042
188037
  immediate = nextImmediate;
187043
188038
  lastWriteAt = Number.NEGATIVE_INFINITY;
188039
+ retireTextSessions();
187044
188040
  },
187045
188041
  isActive() {
187046
188042
  return doc !== null && factories !== null;
@@ -187054,6 +188050,9 @@ function createCollaborationLivePatcher(options = {}) {
187054
188050
  schedule();
187055
188051
  },
187056
188052
  patchText(slideId, elementId, text22, source) {
188053
+ if (textOwners.has(keyFor3(slideId, elementId))) {
188054
+ return;
188055
+ }
187057
188056
  const entry2 = enqueue(slideId, elementId);
187058
188057
  if (!entry2) {
187059
188058
  return;
@@ -187070,6 +188069,7 @@ function createCollaborationLivePatcher(options = {}) {
187070
188069
  pending.clear();
187071
188070
  doc = null;
187072
188071
  factories = null;
188072
+ retireTextSessions();
187073
188073
  }
187074
188074
  };
187075
188075
  }
@@ -187092,6 +188092,731 @@ function publishLiveGeometry(patcher, slideId, elementId, geometry) {
187092
188092
  }
187093
188093
  patcher.patchGeometry(slideId, elementId, geometry);
187094
188094
  }
188095
+ function normalizedRuns(delta) {
188096
+ const runs = [];
188097
+ for (const op2 of delta) {
188098
+ if (typeof op2.insert !== "string") {
188099
+ return void 0;
188100
+ }
188101
+ const entries = Object.entries(op2.attributes ?? {});
188102
+ if (entries.some(([, value]) => typeof value !== "string")) {
188103
+ return void 0;
188104
+ }
188105
+ if (!op2.insert) {
188106
+ continue;
188107
+ }
188108
+ const attributes = JSON.stringify(entries.sort(([a], [b]) => a.localeCompare(b)));
188109
+ const previous = runs[runs.length - 1];
188110
+ if (previous?.attributes === attributes) {
188111
+ previous.text += op2.insert;
188112
+ } else {
188113
+ runs.push({ text: op2.insert, attributes });
188114
+ }
188115
+ }
188116
+ return runs;
188117
+ }
188118
+ function validBoundary(text22, offset) {
188119
+ return Number.isInteger(offset) && offset >= 0 && offset <= text22.length && !(text22.charCodeAt(offset - 1) >= 55296 && text22.charCodeAt(offset - 1) <= 56319 && text22.charCodeAt(offset) >= 56320 && text22.charCodeAt(offset) <= 57343);
188120
+ }
188121
+ function createCollaborationTextProjection(segments, delta, body) {
188122
+ if (inlineListBodyText(segments) !== body) {
188123
+ return void 0;
188124
+ }
188125
+ const expected = normalizedRuns(encodeSegmentsToDelta([...segments]));
188126
+ const actual = normalizedRuns(delta);
188127
+ if (!expected || !actual || expected.length !== actual.length || expected.some(
188128
+ (run, index) => run.text !== actual[index].text || run.attributes !== actual[index].attributes
188129
+ )) {
188130
+ return void 0;
188131
+ }
188132
+ const encoded = actual.map((run) => run.text).join("");
188133
+ const spans = [];
188134
+ let bodyStart = 0;
188135
+ let encodedStart = 0;
188136
+ let first = true;
188137
+ for (const [segmentIndex, segment] of segments.entries()) {
188138
+ const paragraphBreak = isParagraphSeparatorSegment(segment);
188139
+ const marker = !paragraphBreak && first && isBulletMarkerSegment(segment);
188140
+ const kind = paragraphBreak ? "paragraph-break" : segment.isLineBreak ? "line-break" : marker ? "bullet-marker" : segment.text.length === 0 ? "empty-carrier" : "text";
188141
+ const bodyLength = paragraphBreak || segment.isLineBreak ? 1 : marker ? 0 : segment.text.length;
188142
+ const encodedLength = segment.isParagraphBreak || segment.isLineBreak ? 1 : Math.max(1, segment.text.length);
188143
+ spans.push({
188144
+ segmentIndex,
188145
+ bodyStart,
188146
+ bodyEnd: bodyStart + bodyLength,
188147
+ encodedStart,
188148
+ encodedEnd: encodedStart + encodedLength,
188149
+ kind
188150
+ });
188151
+ bodyStart += bodyLength;
188152
+ encodedStart += encodedLength;
188153
+ first = paragraphBreak;
188154
+ }
188155
+ return {
188156
+ spans,
188157
+ bodyOffsetToEncoded(offset) {
188158
+ if (!validBoundary(body, offset)) {
188159
+ return void 0;
188160
+ }
188161
+ let start = encoded.length;
188162
+ let end = 0;
188163
+ for (const span of spans) {
188164
+ if (offset < span.bodyStart || offset > span.bodyEnd) {
188165
+ continue;
188166
+ }
188167
+ const point = span.encodedStart + offset - span.bodyStart;
188168
+ start = Math.min(start, point);
188169
+ end = Math.max(end, span.bodyStart === span.bodyEnd ? span.encodedEnd : point);
188170
+ }
188171
+ return { start, end };
188172
+ },
188173
+ encodedOffsetToBody(offset) {
188174
+ if (!validBoundary(encoded, offset)) {
188175
+ return void 0;
188176
+ }
188177
+ for (const span of spans) {
188178
+ if (offset >= span.encodedStart && offset <= span.encodedEnd) {
188179
+ const point = span.bodyStart === span.bodyEnd ? span.bodyStart : span.bodyStart + offset - span.encodedStart;
188180
+ return validBoundary(body, point) ? point : void 0;
188181
+ }
188182
+ }
188183
+ return 0;
188184
+ }
188185
+ };
188186
+ }
188187
+ var initialized = /* @__PURE__ */ new WeakSet();
188188
+ function initializeInlineListDom(root, seed) {
188189
+ const session = inlineListSession(seed);
188190
+ if (!session || initialized.has(root) || root.childNodes.length > 0 || session.boundParagraphs.size > 0) {
188191
+ return false;
188192
+ }
188193
+ const textStyle = "textStyle" in session.element ? session.element.textStyle : void 0;
188194
+ const fontScale = resolveAutoFitFontScale(textStyle);
188195
+ for (const paragraph of seed.paragraphs) {
188196
+ const block = root.ownerDocument.createElement("div");
188197
+ block.dataset.pptxListParagraph = paragraph.token;
188198
+ for (const run of paragraph.runs) {
188199
+ const span = root.ownerDocument.createElement("span");
188200
+ span.dataset.pptxListRun = run.token;
188201
+ const source = session.segments[run.segmentIndex];
188202
+ const projected = {
188203
+ ...source,
188204
+ style: withInlineListDecorationDefaults(source.style, textStyle)
188205
+ };
188206
+ const style = segmentStyleToCss(projected, fontScale);
188207
+ applyUnderlineVariant(style, projected);
188208
+ for (const [key2, value] of Object.entries(style)) {
188209
+ span.style.setProperty(
188210
+ key2.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`),
188211
+ String(value)
188212
+ );
188213
+ }
188214
+ if (run.text === "" || run.isLineBreak) {
188215
+ span.append(root.ownerDocument.createElement("br"));
188216
+ } else {
188217
+ for (const [index, line4] of run.text.split("\n").entries()) {
188218
+ if (index > 0) {
188219
+ span.append(root.ownerDocument.createElement("br"));
188220
+ }
188221
+ span.append(root.ownerDocument.createTextNode(line4));
188222
+ }
188223
+ }
188224
+ block.append(span);
188225
+ bindInlineListRun(seed, span, run.segmentIndex);
188226
+ }
188227
+ root.append(block);
188228
+ bindInlineListParagraph(seed, block, paragraph.sourceIndex);
188229
+ }
188230
+ initialized.add(root);
188231
+ return true;
188232
+ }
188233
+ function collaborationInlineModelKey(element) {
188234
+ return JSON.stringify(
188235
+ element && {
188236
+ id: element.id,
188237
+ type: element.type,
188238
+ ..."text" in element ? { text: element.text } : {},
188239
+ ..."textSegments" in element ? { textSegments: element.textSegments } : {},
188240
+ ..."textStyle" in element ? { textStyle: element.textStyle } : {}
188241
+ }
188242
+ );
188243
+ }
188244
+ function prepareCollaborationInlineDom(root, element, snapshot) {
188245
+ const seed = createInlineListSeed({ ...element, ...snapshot }, {
188246
+ includePlain: true
188247
+ });
188248
+ if (!seed) {
188249
+ return void 0;
188250
+ }
188251
+ const detached = root.ownerDocument.createElement("div");
188252
+ return initializeInlineListDom(detached, seed) ? { seed, children: Array.from(detached.childNodes) } : void 0;
188253
+ }
188254
+ function bookmarkCollaborationInlineSelection(root, seed, snapshot, target) {
188255
+ const selected = readInlineListSelection(seed, root);
188256
+ const selection = root.ownerDocument.getSelection();
188257
+ const range = selection?.rangeCount ? selection.getRangeAt(0) : void 0;
188258
+ const backward = Boolean(
188259
+ range && !range.collapsed && selection?.anchorNode === range.endContainer && selection.anchorOffset === range.endOffset
188260
+ );
188261
+ const segments = snapshot.textSegments ?? [];
188262
+ const projection = createCollaborationTextProjection(
188263
+ segments,
188264
+ encodeSegmentsToDelta(segments),
188265
+ snapshot.text
188266
+ );
188267
+ if (selected.kind !== "supported" || !selected.bodyRange || !projection) {
188268
+ return void 0;
188269
+ }
188270
+ const { start, end } = selected.bodyRange;
188271
+ const first = projection.bodyOffsetToEncoded(start);
188272
+ const last = projection.bodyOffsetToEncoded(end);
188273
+ if (!first || !last) {
188274
+ return void 0;
188275
+ }
188276
+ const from = target.bookmark(first.end, 0);
188277
+ const to = start === end ? from : target.bookmark(last.start, -1);
188278
+ return (nextSeed, next) => {
188279
+ const nextSegments = next.textSegments ?? [];
188280
+ const nextProjection = createCollaborationTextProjection(
188281
+ nextSegments,
188282
+ encodeSegmentsToDelta(nextSegments),
188283
+ next.text
188284
+ );
188285
+ const encodedStart = from();
188286
+ const encodedEnd = to();
188287
+ const bodyStart = encodedStart === null ? void 0 : nextProjection?.encodedOffsetToBody(encodedStart);
188288
+ const bodyEnd = encodedEnd === null ? void 0 : nextProjection?.encodedOffsetToBody(encodedEnd);
188289
+ if (bodyStart !== void 0 && bodyEnd !== void 0) {
188290
+ restoreInlineListBodySelection(nextSeed, root, {
188291
+ start: Math.min(bodyStart, bodyEnd),
188292
+ end: Math.max(bodyStart, bodyEnd)
188293
+ });
188294
+ if (backward && selection?.rangeCount) {
188295
+ const restored = selection.getRangeAt(0);
188296
+ selection.setBaseAndExtent(
188297
+ restored.endContainer,
188298
+ restored.endOffset,
188299
+ restored.startContainer,
188300
+ restored.startOffset
188301
+ );
188302
+ }
188303
+ }
188304
+ };
188305
+ }
188306
+ function resolveCollaborationNativeRange(range, previous, current) {
188307
+ if (!range?.deleteDirection) {
188308
+ return range;
188309
+ }
188310
+ const removed = previous.length - current.length;
188311
+ if (removed <= 0) {
188312
+ return void 0;
188313
+ }
188314
+ const from = range.deleteDirection === "backward" ? range.from - removed : range.from;
188315
+ const to = range.deleteDirection === "forward" ? range.to + removed : range.to;
188316
+ return from >= 0 && to <= previous.length ? { from, to } : void 0;
188317
+ }
188318
+ function observeCollaborationInlineInput(root, getSeed, apply, settled) {
188319
+ let disposed = false;
188320
+ let composing = false;
188321
+ let pending = false;
188322
+ let range;
188323
+ const capture = (event) => {
188324
+ const target = event?.getTargetRanges?.()[0];
188325
+ const read = target ? readInlineListRange(getSeed(), root, target) : readInlineListSelection(getSeed(), root);
188326
+ range = read.kind === "supported" && read.bodyRange ? { from: read.bodyRange.start, to: read.bodyRange.end } : void 0;
188327
+ if (!target && range && range.from === range.to && event?.inputType?.startsWith("delete")) {
188328
+ if (event.inputType.endsWith("Backward")) {
188329
+ range.deleteDirection = "backward";
188330
+ } else if (event.inputType.endsWith("Forward")) {
188331
+ range.deleteDirection = "forward";
188332
+ }
188333
+ }
188334
+ };
188335
+ const before = (event) => {
188336
+ if (!composing) {
188337
+ capture(event);
188338
+ }
188339
+ pending = true;
188340
+ queueMicrotask(() => {
188341
+ if (!disposed && !composing && pending) {
188342
+ pending = false;
188343
+ settled();
188344
+ }
188345
+ });
188346
+ };
188347
+ const input = () => {
188348
+ if (composing || disposed) {
188349
+ return;
188350
+ }
188351
+ pending = false;
188352
+ const replacement = range;
188353
+ range = void 0;
188354
+ apply(replacement);
188355
+ };
188356
+ const start = () => {
188357
+ if (!composing) {
188358
+ capture();
188359
+ }
188360
+ composing = true;
188361
+ };
188362
+ const end = () => {
188363
+ queueMicrotask(() => {
188364
+ if (disposed) {
188365
+ return;
188366
+ }
188367
+ composing = false;
188368
+ input();
188369
+ });
188370
+ };
188371
+ root.addEventListener("beforeinput", before, true);
188372
+ root.addEventListener("paste", before, true);
188373
+ root.addEventListener("input", input, true);
188374
+ root.addEventListener("compositionstart", start, true);
188375
+ root.addEventListener("compositionend", end, true);
188376
+ return {
188377
+ blocked: () => composing || pending,
188378
+ reason: () => composing ? "composition-active" : pending ? "input-active" : void 0,
188379
+ dispose() {
188380
+ disposed = true;
188381
+ root.removeEventListener("beforeinput", before, true);
188382
+ root.removeEventListener("paste", before, true);
188383
+ root.removeEventListener("input", input, true);
188384
+ root.removeEventListener("compositionstart", start, true);
188385
+ root.removeEventListener("compositionend", end, true);
188386
+ }
188387
+ };
188388
+ }
188389
+ function paragraphCarriers(projection) {
188390
+ const carriers = [void 0];
188391
+ for (const span of projection.spans) {
188392
+ carriers[carriers.length - 1] ??= span;
188393
+ if (span.kind === "paragraph-break") {
188394
+ carriers.push(void 0);
188395
+ }
188396
+ }
188397
+ return carriers;
188398
+ }
188399
+ function bodyUnits(projection) {
188400
+ const indices = [];
188401
+ for (const span of projection.spans) {
188402
+ for (let body = span.bodyStart; body < span.bodyEnd; body++) {
188403
+ indices[body] = span.encodedStart + body - span.bodyStart;
188404
+ }
188405
+ }
188406
+ return indices;
188407
+ }
188408
+ function createNativeCollaborationTextEdit(before, after, replacement) {
188409
+ const range = textSessionReplacementSpan(before.body, after.body, replacement);
188410
+ const delta = encodeSegmentsToDelta([...after.segments]);
188411
+ const oldProjection = createCollaborationTextProjection(
188412
+ before.segments,
188413
+ before.delta,
188414
+ before.body
188415
+ );
188416
+ const nextProjection = createCollaborationTextProjection(after.segments, delta, after.body);
188417
+ if (!range || !oldProjection || !nextProjection) {
188418
+ return void 0;
188419
+ }
188420
+ const oldCarriers = new Map(
188421
+ paragraphCarriers(oldProjection).flatMap(
188422
+ (span) => span ? [[span.segmentIndex, span]] : []
188423
+ )
188424
+ );
188425
+ const nextCarriers = paragraphCarriers(nextProjection);
188426
+ if (after.paragraphSources.length !== nextCarriers.length || Array.from(after.paragraphSources).some(
188427
+ (source) => source !== null && (!Number.isInteger(source) || !oldCarriers.has(source))
188428
+ )) {
188429
+ return void 0;
188430
+ }
188431
+ const oldText = before.delta.map((op2) => op2.insert).join("");
188432
+ const nextText = delta.map((op2) => op2.insert).join("");
188433
+ const oldBody = bodyUnits(oldProjection);
188434
+ const nextBody = bodyUnits(nextProjection);
188435
+ const retainedIndices = Array(nextText.length).fill(null);
188436
+ const paragraphSources = Array(nextText.length).fill(null);
188437
+ const afterEnd = after.body.length - range.suffix;
188438
+ for (const [bodyIndex, encodedIndex] of nextBody.entries()) {
188439
+ const previous = bodyIndex < range.prefix ? bodyIndex : bodyIndex >= afterEnd ? before.body.length - (after.body.length - bodyIndex) : void 0;
188440
+ if (previous !== void 0) {
188441
+ retainedIndices[encodedIndex] = oldBody[previous];
188442
+ }
188443
+ }
188444
+ for (const [paragraph, carrier] of nextCarriers.entries()) {
188445
+ const source = after.paragraphSources[paragraph];
188446
+ const oldCarrier = source === null ? void 0 : oldCarriers.get(source);
188447
+ if (!carrier || !oldCarrier) {
188448
+ continue;
188449
+ }
188450
+ paragraphSources.fill(oldCarrier.encodedStart, carrier.encodedStart, carrier.encodedEnd);
188451
+ }
188452
+ const hidden = nextProjection.spans.filter((span) => span.bodyStart === span.bodyEnd);
188453
+ if (after.hiddenSources.length !== hidden.length) {
188454
+ return void 0;
188455
+ }
188456
+ for (const [index, carrier] of hidden.entries()) {
188457
+ const source = after.hiddenSources[index];
188458
+ if (source === null) {
188459
+ continue;
188460
+ }
188461
+ const oldCarrier = oldProjection.spans[source];
188462
+ if (!Number.isInteger(source) || !oldCarrier || oldCarrier.bodyStart !== oldCarrier.bodyEnd || oldCarrier.kind !== carrier.kind || oldText.slice(oldCarrier.encodedStart, oldCarrier.encodedEnd) !== nextText.slice(carrier.encodedStart, carrier.encodedEnd)) {
188463
+ return void 0;
188464
+ }
188465
+ for (let unit = carrier.encodedStart; unit < carrier.encodedEnd; unit++) {
188466
+ retainedIndices[unit] = oldCarrier.encodedStart + unit - carrier.encodedStart;
188467
+ }
188468
+ }
188469
+ const correspondence = { retainedIndices, paragraphSources };
188470
+ return textSessionRetainedIndices(oldText, nextText, correspondence) ? { delta, correspondence } : void 0;
188471
+ }
188472
+ function attachCollaborationInlineEditor(root, element, options) {
188473
+ let disposed = false;
188474
+ let busy = false;
188475
+ let model = element;
188476
+ let modelKey = collaborationInlineModelKey(element);
188477
+ let previous;
188478
+ let painted;
188479
+ let controller;
188480
+ let events = void 0;
188481
+ let target = void 0;
188482
+ target = options.patcher.beginTextEdit?.(options.slideId, element.id, synchronize, checkModel);
188483
+ if (!target) {
188484
+ return void 0;
188485
+ }
188486
+ const initial = target.readMerged();
188487
+ if (!initial || !paint(initial)) {
188488
+ controller?.dispose();
188489
+ target.dispose();
188490
+ return void 0;
188491
+ }
188492
+ events = observeCollaborationInlineInput(root, () => painted.seed, applyInput, synchronize);
188493
+ return {
188494
+ read,
188495
+ readAccepted: () => !disposed ? target?.readMerged()?.inline : void 0,
188496
+ checkModel,
188497
+ mutate(range, apply) {
188498
+ if (disposed || busy || events?.blocked() || !painted) {
188499
+ return false;
188500
+ }
188501
+ const selected = readInlineListRange(painted.seed, root, range);
188502
+ if (selected.kind !== "supported" || !selected.bodyRange) {
188503
+ return false;
188504
+ }
188505
+ try {
188506
+ apply();
188507
+ } catch {
188508
+ cancel();
188509
+ return false;
188510
+ }
188511
+ applyInput({ from: selected.bodyRange.start, to: selected.bodyRange.end });
188512
+ return !disposed;
188513
+ },
188514
+ format(snapshot) {
188515
+ if (disposed || events?.blocked()) {
188516
+ return read();
188517
+ }
188518
+ const result = controller?.format(snapshot);
188519
+ return result?.kind === "unsupported" ? result : read();
188520
+ },
188521
+ readSelection: (selection) => controller?.readSelection(selection) ?? { kind: "unsupported", reason: "inactive-session" },
188522
+ refresh() {
188523
+ synchronize();
188524
+ return read();
188525
+ },
188526
+ dispose
188527
+ };
188528
+ function dispose() {
188529
+ if (disposed) {
188530
+ return;
188531
+ }
188532
+ disposed = true;
188533
+ events?.dispose();
188534
+ controller?.dispose();
188535
+ target.dispose();
188536
+ }
188537
+ function cancel() {
188538
+ if (!disposed) {
188539
+ dispose();
188540
+ options.onCancel?.();
188541
+ }
188542
+ }
188543
+ function read() {
188544
+ const reason = events?.reason();
188545
+ if (reason && !disposed) {
188546
+ return { kind: "unsupported", reason, text: previous?.text ?? "" };
188547
+ }
188548
+ const merged = !disposed && target.readMerged();
188549
+ return merged ? {
188550
+ kind: "supported",
188551
+ snapshot: merged.inline,
188552
+ paragraphs: buildParagraphs(model, void 0, merged.inline.textSegments, {
188553
+ preserveTrailingEmpty: true
188554
+ })
188555
+ } : { kind: "unsupported", reason: "inactive-session", text: "" };
188556
+ }
188557
+ function checkModel(candidate) {
188558
+ if (disposed || !candidate || candidate.id !== element.id) {
188559
+ cancel();
188560
+ return false;
188561
+ }
188562
+ const key2 = collaborationInlineModelKey(candidate);
188563
+ if (key2 === modelKey) {
188564
+ return true;
188565
+ }
188566
+ const merged = target.readMerged();
188567
+ if (merged && collaborationInlineModelKey({ ...model, ...merged.inline }) === key2) {
188568
+ model = candidate;
188569
+ modelKey = key2;
188570
+ return true;
188571
+ }
188572
+ cancel();
188573
+ return false;
188574
+ }
188575
+ function paint(merged) {
188576
+ if (!createCollaborationTextProjection(
188577
+ merged.inline.textSegments ?? [],
188578
+ merged.delta,
188579
+ merged.inline.text
188580
+ )) {
188581
+ return false;
188582
+ }
188583
+ const prepared = prepareCollaborationInlineDom(root, model, merged.inline);
188584
+ if (!prepared) {
188585
+ return false;
188586
+ }
188587
+ const restore = painted && previous ? bookmarkCollaborationInlineSelection(root, painted.seed, previous, target) : void 0;
188588
+ controller?.dispose();
188589
+ root.replaceChildren(...prepared.children);
188590
+ painted = prepared;
188591
+ controller = attachInlineListController(root, prepared.seed, {
188592
+ isCurrent: () => !disposed,
188593
+ onFormat: () => applyInput({ from: 0, to: 0 })
188594
+ });
188595
+ const captured = readInlineListNativeSnapshot(prepared.seed, root);
188596
+ if (captured.kind !== "supported" || !createCollaborationTextProjection(
188597
+ captured.snapshot.textSegments ?? [],
188598
+ merged.delta,
188599
+ captured.snapshot.text
188600
+ ) || !target.adoptMerged(merged)) {
188601
+ return false;
188602
+ }
188603
+ previous = captured.snapshot;
188604
+ restore?.(prepared.seed, previous);
188605
+ return true;
188606
+ }
188607
+ function synchronize() {
188608
+ if (!target || disposed || busy) {
188609
+ return;
188610
+ }
188611
+ const merged = target.readMerged();
188612
+ if (!merged || !previous || !painted) {
188613
+ cancel();
188614
+ return;
188615
+ }
188616
+ if (events?.blocked()) {
188617
+ return;
188618
+ }
188619
+ const matching = createCollaborationTextProjection(
188620
+ previous.textSegments ?? [],
188621
+ merged.delta,
188622
+ previous.text
188623
+ );
188624
+ if (matching ? !target.adoptMerged(merged) : !paint(merged)) {
188625
+ cancel();
188626
+ return;
188627
+ }
188628
+ options.onSnapshot?.(merged.inline);
188629
+ }
188630
+ function applyInput(range) {
188631
+ if (disposed || busy || !previous || !painted) {
188632
+ return;
188633
+ }
188634
+ const next = readInlineListNativeSnapshot(painted.seed, root, previous);
188635
+ if (next.kind !== "supported") {
188636
+ cancel();
188637
+ return;
188638
+ }
188639
+ const beforeDelta = encodeSegmentsToDelta(previous.textSegments ?? []);
188640
+ if (JSON.stringify(beforeDelta) === JSON.stringify(encodeSegmentsToDelta(next.snapshot.textSegments ?? []))) {
188641
+ synchronize();
188642
+ return;
188643
+ }
188644
+ const replacement = resolveCollaborationNativeRange(range, previous.text, next.snapshot.text);
188645
+ const edit = replacement && createNativeCollaborationTextEdit(
188646
+ { segments: previous.textSegments ?? [], body: previous.text, delta: beforeDelta },
188647
+ {
188648
+ segments: next.snapshot.textSegments ?? [],
188649
+ body: next.snapshot.text,
188650
+ paragraphSources: next.paragraphSources,
188651
+ hiddenSources: next.hiddenSources
188652
+ },
188653
+ replacement
188654
+ );
188655
+ if (!edit) {
188656
+ cancel();
188657
+ return;
188658
+ }
188659
+ busy = true;
188660
+ let applied = false;
188661
+ try {
188662
+ applied = target.applyLocalDelta(edit.delta, edit.correspondence);
188663
+ } finally {
188664
+ busy = false;
188665
+ }
188666
+ if (!applied) {
188667
+ cancel();
188668
+ return;
188669
+ }
188670
+ previous = next.snapshot;
188671
+ synchronize();
188672
+ }
188673
+ }
188674
+ function createTextPositionTracker(length) {
188675
+ const start = { index: 0 };
188676
+ const end = { index: length };
188677
+ let cells2 = Array.from({ length }, (_, index) => ({ index }));
188678
+ let disposed = false;
188679
+ const dispose = () => {
188680
+ disposed = true;
188681
+ cells2 = [];
188682
+ };
188683
+ const neighbour = (cell, direction) => {
188684
+ const path = [];
188685
+ while (cell.index < 0) {
188686
+ path.push(cell);
188687
+ cell = cell[direction];
188688
+ }
188689
+ for (const removed of path) {
188690
+ removed[direction] = cell;
188691
+ }
188692
+ return cell;
188693
+ };
188694
+ return {
188695
+ capture(index, association) {
188696
+ if (disposed || !Number.isInteger(index) || index < 0 || index > cells2.length) {
188697
+ throw new RangeError("Cannot capture a position outside the current text");
188698
+ }
188699
+ return {
188700
+ cell: association < 0 ? cells2[index - 1] ?? start : cells2[index] ?? end,
188701
+ association
188702
+ };
188703
+ },
188704
+ resolve(position2) {
188705
+ if (disposed) {
188706
+ return null;
188707
+ }
188708
+ const cell = neighbour(position2.cell, position2.association < 0 ? "left" : "right");
188709
+ return cell === start || cell === end ? cell.index : cell.index + (position2.association < 0 ? 1 : 0);
188710
+ },
188711
+ apply(changes) {
188712
+ if (disposed) {
188713
+ return false;
188714
+ }
188715
+ let oldIndex = 0;
188716
+ const next = [];
188717
+ const removed = [];
188718
+ for (const change of changes) {
188719
+ if ([change.retain, change.delete, change.insert].filter((value) => value !== void 0).length !== 1) {
188720
+ dispose();
188721
+ return false;
188722
+ }
188723
+ if (change.insert !== void 0) {
188724
+ for (let index = 0; index < change.insert.length; index++) {
188725
+ next.push({ index: next.length });
188726
+ }
188727
+ continue;
188728
+ }
188729
+ const count = change.retain ?? change.delete;
188730
+ if (!Number.isInteger(count) || count < 0 || oldIndex + count > cells2.length) {
188731
+ dispose();
188732
+ return false;
188733
+ }
188734
+ for (let index = 0; index < count; index++) {
188735
+ const cell = cells2[oldIndex++];
188736
+ if (change.retain !== void 0) {
188737
+ next.push(cell);
188738
+ } else {
188739
+ removed.push({ cell, left: next.at(-1) ?? start, rightIndex: next.length });
188740
+ }
188741
+ }
188742
+ }
188743
+ while (oldIndex < cells2.length) {
188744
+ next.push(cells2[oldIndex++]);
188745
+ }
188746
+ for (const { cell, left, rightIndex } of removed) {
188747
+ cell.index = -1;
188748
+ cell.left = left;
188749
+ cell.right = next[rightIndex] ?? end;
188750
+ }
188751
+ next.forEach((cell, index) => {
188752
+ cell.index = index;
188753
+ });
188754
+ cells2 = next;
188755
+ end.index = cells2.length;
188756
+ return true;
188757
+ },
188758
+ dispose
188759
+ };
188760
+ }
188761
+ function createSnapshotTextPositions(text22, snapshots2) {
188762
+ const tracker = createTextPositionTracker(text22.toString().length);
188763
+ let previous = snapshots2.read();
188764
+ let busy = false;
188765
+ let disposed = false;
188766
+ let unsubscribe = () => {
188767
+ };
188768
+ const marker = /* @__PURE__ */ Symbol("text-identity-change");
188769
+ const dispose = () => {
188770
+ if (!disposed) {
188771
+ disposed = true;
188772
+ unsubscribe();
188773
+ tracker.dispose();
188774
+ }
188775
+ };
188776
+ const refresh = () => {
188777
+ if (disposed || busy) {
188778
+ return false;
188779
+ }
188780
+ busy = true;
188781
+ try {
188782
+ const current = snapshots2.read();
188783
+ if (snapshots2.equal(current, previous)) {
188784
+ return true;
188785
+ }
188786
+ const delta = text22.toDelta(current, previous, (type) => ({ type, marker }));
188787
+ const changes = [];
188788
+ for (const op2 of delta) {
188789
+ if (typeof op2.insert !== "string") {
188790
+ dispose();
188791
+ return false;
188792
+ }
188793
+ const change = op2.attributes?.ychange;
188794
+ const marked = typeof change === "object" && change !== null && "marker" in change && change.marker === marker && "type" in change;
188795
+ changes.push(
188796
+ !marked ? { retain: op2.insert.length } : change.type === "added" ? { insert: op2.insert } : { delete: op2.insert.length }
188797
+ );
188798
+ }
188799
+ previous = current;
188800
+ if (changes.some((change) => change.insert !== void 0 || change.delete !== void 0) && !tracker.apply(changes)) {
188801
+ dispose();
188802
+ return false;
188803
+ }
188804
+ return true;
188805
+ } catch {
188806
+ dispose();
188807
+ return false;
188808
+ } finally {
188809
+ busy = false;
188810
+ }
188811
+ };
188812
+ const stop = snapshots2.subscribeBeforeObservers(refresh);
188813
+ if (disposed) {
188814
+ stop();
188815
+ } else {
188816
+ unsubscribe = stop;
188817
+ }
188818
+ return { capture: tracker.capture, resolve: tracker.resolve, refresh, dispose };
188819
+ }
187095
188820
  function createSyncGate(onOpen, graceMs = INITIAL_SYNC_GRACE_MS) {
187096
188821
  let opened = false;
187097
188822
  let timer = null;
@@ -191155,6 +192880,362 @@ function collectCoherent3DOffNodeIds(nodes) {
191155
192880
  }
191156
192881
  return ids;
191157
192882
  }
192883
+ var LINE_HEIGHT_RATIO = 1.2;
192884
+ function centeredSvgTextLines(text22, fontSize, options = {}) {
192885
+ const lines = options.maxWidth !== void 0 ? wrapTextByEstimatedWidth(text22, options.maxWidth, fontSize) : text22.split("\n").filter((line4) => line4.length > 0);
192886
+ const centerY = options.centerY ?? 0;
192887
+ if (lines.length === 0) {
192888
+ return [{ text: "", y: centerY }];
192889
+ }
192890
+ const lineHeight = options.lineHeight ?? fontSize * (options.lineHeightRatio ?? LINE_HEIGHT_RATIO);
192891
+ const blockTop = centerY - lines.length * lineHeight / 2;
192892
+ return lines.map((line4, index) => ({
192893
+ text: line4,
192894
+ y: blockTop + lineHeight / 2 + index * lineHeight
192895
+ }));
192896
+ }
192897
+ var PALETTES = {
192898
+ colorful1: ["#3b82f6", "#22c55e", "#f97316", "#eab308", "#a855f7", "#ec4899"],
192899
+ colorful2: ["#6366f1", "#14b8a6", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"],
192900
+ colorful3: ["#0ea5e9", "#84cc16", "#f43e5e", "#a855f7", "#f97316", "#10b981"],
192901
+ monochromatic1: ["#3b82f6", "#60a5fa", "#93c5fd", "#bfdbfe", "#2563eb", "#1d4ed8"],
192902
+ monochromatic2: ["#6366f1", "#818cf8", "#a5b4fc", "#c7d2fe", "#4f46e5", "#4338ca"]
192903
+ };
192904
+ var DEFAULT_PALETTE2 = PALETTES.colorful1;
192905
+ function paletteColour(index, palette) {
192906
+ return palette[index % palette.length];
192907
+ }
192908
+ function resolvePalette(data) {
192909
+ if (!data) {
192910
+ return DEFAULT_PALETTE2;
192911
+ }
192912
+ const ctFills = data.colorTransform?.fillColors;
192913
+ if (ctFills && ctFills.length > 0) {
192914
+ return ctFills;
192915
+ }
192916
+ return PALETTES[data.colorScheme ?? "colorful1"] ?? DEFAULT_PALETTE2;
192917
+ }
192918
+ function buildChromeStyle(chrome) {
192919
+ const s = {
192920
+ width: "100%",
192921
+ height: "100%",
192922
+ "box-sizing": "border-box",
192923
+ overflow: "hidden"
192924
+ };
192925
+ if (!chrome) {
192926
+ return s;
192927
+ }
192928
+ if (chrome.backgroundColor) {
192929
+ s["background-color"] = chrome.backgroundColor;
192930
+ }
192931
+ if (chrome.outlineColor) {
192932
+ s["border"] = `${chrome.outlineWidth ?? 1}px solid ${chrome.outlineColor}`;
192933
+ }
192934
+ return s;
192935
+ }
192936
+ var TEXT_WIDTH_FRACTION = 0.82;
192937
+ var CJK_SMARTART_TEXT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
192938
+ var CJK_SMARTART_LINE_HEIGHT_RATIO = 1.33;
192939
+ var DEFAULT_SMARTART_LINE_HEIGHT_RATIO = 1.2;
192940
+ function drawingTextBaseLineHeightRatio(text22) {
192941
+ return CJK_SMARTART_TEXT_RE.test(text22 ?? "") ? CJK_SMARTART_LINE_HEIGHT_RATIO : DEFAULT_SMARTART_LINE_HEIGHT_RATIO;
192942
+ }
192943
+ function underlyingFill(shape, shapes, index) {
192944
+ const centerX = shape.x + shape.width / 2;
192945
+ const centerY = shape.y + shape.height / 2;
192946
+ for (let below = index - 1; below >= 0; below--) {
192947
+ const candidate = shapes[below];
192948
+ if (!candidate || candidate.fillNone || !candidate.fillColor) {
192949
+ continue;
192950
+ }
192951
+ if (centerX >= candidate.x && centerX <= candidate.x + candidate.width && centerY >= candidate.y && centerY <= candidate.y + candidate.height) {
192952
+ return candidate.fillColor;
192953
+ }
192954
+ }
192955
+ return void 0;
192956
+ }
192957
+ function drawingShapeLabelColor(shape, shapes, index, resolvedFill) {
192958
+ const basis = resolvedFill === "none" || resolvedFill.startsWith("url(") ? underlyingFill(shape, shapes, index) : resolvedFill;
192959
+ return basis ? contrastTextColor(basis) : "#1a1a1a";
192960
+ }
192961
+ function computeDrawingViewBox(shapes) {
192962
+ let minX = Infinity;
192963
+ let minY = Infinity;
192964
+ let maxX = -Infinity;
192965
+ let maxY = -Infinity;
192966
+ for (const s of shapes) {
192967
+ const shapeMinX = Math.min(s.x, s.textFrameX ?? s.x);
192968
+ const shapeMinY = Math.min(s.y, s.textFrameY ?? s.y);
192969
+ const shapeMaxX = Math.max(
192970
+ s.x + s.width,
192971
+ (s.textFrameX ?? s.x) + (s.textFrameWidth ?? s.width)
192972
+ );
192973
+ const shapeMaxY = Math.max(
192974
+ s.y + s.height,
192975
+ (s.textFrameY ?? s.y) + (s.textFrameHeight ?? s.height)
192976
+ );
192977
+ if (shapeMinX < minX) {
192978
+ minX = shapeMinX;
192979
+ }
192980
+ if (shapeMinY < minY) {
192981
+ minY = shapeMinY;
192982
+ }
192983
+ if (shapeMaxX > maxX) {
192984
+ maxX = shapeMaxX;
192985
+ }
192986
+ if (shapeMaxY > maxY) {
192987
+ maxY = shapeMaxY;
192988
+ }
192989
+ }
192990
+ if (!Number.isFinite(minX)) {
192991
+ return { minX: 0, minY: 0, width: 1, height: 1 };
192992
+ }
192993
+ return {
192994
+ minX,
192995
+ minY,
192996
+ width: maxX - minX || 1,
192997
+ height: maxY - minY || 1
192998
+ };
192999
+ }
193000
+ function resolveGradient(shape, id) {
193001
+ const stops = shape.fillGradientStops;
193002
+ if (!stops || stops.length === 0) {
193003
+ return void 0;
193004
+ }
193005
+ const mapped = stops.map((stop) => ({
193006
+ offset: `${Math.max(0, Math.min(100, stop.position))}%`,
193007
+ color: stop.color,
193008
+ ...stop.opacity !== void 0 ? { opacity: stop.opacity } : {}
193009
+ }));
193010
+ if (shape.fillGradientType === "radial") {
193011
+ return { id, kind: "radial", cx: "50%", cy: "50%", r: "50%", stops: mapped };
193012
+ }
193013
+ const radians = (shape.fillGradientAngle ?? 0) * Math.PI / 180;
193014
+ const dx = Math.cos(radians) / 2;
193015
+ const dy = Math.sin(radians) / 2;
193016
+ return {
193017
+ id,
193018
+ kind: "linear",
193019
+ x1: `${(0.5 - dx) * 100}%`,
193020
+ y1: `${(0.5 - dy) * 100}%`,
193021
+ x2: `${(0.5 + dx) * 100}%`,
193022
+ y2: `${(0.5 + dy) * 100}%`,
193023
+ stops: mapped
193024
+ };
193025
+ }
193026
+ function resolveShapeKind(shape, hasImage) {
193027
+ if (hasImage) {
193028
+ return "image";
193029
+ }
193030
+ const normalized = (shape.shapeType ?? "").trim().toLowerCase();
193031
+ if (normalized === "ellipse" || normalized === "oval") {
193032
+ return "ellipse";
193033
+ }
193034
+ const identityPresets = /* @__PURE__ */ new Set(["rect", "flowchartprocess", "roundrect"]);
193035
+ return identityPresets.has(normalized) || normalized.length === 0 ? "rect" : "path";
193036
+ }
193037
+ function drawingShapeTransform(shape, cx, cy) {
193038
+ const transforms = [];
193039
+ if (shape.rotation) {
193040
+ transforms.push(`rotate(${shape.rotation} ${cx} ${cy})`);
193041
+ }
193042
+ if (shape.flipHorizontal || shape.flipVertical) {
193043
+ transforms.push(
193044
+ `translate(${cx} ${cy}) scale(${shape.flipHorizontal ? -1 : 1} ${shape.flipVertical ? -1 : 1}) translate(${-cx} ${-cy})`
193045
+ );
193046
+ }
193047
+ return transforms.length > 0 ? transforms.join(" ") : void 0;
193048
+ }
193049
+ function projectDrawingShapes(elementId, shapes, viewBox, palette, style) {
193050
+ const { minX, minY } = viewBox;
193051
+ const sw = styleStroke(style);
193052
+ return shapes.map((shape, i2) => {
193053
+ const gradient = shape.fillNone ? void 0 : resolveGradient(shape, `${elementId}-dspgrad-${shape.id}-${i2}`);
193054
+ const fill = shape.fillNone ? "none" : gradient ? `url(#${gradient.id})` : shape.fillPatternForegroundColor ?? shape.fillColor ?? paletteColour(i2, palette);
193055
+ const relX = shape.x - minX;
193056
+ const relY = shape.y - minY;
193057
+ const kind = resolveShapeKind(shape, Boolean(shape.fillImageUrl));
193058
+ const rx = getShapeType(shape.shapeType) === "roundRect" ? Math.min(shape.width, shape.height) * 0.1 : 0;
193059
+ const cx = relX + shape.width / 2;
193060
+ const cy = relY + shape.height / 2;
193061
+ const stroke = shape.strokeColor ?? (sw > 0 ? "rgba(255,255,255,0.3)" : "none");
193062
+ const transform6 = drawingShapeTransform(shape, cx, cy);
193063
+ const presetGeometry = kind === "path" ? getPresetShapeVectorGeometry(
193064
+ shape.shapeType,
193065
+ shape.width,
193066
+ shape.height,
193067
+ shape.shapeAdjustments
193068
+ ) : void 0;
193069
+ const fontSize = shape.fontSize ?? Math.max(8, Math.min(14, shape.height * 0.2));
193070
+ const hasTextFrame = Number.isFinite(shape.textFrameX) && Number.isFinite(shape.textFrameY) && Number.isFinite(shape.textFrameWidth) && Number.isFinite(shape.textFrameHeight) && (shape.textFrameWidth ?? 0) > 0 && (shape.textFrameHeight ?? 0) > 0;
193071
+ const textFrameX = (hasTextFrame ? shape.textFrameX : shape.x) - minX;
193072
+ const textFrameY = (hasTextFrame ? shape.textFrameY : shape.y) - minY;
193073
+ const textFrameWidth = hasTextFrame ? shape.textFrameWidth : shape.width;
193074
+ const textFrameHeight = hasTextFrame ? shape.textFrameHeight : shape.height;
193075
+ const textInsetLeft = shape.textInsetLeft ?? 0;
193076
+ const textInsetRight = shape.textInsetRight ?? 0;
193077
+ const textInsetTop = shape.textInsetTop ?? 0;
193078
+ const textInsetBottom = shape.textInsetBottom ?? 0;
193079
+ const textContentWidth = Math.max(1, textFrameWidth - textInsetLeft - textInsetRight);
193080
+ const textContentHeight = Math.max(1, textFrameHeight - textInsetTop - textInsetBottom);
193081
+ const textCenterX = textFrameX + textInsetLeft + textContentWidth / 2;
193082
+ const textCenterY = textFrameY + textInsetTop + textContentHeight / 2;
193083
+ const textWrapWidth = hasTextFrame ? textContentWidth : shape.width * TEXT_WIDTH_FRACTION;
193084
+ const authoredLineHeightRatio = shape.lineHeightRatio ?? 1;
193085
+ const lineHeightRatio = drawingTextBaseLineHeightRatio(shape.text) * authoredLineHeightRatio + (shape.lineSpacingAfterRatio ?? 0);
193086
+ const lineHeight = shape.lineHeight !== void 0 || shape.lineSpacingAfter !== void 0 ? (shape.lineHeight ?? fontSize * drawingTextBaseLineHeightRatio(shape.text) * authoredLineHeightRatio) + (shape.lineSpacingAfter ?? 0) : void 0;
193087
+ return {
193088
+ key: `${elementId}-dsp-${shape.id}-${i2}`,
193089
+ kind,
193090
+ ...presetGeometry ? {
193091
+ pathData: presetGeometry.d,
193092
+ pathTransform: [transform6, `translate(${relX} ${relY})`].filter(Boolean).join(" ")
193093
+ } : {},
193094
+ ...gradient ? { gradient } : {},
193095
+ x: relX,
193096
+ y: relY,
193097
+ width: shape.width,
193098
+ height: shape.height,
193099
+ rx,
193100
+ cx,
193101
+ cy,
193102
+ fill,
193103
+ stroke,
193104
+ strokeWidth: shape.strokeWidth ?? sw,
193105
+ transform: transform6,
193106
+ imageUrl: shape.fillImageUrl,
193107
+ textLines: shape.text ? centeredSvgTextLines(shape.text, fontSize, {
193108
+ maxWidth: textWrapWidth,
193109
+ centerY: textCenterY,
193110
+ lineHeight,
193111
+ lineHeightRatio
193112
+ }) : [],
193113
+ textX: textCenterX,
193114
+ textY: textCenterY,
193115
+ textWidth: textContentWidth,
193116
+ textHeight: textContentHeight,
193117
+ fontColor: shape.fontColor ?? drawingShapeLabelColor(shape, shapes, i2, fill),
193118
+ fontSize,
193119
+ fontFamily: shape.fontFamily ? getSubstituteFontFamily(shape.fontFamily) : void 0,
193120
+ fontWeight: shape.fontWeight,
193121
+ fontStyle: shape.fontStyle
193122
+ };
193123
+ });
193124
+ }
193125
+ function styleShadowFilter(style) {
193126
+ return styleShadow(style);
193127
+ }
193128
+ function fitDrawingToBox(drawing, box) {
193129
+ const scale2 = Math.min(box.width / drawing.width, box.height / drawing.height) || 1;
193130
+ return {
193131
+ scale: scale2,
193132
+ offsetX: (box.width - drawing.width * scale2) / 2,
193133
+ offsetY: (box.height - drawing.height * scale2) / 2
193134
+ };
193135
+ }
193136
+ function solidFill3(shape, rendered) {
193137
+ if (shape.fillNone || rendered.fill === "none") {
193138
+ return null;
193139
+ }
193140
+ if (rendered.gradient) {
193141
+ return rendered.gradient.stops[0]?.color ?? shape.fillColor ?? null;
193142
+ }
193143
+ return rendered.fill;
193144
+ }
193145
+ function drawingShapeNode(shape, rendered, fit) {
193146
+ const fill = solidFill3(shape, rendered);
193147
+ if (!fill) {
193148
+ return null;
193149
+ }
193150
+ const { scale: scale2, offsetX, offsetY } = fit;
193151
+ const sx = (x) => offsetX + x * scale2;
193152
+ const sy = (y) => offsetY + y * scale2;
193153
+ const base = {
193154
+ key: rendered.key,
193155
+ fill,
193156
+ stroke: rendered.stroke,
193157
+ strokeWidth: rendered.strokeWidth * scale2,
193158
+ opacity: 1,
193159
+ text: shape.text ?? "",
193160
+ fontSize: rendered.fontSize * scale2,
193161
+ textX: sx(rendered.textX),
193162
+ textY: sy(rendered.textY)
193163
+ };
193164
+ if (rendered.kind === "ellipse") {
193165
+ return {
193166
+ ...base,
193167
+ kind: "circle",
193168
+ cx: sx(rendered.cx),
193169
+ cy: sy(rendered.cy),
193170
+ r: Math.min(rendered.width, rendered.height) / 2 * scale2,
193171
+ rx: rendered.width / 2 * scale2,
193172
+ ry: rendered.height / 2 * scale2
193173
+ };
193174
+ }
193175
+ if (rendered.kind === "path" && rendered.pathData) {
193176
+ const pts = parsePathPoints(rendered.pathData);
193177
+ if (pts.length >= 3) {
193178
+ return {
193179
+ ...base,
193180
+ kind: "polygon",
193181
+ points: pts.map((p) => `${sx(rendered.x + p.x)},${sy(rendered.y + p.y)}`).join(" ")
193182
+ };
193183
+ }
193184
+ }
193185
+ return {
193186
+ ...base,
193187
+ kind: "rect",
193188
+ x: sx(rendered.x),
193189
+ y: sy(rendered.y),
193190
+ width: rendered.width * scale2,
193191
+ height: rendered.height * scale2,
193192
+ rx: rendered.rx * scale2
193193
+ };
193194
+ }
193195
+ function drawingShapesLayoutResult(elementId, shapes, box, palette, style, family) {
193196
+ if (!shapes || shapes.length === 0) {
193197
+ return null;
193198
+ }
193199
+ const viewBox = computeDrawingViewBox(shapes);
193200
+ const fit = fitDrawingToBox(viewBox, box);
193201
+ const rendered = projectDrawingShapes(elementId, shapes, viewBox, palette, style);
193202
+ const nodes = [];
193203
+ rendered.forEach((r, i2) => {
193204
+ const node = drawingShapeNode(shapes[i2], r, fit);
193205
+ if (node) {
193206
+ nodes.push(node);
193207
+ }
193208
+ });
193209
+ if (nodes.length === 0) {
193210
+ return null;
193211
+ }
193212
+ return {
193213
+ nodes,
193214
+ connectors: [],
193215
+ shadowFilter: void 0,
193216
+ viewBox: `0 0 ${box.width} ${box.height}`,
193217
+ family
193218
+ };
193219
+ }
193220
+ function resolveSmartArt3DLayout(smartArtData, nodes, box, palette, style, elementId) {
193221
+ const family = resolveLayoutFamily(nodes, smartArtData.resolvedLayoutType, smartArtData.layout);
193222
+ return drawingShapesLayoutResult(elementId, smartArtData.drawingShapes, box, palette, style, family) ?? computeSmartArtElementLayout(smartArtData, nodes, box, palette, style, elementId);
193223
+ }
193224
+ function observeElementHeight(el, onHeight) {
193225
+ onHeight(el.getBoundingClientRect().height);
193226
+ if (typeof ResizeObserver === "undefined") {
193227
+ return () => void 0;
193228
+ }
193229
+ const observer = new ResizeObserver((entries) => {
193230
+ const entry2 = entries[entries.length - 1];
193231
+ if (entry2) {
193232
+ const box = entry2.borderBoxSize?.[0]?.blockSize;
193233
+ onHeight(box ?? el.getBoundingClientRect().height);
193234
+ }
193235
+ });
193236
+ observer.observe(el);
193237
+ return () => observer.disconnect();
193238
+ }
191158
193239
  var MAX_LISTED_NODES = 8;
191159
193240
  var LAYOUT_LABELS = {
191160
193241
  list: "List",
@@ -192344,10 +194425,18 @@ function computeSphericalCameraPlacement(maxExtent, targetY, view3D) {
192344
194425
  fov
192345
194426
  };
192346
194427
  }
192347
- function computeCartesianCameraPlacement(cols, rows, view3D) {
194428
+ function computeCartesianCameraPlacement(cols, rows, view3D, horizontal = false) {
192348
194429
  const { gridWidth, gridDepth } = computeCartesianGridExtent(cols, rows, view3D?.depthPercent);
192349
194430
  const maxExtent = Math.max(gridWidth, gridDepth, MAX_VALUE_HEIGHT);
192350
- return computeSphericalCameraPlacement(maxExtent, MAX_VALUE_HEIGHT * 0.2, view3D);
194431
+ const placement = computeSphericalCameraPlacement(maxExtent, MAX_VALUE_HEIGHT * 0.2, view3D);
194432
+ if (!horizontal) {
194433
+ return placement;
194434
+ }
194435
+ return {
194436
+ ...placement,
194437
+ position: transposeForHorizontalBar3D(placement.position),
194438
+ target: transposeForHorizontalBar3D(placement.target)
194439
+ };
192351
194440
  }
192352
194441
  function buildCartesianChart3DLabels(cols, rows, categoryLabels, seriesNames, depthPercent, maxCat = 8, maxSer = 6, horizontal = false) {
192353
194442
  const { gridWidth, gridDepth } = computeCartesianGridExtent(cols, rows, depthPercent);
@@ -192796,7 +194885,12 @@ async function mountBarChart3D(container, options, interaction) {
192796
194885
  const fill = new three.DirectionalLight(16777215, 0.3);
192797
194886
  fill.position.set(-3, 4, -2);
192798
194887
  scene.add(fill);
192799
- const placement = computeCartesianCameraPlacement(options.cols, options.rows, options.view3D);
194888
+ const placement = computeCartesianCameraPlacement(
194889
+ options.cols,
194890
+ options.rows,
194891
+ options.view3D,
194892
+ options.horizontal
194893
+ );
192800
194894
  const camera = new three.PerspectiveCamera(placement.fov, width / height, 0.1, 1e3);
192801
194895
  camera.position.set(...placement.position);
192802
194896
  const target = new three.Vector3(...placement.target);
@@ -194211,344 +196305,6 @@ function buildPieChart3DDataForElement(element, options) {
194211
196305
  const categoryLabels = chartData.categories.length > 0 ? chartData.categories : Array.from({ length: pieSeries.values.length }, (_, i2) => String(i2 + 1));
194212
196306
  return buildPieChart3DData(chartData, categoryLabels, options);
194213
196307
  }
194214
- function estimatedGlyphAdvanceRatio(glyph) {
194215
- if (/\p{Mark}/u.test(glyph)) {
194216
- return 0;
194217
- }
194218
- if (/\s/u.test(glyph)) {
194219
- return 0.33;
194220
- }
194221
- if (/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Extended_Pictographic}]/u.test(
194222
- glyph
194223
- )) {
194224
- return 1;
194225
- }
194226
- if (/[A-Z]/u.test(glyph)) {
194227
- return 0.65;
194228
- }
194229
- if (/[a-z0-9]/u.test(glyph)) {
194230
- return 0.55;
194231
- }
194232
- if (/[,.;:!?()\u005b\u005d{}'"`\-_/\\]/u.test(glyph)) {
194233
- return 0.35;
194234
- }
194235
- return 0.6;
194236
- }
194237
- function estimatedTextWidth(glyphs, fontSize) {
194238
- return glyphs.reduce((sum, glyph) => sum + estimatedGlyphAdvanceRatio(glyph) * fontSize, 0);
194239
- }
194240
- var HANGING_PUNCTUATION_RE = /^[\u3001\u3002\uff0c\uff0e\uff01\uff1f\uff1b\uff1a\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\uff09\uff3d\uff5d\u2019\u201d\u00bb\u203a]$/u;
194241
- var BREAKABLE_GLYPH_RE = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Extended_Pictographic}]$/u;
194242
- function estimatedWrapUnits(text22) {
194243
- const units = [];
194244
- let unbreakableRun = "";
194245
- const flushRun = () => {
194246
- if (unbreakableRun.length > 0) {
194247
- units.push(unbreakableRun);
194248
- unbreakableRun = "";
194249
- }
194250
- };
194251
- for (const glyph of Array.from(text22)) {
194252
- if (/\s/u.test(glyph) || BREAKABLE_GLYPH_RE.test(glyph)) {
194253
- flushRun();
194254
- units.push(glyph);
194255
- } else {
194256
- unbreakableRun += glyph;
194257
- }
194258
- }
194259
- flushRun();
194260
- return units;
194261
- }
194262
- function wrapTextByEstimatedWidth(text22, maxWidth, fontSize, options = {}) {
194263
- if (!text22 || text22.trim().length === 0) {
194264
- return [];
194265
- }
194266
- if (!(maxWidth > 0) || !(fontSize > 0)) {
194267
- return [];
194268
- }
194269
- const lines = [];
194270
- for (const paragraph of text22.split(/\r?\n/u)) {
194271
- if (paragraph.trim().length === 0) {
194272
- if (options.keepBlankLines) {
194273
- lines.push("");
194274
- }
194275
- continue;
194276
- }
194277
- let current = "";
194278
- let pendingWhitespace = false;
194279
- for (const unit of estimatedWrapUnits(paragraph)) {
194280
- if (/^\s+$/u.test(unit)) {
194281
- pendingWhitespace = current.length > 0;
194282
- continue;
194283
- }
194284
- const separator = pendingWhitespace && current.length > 0 ? " " : "";
194285
- const candidate = `${current}${separator}${unit}`;
194286
- if (current.length === 0 || estimatedTextWidth(Array.from(candidate), fontSize) <= maxWidth) {
194287
- current = candidate;
194288
- pendingWhitespace = false;
194289
- continue;
194290
- }
194291
- if (HANGING_PUNCTUATION_RE.test(unit)) {
194292
- current += unit;
194293
- pendingWhitespace = false;
194294
- continue;
194295
- }
194296
- lines.push(current);
194297
- current = unit;
194298
- pendingWhitespace = false;
194299
- }
194300
- const completed = current.trimEnd();
194301
- if (completed.length > 0) {
194302
- lines.push(completed);
194303
- }
194304
- }
194305
- return lines;
194306
- }
194307
- var LINE_HEIGHT_RATIO = 1.2;
194308
- function centeredSvgTextLines(text22, fontSize, options = {}) {
194309
- const lines = options.maxWidth !== void 0 ? wrapTextByEstimatedWidth(text22, options.maxWidth, fontSize) : text22.split("\n").filter((line4) => line4.length > 0);
194310
- const centerY = options.centerY ?? 0;
194311
- if (lines.length === 0) {
194312
- return [{ text: "", y: centerY }];
194313
- }
194314
- const lineHeight = options.lineHeight ?? fontSize * (options.lineHeightRatio ?? LINE_HEIGHT_RATIO);
194315
- const blockTop = centerY - lines.length * lineHeight / 2;
194316
- return lines.map((line4, index) => ({
194317
- text: line4,
194318
- y: blockTop + lineHeight / 2 + index * lineHeight
194319
- }));
194320
- }
194321
- var PALETTES = {
194322
- colorful1: ["#3b82f6", "#22c55e", "#f97316", "#eab308", "#a855f7", "#ec4899"],
194323
- colorful2: ["#6366f1", "#14b8a6", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"],
194324
- colorful3: ["#0ea5e9", "#84cc16", "#f43e5e", "#a855f7", "#f97316", "#10b981"],
194325
- monochromatic1: ["#3b82f6", "#60a5fa", "#93c5fd", "#bfdbfe", "#2563eb", "#1d4ed8"],
194326
- monochromatic2: ["#6366f1", "#818cf8", "#a5b4fc", "#c7d2fe", "#4f46e5", "#4338ca"]
194327
- };
194328
- var DEFAULT_PALETTE2 = PALETTES.colorful1;
194329
- function paletteColour(index, palette) {
194330
- return palette[index % palette.length];
194331
- }
194332
- function resolvePalette(data) {
194333
- if (!data) {
194334
- return DEFAULT_PALETTE2;
194335
- }
194336
- const ctFills = data.colorTransform?.fillColors;
194337
- if (ctFills && ctFills.length > 0) {
194338
- return ctFills;
194339
- }
194340
- return PALETTES[data.colorScheme ?? "colorful1"] ?? DEFAULT_PALETTE2;
194341
- }
194342
- function buildChromeStyle(chrome) {
194343
- const s = {
194344
- width: "100%",
194345
- height: "100%",
194346
- "box-sizing": "border-box",
194347
- overflow: "hidden"
194348
- };
194349
- if (!chrome) {
194350
- return s;
194351
- }
194352
- if (chrome.backgroundColor) {
194353
- s["background-color"] = chrome.backgroundColor;
194354
- }
194355
- if (chrome.outlineColor) {
194356
- s["border"] = `${chrome.outlineWidth ?? 1}px solid ${chrome.outlineColor}`;
194357
- }
194358
- return s;
194359
- }
194360
- var TEXT_WIDTH_FRACTION = 0.82;
194361
- var CJK_SMARTART_TEXT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
194362
- var CJK_SMARTART_LINE_HEIGHT_RATIO = 1.33;
194363
- var DEFAULT_SMARTART_LINE_HEIGHT_RATIO = 1.2;
194364
- function drawingTextBaseLineHeightRatio(text22) {
194365
- return CJK_SMARTART_TEXT_RE.test(text22 ?? "") ? CJK_SMARTART_LINE_HEIGHT_RATIO : DEFAULT_SMARTART_LINE_HEIGHT_RATIO;
194366
- }
194367
- function underlyingFill(shape, shapes, index) {
194368
- const centerX = shape.x + shape.width / 2;
194369
- const centerY = shape.y + shape.height / 2;
194370
- for (let below = index - 1; below >= 0; below--) {
194371
- const candidate = shapes[below];
194372
- if (!candidate || candidate.fillNone || !candidate.fillColor) {
194373
- continue;
194374
- }
194375
- if (centerX >= candidate.x && centerX <= candidate.x + candidate.width && centerY >= candidate.y && centerY <= candidate.y + candidate.height) {
194376
- return candidate.fillColor;
194377
- }
194378
- }
194379
- return void 0;
194380
- }
194381
- function drawingShapeLabelColor(shape, shapes, index, resolvedFill) {
194382
- const basis = resolvedFill === "none" || resolvedFill.startsWith("url(") ? underlyingFill(shape, shapes, index) : resolvedFill;
194383
- return basis ? contrastTextColor(basis) : "#1a1a1a";
194384
- }
194385
- function computeDrawingViewBox(shapes) {
194386
- let minX = Infinity;
194387
- let minY = Infinity;
194388
- let maxX = -Infinity;
194389
- let maxY = -Infinity;
194390
- for (const s of shapes) {
194391
- const shapeMinX = Math.min(s.x, s.textFrameX ?? s.x);
194392
- const shapeMinY = Math.min(s.y, s.textFrameY ?? s.y);
194393
- const shapeMaxX = Math.max(
194394
- s.x + s.width,
194395
- (s.textFrameX ?? s.x) + (s.textFrameWidth ?? s.width)
194396
- );
194397
- const shapeMaxY = Math.max(
194398
- s.y + s.height,
194399
- (s.textFrameY ?? s.y) + (s.textFrameHeight ?? s.height)
194400
- );
194401
- if (shapeMinX < minX) {
194402
- minX = shapeMinX;
194403
- }
194404
- if (shapeMinY < minY) {
194405
- minY = shapeMinY;
194406
- }
194407
- if (shapeMaxX > maxX) {
194408
- maxX = shapeMaxX;
194409
- }
194410
- if (shapeMaxY > maxY) {
194411
- maxY = shapeMaxY;
194412
- }
194413
- }
194414
- if (!Number.isFinite(minX)) {
194415
- return { minX: 0, minY: 0, width: 1, height: 1 };
194416
- }
194417
- return {
194418
- minX,
194419
- minY,
194420
- width: maxX - minX || 1,
194421
- height: maxY - minY || 1
194422
- };
194423
- }
194424
- function resolveGradient(shape, id) {
194425
- const stops = shape.fillGradientStops;
194426
- if (!stops || stops.length === 0) {
194427
- return void 0;
194428
- }
194429
- const mapped = stops.map((stop) => ({
194430
- offset: `${Math.max(0, Math.min(100, stop.position))}%`,
194431
- color: stop.color,
194432
- ...stop.opacity !== void 0 ? { opacity: stop.opacity } : {}
194433
- }));
194434
- if (shape.fillGradientType === "radial") {
194435
- return { id, kind: "radial", cx: "50%", cy: "50%", r: "50%", stops: mapped };
194436
- }
194437
- const radians = (shape.fillGradientAngle ?? 0) * Math.PI / 180;
194438
- const dx = Math.cos(radians) / 2;
194439
- const dy = Math.sin(radians) / 2;
194440
- return {
194441
- id,
194442
- kind: "linear",
194443
- x1: `${(0.5 - dx) * 100}%`,
194444
- y1: `${(0.5 - dy) * 100}%`,
194445
- x2: `${(0.5 + dx) * 100}%`,
194446
- y2: `${(0.5 + dy) * 100}%`,
194447
- stops: mapped
194448
- };
194449
- }
194450
- function resolveShapeKind(shape, hasImage) {
194451
- if (hasImage) {
194452
- return "image";
194453
- }
194454
- const normalized = (shape.shapeType ?? "").trim().toLowerCase();
194455
- if (normalized === "ellipse" || normalized === "oval") {
194456
- return "ellipse";
194457
- }
194458
- const identityPresets = /* @__PURE__ */ new Set(["rect", "flowchartprocess", "roundrect"]);
194459
- return identityPresets.has(normalized) || normalized.length === 0 ? "rect" : "path";
194460
- }
194461
- function drawingShapeTransform(shape, cx, cy) {
194462
- const transforms = [];
194463
- if (shape.rotation) {
194464
- transforms.push(`rotate(${shape.rotation} ${cx} ${cy})`);
194465
- }
194466
- if (shape.flipHorizontal || shape.flipVertical) {
194467
- transforms.push(
194468
- `translate(${cx} ${cy}) scale(${shape.flipHorizontal ? -1 : 1} ${shape.flipVertical ? -1 : 1}) translate(${-cx} ${-cy})`
194469
- );
194470
- }
194471
- return transforms.length > 0 ? transforms.join(" ") : void 0;
194472
- }
194473
- function projectDrawingShapes(elementId, shapes, viewBox, palette, style) {
194474
- const { minX, minY } = viewBox;
194475
- const sw = styleStroke(style);
194476
- return shapes.map((shape, i2) => {
194477
- const gradient = shape.fillNone ? void 0 : resolveGradient(shape, `${elementId}-dspgrad-${shape.id}-${i2}`);
194478
- const fill = shape.fillNone ? "none" : gradient ? `url(#${gradient.id})` : shape.fillPatternForegroundColor ?? shape.fillColor ?? paletteColour(i2, palette);
194479
- const relX = shape.x - minX;
194480
- const relY = shape.y - minY;
194481
- const kind = resolveShapeKind(shape, Boolean(shape.fillImageUrl));
194482
- const rx = getShapeType(shape.shapeType) === "roundRect" ? Math.min(shape.width, shape.height) * 0.1 : 0;
194483
- const cx = relX + shape.width / 2;
194484
- const cy = relY + shape.height / 2;
194485
- const stroke = shape.strokeColor ?? (sw > 0 ? "rgba(255,255,255,0.3)" : "none");
194486
- const transform6 = drawingShapeTransform(shape, cx, cy);
194487
- const presetGeometry = kind === "path" ? getPresetShapeVectorGeometry(
194488
- shape.shapeType,
194489
- shape.width,
194490
- shape.height,
194491
- shape.shapeAdjustments
194492
- ) : void 0;
194493
- const fontSize = shape.fontSize ?? Math.max(8, Math.min(14, shape.height * 0.2));
194494
- const hasTextFrame = Number.isFinite(shape.textFrameX) && Number.isFinite(shape.textFrameY) && Number.isFinite(shape.textFrameWidth) && Number.isFinite(shape.textFrameHeight) && (shape.textFrameWidth ?? 0) > 0 && (shape.textFrameHeight ?? 0) > 0;
194495
- const textFrameX = (hasTextFrame ? shape.textFrameX : shape.x) - minX;
194496
- const textFrameY = (hasTextFrame ? shape.textFrameY : shape.y) - minY;
194497
- const textFrameWidth = hasTextFrame ? shape.textFrameWidth : shape.width;
194498
- const textFrameHeight = hasTextFrame ? shape.textFrameHeight : shape.height;
194499
- const textInsetLeft = shape.textInsetLeft ?? 0;
194500
- const textInsetRight = shape.textInsetRight ?? 0;
194501
- const textInsetTop = shape.textInsetTop ?? 0;
194502
- const textInsetBottom = shape.textInsetBottom ?? 0;
194503
- const textContentWidth = Math.max(1, textFrameWidth - textInsetLeft - textInsetRight);
194504
- const textContentHeight = Math.max(1, textFrameHeight - textInsetTop - textInsetBottom);
194505
- const textCenterX = textFrameX + textInsetLeft + textContentWidth / 2;
194506
- const textCenterY = textFrameY + textInsetTop + textContentHeight / 2;
194507
- const textWrapWidth = hasTextFrame ? textContentWidth : shape.width * TEXT_WIDTH_FRACTION;
194508
- const authoredLineHeightRatio = shape.lineHeightRatio ?? 1;
194509
- const lineHeightRatio = drawingTextBaseLineHeightRatio(shape.text) * authoredLineHeightRatio + (shape.lineSpacingAfterRatio ?? 0);
194510
- const lineHeight = shape.lineHeight !== void 0 || shape.lineSpacingAfter !== void 0 ? (shape.lineHeight ?? fontSize * drawingTextBaseLineHeightRatio(shape.text) * authoredLineHeightRatio) + (shape.lineSpacingAfter ?? 0) : void 0;
194511
- return {
194512
- key: `${elementId}-dsp-${shape.id}-${i2}`,
194513
- kind,
194514
- ...presetGeometry ? {
194515
- pathData: presetGeometry.d,
194516
- pathTransform: [transform6, `translate(${relX} ${relY})`].filter(Boolean).join(" ")
194517
- } : {},
194518
- ...gradient ? { gradient } : {},
194519
- x: relX,
194520
- y: relY,
194521
- width: shape.width,
194522
- height: shape.height,
194523
- rx,
194524
- cx,
194525
- cy,
194526
- fill,
194527
- stroke,
194528
- strokeWidth: shape.strokeWidth ?? sw,
194529
- transform: transform6,
194530
- imageUrl: shape.fillImageUrl,
194531
- textLines: shape.text ? centeredSvgTextLines(shape.text, fontSize, {
194532
- maxWidth: textWrapWidth,
194533
- centerY: textCenterY,
194534
- lineHeight,
194535
- lineHeightRatio
194536
- }) : [],
194537
- textX: textCenterX,
194538
- textY: textCenterY,
194539
- textWidth: textContentWidth,
194540
- textHeight: textContentHeight,
194541
- fontColor: shape.fontColor ?? drawingShapeLabelColor(shape, shapes, i2, fill),
194542
- fontSize,
194543
- fontFamily: shape.fontFamily ? getSubstituteFontFamily(shape.fontFamily) : void 0,
194544
- fontWeight: shape.fontWeight,
194545
- fontStyle: shape.fontStyle
194546
- };
194547
- });
194548
- }
194549
- function styleShadowFilter(style) {
194550
- return styleShadow(style);
194551
- }
194552
196308
  function collectFontsFromElement(element, fonts) {
194553
196309
  if (hasTextProperties(element)) {
194554
196310
  if (element.textStyle?.fontFamily) {
@@ -201494,13 +203250,14 @@ var COMPAT_TOAST_METRICS = {
201494
203250
  /** Stacking order: above the canvas and inspector, below dialogs. */
201495
203251
  zIndex: 40
201496
203252
  };
201497
- function compatToastStackStyle() {
203253
+ function compatToastStackStyle(extraRightInset = 0, extraBottomInset = 0) {
201498
203254
  const m = COMPAT_TOAST_METRICS;
201499
203255
  return {
201500
203256
  position: "absolute",
201501
- right: `${String(m.insetRight)}px`,
201502
- bottom: `${String(STATUS_BAR_METRICS.height + m.marginAboveStatusBar)}px`,
203257
+ right: `${String(m.insetRight + extraRightInset)}px`,
203258
+ bottom: `${String(STATUS_BAR_METRICS.height + m.marginAboveStatusBar + extraBottomInset)}px`,
201503
203259
  width: `${String(m.width)}px`,
203260
+ maxWidth: `calc(100% - ${String(m.insetRight + extraRightInset)}px)`,
201504
203261
  zIndex: String(m.zIndex),
201505
203262
  display: "flex",
201506
203263
  flexDirection: "column",
@@ -201711,8 +203468,20 @@ function filterCommands(query, resolveLabel) {
201711
203468
  (entry2) => resolveLabel(entry2.labelKey).toLowerCase().includes(lowerQuery)
201712
203469
  );
201713
203470
  }
203471
+ var sourceIdentities = /* @__PURE__ */ new WeakMap();
203472
+ function sourceIdentity(source) {
203473
+ if ((typeof source !== "object" || source === null) && typeof source !== "function") {
203474
+ return source;
203475
+ }
203476
+ let identity = sourceIdentities.get(source);
203477
+ if (!identity) {
203478
+ identity = {};
203479
+ sourceIdentities.set(source, identity);
203480
+ }
203481
+ return identity;
203482
+ }
201714
203483
  function autosaveSnapshotMark(filePath, sources) {
201715
- return { filePath, sources: [...sources] };
203484
+ return { filePath, sources: sources.map(sourceIdentity) };
201716
203485
  }
201717
203486
  function shouldWriteAutosaveSnapshot(input) {
201718
203487
  if (!input.filePath || !input.isDirty || input.saving) {
@@ -201725,7 +203494,9 @@ function shouldWriteAutosaveSnapshot(input) {
201725
203494
  if (input.sources.length === 0 || previous.sources.length !== input.sources.length) {
201726
203495
  return true;
201727
203496
  }
201728
- return input.sources.some((source, index) => !Object.is(source, previous.sources[index]));
203497
+ return input.sources.some(
203498
+ (source, index) => !Object.is(sourceIdentity(source), previous.sources[index])
203499
+ );
201729
203500
  }
201730
203501
  function resolveAutosaveActivation(input) {
201731
203502
  if (input.hostAutosave === false) {
@@ -201860,8 +203631,8 @@ async function listBackstageRecentFiles(translate, limit) {
201860
203631
  return [];
201861
203632
  }
201862
203633
  try {
201863
- const snapshots = await listAutosaveSnapshots();
201864
- const sorted = snapshots.map((snapshot) => ({ ...snapshot, ...splitFilePath(snapshot.key, translate) })).sort((a, b) => b.timestamp - a.timestamp);
203634
+ const snapshots2 = await listAutosaveSnapshots();
203635
+ const sorted = snapshots2.map((snapshot) => ({ ...snapshot, ...splitFilePath(snapshot.key, translate) })).sort((a, b) => b.timestamp - a.timestamp);
201865
203636
  return limit === void 0 ? sorted : sorted.slice(0, Math.max(0, limit));
201866
203637
  } catch {
201867
203638
  return [];
@@ -202734,15 +204505,15 @@ function resolveProfileInitial(profile) {
202734
204505
  return trimmed ? trimmed.slice(0, 1).toUpperCase() : "?";
202735
204506
  }
202736
204507
  async function getLocalStorageUsageSummary() {
202737
- const snapshots = await listAutosaveSnapshots();
204508
+ const snapshots2 = await listAutosaveSnapshots();
202738
204509
  return {
202739
- presentationCount: snapshots.length,
202740
- totalBytes: snapshots.reduce((sum, snapshot) => sum + snapshot.size, 0)
204510
+ presentationCount: snapshots2.length,
204511
+ totalBytes: snapshots2.reduce((sum, snapshot) => sum + snapshot.size, 0)
202741
204512
  };
202742
204513
  }
202743
204514
  async function clearAllLocalViewerData() {
202744
- const snapshots = await listAutosaveSnapshots();
202745
- await Promise.all(snapshots.map((snapshot) => deleteAutosaveSnapshot(snapshot.key)));
204515
+ const snapshots2 = await listAutosaveSnapshots();
204516
+ await Promise.all(snapshots2.map((snapshot) => deleteAutosaveSnapshot(snapshot.key)));
202746
204517
  clearStoredViewerPrefs();
202747
204518
  }
202748
204519
  function saveViewerProfile(profile) {
@@ -203261,13 +205032,13 @@ function shouldDiscardAutosaveOnSuccessfulSave(options) {
203261
205032
  function shouldClearAutosaveCacheOnClose(options) {
203262
205033
  return options.save.clearCacheOnClose;
203263
205034
  }
203264
- function resolveExpiredAutosaveSnapshots(snapshots, options, now = Date.now()) {
205035
+ function resolveExpiredAutosaveSnapshots(snapshots2, options, now = Date.now()) {
203265
205036
  const days = options.save.cacheRetentionDays;
203266
205037
  if (!Number.isFinite(days) || days <= 0) {
203267
205038
  return [];
203268
205039
  }
203269
205040
  const maxAgeMs = days * 24 * 60 * 60 * 1e3;
203270
- return snapshots.filter((snapshot) => now - snapshot.timestamp > maxAgeMs).map((s) => s.key);
205041
+ return snapshots2.filter((snapshot) => now - snapshot.timestamp > maxAgeMs).map((s) => s.key);
203271
205042
  }
203272
205043
  function playFeedbackSound(options) {
203273
205044
  if (!options.accessibility.feedbackWithSound || typeof window === "undefined") {
@@ -205381,22 +207152,6 @@ function calculateViewportFit(input, defaults = DEFAULTS2) {
205381
207152
  availableHeight
205382
207153
  };
205383
207154
  }
205384
- function inlineListBodyText(segments) {
205385
- let first = true;
205386
- let text22 = "";
205387
- for (const segment of segments ?? []) {
205388
- if (isParagraphSeparatorSegment(segment)) {
205389
- text22 += "\n";
205390
- first = true;
205391
- } else {
205392
- if (!first || !isBulletMarkerSegment(segment)) {
205393
- text22 += segment.isLineBreak ? "\n" : segment.text;
205394
- }
205395
- first = false;
205396
- }
205397
- }
205398
- return text22;
205399
- }
205400
207155
  function readListActivationSelection(root, body) {
205401
207156
  if (readEditableText(root) !== body) {
205402
207157
  return void 0;
@@ -208288,6 +210043,7 @@ exports.applyTransitionSoundFile = applyTransitionSoundFile;
208288
210043
  exports.applyTransitionStockSound = applyTransitionStockSound;
208289
210044
  exports.applyUnderlineVariant = applyUnderlineVariant;
208290
210045
  exports.assertElementUpdateTarget = assertElementUpdateTarget;
210046
+ exports.attachCollaborationInlineEditor = attachCollaborationInlineEditor;
208291
210047
  exports.attachEditorImagePaste = attachEditorImagePaste;
208292
210048
  exports.attachInlineListController = attachInlineListController;
208293
210049
  exports.attachPresentationVisibilityPause = attachPresentationVisibilityPause;
@@ -208499,6 +210255,7 @@ exports.createPresentationSessionId = createPresentationSessionId;
208499
210255
  exports.createPresenterShowGuard = createPresenterShowGuard;
208500
210256
  exports.createPresenterTimer = createPresenterTimer;
208501
210257
  exports.createRotationDrag = createRotationDrag;
210258
+ exports.createSnapshotTextPositions = createSnapshotTextPositions;
208502
210259
  exports.createSyncGate = createSyncGate;
208503
210260
  exports.createTableStyleEntry = createTableStyleEntry;
208504
210261
  exports.createTouchGestureRecognizer = createTouchGestureRecognizer;
@@ -208518,6 +210275,7 @@ exports.deleteTagFromCollections = deleteTagFromCollections;
208518
210275
  exports.demote = demote;
208519
210276
  exports.deriveSlideFieldContext = deriveSlideFieldContext;
208520
210277
  exports.deriveViewportBreakpoints = deriveViewportBreakpoints;
210278
+ exports.describeCollaborationShellState = describeCollaborationShellState;
208521
210279
  exports.describeFontEmbedding = describeFontEmbedding;
208522
210280
  exports.describeSmartArtBounds = describeSmartArtBounds;
208523
210281
  exports.describeTableStyleEditor = describeTableStyleEditor;
@@ -208784,6 +210542,7 @@ exports.normalizeHexColor = normalizeHexColor2;
208784
210542
  exports.normalizeStrokeDashType = normalizeStrokeDashType;
208785
210543
  exports.normalizeTableStyleGuid = normalizeTableStyleGuid;
208786
210544
  exports.notesSegmentsToSpans = notesSegmentsToSpans;
210545
+ exports.observeElementHeight = observeElementHeight;
208787
210546
  exports.observeExternalCollaborationReadiness = observeExternalCollaborationReadiness;
208788
210547
  exports.observeExternalCollaborationSession = observeExternalCollaborationSession;
208789
210548
  exports.observeYDocSlides = observeYDocSlides;
@@ -208896,6 +210655,8 @@ exports.resolveAutosaveActivation = resolveAutosaveActivation;
208896
210655
  exports.resolveAutosaveIntervalMs = resolveAutosaveIntervalMs;
208897
210656
  exports.resolveAutosaveIntervalSeconds = resolveAutosaveIntervalSeconds;
208898
210657
  exports.resolveChartKind = resolveChartKind;
210658
+ exports.resolveCollaborationShellEditability = resolveCollaborationShellEditability;
210659
+ exports.resolveCollaborationShellState = resolveCollaborationShellState;
208899
210660
  exports.resolveConnectorEndpointUpdate = resolveConnectorEndpointUpdate;
208900
210661
  exports.resolveDefaultFontFamily = resolveDefaultFontFamily;
208901
210662
  exports.resolveDefaultPrintSettings = resolveDefaultPrintSettings;
@@ -208938,6 +210699,7 @@ exports.resolveShapeGeometry = resolveShapeGeometry;
208938
210699
  exports.resolveShowSlideIndexes = resolveShowSlideIndexes;
208939
210700
  exports.resolveSlideSizeSelection = resolveSlideSizeSelection;
208940
210701
  exports.resolveSlideTransition = resolveSlideTransition;
210702
+ exports.resolveSmartArt3DLayout = resolveSmartArt3DLayout;
208941
210703
  exports.resolveTableCellImageUrls = resolveTableCellImageUrls;
208942
210704
  exports.resolveTableStyleImageUrls = resolveTableStyleImageUrls;
208943
210705
  exports.resolveTemplateBackgroundRows = resolveTemplateBackgroundRows;