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.
- package/CHANGELOG.md +9 -0
- package/dist/{AiChatPanel-DPMHPOWF.js → AiChatPanel-LBK6YRKH.js} +22 -22
- package/dist/AiChatPanel-LBK6YRKH.js.br +0 -0
- package/dist/AiChatPanel-LBK6YRKH.js.gz +0 -0
- package/dist/{AiChatPanel-OFOOWR4U.mjs → AiChatPanel-RVZOGGFK.mjs} +3 -3
- package/dist/AiChatPanel-RVZOGGFK.mjs.br +0 -0
- package/dist/AiChatPanel-RVZOGGFK.mjs.gz +0 -0
- package/dist/{Model3DScene-PD2MDBIE.js → Model3DScene-L46RNRU5.js} +2 -2
- package/dist/Model3DScene-L46RNRU5.js.br +0 -0
- package/dist/Model3DScene-L46RNRU5.js.gz +0 -0
- package/dist/{Model3DScene-P4OKVQBF.mjs → Model3DScene-WBUZ74G3.mjs} +1 -1
- package/dist/Model3DScene-WBUZ74G3.mjs.br +0 -0
- package/dist/Model3DScene-WBUZ74G3.mjs.gz +0 -0
- package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs → SurfaceChart3DScene-CB32AJS4.mjs} +1 -1
- package/dist/{SurfaceChart3DScene-TL4ZIOI4.mjs.br → SurfaceChart3DScene-CB32AJS4.mjs.br} +0 -0
- package/dist/SurfaceChart3DScene-CB32AJS4.mjs.gz +0 -0
- package/dist/{SurfaceChart3DScene-FECS3THE.js → SurfaceChart3DScene-RWMGMREC.js} +2 -2
- package/dist/SurfaceChart3DScene-RWMGMREC.js.br +0 -0
- package/dist/SurfaceChart3DScene-RWMGMREC.js.gz +0 -0
- package/dist/{chunk-UUS7QT22.js → chunk-2VE3LVKZ.js} +346 -315
- package/dist/chunk-2VE3LVKZ.js.br +0 -0
- package/dist/chunk-2VE3LVKZ.js.gz +0 -0
- package/dist/{chunk-FFLUALX5.js → chunk-4O7PPQ2V.js} +260 -240
- package/dist/chunk-4O7PPQ2V.js.br +0 -0
- package/dist/chunk-4O7PPQ2V.js.gz +0 -0
- package/dist/{chunk-ZZA62IND.mjs → chunk-54FSVX3O.mjs} +35 -4
- package/dist/chunk-54FSVX3O.mjs.br +0 -0
- package/dist/chunk-54FSVX3O.mjs.gz +0 -0
- package/dist/{chunk-H2FZ2NJ7.js → chunk-AX4Q5JWN.js} +3 -3
- package/dist/chunk-AX4Q5JWN.js.br +0 -0
- package/dist/chunk-AX4Q5JWN.js.gz +0 -0
- package/dist/{chunk-F3JUUSC4.mjs → chunk-BL3WW2BS.mjs} +95 -15
- package/dist/chunk-BL3WW2BS.mjs.br +0 -0
- package/dist/chunk-BL3WW2BS.mjs.gz +0 -0
- package/dist/{chunk-6KOM27PS.mjs → chunk-EI456HZK.mjs} +964 -64
- package/dist/chunk-EI456HZK.mjs.br +0 -0
- package/dist/chunk-EI456HZK.mjs.gz +0 -0
- package/dist/{chunk-SAXG53MO.mjs → chunk-GC6HQMVG.mjs} +1 -1
- package/dist/chunk-GC6HQMVG.mjs.br +0 -0
- package/dist/chunk-GC6HQMVG.mjs.gz +0 -0
- package/dist/{chunk-USHZUHHG.js → chunk-IEFH47TF.js} +929 -849
- package/dist/chunk-IEFH47TF.js.br +0 -0
- package/dist/chunk-IEFH47TF.js.gz +0 -0
- package/dist/{chunk-23Q3I2LM.js → chunk-T7AMP24E.js} +966 -63
- package/dist/chunk-T7AMP24E.js.br +0 -0
- package/dist/chunk-T7AMP24E.js.gz +0 -0
- package/dist/{chunk-QDIF3ZXF.mjs → chunk-ZUNDIOGD.mjs} +28 -8
- package/dist/chunk-ZUNDIOGD.mjs.br +0 -0
- package/dist/chunk-ZUNDIOGD.mjs.gz +0 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +34 -34
- package/dist/index.js.br +0 -0
- package/dist/index.js.gz +0 -0
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.br +0 -0
- package/dist/index.mjs.gz +0 -0
- package/dist/internals.d.ts +44 -0
- package/dist/internals.d.ts.map +1 -1
- package/dist/internals.js +78 -78
- package/dist/internals.js.br +0 -0
- package/dist/internals.js.gz +0 -0
- package/dist/internals.mjs +3 -3
- package/dist/internals.mjs.br +0 -0
- package/dist/internals.mjs.gz +0 -0
- package/dist/pptx-viewer.css +1 -1
- package/dist/pptx-viewer.css.br +0 -0
- package/dist/pptx-viewer.css.gz +0 -0
- package/dist/viewer/index.d.ts +15 -0
- package/dist/viewer/index.js +21 -21
- package/dist/viewer/index.js.br +0 -0
- package/dist/viewer/index.js.gz +0 -0
- package/dist/viewer/index.mjs +5 -5
- package/dist/viewer/index.mjs.br +0 -0
- package/dist/viewer/index.mjs.gz +0 -0
- package/package.json +1 -1
- package/dist/AiChatPanel-DPMHPOWF.js.br +0 -0
- package/dist/AiChatPanel-DPMHPOWF.js.gz +0 -0
- package/dist/AiChatPanel-OFOOWR4U.mjs.br +0 -0
- package/dist/AiChatPanel-OFOOWR4U.mjs.gz +0 -0
- package/dist/Model3DScene-P4OKVQBF.mjs.br +0 -0
- package/dist/Model3DScene-P4OKVQBF.mjs.gz +0 -0
- package/dist/Model3DScene-PD2MDBIE.js.br +0 -0
- package/dist/Model3DScene-PD2MDBIE.js.gz +0 -0
- package/dist/SurfaceChart3DScene-FECS3THE.js.br +0 -0
- package/dist/SurfaceChart3DScene-FECS3THE.js.gz +0 -0
- package/dist/SurfaceChart3DScene-TL4ZIOI4.mjs.gz +0 -0
- package/dist/chunk-23Q3I2LM.js.br +0 -0
- package/dist/chunk-23Q3I2LM.js.gz +0 -0
- package/dist/chunk-6KOM27PS.mjs.br +0 -0
- package/dist/chunk-6KOM27PS.mjs.gz +0 -0
- package/dist/chunk-F3JUUSC4.mjs.br +0 -0
- package/dist/chunk-F3JUUSC4.mjs.gz +0 -0
- package/dist/chunk-FFLUALX5.js.br +0 -0
- package/dist/chunk-FFLUALX5.js.gz +0 -0
- package/dist/chunk-H2FZ2NJ7.js.br +0 -0
- package/dist/chunk-H2FZ2NJ7.js.gz +0 -0
- package/dist/chunk-QDIF3ZXF.mjs.br +0 -0
- package/dist/chunk-QDIF3ZXF.mjs.gz +0 -0
- package/dist/chunk-SAXG53MO.mjs.br +0 -0
- package/dist/chunk-SAXG53MO.mjs.gz +0 -0
- package/dist/chunk-USHZUHHG.js.br +0 -0
- package/dist/chunk-USHZUHHG.js.gz +0 -0
- package/dist/chunk-UUS7QT22.js.br +0 -0
- package/dist/chunk-UUS7QT22.js.gz +0 -0
- package/dist/chunk-ZZA62IND.mjs.br +0 -0
- 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
|
|
12665
|
-
if (Number.isFinite(
|
|
12666
|
-
style.reflectionDistance =
|
|
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
|
-
|
|
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
|
|
20628
|
-
|
|
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
|
|
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
|
-
|
|
20694
|
-
|
|
20695
|
-
}
|
|
20696
|
-
return true;
|
|
20704
|
+
return {
|
|
20705
|
+
morphOption: normalizeMorphOption(value?.["@_option"])
|
|
20706
|
+
};
|
|
20697
20707
|
}
|
|
20698
20708
|
}
|
|
20699
20709
|
}
|
|
20700
|
-
return
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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) *
|
|
51318
|
-
style.textShadowOffsetY = Math.round(Math.sin(dirRad) *
|
|
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:
|
|
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
|
-
|
|
63415
|
-
|
|
63416
|
-
|
|
63417
|
-
|
|
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 =
|
|
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
|
|
66418
|
+
const dist2 = parseInt(String(outerShdw["@_dist"] || "0"));
|
|
66364
66419
|
const dir = parseInt(String(outerShdw["@_dir"] || "0"));
|
|
66365
|
-
if (Number.isFinite(
|
|
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) *
|
|
66368
|
-
result.shadowOffsetY = Math.sin(angleRad) *
|
|
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
|
|
66434
|
+
const dist2 = parseInt(String(innerShdw["@_dist"] || "0"));
|
|
66380
66435
|
const dir = parseInt(String(innerShdw["@_dir"] || "0"));
|
|
66381
|
-
if (Number.isFinite(
|
|
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) *
|
|
66384
|
-
result.innerShadowOffsetY = Math.sin(angleRad) *
|
|
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
|
|
66430
|
-
if (Number.isFinite(
|
|
66431
|
-
result.reflectionDistance =
|
|
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;
|