pptx-react-viewer 4.3.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/dist/{AiChatPanel-UCEK3ZTD.mjs → AiChatPanel-HXGCZPUX.mjs} +4 -4
  3. package/dist/AiChatPanel-HXGCZPUX.mjs.br +0 -0
  4. package/dist/AiChatPanel-HXGCZPUX.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-7UQA25FA.js → AiChatPanel-P2N6X2KB.js} +28 -28
  6. package/dist/AiChatPanel-P2N6X2KB.js.br +0 -0
  7. package/dist/AiChatPanel-P2N6X2KB.js.gz +0 -0
  8. package/dist/{Model3DScene-X3DS3ELB.js → Model3DScene-PIFMH2TU.js} +2 -2
  9. package/dist/Model3DScene-PIFMH2TU.js.br +0 -0
  10. package/dist/Model3DScene-PIFMH2TU.js.gz +0 -0
  11. package/dist/{Model3DScene-AI2JTBQM.mjs → Model3DScene-QXMMJRV3.mjs} +1 -1
  12. package/dist/Model3DScene-QXMMJRV3.mjs.br +0 -0
  13. package/dist/Model3DScene-QXMMJRV3.mjs.gz +0 -0
  14. package/dist/{chunk-E7O4HTS5.js → chunk-6FVYG27J.js} +211 -187
  15. package/dist/chunk-6FVYG27J.js.br +0 -0
  16. package/dist/chunk-6FVYG27J.js.gz +0 -0
  17. package/dist/{chunk-OBQ453H6.mjs → chunk-APAVAD2A.mjs} +37 -0
  18. package/dist/chunk-APAVAD2A.mjs.br +0 -0
  19. package/dist/chunk-APAVAD2A.mjs.gz +0 -0
  20. package/dist/{chunk-YQJOCGOK.mjs → chunk-DX2JCSQ4.mjs} +1 -1
  21. package/dist/chunk-DX2JCSQ4.mjs.br +0 -0
  22. package/dist/chunk-DX2JCSQ4.mjs.gz +0 -0
  23. package/dist/{chunk-RXYLPESV.mjs → chunk-IDV2ITXM.mjs} +607 -102
  24. package/dist/chunk-IDV2ITXM.mjs.br +0 -0
  25. package/dist/chunk-IDV2ITXM.mjs.gz +0 -0
  26. package/dist/{chunk-UTI4CLYJ.js → chunk-LYZQLV7R.js} +3417 -1722
  27. package/dist/chunk-LYZQLV7R.js.br +0 -0
  28. package/dist/chunk-LYZQLV7R.js.gz +0 -0
  29. package/dist/{chunk-SKTZSG7Q.mjs → chunk-PRXJ3J5W.mjs} +325 -48
  30. package/dist/chunk-PRXJ3J5W.mjs.br +0 -0
  31. package/dist/chunk-PRXJ3J5W.mjs.gz +0 -0
  32. package/dist/{chunk-KAO5USPE.js → chunk-T35BGKZG.js} +5 -5
  33. package/dist/chunk-T35BGKZG.js.br +0 -0
  34. package/dist/chunk-T35BGKZG.js.gz +0 -0
  35. package/dist/{chunk-W5KLLGVH.js → chunk-UMQV2432.js} +37 -0
  36. package/dist/chunk-UMQV2432.js.br +0 -0
  37. package/dist/chunk-UMQV2432.js.gz +0 -0
  38. package/dist/{chunk-42XEZVUQ.js → chunk-UZFCFYK6.js} +1667 -1162
  39. package/dist/chunk-UZFCFYK6.js.br +0 -0
  40. package/dist/chunk-UZFCFYK6.js.gz +0 -0
  41. package/dist/{chunk-3UWJWJCR.mjs → chunk-VZNIVS3X.mjs} +3397 -1723
  42. package/dist/chunk-VZNIVS3X.mjs.br +0 -0
  43. package/dist/chunk-VZNIVS3X.mjs.gz +0 -0
  44. package/dist/{chunk-Y7LI2JIR.js → chunk-Y4VRYQQS.js} +1123 -846
  45. package/dist/chunk-Y4VRYQQS.js.br +0 -0
  46. package/dist/chunk-Y4VRYQQS.js.gz +0 -0
  47. package/dist/{chunk-PLDG3CXW.mjs → chunk-ZF5S3HHW.mjs} +31 -7
  48. package/dist/chunk-ZF5S3HHW.mjs.br +0 -0
  49. package/dist/chunk-ZF5S3HHW.mjs.gz +0 -0
  50. package/dist/i18n/de.cjs +33 -0
  51. package/dist/i18n/de.cjs.br +0 -0
  52. package/dist/i18n/de.cjs.gz +0 -0
  53. package/dist/i18n/de.mjs +33 -0
  54. package/dist/i18n/de.mjs.br +0 -0
  55. package/dist/i18n/de.mjs.gz +0 -0
  56. package/dist/i18n/es.cjs +33 -0
  57. package/dist/i18n/es.cjs.br +0 -0
  58. package/dist/i18n/es.cjs.gz +0 -0
  59. package/dist/i18n/es.mjs +33 -0
  60. package/dist/i18n/es.mjs.br +0 -0
  61. package/dist/i18n/es.mjs.gz +0 -0
  62. package/dist/i18n/fr.cjs +33 -0
  63. package/dist/i18n/fr.cjs.br +0 -0
  64. package/dist/i18n/fr.cjs.gz +0 -0
  65. package/dist/i18n/fr.mjs +33 -0
  66. package/dist/i18n/fr.mjs.br +0 -0
  67. package/dist/i18n/fr.mjs.gz +0 -0
  68. package/dist/i18n/zh-CN.cjs +33 -0
  69. package/dist/i18n/zh-CN.cjs.br +0 -0
  70. package/dist/i18n/zh-CN.cjs.gz +0 -0
  71. package/dist/i18n/zh-CN.mjs +33 -0
  72. package/dist/i18n/zh-CN.mjs.br +0 -0
  73. package/dist/i18n/zh-CN.mjs.gz +0 -0
  74. package/dist/i18n.js +4 -4
  75. package/dist/i18n.js.br +0 -0
  76. package/dist/i18n.js.gz +0 -0
  77. package/dist/i18n.mjs +1 -1
  78. package/dist/i18n.mjs.br +0 -0
  79. package/dist/i18n.mjs.gz +0 -0
  80. package/dist/index.d.ts +116 -8
  81. package/dist/index.js +49 -49
  82. package/dist/index.js.br +0 -0
  83. package/dist/index.js.gz +0 -0
  84. package/dist/index.mjs +6 -6
  85. package/dist/index.mjs.br +0 -0
  86. package/dist/index.mjs.gz +0 -0
  87. package/dist/internals.d.ts +228 -44
  88. package/dist/internals.js +105 -105
  89. package/dist/internals.js.br +0 -0
  90. package/dist/internals.js.gz +0 -0
  91. package/dist/internals.mjs +4 -4
  92. package/dist/internals.mjs.br +0 -0
  93. package/dist/internals.mjs.gz +0 -0
  94. package/dist/pptx-viewer.css +1 -1
  95. package/dist/pptx-viewer.css.br +0 -0
  96. package/dist/pptx-viewer.css.gz +0 -0
  97. package/dist/viewer/index.d.ts +97 -8
  98. package/dist/viewer/index.js +27 -27
  99. package/dist/viewer/index.js.br +0 -0
  100. package/dist/viewer/index.js.gz +0 -0
  101. package/dist/viewer/index.mjs +6 -6
  102. package/dist/viewer/index.mjs.br +0 -0
  103. package/dist/viewer/index.mjs.gz +0 -0
  104. package/package.json +1 -1
  105. package/dist/AiChatPanel-7UQA25FA.js.br +0 -0
  106. package/dist/AiChatPanel-7UQA25FA.js.gz +0 -0
  107. package/dist/AiChatPanel-UCEK3ZTD.mjs.br +0 -0
  108. package/dist/AiChatPanel-UCEK3ZTD.mjs.gz +0 -0
  109. package/dist/Model3DScene-AI2JTBQM.mjs.br +0 -0
  110. package/dist/Model3DScene-AI2JTBQM.mjs.gz +0 -0
  111. package/dist/Model3DScene-X3DS3ELB.js.br +0 -0
  112. package/dist/Model3DScene-X3DS3ELB.js.gz +0 -0
  113. package/dist/chunk-3UWJWJCR.mjs.br +0 -0
  114. package/dist/chunk-3UWJWJCR.mjs.gz +0 -0
  115. package/dist/chunk-42XEZVUQ.js.br +0 -0
  116. package/dist/chunk-42XEZVUQ.js.gz +0 -0
  117. package/dist/chunk-E7O4HTS5.js.br +0 -0
  118. package/dist/chunk-E7O4HTS5.js.gz +0 -0
  119. package/dist/chunk-KAO5USPE.js.br +0 -0
  120. package/dist/chunk-KAO5USPE.js.gz +0 -0
  121. package/dist/chunk-OBQ453H6.mjs.br +0 -0
  122. package/dist/chunk-OBQ453H6.mjs.gz +0 -0
  123. package/dist/chunk-PLDG3CXW.mjs.br +0 -0
  124. package/dist/chunk-PLDG3CXW.mjs.gz +0 -0
  125. package/dist/chunk-RXYLPESV.mjs.br +0 -0
  126. package/dist/chunk-RXYLPESV.mjs.gz +0 -0
  127. package/dist/chunk-SKTZSG7Q.mjs.br +0 -0
  128. package/dist/chunk-SKTZSG7Q.mjs.gz +0 -0
  129. package/dist/chunk-UTI4CLYJ.js.br +0 -0
  130. package/dist/chunk-UTI4CLYJ.js.gz +0 -0
  131. package/dist/chunk-W5KLLGVH.js.br +0 -0
  132. package/dist/chunk-W5KLLGVH.js.gz +0 -0
  133. package/dist/chunk-Y7LI2JIR.js.br +0 -0
  134. package/dist/chunk-Y7LI2JIR.js.gz +0 -0
  135. package/dist/chunk-YQJOCGOK.mjs.br +0 -0
  136. package/dist/chunk-YQJOCGOK.mjs.gz +0 -0
@@ -1692,6 +1692,16 @@ interface TextStyle {
1692
1692
  hyperlinkHighlightClick?: boolean;
1693
1693
  /** Whether hyperlink ends a sound (`a:hlinkClick/@endSnd`). */
1694
1694
  hyperlinkEndSound?: boolean;
1695
+ /**
1696
+ * Raw `a:hlinkClick/a:extLst` child, preserved verbatim for round-trip.
1697
+ * Carries vendor extensions this engine does not interpret, most commonly
1698
+ * `ahyp:hlinkClr` (Microsoft's "hyperlink color" extension,
1699
+ * `{A12FA001-AC4F-418D-AE19-62706E023703}`), which records whether a
1700
+ * hyperlink run should paint with the theme's text colour instead of the
1701
+ * hyperlink colour. Dropping the whole `a:extLst` silently reverted such a
1702
+ * run to the default (themed) hyperlink colour on save.
1703
+ */
1704
+ hyperlinkExtensionXml?: XmlObject;
1695
1705
  /** Kumimoji (ideographic text combining) flag for vertical CJK text (`a:rPr/@kumimoji`). */
1696
1706
  kumimoji?: boolean;
1697
1707
  /** Normalize height flag (`a:rPr/@normalizeH`). */
@@ -1794,6 +1804,15 @@ interface TextStyle {
1794
1804
  textInnerShadowOffsetX?: number;
1795
1805
  /** Text inner shadow vertical offset in px. */
1796
1806
  textInnerShadowOffsetY?: number;
1807
+ /**
1808
+ * Original inner-shadow colour-choice XML (`a:innerShdw`'s
1809
+ * `a:prstClr`/`a:schemeClr`/`a:srgbClr`/… child), preserved verbatim so an
1810
+ * authored preset or theme colour round-trips instead of always being
1811
+ * re-serialized as a resolved `a:srgbClr`. Mirrors {@link textGlowColorXml}.
1812
+ */
1813
+ textInnerShadowColorXml?: XmlObject;
1814
+ /** Theme colour slot the inner shadow colour resolved from, when it is `a:schemeClr`. */
1815
+ textInnerShadowColorRef?: PptxThemeColorRef;
1797
1816
  /** Preset shadow type from `a:prstShdw/@prst` (e.g. "shdw1"..."shdw20"). */
1798
1817
  textPresetShadowName?: string;
1799
1818
  /** Preset shadow colour as hex string. */
@@ -1806,6 +1825,18 @@ interface TextStyle {
1806
1825
  textPresetShadowDirection?: number;
1807
1826
  /** Text blur effect radius in px (`a:blur`). */
1808
1827
  textBlurRadius?: number;
1828
+ /**
1829
+ * Text soft-edge radius in px (`a:softEdge/@rad`).
1830
+ *
1831
+ * Feathers the glyph's own edges (a uniform blur of the alpha silhouette,
1832
+ * the same effect a shape's `a:softEdge` gives its fill), unrelated to
1833
+ * `a:blur` (which blurs the whole run, colour included) or a shadow. Never
1834
+ * parsed before this field existed, so `a:softEdge` on a run was silently
1835
+ * dropped: PowerPoint fades the glyphs to near-transparent at their
1836
+ * outline (COM-verified, `audit-text` slide 14's "SOFTEDGE" run), while
1837
+ * the viewer painted them fully crisp.
1838
+ */
1839
+ textSoftEdgeRadius?: number;
1809
1840
  /**
1810
1841
  * Raw `a:effectDag` XML node from `a:rPr`, preserved verbatim for
1811
1842
  * round-trip serialisation. Mirrors the shape-level
@@ -1845,6 +1876,15 @@ interface TextStyle {
1845
1876
  textGlowRadius?: number;
1846
1877
  /** Text glow opacity (0-1). */
1847
1878
  textGlowOpacity?: number;
1879
+ /**
1880
+ * Original glow colour-choice XML (`a:glow`'s `a:schemeClr`/`a:srgbClr`/…
1881
+ * child), preserved verbatim so a theme colour reference round-trips
1882
+ * instead of always being re-serialized as a resolved `a:srgbClr` (which
1883
+ * cuts the glow off from theme/Recolor changes).
1884
+ */
1885
+ textGlowColorXml?: XmlObject;
1886
+ /** Theme colour slot the glow colour resolved from, when it is `a:schemeClr`. */
1887
+ textGlowColorRef?: PptxThemeColorRef;
1848
1888
  /** Text reflection enabled flag. */
1849
1889
  textReflection?: boolean;
1850
1890
  /** Text reflection blur radius in px. */
@@ -1981,6 +2021,18 @@ interface BulletInfo {
1981
2021
  paragraphIndex?: number;
1982
2022
  /** Bullet font family from `a:buFont`. */
1983
2023
  fontFamily?: string;
2024
+ /**
2025
+ * PANOSE font-matching hint from `a:buFont/@panose`. `a:buFont` is a
2026
+ * CT_TextFont, the same complex type as `a:latin`/`a:ea`/`a:cs`/`a:sym`
2027
+ * (which carry the equivalent `TextStyle.latinFontPanose` etc.), so a
2028
+ * bullet's own PANOSE/pitch-family/charset decide the fallback glyph
2029
+ * PowerPoint substitutes when the named typeface is missing.
2030
+ */
2031
+ fontPanose?: string;
2032
+ /** Font pitch-and-family byte from `a:buFont/@pitchFamily`. */
2033
+ fontPitchFamily?: number;
2034
+ /** Font character-set byte from `a:buFont/@charset`. */
2035
+ fontCharset?: number;
1984
2036
  /** Bullet size as percentage of text font size from `a:buSzPct`. */
1985
2037
  sizePercent?: number;
1986
2038
  /** Bullet size in points from `a:buSzPts`. */
@@ -3417,6 +3469,15 @@ interface PptxChartHistogramOptions {
3417
3469
  intervalClosed?: 'l' | 'r';
3418
3470
  underflow?: number | 'auto';
3419
3471
  overflow?: number | 'auto';
3472
+ /**
3473
+ * `c:layoutPr/cx:aggregation` was authored instead of `cx:binning`: the
3474
+ * raw rows are CATEGORICAL (a Pareto chart's `clusteredColumn` series
3475
+ * counting occurrences of each authored category, COM-verified against
3476
+ * charts-com.pptx slide 31 / chartEx6.xml), not a numeric range to bin.
3477
+ * Mutually exclusive with `binSize`/`binCount`/`intervalClosed`, which
3478
+ * only apply to a true numeric-value histogram.
3479
+ */
3480
+ aggregateByCategory?: boolean;
3420
3481
  }
3421
3482
  /** Office 2016 ChartEx waterfall series layout options. */
3422
3483
  interface PptxChartWaterfallOptions {
@@ -4081,6 +4142,18 @@ interface PptxChartData {
4081
4142
  * the source" and callers should treat it as `true`. Surface only.
4082
4143
  */
4083
4144
  wireframe?: boolean;
4145
+ /**
4146
+ * Whether the surface chart is the 2-D "top view" projection
4147
+ * (`c:surfaceChart`, PowerPoint's "Contour" / "Wireframe Contour" types)
4148
+ * rather than the 3-D isometric one (`c:surface3DChart`, "3-D Surface" /
4149
+ * "3-D Surface (Wireframe)"). Both element names map to chart type
4150
+ * `"surface"`; this bit is the only thing that tells the renderer which
4151
+ * of the two projections PowerPoint actually drew, since a top-view
4152
+ * surface has no Z-axis at all (only category and series axes) while the
4153
+ * 3-D one draws all three. Surface only; `undefined` for every other
4154
+ * chart type.
4155
+ */
4156
+ surfaceTopView?: boolean;
4084
4157
  /**
4085
4158
  * Scatter presentation mode (`c:scatterChart/c:scatterStyle/@val`).
4086
4159
  *
@@ -7270,11 +7343,17 @@ interface ZoomPptxElement extends PptxElementBase, PptxImageProperties {
7270
7343
  * `zmPr/@returnToParent` (MS-PPTX `CT_ZoomObjectProperties`, shared by all
7271
7344
  * three Zoom kinds): whether continuing forward from the destination slide
7272
7345
  * during a live show returns to this Zoom's origin slide instead of
7273
- * advancing linearly through the deck. OOXML default is `true` when the
7274
- * attribute is present but this codebase leaves it `undefined` when the
7275
- * source XML omits it, so a round-trip never fabricates the attribute.
7276
- * For `zoomType: 'summary'`, this mirrors the first tile's own value; see
7277
- * {@link SummaryZoomTarget.returnToParent} for the per-tile value.
7346
+ * advancing linearly through the deck. The schema declares `<xsd:attribute
7347
+ * name="returnToParent" type="xsd:boolean" use="optional" default="true"/>`,
7348
+ * so an ABSENT attribute means `true`, not `false`. This codebase still
7349
+ * leaves the field `undefined` (rather than fabricating `true`) when the
7350
+ * source XML omits it, so a round-trip never invents an attribute the
7351
+ * source never had; a CONSUMER of this field (playback, e.g.
7352
+ * `pptx-viewer-shared`'s `resolveZoomNavigationTarget`) must read
7353
+ * `returnToParent !== false`, not `Boolean(returnToParent)`, to get the
7354
+ * spec-correct effective value. For `zoomType: 'summary'`, this mirrors the
7355
+ * first tile's own value; see {@link SummaryZoomTarget.returnToParent} for
7356
+ * the per-tile value.
7278
7357
  */
7279
7358
  returnToParent?: boolean;
7280
7359
  /**
@@ -9284,7 +9363,12 @@ interface PptxSlideTransition {
9284
9363
  spokes?: number;
9285
9364
  /** Pattern type for shred transition. */
9286
9365
  pattern?: string;
9287
- /** Through-black flag for blinds/checker (OOXML `@_thruBlk`). */
9366
+ /**
9367
+ * Through-black flag (OOXML `@_thruBlk`). COM-verified to actually apply to
9368
+ * `cut` and `fade` (see {@link TRANSITION_THRUBLK_TYPES}); parsed generically
9369
+ * off any standard transition child so an unexpected authored value still
9370
+ * round-trips.
9371
+ */
9288
9372
  thruBlk?: boolean;
9289
9373
  /** Split orientation (horz/vert) parsed from `@_orient`. */
9290
9374
  orient?: PptxSplitOrientation;
@@ -12038,7 +12122,7 @@ interface ReflectionWrapperStyle {
12038
12122
  top: string;
12039
12123
  width: string;
12040
12124
  height: string;
12041
- /** Mirror (`scaleY(-1)`) composed with `@sx`/`@sy`/`@kx`/`@ky`/`@rot`. */
12125
+ /** `scale(@sx, @sy)` (the sign of `@sy` IS the mirror) composed with `@kx`/`@ky`/`@rot`. */
12042
12126
  transform: string;
12043
12127
  /** Anchor point for the transform above, from `@algn` (default `center top`). */
12044
12128
  transformOrigin: string;
@@ -13190,7 +13274,7 @@ declare const P14_TRANSITION_KEYFRAMES = "\n/* ── Conveyor (translate X with
13190
13274
  /** Part 2: prism / reveal / ripple / shred / switch / vortex / warp / wheelReverse / window. */
13191
13275
  declare const P14_TRANSITION_KEYFRAMES_2 = "\n/* ── Prism: see `slide-transition-prism` (split out to keep this module\n under the per-file LOC budget) ─────────────────────────────────────── */\n\n@keyframes pptx-tr-prism-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-bottom {\n\tfrom { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-top {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-top {\n\tfrom { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-bottom {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n}\n\n/* ── Reveal (slide away reveal) ──────────────────────────────────── */\n@keyframes pptx-tr-reveal-out-to-right {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(100%); }\n}\n@keyframes pptx-tr-reveal-out-to-left {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(-100%); }\n}\n/* MEASURED: the incoming layer stays hidden for roughly the first half of the\n transition (a real black/background gap shows through), then fades in -\n not a flat 0.5->1 fade running the whole duration. */\n@keyframes pptx-tr-reveal-in {\n\t0% { opacity: 0; }\n\t50% { opacity: 0; }\n\t100% { opacity: 1; }\n}\n\n/* ── Ripple (expanding ring clip-path) ───────────────────────────── */\n@keyframes pptx-tr-ripple-in {\n\tfrom { clip-path: circle(0% at 50% 50%); opacity: 0.5; }\n\t30% { clip-path: circle(20% at 50% 50%); opacity: 0.7; }\n\t60% { clip-path: circle(50% at 50% 50%); opacity: 0.9; }\n\tto { clip-path: circle(75% at 50% 50%); opacity: 1; }\n}\n\n/* ── Shred (fragmented clip-path pieces) ─────────────────────────── */\n@keyframes pptx-tr-shred-strips-in {\n\tfrom { clip-path: inset(0 100% 0 0); opacity: 0; }\n\t30% { clip-path: inset(0 60% 0 0); opacity: 0.5; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-rectangles-in {\n\tfrom { clip-path: inset(50%); opacity: 0; }\n\t40% { clip-path: inset(20%); opacity: 0.6; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-out {\n\tfrom { opacity: 1; }\n\tto { opacity: 0; filter: blur(2px); }\n}\n\n/* ── Switch (flip/rotate swap) ───────────────────────────────────── */\n@keyframes pptx-tr-switch-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n}\n@keyframes pptx-tr-switch-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n}\n\n/* ── Vortex (rotate + scale spiral) ──────────────────────────────── */\n@keyframes pptx-tr-vortex-in {\n\tfrom { transform: rotate(720deg) scale(0); opacity: 0; }\n\tto { transform: rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-vortex-out {\n\tfrom { transform: rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: rotate(-720deg) scale(0); opacity: 0; }\n}\n\n/* ── Warp: see `slide-transition-warp` (COM-measured radial zoom blur,\n split out to keep this module under the per-file LOC budget) ────────── */\n\n@keyframes pptx-tr-warp-in {\n\t0% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n}\n@keyframes pptx-tr-warp-reverse-in {\n\t0% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-reverse-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n}\n\n\n/* ── WheelReverse (reverse wheel rotation) ───────────────────────── */\n@keyframes pptx-tr-wheel-reverse-in {\n\tfrom { clip-path: circle(0% at 50% 50%); transform: rotate(180deg); }\n\tto { clip-path: circle(75% at 50% 50%); transform: rotate(0deg); }\n}\n\n/* ── Window (scale from center with border) ──────────────────────────\n Same measured horz/vert meaning as Doors above (horz = horizontal split\n line opening vertically; vert = vertical split line opening horizontally). */\n@keyframes pptx-tr-window-horz {\n\tfrom { clip-path: inset(50% 0); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-vert {\n\tfrom { clip-path: inset(0 50%); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-out {\n\tfrom { opacity: 1; transform: scale(1); }\n\tto { opacity: 0; transform: scale(0.9); }\n}\n";
13192
13276
  /** Both p14 keyframe blocks concatenated, for single `<style>` injection. */
13193
- declare const P14_TRANSITION_KEYFRAMES_ALL = "\n/* ── Conveyor (translate X with staggered timing) ──────────────────── */\n@keyframes pptx-tr-conveyor-in-from-right {\n\tfrom { transform: translateX(100%) rotateY(-30deg); }\n\t60% { transform: translateX(20%) rotateY(-10deg); }\n\tto { transform: translateX(0) rotateY(0deg); }\n}\n@keyframes pptx-tr-conveyor-out-to-left {\n\tfrom { transform: translateX(0) rotateY(0deg); }\n\t40% { transform: translateX(-20%) rotateY(10deg); }\n\tto { transform: translateX(-100%) rotateY(30deg); }\n}\n@keyframes pptx-tr-conveyor-in-from-left {\n\tfrom { transform: translateX(-100%) rotateY(30deg); }\n\t60% { transform: translateX(-20%) rotateY(10deg); }\n\tto { transform: translateX(0) rotateY(0deg); }\n}\n@keyframes pptx-tr-conveyor-out-to-right {\n\tfrom { transform: translateX(0) rotateY(0deg); }\n\t40% { transform: translateX(20%) rotateY(-10deg); }\n\tto { transform: translateX(100%) rotateY(-30deg); }\n}\n\n/* ── Doors (clip-path from center split) ──────────────────────────────\n MEASURED via COM CreateVideo: PowerPoint's `dir=\"horz\"` names a\n HORIZONTAL split line (two panels stacked top/bottom, opening upward and\n downward), and `dir=\"vert\"` a VERTICAL split line (panels side by side,\n opening left and right) - the opposite of what \"clips left/right\" vs\n \"clips top/bottom\" would suggest at a glance. Keep the clip-path bodies\n matched to the MEASURED direction, not the intuitive one. */\n@keyframes pptx-tr-doors-horz {\n\tfrom { clip-path: inset(50% 0); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-doors-vert {\n\tfrom { clip-path: inset(0 50%); }\n\tto { clip-path: inset(0 0); }\n}\n\n/* ── Ferris (rotate elements around center) ───────────────────────── */\n@keyframes pptx-tr-ferris-in-from-right {\n\tfrom { transform: translateX(80%) rotate(45deg) scale(0.6); opacity: 0; }\n\tto { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-ferris-out-to-left {\n\tfrom { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: translateX(-80%) rotate(-45deg) scale(0.6); opacity: 0; }\n}\n@keyframes pptx-tr-ferris-in-from-left {\n\tfrom { transform: translateX(-80%) rotate(-45deg) scale(0.6); opacity: 0; }\n\tto { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-ferris-out-to-right {\n\tfrom { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: translateX(80%) rotate(45deg) scale(0.6); opacity: 0; }\n}\n\n/* ── Flash (bright flash opacity burst) ──────────────────────────── */\n@keyframes pptx-tr-flash-white {\n\t0% { opacity: 1; }\n\t30% { opacity: 0; }\n\t50% { opacity: 0; }\n\t100% { opacity: 1; }\n}\n@keyframes pptx-tr-flash-in {\n\t0% { opacity: 0; }\n\t50% { opacity: 0; }\n\t70% { opacity: 1; }\n\t100% { opacity: 1; }\n}\n\n/* ── Flythrough (scale + translate Z-axis feel) ──────────────────── */\n@keyframes pptx-tr-flythrough-in {\n\tfrom { transform: scale(4) translateZ(200px); opacity: 0; filter: blur(8px); }\n\tto { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n}\n@keyframes pptx-tr-flythrough-out {\n\tfrom { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n\tto { transform: scale(0.1) translateZ(-200px); opacity: 0; filter: blur(8px); }\n}\n@keyframes pptx-tr-flythrough-reverse-in {\n\tfrom { transform: scale(0.1) translateZ(-200px); opacity: 0; filter: blur(8px); }\n\tto { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n}\n@keyframes pptx-tr-flythrough-reverse-out {\n\tfrom { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n\tto { transform: scale(4) translateZ(200px); opacity: 0; filter: blur(8px); }\n}\n\n/* ── Gallery (translate with perspective) ─────────────────────────── */\n@keyframes pptx-tr-gallery-in-from-right {\n\tfrom { transform: perspective(800px) translateX(100%) rotateY(-45deg); opacity: 0.5; }\n\tto { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-gallery-out-to-left {\n\tfrom { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) translateX(-100%) rotateY(45deg); opacity: 0.5; }\n}\n@keyframes pptx-tr-gallery-in-from-left {\n\tfrom { transform: perspective(800px) translateX(-100%) rotateY(45deg); opacity: 0.5; }\n\tto { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-gallery-out-to-right {\n\tfrom { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) translateX(100%) rotateY(-45deg); opacity: 0.5; }\n}\n\n/* ── Glitter (particle dissolve effect) ──────────────────────────── */\n@keyframes pptx-tr-glitter-in {\n\tfrom { opacity: 0; filter: brightness(1.5) contrast(1.3) blur(2px); }\n\t60% { opacity: 0.7; filter: brightness(1.2) contrast(1.1) blur(1px); }\n\tto { opacity: 1; filter: brightness(1) contrast(1) blur(0); }\n}\n\n/* ── Honeycomb (hexagonal reveal) ────────────────────────────────── */\n@keyframes pptx-tr-honeycomb-in {\n\tfrom {\n\t\tclip-path: polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%, 50% 50%, 50% 50%);\n\t\topacity: 0;\n\t}\n\tto {\n\t\tclip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);\n\t\topacity: 1;\n\t}\n}\n@keyframes pptx-tr-honeycomb-out {\n\tfrom { opacity: 1; }\n\tto { opacity: 0; filter: blur(2px); }\n}\n\n/* ── Pan (large-scale translate) ─────────────────────────────────── */\n@keyframes pptx-tr-pan-from-right {\n\tfrom { transform: translateX(100%); }\n\tto { transform: translateX(0); }\n}\n@keyframes pptx-tr-pan-to-left {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(-100%); }\n}\n@keyframes pptx-tr-pan-from-left {\n\tfrom { transform: translateX(-100%); }\n\tto { transform: translateX(0); }\n}\n@keyframes pptx-tr-pan-to-right {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(100%); }\n}\n@keyframes pptx-tr-pan-from-bottom {\n\tfrom { transform: translateY(100%); }\n\tto { transform: translateY(0); }\n}\n@keyframes pptx-tr-pan-to-top {\n\tfrom { transform: translateY(0); }\n\tto { transform: translateY(-100%); }\n}\n@keyframes pptx-tr-pan-from-top {\n\tfrom { transform: translateY(-100%); }\n\tto { transform: translateY(0); }\n}\n@keyframes pptx-tr-pan-to-bottom {\n\tfrom { transform: translateY(0); }\n\tto { transform: translateY(100%); }\n}\n\n\n/* ── Prism: see `slide-transition-prism` (split out to keep this module\n under the per-file LOC budget) ─────────────────────────────────────── */\n\n@keyframes pptx-tr-prism-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-bottom {\n\tfrom { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-top {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-top {\n\tfrom { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-bottom {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n}\n\n/* ── Reveal (slide away reveal) ──────────────────────────────────── */\n@keyframes pptx-tr-reveal-out-to-right {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(100%); }\n}\n@keyframes pptx-tr-reveal-out-to-left {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(-100%); }\n}\n/* MEASURED: the incoming layer stays hidden for roughly the first half of the\n transition (a real black/background gap shows through), then fades in -\n not a flat 0.5->1 fade running the whole duration. */\n@keyframes pptx-tr-reveal-in {\n\t0% { opacity: 0; }\n\t50% { opacity: 0; }\n\t100% { opacity: 1; }\n}\n\n/* ── Ripple (expanding ring clip-path) ───────────────────────────── */\n@keyframes pptx-tr-ripple-in {\n\tfrom { clip-path: circle(0% at 50% 50%); opacity: 0.5; }\n\t30% { clip-path: circle(20% at 50% 50%); opacity: 0.7; }\n\t60% { clip-path: circle(50% at 50% 50%); opacity: 0.9; }\n\tto { clip-path: circle(75% at 50% 50%); opacity: 1; }\n}\n\n/* ── Shred (fragmented clip-path pieces) ─────────────────────────── */\n@keyframes pptx-tr-shred-strips-in {\n\tfrom { clip-path: inset(0 100% 0 0); opacity: 0; }\n\t30% { clip-path: inset(0 60% 0 0); opacity: 0.5; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-rectangles-in {\n\tfrom { clip-path: inset(50%); opacity: 0; }\n\t40% { clip-path: inset(20%); opacity: 0.6; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-out {\n\tfrom { opacity: 1; }\n\tto { opacity: 0; filter: blur(2px); }\n}\n\n/* ── Switch (flip/rotate swap) ───────────────────────────────────── */\n@keyframes pptx-tr-switch-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n}\n@keyframes pptx-tr-switch-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n}\n\n/* ── Vortex (rotate + scale spiral) ──────────────────────────────── */\n@keyframes pptx-tr-vortex-in {\n\tfrom { transform: rotate(720deg) scale(0); opacity: 0; }\n\tto { transform: rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-vortex-out {\n\tfrom { transform: rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: rotate(-720deg) scale(0); opacity: 0; }\n}\n\n/* ── Warp: see `slide-transition-warp` (COM-measured radial zoom blur,\n split out to keep this module under the per-file LOC budget) ────────── */\n\n@keyframes pptx-tr-warp-in {\n\t0% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n}\n@keyframes pptx-tr-warp-reverse-in {\n\t0% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-reverse-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n}\n\n\n/* ── WheelReverse (reverse wheel rotation) ───────────────────────── */\n@keyframes pptx-tr-wheel-reverse-in {\n\tfrom { clip-path: circle(0% at 50% 50%); transform: rotate(180deg); }\n\tto { clip-path: circle(75% at 50% 50%); transform: rotate(0deg); }\n}\n\n/* ── Window (scale from center with border) ──────────────────────────\n Same measured horz/vert meaning as Doors above (horz = horizontal split\n line opening vertically; vert = vertical split line opening horizontally). */\n@keyframes pptx-tr-window-horz {\n\tfrom { clip-path: inset(50% 0); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-vert {\n\tfrom { clip-path: inset(0 50%); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-out {\n\tfrom { opacity: 1; transform: scale(1); }\n\tto { opacity: 0; transform: scale(0.9); }\n}\n";
13277
+ declare const P14_TRANSITION_KEYFRAMES_ALL = "\n/* ── Conveyor (translate X with staggered timing) ──────────────────── */\n@keyframes pptx-tr-conveyor-in-from-right {\n\tfrom { transform: translateX(100%) rotateY(-30deg); }\n\t60% { transform: translateX(20%) rotateY(-10deg); }\n\tto { transform: translateX(0) rotateY(0deg); }\n}\n@keyframes pptx-tr-conveyor-out-to-left {\n\tfrom { transform: translateX(0) rotateY(0deg); }\n\t40% { transform: translateX(-20%) rotateY(10deg); }\n\tto { transform: translateX(-100%) rotateY(30deg); }\n}\n@keyframes pptx-tr-conveyor-in-from-left {\n\tfrom { transform: translateX(-100%) rotateY(30deg); }\n\t60% { transform: translateX(-20%) rotateY(10deg); }\n\tto { transform: translateX(0) rotateY(0deg); }\n}\n@keyframes pptx-tr-conveyor-out-to-right {\n\tfrom { transform: translateX(0) rotateY(0deg); }\n\t40% { transform: translateX(20%) rotateY(-10deg); }\n\tto { transform: translateX(100%) rotateY(-30deg); }\n}\n\n/* ── Doors (clip-path from center split) ──────────────────────────────\n MEASURED via COM CreateVideo: PowerPoint's `dir=\"horz\"` names a\n HORIZONTAL split line (two panels stacked top/bottom, opening upward and\n downward), and `dir=\"vert\"` a VERTICAL split line (panels side by side,\n opening left and right) - the opposite of what \"clips left/right\" vs\n \"clips top/bottom\" would suggest at a glance. Keep the clip-path bodies\n matched to the MEASURED direction, not the intuitive one. */\n@keyframes pptx-tr-doors-horz {\n\tfrom { clip-path: inset(50% 0); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-doors-vert {\n\tfrom { clip-path: inset(0 50%); }\n\tto { clip-path: inset(0 0); }\n}\n\n/* ── Ferris (rotate elements around center) ───────────────────────── */\n@keyframes pptx-tr-ferris-in-from-right {\n\tfrom { transform: translateX(80%) rotate(45deg) scale(0.6); opacity: 0; }\n\tto { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-ferris-out-to-left {\n\tfrom { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: translateX(-80%) rotate(-45deg) scale(0.6); opacity: 0; }\n}\n@keyframes pptx-tr-ferris-in-from-left {\n\tfrom { transform: translateX(-80%) rotate(-45deg) scale(0.6); opacity: 0; }\n\tto { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-ferris-out-to-right {\n\tfrom { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: translateX(80%) rotate(45deg) scale(0.6); opacity: 0; }\n}\n\n/* ── Flash (bright flash opacity burst) ──────────────────────────── */\n@keyframes pptx-tr-flash-white {\n\t0% { opacity: 1; }\n\t30% { opacity: 0; }\n\t50% { opacity: 0; }\n\t100% { opacity: 1; }\n}\n@keyframes pptx-tr-flash-in {\n\t0% { opacity: 0; }\n\t50% { opacity: 0; }\n\t70% { opacity: 1; }\n\t100% { opacity: 1; }\n}\n\n/* ── Flythrough (scale + translate Z-axis feel) ──────────────────── */\n@keyframes pptx-tr-flythrough-in {\n\tfrom { transform: scale(4) translateZ(200px); opacity: 0; filter: blur(8px); }\n\tto { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n}\n@keyframes pptx-tr-flythrough-out {\n\tfrom { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n\tto { transform: scale(0.1) translateZ(-200px); opacity: 0; filter: blur(8px); }\n}\n@keyframes pptx-tr-flythrough-reverse-in {\n\tfrom { transform: scale(0.1) translateZ(-200px); opacity: 0; filter: blur(8px); }\n\tto { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n}\n@keyframes pptx-tr-flythrough-reverse-out {\n\tfrom { transform: scale(1) translateZ(0); opacity: 1; filter: blur(0); }\n\tto { transform: scale(4) translateZ(200px); opacity: 0; filter: blur(8px); }\n}\n\n/* ── Gallery (translate with perspective) ─────────────────────────── */\n@keyframes pptx-tr-gallery-in-from-right {\n\tfrom { transform: perspective(800px) translateX(100%) rotateY(-45deg); opacity: 0.5; }\n\tto { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-gallery-out-to-left {\n\tfrom { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) translateX(-100%) rotateY(45deg); opacity: 0.5; }\n}\n@keyframes pptx-tr-gallery-in-from-left {\n\tfrom { transform: perspective(800px) translateX(-100%) rotateY(45deg); opacity: 0.5; }\n\tto { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-gallery-out-to-right {\n\tfrom { transform: perspective(800px) translateX(0) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) translateX(100%) rotateY(-45deg); opacity: 0.5; }\n}\n\n/* ── Glitter (particle dissolve effect) ──────────────────────────── */\n@keyframes pptx-tr-glitter-in {\n\tfrom { opacity: 0; filter: brightness(1.5) contrast(1.3) blur(2px); }\n\t60% { opacity: 0.7; filter: brightness(1.2) contrast(1.1) blur(1px); }\n\tto { opacity: 1; filter: brightness(1) contrast(1) blur(0); }\n}\n\n/* ── Honeycomb (hexagonal reveal) ────────────────────────────────── */\n@keyframes pptx-tr-honeycomb-in {\n\tfrom {\n\t\tclip-path: polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%, 50% 50%, 50% 50%);\n\t\topacity: 0;\n\t}\n\tto {\n\t\tclip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);\n\t\topacity: 1;\n\t}\n}\n@keyframes pptx-tr-honeycomb-out {\n\tfrom { opacity: 1; }\n\tto { opacity: 0; filter: blur(2px); }\n}\n\n/* ── Pan (large-scale translate) ─────────────────────────────────── */\n@keyframes pptx-tr-pan-from-right {\n\tfrom { transform: translateX(100%); }\n\tto { transform: translateX(0); }\n}\n@keyframes pptx-tr-pan-to-left {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(-100%); }\n}\n@keyframes pptx-tr-pan-from-left {\n\tfrom { transform: translateX(-100%); }\n\tto { transform: translateX(0); }\n}\n@keyframes pptx-tr-pan-to-right {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(100%); }\n}\n@keyframes pptx-tr-pan-from-bottom {\n\tfrom { transform: translateY(100%); }\n\tto { transform: translateY(0); }\n}\n@keyframes pptx-tr-pan-to-top {\n\tfrom { transform: translateY(0); }\n\tto { transform: translateY(-100%); }\n}\n@keyframes pptx-tr-pan-from-top {\n\tfrom { transform: translateY(-100%); }\n\tto { transform: translateY(0); }\n}\n@keyframes pptx-tr-pan-to-bottom {\n\tfrom { transform: translateY(0); }\n\tto { transform: translateY(100%); }\n}\n\n\n/* ── Prism: see `slide-transition-prism` (split out to keep this module\n under the per-file LOC budget) ─────────────────────────────────────── */\n\n@keyframes pptx-tr-prism-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(90deg) translateX(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg) translateX(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-90deg) translateX(50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-bottom {\n\tfrom { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-top {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n}\n@keyframes pptx-tr-prism-in-from-top {\n\tfrom { transform: perspective(800px) rotateX(-90deg) translateY(-50%); opacity: 0; }\n\tto { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n}\n@keyframes pptx-tr-prism-out-to-bottom {\n\tfrom { transform: perspective(800px) rotateX(0deg) translateY(0); opacity: 1; }\n\tto { transform: perspective(800px) rotateX(90deg) translateY(50%); opacity: 0; }\n}\n\n/* ── Reveal (slide away reveal) ──────────────────────────────────── */\n@keyframes pptx-tr-reveal-out-to-right {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(100%); }\n}\n@keyframes pptx-tr-reveal-out-to-left {\n\tfrom { transform: translateX(0); }\n\tto { transform: translateX(-100%); }\n}\n/* MEASURED: the incoming layer stays hidden for roughly the first half of the\n transition (a real black/background gap shows through), then fades in -\n not a flat 0.5->1 fade running the whole duration. */\n@keyframes pptx-tr-reveal-in {\n\t0% { opacity: 0; }\n\t50% { opacity: 0; }\n\t100% { opacity: 1; }\n}\n\n/* ── Ripple (expanding ring clip-path) ───────────────────────────── */\n@keyframes pptx-tr-ripple-in {\n\tfrom { clip-path: circle(0% at 50% 50%); opacity: 0.5; }\n\t30% { clip-path: circle(20% at 50% 50%); opacity: 0.7; }\n\t60% { clip-path: circle(50% at 50% 50%); opacity: 0.9; }\n\tto { clip-path: circle(75% at 50% 50%); opacity: 1; }\n}\n\n/* ── Shred (fragmented clip-path pieces) ─────────────────────────── */\n@keyframes pptx-tr-shred-strips-in {\n\tfrom { clip-path: inset(0 100% 0 0); opacity: 0; }\n\t30% { clip-path: inset(0 60% 0 0); opacity: 0.5; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-rectangles-in {\n\tfrom { clip-path: inset(50%); opacity: 0; }\n\t40% { clip-path: inset(20%); opacity: 0.6; }\n\tto { clip-path: inset(0); opacity: 1; }\n}\n@keyframes pptx-tr-shred-out {\n\tfrom { opacity: 1; }\n\tto { opacity: 0; filter: blur(2px); }\n}\n\n/* ── Switch (flip/rotate swap) ───────────────────────────────────── */\n@keyframes pptx-tr-switch-in-from-right {\n\tfrom { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-left {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n}\n@keyframes pptx-tr-switch-in-from-left {\n\tfrom { transform: perspective(800px) rotateY(180deg); opacity: 0; }\n\tto { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n}\n@keyframes pptx-tr-switch-out-to-right {\n\tfrom { transform: perspective(800px) rotateY(0deg); opacity: 1; }\n\tto { transform: perspective(800px) rotateY(-180deg); opacity: 0; }\n}\n\n/* ── Vortex (rotate + scale spiral) ──────────────────────────────── */\n@keyframes pptx-tr-vortex-in {\n\tfrom { transform: rotate(720deg) scale(0); opacity: 0; }\n\tto { transform: rotate(0deg) scale(1); opacity: 1; }\n}\n@keyframes pptx-tr-vortex-out {\n\tfrom { transform: rotate(0deg) scale(1); opacity: 1; }\n\tto { transform: rotate(-720deg) scale(0); opacity: 0; }\n}\n\n/* ── Warp: see `slide-transition-warp` (COM-measured radial zoom blur,\n split out to keep this module under the per-file LOC budget) ────────── */\n\n@keyframes pptx-tr-warp-in {\n\t0% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(0.85); opacity: 0.7; filter: blur(3px) brightness(1.3); }\n\t100% { transform: scale(0.25); opacity: 0; filter: blur(10px) brightness(1.8); }\n}\n@keyframes pptx-tr-warp-reverse-in {\n\t0% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n}\n@keyframes pptx-tr-warp-reverse-out {\n\t0% { transform: scale(1); opacity: 1; filter: blur(0) brightness(1); }\n\t50% { transform: scale(1.7); opacity: 0.7; filter: blur(6px) brightness(1.5); }\n\t100% { transform: scale(3.2); opacity: 0; filter: blur(14px) brightness(2.2); }\n}\n\n\n/* ── WheelReverse (reverse wheel rotation) ───────────────────────── */\n@keyframes pptx-tr-wheel-reverse-in {\n\tfrom { clip-path: circle(0% at 50% 50%); transform: rotate(180deg); }\n\tto { clip-path: circle(75% at 50% 50%); transform: rotate(0deg); }\n}\n\n/* ── Window (scale from center with border) ──────────────────────────\n Same measured horz/vert meaning as Doors above (horz = horizontal split\n line opening vertically; vert = vertical split line opening horizontally). */\n@keyframes pptx-tr-window-horz {\n\tfrom { clip-path: inset(50% 0); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-vert {\n\tfrom { clip-path: inset(0 50%); }\n\tto { clip-path: inset(0 0); }\n}\n@keyframes pptx-tr-window-out {\n\tfrom { opacity: 1; transform: scale(1); }\n\tto { opacity: 0; transform: scale(0.9); }\n}\n\n\n@keyframes pptx-tr-vortex-in-left { from { transform: translateX(-40%) rotate(720deg) scale(0); opacity: 0; } to { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; } }\n@keyframes pptx-tr-vortex-out-left { from { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; } to { transform: translateX(-40%) rotate(-720deg) scale(0); opacity: 0; } }\n@keyframes pptx-tr-vortex-in-right { from { transform: translateX(40%) rotate(-720deg) scale(0); opacity: 0; } to { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; } }\n@keyframes pptx-tr-vortex-out-right { from { transform: translateX(0) rotate(0deg) scale(1); opacity: 1; } to { transform: translateX(40%) rotate(720deg) scale(0); opacity: 0; } }\n@keyframes pptx-tr-vortex-in-up { from { transform: translateY(-40%) rotate(720deg) scale(0); opacity: 0; } to { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; } }\n@keyframes pptx-tr-vortex-out-up { from { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; } to { transform: translateY(-40%) rotate(-720deg) scale(0); opacity: 0; } }\n@keyframes pptx-tr-vortex-in-down { from { transform: translateY(40%) rotate(-720deg) scale(0); opacity: 0; } to { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; } }\n@keyframes pptx-tr-vortex-out-down { from { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; } to { transform: translateY(40%) rotate(720deg) scale(0); opacity: 0; } }\n\n\n@keyframes pptx-tr-ripple-in-lu { from { clip-path: circle(0% at 0% 0%); opacity: 0.5; } 30% { clip-path: circle(20% at 0% 0%); opacity: 0.7; } 60% { clip-path: circle(55% at 0% 0%); opacity: 0.9; } to { clip-path: circle(150% at 0% 0%); opacity: 1; } }\n@keyframes pptx-tr-ripple-in-ru { from { clip-path: circle(0% at 100% 0%); opacity: 0.5; } 30% { clip-path: circle(20% at 100% 0%); opacity: 0.7; } 60% { clip-path: circle(55% at 100% 0%); opacity: 0.9; } to { clip-path: circle(150% at 100% 0%); opacity: 1; } }\n@keyframes pptx-tr-ripple-in-ld { from { clip-path: circle(0% at 0% 100%); opacity: 0.5; } 30% { clip-path: circle(20% at 0% 100%); opacity: 0.7; } 60% { clip-path: circle(55% at 0% 100%); opacity: 0.9; } to { clip-path: circle(150% at 0% 100%); opacity: 1; } }\n@keyframes pptx-tr-ripple-in-rd { from { clip-path: circle(0% at 100% 100%); opacity: 0.5; } 30% { clip-path: circle(20% at 100% 100%); opacity: 0.7; } 60% { clip-path: circle(55% at 100% 100%); opacity: 0.9; } to { clip-path: circle(150% at 100% 100%); opacity: 1; } }\n\n\n@keyframes pptx-tr-glitter-diamond-in-l { from { opacity: 0; transform: translateX(-6%); filter: brightness(1.5) contrast(1.3) blur(2px); } 60% { opacity: 0.7; transform: translateX(-2%); filter: brightness(1.2) contrast(1.1) blur(1px); } to { opacity: 1; transform: translateX(0); filter: brightness(1) contrast(1) blur(0); } }\n@keyframes pptx-tr-glitter-diamond-in-r { from { opacity: 0; transform: translateX(6%); filter: brightness(1.5) contrast(1.3) blur(2px); } 60% { opacity: 0.7; transform: translateX(2%); filter: brightness(1.2) contrast(1.1) blur(1px); } to { opacity: 1; transform: translateX(0); filter: brightness(1) contrast(1) blur(0); } }\n@keyframes pptx-tr-glitter-diamond-in-u { from { opacity: 0; transform: translateY(-6%); filter: brightness(1.5) contrast(1.3) blur(2px); } 60% { opacity: 0.7; transform: translateY(-2%); filter: brightness(1.2) contrast(1.1) blur(1px); } to { opacity: 1; transform: translateY(0); filter: brightness(1) contrast(1) blur(0); } }\n@keyframes pptx-tr-glitter-diamond-in-d { from { opacity: 0; transform: translateY(6%); filter: brightness(1.5) contrast(1.3) blur(2px); } 60% { opacity: 0.7; transform: translateY(2%); filter: brightness(1.2) contrast(1.1) blur(1px); } to { opacity: 1; transform: translateY(0); filter: brightness(1) contrast(1) blur(0); } }\n@keyframes pptx-tr-glitter-hexagon-in-l { from { opacity: 0; transform: translateX(-6%); filter: brightness(1.5) contrast(1.3) blur(2px) hue-rotate(20deg); } 60% { opacity: 0.7; transform: translateX(-2%); filter: brightness(1.2) contrast(1.1) blur(1px) hue-rotate(8deg); } to { opacity: 1; transform: translateX(0); filter: brightness(1) contrast(1) blur(0) hue-rotate(0deg); } }\n@keyframes pptx-tr-glitter-hexagon-in-r { from { opacity: 0; transform: translateX(6%); filter: brightness(1.5) contrast(1.3) blur(2px) hue-rotate(20deg); } 60% { opacity: 0.7; transform: translateX(2%); filter: brightness(1.2) contrast(1.1) blur(1px) hue-rotate(8deg); } to { opacity: 1; transform: translateX(0); filter: brightness(1) contrast(1) blur(0) hue-rotate(0deg); } }\n@keyframes pptx-tr-glitter-hexagon-in-u { from { opacity: 0; transform: translateY(-6%); filter: brightness(1.5) contrast(1.3) blur(2px) hue-rotate(20deg); } 60% { opacity: 0.7; transform: translateY(-2%); filter: brightness(1.2) contrast(1.1) blur(1px) hue-rotate(8deg); } to { opacity: 1; transform: translateY(0); filter: brightness(1) contrast(1) blur(0) hue-rotate(0deg); } }\n@keyframes pptx-tr-glitter-hexagon-in-d { from { opacity: 0; transform: translateY(6%); filter: brightness(1.5) contrast(1.3) blur(2px) hue-rotate(20deg); } 60% { opacity: 0.7; transform: translateY(2%); filter: brightness(1.2) contrast(1.1) blur(1px) hue-rotate(8deg); } to { opacity: 1; transform: translateY(0); filter: brightness(1) contrast(1) blur(0) hue-rotate(0deg); } }\n";
13194
13278
  //#endregion
13195
13279
  //#region src/render/p14-transition-css.d.ts
13196
13280
  /**
@@ -13271,6 +13355,10 @@ interface PresentationInkStroke {
13271
13355
  points: PresentationInkPoint[];
13272
13356
  }
13273
13357
  //#endregion
13358
+ //#region src/render/paste-special.d.ts
13359
+ /** The four paste formats PowerPoint's Paste Options / Paste Special offer. */
13360
+ type PasteSpecialFormat = 'keep-source-formatting' | 'use-destination-theme' | 'picture' | 'keep-text-only';
13361
+ //#endregion
13274
13362
  //#region src/render/find-replace.d.ts
13275
13363
  /** Identifies a single match of the find query at segment-level precision. */
13276
13364
  interface FindResult {
@@ -13343,6 +13431,37 @@ interface FontEmbeddingDescriptor {
13343
13431
  /** Present only when `interactive` is false. */
13344
13432
  disabledReasonKey?: string;
13345
13433
  }
13434
+ //#endregion
13435
+ //#region src/render/zoom-return-navigation.d.ts
13436
+ /**
13437
+ * The navigation-relevant fields of a Zoom click target, independent of
13438
+ * `zoomType`.
13439
+ *
13440
+ * `returnToParent` is already resolved to its EFFECTIVE value here (not the
13441
+ * raw, possibly-`undefined` `ZoomPptxElement`/`SummaryZoomTarget` field):
13442
+ * `CT_ZoomObjectProperties/@returnToParent` (MS-PPTX) is `<xsd:attribute
13443
+ * name="returnToParent" type="xsd:boolean" use="optional" default="true"/>`,
13444
+ * so an ABSENT attribute means true, not false. Core deliberately stores
13445
+ * `undefined` rather than fabricating `true` (so a round-trip never invents
13446
+ * an attribute the source never had), which makes `Boolean(x)` the wrong way
13447
+ * to read it; the two `resolve*NavigationTarget` functions below are the only
13448
+ * place that distinction should be made.
13449
+ */
13450
+ interface ZoomNavigationTarget {
13451
+ targetSlideIndex: number;
13452
+ targetSectionId?: string;
13453
+ returnToParent: boolean;
13454
+ transitionDurationMs?: number;
13455
+ }
13456
+ /** A pending "return to the zoom's origin slide" excursion, tracked by the binding across forward-advance steps. */
13457
+ interface ZoomExcursion {
13458
+ /** The slide to jump back to once `endSlideIndex` is passed (the slide the zoom was clicked from). */
13459
+ returnSlideIndex: number;
13460
+ /** The last slide index of the zoom's target range; see {@link resolveZoomExcursionEndIndex}. */
13461
+ endSlideIndex: number;
13462
+ /** The zoom's own `transitionDur`, applied to the jump INTO the target and to the return jump. */
13463
+ transitionDurationMs?: number;
13464
+ }
13346
13465
  /** Everything a binding needs to render the recovery dialog, and nothing else. */
13347
13466
  interface AutosaveRecoveryPrompt {
13348
13467
  /** IndexedDB key the snapshot is stored under (the deck's file path/name). */
@@ -13978,8 +14097,13 @@ interface ElementContextMenuState {
13978
14097
  y: number;
13979
14098
  elementId: string;
13980
14099
  }
14100
+ /** Tracks the position of an open empty-canvas (no element hit) context menu. */
14101
+ interface CanvasContextMenuState {
14102
+ x: number;
14103
+ y: number;
14104
+ }
13981
14105
  /** Identifies an action triggered from the element right-click context menu. */
13982
- type ElementContextMenuAction = 'copy' | 'cut' | 'paste' | 'duplicate' | 'delete' | 'bring-forward' | 'send-backward' | 'bring-front' | 'send-back' | 'bringForward' | 'sendBackward' | 'bringToFront' | 'sendToBack' | 'comment' | 'addComment' | 'group' | 'ungroup' | 'editPoints' | 'editHyperlink';
14106
+ type ElementContextMenuAction = 'copy' | 'cut' | 'paste' | 'duplicate' | 'delete' | 'bring-forward' | 'send-backward' | 'bring-front' | 'send-back' | 'bringForward' | 'sendBackward' | 'bringToFront' | 'sendToBack' | 'comment' | 'addComment' | 'group' | 'ungroup' | 'editPoints' | 'editHyperlink' | 'edit-text' | 'save-as-picture' | 'edit-alt-text' | 'size-and-position' | 'format-shape';
13983
14107
  /**
13984
14108
  * State of an active marquee (rubber-band) selection rectangle.
13985
14109
  * Created when the user clicks and drags on the canvas background,
@@ -14318,6 +14442,7 @@ interface CanvasInteractionHandlers {
14318
14442
  handleElementDoubleClick: (elementId: string, e: React.MouseEvent) => void;
14319
14443
  handleElementMouseDown: (elementId: string, e: React.MouseEvent) => void;
14320
14444
  handleElementContextMenu: (elementId: string, e: React.MouseEvent) => void;
14445
+ handleCanvasContextMenu: (e: React.MouseEvent) => void;
14321
14446
  handleCanvasMouseDown: (e: React.MouseEvent) => void;
14322
14447
  handleResizePointerDown: (elementId: string, e: React.MouseEvent, handle: string) => void;
14323
14448
  handleAdjustmentPointerDown: (elementId: string, e: React.MouseEvent, descriptor: ShapeAdjustmentHandleDescriptor) => void;
@@ -14497,6 +14622,7 @@ interface UseCanvasInteractionsInput {
14497
14622
  setInlineEditingElementId: React.Dispatch<React.SetStateAction<string | null>>;
14498
14623
  setInlineEditingText: React.Dispatch<React.SetStateAction<string>>;
14499
14624
  setContextMenuState: React.Dispatch<React.SetStateAction<ElementContextMenuState | null>>;
14625
+ setCanvasContextMenuState: React.Dispatch<React.SetStateAction<CanvasContextMenuState | null>>;
14500
14626
  setMarqueeSelectionState: React.Dispatch<React.SetStateAction<MarqueeSelectionState | null>>;
14501
14627
  setSnapLines: React.Dispatch<React.SetStateAction<Array<{
14502
14628
  axis: string;
@@ -14593,6 +14719,25 @@ interface UseElementManipulationInput {
14593
14719
  ops: ElementOperations;
14594
14720
  history: EditorHistoryResult;
14595
14721
  onOpenHyperlinkDialog: () => void;
14722
+ /**
14723
+ * Enter inline text edit for `elementId`, same as double-clicking it.
14724
+ * Wired to `canvasHandlers.handleElementDoubleClick`; omitted (never) in
14725
+ * production, only in tests that do not exercise "Edit Text".
14726
+ */
14727
+ onEditText?: (elementId: string) => void;
14728
+ /**
14729
+ * Rasterise `elementId`'s own DOM node and download it as PNG ("Save as
14730
+ * Picture"). Lives outside this hook because it needs the binding's
14731
+ * `html2canvasFallback` driver and a DOM lookup, neither of which this
14732
+ * hook otherwise touches.
14733
+ */
14734
+ onSaveElementAsPicture?: (elementId: string) => void;
14735
+ /**
14736
+ * Notified with the freshly-inserted clone after an ordinary paste, so the
14737
+ * Paste Options mini-toolbar (`usePasteSpecial`) has something to reformat.
14738
+ * Not called for Duplicate: PowerPoint's toolbar only follows a paste.
14739
+ */
14740
+ onPasted?: (element: PptxElement) => void;
14596
14741
  }
14597
14742
  interface ElementManipulationHandlers {
14598
14743
  handleCopy: () => void;
@@ -14714,6 +14859,28 @@ interface InsertElementHandlers {
14714
14859
  }
14715
14860
  declare function useInsertElements(input: UseInsertElementsInput): InsertElementHandlers;
14716
14861
  //#endregion
14862
+ //#region src/viewer/hooks/usePasteSpecial.d.ts
14863
+ /** The pasted element the "Paste Options" toolbar is currently anchored to. */
14864
+ interface PasteOptionsToolbarState {
14865
+ elementId: string;
14866
+ /** The pristine "Keep Source Formatting" clone every choice re-derives from. */
14867
+ sourceClone: PptxElement;
14868
+ }
14869
+ interface UsePasteSpecialResult {
14870
+ isPasteSpecialDialogOpen: boolean;
14871
+ openPasteSpecialDialog: () => void;
14872
+ closePasteSpecialDialog: () => void;
14873
+ /** Ctrl+Alt+V / dialog OK: paste the clipboard element in the chosen format. */
14874
+ pasteWithFormat: (format: PasteSpecialFormat) => Promise<void>;
14875
+ /** The Paste Options toolbar shown right after an ordinary Ctrl+V paste. */
14876
+ pasteOptionsToolbar: PasteOptionsToolbarState | null;
14877
+ /** Record an ordinary paste's result so the toolbar has something to reformat. */
14878
+ notePastedElement: (element: PptxElement) => void;
14879
+ /** Re-derive the pasted element in `format` from the frozen source clone. */
14880
+ reformatPastedElement: (format: PasteSpecialFormat) => Promise<void>;
14881
+ dismissPasteOptionsToolbar: () => void;
14882
+ }
14883
+ //#endregion
14717
14884
  //#region src/viewer/hooks/presentation-mode/useCustomShowRunner.d.ts
14718
14885
  /**
14719
14886
  * useCustomShowRunner: the runtime side of `ppaction://customshow?id=<id>[&return=true]`.
@@ -14884,7 +15051,7 @@ interface UsePresentationModeResult {
14884
15051
  openAllSlides: () => void;
14885
15052
  closeAllSlides: () => void;
14886
15053
  movePresentationSlide: (direction: 1 | -1, trigger?: SlideAdvanceTrigger) => void;
14887
- navigateToSlide: (slideIndex: number) => void;
15054
+ navigateToSlide: (slideIndex: number, transitionOverride?: PptxSlideTransition) => void;
14888
15055
  /** `elementId` is the clicked element, for the verbs that act on it (`playMedia`, `oleVerb`). */
14889
15056
  handlePresentationAction: (action: PptxAction, elementId?: string) => void;
14890
15057
  /**
@@ -14934,13 +15101,14 @@ interface UsePresentationModeResult {
14934
15101
  rehearsalPaused: boolean;
14935
15102
  /** Toggle the rehearsal timer pause state. */
14936
15103
  toggleRehearsalPause: () => void;
14937
- /** Handle a zoom element click in presentation mode. */
14938
- handleZoomClick: (targetSlideIndex: number, returnSlideIndex: number) => void;
14939
- /** Ref holding the slide index to return to after zoom navigation. */
14940
- zoomReturnSlideIndex: React.RefObject<number | null>;
14941
- /** Navigate back to the zoom summary slide. Returns true if navigation occurred. */
14942
- returnToZoomSlide: () => boolean;
14943
- /** Clear the stored zoom return index. */
15104
+ /**
15105
+ * Handle a zoom element (or Summary Zoom tile) click in presentation mode:
15106
+ * navigates to the target, applying its own `zmPr/@transitionDur`, and (when
15107
+ * `returnToParent` is set) arms an automatic return once the show reaches
15108
+ * the end of the target's range. See `useZoomNavigation` / `useSlideNavigation`.
15109
+ */
15110
+ handleZoomClick: (target: ZoomNavigationTarget, returnSlideIndex: number) => void;
15111
+ /** Clear a pending "return to zoom" excursion (e.g. when presentation mode ends). */
14944
15112
  clearZoomReturn: () => void;
14945
15113
  /** Open the audience display in a separate browser window. Returns `true` if successful. */
14946
15114
  openAudienceWindow: () => boolean;
@@ -15534,6 +15702,9 @@ interface ViewerUIState {
15534
15702
  setAccessibilityIssues: React.Dispatch<React.SetStateAction<AccessibilityIssue[]>>;
15535
15703
  contextMenuState: ElementContextMenuState | null;
15536
15704
  setContextMenuState: React.Dispatch<React.SetStateAction<ElementContextMenuState | null>>;
15705
+ /** The empty-canvas (no element hit) right-click menu; mutually exclusive with `contextMenuState`. */
15706
+ canvasContextMenuState: CanvasContextMenuState | null;
15707
+ setCanvasContextMenuState: React.Dispatch<React.SetStateAction<CanvasContextMenuState | null>>;
15537
15708
  tableEditorState: TableCellEditorState | null;
15538
15709
  setTableEditorState: React.Dispatch<React.SetStateAction<TableCellEditorState | null>>;
15539
15710
  spellCheckEnabled: boolean;
@@ -15652,6 +15823,8 @@ interface EditorOperationsResult {
15652
15823
  canvasHandlers: CanvasInteractionHandlers;
15653
15824
  insertHandlers: InsertElementHandlers;
15654
15825
  manipulation: ElementManipulationHandlers;
15826
+ /** Paste Special (Ctrl+Alt+V) dialog + the post-paste Paste Options toolbar. */
15827
+ pasteSpecial: UsePasteSpecialResult;
15655
15828
  slideOps: SlideManagementHandlers;
15656
15829
  tableOps: TableOperationHandlers;
15657
15830
  /**
@@ -15744,6 +15917,8 @@ interface SlideCanvasProps {
15744
15917
  onContextMenu: (elementId: string, e: React$1.MouseEvent) => void;
15745
15918
  /** Called when the user presses mouse down on empty canvas space. */
15746
15919
  onCanvasMouseDown?: (e: React$1.MouseEvent) => void;
15920
+ /** Right-click on empty canvas (no element hit); opens the canvas context menu. */
15921
+ onCanvasContextMenu?: (e: React$1.MouseEvent) => void;
15747
15922
  onResizePointerDown: (elementId: string, e: React$1.MouseEvent, handle: string) => void;
15748
15923
  onAdjustmentPointerDown: (elementId: string, e: React$1.MouseEvent, descriptor: ShapeAdjustmentHandleDescriptor) => void;
15749
15924
  /** Commit a new rotation (degrees) when the on-canvas rotate handle is dragged. */
@@ -15822,7 +15997,7 @@ interface SlideCanvasProps {
15822
15997
  /** All slides in the presentation (for zoom element thumbnails). */
15823
15998
  allSlides?: readonly PptxSlide[];
15824
15999
  /** Callback fired when a zoom element is clicked in presentation mode. */
15825
- onZoomClick?: (targetSlideIndex: number, returnSlideIndex: number) => void;
16000
+ onZoomClick?: (target: ZoomNavigationTarget, returnSlideIndex: number) => void;
15826
16001
  /** Index of the current slide (for zoom return navigation). */
15827
16002
  sourceSlideIndex?: number;
15828
16003
  /** Context for text field placeholder substitution (slide number, header/footer, etc.). */
@@ -17218,6 +17393,8 @@ interface UseKeyboardShortcutWiringInput {
17218
17393
  copyFormatFromSelection: () => void;
17219
17394
  /** Ctrl/Cmd+Shift+V: apply the copied format to the given element ids. */
17220
17395
  pasteFormatToSelection: (targetIds: string[]) => void;
17396
+ /** Ctrl/Cmd+Alt+V: open the Paste Special dialog. */
17397
+ onPasteSpecial: () => void;
17221
17398
  }
17222
17399
  declare function useKeyboardShortcutWiring(input: UseKeyboardShortcutWiringInput): void;
17223
17400
  //#endregion
@@ -17542,6 +17719,8 @@ interface ClipboardInput {
17542
17719
  } | null>>;
17543
17720
  ops: ElementOperations;
17544
17721
  history: EditorHistoryResult;
17722
+ /** Notified with the freshly-inserted clone after an ordinary paste. */
17723
+ onPasted?: (element: PptxElement) => void;
17545
17724
  }
17546
17725
  declare function useClipboardHandlers(input: ClipboardInput): ClipboardHandlers;
17547
17726
  //#endregion
@@ -17757,6 +17936,8 @@ interface UseKeyboardShortcutsInput {
17757
17936
  onCycleSelectionNext?: () => void;
17758
17937
  /** Shift+Tab: select the previous element on the slide. */
17759
17938
  onCycleSelectionPrev?: () => void;
17939
+ /** Ctrl/Cmd+Alt+V: open the Paste Special dialog. */
17940
+ onPasteSpecial?: () => void;
17760
17941
  }
17761
17942
  declare function useKeyboardShortcuts(input: UseKeyboardShortcutsInput): void;
17762
17943
  //#endregion
@@ -17998,10 +18179,18 @@ interface UseSlideNavigationInput {
17998
18179
  onOleVerb?: (verb: number, elementId: string | undefined) => void;
17999
18180
  /** `ppaction://program`. */
18000
18181
  onRunProgram?: (target: string) => void;
18182
+ /**
18183
+ * A pending "return to zoom" excursion armed by `useZoomNavigation`'s
18184
+ * `handleZoomClick`. Consulted on every forward advance: once the show
18185
+ * reaches `excursion.endSlideIndex`, the step jumps back to
18186
+ * `excursion.returnSlideIndex` (playing the zoom's own `transitionDur`)
18187
+ * instead of continuing linearly through the deck.
18188
+ */
18189
+ zoomExcursionRef: React.RefObject<ZoomExcursion | undefined>;
18001
18190
  }
18002
18191
  interface UseSlideNavigationResult {
18003
18192
  movePresentationSlide: (direction: 1 | -1, trigger?: SlideAdvanceTrigger) => void;
18004
- navigateToSlide: (slideIndex: number) => void;
18193
+ navigateToSlide: (slideIndex: number, transitionOverride?: PptxSlideTransition) => void;
18005
18194
  /** `elementId` is the clicked element, for the verbs that act on it (`playMedia`, `oleVerb`). */
18006
18195
  handlePresentationAction: (action: PptxAction, elementId?: string) => void;
18007
18196
  scheduleAutoAdvanceForSlide: (slideIndex: number) => void;
@@ -18013,43 +18202,38 @@ declare function useSlideNavigation(input: UseSlideNavigationInput): UseSlideNav
18013
18202
  * Input for the useZoomNavigation sub-hook.
18014
18203
  */
18015
18204
  interface UseZoomNavigationInput {
18016
- /** Navigate to a specific slide index. */
18017
- navigateToSlide: (slideIndex: number) => void;
18205
+ slides: readonly PptxSlide[];
18206
+ /** Navigate to a specific slide index, optionally overriding the destination's own transition. */
18207
+ navigateToSlide: (slideIndex: number, transitionOverride?: PptxSlideTransition) => void;
18208
+ /**
18209
+ * Shared with `useSlideNavigation`'s forward-advance step: set here on a
18210
+ * zoom click that requests `returnToParent`, and consumed there once the
18211
+ * show reaches the end of the zoom's target range.
18212
+ */
18213
+ zoomExcursionRef: React.RefObject<ZoomExcursion | undefined>;
18018
18214
  }
18019
18215
  /**
18020
18216
  * Return type for the useZoomNavigation sub-hook.
18021
18217
  */
18022
18218
  interface UseZoomNavigationResult {
18023
18219
  /**
18024
- * Handle a zoom element click. Navigates to the target slide and
18025
- * stores the return slide index so we can go back later.
18026
- */
18027
- handleZoomClick: (targetSlideIndex: number, returnSlideIndex: number) => void;
18028
- /**
18029
- * The slide index to return to after a zoom navigation, or `null` if
18030
- * there is no pending return.
18031
- */
18032
- zoomReturnSlideIndex: React.RefObject<number | null>;
18033
- /**
18034
- * Navigate back to the zoom summary slide (if a return index is set).
18035
- * Returns `true` if navigation occurred, `false` otherwise.
18036
- */
18037
- returnToZoomSlide: () => boolean;
18038
- /**
18039
- * Clear the stored return index (e.g. when the user manually navigates
18040
- * away from the zoomed section).
18220
+ * Handle a zoom element (or Summary Zoom tile) click: navigates to the
18221
+ * target slide, applying the zoom's own `transitionDur` when authored, and
18222
+ * (when the target's `returnToParent` is set) arms an excursion so the
18223
+ * next forward "advance" past the target's range returns here instead of
18224
+ * continuing linearly through the deck.
18041
18225
  */
18226
+ handleZoomClick: (target: ZoomNavigationTarget, returnSlideIndex: number) => void;
18227
+ /** Clear a pending zoom excursion (e.g. when presentation mode ends). */
18042
18228
  clearZoomReturn: () => void;
18043
18229
  }
18044
18230
  /**
18045
18231
  * Sub-hook that manages zoom element navigation in presentation mode.
18046
18232
  *
18047
- * When a zoom element is clicked, this hook:
18048
- * 1. Navigates to the target slide
18049
- * 2. Stores the "return" slide index
18050
- *
18051
- * The caller can later use `returnToZoomSlide()` to navigate back to
18052
- * the summary zoom slide.
18233
+ * The actual "return to zoom" jump is executed by `useSlideNavigation`'s
18234
+ * forward-advance step (it owns the deck's natural next-slide computation);
18235
+ * this hook only arms the excursion `useSlideNavigation` consults, via the
18236
+ * `zoomExcursionRef` both hooks share.
18053
18237
  */
18054
18238
  declare function useZoomNavigation(input: UseZoomNavigationInput): UseZoomNavigationResult;
18055
18239
  //#endregion