pptx-react-viewer 2.5.3 → 2.6.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 (106) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/{AiChatPanel-DPMHPOWF.js → AiChatPanel-53W2JG6G.js} +22 -22
  3. package/dist/AiChatPanel-53W2JG6G.js.br +0 -0
  4. package/dist/AiChatPanel-53W2JG6G.js.gz +0 -0
  5. package/dist/{AiChatPanel-OFOOWR4U.mjs → AiChatPanel-L5IOO72H.mjs} +3 -3
  6. package/dist/AiChatPanel-L5IOO72H.mjs.br +0 -0
  7. package/dist/AiChatPanel-L5IOO72H.mjs.gz +0 -0
  8. package/dist/{Model3DScene-PD2MDBIE.js → Model3DScene-E7JGXNJN.js} +2 -2
  9. package/dist/Model3DScene-E7JGXNJN.js.br +0 -0
  10. package/dist/Model3DScene-E7JGXNJN.js.gz +0 -0
  11. package/dist/{Model3DScene-P4OKVQBF.mjs → Model3DScene-EW7OWRJK.mjs} +1 -1
  12. package/dist/Model3DScene-EW7OWRJK.mjs.br +0 -0
  13. package/dist/Model3DScene-EW7OWRJK.mjs.gz +0 -0
  14. package/dist/{SurfaceChart3DScene-FECS3THE.js → SurfaceChart3DScene-3QB6NVKD.js} +2 -2
  15. package/dist/SurfaceChart3DScene-3QB6NVKD.js.br +0 -0
  16. package/dist/SurfaceChart3DScene-3QB6NVKD.js.gz +0 -0
  17. package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs → SurfaceChart3DScene-64HI3U7Y.mjs} +1 -1
  18. package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs.br → SurfaceChart3DScene-64HI3U7Y.mjs.br} +0 -0
  19. package/dist/SurfaceChart3DScene-64HI3U7Y.mjs.gz +0 -0
  20. package/dist/{chunk-6KOM27PS.mjs → chunk-34ZW32XK.mjs} +902 -52
  21. package/dist/chunk-34ZW32XK.mjs.br +0 -0
  22. package/dist/chunk-34ZW32XK.mjs.gz +0 -0
  23. package/dist/{chunk-QDIF3ZXF.mjs → chunk-DWQJW3UM.mjs} +19 -4
  24. package/dist/chunk-DWQJW3UM.mjs.br +0 -0
  25. package/dist/chunk-DWQJW3UM.mjs.gz +0 -0
  26. package/dist/{chunk-UUS7QT22.js → chunk-EJ24IFPL.js} +346 -315
  27. package/dist/chunk-EJ24IFPL.js.br +0 -0
  28. package/dist/chunk-EJ24IFPL.js.gz +0 -0
  29. package/dist/{chunk-FFLUALX5.js → chunk-NXSAYLYI.js} +251 -236
  30. package/dist/chunk-NXSAYLYI.js.br +0 -0
  31. package/dist/chunk-NXSAYLYI.js.gz +0 -0
  32. package/dist/{chunk-SAXG53MO.mjs → chunk-PENV7S7Z.mjs} +1 -1
  33. package/dist/chunk-PENV7S7Z.mjs.br +0 -0
  34. package/dist/chunk-PENV7S7Z.mjs.gz +0 -0
  35. package/dist/{chunk-F3JUUSC4.mjs → chunk-UO55N46T.mjs} +91 -13
  36. package/dist/chunk-UO55N46T.mjs.br +0 -0
  37. package/dist/chunk-UO55N46T.mjs.gz +0 -0
  38. package/dist/{chunk-23Q3I2LM.js → chunk-UVA55CRK.js} +904 -51
  39. package/dist/chunk-UVA55CRK.js.br +0 -0
  40. package/dist/chunk-UVA55CRK.js.gz +0 -0
  41. package/dist/{chunk-USHZUHHG.js → chunk-V5XVTKFS.js} +925 -847
  42. package/dist/chunk-V5XVTKFS.js.br +0 -0
  43. package/dist/chunk-V5XVTKFS.js.gz +0 -0
  44. package/dist/{chunk-H2FZ2NJ7.js → chunk-VBWWICDF.js} +3 -3
  45. package/dist/chunk-VBWWICDF.js.br +0 -0
  46. package/dist/chunk-VBWWICDF.js.gz +0 -0
  47. package/dist/{chunk-ZZA62IND.mjs → chunk-WCO3NEH5.mjs} +35 -4
  48. package/dist/chunk-WCO3NEH5.mjs.br +0 -0
  49. package/dist/chunk-WCO3NEH5.mjs.gz +0 -0
  50. package/dist/index.d.ts +15 -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 +42 -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/pptx-viewer.css +1 -1
  66. package/dist/pptx-viewer.css.br +0 -0
  67. package/dist/pptx-viewer.css.gz +0 -0
  68. package/dist/viewer/index.d.ts +15 -0
  69. package/dist/viewer/index.js +21 -21
  70. package/dist/viewer/index.js.br +0 -0
  71. package/dist/viewer/index.js.gz +0 -0
  72. package/dist/viewer/index.mjs +5 -5
  73. package/dist/viewer/index.mjs.br +0 -0
  74. package/dist/viewer/index.mjs.gz +0 -0
  75. package/package.json +1 -1
  76. package/dist/AiChatPanel-DPMHPOWF.js.br +0 -0
  77. package/dist/AiChatPanel-DPMHPOWF.js.gz +0 -0
  78. package/dist/AiChatPanel-OFOOWR4U.mjs.br +0 -0
  79. package/dist/AiChatPanel-OFOOWR4U.mjs.gz +0 -0
  80. package/dist/Model3DScene-P4OKVQBF.mjs.br +0 -0
  81. package/dist/Model3DScene-P4OKVQBF.mjs.gz +0 -0
  82. package/dist/Model3DScene-PD2MDBIE.js.br +0 -0
  83. package/dist/Model3DScene-PD2MDBIE.js.gz +0 -0
  84. package/dist/SurfaceChart3DScene-FECS3THE.js.br +0 -0
  85. package/dist/SurfaceChart3DScene-FECS3THE.js.gz +0 -0
  86. package/dist/SurfaceChart3DScene-TL4ZIOI4.mjs.gz +0 -0
  87. package/dist/chunk-23Q3I2LM.js.br +0 -0
  88. package/dist/chunk-23Q3I2LM.js.gz +0 -0
  89. package/dist/chunk-6KOM27PS.mjs.br +0 -0
  90. package/dist/chunk-6KOM27PS.mjs.gz +0 -0
  91. package/dist/chunk-F3JUUSC4.mjs.br +0 -0
  92. package/dist/chunk-F3JUUSC4.mjs.gz +0 -0
  93. package/dist/chunk-FFLUALX5.js.br +0 -0
  94. package/dist/chunk-FFLUALX5.js.gz +0 -0
  95. package/dist/chunk-H2FZ2NJ7.js.br +0 -0
  96. package/dist/chunk-H2FZ2NJ7.js.gz +0 -0
  97. package/dist/chunk-QDIF3ZXF.mjs.br +0 -0
  98. package/dist/chunk-QDIF3ZXF.mjs.gz +0 -0
  99. package/dist/chunk-SAXG53MO.mjs.br +0 -0
  100. package/dist/chunk-SAXG53MO.mjs.gz +0 -0
  101. package/dist/chunk-USHZUHHG.js.br +0 -0
  102. package/dist/chunk-USHZUHHG.js.gz +0 -0
  103. package/dist/chunk-UUS7QT22.js.br +0 -0
  104. package/dist/chunk-UUS7QT22.js.gz +0 -0
  105. package/dist/chunk-ZZA62IND.mjs.br +0 -0
  106. package/dist/chunk-ZZA62IND.mjs.gz +0 -0
@@ -12661,9 +12661,9 @@ var PptxEffectDagExtractor = class {
12661
12661
  if (Number.isFinite(endPos)) {
12662
12662
  style.reflectionEndPosition = endPos / 1e5;
12663
12663
  }
12664
- const dist = parseInt(String(refl["@_dist"] || ""), 10);
12665
- if (Number.isFinite(dist) && dist >= 0) {
12666
- style.reflectionDistance = dist / this.context.emuPerPx;
12664
+ const dist2 = parseInt(String(refl["@_dist"] || ""), 10);
12665
+ if (Number.isFinite(dist2) && dist2 >= 0) {
12666
+ style.reflectionDistance = dist2 / this.context.emuPerPx;
12667
12667
  }
12668
12668
  }
12669
12669
  extractDagBlur(dag, style) {
@@ -13810,10 +13810,7 @@ var PptxShapeStyleExtractor = class {
13810
13810
  }
13811
13811
  const lineNode = shapeProps["a:ln"];
13812
13812
  if (lineNode) {
13813
- const earlyReturn = applyLineProperties(lineNode, style, this.context);
13814
- if (earlyReturn) {
13815
- return style;
13816
- }
13813
+ applyLineProperties(lineNode, style, this.context);
13817
13814
  } else if (styleNode?.["a:lnRef"]) {
13818
13815
  this.context.resolveThemeLineRef(styleNode["a:lnRef"], style);
13819
13816
  }
@@ -20394,6 +20391,11 @@ var STANDARD_TRANSITION_TYPES = /* @__PURE__ */ new Set([
20394
20391
  ]);
20395
20392
  var SPEEDS = /* @__PURE__ */ new Set(["slow", "med", "fast"]);
20396
20393
  var UINT_MAX = 4294967295;
20394
+ var MORPH_OPTIONS = /* @__PURE__ */ new Set(["byObject", "byWord", "byChar"]);
20395
+ function normalizeMorphOption(value) {
20396
+ const candidate = token(value);
20397
+ return MORPH_OPTIONS.has(candidate) ? candidate : void 0;
20398
+ }
20397
20399
  function parseTransitionDetails(node, localName22) {
20398
20400
  const result = { type: "cut" };
20399
20401
  for (const [key, value] of Object.entries(node)) {
@@ -20409,6 +20411,11 @@ function parseTransitionDetails(node, localName22) {
20409
20411
  result.rawExtLst = value;
20410
20412
  continue;
20411
20413
  }
20414
+ if (name === "morph") {
20415
+ result.type = "morph";
20416
+ result.morphOption = normalizeMorphOption(value?.["@_option"]);
20417
+ continue;
20418
+ }
20412
20419
  if (STANDARD_TRANSITION_TYPES.has(name)) {
20413
20420
  result.type = name;
20414
20421
  }
@@ -20608,6 +20615,7 @@ var PptxSlideTransitionService = class {
20608
20615
  let transitionType = details.type;
20609
20616
  let { direction, orient, pattern } = details;
20610
20617
  const { spokes, thruBlk, rawSoundAction, rawExtLst } = details;
20618
+ let { morphOption } = details;
20611
20619
  if (rawExtLst && transitionType === "cut") {
20612
20620
  const p14Result = parseP14FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
20613
20621
  const p15Result = p14Result ? void 0 : parseP15FromExtLst(rawExtLst, this.xmlLookupService, this.getXmlLocalName);
@@ -20624,8 +20632,12 @@ var PptxSlideTransitionService = class {
20624
20632
  }
20625
20633
  } else if (p15Result) {
20626
20634
  transitionType = p15Result.type;
20627
- } else if (this.parseMorphFromExtLst(rawExtLst)) {
20628
- transitionType = "morph";
20635
+ } else {
20636
+ const morphResult = this.parseMorphFromExtLst(rawExtLst);
20637
+ if (morphResult) {
20638
+ transitionType = "morph";
20639
+ morphOption = morphResult.morphOption;
20640
+ }
20629
20641
  }
20630
20642
  }
20631
20643
  const attributes = parseTransitionAttributes(transitionNode);
@@ -20638,6 +20650,7 @@ var PptxSlideTransitionService = class {
20638
20650
  spokes,
20639
20651
  pattern,
20640
20652
  thruBlk,
20653
+ morphOption,
20641
20654
  ...sound,
20642
20655
  rawSoundAction,
20643
20656
  rawExtLst,
@@ -20683,21 +20696,18 @@ var PptxSlideTransitionService = class {
20683
20696
  if (!ext) {
20684
20697
  continue;
20685
20698
  }
20686
- const uri = String(ext["@_uri"] || "").trim();
20687
- const matchesUri = uri.toUpperCase() === MORPH_EXT_URI.toUpperCase();
20688
- for (const key of Object.keys(ext)) {
20699
+ for (const [key, value] of Object.entries(ext)) {
20689
20700
  if (key.startsWith("@_")) {
20690
20701
  continue;
20691
20702
  }
20692
20703
  if (this.getXmlLocalName(key) === "morph") {
20693
- if (matchesUri || uri.length === 0) {
20694
- return true;
20695
- }
20696
- return true;
20704
+ return {
20705
+ morphOption: normalizeMorphOption(value?.["@_option"])
20706
+ };
20697
20707
  }
20698
20708
  }
20699
20709
  }
20700
- return false;
20710
+ return void 0;
20701
20711
  }
20702
20712
  buildSlideTransitionXml(transition) {
20703
20713
  if (!transition || transition.type === "none") {
@@ -20721,7 +20731,9 @@ var PptxSlideTransitionService = class {
20721
20731
  } else if (isP15Type) {
20722
20732
  node["p:extLst"] = transition.rawExtLst ?? buildP15ExtLst(transitionType);
20723
20733
  } else if (isMorphType) {
20724
- node["p:extLst"] = this.buildMorphExtLst(transition.rawExtLst);
20734
+ if (!this.hasDirectMorphChild(node)) {
20735
+ node["p:extLst"] = this.buildMorphExtLst(transition.rawExtLst, transition.morphOption);
20736
+ }
20725
20737
  } else {
20726
20738
  node[`p:${transitionType}`] = buildStandardTransitionChild(transition);
20727
20739
  }
@@ -20735,16 +20747,32 @@ var PptxSlideTransitionService = class {
20735
20747
  }
20736
20748
  return node;
20737
20749
  }
20750
+ /**
20751
+ * True when the (preserved) transition node already carries a `morph`
20752
+ * element as a direct child, in any namespace prefix.
20753
+ */
20754
+ hasDirectMorphChild(node) {
20755
+ for (const key of Object.keys(node)) {
20756
+ if (!key.startsWith("@_") && this.getXmlLocalName(key) === "morph") {
20757
+ return true;
20758
+ }
20759
+ }
20760
+ return false;
20761
+ }
20738
20762
  /**
20739
20763
  * Build the extLst XML node for a morph (p159) transition, preserving any
20740
20764
  * non-morph extensions from rawExtLst.
20741
20765
  */
20742
- buildMorphExtLst(rawExtLst) {
20766
+ buildMorphExtLst(rawExtLst, morphOption) {
20767
+ const morphNode = {
20768
+ "@_xmlns:p159": "http://schemas.microsoft.com/office/powerpoint/2015/09/main"
20769
+ };
20770
+ if (morphOption) {
20771
+ morphNode["@_option"] = morphOption;
20772
+ }
20743
20773
  const morphExt = {
20744
20774
  "@_uri": MORPH_EXT_URI,
20745
- "p159:morph": {
20746
- "@_xmlns:p159": "http://schemas.microsoft.com/office/powerpoint/2015/09/main"
20747
- }
20775
+ "p159:morph": morphNode
20748
20776
  };
20749
20777
  if (!rawExtLst) {
20750
20778
  return { "p:ext": morphExt };
@@ -49665,17 +49693,17 @@ function buildShadowColorNode(hex10, opacity2) {
49665
49693
  };
49666
49694
  }
49667
49695
  function distAndDir(ox, oy) {
49668
- const dist = Math.sqrt(ox * ox + oy * oy);
49696
+ const dist2 = Math.sqrt(ox * ox + oy * oy);
49669
49697
  const dir = Math.atan2(oy, ox) * 180 / Math.PI;
49670
- return { dist, dir };
49698
+ return { dist: dist2, dir };
49671
49699
  }
49672
49700
  function buildOuterShadowNode(style) {
49673
49701
  const ox = style.textShadowOffsetX ?? 0;
49674
49702
  const oy = style.textShadowOffsetY ?? 0;
49675
- const { dist, dir } = distAndDir(ox, oy);
49703
+ const { dist: dist2, dir } = distAndDir(ox, oy);
49676
49704
  return {
49677
49705
  "@_blurRad": String(Math.round((style.textShadowBlur ?? 4) * EMU_PER_PX8)),
49678
- "@_dist": String(Math.round(dist * EMU_PER_PX8)),
49706
+ "@_dist": String(Math.round(dist2 * EMU_PER_PX8)),
49679
49707
  "@_dir": String(Math.round(dir * 6e4)),
49680
49708
  "a:srgbClr": buildShadowColorNode(style.textShadowColor || "#000000", style.textShadowOpacity)
49681
49709
  };
@@ -49683,10 +49711,10 @@ function buildOuterShadowNode(style) {
49683
49711
  function buildInnerShadowNode(style) {
49684
49712
  const ox = style.textInnerShadowOffsetX ?? 0;
49685
49713
  const oy = style.textInnerShadowOffsetY ?? 0;
49686
- const { dist, dir } = distAndDir(ox, oy);
49714
+ const { dist: dist2, dir } = distAndDir(ox, oy);
49687
49715
  return {
49688
49716
  "@_blurRad": String(Math.round((style.textInnerShadowBlur ?? 3) * EMU_PER_PX8)),
49689
- "@_dist": String(Math.round(dist * EMU_PER_PX8)),
49717
+ "@_dist": String(Math.round(dist2 * EMU_PER_PX8)),
49690
49718
  "@_dir": String(Math.round(dir * 6e4)),
49691
49719
  "a:srgbClr": buildShadowColorNode(
49692
49720
  style.textInnerShadowColor || "#000000",
@@ -51312,10 +51340,10 @@ var PptxHandlerRuntime18 = class extends PptxHandlerRuntime17 {
51312
51340
  const distRaw = Number.parseInt(String(outerShdw["@_dist"] || ""), 10);
51313
51341
  const dirRaw = Number.parseInt(String(outerShdw["@_dir"] || ""), 10);
51314
51342
  if (Number.isFinite(distRaw) && distRaw >= 0) {
51315
- const dist = distRaw / PptxHandlerRuntime17.EMU_PER_PX;
51343
+ const dist2 = distRaw / PptxHandlerRuntime17.EMU_PER_PX;
51316
51344
  const dirRad = (Number.isFinite(dirRaw) ? dirRaw / 6e4 : 0) * Math.PI / 180;
51317
- style.textShadowOffsetX = Math.round(Math.cos(dirRad) * dist * 100) / 100;
51318
- style.textShadowOffsetY = Math.round(Math.sin(dirRad) * dist * 100) / 100;
51345
+ style.textShadowOffsetX = Math.round(Math.cos(dirRad) * dist2 * 100) / 100;
51346
+ style.textShadowOffsetY = Math.round(Math.sin(dirRad) * dist2 * 100) / 100;
51319
51347
  }
51320
51348
  }
51321
51349
  const glowNode = runEffectList["a:glow"];
@@ -62905,6 +62933,12 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime26 extends PptxHandlerRuntim
62905
62933
  ...endParagraphStyle,
62906
62934
  ...defaultRunStyle
62907
62935
  };
62936
+ if (mergedDefaultRunStyle.color === void 0 && ctx.styleFontRefColor !== void 0) {
62937
+ mergedDefaultRunStyle.color = ctx.styleFontRefColor;
62938
+ }
62939
+ if (mergedDefaultRunStyle.fontFamily === void 0 && ctx.styleFontRefTypeface !== void 0) {
62940
+ mergedDefaultRunStyle.fontFamily = ctx.styleFontRefTypeface;
62941
+ }
62908
62942
  if (ctx.effectiveLevelStyles) {
62909
62943
  const normalizedLevel = level === -1 ? -1 : Number.isFinite(level) ? Math.min(Math.max(level, 0), 8) : 0;
62910
62944
  const phLevel = ctx.effectiveLevelStyles[normalizedLevel] ?? ctx.effectiveLevelStyles[-1] ?? (normalizedLevel === -1 ? ctx.effectiveLevelStyles[0] : void 0);
@@ -62977,10 +63011,17 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
62977
63011
  } else {
62978
63012
  bulletText = "\u2022 ";
62979
63013
  }
63014
+ const bulletStyle = { ...mergedDefaultRunStyle };
63015
+ if (paragraphBulletInfo.sizePercent === void 0 && paragraphBulletInfo.sizePts === void 0) {
63016
+ const firstRunSize = this.resolveFirstRunFontSize(p, paraAlign, ctx);
63017
+ if (firstRunSize !== void 0) {
63018
+ bulletStyle.fontSize = firstRunSize;
63019
+ }
63020
+ }
62980
63021
  parts.push(bulletText);
62981
63022
  segments.push({
62982
63023
  text: bulletText,
62983
- style: { ...mergedDefaultRunStyle },
63024
+ style: bulletStyle,
62984
63025
  bulletInfo: paragraphBulletInfo
62985
63026
  });
62986
63027
  maybeSeed(mergedDefaultRunStyle);
@@ -63190,6 +63231,32 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
63190
63231
  }
63191
63232
  return { parts, segments, seedStyle };
63192
63233
  }
63234
+ /**
63235
+ * Font size (px) of the first text run in a paragraph, or `undefined` when
63236
+ * the paragraph has no run that declares one.
63237
+ *
63238
+ * Used to size an unsized bullet the way PowerPoint does: `a:buChar` /
63239
+ * `a:buAutoNum` with no `a:buSzPct`/`a:buSzPts` inherits the first run's
63240
+ * size. Only `a:r` and `a:fld` carry renderable text; `a:br` does not.
63241
+ */
63242
+ resolveFirstRunFontSize(p, paraAlign, ctx) {
63243
+ for (const key of ["a:r", "a:fld"]) {
63244
+ const node = p[key];
63245
+ if (!node) {
63246
+ continue;
63247
+ }
63248
+ const first = this.ensureArray(node)[0];
63249
+ const runProps = first?.["a:rPr"];
63250
+ if (!runProps) {
63251
+ continue;
63252
+ }
63253
+ const style = this.extractTextRunStyle(runProps, paraAlign, ctx.slideRelationshipMap);
63254
+ if (typeof style.fontSize === "number") {
63255
+ return style.fontSize;
63256
+ }
63257
+ }
63258
+ return void 0;
63259
+ }
63193
63260
  /**
63194
63261
  * Parse an `a:ruby` element into a {@link TextSegment} with ruby annotation metadata.
63195
63262
  *
@@ -63411,15 +63478,13 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime27 extends PptxHandlerRuntim
63411
63478
  Object.assign(textStyle, bodyDefaultRunStyle);
63412
63479
  const fontRef = styleNode?.["a:fontRef"];
63413
63480
  const fontRefIdx = String(fontRef?.["@_idx"] || "").toLowerCase();
63414
- if (!textStyle.fontFamily && fontRefIdx.length > 0) {
63415
- const token2 = fontRefIdx.includes("minor") ? "+mn-lt" : "+mj-lt";
63416
- const resolved = this.resolveThemeTypeface(token2);
63417
- if (resolved) {
63418
- textStyle.fontFamily = resolved;
63419
- }
63481
+ const styleFontRefTypeface = fontRefIdx.length > 0 ? this.resolveThemeTypeface(fontRefIdx.includes("minor") ? "+mn-lt" : "+mj-lt") : void 0;
63482
+ const styleFontRefColor = fontRef ? this.parseColor(fontRef) : void 0;
63483
+ if (!textStyle.fontFamily && styleFontRefTypeface) {
63484
+ textStyle.fontFamily = styleFontRefTypeface;
63420
63485
  }
63421
63486
  if (!textStyle.color) {
63422
- textStyle.color = this.parseColor(fontRef);
63487
+ textStyle.color = styleFontRefColor;
63423
63488
  }
63424
63489
  const bodyPr = txBody?.["a:bodyPr"] || inheritedTxBody?.["a:bodyPr"];
63425
63490
  const bodyPropResult = this.applyBodyProperties(
@@ -63450,7 +63515,9 @@ var PptxHandlerRuntime64 = class _PptxHandlerRuntime27 extends PptxHandlerRuntim
63450
63515
  placeholderInfo: placeholderInfo ?? void 0,
63451
63516
  phDefaults,
63452
63517
  slidePath,
63453
- effectiveLevelStyles
63518
+ effectiveLevelStyles,
63519
+ styleFontRefColor,
63520
+ styleFontRefTypeface
63454
63521
  };
63455
63522
  paras.forEach((p, pIdx) => {
63456
63523
  const styleResult = this.resolveShapeParagraphStyle(p, textStyle, ctx);
@@ -66360,12 +66427,12 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66360
66427
  if (Number.isFinite(blurRad) && blurRad > 0) {
66361
66428
  result.shadowBlur = blurRad / _PptxHandlerRuntime33.EMU_PER_PX;
66362
66429
  }
66363
- const dist = parseInt(String(outerShdw["@_dist"] || "0"));
66430
+ const dist2 = parseInt(String(outerShdw["@_dist"] || "0"));
66364
66431
  const dir = parseInt(String(outerShdw["@_dir"] || "0"));
66365
- if (Number.isFinite(dist) && dist > 0 && Number.isFinite(dir)) {
66432
+ if (Number.isFinite(dist2) && dist2 > 0 && Number.isFinite(dir)) {
66366
66433
  const angleRad = dir / 6e4 * (Math.PI / 180);
66367
- result.shadowOffsetX = Math.cos(angleRad) * dist / _PptxHandlerRuntime33.EMU_PER_PX;
66368
- result.shadowOffsetY = Math.sin(angleRad) * dist / _PptxHandlerRuntime33.EMU_PER_PX;
66434
+ result.shadowOffsetX = Math.cos(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66435
+ result.shadowOffsetY = Math.sin(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66369
66436
  }
66370
66437
  }
66371
66438
  const innerShdw = effectLst["a:innerShdw"];
@@ -66376,12 +66443,12 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66376
66443
  if (Number.isFinite(blurRad) && blurRad > 0) {
66377
66444
  result.innerShadowBlur = blurRad / _PptxHandlerRuntime33.EMU_PER_PX;
66378
66445
  }
66379
- const dist = parseInt(String(innerShdw["@_dist"] || "0"));
66446
+ const dist2 = parseInt(String(innerShdw["@_dist"] || "0"));
66380
66447
  const dir = parseInt(String(innerShdw["@_dir"] || "0"));
66381
- if (Number.isFinite(dist) && dist > 0 && Number.isFinite(dir)) {
66448
+ if (Number.isFinite(dist2) && dist2 > 0 && Number.isFinite(dir)) {
66382
66449
  const angleRad = dir / 6e4 * (Math.PI / 180);
66383
- result.innerShadowOffsetX = Math.cos(angleRad) * dist / _PptxHandlerRuntime33.EMU_PER_PX;
66384
- result.innerShadowOffsetY = Math.sin(angleRad) * dist / _PptxHandlerRuntime33.EMU_PER_PX;
66450
+ result.innerShadowOffsetX = Math.cos(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66451
+ result.innerShadowOffsetY = Math.sin(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66385
66452
  }
66386
66453
  }
66387
66454
  const glow = effectLst["a:glow"];
@@ -66426,9 +66493,9 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66426
66493
  if (Number.isFinite(rot)) {
66427
66494
  result.reflectionRotation = rot / 6e4;
66428
66495
  }
66429
- const dist = parseInt(String(reflection["@_dist"] || "0"));
66430
- if (Number.isFinite(dist) && dist >= 0) {
66431
- result.reflectionDistance = dist / _PptxHandlerRuntime33.EMU_PER_PX;
66496
+ const dist2 = parseInt(String(reflection["@_dist"] || "0"));
66497
+ if (Number.isFinite(dist2) && dist2 >= 0) {
66498
+ result.reflectionDistance = dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66432
66499
  }
66433
66500
  }
66434
66501
  const scene3dNode = es["a:scene3d"];
@@ -97948,6 +98015,789 @@ function sanitizeMathMl(markup) {
97948
98015
  }
97949
98016
  return sanitized;
97950
98017
  }
98018
+ function resolveParagraphStrutFontSize(segments, bodyFontSize) {
98019
+ let largest;
98020
+ for (const segment of segments) {
98021
+ if (segment.bulletInfo) {
98022
+ continue;
98023
+ }
98024
+ const size = segment.style?.fontSize;
98025
+ if (typeof size !== "number" || !Number.isFinite(size) || size <= 0) {
98026
+ continue;
98027
+ }
98028
+ if (largest === void 0 || size > largest) {
98029
+ largest = size;
98030
+ }
98031
+ }
98032
+ if (largest === void 0) {
98033
+ return void 0;
98034
+ }
98035
+ if (typeof bodyFontSize === "number" && Math.abs(largest - bodyFontSize) < 0.01) {
98036
+ return void 0;
98037
+ }
98038
+ return largest;
98039
+ }
98040
+ function parseHexColor(hex10) {
98041
+ if (!hex10 || typeof hex10 !== "string") {
98042
+ return null;
98043
+ }
98044
+ let cleaned = hex10.replace(/^#/u, "");
98045
+ if (cleaned.length === 3) {
98046
+ cleaned = cleaned[0] + cleaned[0] + cleaned[1] + cleaned[1] + cleaned[2] + cleaned[2];
98047
+ } else if (cleaned.length === 4) {
98048
+ cleaned = cleaned[0] + cleaned[0] + cleaned[1] + cleaned[1] + cleaned[2] + cleaned[2] + cleaned[3] + cleaned[3];
98049
+ }
98050
+ if (cleaned.length !== 6 && cleaned.length !== 8) {
98051
+ return null;
98052
+ }
98053
+ const r = Number.parseInt(cleaned.slice(0, 2), 16);
98054
+ const g = Number.parseInt(cleaned.slice(2, 4), 16);
98055
+ const b = Number.parseInt(cleaned.slice(4, 6), 16);
98056
+ const a = cleaned.length === 8 ? Number.parseInt(cleaned.slice(6, 8), 16) / 255 : 1;
98057
+ if ([r, g, b].some((v) => Number.isNaN(v))) {
98058
+ return null;
98059
+ }
98060
+ return { r, g, b, a: Number.isNaN(a) ? 1 : a };
98061
+ }
98062
+ function lerpColor2(from, to, t) {
98063
+ const clamped = Math.max(0, Math.min(1, t));
98064
+ const r = Math.round(from.r + (to.r - from.r) * clamped);
98065
+ const g = Math.round(from.g + (to.g - from.g) * clamped);
98066
+ const b = Math.round(from.b + (to.b - from.b) * clamped);
98067
+ const a = Number((from.a + (to.a - from.a) * clamped).toFixed(3));
98068
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
98069
+ }
98070
+ var OUTLINE_SAMPLE_COUNT = 64;
98071
+ var ELLIPSE_SAMPLE_COUNT = 48;
98072
+ function resolveLength(token2, axis) {
98073
+ const trimmed = token2.trim();
98074
+ if (trimmed.endsWith("%")) {
98075
+ const pct = Number.parseFloat(trimmed.slice(0, -1));
98076
+ return Number.isFinite(pct) ? pct / 100 * axis : 0;
98077
+ }
98078
+ const px3 = Number.parseFloat(trimmed.replace(/px$/u, ""));
98079
+ return Number.isFinite(px3) ? px3 : 0;
98080
+ }
98081
+ function polygonClipToPoints(value, width, height) {
98082
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98083
+ const points3 = [];
98084
+ for (const pairStr of inner.split(",")) {
98085
+ const parts = pairStr.trim().split(/\s+/u);
98086
+ if (parts.length < 2) {
98087
+ continue;
98088
+ }
98089
+ points3.push({
98090
+ x: resolveLength(parts[0], width),
98091
+ y: resolveLength(parts[1], height)
98092
+ });
98093
+ }
98094
+ return points3;
98095
+ }
98096
+ function insetClipToPoints(value, width, height) {
98097
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98098
+ const tokens = inner.split(/round/u)[0].trim().split(/\s+/u);
98099
+ const top = resolveLength(tokens[0] ?? "0", height);
98100
+ const right = resolveLength(tokens[1] ?? tokens[0] ?? "0", width);
98101
+ const bottom = resolveLength(tokens[2] ?? tokens[0] ?? "0", height);
98102
+ const left = resolveLength(tokens[3] ?? tokens[1] ?? tokens[0] ?? "0", width);
98103
+ return [
98104
+ { x: left, y: top },
98105
+ { x: width - right, y: top },
98106
+ { x: width - right, y: height - bottom },
98107
+ { x: left, y: height - bottom }
98108
+ ];
98109
+ }
98110
+ function ellipseClipToPoints(value, width, height) {
98111
+ const isCircle = value.startsWith("circle");
98112
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98113
+ const [radii, position2] = inner.split(/\s+at\s+/u);
98114
+ const radiusTokens = radii.trim().split(/\s+/u).filter(Boolean);
98115
+ let rx = width / 2;
98116
+ let ry = height / 2;
98117
+ if (isCircle) {
98118
+ const r = resolveLength(radiusTokens[0] ?? "50%", Math.min(width, height));
98119
+ rx = r;
98120
+ ry = r;
98121
+ } else {
98122
+ rx = resolveLength(radiusTokens[0] ?? "50%", width);
98123
+ ry = resolveLength(radiusTokens[1] ?? radiusTokens[0] ?? "50%", height);
98124
+ }
98125
+ let cx = width / 2;
98126
+ let cy = height / 2;
98127
+ if (position2) {
98128
+ const posTokens = position2.trim().split(/\s+/u);
98129
+ cx = resolveLength(posTokens[0] ?? "50%", width);
98130
+ cy = resolveLength(posTokens[1] ?? posTokens[0] ?? "50%", height);
98131
+ }
98132
+ const points3 = [];
98133
+ for (let i = 0; i < ELLIPSE_SAMPLE_COUNT; i++) {
98134
+ const a = i / ELLIPSE_SAMPLE_COUNT * Math.PI * 2;
98135
+ points3.push({ x: cx + Math.cos(a) * rx, y: cy + Math.sin(a) * ry });
98136
+ }
98137
+ return points3;
98138
+ }
98139
+ function clipPathToPolygon(value, width, height) {
98140
+ const v = value.trim();
98141
+ if (v.startsWith("polygon")) {
98142
+ return polygonClipToPoints(v, width, height);
98143
+ }
98144
+ if (v.startsWith("inset")) {
98145
+ return insetClipToPoints(v, width, height);
98146
+ }
98147
+ if (v.startsWith("ellipse") || v.startsWith("circle")) {
98148
+ return ellipseClipToPoints(v, width, height);
98149
+ }
98150
+ if (v.startsWith("path")) {
98151
+ const start = v.indexOf("'") >= 0 ? v.indexOf("'") : v.indexOf('"');
98152
+ const end = v.lastIndexOf("'") >= 0 ? v.lastIndexOf("'") : v.lastIndexOf('"');
98153
+ if (start >= 0 && end > start) {
98154
+ const d = v.slice(start + 1, end);
98155
+ const polys = svgPathToPolygons(d);
98156
+ if (polys.length === 0) {
98157
+ return [];
98158
+ }
98159
+ return polys.reduce((a, b) => b.length > a.length ? b : a);
98160
+ }
98161
+ }
98162
+ return [];
98163
+ }
98164
+ function resolveElementOutline(element) {
98165
+ const width = Math.max(element.width, 1);
98166
+ const height = Math.max(element.height, 1);
98167
+ const shapeType = element.shapeType;
98168
+ const adjustments = element.shapeAdjustments;
98169
+ const clip = getResolvedShapeClipPathFor(shapeType, width, height, adjustments);
98170
+ if (clip) {
98171
+ const poly = clipPathToPolygon(clip, width, height);
98172
+ if (poly.length >= 3) {
98173
+ return poly;
98174
+ }
98175
+ }
98176
+ return [
98177
+ { x: 0, y: 0 },
98178
+ { x: width, y: 0 },
98179
+ { x: width, y: height },
98180
+ { x: 0, y: height }
98181
+ ];
98182
+ }
98183
+ function dist(a, b) {
98184
+ return Math.hypot(a.x - b.x, a.y - b.y);
98185
+ }
98186
+ function resamplePolygon(poly, count) {
98187
+ if (poly.length < 2) {
98188
+ return Array.from({ length: count }, () => ({ x: poly[0]?.x ?? 0, y: poly[0]?.y ?? 0 }));
98189
+ }
98190
+ const ring = [...poly, poly[0]];
98191
+ const segLen = [];
98192
+ let total = 0;
98193
+ for (let i = 0; i < ring.length - 1; i++) {
98194
+ const d = dist(ring[i], ring[i + 1]);
98195
+ segLen.push(d);
98196
+ total += d;
98197
+ }
98198
+ if (total === 0) {
98199
+ return Array.from({ length: count }, () => ({ x: poly[0].x, y: poly[0].y }));
98200
+ }
98201
+ const result = [];
98202
+ const step = total / count;
98203
+ let seg = 0;
98204
+ let segStart = 0;
98205
+ for (let i = 0; i < count; i++) {
98206
+ const target = i * step;
98207
+ while (seg < segLen.length - 1 && segStart + segLen[seg] < target) {
98208
+ segStart += segLen[seg];
98209
+ seg++;
98210
+ }
98211
+ const within = segLen[seg] > 0 ? (target - segStart) / segLen[seg] : 0;
98212
+ const a = ring[seg];
98213
+ const b = ring[seg + 1];
98214
+ result.push({ x: a.x + (b.x - a.x) * within, y: a.y + (b.y - a.y) * within });
98215
+ }
98216
+ return result;
98217
+ }
98218
+ function signedArea2(poly) {
98219
+ let area = 0;
98220
+ for (let i = 0; i < poly.length; i++) {
98221
+ const a = poly[i];
98222
+ const b = poly[(i + 1) % poly.length];
98223
+ area += a.x * b.y - b.x * a.y;
98224
+ }
98225
+ return area / 2;
98226
+ }
98227
+ function rotateRing(poly, offset) {
98228
+ const n = poly.length;
98229
+ const o = (offset % n + n) % n;
98230
+ return poly.slice(o).concat(poly.slice(0, o));
98231
+ }
98232
+ function bestRotation(from, to) {
98233
+ let bestOffset = 0;
98234
+ let bestCost = Infinity;
98235
+ for (let offset = 0; offset < to.length; offset++) {
98236
+ let cost = 0;
98237
+ for (let i = 0; i < from.length; i++) {
98238
+ const t = to[(i + offset) % to.length];
98239
+ const dx = from[i].x - t.x;
98240
+ const dy = from[i].y - t.y;
98241
+ cost += dx * dx + dy * dy;
98242
+ if (cost >= bestCost) {
98243
+ break;
98244
+ }
98245
+ }
98246
+ if (cost < bestCost) {
98247
+ bestCost = cost;
98248
+ bestOffset = offset;
98249
+ }
98250
+ }
98251
+ return bestOffset;
98252
+ }
98253
+ function normalizeOutlinePair(fromPoly, toPoly, count = OUTLINE_SAMPLE_COUNT) {
98254
+ const from = resamplePolygon(fromPoly, count);
98255
+ let to = resamplePolygon(toPoly, count);
98256
+ if (Math.sign(signedArea2(from)) !== Math.sign(signedArea2(to))) {
98257
+ to = [...to].reverse();
98258
+ }
98259
+ const offset = bestRotation(from, to);
98260
+ to = rotateRing(to, offset);
98261
+ return [from, to];
98262
+ }
98263
+ function interpolateOutline(from, to, t) {
98264
+ const clamped = Math.max(0, Math.min(1, t));
98265
+ const len = Math.min(from.length, to.length);
98266
+ if (len === 0) {
98267
+ return "";
98268
+ }
98269
+ const parts = [];
98270
+ for (let i = 0; i < len; i++) {
98271
+ const x = from[i].x + (to[i].x - from[i].x) * clamped;
98272
+ const y = from[i].y + (to[i].y - from[i].y) * clamped;
98273
+ parts.push(`${i === 0 ? "M" : "L"}${Number(x.toFixed(2))} ${Number(y.toFixed(2))}`);
98274
+ }
98275
+ parts.push("Z");
98276
+ return parts.join(" ");
98277
+ }
98278
+ var MORPH_EASING = "cubic-bezier(0.4, 0, 0.2, 1)";
98279
+ var PROXIMITY_THRESHOLD = 300;
98280
+ var GEOMETRY_MORPH_STEPS = 8;
98281
+ function shouldGeometryMorph(pair) {
98282
+ const fromType = pair.fromElement.shapeType;
98283
+ const toType = pair.toElement.shapeType;
98284
+ if (!fromType || !toType) {
98285
+ return false;
98286
+ }
98287
+ if (fromType.toLowerCase() !== toType.toLowerCase()) {
98288
+ return true;
98289
+ }
98290
+ const fromAdj = JSON.stringify(
98291
+ pair.fromElement.shapeAdjustments ?? {}
98292
+ );
98293
+ const toAdj = JSON.stringify(
98294
+ pair.toElement.shapeAdjustments ?? {}
98295
+ );
98296
+ return fromAdj !== toAdj;
98297
+ }
98298
+ function buildClipKeyframeBody(from, to, steps) {
98299
+ const [fromRing, toRing] = normalizeOutlinePair(
98300
+ resolveElementOutline(from),
98301
+ resolveElementOutline(to)
98302
+ );
98303
+ if (fromRing.length === 0 || toRing.length === 0) {
98304
+ return null;
98305
+ }
98306
+ const lines = [];
98307
+ for (let s = 0; s <= steps; s++) {
98308
+ const t = s / steps;
98309
+ const d = interpolateOutline(fromRing, toRing, t);
98310
+ if (!d) {
98311
+ return null;
98312
+ }
98313
+ const pct = Number((s / steps * 100).toFixed(2));
98314
+ lines.push(` ${pct}% {
98315
+ clip-path: path('${d}');
98316
+ }`);
98317
+ }
98318
+ return lines.join("\n");
98319
+ }
98320
+ function generateGeometryMorphAnimation(pair, durationMs, pairIndex, steps = GEOMETRY_MORPH_STEPS) {
98321
+ if (!shouldGeometryMorph(pair)) {
98322
+ return null;
98323
+ }
98324
+ const body = buildClipKeyframeBody(pair.fromElement, pair.toElement, steps);
98325
+ if (!body) {
98326
+ return null;
98327
+ }
98328
+ const safeName = `pptx-morph-geo-${pairIndex}-${pair.toElement.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98329
+ const keyframes = `
98330
+ @keyframes ${safeName} {
98331
+ ${body}
98332
+ }`;
98333
+ return {
98334
+ elementId: pair.toElement.id,
98335
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98336
+ keyframes
98337
+ };
98338
+ }
98339
+ function getElementMorphName(element) {
98340
+ if (element.name) {
98341
+ const name = element.name.trim();
98342
+ if (name.startsWith("!!")) {
98343
+ return name;
98344
+ }
98345
+ }
98346
+ if (hasTextProperties(element) && element.text) {
98347
+ const text2 = element.text.trim();
98348
+ if (text2.startsWith("!!")) {
98349
+ return text2;
98350
+ }
98351
+ }
98352
+ return void 0;
98353
+ }
98354
+ function matchMorphElementsFull(fromSlide, toSlide) {
98355
+ const pairs2 = [];
98356
+ const usedFrom = /* @__PURE__ */ new Set();
98357
+ const usedTo = /* @__PURE__ */ new Set();
98358
+ for (const fromEl of fromSlide.elements) {
98359
+ const fromName = getElementMorphName(fromEl);
98360
+ if (!fromName) {
98361
+ continue;
98362
+ }
98363
+ for (const toEl of toSlide.elements) {
98364
+ if (usedTo.has(toEl.id)) {
98365
+ continue;
98366
+ }
98367
+ const toName = getElementMorphName(toEl);
98368
+ if (toName === fromName) {
98369
+ pairs2.push({ fromElement: fromEl, toElement: toEl });
98370
+ usedFrom.add(fromEl.id);
98371
+ usedTo.add(toEl.id);
98372
+ break;
98373
+ }
98374
+ }
98375
+ }
98376
+ for (const fromEl of fromSlide.elements) {
98377
+ if (usedFrom.has(fromEl.id)) {
98378
+ continue;
98379
+ }
98380
+ for (const toEl of toSlide.elements) {
98381
+ if (usedTo.has(toEl.id)) {
98382
+ continue;
98383
+ }
98384
+ if (fromEl.id === toEl.id) {
98385
+ pairs2.push({ fromElement: fromEl, toElement: toEl });
98386
+ usedFrom.add(fromEl.id);
98387
+ usedTo.add(toEl.id);
98388
+ break;
98389
+ }
98390
+ }
98391
+ }
98392
+ for (const fromEl of fromSlide.elements) {
98393
+ if (usedFrom.has(fromEl.id)) {
98394
+ continue;
98395
+ }
98396
+ let bestMatch = null;
98397
+ let bestDist = Infinity;
98398
+ for (const toEl of toSlide.elements) {
98399
+ if (usedTo.has(toEl.id)) {
98400
+ continue;
98401
+ }
98402
+ if (fromEl.type !== toEl.type) {
98403
+ continue;
98404
+ }
98405
+ const dx = fromEl.x - toEl.x;
98406
+ const dy = fromEl.y - toEl.y;
98407
+ const dist2 = Math.sqrt(dx * dx + dy * dy);
98408
+ if (dist2 < bestDist && dist2 < PROXIMITY_THRESHOLD) {
98409
+ bestDist = dist2;
98410
+ bestMatch = toEl;
98411
+ }
98412
+ }
98413
+ if (bestMatch) {
98414
+ pairs2.push({ fromElement: fromEl, toElement: bestMatch });
98415
+ usedFrom.add(fromEl.id);
98416
+ usedTo.add(bestMatch.id);
98417
+ }
98418
+ }
98419
+ const unmatchedFrom = fromSlide.elements.filter((el) => !usedFrom.has(el.id));
98420
+ const unmatchedTo = toSlide.elements.filter((el) => !usedTo.has(el.id));
98421
+ return { pairs: pairs2, unmatchedFrom, unmatchedTo };
98422
+ }
98423
+ function tokenizeText(element, mode) {
98424
+ if (!hasTextProperties(element) || !element.text) {
98425
+ return [];
98426
+ }
98427
+ const text2 = element.text;
98428
+ const style = element.textStyle;
98429
+ const fontSize = style?.fontSize ?? 14;
98430
+ const fontWeight = style?.bold ? "bold" : "normal";
98431
+ const color2 = style?.color ?? "#000000";
98432
+ const tokens = [];
98433
+ if (mode === "character") {
98434
+ const chars = Array.from(text2);
98435
+ const totalChars = chars.length;
98436
+ if (totalChars === 0) {
98437
+ return [];
98438
+ }
98439
+ for (let i = 0; i < chars.length; i++) {
98440
+ if (chars[i] === "\n") {
98441
+ continue;
98442
+ }
98443
+ tokens.push({
98444
+ text: chars[i],
98445
+ x: totalChars > 1 ? i / (totalChars - 1) : 0.5,
98446
+ y: 0.5,
98447
+ fontSize,
98448
+ fontWeight,
98449
+ color: color2
98450
+ });
98451
+ }
98452
+ } else {
98453
+ const words = text2.split(/\s+/u);
98454
+ const nonEmptyWords = words.filter((w) => w.trim().length > 0);
98455
+ const totalWords = nonEmptyWords.length;
98456
+ if (totalWords === 0) {
98457
+ return [];
98458
+ }
98459
+ let wordIndex = 0;
98460
+ for (const word of words) {
98461
+ if (word.trim().length === 0) {
98462
+ continue;
98463
+ }
98464
+ tokens.push({
98465
+ text: word,
98466
+ x: totalWords > 1 ? wordIndex / (totalWords - 1) : 0.5,
98467
+ y: 0.5,
98468
+ fontSize,
98469
+ fontWeight,
98470
+ color: color2
98471
+ });
98472
+ wordIndex++;
98473
+ }
98474
+ }
98475
+ return tokens;
98476
+ }
98477
+ function diffTokens(fromTokens, toTokens) {
98478
+ const n = fromTokens.length;
98479
+ const m = toTokens.length;
98480
+ const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
98481
+ for (let i2 = n - 1; i2 >= 0; i2--) {
98482
+ for (let j2 = m - 1; j2 >= 0; j2--) {
98483
+ lcs[i2][j2] = fromTokens[i2].text === toTokens[j2].text ? lcs[i2 + 1][j2 + 1] + 1 : Math.max(lcs[i2 + 1][j2], lcs[i2][j2 + 1]);
98484
+ }
98485
+ }
98486
+ const ops = [];
98487
+ let i = 0;
98488
+ let j = 0;
98489
+ while (i < n && j < m) {
98490
+ if (fromTokens[i].text === toTokens[j].text) {
98491
+ ops.push({
98492
+ change: "shared",
98493
+ from: fromTokens[i],
98494
+ to: toTokens[j],
98495
+ fromIndex: i,
98496
+ toIndex: j
98497
+ });
98498
+ i++;
98499
+ j++;
98500
+ } else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
98501
+ ops.push({ change: "removed", from: fromTokens[i], to: null, fromIndex: i, toIndex: -1 });
98502
+ i++;
98503
+ } else {
98504
+ ops.push({ change: "added", from: null, to: toTokens[j], fromIndex: -1, toIndex: j });
98505
+ j++;
98506
+ }
98507
+ }
98508
+ while (i < n) {
98509
+ ops.push({ change: "removed", from: fromTokens[i], to: null, fromIndex: i, toIndex: -1 });
98510
+ i++;
98511
+ }
98512
+ while (j < m) {
98513
+ ops.push({ change: "added", from: null, to: toTokens[j], fromIndex: -1, toIndex: j });
98514
+ j++;
98515
+ }
98516
+ return ops;
98517
+ }
98518
+ function tokenColor(token2) {
98519
+ const parsed = parseHexColor(token2.color);
98520
+ return parsed ? lerpColor2(parsed, parsed, 0) : token2.color;
98521
+ }
98522
+ function sharedKeyframes(name, op) {
98523
+ const from = op.from;
98524
+ const to = op.to;
98525
+ return `
98526
+ @keyframes ${name} {
98527
+ from {
98528
+ left: ${Number((from.x * 100).toFixed(2))}%;
98529
+ top: ${Number((from.y * 100).toFixed(2))}%;
98530
+ font-size: ${from.fontSize}pt;
98531
+ font-weight: ${from.fontWeight};
98532
+ color: ${tokenColor(from)};
98533
+ opacity: 1;
98534
+ }
98535
+ to {
98536
+ left: ${Number((to.x * 100).toFixed(2))}%;
98537
+ top: ${Number((to.y * 100).toFixed(2))}%;
98538
+ font-size: ${to.fontSize}pt;
98539
+ font-weight: ${to.fontWeight};
98540
+ color: ${tokenColor(to)};
98541
+ opacity: 1;
98542
+ }
98543
+ }`;
98544
+ }
98545
+ function fadeKeyframes(name, fadeIn) {
98546
+ const a = fadeIn ? 0 : 1;
98547
+ const b = fadeIn ? 1 : 0;
98548
+ return `
98549
+ @keyframes ${name} {
98550
+ from { opacity: ${a}; }
98551
+ to { opacity: ${b}; }
98552
+ }`;
98553
+ }
98554
+ function buildTokenMorphAnimations(ops, fromId, toId, durationMs, pairIndex) {
98555
+ const animations = [];
98556
+ for (let k = 0; k < ops.length; k++) {
98557
+ const op = ops[k];
98558
+ const name = `pptx-morph-tok-${pairIndex}-${k}`;
98559
+ const anim = `${name} ${durationMs}ms ${MORPH_EASING} forwards`;
98560
+ if (op.change === "shared") {
98561
+ animations.push({
98562
+ elementId: `${toId}__token_${op.toIndex}`,
98563
+ animation: anim,
98564
+ keyframes: sharedKeyframes(name, op)
98565
+ });
98566
+ } else if (op.change === "added") {
98567
+ animations.push({
98568
+ elementId: `${toId}__token_${op.toIndex}`,
98569
+ animation: anim,
98570
+ keyframes: fadeKeyframes(name, true)
98571
+ });
98572
+ } else {
98573
+ animations.push({
98574
+ elementId: `${fromId}__token_${op.fromIndex}`,
98575
+ animation: anim,
98576
+ keyframes: fadeKeyframes(name, false)
98577
+ });
98578
+ }
98579
+ }
98580
+ return animations;
98581
+ }
98582
+ function buildColorInterpolationProps(fromElement, toElement) {
98583
+ const fromFill = hasShapeProperties(fromElement) ? fromElement.shapeStyle?.fillColor : void 0;
98584
+ const toFill = hasShapeProperties(toElement) ? toElement.shapeStyle?.fillColor : void 0;
98585
+ if (!fromFill && !toFill) {
98586
+ return null;
98587
+ }
98588
+ if (fromFill === toFill) {
98589
+ return null;
98590
+ }
98591
+ const fromColor = parseHexColor(fromFill);
98592
+ const toColor = parseHexColor(toFill);
98593
+ if (!fromColor && !toColor) {
98594
+ return null;
98595
+ }
98596
+ const from = fromColor ?? { r: 255, g: 255, b: 255, a: 0 };
98597
+ const to = toColor ?? { r: 255, g: 255, b: 255, a: 0 };
98598
+ return {
98599
+ fromBg: lerpColor2(from, from, 0),
98600
+ toBg: lerpColor2(to, to, 0)
98601
+ };
98602
+ }
98603
+ function buildStrokeInterpolationProps(fromElement, toElement) {
98604
+ const fromStyle = hasShapeProperties(fromElement) ? fromElement.shapeStyle : void 0;
98605
+ const toStyle = hasShapeProperties(toElement) ? toElement.shapeStyle : void 0;
98606
+ const fromColor = fromStyle?.strokeColor;
98607
+ const toColor = toStyle?.strokeColor;
98608
+ const fromWidth = fromStyle?.strokeWidth ?? 0;
98609
+ const toWidth = toStyle?.strokeWidth ?? 0;
98610
+ if (!fromColor && !toColor && fromWidth === 0 && toWidth === 0) {
98611
+ return null;
98612
+ }
98613
+ if (fromColor === toColor && fromWidth === toWidth) {
98614
+ return null;
98615
+ }
98616
+ const fc = parseHexColor(fromColor) ?? { r: 0, g: 0, b: 0, a: 1 };
98617
+ const tc = parseHexColor(toColor) ?? { r: 0, g: 0, b: 0, a: 1 };
98618
+ return {
98619
+ fromStroke: lerpColor2(fc, fc, 0),
98620
+ toStroke: lerpColor2(tc, tc, 0),
98621
+ fromWidth,
98622
+ toWidth
98623
+ };
98624
+ }
98625
+ function generateMorphAnimations(pairs2, durationMs, _mode = "object") {
98626
+ const animations = [];
98627
+ for (let index = 0; index < pairs2.length; index++) {
98628
+ const { fromElement, toElement } = pairs2[index];
98629
+ const safeName = `pptx-morph-${index}-${toElement.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98630
+ const dx = fromElement.x - toElement.x;
98631
+ const dy = fromElement.y - toElement.y;
98632
+ const sx = Math.max(fromElement.width, 1) / Math.max(toElement.width, 1);
98633
+ const sy = Math.max(fromElement.height, 1) / Math.max(toElement.height, 1);
98634
+ const dr = (fromElement.rotation ?? 0) - (toElement.rotation ?? 0);
98635
+ const fromOpacity = fromElement.opacity ?? 1;
98636
+ const toOpacity = toElement.opacity ?? 1;
98637
+ const fromProps = [
98638
+ ` transform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${dr}deg);`,
98639
+ ` opacity: ${fromOpacity};`
98640
+ ];
98641
+ const toProps = [
98642
+ " transform: translate(0, 0) scale(1, 1) rotate(0deg);",
98643
+ ` opacity: ${toOpacity};`
98644
+ ];
98645
+ const colorInterp = buildColorInterpolationProps(fromElement, toElement);
98646
+ if (colorInterp) {
98647
+ fromProps.push(` background-color: ${colorInterp.fromBg};`);
98648
+ toProps.push(` background-color: ${colorInterp.toBg};`);
98649
+ }
98650
+ const strokeInterp = buildStrokeInterpolationProps(fromElement, toElement);
98651
+ if (strokeInterp) {
98652
+ fromProps.push(` outline: ${strokeInterp.fromWidth}px solid ${strokeInterp.fromStroke};`);
98653
+ toProps.push(` outline: ${strokeInterp.toWidth}px solid ${strokeInterp.toStroke};`);
98654
+ }
98655
+ const keyframes = `
98656
+ @keyframes ${safeName} {
98657
+ from {
98658
+ ${fromProps.join("\n")}
98659
+ }
98660
+ to {
98661
+ ${toProps.join("\n")}
98662
+ }
98663
+ }`;
98664
+ animations.push({
98665
+ elementId: toElement.id,
98666
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98667
+ keyframes
98668
+ });
98669
+ }
98670
+ return animations;
98671
+ }
98672
+ function generateUnmatchedFadeOutAnimations(elements, durationMs, startIndex) {
98673
+ return elements.map((el, i) => {
98674
+ const safeName = `pptx-morph-fadeout-${startIndex + i}-${el.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98675
+ const keyframes = `
98676
+ @keyframes ${safeName} {
98677
+ from {
98678
+ opacity: ${el.opacity ?? 1};
98679
+ transform: scale(1);
98680
+ }
98681
+ to {
98682
+ opacity: 0;
98683
+ transform: scale(0.95);
98684
+ }
98685
+ }`;
98686
+ return {
98687
+ elementId: el.id,
98688
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98689
+ keyframes
98690
+ };
98691
+ });
98692
+ }
98693
+ function generateUnmatchedFadeInAnimations(elements, durationMs, startIndex) {
98694
+ return elements.map((el, i) => {
98695
+ const safeName = `pptx-morph-fadein-${startIndex + i}-${el.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98696
+ const keyframes = `
98697
+ @keyframes ${safeName} {
98698
+ from {
98699
+ opacity: 0;
98700
+ transform: scale(0.95);
98701
+ }
98702
+ to {
98703
+ opacity: ${el.opacity ?? 1};
98704
+ transform: scale(1);
98705
+ }
98706
+ }`;
98707
+ return {
98708
+ elementId: el.id,
98709
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98710
+ keyframes
98711
+ };
98712
+ });
98713
+ }
98714
+ function generateTextMorphAnimations(pair, durationMs, mode, pairIndex) {
98715
+ const fromTokens = tokenizeText(pair.fromElement, mode);
98716
+ const toTokens = tokenizeText(pair.toElement, mode);
98717
+ if (fromTokens.length === 0 && toTokens.length === 0) {
98718
+ return [];
98719
+ }
98720
+ const ops = diffTokens(fromTokens, toTokens);
98721
+ return buildTokenMorphAnimations(
98722
+ ops,
98723
+ pair.fromElement.id,
98724
+ pair.toElement.id,
98725
+ durationMs,
98726
+ pairIndex
98727
+ );
98728
+ }
98729
+ function generateFullMorphTransition(fromSlide, toSlide, durationMs, mode = "object") {
98730
+ const matchResult = matchMorphElementsFull(fromSlide, toSlide);
98731
+ const allAnimations = [];
98732
+ const pairAnims = generateMorphAnimations(matchResult.pairs, durationMs, mode);
98733
+ allAnimations.push(...pairAnims);
98734
+ for (let i = 0; i < matchResult.pairs.length; i++) {
98735
+ const geo = generateGeometryMorphAnimation(matchResult.pairs[i], durationMs, i);
98736
+ if (geo) {
98737
+ allAnimations.push(geo);
98738
+ }
98739
+ }
98740
+ if (mode === "word" || mode === "character") {
98741
+ for (let i = 0; i < matchResult.pairs.length; i++) {
98742
+ const pair = matchResult.pairs[i];
98743
+ if (hasTextProperties(pair.fromElement) && hasTextProperties(pair.toElement)) {
98744
+ const textAnims = generateTextMorphAnimations(pair, durationMs, mode, i);
98745
+ allAnimations.push(...textAnims);
98746
+ }
98747
+ }
98748
+ }
98749
+ const fadeOuts = generateUnmatchedFadeOutAnimations(
98750
+ matchResult.unmatchedFrom,
98751
+ durationMs,
98752
+ pairAnims.length
98753
+ );
98754
+ allAnimations.push(...fadeOuts);
98755
+ const fadeIns = generateUnmatchedFadeInAnimations(
98756
+ matchResult.unmatchedTo,
98757
+ durationMs,
98758
+ pairAnims.length + fadeOuts.length
98759
+ );
98760
+ allAnimations.push(...fadeIns);
98761
+ return allAnimations;
98762
+ }
98763
+ function morphOptionToMode(option) {
98764
+ if (option === "byWord") {
98765
+ return "word";
98766
+ }
98767
+ if (option === "byChar") {
98768
+ return "character";
98769
+ }
98770
+ return "object";
98771
+ }
98772
+ function buildMorphTransitionPlan(fromSlide, toSlide, durationMs, mode = "object") {
98773
+ if (!fromSlide || !toSlide) {
98774
+ return void 0;
98775
+ }
98776
+ const match = matchMorphElementsFull(fromSlide, toSlide);
98777
+ if (match.pairs.length === 0 && match.unmatchedFrom.length === 0 && match.unmatchedTo.length === 0) {
98778
+ return void 0;
98779
+ }
98780
+ const animations = generateFullMorphTransition(fromSlide, toSlide, durationMs, mode);
98781
+ const outgoingIds = new Set(match.unmatchedFrom.map((element) => element.id));
98782
+ const incomingAnimations = /* @__PURE__ */ new Map();
98783
+ const outgoingAnimations = /* @__PURE__ */ new Map();
98784
+ const keyframes = [];
98785
+ for (const animation of animations) {
98786
+ keyframes.push(animation.keyframes);
98787
+ if (outgoingIds.has(animation.elementId)) {
98788
+ outgoingAnimations.set(animation.elementId, animation.animation);
98789
+ } else {
98790
+ incomingAnimations.set(animation.elementId, animation.animation);
98791
+ }
98792
+ }
98793
+ return {
98794
+ keyframesCss: keyframes.join("\n"),
98795
+ incomingAnimations,
98796
+ outgoingAnimations,
98797
+ outgoingElements: match.unmatchedFrom,
98798
+ durationMs
98799
+ };
98800
+ }
97951
98801
  function hexToRgb6(hex10) {
97952
98802
  const clean = hex10.replace(/^#/u, "");
97953
98803
  return {
@@ -109835,6 +110685,7 @@ exports.buildHandoutsHtml = buildHandoutsHtml;
109835
110685
  exports.buildInitialGuides = buildInitialGuides;
109836
110686
  exports.buildInnerShadowCssFromShapeStyle = buildInnerShadowCssFromShapeStyle;
109837
110687
  exports.buildJoinCollaborationConfig = buildJoinCollaborationConfig;
110688
+ exports.buildMorphTransitionPlan = buildMorphTransitionPlan;
109838
110689
  exports.buildMultiLayerShadowCss = buildMultiLayerShadowCss;
109839
110690
  exports.buildNotesHtml = buildNotesHtml;
109840
110691
  exports.buildNotesPdfBytes = buildNotesPdfBytes;
@@ -110071,6 +110922,7 @@ exports.mergePresentationSnapshot = mergePresentationSnapshot;
110071
110922
  exports.mergeShapes = mergeShapes;
110072
110923
  exports.mobileElapsedSince = mobileElapsedSince;
110073
110924
  exports.mobileSlideCounter = mobileSlideCounter;
110925
+ exports.morphOptionToMode = morphOptionToMode;
110074
110926
  exports.mountModel3D = mountModel3D;
110075
110927
  exports.mountSurfaceChart3D = mountSurfaceChart3D;
110076
110928
  exports.movePresenterPointer = movePresenterPointer;
@@ -110139,6 +110991,7 @@ exports.resolveLineHeight = resolveLineHeight;
110139
110991
  exports.resolveOleType = resolveOleType;
110140
110992
  exports.resolveParagraphAlign = resolveParagraphAlign;
110141
110993
  exports.resolveParagraphRtl = resolveParagraphRtl;
110994
+ exports.resolveParagraphStrutFontSize = resolveParagraphStrutFontSize;
110142
110995
  exports.resolvePictureBullet = resolvePictureBullet;
110143
110996
  exports.resolveProfileInitial = resolveProfileInitial;
110144
110997
  exports.resolveRegionCode = resolveRegionCode;