pptx-react-viewer 2.18.0 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +701 -0
  2. package/dist/{AiChatPanel-UN5DHPZY.js → AiChatPanel-2GBJETOY.js} +24 -24
  3. package/dist/AiChatPanel-2GBJETOY.js.br +0 -0
  4. package/dist/AiChatPanel-2GBJETOY.js.gz +0 -0
  5. package/dist/{AiChatPanel-SSSBERWJ.mjs → AiChatPanel-FZUKTQPQ.mjs} +4 -4
  6. package/dist/AiChatPanel-FZUKTQPQ.mjs.br +0 -0
  7. package/dist/AiChatPanel-FZUKTQPQ.mjs.gz +0 -0
  8. package/dist/{Model3DScene-4RPYKC2I.js → Model3DScene-JHTI2AQ6.js} +2 -2
  9. package/dist/Model3DScene-JHTI2AQ6.js.br +0 -0
  10. package/dist/Model3DScene-JHTI2AQ6.js.gz +0 -0
  11. package/dist/{Model3DScene-LYEESYAI.mjs → Model3DScene-WRRQSYAZ.mjs} +1 -1
  12. package/dist/Model3DScene-WRRQSYAZ.mjs.br +0 -0
  13. package/dist/Model3DScene-WRRQSYAZ.mjs.gz +0 -0
  14. package/dist/{PowerPointViewer-Cf4YHjdF.d.ts → PowerPointViewer-DVFkeluD.d.ts} +2 -2
  15. package/dist/PowerPointViewer-DVFkeluD.d.ts.map +1 -0
  16. package/dist/{audience-content-store-CyS0oP6t.d.ts → audience-content-store-ChVOSdBh.d.ts} +2 -2
  17. package/dist/{audience-content-store-CyS0oP6t.d.ts.map → audience-content-store-ChVOSdBh.d.ts.map} +1 -1
  18. package/dist/{chunk-WVDM36ZM.js → chunk-7ARD2J6Y.js} +1096 -1033
  19. package/dist/chunk-7ARD2J6Y.js.br +0 -0
  20. package/dist/chunk-7ARD2J6Y.js.gz +0 -0
  21. package/dist/{chunk-QUB5OSKY.mjs → chunk-BO373PYH.mjs} +70 -115
  22. package/dist/chunk-BO373PYH.mjs.br +0 -0
  23. package/dist/chunk-BO373PYH.mjs.gz +0 -0
  24. package/dist/{chunk-ASKYZ5ZY.js → chunk-IRLOXBO7.js} +439 -484
  25. package/dist/chunk-IRLOXBO7.js.br +0 -0
  26. package/dist/chunk-IRLOXBO7.js.gz +0 -0
  27. package/dist/{chunk-RTUGI4HQ.js → chunk-MVKRI3CZ.js} +9 -0
  28. package/dist/chunk-MVKRI3CZ.js.br +0 -0
  29. package/dist/chunk-MVKRI3CZ.js.gz +0 -0
  30. package/dist/{chunk-BZOL6FXF.mjs → chunk-MWEBCWVD.mjs} +16 -2270
  31. package/dist/chunk-MWEBCWVD.mjs.br +0 -0
  32. package/dist/chunk-MWEBCWVD.mjs.gz +0 -0
  33. package/dist/{chunk-ICZDMFF2.js → chunk-NFFV3RDS.js} +1219 -1101
  34. package/dist/chunk-NFFV3RDS.js.br +0 -0
  35. package/dist/chunk-NFFV3RDS.js.gz +0 -0
  36. package/dist/{chunk-4LWGAVAP.js → chunk-OVPJT4EQ.js} +162 -2416
  37. package/dist/chunk-OVPJT4EQ.js.br +0 -0
  38. package/dist/chunk-OVPJT4EQ.js.gz +0 -0
  39. package/dist/{chunk-MAVLV56S.js → chunk-RPJ2BIQ7.js} +3 -3
  40. package/dist/chunk-RPJ2BIQ7.js.br +0 -0
  41. package/dist/chunk-RPJ2BIQ7.js.gz +0 -0
  42. package/dist/{chunk-SNL6LBRX.mjs → chunk-SQJBFMEX.mjs} +9 -0
  43. package/dist/chunk-SQJBFMEX.mjs.br +0 -0
  44. package/dist/chunk-SQJBFMEX.mjs.gz +0 -0
  45. package/dist/{chunk-GODW6RNR.mjs → chunk-XF3EOHY2.mjs} +1087 -1017
  46. package/dist/chunk-XF3EOHY2.mjs.br +0 -0
  47. package/dist/chunk-XF3EOHY2.mjs.gz +0 -0
  48. package/dist/{chunk-O7FTUUXP.mjs → chunk-YWJBD7KV.mjs} +210 -92
  49. package/dist/chunk-YWJBD7KV.mjs.br +0 -0
  50. package/dist/chunk-YWJBD7KV.mjs.gz +0 -0
  51. package/dist/{chunk-7XF6S4AM.mjs → chunk-ZMEYXAC6.mjs} +1 -1
  52. package/dist/chunk-ZMEYXAC6.mjs.br +0 -0
  53. package/dist/{chunk-7XF6S4AM.mjs.gz → chunk-ZMEYXAC6.mjs.gz} +0 -0
  54. package/dist/i18n.js +4 -4
  55. package/dist/i18n.js.br +0 -0
  56. package/dist/i18n.js.gz +0 -0
  57. package/dist/i18n.mjs +1 -1
  58. package/dist/i18n.mjs.br +0 -0
  59. package/dist/i18n.mjs.gz +0 -0
  60. package/dist/index.d.ts +38 -1
  61. package/dist/index.js +47 -47
  62. package/dist/index.js.br +0 -0
  63. package/dist/index.js.gz +0 -0
  64. package/dist/index.mjs +6 -6
  65. package/dist/index.mjs.br +0 -0
  66. package/dist/index.mjs.gz +0 -0
  67. package/dist/internals.d.ts +102 -15
  68. package/dist/internals.d.ts.map +1 -1
  69. package/dist/internals.js +79 -79
  70. package/dist/internals.js.br +0 -0
  71. package/dist/internals.js.gz +0 -0
  72. package/dist/internals.mjs +4 -4
  73. package/dist/internals.mjs.br +0 -0
  74. package/dist/internals.mjs.gz +0 -0
  75. package/dist/{types-C_CTI-QE.d.ts → types-TCH6icpi.d.ts} +23 -1
  76. package/dist/{types-C_CTI-QE.d.ts.map → types-TCH6icpi.d.ts.map} +1 -1
  77. package/dist/{useViewerBuildingBlocks-DItilDbP.d.ts → useViewerBuildingBlocks-BKb0qs1j.d.ts} +20 -4
  78. package/dist/{useViewerBuildingBlocks-DItilDbP.d.ts.map → useViewerBuildingBlocks-BKb0qs1j.d.ts.map} +1 -1
  79. package/dist/viewer/index.d.ts +38 -1
  80. package/dist/viewer/index.js +27 -27
  81. package/dist/viewer/index.js.br +0 -0
  82. package/dist/viewer/index.js.gz +0 -0
  83. package/dist/viewer/index.mjs +6 -6
  84. package/dist/viewer/index.mjs.br +0 -0
  85. package/dist/viewer/index.mjs.gz +0 -0
  86. package/package.json +1 -1
  87. package/dist/AiChatPanel-SSSBERWJ.mjs.br +0 -0
  88. package/dist/AiChatPanel-SSSBERWJ.mjs.gz +0 -0
  89. package/dist/AiChatPanel-UN5DHPZY.js.br +0 -0
  90. package/dist/AiChatPanel-UN5DHPZY.js.gz +0 -0
  91. package/dist/Model3DScene-4RPYKC2I.js.br +0 -0
  92. package/dist/Model3DScene-4RPYKC2I.js.gz +0 -0
  93. package/dist/Model3DScene-LYEESYAI.mjs.br +0 -0
  94. package/dist/Model3DScene-LYEESYAI.mjs.gz +0 -0
  95. package/dist/PowerPointViewer-Cf4YHjdF.d.ts.map +0 -1
  96. package/dist/SurfaceChart3DScene-ACPKCWLJ.js +0 -78
  97. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.br +0 -0
  98. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.gz +0 -0
  99. package/dist/SurfaceChart3DScene-JR62SOYO.mjs +0 -76
  100. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.br +0 -0
  101. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.gz +0 -0
  102. package/dist/chunk-4LWGAVAP.js.br +0 -0
  103. package/dist/chunk-4LWGAVAP.js.gz +0 -0
  104. package/dist/chunk-7XF6S4AM.mjs.br +0 -0
  105. package/dist/chunk-ASKYZ5ZY.js.br +0 -0
  106. package/dist/chunk-ASKYZ5ZY.js.gz +0 -0
  107. package/dist/chunk-BZOL6FXF.mjs.br +0 -0
  108. package/dist/chunk-BZOL6FXF.mjs.gz +0 -0
  109. package/dist/chunk-GODW6RNR.mjs.br +0 -0
  110. package/dist/chunk-GODW6RNR.mjs.gz +0 -0
  111. package/dist/chunk-ICZDMFF2.js.br +0 -0
  112. package/dist/chunk-ICZDMFF2.js.gz +0 -0
  113. package/dist/chunk-MAVLV56S.js.br +0 -0
  114. package/dist/chunk-MAVLV56S.js.gz +0 -0
  115. package/dist/chunk-O7FTUUXP.mjs.br +0 -0
  116. package/dist/chunk-O7FTUUXP.mjs.gz +0 -0
  117. package/dist/chunk-QUB5OSKY.mjs.br +0 -0
  118. package/dist/chunk-QUB5OSKY.mjs.gz +0 -0
  119. package/dist/chunk-RTUGI4HQ.js.br +0 -0
  120. package/dist/chunk-RTUGI4HQ.js.gz +0 -0
  121. package/dist/chunk-SNL6LBRX.mjs.br +0 -0
  122. package/dist/chunk-SNL6LBRX.mjs.gz +0 -0
  123. package/dist/chunk-WVDM36ZM.js.br +0 -0
  124. package/dist/chunk-WVDM36ZM.js.gz +0 -0
@@ -21501,6 +21501,25 @@ function hasDrawingChild(node, requestedName) {
21501
21501
  }
21502
21502
  return false;
21503
21503
  }
21504
+ function hasEmptyDrawingChild(node, requestedName) {
21505
+ if (!node) {
21506
+ return false;
21507
+ }
21508
+ for (const [key2, value] of Object.entries(node)) {
21509
+ if (key2.startsWith(ATTRIBUTE_PREFIX) || key2 === "#text") {
21510
+ continue;
21511
+ }
21512
+ if (key2.split(":").at(-1) !== requestedName) {
21513
+ continue;
21514
+ }
21515
+ const child222 = Array.isArray(value) ? value[0] : value;
21516
+ if (child222 === "" || child222 === void 0) {
21517
+ return true;
21518
+ }
21519
+ return typeof child222 === "object" && !Array.isArray(child222) && Object.keys(child222).every((childKey3) => childKey3.startsWith(ATTRIBUTE_PREFIX));
21520
+ }
21521
+ return false;
21522
+ }
21504
21523
  function drawingChildren(node, requestedName) {
21505
21524
  if (!node) {
21506
21525
  return [];
@@ -25255,6 +25274,141 @@ function reconcileSmartArtTextParagraphs(paragraphs, desired) {
25255
25274
  insertAt(result, prefix, desired.slice(prefix, desired.length - suffix));
25256
25275
  return result.length > 0 ? result : [{ items: [] }];
25257
25276
  }
25277
+ var ATTR_PREFIX = "@_";
25278
+ var TEXT_KEY = "#text";
25279
+ function isXmlObject2(value) {
25280
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25281
+ }
25282
+ function coerceString(value) {
25283
+ if (typeof value === "string") {
25284
+ return value;
25285
+ }
25286
+ if (typeof value === "number" || typeof value === "boolean") {
25287
+ return String(value);
25288
+ }
25289
+ return void 0;
25290
+ }
25291
+ function xmlChild(node, key2) {
25292
+ if (!isXmlObject2(node)) {
25293
+ return void 0;
25294
+ }
25295
+ const value = node[key2];
25296
+ if (Array.isArray(value)) {
25297
+ const first = value[0];
25298
+ return isXmlObject2(first) ? first : void 0;
25299
+ }
25300
+ return isXmlObject2(value) ? value : void 0;
25301
+ }
25302
+ function xmlChildren(node, key2) {
25303
+ if (!isXmlObject2(node)) {
25304
+ return [];
25305
+ }
25306
+ const value = node[key2];
25307
+ if (value === void 0 || value === null) {
25308
+ return [];
25309
+ }
25310
+ if (Array.isArray(value)) {
25311
+ return value.filter(isXmlObject2);
25312
+ }
25313
+ return isXmlObject2(value) ? [value] : [];
25314
+ }
25315
+ function xmlHasChild(node, key2) {
25316
+ return isXmlObject2(node) && Object.hasOwn(node, key2);
25317
+ }
25318
+ function ensureXmlChild(parent, key2) {
25319
+ if (!isXmlObject2(parent) || !Object.hasOwn(parent, key2)) {
25320
+ return void 0;
25321
+ }
25322
+ const existing = parent[key2];
25323
+ if (isXmlObject2(existing)) {
25324
+ return existing;
25325
+ }
25326
+ if (Array.isArray(existing)) {
25327
+ const first = existing[0];
25328
+ return isXmlObject2(first) ? first : void 0;
25329
+ }
25330
+ if (existing === "" || existing === void 0 || existing === null) {
25331
+ const created = {};
25332
+ parent[key2] = created;
25333
+ return created;
25334
+ }
25335
+ return void 0;
25336
+ }
25337
+ function ensureXmlChildren(parent, key2) {
25338
+ if (!Object.hasOwn(parent, key2)) {
25339
+ return [];
25340
+ }
25341
+ const value = parent[key2];
25342
+ if (!Array.isArray(value)) {
25343
+ const single = ensureXmlChild(parent, key2);
25344
+ return single ? [single] : [];
25345
+ }
25346
+ const healed = [];
25347
+ for (const [index, entry2] of value.entries()) {
25348
+ if (isXmlObject2(entry2)) {
25349
+ healed.push(entry2);
25350
+ continue;
25351
+ }
25352
+ const created = {};
25353
+ value[index] = created;
25354
+ healed.push(created);
25355
+ }
25356
+ return healed;
25357
+ }
25358
+ function ensureXmlChildOrCreate(parent, key2, position2 = "last") {
25359
+ const existing = ensureXmlChild(parent, key2);
25360
+ if (existing) {
25361
+ return existing;
25362
+ }
25363
+ const created = {};
25364
+ if (position2 === "last") {
25365
+ parent[key2] = created;
25366
+ return created;
25367
+ }
25368
+ const carried = { ...parent };
25369
+ for (const existingKey of Object.keys(parent)) {
25370
+ delete parent[existingKey];
25371
+ }
25372
+ parent[key2] = created;
25373
+ Object.assign(parent, carried);
25374
+ return created;
25375
+ }
25376
+ function xmlAttr(node, name) {
25377
+ if (!isXmlObject2(node)) {
25378
+ return void 0;
25379
+ }
25380
+ return coerceString(node[ATTR_PREFIX + name]);
25381
+ }
25382
+ function xmlAttrNumber(node, name) {
25383
+ const raw = xmlAttr(node, name);
25384
+ if (raw === void 0) {
25385
+ return void 0;
25386
+ }
25387
+ const parsed = Number(raw);
25388
+ return Number.isFinite(parsed) ? parsed : void 0;
25389
+ }
25390
+ function xmlText(node) {
25391
+ if (typeof node === "string") {
25392
+ return node;
25393
+ }
25394
+ if (!isXmlObject2(node)) {
25395
+ return void 0;
25396
+ }
25397
+ return coerceString(node[TEXT_KEY]);
25398
+ }
25399
+ function xmlPath(node, ...keys) {
25400
+ let current = isXmlObject2(node) ? node : void 0;
25401
+ for (const key2 of keys) {
25402
+ if (!current) {
25403
+ return void 0;
25404
+ }
25405
+ current = xmlChild(current, key2);
25406
+ }
25407
+ return current;
25408
+ }
25409
+ function isXmlNode(value) {
25410
+ return isXmlObject2(value);
25411
+ }
25258
25412
  var EMU_PER_PX2 = 9525;
25259
25413
  function parseBoolAttr2(value) {
25260
25414
  if (value === void 0 || value === null) {
@@ -25417,7 +25571,7 @@ function parseBulletInfo(pPr, paragraphIndex = 0) {
25417
25571
  if (!pPr) {
25418
25572
  return null;
25419
25573
  }
25420
- if (pPr["a:buNone"]) {
25574
+ if (xmlHasChild(pPr, "a:buNone")) {
25421
25575
  return { none: true };
25422
25576
  }
25423
25577
  const buFont = pPr["a:buFont"];
@@ -34415,83 +34569,6 @@ function resolveLayoutDisplayName(input) {
34415
34569
  }
34416
34570
  return fallbackFromPath(input.path);
34417
34571
  }
34418
- var ATTR_PREFIX = "@_";
34419
- var TEXT_KEY = "#text";
34420
- function isXmlObject2(value) {
34421
- return typeof value === "object" && value !== null && !Array.isArray(value);
34422
- }
34423
- function coerceString(value) {
34424
- if (typeof value === "string") {
34425
- return value;
34426
- }
34427
- if (typeof value === "number" || typeof value === "boolean") {
34428
- return String(value);
34429
- }
34430
- return void 0;
34431
- }
34432
- function xmlChild(node, key2) {
34433
- if (!isXmlObject2(node)) {
34434
- return void 0;
34435
- }
34436
- const value = node[key2];
34437
- if (Array.isArray(value)) {
34438
- const first = value[0];
34439
- return isXmlObject2(first) ? first : void 0;
34440
- }
34441
- return isXmlObject2(value) ? value : void 0;
34442
- }
34443
- function xmlChildren(node, key2) {
34444
- if (!isXmlObject2(node)) {
34445
- return [];
34446
- }
34447
- const value = node[key2];
34448
- if (value === void 0 || value === null) {
34449
- return [];
34450
- }
34451
- if (Array.isArray(value)) {
34452
- return value.filter(isXmlObject2);
34453
- }
34454
- return isXmlObject2(value) ? [value] : [];
34455
- }
34456
- function xmlHasChild(node, key2) {
34457
- return isXmlObject2(node) && Object.hasOwn(node, key2);
34458
- }
34459
- function xmlAttr(node, name) {
34460
- if (!isXmlObject2(node)) {
34461
- return void 0;
34462
- }
34463
- return coerceString(node[ATTR_PREFIX + name]);
34464
- }
34465
- function xmlAttrNumber(node, name) {
34466
- const raw = xmlAttr(node, name);
34467
- if (raw === void 0) {
34468
- return void 0;
34469
- }
34470
- const parsed = Number(raw);
34471
- return Number.isFinite(parsed) ? parsed : void 0;
34472
- }
34473
- function xmlText(node) {
34474
- if (typeof node === "string") {
34475
- return node;
34476
- }
34477
- if (!isXmlObject2(node)) {
34478
- return void 0;
34479
- }
34480
- return coerceString(node[TEXT_KEY]);
34481
- }
34482
- function xmlPath(node, ...keys) {
34483
- let current = isXmlObject2(node) ? node : void 0;
34484
- for (const key2 of keys) {
34485
- if (!current) {
34486
- return void 0;
34487
- }
34488
- current = xmlChild(current, key2);
34489
- }
34490
- return current;
34491
- }
34492
- function isXmlNode(value) {
34493
- return isXmlObject2(value);
34494
- }
34495
34572
  var ORDER2 = [
34496
34573
  "varyColors",
34497
34574
  "ser",
@@ -36325,7 +36402,16 @@ var PptxShapeStyleExtractor = class {
36325
36402
  Object.assign(style, this.context.extractBlurStyle(shapeProps));
36326
36403
  Object.assign(style, this.context.extractEffectDagStyle(shapeProps));
36327
36404
  if (styleNode?.["a:effectRef"]) {
36405
+ const suppressInherited = hasEmptyDrawingChild(shapeProps, "effectLst");
36406
+ const authored = suppressInherited ? new Set(Object.keys(style)) : void 0;
36328
36407
  this.context.resolveThemeEffectRef(styleNode["a:effectRef"], style);
36408
+ if (authored) {
36409
+ for (const key2 of Object.keys(style)) {
36410
+ if (!authored.has(key2) && key2 !== "effectRefIdx" && key2 !== "effectRefColorXml") {
36411
+ delete style[key2];
36412
+ }
36413
+ }
36414
+ }
36329
36415
  }
36330
36416
  const fontRef = styleNode?.["a:fontRef"];
36331
36417
  if (fontRef) {
@@ -37295,6 +37381,150 @@ var PptxMediaDataParser = class {
37295
37381
  return mimeMap[extension];
37296
37382
  }
37297
37383
  };
37384
+ var LOCK_ATTRIBUTE = {
37385
+ noGrouping: "@_noGrp",
37386
+ noRotation: "@_noRot",
37387
+ noMove: "@_noMove",
37388
+ noResize: "@_noResize",
37389
+ noTextEdit: "@_noTextEdit",
37390
+ noSelect: "@_noSelect",
37391
+ noChangeAspect: "@_noChangeAspect",
37392
+ noEditPoints: "@_noEditPoints",
37393
+ noAdjustHandles: "@_noAdjustHandles",
37394
+ noChangeArrowheads: "@_noChangeArrowheads",
37395
+ noChangeShapeType: "@_noChangeShapeType",
37396
+ noDrilldown: "@_noDrilldown"
37397
+ };
37398
+ var AG_LOCKING = [
37399
+ "noGrouping",
37400
+ "noSelect",
37401
+ "noRotation",
37402
+ "noChangeAspect",
37403
+ "noMove",
37404
+ "noResize",
37405
+ "noEditPoints",
37406
+ "noAdjustHandles",
37407
+ "noChangeArrowheads",
37408
+ "noChangeShapeType"
37409
+ ];
37410
+ var SHAPE_LOCK_CONTAINERS = {
37411
+ "p:sp": {
37412
+ nvKey: "p:nvSpPr",
37413
+ cNvKey: "p:cNvSpPr",
37414
+ lockTag: "a:spLocks",
37415
+ permitted: [...AG_LOCKING, "noTextEdit"]
37416
+ },
37417
+ "p:pic": {
37418
+ nvKey: "p:nvPicPr",
37419
+ cNvKey: "p:cNvPicPr",
37420
+ lockTag: "a:picLocks",
37421
+ permitted: AG_LOCKING
37422
+ },
37423
+ "p:cxnSp": {
37424
+ nvKey: "p:nvCxnSpPr",
37425
+ cNvKey: "p:cNvCxnSpPr",
37426
+ lockTag: "a:cxnSpLocks",
37427
+ permitted: AG_LOCKING
37428
+ },
37429
+ "p:grpSp": {
37430
+ nvKey: "p:nvGrpSpPr",
37431
+ cNvKey: "p:cNvGrpSpPr",
37432
+ lockTag: "a:grpSpLocks",
37433
+ // CT_GroupLocking omits the shape-editing half of AG_Locking; `@noUngrp`
37434
+ // is its own addition and has no model property, so it survives as a
37435
+ // carried-over attribute rather than being written from the model.
37436
+ permitted: ["noGrouping", "noSelect", "noRotation", "noChangeAspect", "noMove", "noResize"]
37437
+ },
37438
+ "p:graphicFrame": {
37439
+ nvKey: "p:nvGraphicFramePr",
37440
+ cNvKey: "p:cNvGraphicFramePr",
37441
+ lockTag: "a:graphicFrameLocks",
37442
+ // `CT_GraphicalObjectFrameLocking` is NOT `AG_Locking`: it has no
37443
+ // `@noRot`, no `@noTextEdit` and none of the geometry-editing flags, and
37444
+ // it is the only type that declares `@noDrilldown`. Aliasing it onto the
37445
+ // shape list would emit five attributes the schema rejects.
37446
+ permitted: ["noGrouping", "noDrilldown", "noSelect", "noChangeAspect", "noMove", "noResize"]
37447
+ }
37448
+ };
37449
+ function resolveShapeLockContainer(shape, bucketKey) {
37450
+ if (shape) {
37451
+ for (const spec2 of Object.values(SHAPE_LOCK_CONTAINERS)) {
37452
+ if (asNode(shape[spec2.nvKey])) {
37453
+ return spec2;
37454
+ }
37455
+ }
37456
+ }
37457
+ return SHAPE_LOCK_CONTAINERS[bucketKey];
37458
+ }
37459
+ function asNode(value) {
37460
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
37461
+ }
37462
+ function parseShapeLocksFromNode(shape, spec2) {
37463
+ const nv = asNode(shape?.[spec2.nvKey]);
37464
+ const container = asNode(nv?.[spec2.cNvKey]);
37465
+ return parseShapeLockNode(asNode(container?.[spec2.lockTag]), spec2);
37466
+ }
37467
+ function resolveLockContainerNode(shape, spec2, create) {
37468
+ const nv = asNode(shape[spec2.nvKey]);
37469
+ if (!nv) {
37470
+ return void 0;
37471
+ }
37472
+ const existing = asNode(nv[spec2.cNvKey]);
37473
+ if (existing || !create) {
37474
+ return existing;
37475
+ }
37476
+ const created = {};
37477
+ const rebuilt = {};
37478
+ if ("p:cNvPr" in nv) {
37479
+ rebuilt["p:cNvPr"] = nv["p:cNvPr"];
37480
+ }
37481
+ rebuilt[spec2.cNvKey] = created;
37482
+ for (const [key2, value] of Object.entries(nv)) {
37483
+ if (key2 !== "p:cNvPr" && key2 !== spec2.cNvKey) {
37484
+ rebuilt[key2] = value;
37485
+ }
37486
+ }
37487
+ for (const key2 of Object.keys(nv)) {
37488
+ delete nv[key2];
37489
+ }
37490
+ Object.assign(nv, rebuilt);
37491
+ return created;
37492
+ }
37493
+ var MODELLED_ATTRIBUTES = new Set(Object.values(LOCK_ATTRIBUTE));
37494
+ function buildShapeLockNode(locks, spec2, existing) {
37495
+ const node = {};
37496
+ for (const [key2, value] of Object.entries(existing ?? {})) {
37497
+ if (!MODELLED_ATTRIBUTES.has(key2)) {
37498
+ node[key2] = value;
37499
+ }
37500
+ }
37501
+ if (locks) {
37502
+ for (const prop of spec2.permitted) {
37503
+ const value = locks[prop];
37504
+ if (value !== void 0) {
37505
+ node[LOCK_ATTRIBUTE[prop]] = value ? "1" : "0";
37506
+ }
37507
+ }
37508
+ }
37509
+ return Object.keys(node).length > 0 ? node : void 0;
37510
+ }
37511
+ function parseShapeLockNode(node, spec2) {
37512
+ if (!node) {
37513
+ return void 0;
37514
+ }
37515
+ const locks = {};
37516
+ let hasAny = false;
37517
+ for (const prop of spec2.permitted) {
37518
+ const raw = node[LOCK_ATTRIBUTE[prop]];
37519
+ if (raw === void 0) {
37520
+ continue;
37521
+ }
37522
+ const value = String(raw).trim().toLowerCase();
37523
+ locks[prop] = value === "1" || value === "true";
37524
+ hasAny = true;
37525
+ }
37526
+ return hasAny ? locks : void 0;
37527
+ }
37298
37528
  var KNOWN_GRAPHIC_FRAME_EXT_URIS = /* @__PURE__ */ new Set([
37299
37529
  // Office 365+ 3D model envelope; handled by parseModel3DElement.
37300
37530
  "{D42C27E5-1956-4C4D-AC15-FE9D03D7D63E}"
@@ -37540,7 +37770,15 @@ var PptxGraphicFrameParser = class {
37540
37770
  skewY: transform?.["@_skewY"] ? parseInt(String(transform["@_skewY"]), 10) / 6e4 : void 0,
37541
37771
  flipHorizontal,
37542
37772
  flipVertical,
37543
- rawXml: frame2
37773
+ rawXml: frame2,
37774
+ // `a:graphicFrameLocks` is the lock element for every family that
37775
+ // round-trips as a graphic frame (table, chart, SmartArt, OLE
37776
+ // object, graphic-frame media, loaded ink). Reading it is what
37777
+ // makes the writer safe: `serializeShapeLocks` rebuilds the node
37778
+ // from `element.locks` and treats an absent bag as "the user
37779
+ // cleared the locks", so a lock that is never parsed would be
37780
+ // erased on the first save.
37781
+ locks: parseShapeLocksFromNode(frame2, SHAPE_LOCK_CONTAINERS["p:graphicFrame"])
37544
37782
  };
37545
37783
  const extensionXml = collectGraphicFrameExtensions(graphicData);
37546
37784
  if (type === "table" && graphicData) {
@@ -44000,6 +44238,7 @@ function annotateOmmlSiblingOrder(xml, parsed) {
44000
44238
  }
44001
44239
  }
44002
44240
  }
44241
+ var MAX_XML_NESTING_DEPTH = 256;
44003
44242
  var PptxRuntimeDependencyFactory = class {
44004
44243
  createParser() {
44005
44244
  const parser = new fastXmlParser.XMLParser({
@@ -44065,7 +44304,26 @@ var PptxRuntimeDependencyFactory = class {
44065
44304
  // (`p:cNvPr/@name`), alt text (`@descr`) and layout names
44066
44305
  // (`p:cSld/@name`), which are read from the MODEL, so under-decoding is
44067
44306
  // user-visible even without a save.
44068
- attributeValueProcessor: (_attrName, attrValue) => decodeXmlEntities(attrValue)
44307
+ attributeValueProcessor: (_attrName, attrValue) => decodeXmlEntities(attrValue),
44308
+ // See MAX_XML_NESTING_DEPTH. The parser rejects when the open-tag stack
44309
+ // is STRICTLY greater than this, so it tolerates a part one element
44310
+ // deeper than the number given; the builder is compensated below so the
44311
+ // two ceilings land on the same part.
44312
+ maxNestedTags: MAX_XML_NESTING_DEPTH
44313
+ // XML comments stay DROPPED (`commentPropName` left at its `false`
44314
+ // default), deliberately. Scanning every part of all 45 committed decks
44315
+ // found ZERO comments, in slides, rels and `[Content_Types].xml` alike,
44316
+ // so nothing we have is losing anything. Turning it on would not be
44317
+ // free or even faithful: fast-xml-parser stores a comment as a
44318
+ // `#comment` KEY on its parent, which (a) injects a key the ~50 runtime
44319
+ // mixins that enumerate `Object.keys(spTree)` have never seen, and (b)
44320
+ // groups by tag like every other key, so `<!--A--><p:sp/><!--B--><p:sp/>`
44321
+ // rebuilds as `<!--A--><!--B--><p:sp/><p:sp/>` - the same interleaved-
44322
+ // sibling collapse that has already cost this repo four separate order
44323
+ // annotators (custGeom, OMML, SmartArt text, a:fld/a:br). An XML comment
44324
+ // carries no schema meaning, so the choice is between dropping one and
44325
+ // relocating it, and dropping is the honest half. Parts we do not parse
44326
+ // keep their comments regardless: they are copied through byte for byte.
44069
44327
  });
44070
44328
  const parse = parser.parse.bind(parser);
44071
44329
  parser.parse = ((xml, validationOption) => {
@@ -44130,7 +44388,21 @@ var PptxRuntimeDependencyFactory = class {
44130
44388
  // `\r`, and `encodeXmlAttributeValue` applies the attribute rules.
44131
44389
  processEntities: false,
44132
44390
  tagValueProcessor: (_tagName, tagValue) => encodeXmlTextValue(String(tagValue)),
44133
- attributeValueProcessor: (_attrName, attrValue) => encodeXmlAttributeValue(String(attrValue))
44391
+ attributeValueProcessor: (_attrName, attrValue) => encodeXmlAttributeValue(String(attrValue)),
44392
+ // See MAX_XML_NESTING_DEPTH. The doubling makes the PARSER the single
44393
+ // gatekeeper: whatever it let into the model, the builder can write back.
44394
+ // Matching the two numbers exactly does not achieve that, because the
44395
+ // builder measures a different thing. It walks the parsed OBJECT, where
44396
+ // repeated siblings sit under an extra array level and our own
44397
+ // order-annotation keys (`#pptx-order-N`, custGeom / OMML / SmartArt /
44398
+ // paragraph) add levels the source XML never had, so its depth runs 1-2
44399
+ // above the parser's for the same part and drifts with what the
44400
+ // annotators do. Deriving that offset would mean pinning two libraries'
44401
+ // internals plus our annotators; a margin no realistic accounting
44402
+ // difference can cross is both simpler and stabler, and the builder
44403
+ // still keeps a bound of its own for models built programmatically
44404
+ // rather than parsed. The round-trip test asserts the property directly.
44405
+ maxNestedTags: MAX_XML_NESTING_DEPTH * 2
44134
44406
  });
44135
44407
  const build = builder2.build.bind(builder2);
44136
44408
  builder2.build = ((value) => stripXmlOrderMarkers(build(value)));
@@ -54158,95 +54430,6 @@ var PptxHandlerRuntime2 = class _PptxHandlerRuntime extends PptxHandlerRuntime {
54158
54430
  }
54159
54431
  }
54160
54432
  };
54161
- var LOCK_ATTRIBUTE = {
54162
- noGrouping: "@_noGrp",
54163
- noRotation: "@_noRot",
54164
- noMove: "@_noMove",
54165
- noResize: "@_noResize",
54166
- noTextEdit: "@_noTextEdit",
54167
- noSelect: "@_noSelect",
54168
- noChangeAspect: "@_noChangeAspect",
54169
- noEditPoints: "@_noEditPoints",
54170
- noAdjustHandles: "@_noAdjustHandles",
54171
- noChangeArrowheads: "@_noChangeArrowheads",
54172
- noChangeShapeType: "@_noChangeShapeType"
54173
- };
54174
- var AG_LOCKING = [
54175
- "noGrouping",
54176
- "noSelect",
54177
- "noRotation",
54178
- "noChangeAspect",
54179
- "noMove",
54180
- "noResize",
54181
- "noEditPoints",
54182
- "noAdjustHandles",
54183
- "noChangeArrowheads",
54184
- "noChangeShapeType"
54185
- ];
54186
- var SHAPE_LOCK_CONTAINERS = {
54187
- "p:sp": {
54188
- nvKey: "p:nvSpPr",
54189
- cNvKey: "p:cNvSpPr",
54190
- lockTag: "a:spLocks",
54191
- permitted: [...AG_LOCKING, "noTextEdit"]
54192
- },
54193
- "p:pic": {
54194
- nvKey: "p:nvPicPr",
54195
- cNvKey: "p:cNvPicPr",
54196
- lockTag: "a:picLocks",
54197
- permitted: AG_LOCKING
54198
- },
54199
- "p:cxnSp": {
54200
- nvKey: "p:nvCxnSpPr",
54201
- cNvKey: "p:cNvCxnSpPr",
54202
- lockTag: "a:cxnSpLocks",
54203
- permitted: AG_LOCKING
54204
- },
54205
- "p:grpSp": {
54206
- nvKey: "p:nvGrpSpPr",
54207
- cNvKey: "p:cNvGrpSpPr",
54208
- lockTag: "a:grpSpLocks",
54209
- // CT_GroupLocking omits the shape-editing half of AG_Locking; `@noUngrp`
54210
- // is its own addition and has no model property, so it survives as a
54211
- // carried-over attribute rather than being written from the model.
54212
- permitted: ["noGrouping", "noSelect", "noRotation", "noChangeAspect", "noMove", "noResize"]
54213
- }
54214
- };
54215
- var MODELLED_ATTRIBUTES = new Set(Object.values(LOCK_ATTRIBUTE));
54216
- function buildShapeLockNode(locks, spec2, existing) {
54217
- const node = {};
54218
- for (const [key2, value] of Object.entries(existing ?? {})) {
54219
- if (!MODELLED_ATTRIBUTES.has(key2)) {
54220
- node[key2] = value;
54221
- }
54222
- }
54223
- if (locks) {
54224
- for (const prop of spec2.permitted) {
54225
- const value = locks[prop];
54226
- if (value !== void 0) {
54227
- node[LOCK_ATTRIBUTE[prop]] = value ? "1" : "0";
54228
- }
54229
- }
54230
- }
54231
- return Object.keys(node).length > 0 ? node : void 0;
54232
- }
54233
- function parseShapeLockNode(node, spec2) {
54234
- if (!node) {
54235
- return void 0;
54236
- }
54237
- const locks = {};
54238
- let hasAny = false;
54239
- for (const prop of spec2.permitted) {
54240
- const raw = node[LOCK_ATTRIBUTE[prop]];
54241
- if (raw === void 0) {
54242
- continue;
54243
- }
54244
- const value = String(raw).trim().toLowerCase();
54245
- locks[prop] = value === "1" || value === "true";
54246
- hasAny = true;
54247
- }
54248
- return hasAny ? locks : void 0;
54249
- }
54250
54433
  var PptxHandlerRuntime3 = class extends PptxHandlerRuntime2 {
54251
54434
  /**
54252
54435
  * Write or remove a single `a:hlinkClick` / `a:hlinkHover` node on
@@ -54307,20 +54490,26 @@ var PptxHandlerRuntime3 = class extends PptxHandlerRuntime2 {
54307
54490
  }
54308
54491
  return "p:sp";
54309
54492
  }
54493
+ /**
54494
+ * The `p:cNvPr` an element's hyperlinks hang on.
54495
+ *
54496
+ * Resolved from the MARKUP, not from `el.type`, for exactly the reason
54497
+ * {@link resolveShapeLockContainer} documents: the two disagree in real
54498
+ * files. `media` buckets as `p:graphicFrame`, but PowerPoint writes a video
54499
+ * as a `p:pic`, so looking for `p:nvGraphicFramePr` found nothing and the
54500
+ * writer returned early - a hyperlink or an action on a video or an audio
54501
+ * clip was accepted by the editor and then never reached the saved file.
54502
+ * Loaded ink is the mirror image: it buckets as `p:sp` and arrives as a
54503
+ * graphic frame or a `p:contentPart`. This is the unfixed sibling of the
54504
+ * lock-container bug, and it shares the fix rather than restating it.
54505
+ */
54310
54506
  getCnvPrNode(shape, key2) {
54311
- if (key2 === "p:pic") {
54312
- return xmlPath(shape, "p:nvPicPr", "p:cNvPr");
54313
- }
54314
- if (key2 === "p:cxnSp") {
54315
- return xmlPath(shape, "p:nvCxnSpPr", "p:cNvPr");
54316
- }
54317
- if (key2 === "p:graphicFrame") {
54318
- return xmlPath(shape, "p:nvGraphicFramePr", "p:cNvPr");
54319
- }
54320
- if (key2 === "p:grpSp") {
54321
- return xmlPath(shape, "p:nvGrpSpPr", "p:cNvPr");
54507
+ const contentPart = xmlPath(shape, "p:nvContentPartPr", "p:cNvPr");
54508
+ if (contentPart) {
54509
+ return contentPart;
54322
54510
  }
54323
- return xmlPath(shape, "p:nvSpPr", "p:cNvPr");
54511
+ const spec2 = resolveShapeLockContainer(shape, key2);
54512
+ return xmlPath(shape, spec2?.nvKey ?? "p:nvSpPr", "p:cNvPr");
54324
54513
  }
54325
54514
  /**
54326
54515
  * Serialize shape-level actions back onto the `p:cNvPr` node, updating
@@ -54342,27 +54531,35 @@ var PptxHandlerRuntime3 = class extends PptxHandlerRuntime2 {
54342
54531
  * Serialize shape lock attributes from an element back into the XML.
54343
54532
  *
54344
54533
  * Writes `a:spLocks` (shapes), `a:picLocks` (pictures), `a:cxnSpLocks`
54345
- * (connectors) or `a:grpSpLocks` (groups) onto that family's own
54346
- * `p:cNvXxxPr` container, restricted to the attributes that container's
54347
- * type declares. See {@link module:shape-lock-containers} for why the four
54348
- * are not interchangeable, and for the one family
54349
- * (`a:graphicFrameLocks`) deliberately left out.
54534
+ * (connectors), `a:grpSpLocks` (groups) or `a:graphicFrameLocks` (tables,
54535
+ * charts, SmartArt, OLE objects, media) onto that family's own `p:cNvXxxPr`
54536
+ * container, restricted to the attributes that container's type declares.
54537
+ * See {@link module:shape-lock-containers} for why the five are not
54538
+ * interchangeable.
54539
+ *
54540
+ * The container is resolved from the MARKUP, not from `el.type`: PowerPoint
54541
+ * writes media as a `p:pic` even though the type buckets as
54542
+ * `p:graphicFrame`, and loaded ink as a graphic frame even though it buckets
54543
+ * as `p:sp`. Trusting the type there would rebuild the wrong lock element
54544
+ * and delete the authored one.
54350
54545
  */
54351
54546
  serializeShapeLocks(shape, el) {
54352
- const spec2 = SHAPE_LOCK_CONTAINERS[this.getTreeBucketKeyForElementType(el.type)];
54547
+ const spec2 = resolveShapeLockContainer(shape, this.getTreeBucketKeyForElementType(el.type));
54353
54548
  if (!spec2) {
54354
54549
  return;
54355
54550
  }
54356
- const container = xmlPath(shape, spec2.nvKey, spec2.cNvKey);
54357
- if (!container) {
54551
+ const locks = "locks" in el ? el.locks : void 0;
54552
+ const existing = resolveLockContainerNode(shape, spec2, false);
54553
+ const next = buildShapeLockNode(locks, spec2, existing?.[spec2.lockTag]);
54554
+ if (!next) {
54555
+ if (existing) {
54556
+ delete existing[spec2.lockTag];
54557
+ }
54358
54558
  return;
54359
54559
  }
54360
- const locks = "locks" in el ? el.locks : void 0;
54361
- const next = buildShapeLockNode(locks, spec2, container[spec2.lockTag]);
54362
- if (next) {
54560
+ const container = existing ?? resolveLockContainerNode(shape, spec2, true);
54561
+ if (container) {
54363
54562
  container[spec2.lockTag] = next;
54364
- } else {
54365
- delete container[spec2.lockTag];
54366
54563
  }
54367
54564
  }
54368
54565
  };
@@ -57096,6 +57293,7 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime4 extends PptxHandlerRuntime
57096
57293
  * `rebuildTableXmlFromData` and fills in `a:tblGrid` / `a:tr` children.
57097
57294
  */
57098
57295
  createTableGraphicFrameXml(el) {
57296
+ el.locks = { noGrouping: true, ...el.locks };
57099
57297
  const EMU = _PptxHandlerRuntime4.EMU_PER_PX;
57100
57298
  const offX = String(Math.round(el.x * EMU));
57101
57299
  const offY = String(Math.round(el.y * EMU));
@@ -57197,6 +57395,7 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime4 extends PptxHandlerRuntime
57197
57395
  * specified relationship ID.
57198
57396
  */
57199
57397
  createOleGraphicFrameXml(el, embedRelationshipId) {
57398
+ el.locks = { noChangeAspect: true, ...el.locks };
57200
57399
  const EMU = _PptxHandlerRuntime4.EMU_PER_PX;
57201
57400
  const offX = String(Math.round(el.x * EMU));
57202
57401
  const offY = String(Math.round(el.y * EMU));
@@ -57490,6 +57689,7 @@ var PptxHandlerRuntime15 = class _PptxHandlerRuntime4 extends PptxHandlerRuntime
57490
57689
  if (!xml) {
57491
57690
  return null;
57492
57691
  }
57692
+ this.serializeShapeLocks(xml, child222);
57493
57693
  applyGroupChildTransform(xml, child222, _PptxHandlerRuntime4.EMU_PER_PX);
57494
57694
  return { tag: "p:grpSp", xml };
57495
57695
  }
@@ -59421,7 +59621,7 @@ function buildChartPoints(values) {
59421
59621
  var DEFAULT_ROW_HEIGHT_PX = 40;
59422
59622
  var DEFAULT_ROW_HEIGHT_EMU = DEFAULT_ROW_HEIGHT_PX * EMU_PER_PX;
59423
59623
  function ensureArray16(value) {
59424
- if (!value) {
59624
+ if (value === void 0 || value === null) {
59425
59625
  return [];
59426
59626
  }
59427
59627
  return Array.isArray(value) ? value : [value];
@@ -59621,37 +59821,38 @@ function updateCellTextInRawXml(element, rowIndex, colIndex, text2) {
59621
59821
  if (colIndex < 0 || colIndex >= cells.length) {
59622
59822
  return void 0;
59623
59823
  }
59624
- const cell = cells[colIndex];
59625
- const existingTxBody = cell["a:txBody"];
59824
+ cells[colIndex]["a:txBody"] = rebuildCellTextBody(
59825
+ cells[colIndex]["a:txBody"],
59826
+ text2
59827
+ );
59828
+ return newRawXml;
59829
+ }
59830
+ function rebuildCellTextBody(existingTxBody, text2) {
59626
59831
  const existingParagraphs = ensureArray16(
59627
59832
  existingTxBody?.["a:p"]
59628
59833
  );
59629
59834
  const firstParagraph = existingParagraphs.length > 0 ? existingParagraphs[0] : void 0;
59630
59835
  const existingRuns = firstParagraph ? ensureArray16(firstParagraph["a:r"]) : [];
59631
59836
  const firstRunProps = existingRuns.length > 0 ? existingRuns[0]["a:rPr"] : void 0;
59632
- const newRun = { "a:t": text2 };
59633
- if (firstRunProps) {
59837
+ const newRun = {};
59838
+ if (firstRunProps !== void 0) {
59634
59839
  newRun["a:rPr"] = firstRunProps;
59635
59840
  }
59636
- const newParagraph = {
59637
- "a:r": newRun
59638
- };
59639
- if (firstParagraph?.["a:pPr"]) {
59841
+ newRun["a:t"] = text2;
59842
+ const newParagraph = {};
59843
+ if (firstParagraph?.["a:pPr"] !== void 0) {
59640
59844
  newParagraph["a:pPr"] = firstParagraph["a:pPr"];
59641
59845
  }
59642
- const bodyPr = existingTxBody?.["a:bodyPr"];
59643
- const lstStyle = existingTxBody?.["a:lstStyle"];
59644
- const newTxBody = {
59645
- "a:p": newParagraph
59646
- };
59647
- if (bodyPr !== void 0) {
59648
- newTxBody["a:bodyPr"] = bodyPr;
59846
+ newParagraph["a:r"] = newRun;
59847
+ const newTxBody = {};
59848
+ if (existingTxBody?.["a:bodyPr"] !== void 0) {
59849
+ newTxBody["a:bodyPr"] = existingTxBody["a:bodyPr"];
59649
59850
  }
59650
- if (lstStyle !== void 0) {
59651
- newTxBody["a:lstStyle"] = lstStyle;
59851
+ if (existingTxBody?.["a:lstStyle"] !== void 0) {
59852
+ newTxBody["a:lstStyle"] = existingTxBody["a:lstStyle"];
59652
59853
  }
59653
- cell["a:txBody"] = newTxBody;
59654
- return newRawXml;
59854
+ newTxBody["a:p"] = newParagraph;
59855
+ return newTxBody;
59655
59856
  }
59656
59857
  function updateCellTextStyleInRawXml(element, rowIndex, colIndex, styleUpdates) {
59657
59858
  if (!element.rawXml) {
@@ -59675,11 +59876,15 @@ function updateCellTextStyleInRawXml(element, rowIndex, colIndex, styleUpdates)
59675
59876
  if (!txBody) {
59676
59877
  return void 0;
59677
59878
  }
59678
- const paragraphs = ensureArray16(txBody["a:p"]);
59879
+ const paragraphs = ensureXmlChildren(txBody, "a:p");
59679
59880
  for (const paragraph of paragraphs) {
59881
+ if ("align" in styleUpdates) {
59882
+ const pPr = ensureXmlChildOrCreate(paragraph, "a:pPr", "first");
59883
+ pPr["@_algn"] = styleUpdates.align === "left" ? "l" : styleUpdates.align === "center" ? "ctr" : styleUpdates.align === "right" ? "r" : styleUpdates.align === "justify" ? "just" : String(styleUpdates.align);
59884
+ }
59680
59885
  const runs = ensureArray16(paragraph["a:r"]);
59681
59886
  for (const run of runs) {
59682
- const rPr = run["a:rPr"] ?? {};
59887
+ const rPr = ensureXmlChildOrCreate(run, "a:rPr", "first");
59683
59888
  if ("bold" in styleUpdates) {
59684
59889
  if (styleUpdates.bold) {
59685
59890
  rPr["@_b"] = "1";
@@ -59712,15 +59917,9 @@ function updateCellTextStyleInRawXml(element, rowIndex, colIndex, styleUpdates)
59712
59917
  const hex4 = styleUpdates.color.replace("#", "");
59713
59918
  rPr["a:solidFill"] = { "a:srgbClr": { "@_val": hex4 } };
59714
59919
  }
59715
- if ("align" in styleUpdates) {
59716
- const pPr = paragraph["a:pPr"] ?? {};
59717
- pPr["@_algn"] = styleUpdates.align === "left" ? "l" : styleUpdates.align === "center" ? "ctr" : styleUpdates.align === "right" ? "r" : styleUpdates.align === "justify" ? "just" : String(styleUpdates.align);
59718
- paragraph["a:pPr"] = pPr;
59719
- }
59720
- run["a:rPr"] = rPr;
59721
59920
  }
59722
- if (runs.length === 0 && paragraph["a:endParaRPr"]) {
59723
- const endRPr = paragraph["a:endParaRPr"];
59921
+ const endRPr = runs.length === 0 ? ensureXmlChild(paragraph, "a:endParaRPr") : void 0;
59922
+ if (endRPr) {
59724
59923
  if ("bold" in styleUpdates) {
59725
59924
  if (styleUpdates.bold) {
59726
59925
  endRPr["@_b"] = "1";
@@ -59794,35 +59993,10 @@ function updateMergeAttrsInRawXml(element, tableData) {
59794
59993
  delete xmlCell["@_vMerge"];
59795
59994
  }
59796
59995
  if (cell.text !== void 0) {
59797
- const existingTxBody = xmlCell["a:txBody"];
59798
- const existingParagraphs = existingTxBody ? ensureArray16(existingTxBody["a:p"]) : [];
59799
- const firstParagraph = existingParagraphs.length > 0 ? existingParagraphs[0] : void 0;
59800
- const existingRuns = firstParagraph ? ensureArray16(firstParagraph["a:r"]) : [];
59801
- const firstRunProps = existingRuns.length > 0 ? existingRuns[0]["a:rPr"] : void 0;
59802
- const newRun = {
59803
- "a:t": cell.text
59804
- };
59805
- if (firstRunProps) {
59806
- newRun["a:rPr"] = firstRunProps;
59807
- }
59808
- const newParagraph = {
59809
- "a:r": newRun
59810
- };
59811
- if (firstParagraph?.["a:pPr"]) {
59812
- newParagraph["a:pPr"] = firstParagraph["a:pPr"];
59813
- }
59814
- const bodyPr = existingTxBody?.["a:bodyPr"];
59815
- const lstStyle = existingTxBody?.["a:lstStyle"];
59816
- const newTxBody = {
59817
- "a:p": newParagraph
59818
- };
59819
- if (bodyPr !== void 0) {
59820
- newTxBody["a:bodyPr"] = bodyPr;
59821
- }
59822
- if (lstStyle !== void 0) {
59823
- newTxBody["a:lstStyle"] = lstStyle;
59824
- }
59825
- xmlCell["a:txBody"] = newTxBody;
59996
+ xmlCell["a:txBody"] = rebuildCellTextBody(
59997
+ xmlCell["a:txBody"],
59998
+ cell.text
59999
+ );
59826
60000
  }
59827
60001
  }
59828
60002
  }
@@ -64168,10 +64342,13 @@ var PptxHandlerRuntime31 = class extends PptxHandlerRuntime30 {
64168
64342
  }
64169
64343
  /** Apply geometry preset or custom paths to spPr. */
64170
64344
  applyGeometryUpdate(shape, el) {
64171
- if (!hasShapeProperties(el) || !shape["p:spPr"]) {
64345
+ if (!hasShapeProperties(el)) {
64346
+ return;
64347
+ }
64348
+ const spPr = ensureXmlChild(shape, "p:spPr");
64349
+ if (!spPr) {
64172
64350
  return;
64173
64351
  }
64174
- const spPr = shape["p:spPr"];
64175
64352
  const elWithPaths = el;
64176
64353
  if (elWithPaths.customGeometryPaths && elWithPaths.customGeometryPaths.length > 0) {
64177
64354
  delete spPr["a:prstGeom"];
@@ -64804,7 +64981,7 @@ var PptxHandlerRuntime35 = class _PptxHandlerRuntime12 extends PptxHandlerRuntim
64804
64981
  }
64805
64982
  applyZoomTransform(shapeProperties, el) {
64806
64983
  const emu2 = _PptxHandlerRuntime12.EMU_PER_PX;
64807
- const transform = shapeProperties["a:xfrm"] ??= {};
64984
+ const transform = ensureXmlChildOrCreate(shapeProperties, "a:xfrm");
64808
64985
  transform["a:off"] = {
64809
64986
  "@_x": String(Math.round(el.x * emu2)),
64810
64987
  "@_y": String(Math.round(el.y * emu2))
@@ -64831,8 +65008,8 @@ var PptxHandlerRuntime35 = class _PptxHandlerRuntime12 extends PptxHandlerRuntim
64831
65008
  if (!relationshipId2) {
64832
65009
  return;
64833
65010
  }
64834
- const blipFill = zoomProperties["p166:blipFill"] ??= {};
64835
- const blip = blipFill["a:blip"] ??= {};
65011
+ const blipFill = ensureXmlChildOrCreate(zoomProperties, "p166:blipFill");
65012
+ const blip = ensureXmlChildOrCreate(blipFill, "a:blip");
64836
65013
  blip["@_r:embed"] = relationshipId2;
64837
65014
  }
64838
65015
  updateZoomFallback(shape, el, relationshipId2) {
@@ -64842,11 +65019,11 @@ var PptxHandlerRuntime35 = class _PptxHandlerRuntime12 extends PptxHandlerRuntim
64842
65019
  if (!picture) {
64843
65020
  return;
64844
65021
  }
64845
- const shapeProperties = picture["p:spPr"] ??= {};
65022
+ const shapeProperties = ensureXmlChildOrCreate(picture, "p:spPr");
64846
65023
  this.applyZoomTransform(shapeProperties, el);
64847
65024
  if (relationshipId2) {
64848
- const blipFill = picture["p:blipFill"] ??= {};
64849
- const blip = blipFill["a:blip"] ??= {};
65025
+ const blipFill = ensureXmlChildOrCreate(picture, "p:blipFill");
65026
+ const blip = ensureXmlChildOrCreate(blipFill, "a:blip");
64850
65027
  blip["@_r:embed"] = relationshipId2;
64851
65028
  }
64852
65029
  }
@@ -64941,7 +65118,7 @@ var PptxHandlerRuntime37 = class _PptxHandlerRuntime13 extends PptxHandlerRuntim
64941
65118
  continue;
64942
65119
  }
64943
65120
  const object = target.rawXml ?? existing[index] ?? {};
64944
- const properties = object["psuz:zmPr"] ??= {};
65121
+ const properties = ensureXmlChildOrCreate(object, "psuz:zmPr");
64945
65122
  const tile = this.summaryTileElement(el, target, index);
64946
65123
  const relationshipShape = {
64947
65124
  "psezm:sectionZmObj": { "psezm:zmPr": properties }
@@ -64956,8 +65133,10 @@ var PptxHandlerRuntime37 = class _PptxHandlerRuntime13 extends PptxHandlerRuntim
64956
65133
  this.applyOptionalAttribute(object, "@_scaleFactorY", target.scaleFactorY);
64957
65134
  properties["@_id"] ??= `{${generateFontGuid()}}`;
64958
65135
  properties["@_imageType"] ??= "preview";
64959
- properties["p166:blipFill"] ??= this.buildZoomBlipFill(relationshipId2);
64960
- const shapeProperties = properties["p166:spPr"] ??= this.buildZoomShapeProperties(tile);
65136
+ if (!xmlHasChild(properties, "p166:blipFill")) {
65137
+ properties["p166:blipFill"] = this.buildZoomBlipFill(relationshipId2);
65138
+ }
65139
+ const shapeProperties = xmlHasChild(properties, "p166:spPr") ? ensureXmlChildOrCreate(properties, "p166:spPr") : properties["p166:spPr"] = this.buildZoomShapeProperties(tile);
64961
65140
  this.applyZoomTransform(shapeProperties, tile);
64962
65141
  this.applyZoomBlipRelationship(properties, relationshipId2);
64963
65142
  target.sectionId = sectionId;
@@ -65023,10 +65202,10 @@ var PptxHandlerRuntime37 = class _PptxHandlerRuntime13 extends PptxHandlerRuntim
65023
65202
  group2["p:pic"] = targets.map((target, index) => {
65024
65203
  const tile = this.summaryTileElement(el, target, index);
65025
65204
  const picture = existing[index] ?? this.buildZoomFallbackPicture(tile, relationships[index]);
65026
- this.applyZoomTransform(picture["p:spPr"] ??= {}, tile);
65205
+ this.applyZoomTransform(ensureXmlChildOrCreate(picture, "p:spPr"), tile);
65027
65206
  if (relationships[index]) {
65028
- const fill = picture["p:blipFill"] ??= {};
65029
- const blip = fill["a:blip"] ??= {};
65207
+ const fill = ensureXmlChildOrCreate(picture, "p:blipFill");
65208
+ const blip = ensureXmlChildOrCreate(fill, "a:blip");
65030
65209
  blip["@_r:embed"] = relationships[index];
65031
65210
  }
65032
65211
  return picture;
@@ -65121,12 +65300,11 @@ var PptxHandlerRuntime38 = class _PptxHandlerRuntime14 extends PptxHandlerRuntim
65121
65300
  el.rawXml = shape;
65122
65301
  return shape;
65123
65302
  }
65124
- shape["p16:model3Drel"] ??= {};
65125
- shape["p16:model3Drel"]["@_r:id"] = modelRelationshipId;
65126
- const spPr = shape["p16:spPr"] ??= {};
65303
+ ensureXmlChildOrCreate(shape, "p16:model3Drel")["@_r:id"] = modelRelationshipId;
65304
+ const spPr = ensureXmlChildOrCreate(shape, "p16:spPr");
65127
65305
  this.applyModel3DTransform(spPr, el);
65128
65306
  if (poster.relationshipId) {
65129
- const posterNode = shape["p16:posterImage"] ??= {};
65307
+ const posterNode = ensureXmlChildOrCreate(shape, "p16:posterImage");
65130
65308
  posterNode["@_r:embed"] = poster.relationshipId;
65131
65309
  this.updateModel3DFallback(shape, el, poster.relationshipId);
65132
65310
  }
@@ -65191,7 +65369,7 @@ var PptxHandlerRuntime38 = class _PptxHandlerRuntime14 extends PptxHandlerRuntim
65191
65369
  return result;
65192
65370
  }
65193
65371
  applyModel3DTransform(spPr, el) {
65194
- const transform = spPr["a:xfrm"] ??= {};
65372
+ const transform = ensureXmlChildOrCreate(spPr, "a:xfrm");
65195
65373
  const emu2 = _PptxHandlerRuntime14.EMU_PER_PX;
65196
65374
  transform["a:off"] = {
65197
65375
  "@_x": String(Math.round(el.x * emu2)),
@@ -65247,9 +65425,9 @@ var PptxHandlerRuntime38 = class _PptxHandlerRuntime14 extends PptxHandlerRuntim
65247
65425
  if (!picture) {
65248
65426
  return;
65249
65427
  }
65250
- this.applyModel3DTransform(picture["p:spPr"] ??= {}, el);
65251
- const fill = picture["p:blipFill"] ??= {};
65252
- const blip = fill["a:blip"] ??= {};
65428
+ this.applyModel3DTransform(ensureXmlChildOrCreate(picture, "p:spPr"), el);
65429
+ const fill = ensureXmlChildOrCreate(picture, "p:blipFill");
65430
+ const blip = ensureXmlChildOrCreate(fill, "a:blip");
65253
65431
  blip["@_r:embed"] = posterRelationshipId;
65254
65432
  }
65255
65433
  };
@@ -65369,7 +65547,7 @@ var PptxHandlerRuntime39 = class _PptxHandlerRuntime15 extends PptxHandlerRuntim
65369
65547
  }
65370
65548
  applyContentPartTransform(shape, el) {
65371
65549
  const emu2 = _PptxHandlerRuntime15.EMU_PER_PX;
65372
- const transform = shape["p:xfrm"] ??= {};
65550
+ const transform = ensureXmlChildOrCreate(shape, "p:xfrm");
65373
65551
  transform["a:off"] = {
65374
65552
  "@_x": String(Math.round(el.x * emu2)),
65375
65553
  "@_y": String(Math.round(el.y * emu2))
@@ -65870,12 +66048,14 @@ var PptxHandlerRuntime40 = class _PptxHandlerRuntime16 extends PptxHandlerRuntim
65870
66048
  this.applyImageProperties(shape, el);
65871
66049
  this.finalizePictureBlipFillOrder(shape);
65872
66050
  this.applyGeometryUpdate(shape, el);
65873
- if (hasShapeProperties(el) && el.shapeStyle && shape["p:spPr"]) {
65874
- const spPr = shape["p:spPr"];
65875
- this.applyFillAndStroke(spPr, el.shapeStyle, ctx.inheritedGroupFill);
65876
- this.applyEffectsAndThreeD(spPr, el.shapeStyle);
65877
- this.finalizeSpPrSchemaOrder(shape);
65878
- this.applyShapeStyleRefs(shape, el.shapeStyle);
66051
+ if (hasShapeProperties(el) && el.shapeStyle) {
66052
+ const spPr = ensureXmlChild(shape, "p:spPr");
66053
+ if (spPr) {
66054
+ this.applyFillAndStroke(spPr, el.shapeStyle, ctx.inheritedGroupFill);
66055
+ this.applyEffectsAndThreeD(spPr, el.shapeStyle);
66056
+ this.finalizeSpPrSchemaOrder(shape);
66057
+ this.applyShapeStyleRefs(shape, el.shapeStyle);
66058
+ }
65879
66059
  }
65880
66060
  if (hasTextProperties(el)) {
65881
66061
  this.applyTextBodyContent(
@@ -71631,6 +71811,12 @@ var PptxHandlerRuntime65 = class _PptxHandlerRuntime28 extends PptxHandlerRuntim
71631
71811
  isLinked: mediaReference.isLinked,
71632
71812
  posterFramePath,
71633
71813
  posterFrameData,
71814
+ // Real PowerPoint media is `p:pic`-shaped even though the
71815
+ // `media` type buckets as `p:graphicFrame`, so its locks live
71816
+ // in `a:picLocks`. The writer resolves the same container from
71817
+ // the markup; leaving this unparsed would hand it an empty bag
71818
+ // and delete the authored lock on the first save.
71819
+ locks: parseShapeLocksFromNode(pic, SHAPE_LOCK_CONTAINERS["p:pic"]),
71634
71820
  rawXml: pic
71635
71821
  };
71636
71822
  }
@@ -73768,11 +73954,11 @@ var PptxHandlerRuntime74 = class extends PptxHandlerRuntime73 {
73768
73954
  if (!masterXmlStr) {
73769
73955
  return [];
73770
73956
  }
73771
- const masterXmlObj = this.parser.parse(masterXmlStr);
73957
+ const masterXmlObj = this.masterXmlMap.get(masterPath) ?? this.parser.parse(masterXmlStr);
73772
73958
  this.masterXmlMap.set(masterPath, masterXmlObj);
73773
73959
  const masterRelsPath = partRelsPath(masterPath);
73774
73960
  await this.loadSlideRelationships(masterPath, masterRelsPath);
73775
- const spTree = masterXmlObj["p:sldMaster"]?.["p:cSld"]?.["p:spTree"];
73961
+ const spTree = xmlPath(masterXmlObj, "p:sldMaster", "p:cSld", "p:spTree");
73776
73962
  if (!spTree) {
73777
73963
  this.masterCache.set(masterPath, []);
73778
73964
  return [];
@@ -77750,7 +77936,7 @@ var PptxHandlerRuntime91 = class extends PptxHandlerRuntime90 {
77750
77936
  ).trim();
77751
77937
  const seriesShapeProperties = this.xmlLookupService.getChildByLocalName(seriesNode, "spPr");
77752
77938
  const readsLineColor = seriesChartType === "line" || seriesChartType === "line3D" || seriesChartType === "scatter" || seriesChartType === "radar" || seriesChartType === "stock";
77753
- const seriesColor23 = this.parseColor(
77939
+ const seriesColor22 = this.parseColor(
77754
77940
  this.xmlLookupService.getChildByLocalName(seriesShapeProperties, "solidFill")
77755
77941
  ) ?? (readsLineColor ? this.parseColor(
77756
77942
  this.xmlLookupService.getChildByLocalName(
@@ -77804,7 +77990,7 @@ var PptxHandlerRuntime91 = class extends PptxHandlerRuntime90 {
77804
77990
  ...dataLabelOptions && Object.keys(dataLabelOptions).length > 0 ? { dataLabelOptions } : {},
77805
77991
  ...lineNoFill ? { lineNoFill } : {},
77806
77992
  ...seriesNumberFormat ? { numberFormat: seriesNumberFormat } : {},
77807
- color: seriesColor23,
77993
+ color: seriesColor22,
77808
77994
  ...trendlines.length > 0 ? { trendlines } : {},
77809
77995
  ...errBars.length > 0 ? { errBars } : {},
77810
77996
  ...dataPoints.length > 0 ? { dataPoints } : {},
@@ -92890,357 +93076,10 @@ function strokeOnlyPresetPathData(element) {
92890
93076
  const stroked = paths.filter((path) => path.stroke !== false).map((path) => path.d);
92891
93077
  return stroked.length > 0 ? stroked.join(" ") : void 0;
92892
93078
  }
92893
- function round4(value) {
92894
- return Math.round(value * 1e4) / 1e4;
92895
- }
92896
- function svgGradientId(elementId, suffix = "grad") {
92897
- const seed = String(elementId).replace(/[^a-zA-Z0-9_-]/gu, "_");
92898
- return `pptx-${suffix}-${seed}`;
92899
- }
92900
- function toSvgStops(stops) {
92901
- return sanitizeGradientStops(stops).map((stop) => ({
92902
- offset: round4(stop.position / 100),
92903
- color: stop.color,
92904
- ...typeof stop.opacity === "number" ? { opacity: round4(stop.opacity) } : {}
92905
- }));
92906
- }
92907
- function linearEndpoints(angleDegrees) {
92908
- const radians = angleDegrees * Math.PI / 180;
92909
- const dx = Math.cos(radians);
92910
- const dy = Math.sin(radians);
92911
- const span = (Math.abs(dx) + Math.abs(dy)) / 2;
92912
- return {
92913
- x1: round4(0.5 - dx * span),
92914
- y1: round4(0.5 - dy * span),
92915
- x2: round4(0.5 + dx * span),
92916
- y2: round4(0.5 + dy * span)
92917
- };
92918
- }
92919
- function buildFromSource(source, id) {
92920
- const { stops } = source;
92921
- if (stops.length === 0) {
92922
- return void 0;
92923
- }
92924
- if ((source.type || "linear") === "radial") {
92925
- const { cx, cy } = computeGradientCenter(source.fillToRect, source.focalPoint);
92926
- const fx = cx / 100;
92927
- const fy = cy / 100;
92928
- const r = Math.hypot(Math.max(fx, 1 - fx), Math.max(fy, 1 - fy));
92929
- return { kind: "radial", id, cx: round4(fx), cy: round4(fy), r: round4(r), stops };
92930
- }
92931
- const angle = typeof source.angle === "number" && Number.isFinite(source.angle) ? source.angle : 90;
92932
- return { kind: "linear", id, ...linearEndpoints(angle), stops };
92933
- }
92934
- function buildSvgGradientDef(style, elementId) {
92935
- if (!style || style.fillMode !== "gradient") {
92936
- return void 0;
92937
- }
92938
- return buildFromSource(
92939
- {
92940
- stops: toSvgStops(style.fillGradientStops),
92941
- type: style.fillGradientType,
92942
- angle: style.fillGradientAngle,
92943
- fillToRect: style.fillGradientFillToRect,
92944
- focalPoint: style.fillGradientFocalPoint
92945
- },
92946
- svgGradientId(elementId)
92947
- );
92948
- }
92949
- function buildSvgStrokeGradientDef(style, elementId) {
92950
- if (!style || style.strokeFillMode !== "gradient") {
92951
- return void 0;
92952
- }
92953
- return buildFromSource(
92954
- {
92955
- stops: toSvgStops(style.strokeGradientStops),
92956
- type: style.strokeGradientType,
92957
- angle: style.strokeGradientAngle
92958
- },
92959
- svgGradientId(elementId, "stroke")
92960
- );
92961
- }
92962
- function buildSvgStrokePatternDef(style, elementId) {
92963
- if (!style || style.strokeFillMode !== "pattern" || !style.strokePatternPreset) {
92964
- return void 0;
92965
- }
92966
- const fg = normalizeHexColor(style.strokeColor, "#000000");
92967
- const bg = normalizeHexColor(style.strokePatternBackgroundColor, "#ffffff");
92968
- const tile = getPatternTile(style.strokePatternPreset, fg, bg);
92969
- if (!tile) {
92970
- return void 0;
92971
- }
92972
- const markup = `<svg xmlns="http://www.w3.org/2000/svg" width="${tile.w}" height="${tile.h}">${tile.inner}</svg>`;
92973
- return {
92974
- kind: "pattern",
92975
- id: svgGradientId(elementId, "strokepat"),
92976
- width: tile.w,
92977
- height: tile.h,
92978
- href: `data:image/svg+xml,${encodeURIComponent(markup)}`
92979
- };
92980
- }
92981
- function svgGradientFillRef(def) {
92982
- return `url(#${def.id})`;
92983
- }
92984
- var DEFAULT_OPEN_PRESET_STROKE_WIDTH = 2;
92985
- function outlinePathData(clipPath, width, height) {
92986
- if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
92987
- return void 0;
92988
- }
92989
- const rect2 = `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z`;
92990
- if (!clipPath) {
92991
- return rect2;
92992
- }
92993
- const asPath = /^path\('(.*)'\)$/su.exec(clipPath.trim());
92994
- if (asPath) {
92995
- return asPath[1];
92996
- }
92997
- const asPolygon = /^polygon\((.*)\)$/su.exec(clipPath.trim());
92998
- if (asPolygon) {
92999
- const points3 = asPolygon[1].split(",").map((pair) => pair.trim().split(/\s+/u)).filter((parts) => parts.length === 2).map(([rawX, rawY]) => {
93000
- const toPx2 = (token2, extent) => token2.endsWith("%") ? Number.parseFloat(token2) / 100 * extent : Number.parseFloat(token2);
93001
- return [toPx2(rawX, width), toPx2(rawY, height)];
93002
- }).filter(([x, y]) => Number.isFinite(x) && Number.isFinite(y));
93003
- if (points3.length < 3) {
93004
- return rect2;
93005
- }
93006
- const [first, ...rest] = points3;
93007
- return `M ${first[0]} ${first[1]} ${rest.map(([x, y]) => `L ${x} ${y}`).join(" ")} Z`;
93008
- }
93009
- return rect2;
93010
- }
93011
- function outlineStrands(compoundLine, strokeWidth) {
93012
- const offsets = getCompoundLineOffsets(compoundLine, strokeWidth);
93013
- if (offsets.length <= 1) {
93014
- return [{ strokeWidth, offset: 0 }];
93015
- }
93016
- const widths = getCompoundLineWidths(compoundLine, strokeWidth);
93017
- return offsets.map((offset, idx) => ({ strokeWidth: widths[idx] ?? strokeWidth, offset }));
93018
- }
93019
- function buildStrokeOutline(element) {
93020
- if (!hasShapeProperties(element)) {
93021
- return void 0;
93022
- }
93023
- const style = element.shapeStyle;
93024
- const declaredWidth = Math.max(0, style?.strokeWidth ?? 0);
93025
- const openPresetD = strokeOnlyPresetPathData(element);
93026
- if (!openPresetD && (!style || declaredWidth <= 0)) {
93027
- return void 0;
93028
- }
93029
- const paint = style && declaredWidth > 0 ? buildSvgStrokeGradientDef(style, element.id) ?? buildSvgStrokePatternDef(style, element.id) : void 0;
93030
- if (!paint && !openPresetD) {
93031
- return void 0;
93032
- }
93033
- const d = openPresetD ?? outlinePathData(getResolvedShapeClipPath(element), element.width, element.height);
93034
- if (!d) {
93035
- return void 0;
93036
- }
93037
- const strokeWidth = declaredWidth > 0 ? declaredWidth : DEFAULT_OPEN_PRESET_STROKE_WIDTH;
93038
- return {
93039
- d,
93040
- paint,
93041
- stroke: paint ? svgGradientFillRef(paint) : colorWithOpacity(style?.strokeColor ?? DEFAULT_STROKE_COLOR, style?.strokeOpacity),
93042
- strokeWidth,
93043
- strands: outlineStrands(style?.compoundLine, strokeWidth),
93044
- dashArray: getSvgStrokeDasharray(
93045
- normalizeStrokeDashType(style?.strokeDash),
93046
- Math.max(strokeWidth, 1),
93047
- style?.customDashSegments
93048
- ),
93049
- lineCap: svgLineCap(style?.lineCap),
93050
- lineJoin: style?.lineJoin === "bevel" ? "bevel" : style?.lineJoin === "miter" ? "miter" : "round"
93051
- };
93052
- }
93053
- function strokeOutlineViewBox(element) {
93054
- const width = Math.max(element.width, MIN_ELEMENT_SIZE);
93055
- const height = Math.max(element.height, MIN_ELEMENT_SIZE);
93056
- return `0 0 ${width} ${height}`;
93057
- }
93058
- function suppressesCssBorder(element) {
93059
- return buildStrokeOutline(element) !== void 0;
93060
- }
93061
- var HOLLOW_HIT_MIN_WIDTH = 10;
93062
- function isHollowShapeElement(element) {
93063
- if (element.type !== "shape" || !hasShapeProperties(element)) {
93064
- return false;
93065
- }
93066
- const style = element.shapeStyle;
93067
- const filled = style?.fillColor !== void 0 && style.fillColor !== "transparent" || style?.fillMode === "gradient" || style?.fillMode === "pattern" || style?.fillMode === "image" || style?.fillMode === "group" || Boolean(style?.fillGradient);
93068
- if (filled) {
93069
- return false;
93070
- }
93071
- return getElementTextContent(element).trim() === "";
93072
- }
93073
- function buildHollowHitOutline(element) {
93074
- if (!isHollowShapeElement(element)) {
93075
- return void 0;
93076
- }
93077
- const d = outlinePathData(getResolvedShapeClipPath(element), element.width, element.height);
93078
- if (!d) {
93079
- return void 0;
93080
- }
93081
- const strokeWidth = hasShapeProperties(element) ? element.shapeStyle?.strokeWidth ?? 0 : 0;
93082
- return { d, strokeWidth: Math.max(strokeWidth * 3, HOLLOW_HIT_MIN_WIDTH) };
93083
- }
93084
- function createWheelStepBuffer() {
93085
- return { accumulated: 0 };
93086
- }
93087
- var LINE_PX = 16;
93088
- var PAGE_PX = 400;
93089
- var STEP_THRESHOLD_PX = 120;
93090
- var ZOOM_PER_PX = 15e-4;
93091
- function normalizeWheelDelta({ deltaY, deltaMode = 0 }) {
93092
- if (deltaMode === 1) {
93093
- return deltaY * LINE_PX;
93094
- }
93095
- if (deltaMode === 2) {
93096
- return deltaY * PAGE_PX;
93097
- }
93098
- return deltaY;
93099
- }
93100
- function accumulate(buffer, px3) {
93101
- if (px3 !== 0 && Math.sign(px3) !== Math.sign(buffer.accumulated)) {
93102
- buffer.accumulated = 0;
93103
- }
93104
- buffer.accumulated += px3;
93105
- if (buffer.accumulated >= STEP_THRESHOLD_PX) {
93106
- buffer.accumulated = 0;
93107
- return { intent: "next-slide" };
93108
- }
93109
- if (buffer.accumulated <= -STEP_THRESHOLD_PX) {
93110
- buffer.accumulated = 0;
93111
- return { intent: "previous-slide" };
93112
- }
93113
- return { intent: "none" };
93114
- }
93115
- function mapEditingWheel(input, buffer, canScrollFurther) {
93116
- const px3 = normalizeWheelDelta(input);
93117
- if (input.ctrlKey === true || input.metaKey === true) {
93118
- buffer.accumulated = 0;
93119
- return { intent: "zoom", deltaScale: -px3 * ZOOM_PER_PX };
93120
- }
93121
- if (canScrollFurther) {
93122
- buffer.accumulated = 0;
93123
- return { intent: "scroll" };
93124
- }
93125
- return accumulate(buffer, px3);
93126
- }
93127
- function mapPresentationWheel(input, buffer) {
93128
- return accumulate(buffer, normalizeWheelDelta(input));
93129
- }
93130
- var CYLINDER_RADIUS = "48% / 12%";
93131
- var MIN_ROUND_RECT_RADIUS_PX = 0.01;
93132
- function resolveShapeGeometry(element) {
93133
- const shapeType = getShapeType(element.shapeType);
93134
- if (element.type === "connector" || shapeType === "connector") {
93135
- return { kind: "bare" };
93136
- }
93137
- if (isStrokeOnlyPresetElement(element)) {
93138
- return { kind: "strokeOnly" };
93139
- }
93140
- if (shapeType === "roundRect" && hasShapeProperties(element)) {
93141
- const radiusPx = getRoundRectRadiusPx(element);
93142
- return radiusPx > MIN_ROUND_RECT_RADIUS_PX ? { kind: "borderRadius", radius: `${radiusPx}px` } : { kind: "none" };
93143
- }
93144
- if (shapeType === "ellipse") {
93145
- return { kind: "borderRadius", radius: "50%" };
93146
- }
93147
- const clipPath = isIdentityRectClip(element) ? void 0 : getResolvedShapeClipPath(element);
93148
- if (clipPath) {
93149
- return { kind: "clipPath", clipPath };
93150
- }
93151
- if (shapeType === "line") {
93152
- const authored = element.shapeStyle?.strokeWidth;
93153
- return { kind: "lineEdge", strokeWidth: Math.max(Math.max(0, authored ?? 0), 2) };
93154
- }
93155
- if (shapeType === "cylinder") {
93156
- return { kind: "borderRadius", radius: CYLINDER_RADIUS };
93157
- }
93158
- return { kind: "none" };
93159
- }
93160
- function hasStrokePaint(style) {
93161
- if (!style || Math.max(0, style.strokeWidth ?? 0) <= 0) {
93162
- return false;
93163
- }
93164
- return style.strokeColor !== void 0 || style.strokeFillMode !== void 0;
93165
- }
93166
- function paintedStrokeWidth(style) {
93167
- return hasStrokePaint(style) ? Math.max(0, style?.strokeWidth ?? 0) : 0;
93168
- }
93169
- var NO_STROKE = {
93170
- borderWidth: 0,
93171
- borderStyle: void 0,
93172
- borderColor: void 0,
93173
- border: void 0,
93174
- strokeLinejoin: void 0,
93175
- strokeLinecap: void 0,
93176
- strokeMiterlimit: void 0
93177
- };
93178
- function svgLineJoin(join) {
93179
- switch (join) {
93180
- case "round":
93181
- return "round";
93182
- case "bevel":
93183
- return "bevel";
93184
- case "miter":
93185
- return "miter";
93186
- default:
93187
- return void 0;
93188
- }
93189
- }
93190
- function svgStrokeLineCap(cap) {
93191
- switch (cap) {
93192
- case "rnd":
93193
- return "round";
93194
- case "sq":
93195
- return "square";
93196
- case "flat":
93197
- return "butt";
93198
- default:
93199
- return void 0;
93200
- }
93201
- }
93202
- function strokeMiterLimit(style) {
93203
- if (style?.lineJoin !== "miter" || typeof style.miterLimit !== "number") {
93204
- return void 0;
93205
- }
93206
- if (!Number.isFinite(style.miterLimit)) {
93207
- return void 0;
93208
- }
93209
- return Math.max(style.miterLimit / 1e5, 1);
93210
- }
93211
- function getComputedStrokeStyle(element) {
93212
- if (!hasShapeProperties(element)) {
93213
- return NO_STROKE;
93214
- }
93215
- const style = element.shapeStyle;
93216
- const width = suppressesCssBorder(element) ? 0 : paintedStrokeWidth(style);
93217
- const joins = {
93218
- strokeLinejoin: svgLineJoin(style?.lineJoin),
93219
- strokeLinecap: svgStrokeLineCap(style?.lineCap),
93220
- strokeMiterlimit: strokeMiterLimit(style)
93221
- };
93222
- if (width <= 0 || !style) {
93223
- return { ...NO_STROKE, ...joins };
93224
- }
93225
- const borderWidth = width;
93226
- const borderStyle = getCssBorderDashStyle(
93227
- normalizeStrokeDashType(style.strokeDash),
93228
- style.compoundLine
93229
- );
93230
- const rawColor = style.strokeColor ?? DEFAULT_STROKE_COLOR;
93231
- const borderColor = style.strokeOpacity === void 0 ? rawColor : colorWithOpacity(normalizeHexColor(rawColor, DEFAULT_STROKE_COLOR), style.strokeOpacity);
93232
- return {
93233
- borderWidth,
93234
- borderStyle,
93235
- borderColor,
93236
- border: `${borderWidth}px ${borderStyle ?? "solid"} ${borderColor}`,
93237
- ...joins
93238
- };
93239
- }
93240
93079
  var DEFAULT_SHADOW_COLOR = "#000000";
93241
93080
  var DEFAULT_GLOW_COLOR = "#ffff00";
93242
93081
  function escapeSvgAttr(value) {
93243
- return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
93082
+ return String(value).replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
93244
93083
  }
93245
93084
  function clampUnitInterval22(value) {
93246
93085
  return Math.min(1, Math.max(0, value));
@@ -93625,6 +93464,353 @@ function getComputedEffectStyle(element, options = {}) {
93625
93464
  }
93626
93465
  return result;
93627
93466
  }
93467
+ function round4(value) {
93468
+ return Math.round(value * 1e4) / 1e4;
93469
+ }
93470
+ function svgGradientId(elementId, suffix = "grad") {
93471
+ const seed = String(elementId).replace(/[^a-zA-Z0-9_-]/gu, "_");
93472
+ return `pptx-${suffix}-${seed}`;
93473
+ }
93474
+ function toSvgStops(stops) {
93475
+ return sanitizeGradientStops(stops).map((stop) => ({
93476
+ offset: round4(stop.position / 100),
93477
+ color: stop.color,
93478
+ ...typeof stop.opacity === "number" ? { opacity: round4(stop.opacity) } : {}
93479
+ }));
93480
+ }
93481
+ function linearEndpoints(angleDegrees) {
93482
+ const radians = angleDegrees * Math.PI / 180;
93483
+ const dx = Math.cos(radians);
93484
+ const dy = Math.sin(radians);
93485
+ const span = (Math.abs(dx) + Math.abs(dy)) / 2;
93486
+ return {
93487
+ x1: round4(0.5 - dx * span),
93488
+ y1: round4(0.5 - dy * span),
93489
+ x2: round4(0.5 + dx * span),
93490
+ y2: round4(0.5 + dy * span)
93491
+ };
93492
+ }
93493
+ function buildFromSource(source, id) {
93494
+ const { stops } = source;
93495
+ if (stops.length === 0) {
93496
+ return void 0;
93497
+ }
93498
+ if ((source.type || "linear") === "radial") {
93499
+ const { cx, cy } = computeGradientCenter(source.fillToRect, source.focalPoint);
93500
+ const fx = cx / 100;
93501
+ const fy = cy / 100;
93502
+ const r = Math.hypot(Math.max(fx, 1 - fx), Math.max(fy, 1 - fy));
93503
+ return { kind: "radial", id, cx: round4(fx), cy: round4(fy), r: round4(r), stops };
93504
+ }
93505
+ const angle = typeof source.angle === "number" && Number.isFinite(source.angle) ? source.angle : 90;
93506
+ return { kind: "linear", id, ...linearEndpoints(angle), stops };
93507
+ }
93508
+ function buildSvgGradientDef(style, elementId) {
93509
+ if (!style || style.fillMode !== "gradient") {
93510
+ return void 0;
93511
+ }
93512
+ return buildFromSource(
93513
+ {
93514
+ stops: toSvgStops(style.fillGradientStops),
93515
+ type: style.fillGradientType,
93516
+ angle: style.fillGradientAngle,
93517
+ fillToRect: style.fillGradientFillToRect,
93518
+ focalPoint: style.fillGradientFocalPoint
93519
+ },
93520
+ svgGradientId(elementId)
93521
+ );
93522
+ }
93523
+ function buildSvgStrokeGradientDef(style, elementId) {
93524
+ if (!style || style.strokeFillMode !== "gradient") {
93525
+ return void 0;
93526
+ }
93527
+ return buildFromSource(
93528
+ {
93529
+ stops: toSvgStops(style.strokeGradientStops),
93530
+ type: style.strokeGradientType,
93531
+ angle: style.strokeGradientAngle
93532
+ },
93533
+ svgGradientId(elementId, "stroke")
93534
+ );
93535
+ }
93536
+ function buildSvgStrokePatternDef(style, elementId) {
93537
+ if (!style || style.strokeFillMode !== "pattern" || !style.strokePatternPreset) {
93538
+ return void 0;
93539
+ }
93540
+ const fg = normalizeHexColor(style.strokeColor, "#000000");
93541
+ const bg = normalizeHexColor(style.strokePatternBackgroundColor, "#ffffff");
93542
+ const tile = getPatternTile(style.strokePatternPreset, fg, bg);
93543
+ if (!tile) {
93544
+ return void 0;
93545
+ }
93546
+ const markup = `<svg xmlns="http://www.w3.org/2000/svg" width="${tile.w}" height="${tile.h}">${tile.inner}</svg>`;
93547
+ return {
93548
+ kind: "pattern",
93549
+ id: svgGradientId(elementId, "strokepat"),
93550
+ width: tile.w,
93551
+ height: tile.h,
93552
+ href: `data:image/svg+xml,${encodeURIComponent(markup)}`
93553
+ };
93554
+ }
93555
+ function svgGradientFillRef(def) {
93556
+ return `url(#${def.id})`;
93557
+ }
93558
+ var DEFAULT_OPEN_PRESET_STROKE_WIDTH = 2;
93559
+ function outlinePathData(clipPath, width, height) {
93560
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
93561
+ return void 0;
93562
+ }
93563
+ const rect2 = `M 0 0 L ${width} 0 L ${width} ${height} L 0 ${height} Z`;
93564
+ if (!clipPath) {
93565
+ return rect2;
93566
+ }
93567
+ const asPath = /^path\('(.*)'\)$/su.exec(clipPath.trim());
93568
+ if (asPath) {
93569
+ return asPath[1];
93570
+ }
93571
+ const asPolygon = /^polygon\((.*)\)$/su.exec(clipPath.trim());
93572
+ if (asPolygon) {
93573
+ const points3 = asPolygon[1].split(",").map((pair) => pair.trim().split(/\s+/u)).filter((parts) => parts.length === 2).map(([rawX, rawY]) => {
93574
+ const toPx2 = (token2, extent) => token2.endsWith("%") ? Number.parseFloat(token2) / 100 * extent : Number.parseFloat(token2);
93575
+ return [toPx2(rawX, width), toPx2(rawY, height)];
93576
+ }).filter(([x, y]) => Number.isFinite(x) && Number.isFinite(y));
93577
+ if (points3.length < 3) {
93578
+ return rect2;
93579
+ }
93580
+ const [first, ...rest] = points3;
93581
+ return `M ${first[0]} ${first[1]} ${rest.map(([x, y]) => `L ${x} ${y}`).join(" ")} Z`;
93582
+ }
93583
+ return rect2;
93584
+ }
93585
+ function outlineStrands(compoundLine, strokeWidth) {
93586
+ const offsets = getCompoundLineOffsets(compoundLine, strokeWidth);
93587
+ if (offsets.length <= 1) {
93588
+ return [{ strokeWidth, offset: 0 }];
93589
+ }
93590
+ const widths = getCompoundLineWidths(compoundLine, strokeWidth);
93591
+ return offsets.map((offset, idx) => ({ strokeWidth: widths[idx] ?? strokeWidth, offset }));
93592
+ }
93593
+ function buildStrokeOutline(element) {
93594
+ if (!hasShapeProperties(element)) {
93595
+ return void 0;
93596
+ }
93597
+ const style = element.shapeStyle;
93598
+ const declaredWidth = Math.max(0, style?.strokeWidth ?? 0);
93599
+ const openPresetD = strokeOnlyPresetPathData(element);
93600
+ if (!openPresetD && (!style || declaredWidth <= 0)) {
93601
+ return void 0;
93602
+ }
93603
+ const paint = style && declaredWidth > 0 ? buildSvgStrokeGradientDef(style, element.id) ?? buildSvgStrokePatternDef(style, element.id) : void 0;
93604
+ if (!paint && !openPresetD) {
93605
+ return void 0;
93606
+ }
93607
+ const d = openPresetD ?? outlinePathData(getResolvedShapeClipPath(element), element.width, element.height);
93608
+ if (!d) {
93609
+ return void 0;
93610
+ }
93611
+ const strokeWidth = declaredWidth > 0 ? declaredWidth : DEFAULT_OPEN_PRESET_STROKE_WIDTH;
93612
+ return {
93613
+ d,
93614
+ paint,
93615
+ stroke: paint ? svgGradientFillRef(paint) : colorWithOpacity(style?.strokeColor ?? DEFAULT_STROKE_COLOR, style?.strokeOpacity),
93616
+ strokeWidth,
93617
+ strands: outlineStrands(style?.compoundLine, strokeWidth),
93618
+ dashArray: getSvgStrokeDasharray(
93619
+ normalizeStrokeDashType(style?.strokeDash),
93620
+ Math.max(strokeWidth, 1),
93621
+ style?.customDashSegments
93622
+ ),
93623
+ lineCap: svgLineCap(style?.lineCap),
93624
+ lineJoin: style?.lineJoin === "bevel" ? "bevel" : style?.lineJoin === "miter" ? "miter" : "round"
93625
+ };
93626
+ }
93627
+ function strokeOutlineViewBox(element) {
93628
+ const width = Math.max(element.width, MIN_ELEMENT_SIZE);
93629
+ const height = Math.max(element.height, MIN_ELEMENT_SIZE);
93630
+ return `0 0 ${width} ${height}`;
93631
+ }
93632
+ function suppressesCssBorder(element) {
93633
+ return buildStrokeOutline(element) !== void 0;
93634
+ }
93635
+ var HOLLOW_HIT_MIN_WIDTH = 10;
93636
+ function isHollowShapeElement(element) {
93637
+ if (element.type !== "shape" || !hasShapeProperties(element)) {
93638
+ return false;
93639
+ }
93640
+ const style = element.shapeStyle;
93641
+ const filled = style?.fillColor !== void 0 && style.fillColor !== "transparent" || style?.fillMode === "gradient" || style?.fillMode === "pattern" || style?.fillMode === "image" || style?.fillMode === "group" || Boolean(style?.fillGradient);
93642
+ if (filled) {
93643
+ return false;
93644
+ }
93645
+ return getElementTextContent(element).trim() === "";
93646
+ }
93647
+ function buildHollowHitOutline(element) {
93648
+ if (!isHollowShapeElement(element)) {
93649
+ return void 0;
93650
+ }
93651
+ const d = outlinePathData(getResolvedShapeClipPath(element), element.width, element.height);
93652
+ if (!d) {
93653
+ return void 0;
93654
+ }
93655
+ const strokeWidth = hasShapeProperties(element) ? element.shapeStyle?.strokeWidth ?? 0 : 0;
93656
+ return { d, strokeWidth: Math.max(strokeWidth * 3, HOLLOW_HIT_MIN_WIDTH) };
93657
+ }
93658
+ function createWheelStepBuffer() {
93659
+ return { accumulated: 0 };
93660
+ }
93661
+ var LINE_PX = 16;
93662
+ var PAGE_PX = 400;
93663
+ var STEP_THRESHOLD_PX = 120;
93664
+ var ZOOM_PER_PX = 15e-4;
93665
+ function normalizeWheelDelta({ deltaY, deltaMode = 0 }) {
93666
+ if (deltaMode === 1) {
93667
+ return deltaY * LINE_PX;
93668
+ }
93669
+ if (deltaMode === 2) {
93670
+ return deltaY * PAGE_PX;
93671
+ }
93672
+ return deltaY;
93673
+ }
93674
+ function accumulate(buffer, px3) {
93675
+ if (px3 !== 0 && Math.sign(px3) !== Math.sign(buffer.accumulated)) {
93676
+ buffer.accumulated = 0;
93677
+ }
93678
+ buffer.accumulated += px3;
93679
+ if (buffer.accumulated >= STEP_THRESHOLD_PX) {
93680
+ buffer.accumulated = 0;
93681
+ return { intent: "next-slide" };
93682
+ }
93683
+ if (buffer.accumulated <= -STEP_THRESHOLD_PX) {
93684
+ buffer.accumulated = 0;
93685
+ return { intent: "previous-slide" };
93686
+ }
93687
+ return { intent: "none" };
93688
+ }
93689
+ function mapEditingWheel(input, buffer, canScrollFurther) {
93690
+ const px3 = normalizeWheelDelta(input);
93691
+ if (input.ctrlKey === true || input.metaKey === true) {
93692
+ buffer.accumulated = 0;
93693
+ return { intent: "zoom", deltaScale: -px3 * ZOOM_PER_PX };
93694
+ }
93695
+ if (canScrollFurther) {
93696
+ buffer.accumulated = 0;
93697
+ return { intent: "scroll" };
93698
+ }
93699
+ return accumulate(buffer, px3);
93700
+ }
93701
+ function mapPresentationWheel(input, buffer) {
93702
+ return accumulate(buffer, normalizeWheelDelta(input));
93703
+ }
93704
+ var CYLINDER_RADIUS = "48% / 12%";
93705
+ var MIN_ROUND_RECT_RADIUS_PX = 0.01;
93706
+ function resolveShapeGeometry(element) {
93707
+ const shapeType = getShapeType(element.shapeType);
93708
+ if (element.type === "connector" || shapeType === "connector") {
93709
+ return { kind: "bare" };
93710
+ }
93711
+ if (isStrokeOnlyPresetElement(element)) {
93712
+ return { kind: "strokeOnly" };
93713
+ }
93714
+ if (shapeType === "roundRect" && hasShapeProperties(element)) {
93715
+ const radiusPx = getRoundRectRadiusPx(element);
93716
+ return radiusPx > MIN_ROUND_RECT_RADIUS_PX ? { kind: "borderRadius", radius: `${radiusPx}px` } : { kind: "none" };
93717
+ }
93718
+ if (shapeType === "ellipse") {
93719
+ return { kind: "borderRadius", radius: "50%" };
93720
+ }
93721
+ const clipPath = isIdentityRectClip(element) ? void 0 : getResolvedShapeClipPath(element);
93722
+ if (clipPath) {
93723
+ return { kind: "clipPath", clipPath };
93724
+ }
93725
+ if (shapeType === "line") {
93726
+ const authored = element.shapeStyle?.strokeWidth;
93727
+ return { kind: "lineEdge", strokeWidth: Math.max(Math.max(0, authored ?? 0), 2) };
93728
+ }
93729
+ if (shapeType === "cylinder") {
93730
+ return { kind: "borderRadius", radius: CYLINDER_RADIUS };
93731
+ }
93732
+ return { kind: "none" };
93733
+ }
93734
+ function hasStrokePaint(style) {
93735
+ if (!style || Math.max(0, style.strokeWidth ?? 0) <= 0) {
93736
+ return false;
93737
+ }
93738
+ return style.strokeColor !== void 0 || style.strokeFillMode !== void 0;
93739
+ }
93740
+ function paintedStrokeWidth(style) {
93741
+ return hasStrokePaint(style) ? Math.max(0, style?.strokeWidth ?? 0) : 0;
93742
+ }
93743
+ var NO_STROKE = {
93744
+ borderWidth: 0,
93745
+ borderStyle: void 0,
93746
+ borderColor: void 0,
93747
+ border: void 0,
93748
+ strokeLinejoin: void 0,
93749
+ strokeLinecap: void 0,
93750
+ strokeMiterlimit: void 0
93751
+ };
93752
+ function svgLineJoin(join) {
93753
+ switch (join) {
93754
+ case "round":
93755
+ return "round";
93756
+ case "bevel":
93757
+ return "bevel";
93758
+ case "miter":
93759
+ return "miter";
93760
+ default:
93761
+ return void 0;
93762
+ }
93763
+ }
93764
+ function svgStrokeLineCap(cap) {
93765
+ switch (cap) {
93766
+ case "rnd":
93767
+ return "round";
93768
+ case "sq":
93769
+ return "square";
93770
+ case "flat":
93771
+ return "butt";
93772
+ default:
93773
+ return void 0;
93774
+ }
93775
+ }
93776
+ function strokeMiterLimit(style) {
93777
+ if (style?.lineJoin !== "miter" || typeof style.miterLimit !== "number") {
93778
+ return void 0;
93779
+ }
93780
+ if (!Number.isFinite(style.miterLimit)) {
93781
+ return void 0;
93782
+ }
93783
+ return Math.max(style.miterLimit / 1e5, 1);
93784
+ }
93785
+ function getComputedStrokeStyle(element) {
93786
+ if (!hasShapeProperties(element)) {
93787
+ return NO_STROKE;
93788
+ }
93789
+ const style = element.shapeStyle;
93790
+ const width = suppressesCssBorder(element) ? 0 : paintedStrokeWidth(style);
93791
+ const joins = {
93792
+ strokeLinejoin: svgLineJoin(style?.lineJoin),
93793
+ strokeLinecap: svgStrokeLineCap(style?.lineCap),
93794
+ strokeMiterlimit: strokeMiterLimit(style)
93795
+ };
93796
+ if (width <= 0 || !style) {
93797
+ return { ...NO_STROKE, ...joins };
93798
+ }
93799
+ const borderWidth = width;
93800
+ const borderStyle = getCssBorderDashStyle(
93801
+ normalizeStrokeDashType(style.strokeDash),
93802
+ style.compoundLine
93803
+ );
93804
+ const rawColor = style.strokeColor ?? DEFAULT_STROKE_COLOR;
93805
+ const borderColor = style.strokeOpacity === void 0 ? rawColor : colorWithOpacity(normalizeHexColor(rawColor, DEFAULT_STROKE_COLOR), style.strokeOpacity);
93806
+ return {
93807
+ borderWidth,
93808
+ borderStyle,
93809
+ borderColor,
93810
+ border: `${borderWidth}px ${borderStyle ?? "solid"} ${borderColor}`,
93811
+ ...joins
93812
+ };
93813
+ }
93628
93814
  function isImageTiled(element) {
93629
93815
  if (!isImageLikeElement(element)) {
93630
93816
  return false;
@@ -96648,24 +96834,6 @@ function getChartStylePalette(styleId) {
96648
96834
  }
96649
96835
  return palette;
96650
96836
  }
96651
- function seriesColor2(series, index, styleId, colorPalette) {
96652
- const explicit = series.color ?? series.marker?.spPr?.fillColor;
96653
- if (explicit) {
96654
- return explicit;
96655
- }
96656
- if (colorPalette && colorPalette.length > 0) {
96657
- return colorPalette[index % colorPalette.length];
96658
- }
96659
- const palette = getChartStylePalette(styleId);
96660
- return palette[index % palette.length];
96661
- }
96662
- function paletteColor(index, styleId, colorPalette) {
96663
- if (colorPalette && colorPalette.length > 0) {
96664
- return colorPalette[index % colorPalette.length];
96665
- }
96666
- const palette = getChartStylePalette(styleId);
96667
- return palette[index % palette.length];
96668
- }
96669
96837
  function computeValueRange(series) {
96670
96838
  const allValues = series.flatMap((s) => s.values);
96671
96839
  if (allValues.length === 0) {
@@ -96677,20 +96845,6 @@ function computeValueRange(series) {
96677
96845
  );
96678
96846
  return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
96679
96847
  }
96680
- function valueToY(val2, range, topY, bottomY) {
96681
- const usable = bottomY - topY;
96682
- let ratio;
96683
- if (range.logScale && range.logBase) {
96684
- const base = range.logBase;
96685
- const clampedVal = Math.max(val2, range.min);
96686
- const logVal = Math.log(clampedVal) / Math.log(base);
96687
- const logMin = Math.log(range.min) / Math.log(base);
96688
- ratio = (logVal - logMin) / range.span;
96689
- } else {
96690
- ratio = (val2 - range.min) / range.span;
96691
- }
96692
- return range.reverseOrder ? topY + ratio * usable : bottomY - ratio * usable;
96693
- }
96694
96848
  function formatAxisValue(val2, formatCode) {
96695
96849
  const formatted = formatChartNumber(val2, formatCode);
96696
96850
  if (formatted !== void 0) {
@@ -96707,50 +96861,6 @@ function formatAxisValue(val2, formatCode) {
96707
96861
  }
96708
96862
  return val2.toFixed(1);
96709
96863
  }
96710
- function computeLayout(elementWidth, elementHeight, style, hasAxes, legendPos, options) {
96711
- const svgWidth = Math.max(1, elementWidth);
96712
- const svgHeight = Math.max(1, elementHeight);
96713
- let plotLeft = hasAxes ? 48 : 8;
96714
- let plotTop = 8;
96715
- let plotRight = svgWidth - 8;
96716
- let plotBottom = svgHeight - (hasAxes ? 24 : 8);
96717
- if (style?.hasTitle) {
96718
- plotTop += 20;
96719
- }
96720
- if (style?.hasLegend) {
96721
- if (legendPos === "b") {
96722
- plotBottom -= 20;
96723
- } else if (legendPos === "t") {
96724
- plotTop += 20;
96725
- } else if (legendPos === "r") {
96726
- plotRight -= 80;
96727
- } else if (legendPos === "l") {
96728
- plotLeft += 80;
96729
- }
96730
- }
96731
- if (options?.hasSecondaryValueAxis) {
96732
- plotRight -= 40;
96733
- }
96734
- if (options?.hasSecondaryCategoryAxis) {
96735
- plotTop += 16;
96736
- }
96737
- if (options?.hasDataTable) {
96738
- const rowCount = options.dataTableRowCount ?? 1;
96739
- plotBottom -= 14 + rowCount * 14;
96740
- }
96741
- const pw = Math.max(plotRight - plotLeft, 1);
96742
- const ph = Math.max(plotBottom - plotTop, 1);
96743
- return {
96744
- plotLeft,
96745
- plotTop,
96746
- plotRight: plotLeft + pw,
96747
- plotBottom: plotTop + ph,
96748
- plotWidth: pw,
96749
- plotHeight: ph,
96750
- svgWidth,
96751
- svgHeight
96752
- };
96753
- }
96754
96864
  var DEFAULT_CHART_AREA_FILL = "#0f172a11";
96755
96865
  function resolve(fill, fallback) {
96756
96866
  if (fill === "none") {
@@ -97714,7 +97824,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97714
97824
  const valY = valueToY2(val2, activeRange, layout.plotTop, layout.plotBottom);
97715
97825
  const y = Math.min(zeroY, valY);
97716
97826
  const h = Math.max(Math.abs(zeroY - valY), 1);
97717
- const baseFill = varyColorsSingle ? resolveVaryColorFill(series[si], sourceIndex, paletteColor2(sourceIndex, palette)) : resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor22(series[si], si, palette);
97827
+ const baseFill = varyColorsSingle ? resolveVaryColorFill(series[si], sourceIndex, paletteColor2(sourceIndex, palette)) : resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
97718
97828
  primitives.push({
97719
97829
  kind: "rect",
97720
97830
  x,
@@ -97803,7 +97913,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97803
97913
  const topY = valueToY2(top, primaryRange, layout.plotTop, layout.plotBottom);
97804
97914
  const y = Math.min(baseY, topY);
97805
97915
  const h = Math.max(Math.abs(baseY - topY), 0.5);
97806
- const pctBaseFill = resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor22(series[si], si, palette);
97916
+ const pctBaseFill = resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
97807
97917
  primitives.push({
97808
97918
  kind: "rect",
97809
97919
  x,
@@ -98083,7 +98193,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98083
98193
  x: xPositions?.[index] ?? point.x
98084
98194
  })
98085
98195
  );
98086
- const c = seriesColor22(series, si, chartData.colorPalette);
98196
+ const c = seriesColor2(series, si, chartData.colorPalette);
98087
98197
  const seriesPart = { role: "series", seriesIndex: si };
98088
98198
  const allVisible = visible.every(Boolean);
98089
98199
  if (allVisible) {
@@ -98177,7 +98287,7 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98177
98287
  ...point,
98178
98288
  x: xPositions?.[index] ?? point.x
98179
98289
  }));
98180
- const c = seriesColor22(series, si, chartData.colorPalette);
98290
+ const c = seriesColor2(series, si, chartData.colorPalette);
98181
98291
  const lineStr = linePointsToSvgString(pts);
98182
98292
  const firstPt = pts[0];
98183
98293
  const lastPt = pts[pts.length - 1];
@@ -98265,7 +98375,7 @@ function buildScatter(chartData, layout, range) {
98265
98375
  const smoothStyle = chartData.scatterStyle === "smooth" || chartData.scatterStyle === "smoothMarker";
98266
98376
  for (let si = 0; si < chartData.series.length; si++) {
98267
98377
  const series = chartData.series[si];
98268
- const c = seriesColor22(series, si, chartData.colorPalette);
98378
+ const c = seriesColor2(series, si, chartData.colorPalette);
98269
98379
  const dots = computeScatterDots(
98270
98380
  series.values,
98271
98381
  maxXIndex,
@@ -98343,7 +98453,7 @@ function buildBubbles(chartData, layout, range) {
98343
98453
  const medianRadius = Math.min(layout.plotWidth, layout.plotHeight) * 0.04;
98344
98454
  for (let si = 0; si < chartData.series.length; si++) {
98345
98455
  const series = chartData.series[si];
98346
- const c = seriesColor22(series, si, chartData.colorPalette);
98456
+ const c = seriesColor2(series, si, chartData.colorPalette);
98347
98457
  const dots = computeScatterDots(
98348
98458
  series.values,
98349
98459
  maxXIndex,
@@ -98953,7 +99063,7 @@ function barFill(chartData, series, seriesIndex, pointIndex) {
98953
99063
  if (chartData.varyColors === true && chartData.series.length === 1) {
98954
99064
  return resolveVaryColorFill(series, pointIndex, paletteColor2(pointIndex, palette));
98955
99065
  }
98956
- return resolveDataPointFill(series, pointIndex, paletteColor2(seriesIndex, palette)) ?? seriesColor22(series, seriesIndex, palette);
99066
+ return resolveDataPointFill(series, pointIndex, paletteColor2(seriesIndex, palette)) ?? seriesColor2(series, seriesIndex, palette);
98957
99067
  }
98958
99068
  function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
98959
99069
  const layout = computePlotLayout(element.width, element.height, chartData, true);
@@ -99448,7 +99558,7 @@ function computeTrendlinePrimitives(chartData, catCount, layout, range, mode = "
99448
99558
  return;
99449
99559
  }
99450
99560
  const pathD = points3.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x.toFixed(2)} ${p.y.toFixed(2)}`).join(" ");
99451
- const strokeColor = tl.color ?? seriesColor22(series, si, colorPalette);
99561
+ const strokeColor = tl.color ?? seriesColor2(series, si, colorPalette);
99452
99562
  const pathPrimitive = {
99453
99563
  kind: "path",
99454
99564
  d: pathD,
@@ -99640,7 +99750,7 @@ function computeDataTablePrimitives(chartData, layout, colorPalette) {
99640
99750
  if (showK) {
99641
99751
  const swatchX = layout.plotLeft + DATA_TABLE_PADDING;
99642
99752
  const swatchY = ry + DATA_TABLE_ROW_H / 2 - 3;
99643
- const swatchColor = seriesColor22(s, si, colorPalette);
99753
+ const swatchColor = seriesColor2(s, si, colorPalette);
99644
99754
  out.push({
99645
99755
  kind: "rect",
99646
99756
  x: swatchX,
@@ -99963,7 +100073,7 @@ function buildComboViewModel(element, chartData, categoryLabels) {
99963
100073
  return;
99964
100074
  }
99965
100075
  const range = rangeForSeries(seriesIndex, primaryRange, secondaryRange, secondaryIndexes);
99966
- const fill = seriesColor22(series, seriesIndex, chartData.colorPalette);
100076
+ const fill = seriesColor2(series, seriesIndex, chartData.colorPalette);
99967
100077
  const points3 = sourceIndices2.map((sourceIndex, displayIndex) => {
99968
100078
  const value = series.values[sourceIndex] ?? 0;
99969
100079
  return {
@@ -100010,15 +100120,30 @@ function buildComboViewModel(element, chartData, categoryLabels) {
100010
100120
  });
100011
100121
  primitives.push(...horizontalAxis.tickMarks);
100012
100122
  const displayChartData = horizontalAxis.displayChartData;
100013
- primitives.push(
100123
+ const overlays = [
100014
100124
  ...computeErrorBarPrimitives(displayChartData, catCount, layout, primaryRange, "line", {
100015
100125
  xPositions: horizontalAxis.xPositions,
100016
100126
  seriesRanges: chartData.series.map(
100017
100127
  (_series, index) => rangeForSeries(index, primaryRange, secondaryRange, secondaryIndexes)
100018
100128
  ),
100019
100129
  seriesModes: chartData.series.map((_series, index) => index === 0 ? "bar" : "line")
100020
- })
100130
+ }),
100131
+ ...computeTrendlinePrimitives(
100132
+ displayChartData,
100133
+ catCount,
100134
+ layout,
100135
+ primaryRange,
100136
+ "bar",
100137
+ chartData.colorPalette
100138
+ ),
100139
+ ...computeAxisTitlePrimitives(chartData, layout)
100140
+ ];
100141
+ const dataTablePrimitives = computeDataTablePrimitives(
100142
+ displayChartData,
100143
+ layout,
100144
+ chartData.colorPalette
100021
100145
  );
100146
+ primitives.push(...overlays, ...dataTablePrimitives);
100022
100147
  return {
100023
100148
  svgWidth: layout.svgWidth,
100024
100149
  svgHeight: layout.svgHeight,
@@ -100036,7 +100161,9 @@ function buildComboViewModel(element, chartData, categoryLabels) {
100036
100161
  legendY,
100037
100162
  legendAnchor,
100038
100163
  secondaryGridlines: secondaryAxis?.gridlines,
100039
- secondaryAxisLabels: secondaryAxis?.axisLabels
100164
+ secondaryAxisLabels: secondaryAxis?.axisLabels,
100165
+ overlays: overlays.length > 0 ? overlays : void 0,
100166
+ dataTable: dataTablePrimitives.length > 0 ? dataTablePrimitives : void 0
100040
100167
  };
100041
100168
  }
100042
100169
  function appendBarLabels(series, chartData, layout, catCount, range, sourceIndices2, labels, xPositions) {
@@ -100073,7 +100200,7 @@ function buildStockViewModel(element, chartData, categoryLabels) {
100073
100200
  computeLayoutOptions(chartData.axes, chartData.dataTable, chartData.series.length)
100074
100201
  );
100075
100202
  const catCount = Math.max(categoryLabels.length, 1);
100076
- const range = computeValueRange2(chartData.series);
100203
+ const range = computeValueRangeForChart(chartData.series, chartData.axes);
100077
100204
  const valueAxis = chartData.axes?.find((axis) => axis.axisType === "valAx" && axis.axPos !== "r");
100078
100205
  const categoryAxis = chartData.axes?.find(
100079
100206
  (axis) => (axis.axisType === "catAx" || axis.axisType === "dateAx") && axis.axisId === valueAxis?.crossAxisId
@@ -100110,6 +100237,12 @@ function buildStockViewModel(element, chartData, categoryLabels) {
100110
100237
  const closeSeries = chartData.series[hasFour ? 3 : 2];
100111
100238
  const primitives = [];
100112
100239
  const dataLabels = [];
100240
+ primitives.push(
100241
+ ...computeHelperLinePrimitives(chartData, layout, range, catCount, {
100242
+ mode: "bar",
100243
+ xPositions: horizontalAxis.xPositions
100244
+ })
100245
+ );
100113
100246
  if (highSeries && lowSeries && closeSeries) {
100114
100247
  const barGroupWidth = layout.plotWidth / catCount;
100115
100248
  const candleWidth = barGroupWidth * 0.5;
@@ -100164,6 +100297,27 @@ function buildStockViewModel(element, chartData, categoryLabels) {
100164
100297
  }
100165
100298
  }
100166
100299
  primitives.push(...horizontalAxis.tickMarks);
100300
+ const displayChartData = horizontalAxis.displayChartData;
100301
+ const overlays = [
100302
+ ...computeTrendlinePrimitives(
100303
+ displayChartData,
100304
+ catCount,
100305
+ layout,
100306
+ range,
100307
+ "bar",
100308
+ chartData.colorPalette
100309
+ ),
100310
+ ...computeErrorBarPrimitives(displayChartData, catCount, layout, range, "bar", {
100311
+ xPositions: horizontalAxis.xPositions
100312
+ }),
100313
+ ...computeAxisTitlePrimitives(chartData, layout)
100314
+ ];
100315
+ const dataTablePrimitives = computeDataTablePrimitives(
100316
+ displayChartData,
100317
+ layout,
100318
+ chartData.colorPalette
100319
+ );
100320
+ primitives.push(...overlays, ...dataTablePrimitives);
100167
100321
  const title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
100168
100322
  return {
100169
100323
  svgWidth: layout.svgWidth,
@@ -100180,7 +100334,9 @@ function buildStockViewModel(element, chartData, categoryLabels) {
100180
100334
  legend: chartData.style?.hasLegend ? legend : [],
100181
100335
  legendX,
100182
100336
  legendY,
100183
- legendAnchor
100337
+ legendAnchor,
100338
+ overlays: overlays.length > 0 ? overlays : void 0,
100339
+ dataTable: dataTablePrimitives.length > 0 ? dataTablePrimitives : void 0
100184
100340
  };
100185
100341
  }
100186
100342
  function percentile(sorted, p, method) {
@@ -101413,7 +101569,8 @@ function buildIsometricSurfaceViewModel(element, chartData, categoryLabels) {
101413
101569
  fill: `rgb(${r},${g},${b})`,
101414
101570
  stroke: "none",
101415
101571
  strokeWidth: 0,
101416
- opacity: 0.9
101572
+ opacity: 0.9,
101573
+ part: { role: "dataPoint", seriesIndex: row, pointIndex: col }
101417
101574
  });
101418
101575
  primitives.push({
101419
101576
  kind: "polygon",
@@ -101468,7 +101625,8 @@ function buildFlatSurfaceViewModel(element, chartData, categoryLabels) {
101468
101625
  w: cellW + 0.5,
101469
101626
  h: cellH + 0.5,
101470
101627
  fill: `rgb(${r},${g},${b})`,
101471
- opacity: 0.85
101628
+ opacity: 0.85,
101629
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: ci }
101472
101630
  });
101473
101631
  }
101474
101632
  }
@@ -101738,6 +101896,7 @@ var WF_COLOR_POSITIVE = "#22c55e";
101738
101896
  var WF_COLOR_NEGATIVE = "#ef4444";
101739
101897
  var WF_COLOR_TOTAL = "#6366f1";
101740
101898
  var WF_CONNECTOR_COLOR = "#94a3b8";
101899
+ var REGION_LEGEND_BANDS = 32;
101741
101900
  function buildWaterfallViewModel(element, chartData, categoryLabels) {
101742
101901
  const layout = computePlotLayout(element.width, element.height, chartData, true);
101743
101902
  const series = chartData.series[0];
@@ -102171,6 +102330,10 @@ function buildRegionMapViewModel(element, chartData, categoryLabels) {
102171
102330
  fill,
102172
102331
  stroke: "#94a3b8",
102173
102332
  strokeWidth: Math.max(0.5 / mapScale, 0.3),
102333
+ // Hover tooltip. A choropleth prints only the value inside the shape
102334
+ // (and only where the shape is big enough), so without this the reader
102335
+ // has no way to find out WHICH country a patch of colour is.
102336
+ title: entry2 ? `${region.name}: ${formatAxisValue2(entry2.value)}` : region.name,
102174
102337
  ...entry2 ? {
102175
102338
  part: {
102176
102339
  role: "dataPoint",
@@ -102203,27 +102366,16 @@ function buildRegionMapViewModel(element, chartData, categoryLabels) {
102203
102366
  const legendY = mapOffsetY + mapAreaH + 4;
102204
102367
  const barW = Math.min(svgWidth * 0.4, 160);
102205
102368
  const barX = (svgWidth - barW) / 2;
102206
- const gradStops = [
102207
- { offset: 0, color: "#dbeafe" },
102208
- { offset: 0.5, color: "#3b82f6" },
102209
- { offset: 1, color: "#1e3a5f" }
102210
- ];
102211
- const stopCount = gradStops.length - 1;
102212
- for (let si = 0; si < stopCount; si++) {
102213
- const stopA = gradStops[si];
102214
- const stopB = gradStops[si + 1];
102215
- if (stopA === void 0 || stopB === void 0) {
102216
- continue;
102217
- }
102218
- const midColor = lerpColor(stopA.color, stopB.color, 0.5);
102369
+ for (let band = 0; band < REGION_LEGEND_BANDS; band++) {
102219
102370
  primitives.push({
102220
102371
  kind: "rect",
102221
- x: barX + stopA.offset * barW,
102372
+ x: barX + band / REGION_LEGEND_BANDS * barW,
102222
102373
  y: legendY,
102223
- w: (stopB.offset - stopA.offset) * barW,
102374
+ // A hair of overlap: adjacent rects on fractional pixel boundaries
102375
+ // otherwise leave hairline gaps once the slide's zoom transform lands.
102376
+ w: barW / REGION_LEGEND_BANDS + 0.5,
102224
102377
  h: 8,
102225
- fill: midColor,
102226
- rx: si === 0 ? 4 : 0
102378
+ fill: sequentialColorScale((band + 0.5) / REGION_LEGEND_BANDS)
102227
102379
  });
102228
102380
  }
102229
102381
  primitives.push(
@@ -102377,7 +102529,7 @@ function paletteColor2(index, colorPalette) {
102377
102529
  const pal = colorPalette && colorPalette.length > 0 ? colorPalette : DEFAULT_PALETTE;
102378
102530
  return pal[index % pal.length];
102379
102531
  }
102380
- function seriesColor22(series, index, colorPalette) {
102532
+ function seriesColor2(series, index, colorPalette) {
102381
102533
  return series.color ?? series.marker?.spPr?.fillColor ?? paletteColor2(index, colorPalette);
102382
102534
  }
102383
102535
  function computeValueRange2(series) {
@@ -102579,7 +102731,7 @@ function buildCategoryLabels(categoryLabels, layout, catSpacing) {
102579
102731
  }
102580
102732
  function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotTop) {
102581
102733
  const legend = series.map((s, i) => ({
102582
- color: seriesColor22(s, i, colorPalette),
102734
+ color: seriesColor2(s, i, colorPalette),
102583
102735
  label: s.name
102584
102736
  }));
102585
102737
  let legendX = svgWidth / 2;
@@ -102617,7 +102769,7 @@ function computeBarRects(series, catCount, layout, range, colorPalette) {
102617
102769
  y,
102618
102770
  w: singleBarWidth,
102619
102771
  h,
102620
- fill: seriesColor22(series[si], si, colorPalette)
102772
+ fill: seriesColor2(series[si], si, colorPalette)
102621
102773
  });
102622
102774
  }
102623
102775
  }
@@ -102650,7 +102802,7 @@ function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102650
102802
  y,
102651
102803
  w: barW,
102652
102804
  h,
102653
- fill: seriesColor22(series[si], si, colorPalette),
102805
+ fill: seriesColor2(series[si], si, colorPalette),
102654
102806
  seriesIndex: si,
102655
102807
  pointIndex: ci
102656
102808
  });
@@ -102662,7 +102814,7 @@ function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102662
102814
  y,
102663
102815
  w: barW,
102664
102816
  h,
102665
- fill: seriesColor22(series[si], si, colorPalette),
102817
+ fill: seriesColor2(series[si], si, colorPalette),
102666
102818
  seriesIndex: si,
102667
102819
  pointIndex: ci
102668
102820
  });
@@ -102790,6 +102942,9 @@ function radarRingPoints(cx, cy, rr, catCount) {
102790
102942
  return `${(cx + rr * Math.cos(angle)).toFixed(2)},${(cy + rr * Math.sin(angle)).toFixed(2)}`;
102791
102943
  }).join(" ");
102792
102944
  }
102945
+ function chartPreserveAspectRatio(kind) {
102946
+ return kind === "pie" || kind === "doughnut" || kind === "radar" || kind === "regionMap" ? "xMidYMid meet" : "none";
102947
+ }
102793
102948
  function resolveChartKind(chartType) {
102794
102949
  switch (chartType) {
102795
102950
  case "bar":
@@ -103102,7 +103257,7 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103102
103257
  }
103103
103258
  const dataLabels = [];
103104
103259
  chartData.series.forEach((series, si) => {
103105
- const c = seriesColor22(series, si, chartData.colorPalette);
103260
+ const c = seriesColor2(series, si, chartData.colorPalette);
103106
103261
  const pts = computeRadarPoints(series.values, maxVal, radius, cx, cy, catCount);
103107
103262
  if (pts.length === 0) {
103108
103263
  return;
@@ -103342,6 +103497,31 @@ function withChartTitle(chartData, title) {
103342
103497
  style: { ...chartData.style, hasTitle: trimmed.length > 0 }
103343
103498
  };
103344
103499
  }
103500
+ var STYLE_ELEMENT_ID = "pptx-chart-interaction-styles";
103501
+ var INTERACTION_CSS = `
103502
+ .pptx-chart-interactive svg [data-chart-part] { pointer-events: auto; cursor: pointer; }
103503
+ .pptx-chart-interactive svg [data-chart-part]:hover { filter: brightness(1.12); }
103504
+ .pptx-chart-interactive svg [data-chart-part='title'] { cursor: text; }
103505
+ /* A data label is decoration painted ON TOP of the mark it describes, so it
103506
+ must never intercept that mark's click. The treemap made this unmissable -
103507
+ its label sits dead-centre on the cell, so clicking a cell hit the <text> and
103508
+ selected nothing - but every kind's data labels overlap their marks. Only
103509
+ labels are excluded: the chart title is itself a part and stays clickable.
103510
+ Bindings whose chart <svg> is blanket pointer-events:none (React) never saw
103511
+ this; the other three did, which is exactly why the rule belongs here. */
103512
+ .pptx-chart-interactive svg text:not([data-chart-part]) { pointer-events: none; }
103513
+ .pptx-chart-interactive svg .pptx-chart-part-selected { filter: drop-shadow(0 0 2.5px #3b82f6); }
103514
+ .pptx-chart-interactive svg .pptx-chart-part-selected:hover { filter: drop-shadow(0 0 2.5px #3b82f6) brightness(1.12); }
103515
+ `;
103516
+ function ensureChartInteractionStyles() {
103517
+ if (typeof document === "undefined" || document.getElementById(STYLE_ELEMENT_ID)) {
103518
+ return;
103519
+ }
103520
+ const style = document.createElement("style");
103521
+ style.id = STYLE_ELEMENT_ID;
103522
+ style.textContent = INTERACTION_CSS;
103523
+ document.head.appendChild(style);
103524
+ }
103345
103525
  var HARD_STOP = "#000 50%, transparent 50%";
103346
103526
  var EDGE_CONFIG = {
103347
103527
  left: {
@@ -109722,12 +109902,21 @@ var translationsEn = {
109722
109902
  "pptx.autosave.disabled": "AutoSave unavailable",
109723
109903
  "pptx.autosave.disabledNoFilePath": "AutoSave disabled: no file path provided",
109724
109904
  "pptx.autosave.disabledToggleOff": "AutoSave off",
109905
+ "pptx.autosave.disabledByHost": "AutoSave turned off by this application",
109906
+ "pptx.autosave.disabledReadOnly": "AutoSave disabled: this presentation is read-only",
109725
109907
  "pptx.autosave.justNow": "just now",
109726
109908
  "pptx.autosave.oneMinAgo": "1 min ago",
109727
109909
  "pptx.autosave.minutesAgo": "{{count}} min ago",
109728
109910
  "pptx.autosave.saveFailed": "Save failed",
109729
109911
  "pptx.autosave.savedShort": "Saved",
109730
109912
  "pptx.autosave.allChangesSaved": "All changes saved",
109913
+ // Crash-recovery prompt (offered on load when a newer snapshot exists)
109914
+ "pptx.autosave.recovery.title": "Recover unsaved changes?",
109915
+ "pptx.autosave.recovery.message": 'An autosaved copy of "{{file}}" ({{size}}) has changes that are not in the version you just opened.',
109916
+ "pptx.autosave.recovery.savedLabel": "Autosaved {{when}}",
109917
+ "pptx.autosave.recovery.hoursAgo": "{{count}} h ago",
109918
+ "pptx.autosave.recovery.restore": "Restore",
109919
+ "pptx.autosave.recovery.discard": "Discard",
109731
109920
  // Title bar (PowerPoint-style top chrome row)
109732
109921
  "pptx.titleBar.autoSave": "AutoSave",
109733
109922
  "pptx.titleBar.autoSaveOn": "On",
@@ -124492,268 +124681,6 @@ async function mountModel3D(container, modelUrl, options) {
124492
124681
  }
124493
124682
  };
124494
124683
  }
124495
- var GRID_SPACING = 0.5;
124496
- var MAX_HEIGHT = 1.5;
124497
- function computeGridExtent(cols, rows) {
124498
- return {
124499
- gridWidth: Math.max(cols - 1, 1) * GRID_SPACING,
124500
- gridDepth: Math.max(rows - 1, 1) * GRID_SPACING
124501
- };
124502
- }
124503
- function buildSurfaceGeometry(three, cols, rows, heightMap, colorMap) {
124504
- const widthSegs = Math.max(cols - 1, 0);
124505
- const depthSegs = Math.max(rows - 1, 0);
124506
- const { gridWidth, gridDepth } = computeGridExtent(cols, rows);
124507
- const geo = new three.PlaneGeometry(gridWidth, gridDepth, widthSegs, depthSegs);
124508
- geo.rotateX(-Math.PI / 2);
124509
- const pos2 = geo.attributes.position;
124510
- const vertexCount = pos2.count;
124511
- const colors = new Float32Array(vertexCount * 3);
124512
- for (let i = 0; i < vertexCount; i++) {
124513
- const row = Math.floor(i / cols);
124514
- const col = i % cols;
124515
- const idx = row * cols + col;
124516
- const h = idx < heightMap.length ? heightMap[idx] : 0;
124517
- pos2.setY(i, h * MAX_HEIGHT);
124518
- const ci = idx * 3;
124519
- colors[i * 3] = ci < colorMap.length ? colorMap[ci] : 0.5;
124520
- colors[i * 3 + 1] = ci + 1 < colorMap.length ? colorMap[ci + 1] : 0.5;
124521
- colors[i * 3 + 2] = ci + 2 < colorMap.length ? colorMap[ci + 2] : 0.5;
124522
- }
124523
- geo.setAttribute("color", new three.BufferAttribute(colors, 3));
124524
- geo.computeVertexNormals();
124525
- pos2.needsUpdate = true;
124526
- const wireGeometry = new three.WireframeGeometry(geo);
124527
- return { geometry: geo, wireGeometry };
124528
- }
124529
- function buildSurfaceLabels(cols, rows, categoryLabels, seriesNames, maxCat = 8, maxSer = 6) {
124530
- const { gridWidth, gridDepth } = computeGridExtent(cols, rows);
124531
- const labels = [];
124532
- const catStep = Math.max(1, Math.ceil(categoryLabels.length / maxCat));
124533
- for (let i = 0; i < categoryLabels.length; i += catStep) {
124534
- const x = -gridWidth / 2 + i / Math.max(cols - 1, 1) * gridWidth;
124535
- labels.push({
124536
- key: `cat-${i}`,
124537
- text: categoryLabels[i],
124538
- anchor: [x, -0.15, gridDepth / 2 + 0.25],
124539
- axis: "category"
124540
- });
124541
- }
124542
- const serStep = Math.max(1, Math.ceil(seriesNames.length / maxSer));
124543
- for (let i = 0; i < seriesNames.length; i += serStep) {
124544
- const z = -gridDepth / 2 + i / Math.max(rows - 1, 1) * gridDepth;
124545
- labels.push({
124546
- key: `ser-${i}`,
124547
- text: seriesNames[i],
124548
- anchor: [gridWidth / 2 + 0.3, -0.15, z],
124549
- axis: "series"
124550
- });
124551
- }
124552
- labels.push({
124553
- key: "value-axis",
124554
- text: "Value",
124555
- anchor: [-gridWidth / 2 - 0.35, 0.75, -gridDepth / 2],
124556
- axis: "value"
124557
- });
124558
- return labels;
124559
- }
124560
- function computeCameraPlacement(cols, rows) {
124561
- const { gridWidth, gridDepth } = computeGridExtent(cols, rows);
124562
- const maxExtent = Math.max(gridWidth, gridDepth, MAX_HEIGHT);
124563
- const dist2 = maxExtent * 1.8;
124564
- return {
124565
- position: [dist2 * 0.8, dist2 * 0.7, dist2 * 0.8],
124566
- target: [0, 0.3, 0]
124567
- };
124568
- }
124569
- var SURFACE_THREE_UNAVAILABLE = {
124570
- ok: false,
124571
- resize: () => {
124572
- },
124573
- dispose: () => {
124574
- }
124575
- };
124576
- var FOV2 = 45;
124577
- async function loadThree2() {
124578
- try {
124579
- return await import('./three.module-GNNNRIMK.js');
124580
- } catch {
124581
- return null;
124582
- }
124583
- }
124584
- async function loadOrbitControlsCtor2() {
124585
- try {
124586
- const mod = await import('./OrbitControls-SMYCPLXO.js');
124587
- return mod.OrbitControls;
124588
- } catch {
124589
- return null;
124590
- }
124591
- }
124592
- function createLabelOverlay(doc, labels) {
124593
- const layer = doc.createElement("div");
124594
- Object.assign(layer.style, {
124595
- position: "absolute",
124596
- inset: "0",
124597
- pointerEvents: "none",
124598
- overflow: "hidden"
124599
- });
124600
- const nodes = labels.map((label) => {
124601
- const node = doc.createElement("div");
124602
- node.textContent = label.text;
124603
- const color2 = label.axis === "value" ? "#999" : "#666";
124604
- Object.assign(node.style, {
124605
- position: "absolute",
124606
- fontSize: "9px",
124607
- color: color2,
124608
- whiteSpace: "nowrap",
124609
- userSelect: "none",
124610
- transform: "translate(-50%, -50%)",
124611
- willChange: "left, top"
124612
- });
124613
- if (label.axis === "value") {
124614
- node.style.writingMode = "vertical-rl";
124615
- }
124616
- layer.appendChild(node);
124617
- return node;
124618
- });
124619
- return { layer, nodes };
124620
- }
124621
- async function mountSurfaceChart3D(container, options) {
124622
- const three = await loadThree2();
124623
- const OrbitCtrlCtor = three ? await loadOrbitControlsCtor2() : null;
124624
- if (!three || !OrbitCtrlCtor) {
124625
- return SURFACE_THREE_UNAVAILABLE;
124626
- }
124627
- const { cols, rows } = options;
124628
- let width = Math.max(1, options.width);
124629
- let height = Math.max(1, options.height);
124630
- const renderer = new three.WebGLRenderer({ antialias: true, alpha: true });
124631
- renderer.setPixelRatio(
124632
- Math.min(
124633
- typeof window === "undefined" ? 1 : window.devicePixelRatio || 1,
124634
- options.maxPixelRatio ?? 2
124635
- )
124636
- );
124637
- renderer.setSize(width, height, false);
124638
- const canvas = renderer.domElement;
124639
- canvas.style.width = `${width}px`;
124640
- canvas.style.height = `${height}px`;
124641
- canvas.style.display = "block";
124642
- canvas.style.willChange = "transform";
124643
- container.appendChild(canvas);
124644
- const scene = new three.Scene();
124645
- scene.add(new three.AmbientLight(16777215, 0.6));
124646
- const key2 = new three.DirectionalLight(16777215, 0.8);
124647
- key2.position.set(5, 8, 5);
124648
- scene.add(key2);
124649
- const fill = new three.DirectionalLight(16777215, 0.3);
124650
- fill.position.set(-3, 4, -2);
124651
- scene.add(fill);
124652
- const camera = new three.PerspectiveCamera(FOV2, width / height, 0.1, 1e3);
124653
- const placement = computeCameraPlacement(cols, rows);
124654
- camera.position.set(...placement.position);
124655
- const target = new three.Vector3(...placement.target);
124656
- camera.lookAt(target);
124657
- const { gridWidth, gridDepth } = computeGridExtent(cols, rows);
124658
- const floorSize = Math.max(gridWidth, gridDepth) * 1.2;
124659
- const gridFloor = new three.GridHelper(floorSize, Math.max(cols, rows), 13421772, 15263976);
124660
- gridFloor.position.y = -0.02;
124661
- scene.add(gridFloor);
124662
- const { geometry, wireGeometry } = buildSurfaceGeometry(
124663
- three,
124664
- cols,
124665
- rows,
124666
- options.heightMap,
124667
- options.colorMap
124668
- );
124669
- const surfaceMaterial = new three.MeshPhongMaterial({
124670
- vertexColors: true,
124671
- side: three.DoubleSide,
124672
- shininess: 30,
124673
- transparent: true,
124674
- opacity: 0.92
124675
- });
124676
- const surfaceMesh = new three.Mesh(geometry, surfaceMaterial);
124677
- scene.add(surfaceMesh);
124678
- let wireMaterial = null;
124679
- if (options.wireframe) {
124680
- wireMaterial = new three.LineBasicMaterial({
124681
- color: 3355443,
124682
- transparent: true,
124683
- opacity: 0.25
124684
- });
124685
- scene.add(new three.LineSegments(wireGeometry, wireMaterial));
124686
- }
124687
- const controls = new OrbitCtrlCtor(camera, canvas);
124688
- controls.enablePan = true;
124689
- controls.enableZoom = true;
124690
- controls.enableRotate = true;
124691
- controls.minDistance = 1;
124692
- controls.maxDistance = 20;
124693
- controls.maxPolarAngle = Math.PI / 2 + 0.3;
124694
- controls.target.copy(target);
124695
- controls.update();
124696
- const doc = container.ownerDocument ?? document;
124697
- const labels = buildSurfaceLabels(cols, rows, options.categoryLabels, options.seriesNames);
124698
- const { layer, nodes } = createLabelOverlay(doc, labels);
124699
- container.appendChild(layer);
124700
- const anchors = labels.map((l) => new three.Vector3(...l.anchor));
124701
- const projected = new three.Vector3();
124702
- const updateLabels = () => {
124703
- for (let i = 0; i < nodes.length; i++) {
124704
- projected.copy(anchors[i]).project(camera);
124705
- const node = nodes[i];
124706
- if (projected.z > 1) {
124707
- node.style.display = "none";
124708
- continue;
124709
- }
124710
- node.style.display = "";
124711
- node.style.left = `${(projected.x + 1) / 2 * width}px`;
124712
- node.style.top = `${(-projected.y + 1) / 2 * height}px`;
124713
- }
124714
- };
124715
- let frame2 = 0;
124716
- let disposed = false;
124717
- const renderLoop = () => {
124718
- if (disposed) {
124719
- return;
124720
- }
124721
- frame2 = requestAnimationFrame(renderLoop);
124722
- controls.update();
124723
- renderer.render(scene, camera);
124724
- updateLabels();
124725
- };
124726
- frame2 = requestAnimationFrame(renderLoop);
124727
- return {
124728
- ok: true,
124729
- resize(w, h) {
124730
- width = Math.max(1, w);
124731
- height = Math.max(1, h);
124732
- camera.aspect = width / height;
124733
- camera.updateProjectionMatrix();
124734
- renderer.setSize(width, height, false);
124735
- canvas.style.width = `${width}px`;
124736
- canvas.style.height = `${height}px`;
124737
- },
124738
- dispose() {
124739
- if (disposed) {
124740
- return;
124741
- }
124742
- disposed = true;
124743
- cancelAnimationFrame(frame2);
124744
- controls.dispose();
124745
- geometry.dispose();
124746
- wireGeometry.dispose();
124747
- surfaceMaterial.dispose();
124748
- wireMaterial?.dispose();
124749
- gridFloor.dispose();
124750
- scene.clear();
124751
- renderer.dispose();
124752
- canvas.remove();
124753
- layer.remove();
124754
- }
124755
- };
124756
- }
124757
124684
  var AVERAGE_ADVANCE_RATIO = 0.5;
124758
124685
  function wrapTextByEstimatedWidth(text2, maxWidth, fontSize, options = {}) {
124759
124686
  if (!text2 || text2.trim().length === 0) {
@@ -125156,6 +125083,7 @@ function savedPresentationFileName(sourceName, format = "pptx") {
125156
125083
  var AUTOSAVE_DB_NAME = "pptx-viewer-autosave";
125157
125084
  var AUTOSAVE_DB_VERSION = 1;
125158
125085
  var AUTOSAVE_STORE_NAME = "recoveryVersions";
125086
+ var AUTOSAVE_DEFAULT_INTERVAL_SECONDS = 120;
125159
125087
  var AUTOSAVE_MIN_INTERVAL_SECONDS = 10;
125160
125088
  function openAutosaveDb() {
125161
125089
  return new Promise((resolve2, reject) => {
@@ -125319,6 +125247,117 @@ async function saveAutosaveSnapshot(filePath, data) {
125319
125247
  return putAutosaveRecord(filePath, data);
125320
125248
  }
125321
125249
  }
125250
+ var AUTOSAVE_RECOVERY_WINDOW_MS = 24 * 60 * 60 * 1e3;
125251
+ var CONSUMED_KEY = "pptx-viewer-recovery-consumed";
125252
+ function markAutosaveSnapshotConsumed(timestamp) {
125253
+ try {
125254
+ if (typeof sessionStorage === "undefined" || !Number.isFinite(timestamp)) {
125255
+ return;
125256
+ }
125257
+ const previous = consumedAutosaveSnapshotTimestamp();
125258
+ if (timestamp > previous) {
125259
+ sessionStorage.setItem(CONSUMED_KEY, String(timestamp));
125260
+ }
125261
+ } catch {
125262
+ }
125263
+ }
125264
+ function consumedAutosaveSnapshotTimestamp() {
125265
+ try {
125266
+ if (typeof sessionStorage === "undefined") {
125267
+ return 0;
125268
+ }
125269
+ const raw = sessionStorage.getItem(CONSUMED_KEY);
125270
+ const value = raw === null ? Number.NaN : Number(raw);
125271
+ return Number.isFinite(value) ? value : 0;
125272
+ } catch {
125273
+ return 0;
125274
+ }
125275
+ }
125276
+ function shouldProbeAutosaveRecovery(input) {
125277
+ return !input.alreadyChecked && input.autosaveAllowed && Boolean(input.filePath) && !input.loading && !input.error && input.slideCount > 0;
125278
+ }
125279
+ function formatSnapshotSize(bytes) {
125280
+ if (!Number.isFinite(bytes) || bytes <= 0) {
125281
+ return "0 KB";
125282
+ }
125283
+ if (bytes < 1024 * 1024) {
125284
+ return `${Math.max(1, Math.round(bytes / 1024))} KB`;
125285
+ }
125286
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
125287
+ }
125288
+ function ageKeyFor(ageMinutes) {
125289
+ if (ageMinutes < 1) {
125290
+ return { key: "pptx.autosave.justNow", count: 0 };
125291
+ }
125292
+ if (ageMinutes === 1) {
125293
+ return { key: "pptx.autosave.oneMinAgo", count: 1 };
125294
+ }
125295
+ if (ageMinutes < 60) {
125296
+ return { key: "pptx.autosave.minutesAgo", count: ageMinutes };
125297
+ }
125298
+ return { key: "pptx.autosave.recovery.hoursAgo", count: Math.floor(ageMinutes / 60) };
125299
+ }
125300
+ function autosaveRecoveryPrompt(input) {
125301
+ const record = input.record;
125302
+ if (!record || record.size <= 0 || !record.key) {
125303
+ return null;
125304
+ }
125305
+ const age = input.now - record.timestamp;
125306
+ if (!Number.isFinite(age) || age < 0 || age >= AUTOSAVE_RECOVERY_WINDOW_MS) {
125307
+ return null;
125308
+ }
125309
+ if (record.timestamp <= (input.consumedTimestamp ?? 0)) {
125310
+ return null;
125311
+ }
125312
+ const ageMinutes = Math.floor(age / 6e4);
125313
+ const relative = ageKeyFor(ageMinutes);
125314
+ return {
125315
+ filePath: record.key,
125316
+ timestamp: record.timestamp,
125317
+ size: record.size,
125318
+ ageMinutes,
125319
+ titleKey: "pptx.autosave.recovery.title",
125320
+ messageKey: "pptx.autosave.recovery.message",
125321
+ messageParams: { file: record.key, size: formatSnapshotSize(record.size) },
125322
+ ageKey: relative.key,
125323
+ ageParams: { count: relative.count },
125324
+ restoreKey: "pptx.autosave.recovery.restore",
125325
+ discardKey: "pptx.autosave.recovery.discard"
125326
+ };
125327
+ }
125328
+ function shouldShowAutosaveRecoveryPrompt(input) {
125329
+ return Boolean(input.prompt) && !input.presenting;
125330
+ }
125331
+ async function probeAutosaveRecovery(filePath, now = Date.now()) {
125332
+ if (typeof indexedDB === "undefined") {
125333
+ return null;
125334
+ }
125335
+ try {
125336
+ const record = await getAutosaveSnapshot(filePath);
125337
+ const prompt = autosaveRecoveryPrompt({
125338
+ record: record ? { key: record.key, timestamp: record.timestamp, size: record.size } : void 0,
125339
+ now,
125340
+ consumedTimestamp: consumedAutosaveSnapshotTimestamp()
125341
+ });
125342
+ if (!prompt || !record) {
125343
+ return null;
125344
+ }
125345
+ return { prompt, record };
125346
+ } catch {
125347
+ return null;
125348
+ }
125349
+ }
125350
+ function acceptAutosaveRecovery(record) {
125351
+ markAutosaveSnapshotConsumed(record.timestamp);
125352
+ return record.data instanceof Uint8Array ? record.data : new Uint8Array(record.data);
125353
+ }
125354
+ async function discardAutosaveRecovery(record) {
125355
+ markAutosaveSnapshotConsumed(record.timestamp);
125356
+ try {
125357
+ await deleteAutosaveSnapshot(record.key);
125358
+ } catch {
125359
+ }
125360
+ }
125322
125361
  function secureRandomBytes(length) {
125323
125362
  const bytes = new Uint8Array(length);
125324
125363
  if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
@@ -125517,6 +125556,7 @@ async function restoreSessionDeck() {
125517
125556
  const snapshot = await getAutosaveSnapshot(deck.fileName);
125518
125557
  const bytes = snapshot ? toBytes(snapshot.data) : null;
125519
125558
  if (snapshot && bytes && bytes.byteLength > 0 && snapshot.timestamp > deck.timestamp) {
125559
+ markAutosaveSnapshotConsumed(snapshot.timestamp);
125520
125560
  return { fileName: deck.fileName, data: bytes, timestamp: snapshot.timestamp };
125521
125561
  }
125522
125562
  } catch {
@@ -126907,11 +126947,13 @@ var TITLE_PH_TYPES = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
126907
126947
  var CHROME_PH_TYPES = /* @__PURE__ */ new Set(["ftr", "hdr", "dt", "sldnum"]);
126908
126948
  var OUTLINE_TITLE_ELEMENT_NAME = "Title";
126909
126949
  function placeholderType(element) {
126910
- const ph = element.rawXml?.["p:nvSpPr"]?.["p:nvPr"]?.["p:ph"];
126911
- if (!ph) {
126950
+ const nvPr = element.rawXml?.["p:nvSpPr"]?.["p:nvPr"];
126951
+ const ph = nvPr === void 0 || typeof nvPr === "string" ? void 0 : nvPr["p:ph"];
126952
+ if (ph === void 0) {
126912
126953
  return void 0;
126913
126954
  }
126914
- const type = typeof ph["@_type"] === "string" ? ph["@_type"].trim().toLowerCase() : "";
126955
+ const rawType = typeof ph === "object" && ph !== null ? ph["@_type"] : void 0;
126956
+ const type = typeof rawType === "string" ? rawType.trim().toLowerCase() : "";
126915
126957
  return type.length > 0 ? type : "body";
126916
126958
  }
126917
126959
  function isTextBearing(element) {
@@ -130742,6 +130784,34 @@ function shouldWriteAutosaveSnapshot(input) {
130742
130784
  }
130743
130785
  return input.sources.some((source, index) => !Object.is(source, previous.sources[index]));
130744
130786
  }
130787
+ function resolveAutosaveActivation(input) {
130788
+ if (input.hostAutosave === false) {
130789
+ return { active: false, toggleAvailable: false, reason: "autosave_host_off" };
130790
+ }
130791
+ if (!input.userEnabled) {
130792
+ return { active: false, toggleAvailable: true, reason: "autosave_toggle_off" };
130793
+ }
130794
+ if (!input.filePath) {
130795
+ return { active: false, toggleAvailable: true, reason: "no_file_path" };
130796
+ }
130797
+ if (!input.canEdit) {
130798
+ return { active: false, toggleAvailable: true, reason: "read_only" };
130799
+ }
130800
+ return { active: true, toggleAvailable: true };
130801
+ }
130802
+ var AUTOSAVE_DEFAULT_INTERVAL_MS = AUTOSAVE_DEFAULT_INTERVAL_SECONDS * 1e3;
130803
+ var HOST_INTERVAL_FLOOR_MS = 50;
130804
+ function resolveAutosaveIntervalMs(input) {
130805
+ const host = input.hostIntervalMs;
130806
+ if (typeof host === "number" && Number.isFinite(host)) {
130807
+ return Math.max(HOST_INTERVAL_FLOOR_MS, host);
130808
+ }
130809
+ const seconds = input.optionsIntervalSeconds;
130810
+ if (typeof seconds === "number" && Number.isFinite(seconds)) {
130811
+ return Math.max(AUTOSAVE_MIN_INTERVAL_SECONDS, seconds) * 1e3;
130812
+ }
130813
+ return AUTOSAVE_DEFAULT_INTERVAL_MS;
130814
+ }
130745
130815
  var BACKSTAGE_NAV = [
130746
130816
  { id: "home", label: "Home", labelKey: "pptx.backstage.nav.home" },
130747
130817
  { id: "new", label: "New", labelKey: "pptx.backstage.nav.new" },
@@ -134105,6 +134175,7 @@ exports.VIEWER_OPTIONS_TABS = VIEWER_OPTIONS_TABS;
134105
134175
  exports.VIEWER_PREFS_STORAGE_KEY = VIEWER_PREFS_STORAGE_KEY;
134106
134176
  exports.VIEWER_SHORTCUT_REFERENCE = VIEWER_SHORTCUT_REFERENCE;
134107
134177
  exports.WEBM_MIME_CANDIDATES = WEBM_MIME_CANDIDATES;
134178
+ exports.acceptAutosaveRecovery = acceptAutosaveRecovery;
134108
134179
  exports.acceptsPresentationInput = acceptsPresentationInput;
134109
134180
  exports.actionAffordanceLabels = actionAffordanceLabels;
134110
134181
  exports.activateModalFocus = activateModalFocus;
@@ -134207,9 +134278,9 @@ exports.canvasToJpegData = canvasToJpegData;
134207
134278
  exports.cellRunStyle = cellRunStyle;
134208
134279
  exports.cellStyleToCss = cellStyleToCss;
134209
134280
  exports.centeredSvgTextLines = centeredSvgTextLines;
134210
- exports.chartAreaFill = chartAreaFill;
134211
134281
  exports.chartDataChangeType = chartDataChangeType;
134212
134282
  exports.chartPartToAttrs = chartPartToAttrs;
134283
+ exports.chartPreserveAspectRatio = chartPreserveAspectRatio;
134213
134284
  exports.clampCropValue = clampCropValue;
134214
134285
  exports.clampNotesFontSize = clampNotesFontSize;
134215
134286
  exports.clampPercent = clampPercent;
@@ -134242,8 +134313,6 @@ exports.computeEntranceAnimationDelay = computeEntranceAnimationDelay;
134242
134313
  exports.computeHandoutLayout = computeHandoutLayout;
134243
134314
  exports.computeInlineEditorRect = computeInlineEditorRect;
134244
134315
  exports.computeKeyboardInset = computeKeyboardInset;
134245
- exports.computeLayout = computeLayout;
134246
- exports.computeLayoutOptions = computeLayoutOptions;
134247
134316
  exports.computeMarqueeHitIds = computeMarqueeHitIds;
134248
134317
  exports.computeMergeCellDown = computeMergeCellDown;
134249
134318
  exports.computeMergeCellRight = computeMergeCellRight;
@@ -134254,8 +134323,6 @@ exports.computeSelectionRect = computeSelectionRect;
134254
134323
  exports.computeSmartArtLayout = computeSmartArtLayout2;
134255
134324
  exports.computeSnapToShape = computeSnapToShape;
134256
134325
  exports.computeSplitCell = computeSplitCell;
134257
- exports.computeValueRange = computeValueRange;
134258
- exports.computeValueRangeForChart = computeValueRangeForChart;
134259
134326
  exports.computeVirtualRange = computeVirtualRange;
134260
134327
  exports.convertLatexToOmml = convertLatexToOmml;
134261
134328
  exports.convertOmmlToLatex = convertOmmlToLatex;
@@ -134292,6 +134359,7 @@ exports.deriveSlideFieldContext = deriveSlideFieldContext;
134292
134359
  exports.describeFontEmbedding = describeFontEmbedding;
134293
134360
  exports.detectOrientation = detectOrientation;
134294
134361
  exports.detectTouchDevice = detectTouchDevice;
134362
+ exports.discardAutosaveRecovery = discardAutosaveRecovery;
134295
134363
  exports.distributeElements = distributeElements;
134296
134364
  exports.downloadBlob = downloadBlob;
134297
134365
  exports.downloadDataUrl = downloadDataUrl;
@@ -134303,6 +134371,7 @@ exports.embeddedFontSaveOptions = embeddedFontSaveOptions;
134303
134371
  exports.encodeGif = encodeGif;
134304
134372
  exports.endAudienceDisplay = endAudienceDisplay;
134305
134373
  exports.ensureActionAffordanceStyles = ensureActionAffordanceStyles;
134374
+ exports.ensureChartInteractionStyles = ensureChartInteractionStyles;
134306
134375
  exports.erasePresentationInkAt = erasePresentationInkAt;
134307
134376
  exports.escapeHtml2 = escapeHtml22;
134308
134377
  exports.exportDeckJson = exportDeckJson;
@@ -134321,7 +134390,6 @@ exports.flattenNodes = flattenNodes;
134321
134390
  exports.flattenTagCollections = flattenTagCollections;
134322
134391
  exports.forgetSessionDeck = forgetSessionDeck;
134323
134392
  exports.formatAxisValue = formatAxisValue;
134324
- exports.formatAxisValueWithUnits = formatAxisValueWithUnits;
134325
134393
  exports.formatBackstageDate = formatBackstageDate;
134326
134394
  exports.formatBackstageSize = formatBackstageSize;
134327
134395
  exports.formatBytes = formatBytes;
@@ -134335,7 +134403,6 @@ exports.formatVersionTimestamp = formatVersionTimestamp;
134335
134403
  exports.fpsToFrameIntervalMs = fpsToFrameIntervalMs;
134336
134404
  exports.generateBroadcastRoomId = generateBroadcastRoomId;
134337
134405
  exports.generateElementId = generateElementId;
134338
- exports.generateLogTicks = generateLogTicks;
134339
134406
  exports.generateNoteLineCount = generateNoteLineCount;
134340
134407
  exports.generatePackageReadme = generatePackageReadme;
134341
134408
  exports.generatePressureCircles = generatePressureCircles;
@@ -134358,7 +134425,6 @@ exports.getComputedStrokeStyle = getComputedStrokeStyle;
134358
134425
  exports.getConnectorEndpointHandles = getConnectorEndpointHandles;
134359
134426
  exports.getContentPartReplayStyles = getContentPartReplayStyles;
134360
134427
  exports.getCurrentParagraphIndex = getCurrentParagraphIndex;
134361
- exports.getDisplayUnitLabel = getDisplayUnitLabel;
134362
134428
  exports.getDraggedShapeAdjustments = getDraggedShapeAdjustments;
134363
134429
  exports.getDuotoneCachedResult = getDuotoneCachedResult;
134364
134430
  exports.getElementLabel = getElementLabel;
@@ -134386,7 +134452,6 @@ exports.getPresetShapeClipPath = getPresetShapeClipPath;
134386
134452
  exports.getPrintableArea = getPrintableArea;
134387
134453
  exports.getResolvedShapeClipPath = getResolvedShapeClipPath;
134388
134454
  exports.getRoundRectRadiusPx2 = getRoundRectRadiusPx2;
134389
- exports.getSecondaryValueAxis = getSecondaryValueAxis;
134390
134455
  exports.getSessionTabId = getSessionTabId;
134391
134456
  exports.getShapeAdjustmentHandleDescriptors = getShapeAdjustmentHandleDescriptors;
134392
134457
  exports.getShapeConnectionSites = getShapeConnectionSites;
@@ -134482,7 +134547,6 @@ exports.motionPathPresetLabelKey = motionPathPresetLabelKey;
134482
134547
  exports.motionPathPresetsByFamily = motionPathPresetsByFamily;
134483
134548
  exports.motionPathToSvgD = motionPathToSvgD;
134484
134549
  exports.mountModel3D = mountModel3D;
134485
- exports.mountSurfaceChart3D = mountSurfaceChart3D;
134486
134550
  exports.movePresenterPointer = movePresenterPointer;
134487
134551
  exports.moveQuickAccessCommand = moveQuickAccessCommand;
134488
134552
  exports.moveSectionDown = moveSectionDown;
@@ -134495,7 +134559,6 @@ exports.normalizeColorsForCapture = normalizeColorsForCapture;
134495
134559
  exports.normalizeHexColor = normalizeHexColor;
134496
134560
  exports.normalizeSegments = normalizeSegments;
134497
134561
  exports.normalizeStrokeDashType = normalizeStrokeDashType;
134498
- exports.normalizeValue = normalizeValue;
134499
134562
  exports.notesSegmentsToSpans = notesSegmentsToSpans;
134500
134563
  exports.observeYDocSlides = observeYDocSlides;
134501
134564
  exports.ooxmlGradientAngleToCssDegrees = ooxmlGradientAngleToCssDegrees;
@@ -134504,7 +134567,6 @@ exports.openPptxFile = openPptxFile;
134504
134567
  exports.openReadingView = openReadingView;
134505
134568
  exports.openUrlInNewTab = openUrlInNewTab;
134506
134569
  exports.paintedStrokeWidth = paintedStrokeWidth;
134507
- exports.paletteColor = paletteColor;
134508
134570
  exports.paragraphsToSegments = paragraphsToSegments;
134509
134571
  exports.parseDrawingColor = parseDrawingColor;
134510
134572
  exports.parseDrawingColorOpacity = parseDrawingColorOpacity;
@@ -134531,6 +134593,7 @@ exports.pressuresToWidths = pressuresToWidths;
134531
134593
  exports.previousShowSlideIndex = previousShowSlideIndex;
134532
134594
  exports.printPropertiesFrameSlides = printPropertiesFrameSlides;
134533
134595
  exports.printPropertiesSlidesPerPage = printPropertiesSlidesPerPage;
134596
+ exports.probeAutosaveRecovery = probeAutosaveRecovery;
134534
134597
  exports.projectDrawingShapes = projectDrawingShapes;
134535
134598
  exports.promoteSmartArtNode = promoteSmartArtNode;
134536
134599
  exports.publishLiveGeometry = publishLiveGeometry;
@@ -134573,7 +134636,10 @@ exports.resolveAudienceScreenPlacement = resolveAudienceScreenPlacement;
134573
134636
  exports.resolveAuthoredCustomShowId = resolveAuthoredCustomShowId;
134574
134637
  exports.resolveAutoAdvanceDelayMs = resolveAutoAdvanceDelayMs;
134575
134638
  exports.resolveAutoFitFontScale = resolveAutoFitFontScale;
134639
+ exports.resolveAutosaveActivation = resolveAutosaveActivation;
134640
+ exports.resolveAutosaveIntervalMs = resolveAutosaveIntervalMs;
134576
134641
  exports.resolveAutosaveIntervalSeconds = resolveAutosaveIntervalSeconds;
134642
+ exports.resolveChartKind = resolveChartKind;
134577
134643
  exports.resolveConnectorEndpointUpdate = resolveConnectorEndpointUpdate;
134578
134644
  exports.resolveDefaultFontFamily = resolveDefaultFontFamily;
134579
134645
  exports.resolveDrawingShapeNodeId = resolveDrawingShapeNodeId;
@@ -134588,7 +134654,6 @@ exports.resolveMetricTrackingPx = resolveMetricTrackingPx;
134588
134654
  exports.resolveOleType = resolveOleType;
134589
134655
  exports.resolvePalette = resolvePalette;
134590
134656
  exports.resolveProfileInitial = resolveProfileInitial;
134591
- exports.resolveRegionCode = resolveRegionCode;
134592
134657
  exports.resolveSelectionPaneRename = resolveSelectionPaneRename;
134593
134658
  exports.resolveShapeGeometry = resolveShapeGeometry;
134594
134659
  exports.resolveShowSlideIndexes = resolveShowSlideIndexes;
@@ -134624,8 +134689,6 @@ exports.segmentsToParagraphs = segmentsToParagraphs;
134624
134689
  exports.segmentsToPlainText = segmentsToPlainText;
134625
134690
  exports.sendBackward = sendBackward;
134626
134691
  exports.sendToBack = sendToBack;
134627
- exports.sequentialColorScale = sequentialColorScale;
134628
- exports.seriesColor = seriesColor2;
134629
134692
  exports.setCachedResult = setCachedResult;
134630
134693
  exports.setChartAxisGridlineStyle = setChartAxisGridlineStyle;
134631
134694
  exports.setChartAxisLogScale = setChartAxisLogScale;
@@ -134651,6 +134714,8 @@ exports.shouldAutoFollowBroadcaster = shouldAutoFollowBroadcaster;
134651
134714
  exports.shouldCommitSmartArtNodeText = shouldCommitSmartArtNodeText;
134652
134715
  exports.shouldConfirmExternalHyperlink = shouldConfirmExternalHyperlink;
134653
134716
  exports.shouldLoopContinuously = shouldLoopContinuously;
134717
+ exports.shouldProbeAutosaveRecovery = shouldProbeAutosaveRecovery;
134718
+ exports.shouldShowAutosaveRecoveryPrompt = shouldShowAutosaveRecoveryPrompt;
134654
134719
  exports.shouldUseSvgWarp = shouldUseSvgWarp;
134655
134720
  exports.shouldWriteAutosaveSnapshot = shouldWriteAutosaveSnapshot;
134656
134721
  exports.slideProgressPercent = slideProgressPercent;
@@ -134661,7 +134726,6 @@ exports.slideStatusLabel = slideStatusLabel;
134661
134726
  exports.snapBoxToGrid = snapBoxToGrid;
134662
134727
  exports.splitCell = splitCell;
134663
134728
  exports.splitRunForMetrics = splitRunForMetrics;
134664
- exports.splitSeriesByAxis = splitSeriesByAxis;
134665
134729
  exports.stepPresenterZoom = stepPresenterZoom;
134666
134730
  exports.stopAllPersistentAudio = stopAllPersistentAudio;
134667
134731
  exports.storeAudienceContent = storeAudienceContent;
@@ -134698,7 +134762,6 @@ exports.updateMergeAttrsInRawXml = updateMergeAttrsInRawXml;
134698
134762
  exports.updateSmartArtNodeText = updateSmartArtNodeText;
134699
134763
  exports.updateTagInCollections = updateTagInCollections;
134700
134764
  exports.validateRoomId = validateRoomId;
134701
- exports.valueToY = valueToY;
134702
134765
  exports.vermilionDarkColors = vermilionDarkColors;
134703
134766
  exports.vermilionDarkTheme = vermilionDarkTheme;
134704
134767
  exports.vermilionLightColors = vermilionLightColors;