pptx-react-viewer 2.13.0 → 2.13.2

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 (103) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{AiChatPanel-DEI3EQFM.js → AiChatPanel-F4E3A2DE.js} +35 -27
  3. package/dist/AiChatPanel-F4E3A2DE.js.br +0 -0
  4. package/dist/AiChatPanel-F4E3A2DE.js.gz +0 -0
  5. package/dist/{AiChatPanel-4YS6DEIT.mjs → AiChatPanel-VEULATXX.mjs} +15 -7
  6. package/dist/AiChatPanel-VEULATXX.mjs.br +0 -0
  7. package/dist/AiChatPanel-VEULATXX.mjs.gz +0 -0
  8. package/dist/{Model3DScene-JSNQCKCJ.mjs → Model3DScene-KIPEODEJ.mjs} +1 -1
  9. package/dist/Model3DScene-KIPEODEJ.mjs.br +0 -0
  10. package/dist/Model3DScene-KIPEODEJ.mjs.gz +0 -0
  11. package/dist/{Model3DScene-X4W7GZVY.js → Model3DScene-TD2LIHYP.js} +2 -2
  12. package/dist/Model3DScene-TD2LIHYP.js.br +0 -0
  13. package/dist/Model3DScene-TD2LIHYP.js.gz +0 -0
  14. package/dist/{SurfaceChart3DScene-3MSU74YH.mjs → SurfaceChart3DScene-GRBWZ52S.mjs} +1 -1
  15. package/dist/{SurfaceChart3DScene-3MSU74YH.mjs.br → SurfaceChart3DScene-GRBWZ52S.mjs.br} +0 -0
  16. package/dist/SurfaceChart3DScene-GRBWZ52S.mjs.gz +0 -0
  17. package/dist/{SurfaceChart3DScene-IZLUWT27.js → SurfaceChart3DScene-OTKXQH5O.js} +2 -2
  18. package/dist/SurfaceChart3DScene-OTKXQH5O.js.br +0 -0
  19. package/dist/SurfaceChart3DScene-OTKXQH5O.js.gz +0 -0
  20. package/dist/{chunk-YA7VFYTW.mjs → chunk-3HWE6QZG.mjs} +16 -7
  21. package/dist/chunk-3HWE6QZG.mjs.br +0 -0
  22. package/dist/chunk-3HWE6QZG.mjs.gz +0 -0
  23. package/dist/{chunk-RWIQHVZQ.js → chunk-BNSCH4WT.js} +340 -326
  24. package/dist/chunk-BNSCH4WT.js.br +0 -0
  25. package/dist/chunk-BNSCH4WT.js.gz +0 -0
  26. package/dist/{chunk-IDW5UPXW.js → chunk-DOS7NY7C.js} +259 -295
  27. package/dist/chunk-DOS7NY7C.js.br +0 -0
  28. package/dist/chunk-DOS7NY7C.js.gz +0 -0
  29. package/dist/{chunk-SHZ3GWOD.js → chunk-EUQ2IER3.js} +1046 -1037
  30. package/dist/chunk-EUQ2IER3.js.br +0 -0
  31. package/dist/chunk-EUQ2IER3.js.gz +0 -0
  32. package/dist/{chunk-EFSQW6S5.js → chunk-FDR5W67L.js} +713 -349
  33. package/dist/chunk-FDR5W67L.js.br +0 -0
  34. package/dist/chunk-FDR5W67L.js.gz +0 -0
  35. package/dist/{chunk-4TD7EINA.mjs → chunk-GKOKCOXR.mjs} +709 -350
  36. package/dist/chunk-GKOKCOXR.mjs.br +0 -0
  37. package/dist/chunk-GKOKCOXR.mjs.gz +0 -0
  38. package/dist/{chunk-HRLF4REI.mjs → chunk-GZ6TXBEO.mjs} +21 -56
  39. package/dist/chunk-GZ6TXBEO.mjs.br +0 -0
  40. package/dist/chunk-GZ6TXBEO.mjs.gz +0 -0
  41. package/dist/{chunk-WEU5EMKK.mjs → chunk-L5YGPCQW.mjs} +1 -1
  42. package/dist/chunk-L5YGPCQW.mjs.br +0 -0
  43. package/dist/chunk-L5YGPCQW.mjs.gz +0 -0
  44. package/dist/{chunk-G2LZT5SV.js → chunk-VY3KLDJF.js} +3 -3
  45. package/dist/chunk-VY3KLDJF.js.br +0 -0
  46. package/dist/chunk-VY3KLDJF.js.gz +0 -0
  47. package/dist/{chunk-6KRNQ2KF.mjs → chunk-ZFRPPY2N.mjs} +16 -2
  48. package/dist/chunk-ZFRPPY2N.mjs.br +0 -0
  49. package/dist/chunk-ZFRPPY2N.mjs.gz +0 -0
  50. package/dist/index.d.ts +14 -0
  51. package/dist/index.js +34 -34
  52. package/dist/index.js.br +0 -0
  53. package/dist/index.js.gz +0 -0
  54. package/dist/index.mjs +5 -5
  55. package/dist/index.mjs.br +0 -0
  56. package/dist/index.mjs.gz +0 -0
  57. package/dist/internals.d.ts +14 -0
  58. package/dist/internals.d.ts.map +1 -1
  59. package/dist/internals.js +78 -78
  60. package/dist/internals.js.br +0 -0
  61. package/dist/internals.js.gz +0 -0
  62. package/dist/internals.mjs +3 -3
  63. package/dist/internals.mjs.br +0 -0
  64. package/dist/internals.mjs.gz +0 -0
  65. package/dist/viewer/index.d.ts +14 -0
  66. package/dist/viewer/index.js +21 -21
  67. package/dist/viewer/index.js.br +0 -0
  68. package/dist/viewer/index.js.gz +0 -0
  69. package/dist/viewer/index.mjs +5 -5
  70. package/dist/viewer/index.mjs.br +0 -0
  71. package/dist/viewer/index.mjs.gz +0 -0
  72. package/package.json +1 -1
  73. package/dist/AiChatPanel-4YS6DEIT.mjs.br +0 -0
  74. package/dist/AiChatPanel-4YS6DEIT.mjs.gz +0 -0
  75. package/dist/AiChatPanel-DEI3EQFM.js.br +0 -0
  76. package/dist/AiChatPanel-DEI3EQFM.js.gz +0 -0
  77. package/dist/Model3DScene-JSNQCKCJ.mjs.br +0 -0
  78. package/dist/Model3DScene-JSNQCKCJ.mjs.gz +0 -0
  79. package/dist/Model3DScene-X4W7GZVY.js.br +0 -0
  80. package/dist/Model3DScene-X4W7GZVY.js.gz +0 -0
  81. package/dist/SurfaceChart3DScene-3MSU74YH.mjs.gz +0 -0
  82. package/dist/SurfaceChart3DScene-IZLUWT27.js.br +0 -0
  83. package/dist/SurfaceChart3DScene-IZLUWT27.js.gz +0 -0
  84. package/dist/chunk-4TD7EINA.mjs.br +0 -0
  85. package/dist/chunk-4TD7EINA.mjs.gz +0 -0
  86. package/dist/chunk-6KRNQ2KF.mjs.br +0 -0
  87. package/dist/chunk-6KRNQ2KF.mjs.gz +0 -0
  88. package/dist/chunk-EFSQW6S5.js.br +0 -0
  89. package/dist/chunk-EFSQW6S5.js.gz +0 -0
  90. package/dist/chunk-G2LZT5SV.js.br +0 -0
  91. package/dist/chunk-G2LZT5SV.js.gz +0 -0
  92. package/dist/chunk-HRLF4REI.mjs.br +0 -0
  93. package/dist/chunk-HRLF4REI.mjs.gz +0 -0
  94. package/dist/chunk-IDW5UPXW.js.br +0 -0
  95. package/dist/chunk-IDW5UPXW.js.gz +0 -0
  96. package/dist/chunk-RWIQHVZQ.js.br +0 -0
  97. package/dist/chunk-RWIQHVZQ.js.gz +0 -0
  98. package/dist/chunk-SHZ3GWOD.js.br +0 -0
  99. package/dist/chunk-SHZ3GWOD.js.gz +0 -0
  100. package/dist/chunk-WEU5EMKK.mjs.br +0 -0
  101. package/dist/chunk-WEU5EMKK.mjs.gz +0 -0
  102. package/dist/chunk-YA7VFYTW.mjs.br +0 -0
  103. package/dist/chunk-YA7VFYTW.mjs.gz +0 -0
@@ -15903,30 +15903,133 @@ var PptxCommentXmlFactoryProvider = class {
15903
15903
  return new PptxCommentAuthorsXmlFactory();
15904
15904
  }
15905
15905
  };
15906
+ var P14_TRANSITION_TYPES = /* @__PURE__ */ new Set([
15907
+ "conveyor",
15908
+ "doors",
15909
+ "ferris",
15910
+ "flash",
15911
+ "flythrough",
15912
+ "gallery",
15913
+ "glitter",
15914
+ "honeycomb",
15915
+ "pan",
15916
+ "prism",
15917
+ "reveal",
15918
+ "ripple",
15919
+ "shred",
15920
+ "switch",
15921
+ "vortex",
15922
+ "warp",
15923
+ "wheelReverse",
15924
+ "window",
15925
+ "cube",
15926
+ "flip",
15927
+ "rotate",
15928
+ "orbit"
15929
+ ]);
15930
+ function readP14Details(localName22, value) {
15931
+ const type = localName22;
15932
+ let direction;
15933
+ let orient;
15934
+ let pattern;
15935
+ if (value && typeof value === "object" && !Array.isArray(value)) {
15936
+ const detail = value;
15937
+ const rawDir = String(detail["@_dir"] || "").trim();
15938
+ if (rawDir.length > 0) {
15939
+ direction = rawDir;
15940
+ }
15941
+ const rawOrient = String(detail["@_orient"] || "").trim();
15942
+ if (rawOrient === "horz" || rawOrient === "vert") {
15943
+ orient = rawOrient;
15944
+ }
15945
+ const rawPattern = String(detail["@_pattern"] || "").trim();
15946
+ if (rawPattern.length > 0) {
15947
+ pattern = rawPattern;
15948
+ }
15949
+ }
15950
+ return { type, direction, orient, pattern };
15951
+ }
15952
+ function parseP14DirectChild(transitionNode, getXmlLocalName) {
15953
+ for (const [key, value] of Object.entries(transitionNode)) {
15954
+ if (key.startsWith("@_")) {
15955
+ continue;
15956
+ }
15957
+ const localName22 = getXmlLocalName(key);
15958
+ if (P14_TRANSITION_TYPES.has(localName22)) {
15959
+ return readP14Details(localName22, value);
15960
+ }
15961
+ }
15962
+ return void 0;
15963
+ }
15964
+ function parseP14FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
15965
+ const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
15966
+ for (const ext of extEntries) {
15967
+ if (!ext) {
15968
+ continue;
15969
+ }
15970
+ for (const [key, value] of Object.entries(ext)) {
15971
+ if (key.startsWith("@_")) {
15972
+ continue;
15973
+ }
15974
+ const localName22 = getXmlLocalName(key);
15975
+ if (!P14_TRANSITION_TYPES.has(localName22)) {
15976
+ continue;
15977
+ }
15978
+ return readP14Details(localName22, value);
15979
+ }
15980
+ }
15981
+ return void 0;
15982
+ }
15983
+ function buildP14ExtLst(transitionType, direction, orient, pattern, rawExtLst, xmlLookupService, getXmlLocalName) {
15984
+ const p14Child = {};
15985
+ const dir = String(direction || "").trim();
15986
+ if (dir.length > 0) {
15987
+ p14Child["@_dir"] = dir;
15988
+ }
15989
+ if (orient) {
15990
+ p14Child["@_orient"] = orient;
15991
+ }
15992
+ if (pattern) {
15993
+ p14Child["@_pattern"] = pattern;
15994
+ }
15995
+ const transitionExt = {
15996
+ "@_uri": "{CE6CE671-F284-4235-B8B7-4F3F06D5A82C}",
15997
+ [`p14:${transitionType}`]: p14Child
15998
+ };
15999
+ if (rawExtLst) {
16000
+ const existing = xmlLookupService.getChildrenArrayByLocalName(rawExtLst, "ext");
16001
+ const otherExts = existing.filter((ext) => {
16002
+ if (!ext) {
16003
+ return false;
16004
+ }
16005
+ for (const key of Object.keys(ext)) {
16006
+ if (key.startsWith("@_")) {
16007
+ continue;
16008
+ }
16009
+ const localName22 = getXmlLocalName(key);
16010
+ if (P14_TRANSITION_TYPES.has(localName22)) {
16011
+ return false;
16012
+ }
16013
+ }
16014
+ return true;
16015
+ });
16016
+ const allExts = [transitionExt, ...otherExts];
16017
+ return { "p:ext": allExts.length === 1 ? allExts[0] : allExts };
16018
+ }
16019
+ return { "p:ext": transitionExt };
16020
+ }
15906
16021
  var MC_NAMESPACE_CAPABILITIES = {
16022
+ // Office 2010 (p14) transitions are shared with the parser's canonical
16023
+ // list (`P14_TRANSITION_TYPES`) so the two can never drift apart again:
16024
+ // this set used to be a hand-copied subset that was missing `reveal` and
16025
+ // `ripple`, so every `mc:Choice Requires="p14"` carrying one of them
16026
+ // reported `UNSUPPORTED_ALTERNATE_CONTENT_CHOICE` and silently used the
16027
+ // fallback fade even though the parser handles both. The extra names are
16028
+ // the non-transition p14 features we also parse.
15907
16029
  p14: /* @__PURE__ */ new Set([
16030
+ ...P14_TRANSITION_TYPES,
15908
16031
  "transition",
15909
- "conveyor",
15910
- "pan",
15911
- "glitter",
15912
- "prism",
15913
- "vortex",
15914
- "switch",
15915
- "flip",
15916
- "gallery",
15917
- "honeycomb",
15918
- "flash",
15919
- "shred",
15920
- "warp",
15921
- "flythrough",
15922
- "doors",
15923
- "window",
15924
- "ferris",
15925
16032
  "newsflash",
15926
- "wheelReverse",
15927
- "rotate",
15928
- "orbit",
15929
- "cube",
15930
16033
  "media",
15931
16034
  "trim",
15932
16035
  "fade",
@@ -15935,6 +16038,17 @@ var MC_NAMESPACE_CAPABILITIES = {
15935
16038
  "hiddenFill",
15936
16039
  "hiddenLine"
15937
16040
  ]),
16041
+ // PowerPoint 2013+ writes its preset transitions (Origami, Fracture, Peel
16042
+ // Off, Page Curl, ...) as `<p15:prstTrans prst="...">`, either inside an
16043
+ // `mc:Choice Requires="p15"` or in a `p:transition/p:extLst` extension.
16044
+ // Both forms are parsed (see `PptxSlideTransitionService`), so the choice
16045
+ // IS supported: without this entry every p15 slide reported
16046
+ // `UNSUPPORTED_ALTERNATE_CONTENT_CHOICE`, which reads as "the transition
16047
+ // was dropped and the fallback fade was used" when in fact the preset
16048
+ // plays. `prstTrans` alone is listed on purpose: any OTHER `p15:*`
16049
+ // element still makes the choice unsupported and falls back, which is
16050
+ // the honest answer.
16051
+ p15: /* @__PURE__ */ new Set(["prstTrans"]),
15938
16052
  // PowerPoint 2016+ writes the Morph transition as `<p159:morph @option>`,
15939
16053
  // either inside an `mc:Choice Requires="p159"` or in a `p:transition/p:extLst`
15940
16054
  // extension. Both forms are parsed (see `PptxSlideTransitionService`), so the
@@ -19911,6 +20025,74 @@ function extractChildBehaviourDurationMs(cTn, toArray2) {
19911
20025
  }
19912
20026
  return longest;
19913
20027
  }
20028
+ var defaultLookup = new PptxXmlLookupService();
20029
+ function resolveSlideTimingNode(slideRoot) {
20030
+ const direct = slideRoot?.["p:timing"];
20031
+ if (direct && typeof direct === "object" && !Array.isArray(direct)) {
20032
+ return direct;
20033
+ }
20034
+ return findEnvelopeChildByLocalName(slideRoot, "timing", defaultLookup);
20035
+ }
20036
+ function findTransitionInAlternateContent(slideRoot, lookup) {
20037
+ return findEnvelopeChildByLocalName(slideRoot, "transition", lookup);
20038
+ }
20039
+ function findEnvelopeChildByLocalName(slideRoot, localName22, lookup) {
20040
+ for (const envelope of lookup.getChildrenArrayByLocalName(slideRoot, "AlternateContent")) {
20041
+ let unsupportedChoiceNode;
20042
+ for (const choice of lookup.getChildrenArrayByLocalName(envelope, "Choice")) {
20043
+ const node = lookup.getChildByLocalName(choice, localName22);
20044
+ if (!node) {
20045
+ continue;
20046
+ }
20047
+ if (isAlternateContentChoiceSupported(choice)) {
20048
+ return node;
20049
+ }
20050
+ unsupportedChoiceNode ??= node;
20051
+ }
20052
+ const fallbackNode = lookup.getChildByLocalName(
20053
+ lookup.getChildByLocalName(envelope, "Fallback"),
20054
+ localName22
20055
+ );
20056
+ const found = fallbackNode ?? unsupportedChoiceNode;
20057
+ if (found) {
20058
+ return found;
20059
+ }
20060
+ }
20061
+ return void 0;
20062
+ }
20063
+ function preservedP14ChildKey(node, transitionType, getXmlLocalName) {
20064
+ for (const key of Object.keys(node)) {
20065
+ if (!key.startsWith("@_") && getXmlLocalName(key) === transitionType) {
20066
+ return key;
20067
+ }
20068
+ }
20069
+ return void 0;
20070
+ }
20071
+ function preservedP15ChildKey(node, transitionType, getXmlLocalName) {
20072
+ for (const [key, value] of Object.entries(node)) {
20073
+ if (key.startsWith("@_") || getXmlLocalName(key) !== "prstTrans") {
20074
+ continue;
20075
+ }
20076
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
20077
+ continue;
20078
+ }
20079
+ if (String(value["@_prst"] || "").trim() === transitionType) {
20080
+ return key;
20081
+ }
20082
+ }
20083
+ return void 0;
20084
+ }
20085
+ function pruneDirectExtensionChildren(node, getXmlLocalName, keepKey) {
20086
+ for (const key of Object.keys(node)) {
20087
+ if (key === keepKey || key.startsWith("@_")) {
20088
+ continue;
20089
+ }
20090
+ const localName22 = getXmlLocalName(key);
20091
+ if (P14_TRANSITION_TYPES.has(localName22) || localName22 === "prstTrans") {
20092
+ delete node[key];
20093
+ }
20094
+ }
20095
+ }
19914
20096
  function isInteractiveSequence(seq) {
19915
20097
  const cTn = seq["p:cTn"];
19916
20098
  if (!cTn || String(cTn["@_nodeType"] || "") === "mainSeq") {
@@ -19932,7 +20114,7 @@ var PptxNativeAnimationService = class {
19932
20114
  */
19933
20115
  parseNativeAnimations(slideXml2) {
19934
20116
  try {
19935
- const timing = slideXml2?.["p:sld"]?.["p:timing"];
20117
+ const timing = resolveSlideTimingNode(slideXml2?.["p:sld"]);
19936
20118
  if (!timing || typeof timing !== "object") {
19937
20119
  return void 0;
19938
20120
  }
@@ -20310,106 +20492,6 @@ var PptxNativeAnimationService = class {
20310
20492
  }
20311
20493
  }
20312
20494
  };
20313
- var P14_TRANSITION_TYPES = /* @__PURE__ */ new Set([
20314
- "conveyor",
20315
- "doors",
20316
- "ferris",
20317
- "flash",
20318
- "flythrough",
20319
- "gallery",
20320
- "glitter",
20321
- "honeycomb",
20322
- "pan",
20323
- "prism",
20324
- "reveal",
20325
- "ripple",
20326
- "shred",
20327
- "switch",
20328
- "vortex",
20329
- "warp",
20330
- "wheelReverse",
20331
- "window",
20332
- "cube",
20333
- "flip",
20334
- "rotate",
20335
- "orbit"
20336
- ]);
20337
- function parseP14FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
20338
- const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
20339
- for (const ext of extEntries) {
20340
- if (!ext) {
20341
- continue;
20342
- }
20343
- for (const [key, value] of Object.entries(ext)) {
20344
- if (key.startsWith("@_")) {
20345
- continue;
20346
- }
20347
- const localName22 = getXmlLocalName(key);
20348
- if (!P14_TRANSITION_TYPES.has(localName22)) {
20349
- continue;
20350
- }
20351
- const type = localName22;
20352
- let direction;
20353
- let orient;
20354
- let pattern;
20355
- if (value && typeof value === "object" && !Array.isArray(value)) {
20356
- const detail = value;
20357
- const rawDir = String(detail["@_dir"] || "").trim();
20358
- if (rawDir.length > 0) {
20359
- direction = rawDir;
20360
- }
20361
- const rawOrient = String(detail["@_orient"] || "").trim();
20362
- if (rawOrient === "horz" || rawOrient === "vert") {
20363
- orient = rawOrient;
20364
- }
20365
- const rawPattern = String(detail["@_pattern"] || "").trim();
20366
- if (rawPattern.length > 0) {
20367
- pattern = rawPattern;
20368
- }
20369
- }
20370
- return { type, direction, orient, pattern };
20371
- }
20372
- }
20373
- return void 0;
20374
- }
20375
- function buildP14ExtLst(transitionType, direction, orient, pattern, rawExtLst, xmlLookupService, getXmlLocalName) {
20376
- const p14Child = {};
20377
- const dir = String(direction || "").trim();
20378
- if (dir.length > 0) {
20379
- p14Child["@_dir"] = dir;
20380
- }
20381
- if (orient) {
20382
- p14Child["@_orient"] = orient;
20383
- }
20384
- if (pattern) {
20385
- p14Child["@_pattern"] = pattern;
20386
- }
20387
- const transitionExt = {
20388
- "@_uri": "{CE6CE671-F284-4235-B8B7-4F3F06D5A82C}",
20389
- [`p14:${transitionType}`]: p14Child
20390
- };
20391
- if (rawExtLst) {
20392
- const existing = xmlLookupService.getChildrenArrayByLocalName(rawExtLst, "ext");
20393
- const otherExts = existing.filter((ext) => {
20394
- if (!ext) {
20395
- return false;
20396
- }
20397
- for (const key of Object.keys(ext)) {
20398
- if (key.startsWith("@_")) {
20399
- continue;
20400
- }
20401
- const localName22 = getXmlLocalName(key);
20402
- if (P14_TRANSITION_TYPES.has(localName22)) {
20403
- return false;
20404
- }
20405
- }
20406
- return true;
20407
- });
20408
- const allExts = [transitionExt, ...otherExts];
20409
- return { "p:ext": allExts.length === 1 ? allExts[0] : allExts };
20410
- }
20411
- return { "p:ext": transitionExt };
20412
- }
20413
20495
  var P15_TRANSITION_PRESETS = /* @__PURE__ */ new Set([
20414
20496
  "fallOver",
20415
20497
  "drape",
@@ -20435,6 +20517,36 @@ function optionalBoolean(value) {
20435
20517
  }
20436
20518
  return void 0;
20437
20519
  }
20520
+ function readPrstTrans(value) {
20521
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
20522
+ return void 0;
20523
+ }
20524
+ const detail = value;
20525
+ const prst = String(detail["@_prst"] || "").trim();
20526
+ if (!P15_TRANSITION_PRESETS.has(prst)) {
20527
+ return void 0;
20528
+ }
20529
+ return {
20530
+ type: prst,
20531
+ invX: optionalBoolean(detail["@_invX"]),
20532
+ invY: optionalBoolean(detail["@_invY"])
20533
+ };
20534
+ }
20535
+ function parseP15DirectChild(transitionNode, getXmlLocalName) {
20536
+ for (const [key, value] of Object.entries(transitionNode)) {
20537
+ if (key.startsWith("@_")) {
20538
+ continue;
20539
+ }
20540
+ if (getXmlLocalName(key) !== "prstTrans") {
20541
+ continue;
20542
+ }
20543
+ const result = readPrstTrans(value);
20544
+ if (result) {
20545
+ return result;
20546
+ }
20547
+ }
20548
+ return void 0;
20549
+ }
20438
20550
  function parseP15FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
20439
20551
  const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
20440
20552
  for (const ext of extEntries) {
@@ -20448,19 +20560,10 @@ function parseP15FromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
20448
20560
  if (getXmlLocalName(key) !== "prstTrans") {
20449
20561
  continue;
20450
20562
  }
20451
- if (!value || typeof value !== "object" || Array.isArray(value)) {
20452
- continue;
20453
- }
20454
- const detail = value;
20455
- const prst = String(detail["@_prst"] || "").trim();
20456
- if (!P15_TRANSITION_PRESETS.has(prst)) {
20457
- continue;
20563
+ const result = readPrstTrans(value);
20564
+ if (result) {
20565
+ return result;
20458
20566
  }
20459
- return {
20460
- type: prst,
20461
- invX: optionalBoolean(detail["@_invX"]),
20462
- invY: optionalBoolean(detail["@_invY"])
20463
- };
20464
20567
  }
20465
20568
  }
20466
20569
  return void 0;
@@ -20709,6 +20812,69 @@ function validUnsignedInteger(value, min = 0) {
20709
20812
  return Number.isInteger(value) && Number(value) >= min && Number(value) <= UINT_MAX;
20710
20813
  }
20711
20814
  var MORPH_EXT_URI = "{C7C9D14B-FE2A-4D35-B620-AB07D5B017F4}";
20815
+ function parseMorphFromExtLst(extLstNode, xmlLookupService, getXmlLocalName) {
20816
+ const extEntries = xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
20817
+ for (const ext of extEntries) {
20818
+ if (!ext) {
20819
+ continue;
20820
+ }
20821
+ for (const [key, value] of Object.entries(ext)) {
20822
+ if (key.startsWith("@_")) {
20823
+ continue;
20824
+ }
20825
+ if (getXmlLocalName(key) === "morph") {
20826
+ return {
20827
+ morphOption: normalizeMorphOption(value?.["@_option"])
20828
+ };
20829
+ }
20830
+ }
20831
+ }
20832
+ return void 0;
20833
+ }
20834
+ function hasDirectMorphChild(node, getXmlLocalName) {
20835
+ for (const key of Object.keys(node)) {
20836
+ if (!key.startsWith("@_") && getXmlLocalName(key) === "morph") {
20837
+ return true;
20838
+ }
20839
+ }
20840
+ return false;
20841
+ }
20842
+ function buildMorphExtLst(rawExtLst, morphOption, xmlLookupService, getXmlLocalName) {
20843
+ const morphNode = {
20844
+ "@_xmlns:p159": "http://schemas.microsoft.com/office/powerpoint/2015/09/main"
20845
+ };
20846
+ if (morphOption) {
20847
+ morphNode["@_option"] = morphOption;
20848
+ }
20849
+ const morphExt = {
20850
+ "@_uri": MORPH_EXT_URI,
20851
+ "p159:morph": morphNode
20852
+ };
20853
+ if (!rawExtLst) {
20854
+ return { "p:ext": morphExt };
20855
+ }
20856
+ const existing = xmlLookupService.getChildrenArrayByLocalName(rawExtLst, "ext");
20857
+ const otherExts = existing.filter((ext) => {
20858
+ if (!ext) {
20859
+ return false;
20860
+ }
20861
+ const uri = String(ext["@_uri"] || "").trim();
20862
+ if (uri.toUpperCase() === MORPH_EXT_URI.toUpperCase()) {
20863
+ return false;
20864
+ }
20865
+ for (const key of Object.keys(ext)) {
20866
+ if (key.startsWith("@_")) {
20867
+ continue;
20868
+ }
20869
+ if (getXmlLocalName(key) === "morph") {
20870
+ return false;
20871
+ }
20872
+ }
20873
+ return true;
20874
+ });
20875
+ const allExts = [morphExt, ...otherExts];
20876
+ return { "p:ext": allExts.length === 1 ? allExts[0] : allExts };
20877
+ }
20712
20878
  var PptxSlideTransitionService = class {
20713
20879
  xmlLookupService;
20714
20880
  getXmlLocalName;
@@ -20718,7 +20884,7 @@ var PptxSlideTransitionService = class {
20718
20884
  }
20719
20885
  parseSlideTransition(slideXml2) {
20720
20886
  const slideRoot = this.xmlLookupService.getChildByLocalName(slideXml2, "sld");
20721
- const transitionNode = this.xmlLookupService.getChildByLocalName(slideRoot, "transition") || this.findTransitionInAlternateContent(slideRoot);
20887
+ const transitionNode = this.xmlLookupService.getChildByLocalName(slideRoot, "transition") || findTransitionInAlternateContent(slideRoot, this.xmlLookupService);
20722
20888
  if (!transitionNode) {
20723
20889
  return void 0;
20724
20890
  }
@@ -20727,6 +20893,18 @@ var PptxSlideTransitionService = class {
20727
20893
  let { direction, orient, pattern } = details;
20728
20894
  const { spokes, thruBlk, rawSoundAction, rawExtLst } = details;
20729
20895
  let { morphOption } = details;
20896
+ if (transitionType === "cut") {
20897
+ const p14Direct = parseP14DirectChild(transitionNode, this.getXmlLocalName);
20898
+ const p15Direct = p14Direct ? void 0 : parseP15DirectChild(transitionNode, this.getXmlLocalName);
20899
+ if (p14Direct) {
20900
+ transitionType = p14Direct.type;
20901
+ direction = p14Direct.direction ?? direction;
20902
+ orient = p14Direct.orient ?? orient;
20903
+ pattern = p14Direct.pattern ?? pattern;
20904
+ } else if (p15Direct) {
20905
+ transitionType = p15Direct.type;
20906
+ }
20907
+ }
20730
20908
  if (rawExtLst && transitionType === "cut") {
20731
20909
  const p14Result = parseP14FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
20732
20910
  const p15Result = p14Result ? void 0 : parseP15FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
@@ -20744,7 +20922,11 @@ var PptxSlideTransitionService = class {
20744
20922
  } else if (p15Result) {
20745
20923
  transitionType = p15Result.type;
20746
20924
  } else {
20747
- const morphResult = this.parseMorphFromExtLst(rawExtLst);
20925
+ const morphResult = parseMorphFromExtLst(
20926
+ rawExtLst,
20927
+ this.xmlLookupService,
20928
+ this.getXmlLocalName
20929
+ );
20748
20930
  if (morphResult) {
20749
20931
  transitionType = "morph";
20750
20932
  morphOption = morphResult.morphOption;
@@ -20768,58 +20950,6 @@ var PptxSlideTransitionService = class {
20768
20950
  rawTransition: transitionNode
20769
20951
  };
20770
20952
  }
20771
- /**
20772
- * Locate a `<p:transition>` wrapped in a slide-root `mc:AlternateContent`
20773
- * envelope.
20774
- *
20775
- * Real PowerPoint (verified via COM-authored fixtures) wraps the
20776
- * transition in `mc:AlternateContent` whenever it carries an Office
20777
- * 2010+ attribute such as `p14:dur` (sub-second transition duration):
20778
- * an `mc:Choice Requires="p14"` branch carries the richer transition,
20779
- * and `mc:Fallback` carries a plain one for older readers. Without this
20780
- * unwrap, `p:sld`'s direct-child lookup for `transition` finds nothing
20781
- * and the whole transition (including plain ones falling back with no
20782
- * p14 data) is silently dropped, even though `mc:Choice` is otherwise a
20783
- * complete, directly usable `p:transition` node.
20784
- */
20785
- findTransitionInAlternateContent(slideRoot) {
20786
- const altContent = this.xmlLookupService.getChildByLocalName(slideRoot, "AlternateContent");
20787
- if (!altContent) {
20788
- return void 0;
20789
- }
20790
- const choices2 = this.xmlLookupService.getChildrenArrayByLocalName(altContent, "Choice");
20791
- for (const choice of choices2) {
20792
- const transitionNode = this.xmlLookupService.getChildByLocalName(choice, "transition");
20793
- if (transitionNode) {
20794
- return transitionNode;
20795
- }
20796
- }
20797
- const fallback = this.xmlLookupService.getChildByLocalName(altContent, "Fallback");
20798
- return this.xmlLookupService.getChildByLocalName(fallback, "transition");
20799
- }
20800
- /**
20801
- * Detects the PowerPoint 2016+ `morph` transition stored as a p159 extension
20802
- * inside the transition's extLst.
20803
- */
20804
- parseMorphFromExtLst(extLstNode) {
20805
- const extEntries = this.xmlLookupService.getChildrenArrayByLocalName(extLstNode, "ext");
20806
- for (const ext of extEntries) {
20807
- if (!ext) {
20808
- continue;
20809
- }
20810
- for (const [key, value] of Object.entries(ext)) {
20811
- if (key.startsWith("@_")) {
20812
- continue;
20813
- }
20814
- if (this.getXmlLocalName(key) === "morph") {
20815
- return {
20816
- morphOption: normalizeMorphOption(value?.["@_option"])
20817
- };
20818
- }
20819
- }
20820
- }
20821
- return void 0;
20822
- }
20823
20953
  buildSlideTransitionXml(transition) {
20824
20954
  if (!transition || transition.type === "none") {
20825
20955
  return void 0;
@@ -20829,21 +20959,33 @@ var PptxSlideTransitionService = class {
20829
20959
  const isP15Type = P15_TRANSITION_PRESETS.has(transitionType);
20830
20960
  const isMorphType = transitionType === "morph";
20831
20961
  const node = createPreservedTransitionNode(transition.rawTransition, this.getXmlLocalName);
20962
+ const p14ChildKey = isP14Type ? preservedP14ChildKey(node, transitionType, this.getXmlLocalName) : void 0;
20963
+ const p15ChildKey = isP15Type ? preservedP15ChildKey(node, transitionType, this.getXmlLocalName) : void 0;
20964
+ pruneDirectExtensionChildren(node, this.getXmlLocalName, p14ChildKey ?? p15ChildKey);
20832
20965
  if (isP14Type) {
20833
- node["p:extLst"] = buildP14ExtLst(
20834
- transitionType,
20835
- transition.direction,
20836
- transition.orient,
20837
- transition.pattern,
20838
- transition.rawExtLst,
20839
- this.xmlLookupService,
20840
- this.getXmlLocalName
20841
- );
20966
+ if (!p14ChildKey) {
20967
+ node["p:extLst"] = buildP14ExtLst(
20968
+ transitionType,
20969
+ transition.direction,
20970
+ transition.orient,
20971
+ transition.pattern,
20972
+ transition.rawExtLst,
20973
+ this.xmlLookupService,
20974
+ this.getXmlLocalName
20975
+ );
20976
+ }
20842
20977
  } else if (isP15Type) {
20843
- node["p:extLst"] = transition.rawExtLst ?? buildP15ExtLst(transitionType);
20978
+ if (!p15ChildKey) {
20979
+ node["p:extLst"] = transition.rawExtLst ?? buildP15ExtLst(transitionType);
20980
+ }
20844
20981
  } else if (isMorphType) {
20845
- if (!this.hasDirectMorphChild(node)) {
20846
- node["p:extLst"] = this.buildMorphExtLst(transition.rawExtLst, transition.morphOption);
20982
+ if (!hasDirectMorphChild(node, this.getXmlLocalName)) {
20983
+ node["p:extLst"] = buildMorphExtLst(
20984
+ transition.rawExtLst,
20985
+ transition.morphOption,
20986
+ this.xmlLookupService,
20987
+ this.getXmlLocalName
20988
+ );
20847
20989
  }
20848
20990
  } else {
20849
20991
  node[`p:${transitionType}`] = buildStandardTransitionChild(transition);
@@ -20858,58 +21000,6 @@ var PptxSlideTransitionService = class {
20858
21000
  }
20859
21001
  return node;
20860
21002
  }
20861
- /**
20862
- * True when the (preserved) transition node already carries a `morph`
20863
- * element as a direct child, in any namespace prefix.
20864
- */
20865
- hasDirectMorphChild(node) {
20866
- for (const key of Object.keys(node)) {
20867
- if (!key.startsWith("@_") && this.getXmlLocalName(key) === "morph") {
20868
- return true;
20869
- }
20870
- }
20871
- return false;
20872
- }
20873
- /**
20874
- * Build the extLst XML node for a morph (p159) transition, preserving any
20875
- * non-morph extensions from rawExtLst.
20876
- */
20877
- buildMorphExtLst(rawExtLst, morphOption) {
20878
- const morphNode = {
20879
- "@_xmlns:p159": "http://schemas.microsoft.com/office/powerpoint/2015/09/main"
20880
- };
20881
- if (morphOption) {
20882
- morphNode["@_option"] = morphOption;
20883
- }
20884
- const morphExt = {
20885
- "@_uri": MORPH_EXT_URI,
20886
- "p159:morph": morphNode
20887
- };
20888
- if (!rawExtLst) {
20889
- return { "p:ext": morphExt };
20890
- }
20891
- const existing = this.xmlLookupService.getChildrenArrayByLocalName(rawExtLst, "ext");
20892
- const otherExts = existing.filter((ext) => {
20893
- if (!ext) {
20894
- return false;
20895
- }
20896
- const uri = String(ext["@_uri"] || "").trim();
20897
- if (uri.toUpperCase() === MORPH_EXT_URI.toUpperCase()) {
20898
- return false;
20899
- }
20900
- for (const key of Object.keys(ext)) {
20901
- if (key.startsWith("@_")) {
20902
- continue;
20903
- }
20904
- if (this.getXmlLocalName(key) === "morph") {
20905
- return false;
20906
- }
20907
- }
20908
- return true;
20909
- });
20910
- const allExts = [morphExt, ...otherExts];
20911
- return { "p:ext": allExts.length === 1 ? allExts[0] : allExts };
20912
- }
20913
21003
  };
20914
21004
  var PRESET_TO_OOXML = {
20915
21005
  // ---- Entrance effects (typed `PptxAnimationPreset` names) ----
@@ -41450,6 +41540,30 @@ var FONT_SUBSTITUTION_MAP = {
41450
41540
  Gulim: ["Noto Sans CJK KR", "AppleGothic", "sans-serif"],
41451
41541
  Malgun: ["Noto Sans CJK KR", "Apple SD Gothic Neo", "sans-serif"],
41452
41542
  "Malgun Gothic": ["Noto Sans CJK KR", "Apple SD Gothic Neo", "sans-serif"],
41543
+ // Source Han Sans (Adobe/Google) ships the same glyphs as Noto Sans CJK;
41544
+ // the zh-CN name 思源黑体 is how decks authored in Chinese reference it.
41545
+ "\u601D\u6E90\u9ED1\u4F53 CN": [
41546
+ "Source Han Sans CN",
41547
+ "Noto Sans CJK SC",
41548
+ "Noto Sans SC",
41549
+ "Microsoft YaHei",
41550
+ "sans-serif"
41551
+ ],
41552
+ \u601D\u6E90\u9ED1\u4F53: [
41553
+ "Source Han Sans SC",
41554
+ "Noto Sans CJK SC",
41555
+ "Noto Sans SC",
41556
+ "Microsoft YaHei",
41557
+ "sans-serif"
41558
+ ],
41559
+ "Source Han Sans CN": [
41560
+ "\u601D\u6E90\u9ED1\u4F53 CN",
41561
+ "Noto Sans CJK SC",
41562
+ "Noto Sans SC",
41563
+ "Microsoft YaHei",
41564
+ "sans-serif"
41565
+ ],
41566
+ \u5FAE\u8F6F\u96C5\u9ED1: ["Microsoft YaHei", "Noto Sans CJK SC", "PingFang SC", "sans-serif"],
41453
41567
  // Complex script fonts
41454
41568
  "Arabic Typesetting": ["Noto Naskh Arabic", "serif"],
41455
41569
  "Simplified Arabic": ["Noto Sans Arabic", "sans-serif"],
@@ -41469,6 +41583,11 @@ var FONT_SUBSTITUTION_MAP = {
41469
41583
  Nyala: ["Noto Sans Ethiopic", "sans-serif"],
41470
41584
  MoolBoran: ["Noto Sans Khmer", "sans-serif"],
41471
41585
  // Decorative / Display
41586
+ // Condensed display faces: decks often reference the FULL style name
41587
+ // ("Bebas Neue Regular"); the suffix-stripped base resolves here. The
41588
+ // fallbacks must stay condensed, or short numeric labels sized to the
41589
+ // narrow face overflow their text boxes and wrap (issue #132, "77%").
41590
+ "Bebas Neue": ["Oswald", "Arial Narrow", "Impact", "sans-serif"],
41472
41591
  "Century Gothic": ["URW Gothic", "Futura", "sans-serif"],
41473
41592
  Oswald: ["Agency FB", "Arial Narrow", "sans-serif"],
41474
41593
  "Franklin Gothic": ["Liberation Sans", "Helvetica Neue", "sans-serif"],
@@ -41480,6 +41599,48 @@ var FONT_SUBSTITUTION_MAP = {
41480
41599
  Constantia: ["Liberation Serif", "Palatino", "serif"],
41481
41600
  Corbel: ["Liberation Sans", "Lucida Grande", "sans-serif"]
41482
41601
  };
41602
+ var FONT_STYLE_SUFFIX_TOKENS = /* @__PURE__ */ new Set([
41603
+ "regular",
41604
+ "normal",
41605
+ "book",
41606
+ "roman",
41607
+ "thin",
41608
+ "hairline",
41609
+ "extralight",
41610
+ "ultralight",
41611
+ "demilight",
41612
+ "semilight",
41613
+ "light",
41614
+ "medium",
41615
+ "demibold",
41616
+ "semibold",
41617
+ "bold",
41618
+ "extrabold",
41619
+ "ultrabold",
41620
+ "heavy",
41621
+ "black",
41622
+ "extrablack",
41623
+ "ultra",
41624
+ "italic",
41625
+ "oblique"
41626
+ ]);
41627
+ function stripFontStyleSuffix(fontName) {
41628
+ let name = fontName.trim();
41629
+ let stripped = false;
41630
+ for (let i = 0; i < 2; i++) {
41631
+ const idx = name.lastIndexOf(" ");
41632
+ if (idx <= 0) {
41633
+ break;
41634
+ }
41635
+ const token2 = name.slice(idx + 1).toLowerCase().replace(/-/g, "");
41636
+ if (!FONT_STYLE_SUFFIX_TOKENS.has(token2)) {
41637
+ break;
41638
+ }
41639
+ name = name.slice(0, idx).trim();
41640
+ stripped = true;
41641
+ }
41642
+ return stripped && name.length > 0 ? name : void 0;
41643
+ }
41483
41644
  var PANOSE_FAMILY_MAP = {
41484
41645
  0: "sans-serif",
41485
41646
  // Any — default to sans-serif
@@ -41553,18 +41714,27 @@ function getSubstituteFontFamily(fontName, panose) {
41553
41714
  if (!trimmed) {
41554
41715
  return "sans-serif";
41555
41716
  }
41556
- const directSubs = FONT_SUBSTITUTION_MAP[trimmed];
41717
+ return buildFontFamilyString(trimmed, getSubstituteFonts(trimmed, panose));
41718
+ }
41719
+ function getSubstituteFonts(fontName, panose) {
41720
+ const trimmed = fontName.trim();
41721
+ if (!trimmed) {
41722
+ return ["sans-serif"];
41723
+ }
41724
+ const baseName = stripFontStyleSuffix(trimmed);
41725
+ const basePrefix = baseName ? [baseName] : [];
41726
+ const directSubs = FONT_SUBSTITUTION_MAP[trimmed] ?? (baseName ? FONT_SUBSTITUTION_MAP[baseName] : void 0);
41557
41727
  if (directSubs) {
41558
- return buildFontFamilyString(trimmed, directSubs);
41728
+ return [...basePrefix, ...directSubs];
41559
41729
  }
41560
41730
  if (panose && panose.length >= 4) {
41561
41731
  const genericFamily = classifyPanose(panose);
41562
41732
  const concreteFonts = GENERIC_FAMILY_CONCRETE_FONTS[genericFamily];
41563
41733
  if (concreteFonts) {
41564
- return buildFontFamilyString(trimmed, concreteFonts);
41734
+ return [...basePrefix, ...concreteFonts];
41565
41735
  }
41566
41736
  }
41567
- return buildFontFamilyString(trimmed, ["sans-serif"]);
41737
+ return [...basePrefix, "sans-serif"];
41568
41738
  }
41569
41739
  var CSS_GENERIC_FAMILIES = /* @__PURE__ */ new Set([
41570
41740
  "serif",
@@ -47188,6 +47358,16 @@ function parseCtnMediaTiming(cTn, mediaTag) {
47188
47358
  }
47189
47359
  return { trimStartMs, trimEndMs, loop, autoPlay, playAcrossSlides };
47190
47360
  }
47361
+ function resolvePlayAcrossSlides(cMediaNode, ctnPlayAcrossSlides, mediaTag) {
47362
+ if (ctnPlayAcrossSlides) {
47363
+ return true;
47364
+ }
47365
+ if (mediaTag !== "p:audio") {
47366
+ return false;
47367
+ }
47368
+ const numSld = Number.parseInt(String(cMediaNode["@_numSld"] ?? ""), 10);
47369
+ return Number.isFinite(numSld) && numSld > 1;
47370
+ }
47191
47371
  function parseMediaExtensionData(mediaNode, cMediaNode, shapeId, ensureArray17) {
47192
47372
  let fadeInDuration;
47193
47373
  let fadeOutDuration;
@@ -48648,6 +48828,11 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
48648
48828
  }
48649
48829
  }
48650
48830
  const hideWhenNotPlaying = cMediaNode["@_showWhenStopped"] === "0";
48831
+ const playAcrossSlides = resolvePlayAcrossSlides(
48832
+ cMediaNode,
48833
+ timing.playAcrossSlides,
48834
+ mediaTag
48835
+ );
48651
48836
  let posterFramePath;
48652
48837
  const posterRId = cMediaNode["@_posterFrame"];
48653
48838
  if (posterRId) {
@@ -48672,7 +48857,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
48672
48857
  fadeInDuration: extData.fadeInDuration,
48673
48858
  fadeOutDuration: extData.fadeOutDuration,
48674
48859
  autoPlay: timing.autoPlay || void 0,
48675
- playAcrossSlides: timing.playAcrossSlides || void 0,
48860
+ playAcrossSlides: playAcrossSlides || void 0,
48676
48861
  hideWhenNotPlaying: hideWhenNotPlaying || void 0,
48677
48862
  bookmarks: extData.bookmarks.length > 0 ? extData.bookmarks : void 0,
48678
48863
  playbackSpeed: extData.playbackSpeed,
@@ -48709,7 +48894,7 @@ var PptxHandlerRuntime6 = class extends PptxHandlerRuntime5 {
48709
48894
  extractMediaTimingMap(slideXml2, slidePath) {
48710
48895
  const result = /* @__PURE__ */ new Map();
48711
48896
  try {
48712
- const timing = slideXml2?.["p:sld"]?.["p:timing"];
48897
+ const timing = resolveSlideTimingNode(slideXml2?.["p:sld"]);
48713
48898
  if (!timing) {
48714
48899
  return result;
48715
48900
  }
@@ -62270,31 +62455,35 @@ var PptxHandlerRuntime57 = class _PptxHandlerRuntime23 extends PptxHandlerRuntim
62270
62455
  return normalized;
62271
62456
  }
62272
62457
  readImageCropFromBlipFill(blipFill) {
62458
+ const result = {};
62273
62459
  const sourceRect = blipFill?.["a:srcRect"];
62274
62460
  if (sourceRect) {
62275
- const cropLeft = this.parseCropFraction(sourceRect["@_l"]);
62276
- const cropTop = this.parseCropFraction(sourceRect["@_t"]);
62277
- const cropRight = this.parseCropFraction(sourceRect["@_r"]);
62278
- const cropBottom = this.parseCropFraction(sourceRect["@_b"]);
62279
- return { cropLeft, cropTop, cropRight, cropBottom };
62461
+ result.cropLeft = this.parseCropFraction(sourceRect["@_l"]);
62462
+ result.cropTop = this.parseCropFraction(sourceRect["@_t"]);
62463
+ result.cropRight = this.parseCropFraction(sourceRect["@_r"]);
62464
+ result.cropBottom = this.parseCropFraction(sourceRect["@_b"]);
62280
62465
  }
62281
62466
  const stretchNode = blipFill?.["a:stretch"];
62282
62467
  const fillRect = stretchNode?.["a:fillRect"];
62283
62468
  if (fillRect) {
62284
- const l = this.parseCropFraction(fillRect["@_l"]);
62285
- const t = this.parseCropFraction(fillRect["@_t"]);
62286
- const r = this.parseCropFraction(fillRect["@_r"]);
62287
- const b = this.parseCropFraction(fillRect["@_b"]);
62288
- if (l !== void 0 || t !== void 0 || r !== void 0 || b !== void 0) {
62289
- return {
62290
- cropLeft: l,
62291
- cropTop: t,
62292
- cropRight: r,
62293
- cropBottom: b
62294
- };
62295
- }
62469
+ result.fillRectLeft = this.parseSignedRectFraction(fillRect["@_l"]);
62470
+ result.fillRectTop = this.parseSignedRectFraction(fillRect["@_t"]);
62471
+ result.fillRectRight = this.parseSignedRectFraction(fillRect["@_r"]);
62472
+ result.fillRectBottom = this.parseSignedRectFraction(fillRect["@_b"]);
62296
62473
  }
62297
- return {};
62474
+ return result;
62475
+ }
62476
+ /**
62477
+ * Parse a signed ST_Percentage rect offset (thousandths of a percent) to a
62478
+ * fraction. Unlike {@link parseCropFraction} the sign is preserved; the
62479
+ * magnitude is capped at 10x the frame to bound hostile input.
62480
+ */
62481
+ parseSignedRectFraction(value) {
62482
+ const raw = Number.parseInt(String(value ?? ""), 10);
62483
+ if (!Number.isFinite(raw)) {
62484
+ return void 0;
62485
+ }
62486
+ return Math.max(-1e6, Math.min(1e6, raw)) / 1e5;
62298
62487
  }
62299
62488
  extractShapeStyle(spPr, styleNode) {
62300
62489
  return this.shapeStyleExtractor.extractShapeStyle(spPr, styleNode);
@@ -63133,6 +63322,19 @@ var PptxHandlerRuntime61 = class _PptxHandlerRuntime25 extends PptxHandlerRuntim
63133
63322
  }
63134
63323
  };
63135
63324
  var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntime61 {
63325
+ /**
63326
+ * A copy of an `a:lstStyle` level entry without its `a:defRPr`: run
63327
+ * defaults follow their own precedence chain, so only the paragraph-level
63328
+ * keys (algn, lnSpc, spacing, margins, tabs) may join the pPr merge.
63329
+ */
63330
+ withoutDefaultRunProperties(node) {
63331
+ if (!node || typeof node !== "object") {
63332
+ return void 0;
63333
+ }
63334
+ const copy2 = { ...node };
63335
+ delete copy2["a:defRPr"];
63336
+ return copy2;
63337
+ }
63136
63338
  /**
63137
63339
  * Extract a paragraph's OWN `a:pPr` geometry (align, spacing, margins,
63138
63340
  * indent, tabs, rtl) as a partial {@link TextStyle} so per-paragraph
@@ -63196,10 +63398,26 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntim
63196
63398
  */
63197
63399
  resolveShapeParagraphStyle(p, textStyle, ctx) {
63198
63400
  const inheritedParagraph = this.ensureArray(ctx.inheritedTxBody?.["a:p"])[0];
63199
- const pPr = this.mergeXmlObjects(
63401
+ const directPPr = this.mergeXmlObjects(
63200
63402
  inheritedParagraph?.["a:pPr"],
63201
63403
  p["a:pPr"]
63202
63404
  );
63405
+ const parsedLevel = Number.parseInt(String(directPPr?.["@_lvl"] ?? "0"), 10);
63406
+ const level = Number.isFinite(parsedLevel) ? Math.min(Math.max(parsedLevel, 0), 8) : 0;
63407
+ const levelKey = `a:lvl${level + 1}pPr`;
63408
+ const ownLstStyle = ctx.txBody?.["a:lstStyle"];
63409
+ const inheritedLstStyle = ctx.inheritedTxBody?.["a:lstStyle"];
63410
+ const lstStyleParagraphDefaults = this.mergeXmlObjects(
63411
+ this.mergeXmlObjects(
63412
+ this.withoutDefaultRunProperties(inheritedLstStyle?.["a:defPPr"]),
63413
+ this.withoutDefaultRunProperties(inheritedLstStyle?.[levelKey])
63414
+ ),
63415
+ this.mergeXmlObjects(
63416
+ this.withoutDefaultRunProperties(ownLstStyle?.["a:defPPr"]),
63417
+ this.withoutDefaultRunProperties(ownLstStyle?.[levelKey])
63418
+ )
63419
+ );
63420
+ const pPr = this.mergeXmlObjects(lstStyleParagraphDefaults, directPPr);
63203
63421
  const paragraphRtl = this.parseOptionalBooleanAttr(pPr?.["@_rtl"]);
63204
63422
  if (paragraphRtl !== void 0 && textStyle.rtl === void 0) {
63205
63423
  textStyle.rtl = paragraphRtl;
@@ -63323,8 +63541,6 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntim
63323
63541
  ctx.slideRelationshipMap,
63324
63542
  false
63325
63543
  );
63326
- const level = pPr?.["@_lvl"] === void 0 ? -1 : Number.parseInt(String(pPr["@_lvl"]), 10);
63327
- const levelKey = level === -1 ? "a:defPPr" : `a:lvl${Number.isFinite(level) ? Math.min(Math.max(level + 1, 1), 9) : 1}pPr`;
63328
63544
  const inheritedLevelStyle = this.extractTextRunStyle(
63329
63545
  ctx.inheritedTxBody?.["a:lstStyle"]?.[levelKey]?.["a:defRPr"],
63330
63546
  paraAlign,
@@ -63357,12 +63573,16 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntim
63357
63573
  mergedDefaultRunStyle.fontFamily = ctx.styleFontRefTypeface;
63358
63574
  }
63359
63575
  if (ctx.effectiveLevelStyles) {
63360
- const normalizedLevel = level === -1 ? -1 : Number.isFinite(level) ? Math.min(Math.max(level, 0), 8) : 0;
63361
- const phLevel = ctx.effectiveLevelStyles[normalizedLevel] ?? ctx.effectiveLevelStyles[-1] ?? (normalizedLevel === -1 ? ctx.effectiveLevelStyles[0] : void 0);
63576
+ const phLevel = ctx.effectiveLevelStyles[level];
63577
+ const phBase = ctx.effectiveLevelStyles[-1];
63362
63578
  if (phLevel) {
63363
63579
  this.applyPlaceholderLevelDefaults(mergedDefaultRunStyle, phLevel);
63364
63580
  this.applyPlaceholderLevelDefaults(textStyle, phLevel);
63365
63581
  }
63582
+ if (phBase) {
63583
+ this.applyPlaceholderLevelDefaults(mergedDefaultRunStyle, phBase);
63584
+ this.applyPlaceholderLevelDefaults(textStyle, phBase);
63585
+ }
63366
63586
  }
63367
63587
  if (pPr?.["@_algn"] === void 0 && textStyle.align !== void 0) {
63368
63588
  paraAlign = textStyle.align;
@@ -63372,15 +63592,13 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntim
63372
63592
  let effectiveMarginLeft = parMarginLeft;
63373
63593
  let effectiveIndent = parIndent;
63374
63594
  if (ctx.effectiveLevelStyles) {
63375
- const normalizedLevel = level === -1 ? -1 : Number.isFinite(level) ? Math.min(Math.max(level, 0), 8) : 0;
63376
- const phLevel = ctx.effectiveLevelStyles[normalizedLevel] ?? ctx.effectiveLevelStyles[-1] ?? (normalizedLevel === -1 ? ctx.effectiveLevelStyles[0] : void 0);
63377
- if (phLevel) {
63378
- if (effectiveMarginLeft === void 0 && phLevel.marginLeft !== void 0) {
63379
- effectiveMarginLeft = phLevel.marginLeft;
63380
- }
63381
- if (effectiveIndent === void 0 && phLevel.indent !== void 0) {
63382
- effectiveIndent = phLevel.indent;
63383
- }
63595
+ const phLevel = ctx.effectiveLevelStyles[level];
63596
+ const phBase = ctx.effectiveLevelStyles[-1];
63597
+ if (effectiveMarginLeft === void 0) {
63598
+ effectiveMarginLeft = phLevel?.marginLeft ?? phBase?.marginLeft;
63599
+ }
63600
+ if (effectiveIndent === void 0) {
63601
+ effectiveIndent = phLevel?.indent ?? phBase?.indent;
63384
63602
  }
63385
63603
  }
63386
63604
  return {
@@ -87232,8 +87450,8 @@ function formatAxisValue(val2, formatCode) {
87232
87450
  return val2.toFixed(1);
87233
87451
  }
87234
87452
  function computeLayout(elementWidth, elementHeight, style, hasAxes, legendPos, options) {
87235
- const svgWidth = Math.max(320, elementWidth);
87236
- const svgHeight = Math.max(180, elementHeight);
87453
+ const svgWidth = Math.max(1, elementWidth);
87454
+ const svgHeight = Math.max(1, elementHeight);
87237
87455
  let plotLeft = hasAxes ? 48 : 8;
87238
87456
  let plotTop = 8;
87239
87457
  let plotRight = svgWidth - 8;
@@ -87288,6 +87506,12 @@ function chartAreaFill(chartData) {
87288
87506
  function plotAreaFill(chartData) {
87289
87507
  return resolve(chartData?.style?.plotAreaFill, void 0);
87290
87508
  }
87509
+ var CHART_PX_PER_PT = 4 / 3;
87510
+ function chartFontPx(sizePt) {
87511
+ return sizePt * CHART_PX_PER_PT;
87512
+ }
87513
+ var DEFAULT_CHART_TEXT_PX = chartFontPx(10);
87514
+ var DEFAULT_CHART_DATA_LABEL_PX = chartFontPx(9);
87291
87515
  var LOG_EXPONENT_TOLERANCE = 1e-12;
87292
87516
  function computeLogValueRange(series, logBase) {
87293
87517
  const allValues = series.flatMap((item) => item.values).filter((value) => value > 0);
@@ -87866,9 +88090,9 @@ function dashArray(style, width) {
87866
88090
  }
87867
88091
  return `${unit * 3} ${unit * 2}`;
87868
88092
  }
87869
- function chartAxisTextStyle(axis, defaultFontSize = 8) {
88093
+ function chartAxisTextStyle(axis, defaultFontSizePx = DEFAULT_CHART_TEXT_PX) {
87870
88094
  return {
87871
- fontSize: axis?.fontSize ?? defaultFontSize,
88095
+ fontSize: axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : defaultFontSizePx,
87872
88096
  fill: axis?.fontColor ?? DEFAULT_COLOR2,
87873
88097
  ...axis?.fontBold !== void 0 ? { fontWeight: axis.fontBold ? "bold" : "normal" } : {},
87874
88098
  ...axis?.fontFamily ? { fontFamily: axis.fontFamily } : {}
@@ -88015,7 +88239,7 @@ function buildPrimaryAxis(range, layout, axis, axisX = layout.plotLeft) {
88015
88239
  x: labelX,
88016
88240
  y: midY,
88017
88241
  text: unitLabel,
88018
- ...chartAxisTextStyle(axis, 9),
88242
+ ...chartAxisTextStyle(axis),
88019
88243
  textAnchor: "middle",
88020
88244
  transform: `rotate(-90, ${labelX}, ${midY})`
88021
88245
  });
@@ -88027,7 +88251,7 @@ function buildSecondaryAxis(range, layout, axis, axisX = layout.plotRight) {
88027
88251
  const gridlines = [];
88028
88252
  const axisLabels = [];
88029
88253
  const textStyle = chartAxisTextStyle(axis);
88030
- const captionStyle = chartAxisTextStyle(axis, 9);
88254
+ const captionStyle = chartAxisTextStyle(axis);
88031
88255
  const axisLine = buildVerticalAxisLine(axis, axisX, layout);
88032
88256
  if (axisLine) {
88033
88257
  gridlines.push(axisLine);
@@ -88249,7 +88473,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
88249
88473
  x: x + singleBarWidth / 2,
88250
88474
  y: val2 >= 0 ? y - 4 : y + h + 10,
88251
88475
  text: formatAxisValue2(val2, series[si].numberFormat),
88252
- fontSize: 7,
88476
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88253
88477
  fill: "#334155",
88254
88478
  textAnchor: "middle"
88255
88479
  });
@@ -88321,7 +88545,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
88321
88545
  x: x + barW / 2,
88322
88546
  y: y + h / 2 + 3,
88323
88547
  text: `${Math.round(val2)}%`,
88324
- fontSize: 7,
88548
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88325
88549
  fill: "#ffffff",
88326
88550
  textAnchor: "middle",
88327
88551
  fontWeight: "bold"
@@ -88354,7 +88578,7 @@ function pushClusteredStackedLabels(series, sourceIndices2, catCount, layout, ra
88354
88578
  x,
88355
88579
  y: labelY,
88356
88580
  text: formatAxisValue2(val2, series[si].numberFormat),
88357
- fontSize: 7,
88581
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88358
88582
  fill: "#334155",
88359
88583
  textAnchor: "middle"
88360
88584
  });
@@ -88640,7 +88864,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
88640
88864
  x: pt.x,
88641
88865
  y: pt.y - 7,
88642
88866
  text: formatAxisValue2(val2, series.numberFormat),
88643
- fontSize: 7,
88867
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88644
88868
  fill: "#334155",
88645
88869
  textAnchor: "middle"
88646
88870
  });
@@ -88712,7 +88936,7 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
88712
88936
  x: pt.x,
88713
88937
  y: pt.y - 6,
88714
88938
  text: formatAxisValue2(val2, series.numberFormat),
88715
- fontSize: 7,
88939
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88716
88940
  fill: "#334155",
88717
88941
  textAnchor: "middle"
88718
88942
  });
@@ -88757,7 +88981,7 @@ function buildScatter(chartData, layout, range) {
88757
88981
  x: dot.cx,
88758
88982
  y: dot.cy - 6,
88759
88983
  text: formatAxisValue2(val2, series.numberFormat),
88760
- fontSize: 7,
88984
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88761
88985
  fill: "#334155",
88762
88986
  textAnchor: "middle"
88763
88987
  });
@@ -88804,7 +89028,7 @@ function buildBubbles(chartData, layout, range) {
88804
89028
  x: dot.cx,
88805
89029
  y: dot.cy - 10,
88806
89030
  text: formatAxisValue2(val2, series.numberFormat),
88807
- fontSize: 7,
89031
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
88808
89032
  fill: "#334155",
88809
89033
  textAnchor: "middle"
88810
89034
  });
@@ -88954,7 +89178,8 @@ function buildMultiLevelCategoryLabels(categoryLabels, categoryLevels, sourceInd
88954
89178
  const skip = Math.max(1, axis?.tickLabelSkip ?? 1);
88955
89179
  const textAnchor = axis?.labelAlignment === "l" ? "start" : axis?.labelAlignment === "r" ? "end" : "middle";
88956
89180
  const direction = labelsAbove ? -1 : 1;
88957
- const bandHeight = Math.max(axis?.fontSize ?? 8, 8) + 4;
89181
+ const fontPx = axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX;
89182
+ const bandHeight = Math.max(fontPx, 8) + 4;
88958
89183
  return levels.flatMap((level, levelIndex) => {
88959
89184
  const values = sourceIndices2.map((sourceIndex) => level[sourceIndex] ?? "");
88960
89185
  return groupedLabels(values).flatMap((group2) => {
@@ -89689,7 +89914,7 @@ function computeTrendlinePrimitives(chartData, catCount, layout, range, mode = "
89689
89914
  x: last.x,
89690
89915
  y: last.y - 6,
89691
89916
  text: labelParts.join(" "),
89692
- fontSize: 7,
89917
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
89693
89918
  fill: strokeColor,
89694
89919
  textAnchor: "end"
89695
89920
  };
@@ -89706,6 +89931,7 @@ function computeAxisTitlePrimitives(chartData, layout) {
89706
89931
  if (!axes || axes.length === 0) {
89707
89932
  return out;
89708
89933
  }
89934
+ const titleFontPx = (axis) => axis.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX;
89709
89935
  const catAxis = axes.find((a) => a.axisType === "catAx" && a.axPos !== "r" && a.titleText);
89710
89936
  if (catAxis?.titleText) {
89711
89937
  const xTitle = {
@@ -89713,7 +89939,7 @@ function computeAxisTitlePrimitives(chartData, layout) {
89713
89939
  x: layout.plotLeft + layout.plotWidth / 2,
89714
89940
  y: layout.plotBottom + 22,
89715
89941
  text: catAxis.titleText,
89716
- fontSize: 9,
89942
+ fontSize: titleFontPx(catAxis),
89717
89943
  fill: AXIS_TITLE_COLOR,
89718
89944
  textAnchor: "middle",
89719
89945
  fontWeight: "bold"
@@ -89729,7 +89955,7 @@ function computeAxisTitlePrimitives(chartData, layout) {
89729
89955
  x: yx,
89730
89956
  y: yy,
89731
89957
  text: valAxis.titleText,
89732
- fontSize: 9,
89958
+ fontSize: titleFontPx(valAxis),
89733
89959
  fill: AXIS_TITLE_COLOR,
89734
89960
  textAnchor: "middle",
89735
89961
  fontWeight: "bold",
@@ -90214,7 +90440,7 @@ function buildComboViewModel(element, chartData, categoryLabels) {
90214
90440
  x: point.x,
90215
90441
  y: point.y - 7,
90216
90442
  text: formatAxisValue2(point.value, series.numberFormat),
90217
- fontSize: 7,
90443
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
90218
90444
  fill: "#334155",
90219
90445
  textAnchor: "middle"
90220
90446
  });
@@ -90269,7 +90495,7 @@ function appendBarLabels(series, chartData, layout, catCount, range, sourceIndic
90269
90495
  x: xPositions?.[displayIndex] ?? layout.plotLeft + groupWidth * displayIndex + offset + barWidth / 2,
90270
90496
  y: value >= 0 ? Math.min(zeroY, valueY) - 4 : Math.max(zeroY, valueY) + 10,
90271
90497
  text: formatAxisValue2(value, series.numberFormat),
90272
- fontSize: 7,
90498
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
90273
90499
  fill: "#334155",
90274
90500
  textAnchor: "middle"
90275
90501
  });
@@ -90370,7 +90596,7 @@ function buildStockViewModel(element, chartData, categoryLabels) {
90370
90596
  x: cx,
90371
90597
  y: highY - 4,
90372
90598
  text: formatAxisValue2(close),
90373
- fontSize: 7,
90599
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
90374
90600
  fill: "#334155",
90375
90601
  textAnchor: "middle"
90376
90602
  });
@@ -90815,7 +91041,7 @@ function buildHistogramViewModel(element, chartData, categoryLabels) {
90815
91041
  x: bar.x + bar.w / 2,
90816
91042
  y: bar.y - 4,
90817
91043
  text: formatAxisValue2(values[index]),
90818
- fontSize: 7,
91044
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
90819
91045
  fill: DATA_LABEL_COLOR,
90820
91046
  textAnchor: "middle"
90821
91047
  })) : [];
@@ -91124,8 +91350,8 @@ function sliceAngles(values) {
91124
91350
  });
91125
91351
  }
91126
91352
  function computeOfPieGeom(element, secondPieSize) {
91127
- const svgWidth = Math.max(element.width, 320);
91128
- const svgHeight = Math.max(element.height, 180);
91353
+ const svgWidth = Math.max(element.width, 1);
91354
+ const svgHeight = Math.max(element.height, 1);
91129
91355
  const primaryR = Math.max(Math.min(svgWidth * 0.28, svgHeight * 0.4), 4);
91130
91356
  const secScale = Math.min(Math.max(secondPieSize / 100, 0.3), 1.4);
91131
91357
  return {
@@ -91145,7 +91371,7 @@ function sliceLabel(x, y, value) {
91145
91371
  x,
91146
91372
  y,
91147
91373
  text: formatAxisValue2(value),
91148
- fontSize: 8,
91374
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
91149
91375
  fill: "#ffffff",
91150
91376
  textAnchor: "middle",
91151
91377
  fontWeight: "bold",
@@ -91320,7 +91546,7 @@ function buildPieDataLabels(params) {
91320
91546
  x: slice.labelX,
91321
91547
  y: slice.labelY,
91322
91548
  text: formatAxisValue2(val2, numberFormat),
91323
- fontSize: 8,
91549
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
91324
91550
  fill: "#ffffff",
91325
91551
  textAnchor: "middle",
91326
91552
  fontWeight: "bold",
@@ -91340,7 +91566,7 @@ function buildPieDataLabels(params) {
91340
91566
  x: labelX + (cos >= 0 ? 2 : -2),
91341
91567
  y: labelY,
91342
91568
  text: formatAxisValue2(val2, numberFormat),
91343
- fontSize: 8,
91569
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
91344
91570
  fill: "#334155",
91345
91571
  textAnchor: anchor,
91346
91572
  dominantBaseline: "central"
@@ -91764,7 +91990,8 @@ function textPrimitives(shape, box) {
91764
91990
  if (!shape.paragraphs || shape.paragraphs.length === 0) {
91765
91991
  return [];
91766
91992
  }
91767
- const lineH = 12;
91993
+ const fontPxOf = (para) => para.fontSize !== void 0 ? chartFontPx(para.fontSize) : DEFAULT_CHART_TEXT_PX;
91994
+ const lineH = Math.max(12, ...shape.paragraphs.map((para) => fontPxOf(para) * 1.2));
91768
91995
  const totalH = shape.paragraphs.length * lineH;
91769
91996
  let cursorY = box.y + Math.max((box.h - totalH) / 2, 0) + lineH * 0.75;
91770
91997
  const out = [];
@@ -91781,7 +92008,7 @@ function textPrimitives(shape, box) {
91781
92008
  x: tx,
91782
92009
  y: cursorY,
91783
92010
  text: para.text,
91784
- fontSize: para.fontSize ?? 9,
92011
+ fontSize: fontPxOf(para),
91785
92012
  fill: para.color ?? "#1e293b",
91786
92013
  textAnchor: anchor,
91787
92014
  fontWeight: para.bold ? "bold" : "normal"
@@ -91977,7 +92204,7 @@ function buildWaterfallViewModel(element, chartData, categoryLabels) {
91977
92204
  x: x + barWidth / 2,
91978
92205
  y: y - 4,
91979
92206
  text: formatAxisValue2(value),
91980
- fontSize: 7,
92207
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
91981
92208
  fill: "#334155",
91982
92209
  textAnchor: "middle"
91983
92210
  });
@@ -92299,8 +92526,8 @@ function regionViewBounds(viewedRegionType, regionValues) {
92299
92526
  };
92300
92527
  }
92301
92528
  function buildRegionMapViewModel(element, chartData, categoryLabels) {
92302
- const svgWidth = Math.max(element.width, 320);
92303
- const svgHeight = Math.max(element.height, 200);
92529
+ const svgWidth = Math.max(element.width, 1);
92530
+ const svgHeight = Math.max(element.height, 1);
92304
92531
  const categories = categoryLabels.length > 0 ? categoryLabels : chartData.categories;
92305
92532
  const series = chartData.series[0];
92306
92533
  const options = series?.regionMapOptions;
@@ -92662,8 +92889,8 @@ function formatAxisValue2(val2, formatCode) {
92662
92889
  return val2.toFixed(1);
92663
92890
  }
92664
92891
  function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, options) {
92665
- const svgWidth = Math.max(320, elementWidth);
92666
- const svgHeight = Math.max(180, elementHeight);
92892
+ const svgWidth = Math.max(1, elementWidth);
92893
+ const svgHeight = Math.max(1, elementHeight);
92667
92894
  let plotLeft = hasAxes ? 48 : 8;
92668
92895
  let plotTop = 8;
92669
92896
  let plotRight = svgWidth - 8;
@@ -92743,7 +92970,7 @@ function buildGridlinesAndLabels(range, layout) {
92743
92970
  x: layout.plotLeft - 4,
92744
92971
  y,
92745
92972
  text: formatAxisValue2(val2),
92746
- fontSize: 8,
92973
+ fontSize: DEFAULT_CHART_TEXT_PX,
92747
92974
  fill: AXIS_LABEL_COLOR,
92748
92975
  textAnchor: "end",
92749
92976
  dominantBaseline: "central"
@@ -92775,7 +93002,7 @@ function buildCategoryLabels(categoryLabels, layout, catSpacing) {
92775
93002
  x,
92776
93003
  y: layout.plotBottom + 12,
92777
93004
  text: label,
92778
- fontSize: 8,
93005
+ fontSize: DEFAULT_CHART_TEXT_PX,
92779
93006
  fill: AXIS_LABEL_COLOR,
92780
93007
  textAnchor: "middle"
92781
93008
  };
@@ -93120,8 +93347,8 @@ function buildFlatViewModel(element, chartData, categoryLabels, kind) {
93120
93347
  return buildCartesianViewModel(element, chartData, categoryLabels, kind);
93121
93348
  }
93122
93349
  function buildFallbackViewModel(width, height, label) {
93123
- const svgWidth = Math.max(width, 100);
93124
- const svgHeight = Math.max(height, 60);
93350
+ const svgWidth = Math.max(width, 1);
93351
+ const svgHeight = Math.max(height, 1);
93125
93352
  return {
93126
93353
  svgWidth,
93127
93354
  svgHeight,
@@ -93275,7 +93502,7 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
93275
93502
  x: cx + labelR * Math.cos(angle),
93276
93503
  y: cy + labelR * Math.sin(angle),
93277
93504
  text: categoryLabels[i] ?? "",
93278
- fontSize: 8,
93505
+ fontSize: DEFAULT_CHART_TEXT_PX,
93279
93506
  fill: RADAR_LABEL_COLOR,
93280
93507
  textAnchor: "middle",
93281
93508
  dominantBaseline: "central"
@@ -93319,7 +93546,7 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
93319
93546
  x: p.x,
93320
93547
  y: p.y - 8,
93321
93548
  text: formatAxisValue2(val2, series.numberFormat),
93322
- fontSize: 7,
93549
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
93323
93550
  fill: "#334155",
93324
93551
  textAnchor: "middle"
93325
93552
  });
@@ -98263,25 +98490,39 @@ function getImageFitStyle(el) {
98263
98490
  if (!isImageLikeElement(el)) {
98264
98491
  return uncropped;
98265
98492
  }
98493
+ const frLeft = el.fillRectLeft ?? 0;
98494
+ const frTop = el.fillRectTop ?? 0;
98495
+ const frRight = el.fillRectRight ?? 0;
98496
+ const frBottom = el.fillRectBottom ?? 0;
98497
+ const hasFillRect = Math.abs(frLeft) + Math.abs(frTop) + Math.abs(frRight) + Math.abs(frBottom) > 1e-4;
98498
+ const placementTransform = hasFillRect ? `translate(${round2(frLeft * 100)}%, ${round2(frTop * 100)}%) scale(${round6(
98499
+ Math.max(0.01, 1 - frLeft - frRight)
98500
+ )}, ${round6(Math.max(0.01, 1 - frTop - frBottom))})` : "";
98266
98501
  const cropLeft = clampCropValue(el.cropLeft);
98267
98502
  const cropTop = clampCropValue(el.cropTop);
98268
98503
  const cropRight = clampCropValue(el.cropRight);
98269
98504
  const cropBottom = clampCropValue(el.cropBottom);
98270
- if (cropLeft + cropRight <= 1e-4 && cropTop + cropBottom <= 1e-4) {
98505
+ const hasCrop = cropLeft + cropRight > 1e-4 || cropTop + cropBottom > 1e-4;
98506
+ if (!hasCrop && !hasFillRect) {
98271
98507
  return uncropped;
98272
98508
  }
98273
- const horizontalScale = cropLeft + cropRight >= 0.99 ? 0.99 / (cropLeft + cropRight) : 1;
98274
- const verticalScale = cropTop + cropBottom >= 0.99 ? 0.99 / (cropTop + cropBottom) : 1;
98275
- const left = clampCropValue(cropLeft * horizontalScale);
98276
- const right = clampCropValue(cropRight * horizontalScale);
98277
- const top = clampCropValue(cropTop * verticalScale);
98278
- const bottom = clampCropValue(cropBottom * verticalScale);
98279
- const remainingWidth = Math.max(0.01, 1 - left - right);
98280
- const remainingHeight = Math.max(0.01, 1 - top - bottom);
98281
- const tx = Math.round(-left / remainingWidth * 1e4) / 100;
98282
- const ty = Math.round(-top / remainingHeight * 1e4) / 100;
98283
- const sx = Math.round(1 / remainingWidth * 1e6) / 1e6;
98284
- const sy = Math.round(1 / remainingHeight * 1e6) / 1e6;
98509
+ let cropTransform = "";
98510
+ if (hasCrop) {
98511
+ const horizontalScale = cropLeft + cropRight >= 0.99 ? 0.99 / (cropLeft + cropRight) : 1;
98512
+ const verticalScale = cropTop + cropBottom >= 0.99 ? 0.99 / (cropTop + cropBottom) : 1;
98513
+ const left = clampCropValue(cropLeft * horizontalScale);
98514
+ const right = clampCropValue(cropRight * horizontalScale);
98515
+ const top = clampCropValue(cropTop * verticalScale);
98516
+ const bottom = clampCropValue(cropBottom * verticalScale);
98517
+ const remainingWidth = Math.max(0.01, 1 - left - right);
98518
+ const remainingHeight = Math.max(0.01, 1 - top - bottom);
98519
+ const tx = Math.round(-left / remainingWidth * 1e4) / 100;
98520
+ const ty = Math.round(-top / remainingHeight * 1e4) / 100;
98521
+ const sx = Math.round(1 / remainingWidth * 1e6) / 1e6;
98522
+ const sy = Math.round(1 / remainingHeight * 1e6) / 1e6;
98523
+ cropTransform = `translate(${tx}%, ${ty}%) scale(${sx}, ${sy})`;
98524
+ }
98525
+ const transform = [placementTransform, cropTransform].filter(Boolean).join(" ");
98285
98526
  return {
98286
98527
  position: "absolute",
98287
98528
  width: "100%",
@@ -98290,9 +98531,15 @@ function getImageFitStyle(el) {
98290
98531
  maxHeight: "none",
98291
98532
  objectFit: "fill",
98292
98533
  transformOrigin: "top left",
98293
- transform: `translate(${tx}%, ${ty}%) scale(${sx}, ${sy})`
98534
+ transform
98294
98535
  };
98295
98536
  }
98537
+ function round2(value) {
98538
+ return Math.round(value * 100) / 100;
98539
+ }
98540
+ function round6(value) {
98541
+ return Math.round(value * 1e6) / 1e6;
98542
+ }
98296
98543
  function groupElements(elements, ids, groupId) {
98297
98544
  const idSet = new Set(ids);
98298
98545
  const gathered = [];
@@ -99078,7 +99325,10 @@ function resolveLineHeight(textStyle, hasItalicRuns2) {
99078
99325
  if (typeof textStyle?.lineSpacingExactPt === "number" && textStyle.lineSpacingExactPt > 0) {
99079
99326
  return `${textStyle.lineSpacingExactPt}pt`;
99080
99327
  }
99081
- return textStyle?.lineSpacing || DEFAULT_LINE_HEIGHT;
99328
+ return proportionalLineHeight(textStyle?.lineSpacing);
99329
+ }
99330
+ function proportionalLineHeight(lineSpacing) {
99331
+ return typeof lineSpacing === "number" && lineSpacing > 0 ? lineSpacing * DEFAULT_LINE_HEIGHT : DEFAULT_LINE_HEIGHT;
99082
99332
  }
99083
99333
  function toCssWritingMode(textDirection) {
99084
99334
  switch (textDirection) {
@@ -99129,7 +99379,7 @@ function computeAutoFitTextStyle(input) {
99129
99379
  result.fontSize = Math.max(6, Math.round(baseFontSize * ts.autoFitFontScale));
99130
99380
  } else if (ts.autoFitMode !== "normal") {
99131
99381
  const textLength = text2.length;
99132
- const lineHeight = ts.lineSpacingExactPt ? ts.lineSpacingExactPt / baseFontSize : ts.lineSpacing || DEFAULT_LINE_HEIGHT;
99382
+ const lineHeight = ts.lineSpacingExactPt ? ts.lineSpacingExactPt / baseFontSize : proportionalLineHeight(ts.lineSpacing);
99133
99383
  const approxCharsPerLine = Math.max(1, Math.floor(width / (baseFontSize * 0.6)));
99134
99384
  const estimatedLines = Math.max(1, Math.ceil(textLength / approxCharsPerLine));
99135
99385
  const requiredHeight = estimatedLines * baseFontSize * lineHeight;
@@ -99140,8 +99390,7 @@ function computeAutoFitTextStyle(input) {
99140
99390
  }
99141
99391
  }
99142
99392
  if (ts.autoFitLineSpacingReduction !== void 0 && ts.autoFitLineSpacingReduction > 0) {
99143
- const baseLineHeight = typeof ts.lineSpacing === "number" ? ts.lineSpacing : DEFAULT_LINE_HEIGHT;
99144
- result.lineHeight = baseLineHeight * (1 - ts.autoFitLineSpacingReduction);
99393
+ result.lineHeight = proportionalLineHeight(ts.lineSpacing) * (1 - ts.autoFitLineSpacingReduction);
99145
99394
  }
99146
99395
  return result;
99147
99396
  }
@@ -99961,6 +100210,8 @@ function buildTextRunFilterChain(style) {
99961
100210
  }
99962
100211
  return parts.length > 0 ? parts.join(" ") : void 0;
99963
100212
  }
100213
+ var POWERPOINT_METRIC_TRACKING_EM = 3e-3;
100214
+ var POWERPOINT_METRIC_TRACKING = `${POWERPOINT_METRIC_TRACKING_EM}em`;
99964
100215
  function resolveParagraphStrutFontSize(segments, bodyFontSize) {
99965
100216
  let largest;
99966
100217
  for (const segment of segments) {
@@ -102190,6 +102441,10 @@ var SCALAR_ELEMENT_KEYS = /* @__PURE__ */ new Set([
102190
102441
  "cropTop",
102191
102442
  "cropRight",
102192
102443
  "cropBottom",
102444
+ "fillRectLeft",
102445
+ "fillRectTop",
102446
+ "fillRectRight",
102447
+ "fillRectBottom",
102193
102448
  "tileOffsetX",
102194
102449
  "tileOffsetY",
102195
102450
  "tileScaleX",
@@ -103804,9 +104059,16 @@ var CINEMATIC_TRANSITION_KEYFRAMES = `
103804
104059
  /* \u2500\u2500 Airplane (fly off like a paper plane) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
103805
104060
  @keyframes pptx-tr-airplane-out { 0% { transform: perspective(1200px) translate3d(0, 0, 0) rotate3d(1, -1, 0, 0deg) scale(1); opacity: 1; } 40% { transform: perspective(1200px) translate3d(10%, -10%, 0) rotate3d(1, -1, 0, 25deg) scale(.85); opacity: 1; } 100% { transform: perspective(1200px) translate3d(150%, -70%, 0) rotate3d(1, -1, 1, 70deg) scale(.05); opacity: 0; } }
103806
104061
 
103807
- /* \u2500\u2500 Origami (fold out / unfold in) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
103808
- @keyframes pptx-tr-origami-out { from { transform: perspective(1600px) rotateY(0deg) scaleX(1); transform-origin: left center; opacity: 1; } to { transform: perspective(1600px) rotateY(75deg) scaleX(.25); transform-origin: left center; opacity: .2; } }
103809
- @keyframes pptx-tr-origami-in { from { transform: perspective(1600px) rotateY(-75deg) scaleX(.25); transform-origin: right center; opacity: .2; } to { transform: perspective(1600px) rotateY(0deg) scaleX(1); transform-origin: right center; opacity: 1; } }
104062
+ /* \u2500\u2500 Origami (fold the sheet over its top edge; the next unfolds up) \u2500\u2500
104063
+ The old single-phase rotateY + scaleX compressed the outgoing slide into a
104064
+ narrow vertical sliver for most of the (3+ second) duration, which read as
104065
+ "just a grey line" instead of paper folding (issue #132). The fold is now
104066
+ hinged like a real sheet: the outgoing slide creases over its TOP edge,
104067
+ dims as it tips through edge-on, and tumbles away shrinking; the incoming
104068
+ slide lies folded at its BOTTOM edge and rises into place. The edge-on
104069
+ moment is brief and already mid-fade, so no line artifact survives. */
104070
+ @keyframes pptx-tr-origami-out { 0% { transform: perspective(1400px) rotateX(0deg) translateY(0) scale(1); transform-origin: top center; opacity: 1; filter: brightness(1); } 45% { transform: perspective(1400px) rotateX(-52deg) translateY(2%) scale(.96); transform-origin: top center; opacity: 1; filter: brightness(.82); } 70% { transform: perspective(1400px) rotateX(-84deg) translateY(8%) scale(.88); transform-origin: top center; opacity: .8; filter: brightness(.68); } 100% { transform: perspective(1400px) rotateX(-125deg) translateY(30%) scale(.68); transform-origin: top center; opacity: 0; filter: brightness(.55); } }
104071
+ @keyframes pptx-tr-origami-in { 0% { transform: perspective(1400px) rotateX(62deg) scale(.94); transform-origin: bottom center; opacity: 0; filter: brightness(.7); } 30% { transform: perspective(1400px) rotateX(62deg) scale(.94); transform-origin: bottom center; opacity: .65; filter: brightness(.75); } 100% { transform: perspective(1400px) rotateX(0deg) scale(1); transform-origin: bottom center; opacity: 1; filter: brightness(1); } }
103810
104072
  `;
103811
104073
  var CORE_SLIDE_TRANSITION_KEYFRAMES = `
103812
104074
  /* \u2500\u2500 Fade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
@@ -110531,6 +110793,103 @@ function mediaTransportVisible(surface) {
110531
110793
  }
110532
110794
  return surface.canvasTransport;
110533
110795
  }
110796
+ var persistentAudioMap = /* @__PURE__ */ new Map();
110797
+ function registerPersistentAudio(elementId, dataUrl, mimetype, loop, volume, trimStartSec) {
110798
+ if (persistentAudioMap.has(elementId) || typeof document === "undefined") {
110799
+ return;
110800
+ }
110801
+ const audio = document.createElement("audio");
110802
+ audio.src = dataUrl;
110803
+ if (mimetype) {
110804
+ const source = document.createElement("source");
110805
+ source.src = dataUrl;
110806
+ source.type = mimetype;
110807
+ audio.appendChild(source);
110808
+ }
110809
+ audio.loop = loop;
110810
+ audio.volume = Math.max(0, Math.min(1, volume));
110811
+ if (trimStartSec > 0) {
110812
+ try {
110813
+ audio.currentTime = trimStartSec;
110814
+ } catch {
110815
+ }
110816
+ }
110817
+ audio.style.display = "none";
110818
+ audio.setAttribute("data-pptx-persistent-audio", elementId);
110819
+ document.body.appendChild(audio);
110820
+ persistentAudioMap.set(elementId, { elementId, audio, loop, pausedByVisibility: false });
110821
+ void audio.play().catch(() => {
110822
+ });
110823
+ }
110824
+ function stopAllPersistentAudio() {
110825
+ for (const entry2 of persistentAudioMap.values()) {
110826
+ entry2.audio.pause();
110827
+ entry2.audio.remove();
110828
+ }
110829
+ persistentAudioMap.clear();
110830
+ }
110831
+ function pauseAllPersistentAudio() {
110832
+ for (const entry2 of persistentAudioMap.values()) {
110833
+ if (!entry2.audio.paused) {
110834
+ entry2.pausedByVisibility = true;
110835
+ entry2.audio.pause();
110836
+ }
110837
+ }
110838
+ }
110839
+ function resumeAllPersistentAudio() {
110840
+ for (const entry2 of persistentAudioMap.values()) {
110841
+ if (entry2.pausedByVisibility) {
110842
+ entry2.pausedByVisibility = false;
110843
+ void entry2.audio.play().catch(() => {
110844
+ });
110845
+ }
110846
+ }
110847
+ }
110848
+ function attachPresentationVisibilityPause(options = {}) {
110849
+ if (typeof document === "undefined") {
110850
+ return () => {
110851
+ };
110852
+ }
110853
+ const root = options.root ?? document;
110854
+ let pausedMedia = [];
110855
+ let suspended = false;
110856
+ const update = () => {
110857
+ const shouldSuspend = document.visibilityState === "hidden" || !document.hasFocus();
110858
+ if (shouldSuspend === suspended) {
110859
+ return;
110860
+ }
110861
+ suspended = shouldSuspend;
110862
+ if (shouldSuspend) {
110863
+ pausedMedia = [];
110864
+ for (const media of root.querySelectorAll("audio, video")) {
110865
+ if (!media.paused && !media.ended) {
110866
+ pausedMedia.push(media);
110867
+ media.pause();
110868
+ }
110869
+ }
110870
+ pauseAllPersistentAudio();
110871
+ options.onHidden?.();
110872
+ return;
110873
+ }
110874
+ for (const media of pausedMedia) {
110875
+ if (media.isConnected) {
110876
+ void media.play().catch(() => {
110877
+ });
110878
+ }
110879
+ }
110880
+ pausedMedia = [];
110881
+ resumeAllPersistentAudio();
110882
+ options.onVisible?.();
110883
+ };
110884
+ document.addEventListener("visibilitychange", update);
110885
+ window.addEventListener("blur", update);
110886
+ window.addEventListener("focus", update);
110887
+ return () => {
110888
+ document.removeEventListener("visibilitychange", update);
110889
+ window.removeEventListener("blur", update);
110890
+ window.removeEventListener("focus", update);
110891
+ };
110892
+ }
110534
110893
  function buildSummaryZoomView(element, lookup) {
110535
110894
  if (element.zoomType !== "summary" || !element.summaryTargets?.length) {
110536
110895
  return void 0;
@@ -114866,6 +115225,7 @@ exports.OUTLINE_SLIDE_ATTR = OUTLINE_SLIDE_ATTR;
114866
115225
  exports.OUTLINE_VIEW_ATTR = OUTLINE_VIEW_ATTR;
114867
115226
  exports.PATTERN_OPTIONS = PATTERN_OPTIONS;
114868
115227
  exports.PEN_COLORS = PEN_COLORS;
115228
+ exports.POWERPOINT_METRIC_TRACKING = POWERPOINT_METRIC_TRACKING;
114869
115229
  exports.PRESENTATION_CHANNEL_NAME = PRESENTATION_CHANNEL_NAME;
114870
115230
  exports.PRESENTATION_HASH = PRESENTATION_HASH;
114871
115231
  exports.PRESENTATION_MESSAGE_ORIGIN = PRESENTATION_MESSAGE_ORIGIN;
@@ -114952,6 +115312,7 @@ exports.applyResize = applyResize;
114952
115312
  exports.applyStyleToSelectedSegments = applyStyleToSelectedSegments;
114953
115313
  exports.applyThemeOverrideToSlide = applyThemeOverrideToSlide;
114954
115314
  exports.applyThemeToData = applyThemeToData;
115315
+ exports.attachPresentationVisibilityPause = attachPresentationVisibilityPause;
114955
115316
  exports.availableQuickAccessCommands = availableQuickAccessCommands;
114956
115317
  exports.backstageCardsFor = backstageCardsFor;
114957
115318
  exports.bringForward = bringForward;
@@ -115296,6 +115657,7 @@ exports.previousShowSlideIndex = previousShowSlideIndex;
115296
115657
  exports.printPropertiesFrameSlides = printPropertiesFrameSlides;
115297
115658
  exports.printPropertiesSlidesPerPage = printPropertiesSlidesPerPage;
115298
115659
  exports.promoteSmartArtNode = promoteSmartArtNode;
115660
+ exports.proportionalLineHeight = proportionalLineHeight;
115299
115661
  exports.publishLiveGeometry = publishLiveGeometry;
115300
115662
  exports.publishLiveInlineText = publishLiveInlineText;
115301
115663
  exports.quickStyleSwatchCss = quickStyleSwatchCss;
@@ -115311,6 +115673,7 @@ exports.reconcileSlidesInYDoc = reconcileSlidesInYDoc;
115311
115673
  exports.recordProgressPercent = recordProgressPercent;
115312
115674
  exports.rectToCells = rectToCells;
115313
115675
  exports.registerCollaborationTeardown = registerCollaborationTeardown;
115676
+ exports.registerPersistentAudio = registerPersistentAudio;
115314
115677
  exports.remapTextToSegments = remapTextToSegments;
115315
115678
  exports.removeChartCategory = removeChartCategory;
115316
115679
  exports.removeChartSeries = removeChartSeries;
@@ -115401,6 +115764,7 @@ exports.snapBoxToGrid = snapBoxToGrid;
115401
115764
  exports.splitCell = splitCell;
115402
115765
  exports.splitSeriesByAxis = splitSeriesByAxis;
115403
115766
  exports.stepPresenterZoom = stepPresenterZoom;
115767
+ exports.stopAllPersistentAudio = stopAllPersistentAudio;
115404
115768
  exports.storeAudienceContent = storeAudienceContent;
115405
115769
  exports.substituteFieldText = substituteFieldText;
115406
115770
  exports.suppressesCssBorder = suppressesCssBorder;