pptx-react-viewer 2.5.3 → 2.6.1

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 +9 -0
  2. package/dist/{AiChatPanel-DPMHPOWF.js → AiChatPanel-LBK6YRKH.js} +22 -22
  3. package/dist/AiChatPanel-LBK6YRKH.js.br +0 -0
  4. package/dist/AiChatPanel-LBK6YRKH.js.gz +0 -0
  5. package/dist/{AiChatPanel-OFOOWR4U.mjs → AiChatPanel-RVZOGGFK.mjs} +3 -3
  6. package/dist/AiChatPanel-RVZOGGFK.mjs.br +0 -0
  7. package/dist/AiChatPanel-RVZOGGFK.mjs.gz +0 -0
  8. package/dist/{Model3DScene-PD2MDBIE.js → Model3DScene-L46RNRU5.js} +2 -2
  9. package/dist/Model3DScene-L46RNRU5.js.br +0 -0
  10. package/dist/Model3DScene-L46RNRU5.js.gz +0 -0
  11. package/dist/{Model3DScene-P4OKVQBF.mjs → Model3DScene-WBUZ74G3.mjs} +1 -1
  12. package/dist/Model3DScene-WBUZ74G3.mjs.br +0 -0
  13. package/dist/Model3DScene-WBUZ74G3.mjs.gz +0 -0
  14. package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs → SurfaceChart3DScene-CB32AJS4.mjs} +1 -1
  15. package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs.br → SurfaceChart3DScene-CB32AJS4.mjs.br} +0 -0
  16. package/dist/SurfaceChart3DScene-CB32AJS4.mjs.gz +0 -0
  17. package/dist/{SurfaceChart3DScene-FECS3THE.js → SurfaceChart3DScene-RWMGMREC.js} +2 -2
  18. package/dist/SurfaceChart3DScene-RWMGMREC.js.br +0 -0
  19. package/dist/SurfaceChart3DScene-RWMGMREC.js.gz +0 -0
  20. package/dist/{chunk-UUS7QT22.js → chunk-2VE3LVKZ.js} +346 -315
  21. package/dist/chunk-2VE3LVKZ.js.br +0 -0
  22. package/dist/chunk-2VE3LVKZ.js.gz +0 -0
  23. package/dist/{chunk-FFLUALX5.js → chunk-4O7PPQ2V.js} +260 -240
  24. package/dist/chunk-4O7PPQ2V.js.br +0 -0
  25. package/dist/chunk-4O7PPQ2V.js.gz +0 -0
  26. package/dist/{chunk-ZZA62IND.mjs → chunk-54FSVX3O.mjs} +35 -4
  27. package/dist/chunk-54FSVX3O.mjs.br +0 -0
  28. package/dist/chunk-54FSVX3O.mjs.gz +0 -0
  29. package/dist/{chunk-H2FZ2NJ7.js → chunk-AX4Q5JWN.js} +3 -3
  30. package/dist/chunk-AX4Q5JWN.js.br +0 -0
  31. package/dist/chunk-AX4Q5JWN.js.gz +0 -0
  32. package/dist/{chunk-F3JUUSC4.mjs → chunk-BL3WW2BS.mjs} +95 -15
  33. package/dist/chunk-BL3WW2BS.mjs.br +0 -0
  34. package/dist/chunk-BL3WW2BS.mjs.gz +0 -0
  35. package/dist/{chunk-6KOM27PS.mjs → chunk-EI456HZK.mjs} +964 -64
  36. package/dist/chunk-EI456HZK.mjs.br +0 -0
  37. package/dist/chunk-EI456HZK.mjs.gz +0 -0
  38. package/dist/{chunk-SAXG53MO.mjs → chunk-GC6HQMVG.mjs} +1 -1
  39. package/dist/chunk-GC6HQMVG.mjs.br +0 -0
  40. package/dist/chunk-GC6HQMVG.mjs.gz +0 -0
  41. package/dist/{chunk-USHZUHHG.js → chunk-IEFH47TF.js} +929 -849
  42. package/dist/chunk-IEFH47TF.js.br +0 -0
  43. package/dist/chunk-IEFH47TF.js.gz +0 -0
  44. package/dist/{chunk-23Q3I2LM.js → chunk-T7AMP24E.js} +966 -63
  45. package/dist/chunk-T7AMP24E.js.br +0 -0
  46. package/dist/chunk-T7AMP24E.js.gz +0 -0
  47. package/dist/{chunk-QDIF3ZXF.mjs → chunk-ZUNDIOGD.mjs} +28 -8
  48. package/dist/chunk-ZUNDIOGD.mjs.br +0 -0
  49. package/dist/chunk-ZUNDIOGD.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 +44 -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);
@@ -64299,18 +64366,6 @@ var PptxHandlerRuntime67 = class _PptxHandlerRuntime30 extends PptxHandlerRuntim
64299
64366
  if (hasShapeProperties(el) && el.shapeStyle?.strokeWidth) {
64300
64367
  el.shapeStyle.strokeWidth *= avgScale;
64301
64368
  }
64302
- if (hasTextProperties(el)) {
64303
- if (el.textStyle?.fontSize) {
64304
- el.textStyle.fontSize *= Math.abs(scaleY);
64305
- }
64306
- if (el.textSegments) {
64307
- el.textSegments.forEach((seg) => {
64308
- if (seg.style.fontSize) {
64309
- seg.style.fontSize *= Math.abs(scaleY);
64310
- }
64311
- });
64312
- }
64313
- }
64314
64369
  return el;
64315
64370
  };
64316
64371
  this.unwrapAlternateContent(group);
@@ -66360,12 +66415,12 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66360
66415
  if (Number.isFinite(blurRad) && blurRad > 0) {
66361
66416
  result.shadowBlur = blurRad / _PptxHandlerRuntime33.EMU_PER_PX;
66362
66417
  }
66363
- const dist = parseInt(String(outerShdw["@_dist"] || "0"));
66418
+ const dist2 = parseInt(String(outerShdw["@_dist"] || "0"));
66364
66419
  const dir = parseInt(String(outerShdw["@_dir"] || "0"));
66365
- if (Number.isFinite(dist) && dist > 0 && Number.isFinite(dir)) {
66420
+ if (Number.isFinite(dist2) && dist2 > 0 && Number.isFinite(dir)) {
66366
66421
  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;
66422
+ result.shadowOffsetX = Math.cos(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66423
+ result.shadowOffsetY = Math.sin(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66369
66424
  }
66370
66425
  }
66371
66426
  const innerShdw = effectLst["a:innerShdw"];
@@ -66376,12 +66431,12 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66376
66431
  if (Number.isFinite(blurRad) && blurRad > 0) {
66377
66432
  result.innerShadowBlur = blurRad / _PptxHandlerRuntime33.EMU_PER_PX;
66378
66433
  }
66379
- const dist = parseInt(String(innerShdw["@_dist"] || "0"));
66434
+ const dist2 = parseInt(String(innerShdw["@_dist"] || "0"));
66380
66435
  const dir = parseInt(String(innerShdw["@_dir"] || "0"));
66381
- if (Number.isFinite(dist) && dist > 0 && Number.isFinite(dir)) {
66436
+ if (Number.isFinite(dist2) && dist2 > 0 && Number.isFinite(dir)) {
66382
66437
  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;
66438
+ result.innerShadowOffsetX = Math.cos(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66439
+ result.innerShadowOffsetY = Math.sin(angleRad) * dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66385
66440
  }
66386
66441
  }
66387
66442
  const glow = effectLst["a:glow"];
@@ -66426,9 +66481,9 @@ var PptxHandlerRuntime77 = class _PptxHandlerRuntime33 extends PptxHandlerRuntim
66426
66481
  if (Number.isFinite(rot)) {
66427
66482
  result.reflectionRotation = rot / 6e4;
66428
66483
  }
66429
- const dist = parseInt(String(reflection["@_dist"] || "0"));
66430
- if (Number.isFinite(dist) && dist >= 0) {
66431
- result.reflectionDistance = dist / _PptxHandlerRuntime33.EMU_PER_PX;
66484
+ const dist2 = parseInt(String(reflection["@_dist"] || "0"));
66485
+ if (Number.isFinite(dist2) && dist2 >= 0) {
66486
+ result.reflectionDistance = dist2 / _PptxHandlerRuntime33.EMU_PER_PX;
66432
66487
  }
66433
66488
  }
66434
66489
  const scene3dNode = es["a:scene3d"];
@@ -97948,6 +98003,851 @@ function sanitizeMathMl(markup) {
97948
98003
  }
97949
98004
  return sanitized;
97950
98005
  }
98006
+ function resolveParagraphStrutFontSize(segments, bodyFontSize) {
98007
+ let largest;
98008
+ for (const segment of segments) {
98009
+ if (segment.bulletInfo) {
98010
+ continue;
98011
+ }
98012
+ const size = segment.style?.fontSize;
98013
+ if (typeof size !== "number" || !Number.isFinite(size) || size <= 0) {
98014
+ continue;
98015
+ }
98016
+ if (largest === void 0 || size > largest) {
98017
+ largest = size;
98018
+ }
98019
+ }
98020
+ if (largest === void 0) {
98021
+ return void 0;
98022
+ }
98023
+ if (typeof bodyFontSize === "number" && Math.abs(largest - bodyFontSize) < 0.01) {
98024
+ return void 0;
98025
+ }
98026
+ return largest;
98027
+ }
98028
+ function parseHexColor(hex10) {
98029
+ if (!hex10 || typeof hex10 !== "string") {
98030
+ return null;
98031
+ }
98032
+ let cleaned = hex10.replace(/^#/u, "");
98033
+ if (cleaned.length === 3) {
98034
+ cleaned = cleaned[0] + cleaned[0] + cleaned[1] + cleaned[1] + cleaned[2] + cleaned[2];
98035
+ } else if (cleaned.length === 4) {
98036
+ cleaned = cleaned[0] + cleaned[0] + cleaned[1] + cleaned[1] + cleaned[2] + cleaned[2] + cleaned[3] + cleaned[3];
98037
+ }
98038
+ if (cleaned.length !== 6 && cleaned.length !== 8) {
98039
+ return null;
98040
+ }
98041
+ const r = Number.parseInt(cleaned.slice(0, 2), 16);
98042
+ const g = Number.parseInt(cleaned.slice(2, 4), 16);
98043
+ const b = Number.parseInt(cleaned.slice(4, 6), 16);
98044
+ const a = cleaned.length === 8 ? Number.parseInt(cleaned.slice(6, 8), 16) / 255 : 1;
98045
+ if ([r, g, b].some((v) => Number.isNaN(v))) {
98046
+ return null;
98047
+ }
98048
+ return { r, g, b, a: Number.isNaN(a) ? 1 : a };
98049
+ }
98050
+ function lerpColor2(from, to, t) {
98051
+ const clamped = Math.max(0, Math.min(1, t));
98052
+ const r = Math.round(from.r + (to.r - from.r) * clamped);
98053
+ const g = Math.round(from.g + (to.g - from.g) * clamped);
98054
+ const b = Math.round(from.b + (to.b - from.b) * clamped);
98055
+ const a = Number((from.a + (to.a - from.a) * clamped).toFixed(3));
98056
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
98057
+ }
98058
+ var OUTLINE_SAMPLE_COUNT = 64;
98059
+ var ELLIPSE_SAMPLE_COUNT = 48;
98060
+ function resolveLength(token2, axis) {
98061
+ const trimmed = token2.trim();
98062
+ if (trimmed.endsWith("%")) {
98063
+ const pct = Number.parseFloat(trimmed.slice(0, -1));
98064
+ return Number.isFinite(pct) ? pct / 100 * axis : 0;
98065
+ }
98066
+ const px3 = Number.parseFloat(trimmed.replace(/px$/u, ""));
98067
+ return Number.isFinite(px3) ? px3 : 0;
98068
+ }
98069
+ function polygonClipToPoints(value, width, height) {
98070
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98071
+ const points3 = [];
98072
+ for (const pairStr of inner.split(",")) {
98073
+ const parts = pairStr.trim().split(/\s+/u);
98074
+ if (parts.length < 2) {
98075
+ continue;
98076
+ }
98077
+ points3.push({
98078
+ x: resolveLength(parts[0], width),
98079
+ y: resolveLength(parts[1], height)
98080
+ });
98081
+ }
98082
+ return points3;
98083
+ }
98084
+ function insetClipToPoints(value, width, height) {
98085
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98086
+ const tokens = inner.split(/round/u)[0].trim().split(/\s+/u);
98087
+ const top = resolveLength(tokens[0] ?? "0", height);
98088
+ const right = resolveLength(tokens[1] ?? tokens[0] ?? "0", width);
98089
+ const bottom = resolveLength(tokens[2] ?? tokens[0] ?? "0", height);
98090
+ const left = resolveLength(tokens[3] ?? tokens[1] ?? tokens[0] ?? "0", width);
98091
+ return [
98092
+ { x: left, y: top },
98093
+ { x: width - right, y: top },
98094
+ { x: width - right, y: height - bottom },
98095
+ { x: left, y: height - bottom }
98096
+ ];
98097
+ }
98098
+ function ellipseClipToPoints(value, width, height) {
98099
+ const isCircle = value.startsWith("circle");
98100
+ const inner = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
98101
+ const [radii, position2] = inner.split(/\s+at\s+/u);
98102
+ const radiusTokens = radii.trim().split(/\s+/u).filter(Boolean);
98103
+ let rx = width / 2;
98104
+ let ry = height / 2;
98105
+ if (isCircle) {
98106
+ const r = resolveLength(radiusTokens[0] ?? "50%", Math.min(width, height));
98107
+ rx = r;
98108
+ ry = r;
98109
+ } else {
98110
+ rx = resolveLength(radiusTokens[0] ?? "50%", width);
98111
+ ry = resolveLength(radiusTokens[1] ?? radiusTokens[0] ?? "50%", height);
98112
+ }
98113
+ let cx = width / 2;
98114
+ let cy = height / 2;
98115
+ if (position2) {
98116
+ const posTokens = position2.trim().split(/\s+/u);
98117
+ cx = resolveLength(posTokens[0] ?? "50%", width);
98118
+ cy = resolveLength(posTokens[1] ?? posTokens[0] ?? "50%", height);
98119
+ }
98120
+ const points3 = [];
98121
+ for (let i = 0; i < ELLIPSE_SAMPLE_COUNT; i++) {
98122
+ const a = i / ELLIPSE_SAMPLE_COUNT * Math.PI * 2;
98123
+ points3.push({ x: cx + Math.cos(a) * rx, y: cy + Math.sin(a) * ry });
98124
+ }
98125
+ return points3;
98126
+ }
98127
+ function clipPathToPolygon(value, width, height) {
98128
+ const v = value.trim();
98129
+ if (v.startsWith("polygon")) {
98130
+ return polygonClipToPoints(v, width, height);
98131
+ }
98132
+ if (v.startsWith("inset")) {
98133
+ return insetClipToPoints(v, width, height);
98134
+ }
98135
+ if (v.startsWith("ellipse") || v.startsWith("circle")) {
98136
+ return ellipseClipToPoints(v, width, height);
98137
+ }
98138
+ if (v.startsWith("path")) {
98139
+ const start = v.indexOf("'") >= 0 ? v.indexOf("'") : v.indexOf('"');
98140
+ const end = v.lastIndexOf("'") >= 0 ? v.lastIndexOf("'") : v.lastIndexOf('"');
98141
+ if (start >= 0 && end > start) {
98142
+ const d = v.slice(start + 1, end);
98143
+ const polys = svgPathToPolygons(d);
98144
+ if (polys.length === 0) {
98145
+ return [];
98146
+ }
98147
+ return polys.reduce((a, b) => b.length > a.length ? b : a);
98148
+ }
98149
+ }
98150
+ return [];
98151
+ }
98152
+ function resolveElementOutline(element) {
98153
+ const width = Math.max(element.width, 1);
98154
+ const height = Math.max(element.height, 1);
98155
+ const shapeType = element.shapeType;
98156
+ const adjustments = element.shapeAdjustments;
98157
+ const clip = getResolvedShapeClipPathFor(shapeType, width, height, adjustments);
98158
+ if (clip) {
98159
+ const poly = clipPathToPolygon(clip, width, height);
98160
+ if (poly.length >= 3) {
98161
+ return poly;
98162
+ }
98163
+ }
98164
+ return [
98165
+ { x: 0, y: 0 },
98166
+ { x: width, y: 0 },
98167
+ { x: width, y: height },
98168
+ { x: 0, y: height }
98169
+ ];
98170
+ }
98171
+ function dist(a, b) {
98172
+ return Math.hypot(a.x - b.x, a.y - b.y);
98173
+ }
98174
+ function resamplePolygon(poly, count) {
98175
+ if (poly.length < 2) {
98176
+ return Array.from({ length: count }, () => ({ x: poly[0]?.x ?? 0, y: poly[0]?.y ?? 0 }));
98177
+ }
98178
+ const ring = [...poly, poly[0]];
98179
+ const segLen = [];
98180
+ let total = 0;
98181
+ for (let i = 0; i < ring.length - 1; i++) {
98182
+ const d = dist(ring[i], ring[i + 1]);
98183
+ segLen.push(d);
98184
+ total += d;
98185
+ }
98186
+ if (total === 0) {
98187
+ return Array.from({ length: count }, () => ({ x: poly[0].x, y: poly[0].y }));
98188
+ }
98189
+ const result = [];
98190
+ const step = total / count;
98191
+ let seg = 0;
98192
+ let segStart = 0;
98193
+ for (let i = 0; i < count; i++) {
98194
+ const target = i * step;
98195
+ while (seg < segLen.length - 1 && segStart + segLen[seg] < target) {
98196
+ segStart += segLen[seg];
98197
+ seg++;
98198
+ }
98199
+ const within = segLen[seg] > 0 ? (target - segStart) / segLen[seg] : 0;
98200
+ const a = ring[seg];
98201
+ const b = ring[seg + 1];
98202
+ result.push({ x: a.x + (b.x - a.x) * within, y: a.y + (b.y - a.y) * within });
98203
+ }
98204
+ return result;
98205
+ }
98206
+ function signedArea2(poly) {
98207
+ let area = 0;
98208
+ for (let i = 0; i < poly.length; i++) {
98209
+ const a = poly[i];
98210
+ const b = poly[(i + 1) % poly.length];
98211
+ area += a.x * b.y - b.x * a.y;
98212
+ }
98213
+ return area / 2;
98214
+ }
98215
+ function rotateRing(poly, offset) {
98216
+ const n = poly.length;
98217
+ const o = (offset % n + n) % n;
98218
+ return poly.slice(o).concat(poly.slice(0, o));
98219
+ }
98220
+ function bestRotation(from, to) {
98221
+ let bestOffset = 0;
98222
+ let bestCost = Infinity;
98223
+ for (let offset = 0; offset < to.length; offset++) {
98224
+ let cost = 0;
98225
+ for (let i = 0; i < from.length; i++) {
98226
+ const t = to[(i + offset) % to.length];
98227
+ const dx = from[i].x - t.x;
98228
+ const dy = from[i].y - t.y;
98229
+ cost += dx * dx + dy * dy;
98230
+ if (cost >= bestCost) {
98231
+ break;
98232
+ }
98233
+ }
98234
+ if (cost < bestCost) {
98235
+ bestCost = cost;
98236
+ bestOffset = offset;
98237
+ }
98238
+ }
98239
+ return bestOffset;
98240
+ }
98241
+ function normalizeOutlinePair(fromPoly, toPoly, count = OUTLINE_SAMPLE_COUNT) {
98242
+ const from = resamplePolygon(fromPoly, count);
98243
+ let to = resamplePolygon(toPoly, count);
98244
+ if (Math.sign(signedArea2(from)) !== Math.sign(signedArea2(to))) {
98245
+ to = [...to].reverse();
98246
+ }
98247
+ const offset = bestRotation(from, to);
98248
+ to = rotateRing(to, offset);
98249
+ return [from, to];
98250
+ }
98251
+ function interpolateOutline(from, to, t) {
98252
+ const clamped = Math.max(0, Math.min(1, t));
98253
+ const len = Math.min(from.length, to.length);
98254
+ if (len === 0) {
98255
+ return "";
98256
+ }
98257
+ const parts = [];
98258
+ for (let i = 0; i < len; i++) {
98259
+ const x = from[i].x + (to[i].x - from[i].x) * clamped;
98260
+ const y = from[i].y + (to[i].y - from[i].y) * clamped;
98261
+ parts.push(`${i === 0 ? "M" : "L"}${Number(x.toFixed(2))} ${Number(y.toFixed(2))}`);
98262
+ }
98263
+ parts.push("Z");
98264
+ return parts.join(" ");
98265
+ }
98266
+ var MORPH_EASING = "cubic-bezier(0.4, 0, 0.2, 1)";
98267
+ var PROXIMITY_THRESHOLD = 300;
98268
+ var GEOMETRY_MORPH_STEPS = 8;
98269
+ function shouldGeometryMorph(pair) {
98270
+ const fromType = pair.fromElement.shapeType;
98271
+ const toType = pair.toElement.shapeType;
98272
+ if (!fromType || !toType) {
98273
+ return false;
98274
+ }
98275
+ if (fromType.toLowerCase() !== toType.toLowerCase()) {
98276
+ return true;
98277
+ }
98278
+ const fromAdj = JSON.stringify(
98279
+ pair.fromElement.shapeAdjustments ?? {}
98280
+ );
98281
+ const toAdj = JSON.stringify(
98282
+ pair.toElement.shapeAdjustments ?? {}
98283
+ );
98284
+ return fromAdj !== toAdj;
98285
+ }
98286
+ function buildClipKeyframeBody(from, to, steps) {
98287
+ const [fromRing, toRing] = normalizeOutlinePair(
98288
+ resolveElementOutline(from),
98289
+ resolveElementOutline(to)
98290
+ );
98291
+ if (fromRing.length === 0 || toRing.length === 0) {
98292
+ return null;
98293
+ }
98294
+ const lines = [];
98295
+ for (let s = 0; s <= steps; s++) {
98296
+ const t = s / steps;
98297
+ const d = interpolateOutline(fromRing, toRing, t);
98298
+ if (!d) {
98299
+ return null;
98300
+ }
98301
+ const pct = Number((s / steps * 100).toFixed(2));
98302
+ lines.push(` ${pct}% {
98303
+ clip-path: path('${d}');
98304
+ }`);
98305
+ }
98306
+ return lines.join("\n");
98307
+ }
98308
+ function generateGeometryMorphAnimation(pair, durationMs, pairIndex, steps = GEOMETRY_MORPH_STEPS) {
98309
+ if (!shouldGeometryMorph(pair)) {
98310
+ return null;
98311
+ }
98312
+ const body = buildClipKeyframeBody(pair.fromElement, pair.toElement, steps);
98313
+ if (!body) {
98314
+ return null;
98315
+ }
98316
+ const safeName = `pptx-morph-geo-${pairIndex}-${pair.toElement.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98317
+ const keyframes = `
98318
+ @keyframes ${safeName} {
98319
+ ${body}
98320
+ }`;
98321
+ return {
98322
+ elementId: pair.toElement.id,
98323
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98324
+ keyframes
98325
+ };
98326
+ }
98327
+ function getElementMorphName(element) {
98328
+ if (element.name) {
98329
+ const name = element.name.trim();
98330
+ if (name.startsWith("!!")) {
98331
+ return name;
98332
+ }
98333
+ }
98334
+ if (hasTextProperties(element) && element.text) {
98335
+ const text2 = element.text.trim();
98336
+ if (text2.startsWith("!!")) {
98337
+ return text2;
98338
+ }
98339
+ }
98340
+ return void 0;
98341
+ }
98342
+ function matchMorphElementsFull(fromSlide, toSlide) {
98343
+ const pairs2 = [];
98344
+ const usedFrom = /* @__PURE__ */ new Set();
98345
+ const usedTo = /* @__PURE__ */ new Set();
98346
+ for (const fromEl of fromSlide.elements) {
98347
+ const fromName = getElementMorphName(fromEl);
98348
+ if (!fromName) {
98349
+ continue;
98350
+ }
98351
+ for (const toEl of toSlide.elements) {
98352
+ if (usedTo.has(toEl.id)) {
98353
+ continue;
98354
+ }
98355
+ const toName = getElementMorphName(toEl);
98356
+ if (toName === fromName) {
98357
+ pairs2.push({ fromElement: fromEl, toElement: toEl });
98358
+ usedFrom.add(fromEl.id);
98359
+ usedTo.add(toEl.id);
98360
+ break;
98361
+ }
98362
+ }
98363
+ }
98364
+ for (const fromEl of fromSlide.elements) {
98365
+ if (usedFrom.has(fromEl.id) || !fromEl.shapeId) {
98366
+ continue;
98367
+ }
98368
+ for (const toEl of toSlide.elements) {
98369
+ if (usedTo.has(toEl.id)) {
98370
+ continue;
98371
+ }
98372
+ if (toEl.shapeId && fromEl.shapeId === toEl.shapeId && fromEl.type === toEl.type) {
98373
+ pairs2.push({ fromElement: fromEl, toElement: toEl });
98374
+ usedFrom.add(fromEl.id);
98375
+ usedTo.add(toEl.id);
98376
+ break;
98377
+ }
98378
+ }
98379
+ }
98380
+ for (const fromEl of fromSlide.elements) {
98381
+ if (usedFrom.has(fromEl.id)) {
98382
+ continue;
98383
+ }
98384
+ let bestMatch = null;
98385
+ let bestDist = Infinity;
98386
+ for (const toEl of toSlide.elements) {
98387
+ if (usedTo.has(toEl.id)) {
98388
+ continue;
98389
+ }
98390
+ if (fromEl.type !== toEl.type) {
98391
+ continue;
98392
+ }
98393
+ const dx = fromEl.x - toEl.x;
98394
+ const dy = fromEl.y - toEl.y;
98395
+ const dist2 = Math.sqrt(dx * dx + dy * dy);
98396
+ if (dist2 < bestDist && dist2 < PROXIMITY_THRESHOLD) {
98397
+ bestDist = dist2;
98398
+ bestMatch = toEl;
98399
+ }
98400
+ }
98401
+ if (bestMatch) {
98402
+ pairs2.push({ fromElement: fromEl, toElement: bestMatch });
98403
+ usedFrom.add(fromEl.id);
98404
+ usedTo.add(bestMatch.id);
98405
+ }
98406
+ }
98407
+ const unmatchedFrom = fromSlide.elements.filter((el) => !usedFrom.has(el.id));
98408
+ const unmatchedTo = toSlide.elements.filter((el) => !usedTo.has(el.id));
98409
+ return { pairs: pairs2, unmatchedFrom, unmatchedTo };
98410
+ }
98411
+ function tokenizeText(element, mode) {
98412
+ if (!hasTextProperties(element) || !element.text) {
98413
+ return [];
98414
+ }
98415
+ const text2 = element.text;
98416
+ const style = element.textStyle;
98417
+ const fontSize = style?.fontSize ?? 14;
98418
+ const fontWeight = style?.bold ? "bold" : "normal";
98419
+ const color2 = style?.color ?? "#000000";
98420
+ const tokens = [];
98421
+ if (mode === "character") {
98422
+ const chars = Array.from(text2);
98423
+ const totalChars = chars.length;
98424
+ if (totalChars === 0) {
98425
+ return [];
98426
+ }
98427
+ for (let i = 0; i < chars.length; i++) {
98428
+ if (chars[i] === "\n") {
98429
+ continue;
98430
+ }
98431
+ tokens.push({
98432
+ text: chars[i],
98433
+ x: totalChars > 1 ? i / (totalChars - 1) : 0.5,
98434
+ y: 0.5,
98435
+ fontSize,
98436
+ fontWeight,
98437
+ color: color2
98438
+ });
98439
+ }
98440
+ } else {
98441
+ const words = text2.split(/\s+/u);
98442
+ const nonEmptyWords = words.filter((w) => w.trim().length > 0);
98443
+ const totalWords = nonEmptyWords.length;
98444
+ if (totalWords === 0) {
98445
+ return [];
98446
+ }
98447
+ let wordIndex = 0;
98448
+ for (const word of words) {
98449
+ if (word.trim().length === 0) {
98450
+ continue;
98451
+ }
98452
+ tokens.push({
98453
+ text: word,
98454
+ x: totalWords > 1 ? wordIndex / (totalWords - 1) : 0.5,
98455
+ y: 0.5,
98456
+ fontSize,
98457
+ fontWeight,
98458
+ color: color2
98459
+ });
98460
+ wordIndex++;
98461
+ }
98462
+ }
98463
+ return tokens;
98464
+ }
98465
+ function diffTokens(fromTokens, toTokens) {
98466
+ const n = fromTokens.length;
98467
+ const m = toTokens.length;
98468
+ const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
98469
+ for (let i2 = n - 1; i2 >= 0; i2--) {
98470
+ for (let j2 = m - 1; j2 >= 0; j2--) {
98471
+ 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]);
98472
+ }
98473
+ }
98474
+ const ops = [];
98475
+ let i = 0;
98476
+ let j = 0;
98477
+ while (i < n && j < m) {
98478
+ if (fromTokens[i].text === toTokens[j].text) {
98479
+ ops.push({
98480
+ change: "shared",
98481
+ from: fromTokens[i],
98482
+ to: toTokens[j],
98483
+ fromIndex: i,
98484
+ toIndex: j
98485
+ });
98486
+ i++;
98487
+ j++;
98488
+ } else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
98489
+ ops.push({ change: "removed", from: fromTokens[i], to: null, fromIndex: i, toIndex: -1 });
98490
+ i++;
98491
+ } else {
98492
+ ops.push({ change: "added", from: null, to: toTokens[j], fromIndex: -1, toIndex: j });
98493
+ j++;
98494
+ }
98495
+ }
98496
+ while (i < n) {
98497
+ ops.push({ change: "removed", from: fromTokens[i], to: null, fromIndex: i, toIndex: -1 });
98498
+ i++;
98499
+ }
98500
+ while (j < m) {
98501
+ ops.push({ change: "added", from: null, to: toTokens[j], fromIndex: -1, toIndex: j });
98502
+ j++;
98503
+ }
98504
+ return ops;
98505
+ }
98506
+ function tokenColor(token2) {
98507
+ const parsed = parseHexColor(token2.color);
98508
+ return parsed ? lerpColor2(parsed, parsed, 0) : token2.color;
98509
+ }
98510
+ function sharedKeyframes(name, op) {
98511
+ const from = op.from;
98512
+ const to = op.to;
98513
+ return `
98514
+ @keyframes ${name} {
98515
+ from {
98516
+ left: ${Number((from.x * 100).toFixed(2))}%;
98517
+ top: ${Number((from.y * 100).toFixed(2))}%;
98518
+ font-size: ${from.fontSize}pt;
98519
+ font-weight: ${from.fontWeight};
98520
+ color: ${tokenColor(from)};
98521
+ opacity: 1;
98522
+ }
98523
+ to {
98524
+ left: ${Number((to.x * 100).toFixed(2))}%;
98525
+ top: ${Number((to.y * 100).toFixed(2))}%;
98526
+ font-size: ${to.fontSize}pt;
98527
+ font-weight: ${to.fontWeight};
98528
+ color: ${tokenColor(to)};
98529
+ opacity: 1;
98530
+ }
98531
+ }`;
98532
+ }
98533
+ function fadeKeyframes(name, fadeIn) {
98534
+ const a = fadeIn ? 0 : 1;
98535
+ const b = fadeIn ? 1 : 0;
98536
+ return `
98537
+ @keyframes ${name} {
98538
+ from { opacity: ${a}; }
98539
+ to { opacity: ${b}; }
98540
+ }`;
98541
+ }
98542
+ function buildTokenMorphAnimations(ops, fromId, toId, durationMs, pairIndex) {
98543
+ const animations = [];
98544
+ for (let k = 0; k < ops.length; k++) {
98545
+ const op = ops[k];
98546
+ const name = `pptx-morph-tok-${pairIndex}-${k}`;
98547
+ const anim = `${name} ${durationMs}ms ${MORPH_EASING} forwards`;
98548
+ if (op.change === "shared") {
98549
+ animations.push({
98550
+ elementId: `${toId}__token_${op.toIndex}`,
98551
+ animation: anim,
98552
+ keyframes: sharedKeyframes(name, op)
98553
+ });
98554
+ } else if (op.change === "added") {
98555
+ animations.push({
98556
+ elementId: `${toId}__token_${op.toIndex}`,
98557
+ animation: anim,
98558
+ keyframes: fadeKeyframes(name, true)
98559
+ });
98560
+ } else {
98561
+ animations.push({
98562
+ elementId: `${fromId}__token_${op.fromIndex}`,
98563
+ animation: anim,
98564
+ keyframes: fadeKeyframes(name, false)
98565
+ });
98566
+ }
98567
+ }
98568
+ return animations;
98569
+ }
98570
+ function buildColorInterpolationProps(fromElement, toElement) {
98571
+ const fromFill = hasShapeProperties(fromElement) ? fromElement.shapeStyle?.fillColor : void 0;
98572
+ const toFill = hasShapeProperties(toElement) ? toElement.shapeStyle?.fillColor : void 0;
98573
+ if (!fromFill && !toFill) {
98574
+ return null;
98575
+ }
98576
+ if (fromFill === toFill) {
98577
+ return null;
98578
+ }
98579
+ const fromColor = parseHexColor(fromFill);
98580
+ const toColor = parseHexColor(toFill);
98581
+ if (!fromColor && !toColor) {
98582
+ return null;
98583
+ }
98584
+ const from = fromColor ?? { r: 255, g: 255, b: 255, a: 0 };
98585
+ const to = toColor ?? { r: 255, g: 255, b: 255, a: 0 };
98586
+ return {
98587
+ fromBg: lerpColor2(from, from, 0),
98588
+ toBg: lerpColor2(to, to, 0)
98589
+ };
98590
+ }
98591
+ function buildStrokeInterpolationProps(fromElement, toElement) {
98592
+ const fromStyle = hasShapeProperties(fromElement) ? fromElement.shapeStyle : void 0;
98593
+ const toStyle = hasShapeProperties(toElement) ? toElement.shapeStyle : void 0;
98594
+ const fromColor = fromStyle?.strokeColor;
98595
+ const toColor = toStyle?.strokeColor;
98596
+ const fromWidth = fromStyle?.strokeWidth ?? 0;
98597
+ const toWidth = toStyle?.strokeWidth ?? 0;
98598
+ if (!fromColor && !toColor && fromWidth === 0 && toWidth === 0) {
98599
+ return null;
98600
+ }
98601
+ if (fromColor === toColor && fromWidth === toWidth) {
98602
+ return null;
98603
+ }
98604
+ const fc = parseHexColor(fromColor) ?? { r: 0, g: 0, b: 0, a: 1 };
98605
+ const tc = parseHexColor(toColor) ?? { r: 0, g: 0, b: 0, a: 1 };
98606
+ return {
98607
+ fromStroke: lerpColor2(fc, fc, 0),
98608
+ toStroke: lerpColor2(tc, tc, 0),
98609
+ fromWidth,
98610
+ toWidth
98611
+ };
98612
+ }
98613
+ function appearanceSignature(element) {
98614
+ const parts = [element.type];
98615
+ if (hasShapeProperties(element)) {
98616
+ const style = element.shapeStyle;
98617
+ parts.push(
98618
+ element.shapeType ?? "",
98619
+ style?.fillMode ?? "",
98620
+ style?.fillColor ?? "",
98621
+ style?.fillGradient ?? "",
98622
+ String(style?.fillOpacity ?? ""),
98623
+ style?.strokeColor ?? "",
98624
+ String(style?.strokeWidth ?? "")
98625
+ );
98626
+ }
98627
+ const image = element;
98628
+ parts.push(image.imagePath ?? "", image.svgPath ?? "");
98629
+ if (hasTextProperties(element)) {
98630
+ parts.push(element.text ?? "", element.textStyle?.color ?? "");
98631
+ }
98632
+ return parts.join("");
98633
+ }
98634
+ function morphPairNeedsCrossfade(fromElement, toElement) {
98635
+ return appearanceSignature(fromElement) !== appearanceSignature(toElement);
98636
+ }
98637
+ function generateMorphAnimations(pairs2, durationMs, _mode = "object") {
98638
+ const animations = [];
98639
+ for (let index = 0; index < pairs2.length; index++) {
98640
+ const { fromElement, toElement } = pairs2[index];
98641
+ const safeName = `pptx-morph-${index}-${toElement.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98642
+ const dx = fromElement.x - toElement.x;
98643
+ const dy = fromElement.y - toElement.y;
98644
+ const sx = Math.max(fromElement.width, 1) / Math.max(toElement.width, 1);
98645
+ const sy = Math.max(fromElement.height, 1) / Math.max(toElement.height, 1);
98646
+ const dr = (fromElement.rotation ?? 0) - (toElement.rotation ?? 0);
98647
+ const fromOpacity = fromElement.opacity ?? 1;
98648
+ const toOpacity = toElement.opacity ?? 1;
98649
+ const crossfades = morphPairNeedsCrossfade(fromElement, toElement);
98650
+ const fromProps = [
98651
+ ` transform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${dr}deg);`,
98652
+ ` opacity: ${crossfades ? 0 : fromOpacity};`
98653
+ ];
98654
+ const toProps = [
98655
+ " transform: translate(0, 0) scale(1, 1) rotate(0deg);",
98656
+ ` opacity: ${toOpacity};`
98657
+ ];
98658
+ const colorInterp = buildColorInterpolationProps(fromElement, toElement);
98659
+ if (colorInterp) {
98660
+ fromProps.push(` background-color: ${colorInterp.fromBg};`);
98661
+ toProps.push(` background-color: ${colorInterp.toBg};`);
98662
+ }
98663
+ const strokeInterp = buildStrokeInterpolationProps(fromElement, toElement);
98664
+ if (strokeInterp) {
98665
+ fromProps.push(` outline: ${strokeInterp.fromWidth}px solid ${strokeInterp.fromStroke};`);
98666
+ toProps.push(` outline: ${strokeInterp.toWidth}px solid ${strokeInterp.toStroke};`);
98667
+ }
98668
+ const keyframes = `
98669
+ @keyframes ${safeName} {
98670
+ from {
98671
+ ${fromProps.join("\n")}
98672
+ }
98673
+ to {
98674
+ ${toProps.join("\n")}
98675
+ }
98676
+ }`;
98677
+ animations.push({
98678
+ elementId: toElement.id,
98679
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98680
+ keyframes
98681
+ });
98682
+ }
98683
+ return animations;
98684
+ }
98685
+ function generateMorphGhostAnimations(pairs2, durationMs, startIndex) {
98686
+ const animations = [];
98687
+ for (let index = 0; index < pairs2.length; index++) {
98688
+ const { fromElement, toElement } = pairs2[index];
98689
+ const fadesOut = morphPairNeedsCrossfade(fromElement, toElement);
98690
+ const safeName = `pptx-morph-ghost-${startIndex + index}-${fromElement.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98691
+ const dx = toElement.x - fromElement.x;
98692
+ const dy = toElement.y - fromElement.y;
98693
+ const sx = Math.max(toElement.width, 1) / Math.max(fromElement.width, 1);
98694
+ const sy = Math.max(toElement.height, 1) / Math.max(fromElement.height, 1);
98695
+ const dr = (toElement.rotation ?? 0) - (fromElement.rotation ?? 0);
98696
+ const originX = fromElement.x + fromElement.width / 2;
98697
+ const originY = fromElement.y + fromElement.height / 2;
98698
+ const keyframes = `
98699
+ @keyframes ${safeName} {
98700
+ from {
98701
+ transform-origin: ${originX}px ${originY}px;
98702
+ transform: translate(0, 0) scale(1, 1) rotate(0deg);
98703
+ opacity: ${fromElement.opacity ?? 1};
98704
+ }
98705
+ to {
98706
+ transform-origin: ${originX}px ${originY}px;
98707
+ transform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${dr}deg);
98708
+ opacity: ${fadesOut ? 0 : fromElement.opacity ?? 1};
98709
+ }
98710
+ }`;
98711
+ animations.push({
98712
+ elementId: fromElement.id,
98713
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98714
+ keyframes
98715
+ });
98716
+ }
98717
+ return animations;
98718
+ }
98719
+ function generateUnmatchedFadeOutAnimations(elements, durationMs, startIndex) {
98720
+ return elements.map((el, i) => {
98721
+ const safeName = `pptx-morph-fadeout-${startIndex + i}-${el.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98722
+ const keyframes = `
98723
+ @keyframes ${safeName} {
98724
+ from {
98725
+ opacity: ${el.opacity ?? 1};
98726
+ transform: scale(1);
98727
+ }
98728
+ to {
98729
+ opacity: 0;
98730
+ transform: scale(0.95);
98731
+ }
98732
+ }`;
98733
+ return {
98734
+ elementId: el.id,
98735
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98736
+ keyframes
98737
+ };
98738
+ });
98739
+ }
98740
+ function generateUnmatchedFadeInAnimations(elements, durationMs, startIndex) {
98741
+ return elements.map((el, i) => {
98742
+ const safeName = `pptx-morph-fadein-${startIndex + i}-${el.id.replace(/[^a-zA-Z0-9]/gu, "")}`;
98743
+ const keyframes = `
98744
+ @keyframes ${safeName} {
98745
+ from {
98746
+ opacity: 0;
98747
+ transform: scale(0.95);
98748
+ }
98749
+ to {
98750
+ opacity: ${el.opacity ?? 1};
98751
+ transform: scale(1);
98752
+ }
98753
+ }`;
98754
+ return {
98755
+ elementId: el.id,
98756
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
98757
+ keyframes
98758
+ };
98759
+ });
98760
+ }
98761
+ function generateTextMorphAnimations(pair, durationMs, mode, pairIndex) {
98762
+ const fromTokens = tokenizeText(pair.fromElement, mode);
98763
+ const toTokens = tokenizeText(pair.toElement, mode);
98764
+ if (fromTokens.length === 0 && toTokens.length === 0) {
98765
+ return [];
98766
+ }
98767
+ const ops = diffTokens(fromTokens, toTokens);
98768
+ return buildTokenMorphAnimations(
98769
+ ops,
98770
+ pair.fromElement.id,
98771
+ pair.toElement.id,
98772
+ durationMs,
98773
+ pairIndex
98774
+ );
98775
+ }
98776
+ function generateFullMorphTransition(fromSlide, toSlide, durationMs, mode = "object") {
98777
+ const matchResult = matchMorphElementsFull(fromSlide, toSlide);
98778
+ const allAnimations = [];
98779
+ const pairAnims = generateMorphAnimations(matchResult.pairs, durationMs, mode);
98780
+ allAnimations.push(...pairAnims);
98781
+ for (let i = 0; i < matchResult.pairs.length; i++) {
98782
+ const geo = generateGeometryMorphAnimation(matchResult.pairs[i], durationMs, i);
98783
+ if (geo) {
98784
+ allAnimations.push(geo);
98785
+ }
98786
+ }
98787
+ if (mode === "word" || mode === "character") {
98788
+ for (let i = 0; i < matchResult.pairs.length; i++) {
98789
+ const pair = matchResult.pairs[i];
98790
+ if (hasTextProperties(pair.fromElement) && hasTextProperties(pair.toElement)) {
98791
+ const textAnims = generateTextMorphAnimations(pair, durationMs, mode, i);
98792
+ allAnimations.push(...textAnims);
98793
+ }
98794
+ }
98795
+ }
98796
+ const ghosts = generateMorphGhostAnimations(matchResult.pairs, durationMs, pairAnims.length);
98797
+ allAnimations.push(...ghosts);
98798
+ const fadeOuts = generateUnmatchedFadeOutAnimations(
98799
+ matchResult.unmatchedFrom,
98800
+ durationMs,
98801
+ pairAnims.length + ghosts.length
98802
+ );
98803
+ allAnimations.push(...fadeOuts);
98804
+ const fadeIns = generateUnmatchedFadeInAnimations(
98805
+ matchResult.unmatchedTo,
98806
+ durationMs,
98807
+ pairAnims.length + ghosts.length + fadeOuts.length
98808
+ );
98809
+ allAnimations.push(...fadeIns);
98810
+ return allAnimations;
98811
+ }
98812
+ function morphOptionToMode(option) {
98813
+ if (option === "byWord") {
98814
+ return "word";
98815
+ }
98816
+ if (option === "byChar") {
98817
+ return "character";
98818
+ }
98819
+ return "object";
98820
+ }
98821
+ function buildMorphTransitionPlan(fromSlide, toSlide, durationMs, mode = "object") {
98822
+ if (!fromSlide || !toSlide) {
98823
+ return void 0;
98824
+ }
98825
+ const match = matchMorphElementsFull(fromSlide, toSlide);
98826
+ if (match.pairs.length === 0 && match.unmatchedFrom.length === 0 && match.unmatchedTo.length === 0) {
98827
+ return void 0;
98828
+ }
98829
+ const animations = generateFullMorphTransition(fromSlide, toSlide, durationMs, mode);
98830
+ const outgoingElements = [...fromSlide.elements];
98831
+ const outgoingIds = new Set(outgoingElements.map((element) => element.id));
98832
+ const incomingAnimations = /* @__PURE__ */ new Map();
98833
+ const outgoingAnimations = /* @__PURE__ */ new Map();
98834
+ const keyframes = [];
98835
+ for (const animation of animations) {
98836
+ keyframes.push(animation.keyframes);
98837
+ if (outgoingIds.has(animation.elementId)) {
98838
+ outgoingAnimations.set(animation.elementId, animation.animation);
98839
+ } else {
98840
+ incomingAnimations.set(animation.elementId, animation.animation);
98841
+ }
98842
+ }
98843
+ return {
98844
+ keyframesCss: keyframes.join("\n"),
98845
+ incomingAnimations,
98846
+ outgoingAnimations,
98847
+ outgoingElements,
98848
+ durationMs
98849
+ };
98850
+ }
97951
98851
  function hexToRgb6(hex10) {
97952
98852
  const clean = hex10.replace(/^#/u, "");
97953
98853
  return {
@@ -109835,6 +110735,7 @@ exports.buildHandoutsHtml = buildHandoutsHtml;
109835
110735
  exports.buildInitialGuides = buildInitialGuides;
109836
110736
  exports.buildInnerShadowCssFromShapeStyle = buildInnerShadowCssFromShapeStyle;
109837
110737
  exports.buildJoinCollaborationConfig = buildJoinCollaborationConfig;
110738
+ exports.buildMorphTransitionPlan = buildMorphTransitionPlan;
109838
110739
  exports.buildMultiLayerShadowCss = buildMultiLayerShadowCss;
109839
110740
  exports.buildNotesHtml = buildNotesHtml;
109840
110741
  exports.buildNotesPdfBytes = buildNotesPdfBytes;
@@ -110071,6 +110972,7 @@ exports.mergePresentationSnapshot = mergePresentationSnapshot;
110071
110972
  exports.mergeShapes = mergeShapes;
110072
110973
  exports.mobileElapsedSince = mobileElapsedSince;
110073
110974
  exports.mobileSlideCounter = mobileSlideCounter;
110975
+ exports.morphOptionToMode = morphOptionToMode;
110074
110976
  exports.mountModel3D = mountModel3D;
110075
110977
  exports.mountSurfaceChart3D = mountSurfaceChart3D;
110076
110978
  exports.movePresenterPointer = movePresenterPointer;
@@ -110139,6 +111041,7 @@ exports.resolveLineHeight = resolveLineHeight;
110139
111041
  exports.resolveOleType = resolveOleType;
110140
111042
  exports.resolveParagraphAlign = resolveParagraphAlign;
110141
111043
  exports.resolveParagraphRtl = resolveParagraphRtl;
111044
+ exports.resolveParagraphStrutFontSize = resolveParagraphStrutFontSize;
110142
111045
  exports.resolvePictureBullet = resolvePictureBullet;
110143
111046
  exports.resolveProfileInitial = resolveProfileInitial;
110144
111047
  exports.resolveRegionCode = resolveRegionCode;