pptx-react-viewer 4.14.0 → 4.16.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 +27 -0
  2. package/dist/{AiChatPanel-WQUOEVQB.mjs → AiChatPanel-5Z4BYP7S.mjs} +4 -4
  3. package/dist/AiChatPanel-5Z4BYP7S.mjs.br +0 -0
  4. package/dist/AiChatPanel-5Z4BYP7S.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-PULXQTFJ.js → AiChatPanel-DHLJ6LKF.js} +28 -28
  6. package/dist/AiChatPanel-DHLJ6LKF.js.br +0 -0
  7. package/dist/AiChatPanel-DHLJ6LKF.js.gz +0 -0
  8. package/dist/{Model3DScene-6MYHPE5N.js → Model3DScene-AXT5KCUX.js} +2 -2
  9. package/dist/Model3DScene-AXT5KCUX.js.br +0 -0
  10. package/dist/Model3DScene-AXT5KCUX.js.gz +0 -0
  11. package/dist/{Model3DScene-HZG33BWN.mjs → Model3DScene-N36X5Z2Z.mjs} +1 -1
  12. package/dist/Model3DScene-N36X5Z2Z.mjs.br +0 -0
  13. package/dist/Model3DScene-N36X5Z2Z.mjs.gz +0 -0
  14. package/dist/{chunk-WSYKEPW6.mjs → chunk-BTTAYCGK.mjs} +904 -1201
  15. package/dist/chunk-BTTAYCGK.mjs.br +0 -0
  16. package/dist/chunk-BTTAYCGK.mjs.gz +0 -0
  17. package/dist/{chunk-E6VYR3GM.js → chunk-BZNYI5U6.js} +866 -820
  18. package/dist/chunk-BZNYI5U6.js.br +0 -0
  19. package/dist/chunk-BZNYI5U6.js.gz +0 -0
  20. package/dist/{chunk-55OLQ7HS.mjs → chunk-CJSIEITL.mjs} +3 -0
  21. package/dist/chunk-CJSIEITL.mjs.br +0 -0
  22. package/dist/chunk-CJSIEITL.mjs.gz +0 -0
  23. package/dist/{chunk-XWO367ZG.js → chunk-FVLBN45Z.js} +5 -5
  24. package/dist/chunk-FVLBN45Z.js.br +0 -0
  25. package/dist/chunk-FVLBN45Z.js.gz +0 -0
  26. package/dist/{chunk-AJTFPTSN.mjs → chunk-MFGRRONU.mjs} +2 -2
  27. package/dist/chunk-MFGRRONU.mjs.br +0 -0
  28. package/dist/chunk-MFGRRONU.mjs.gz +0 -0
  29. package/dist/{chunk-UWVRB4Z5.mjs → chunk-MJ6LTUJ3.mjs} +3437 -1237
  30. package/dist/chunk-MJ6LTUJ3.mjs.br +0 -0
  31. package/dist/chunk-MJ6LTUJ3.mjs.gz +0 -0
  32. package/dist/{chunk-DI4YTG3J.js → chunk-QAVJDYB2.js} +197 -197
  33. package/dist/chunk-QAVJDYB2.js.br +0 -0
  34. package/dist/chunk-QAVJDYB2.js.gz +0 -0
  35. package/dist/{chunk-EPMT65EN.mjs → chunk-QLUA63T3.mjs} +54 -9
  36. package/dist/chunk-QLUA63T3.mjs.br +0 -0
  37. package/dist/chunk-QLUA63T3.mjs.gz +0 -0
  38. package/dist/{chunk-RK5UV5HL.js → chunk-UVK2WBCU.js} +2047 -2344
  39. package/dist/chunk-UVK2WBCU.js.br +0 -0
  40. package/dist/chunk-UVK2WBCU.js.gz +0 -0
  41. package/dist/{chunk-ECKXYCP3.mjs → chunk-WRQ7K3DG.mjs} +1 -1
  42. package/dist/chunk-WRQ7K3DG.mjs.br +0 -0
  43. package/dist/chunk-WRQ7K3DG.mjs.gz +0 -0
  44. package/dist/{chunk-HIYK7HPX.js → chunk-XEYB25ZT.js} +3 -0
  45. package/dist/chunk-XEYB25ZT.js.br +0 -0
  46. package/dist/chunk-XEYB25ZT.js.gz +0 -0
  47. package/dist/{chunk-6ZR27XTL.js → chunk-XZUIS3VB.js} +3454 -1242
  48. package/dist/chunk-XZUIS3VB.js.br +0 -0
  49. package/dist/chunk-XZUIS3VB.js.gz +0 -0
  50. package/dist/i18n/de.cjs +3 -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 +3 -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 +3 -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 +3 -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 +3 -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 +3 -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 +3 -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 +3 -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 +329 -267
  81. package/dist/index.js +63 -63
  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 +643 -573
  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 +196 -136
  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 +2 -2
  105. package/dist/AiChatPanel-PULXQTFJ.js.br +0 -0
  106. package/dist/AiChatPanel-PULXQTFJ.js.gz +0 -0
  107. package/dist/AiChatPanel-WQUOEVQB.mjs.br +0 -0
  108. package/dist/AiChatPanel-WQUOEVQB.mjs.gz +0 -0
  109. package/dist/Model3DScene-6MYHPE5N.js.br +0 -0
  110. package/dist/Model3DScene-6MYHPE5N.js.gz +0 -0
  111. package/dist/Model3DScene-HZG33BWN.mjs.br +0 -0
  112. package/dist/Model3DScene-HZG33BWN.mjs.gz +0 -0
  113. package/dist/chunk-55OLQ7HS.mjs.br +0 -0
  114. package/dist/chunk-55OLQ7HS.mjs.gz +0 -0
  115. package/dist/chunk-6ZR27XTL.js.br +0 -0
  116. package/dist/chunk-6ZR27XTL.js.gz +0 -0
  117. package/dist/chunk-AJTFPTSN.mjs.br +0 -0
  118. package/dist/chunk-AJTFPTSN.mjs.gz +0 -0
  119. package/dist/chunk-DI4YTG3J.js.br +0 -0
  120. package/dist/chunk-DI4YTG3J.js.gz +0 -0
  121. package/dist/chunk-E6VYR3GM.js.br +0 -0
  122. package/dist/chunk-E6VYR3GM.js.gz +0 -0
  123. package/dist/chunk-ECKXYCP3.mjs.br +0 -0
  124. package/dist/chunk-ECKXYCP3.mjs.gz +0 -0
  125. package/dist/chunk-EPMT65EN.mjs.br +0 -0
  126. package/dist/chunk-EPMT65EN.mjs.gz +0 -0
  127. package/dist/chunk-HIYK7HPX.js.br +0 -0
  128. package/dist/chunk-HIYK7HPX.js.gz +0 -0
  129. package/dist/chunk-RK5UV5HL.js.br +0 -0
  130. package/dist/chunk-RK5UV5HL.js.gz +0 -0
  131. package/dist/chunk-UWVRB4Z5.mjs.br +0 -0
  132. package/dist/chunk-UWVRB4Z5.mjs.gz +0 -0
  133. package/dist/chunk-WSYKEPW6.mjs.br +0 -0
  134. package/dist/chunk-WSYKEPW6.mjs.gz +0 -0
  135. package/dist/chunk-XWO367ZG.js.br +0 -0
  136. package/dist/chunk-XWO367ZG.js.gz +0 -0
@@ -13665,103 +13665,54 @@ interface FragmentedLayer {
13665
13665
  easing: string;
13666
13666
  fragments: readonly TransitionFragment[];
13667
13667
  }
13668
+ type BackstagePage = 'home' | 'new' | 'open' | 'info' | 'save' | 'saveAs' | 'print' | 'share' | 'export' | 'close' | 'account' | 'options';
13668
13669
  //#endregion
13669
- //#region src/render/p14-transition-keyframes.d.ts
13670
- /** Part 1: conveyor / doors / ferris / flash / flythrough / gallery / glitter / honeycomb / pan. */
13671
- declare const P14_TRANSITION_KEYFRAMES = "\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";
13672
- /** Part 2: prism / reveal / ripple / shred / switch / vortex / warp / wheelReverse / window. */
13673
- 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";
13674
- /** Both p14 keyframe blocks concatenated, for single `<style>` injection. */
13675
- 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";
13676
- //#endregion
13677
- //#region src/render/p14-transition-css.d.ts
13670
+ //#region src/render/backstage-cards.d.ts
13678
13671
  /**
13679
- * Return CSS animation descriptors for p14 transition types. Returns
13680
- * `undefined` when the type is not a p14 transition.
13672
+ * Every action card the File-tab backstage can show, keyed by the operation it
13673
+ * triggers rather than by its wording.
13674
+ *
13675
+ * The five bindings used to hardcode a title and a body string each, which made
13676
+ * the whole backstage untranslatable and let the copy drift: the same card
13677
+ * carried four different descriptions depending on which binding you opened it
13678
+ * in. Both halves now live here as a dictionary key plus an English fallback,
13679
+ * so a wording change lands everywhere at once and a translator only has to
13680
+ * translate it once.
13681
13681
  */
13682
- declare function getP14TransitionAnimations(type: PptxTransitionType, durationMs: number, direction: string | undefined, orient?: string | undefined, pattern?: string | undefined): SlideTransitionAnimations | undefined;
13683
- interface SlideSizeEmu {
13684
- widthEmu: number;
13685
- heightEmu: number;
13686
- /** ST_SlideSizeType token, or `''` for a size with no preset. */
13687
- type: string;
13688
- }
13682
+ type BackstageCardId = 'protect' | 'inspect' | 'embedFonts' | 'signatures' | 'versionHistory' | 'saveAsPptx' | 'saveAsPpsx' | 'saveAsPptm' | 'saveAsPpt' | 'pdf' | 'png' | 'video' | 'gif' | 'json' | 'copyImage' | 'print' | 'share';
13689
13683
  //#endregion
13690
- //#region src/render/mobile-viewport.d.ts
13684
+ //#region src/render/toolbar-actions.d.ts
13691
13685
  /**
13692
- * mobile-viewport.ts: framework-agnostic viewport / touch / orientation
13693
- * detection shared by the React, Vue, and Angular bindings.
13694
- *
13695
- * These are the pure predicates and feature-detection helpers behind each
13696
- * binding's `useIsMobile` / `IsMobileService`. The reactive wiring (React
13697
- * state, Vue refs, Angular signals) stays in the binding; the breakpoint maths
13698
- * and DOM capability probes live here so all three frameworks switch chrome at
13699
- * exactly the same thresholds.
13686
+ * Toolbar action / ribbon-tab visibility: a single, framework-agnostic
13687
+ * catalogue of every top-level toolbar button and ribbon tab a host app can
13688
+ * independently hide. Each binding exposes a `hiddenActions?: ToolbarActionId[]`
13689
+ * prop, threads it down to the relevant render sites, and gates them with
13690
+ * `isActionHidden`. Default (`undefined` / `[]`) hides nothing, matching
13691
+ * today's always-visible behaviour.
13700
13692
  *
13701
- * SSR / test safe: every probe feature-detects `window` / `navigator` /
13702
- * `screen` and returns a sensible default when absent.
13693
+ * `TOOLBAR_TABS` is also the canonical ribbon-tab list/order, replacing the
13694
+ * copy hand-duplicated in each binding (React's `TOOLBAR_SECTIONS`, Vue's
13695
+ * `ribbon-constants.ts`, Angular's `RIBBON_TABS`, etc.) so the tab set can't
13696
+ * drift between bindings. Per-tab icons stay in each binding (icon libraries
13697
+ * differ per framework); only id + i18n key + order are shared here.
13703
13698
  */
13704
- /** Mobile breakpoint: below this width is considered mobile. */
13705
- declare const MOBILE_BREAKPOINT = 768;
13706
- /** Tablet breakpoint: below this width (but >= MOBILE) is tablet. */
13707
- declare const TABLET_BREAKPOINT = 1024;
13708
- /** Device orientation as reported by the screen / viewport aspect ratio. */
13709
- type DeviceOrientation = 'portrait' | 'landscape';
13710
- //#endregion
13711
- //#region src/render/presentation-session-types.d.ts
13712
- interface PresentationSnapshot {
13713
- slideIndex: number;
13714
- buildStep: number;
13715
- sequence: number;
13716
- blackout: 'none' | 'black' | 'white';
13717
- paused: boolean;
13718
- elapsedMs: number;
13719
- zoom?: PresentationZoomState;
13720
- pointer?: PresentationPointerState;
13721
- inkStrokes?: PresentationInkStroke[];
13722
- /**
13723
- * Whether ink markup is drawn (PowerPoint's Ctrl+M). Undefined means visible,
13724
- * so existing snapshots keep showing their ink. Hiding never discards the
13725
- * strokes, which stay in `inkStrokes` and can be kept on exit.
13726
- */
13727
- inkMarkupVisible?: boolean;
13728
- caption?: string;
13729
- subtitlesVisible?: boolean;
13730
- }
13731
- interface PresentationZoomState {
13732
- scale: number;
13733
- originX: number;
13734
- originY: number;
13735
- }
13736
- type PresentationPointerTool = 'none' | 'laser' | 'pen' | 'highlighter' | 'eraser';
13737
- interface PresentationPointerState {
13738
- tool: PresentationPointerTool;
13739
- x: number;
13740
- y: number;
13741
- color: string;
13742
- }
13743
- interface PresentationInkPoint {
13744
- x: number;
13745
- y: number;
13746
- }
13747
- interface PresentationInkStroke {
13748
- id: string;
13749
- slideIndex: number;
13750
- tool: 'pen' | 'highlighter';
13751
- color: string;
13752
- width: number;
13753
- points: PresentationInkPoint[];
13754
- }
13755
- //#endregion
13756
- //#region src/render/editor-keymap.d.ts
13757
- /** A logical editor command produced by one key press. */
13758
- type EditorKeyActionName = 'undo' | 'redo' | 'copy' | 'cut' | 'paste' | 'duplicate' | 'delete' | 'selectAll' | 'group' | 'ungroup' | 'nudge' | 'prevSlide' | 'nextSlide' | 'escape' | 'find' | 'findReplace' | 'toggleShortcuts' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'increaseFontSize' | 'decreaseFontSize' | 'copyFormat' | 'pasteFormat' | 'newSlide' | 'hyperlink' | 'clearFormatting' | 'cycleSelectionNext' | 'cycleSelectionPrev' | 'pasteSpecial';
13759
- //#endregion
13760
- //#region src/render/merge-shapes/merge-shapes-menu.d.ts
13761
- /** The right-click command id for each operation. */
13762
- type MergeShapesCommandId = 'merge-union' | 'merge-combine' | 'merge-fragment' | 'merge-intersect' | 'merge-subtract';
13763
- /** Every command a canvas context menu can offer, in no particular order. */
13764
- type ContextMenuCommandId = 'copy' | 'cut' | 'paste' | 'duplicate' | 'edit-text' | 'edit-points' | 'bring-forward' | 'send-backward' | 'bring-front' | 'send-back' | 'ai-ask' | 'ai-fix' | 'comment' | 'hyperlink' | 'table-insert-row-above' | 'table-insert-row-below' | 'table-delete-row' | 'table-insert-col-left' | 'table-insert-col-right' | 'table-delete-col' | 'table-merge-selected' | 'table-merge-right' | 'table-merge-down' | 'table-split' | 'group' | 'ungroup' | 'crop' | MergeShapesCommandId | 'save-as-picture' | 'edit-alt-text' | 'size-and-position' | 'format-shape' | 'delete';
13699
+ /**
13700
+ * A single toolbar button/control that can be hidden independently of the
13701
+ * ribbon tab it may also appear inside. `zoom` and `navigation` each cover a
13702
+ * whole control cluster (zoom in/out/fit, prev/next) rather than each button
13703
+ * in it, matching how hosts actually want to hide/keep them as a unit.
13704
+ */
13705
+ type ToolbarButtonId = 'share' | 'broadcast' | 'export' | 'undo' | 'redo' | 'record' | 'notes' | 'fullscreen' | 'zoom' | 'navigation' | 'mergeShapes' | 'crop';
13706
+ /** A top-level ribbon tab. `record` intentionally shares its id with the quick-access Record button above: both surface the same recording feature, so hiding one hides the other. */
13707
+ type ToolbarTabId = 'file' | 'home' | 'insert' | 'draw' | 'design' | 'transitions' | 'animations' | 'slideShow' | 'record' | 'review' | 'view' | 'help';
13708
+ type ToolbarActionId = ToolbarButtonId | ToolbarTabId;
13709
+ /**
13710
+ * PowerPoint's contextual tabs: they join the tab row only while the
13711
+ * selection is of their kind (see `contextualTabsForElement` in
13712
+ * `ribbon-galleries/`). Kept apart from `ToolbarTabId` because they are not
13713
+ * part of the fixed tab order every binding renders.
13714
+ */
13715
+ type RibbonContextualTabId = 'shapeFormat' | 'pictureFormat' | 'tableDesign' | 'chartDesign' | 'smartArtDesign';
13765
13716
  //#endregion
13766
13717
  //#region src/render/canvas-context-menu-commands.d.ts
13767
13718
  /**
@@ -13780,300 +13731,59 @@ type ContextMenuCommandId = 'copy' | 'cut' | 'paste' | 'duplicate' | 'edit-text'
13780
13731
  /** Every command the empty-canvas context menu can offer, in no particular order. */
13781
13732
  type CanvasContextMenuCommandId = 'paste' | 'layout' | 'reset-slide' | 'format-background' | 'grid-and-guides' | 'ruler';
13782
13733
  //#endregion
13783
- //#region src/render/paste-special.d.ts
13784
- /** The four paste formats PowerPoint's Paste Options / Paste Special offer. */
13785
- type PasteSpecialFormat = 'keep-source-formatting' | 'use-destination-theme' | 'picture' | 'keep-text-only';
13734
+ //#region src/render/merge-shapes/merge-shapes-menu.d.ts
13735
+ /** The right-click command id for each operation. */
13736
+ type MergeShapesCommandId = 'merge-union' | 'merge-combine' | 'merge-fragment' | 'merge-intersect' | 'merge-subtract';
13737
+ /** Every command a canvas context menu can offer, in no particular order. */
13738
+ type ContextMenuCommandId = 'copy' | 'cut' | 'paste' | 'duplicate' | 'edit-text' | 'edit-points' | 'bring-forward' | 'send-backward' | 'bring-front' | 'send-back' | 'ai-ask' | 'ai-fix' | 'comment' | 'hyperlink' | 'table-insert-row-above' | 'table-insert-row-below' | 'table-delete-row' | 'table-insert-col-left' | 'table-insert-col-right' | 'table-delete-col' | 'table-merge-selected' | 'table-merge-right' | 'table-merge-down' | 'table-split' | 'group' | 'ungroup' | 'crop' | MergeShapesCommandId | 'save-as-picture' | 'edit-alt-text' | 'size-and-position' | 'format-shape' | 'delete';
13739
+ /** Every command the Edit Points right-click menu can offer. */
13740
+ type EditPointsCommandId = 'add-point' | 'delete-point' | 'delete-segment' | 'open-path' | 'close-path' | 'smooth-point' | 'straight-point' | 'corner-point' | 'straight-segment' | 'curved-segment' | 'exit';
13786
13741
  //#endregion
13787
- //#region src/render/find-replace.d.ts
13788
- /** Identifies a single match of the find query at segment-level precision. */
13789
- interface FindResult {
13790
- /** Zero-based index of the slide in the slides array. */
13791
- slideIndex: number;
13792
- /** Id of the element that contains the match. */
13793
- elementId: string;
13794
- /** Zero-based index of the text segment within the element's `textSegments`. */
13795
- segmentIndex: number;
13796
- /** Character offset of the match start within the segment text. */
13797
- startOffset: number;
13798
- /** Number of characters matched (equals `query.length`). */
13799
- length: number;
13800
- }
13801
- interface TouchGestureCallbacks {
13802
- /** Called continuously during a pinch gesture with the new (clamped) scale. */
13803
- onPinchZoom?: (newScale: number) => void;
13804
- /** Called when a horizontal swipe is detected. direction: -1 = left, 1 = right. */
13805
- onSwipe?: (direction: -1 | 1) => void;
13806
- /** Called when a long-press is detected, with the press coordinates. */
13807
- onLongPress?: (clientX: number, clientY: number) => void;
13808
- }
13742
+ //#region src/render/edit-points/freeform-tool-geometry.d.ts
13743
+ /** The two click-to-place drawing tools. */
13744
+ type FreeformToolKind = 'freeformShape' | 'curve';
13809
13745
  //#endregion
13810
- //#region src/render/insert-chart.d.ts
13746
+ //#region src/render/editor-keymap.d.ts
13747
+ /** A logical editor command produced by one key press. */
13748
+ type EditorKeyActionName = 'undo' | 'redo' | 'copy' | 'cut' | 'paste' | 'duplicate' | 'delete' | 'selectAll' | 'group' | 'ungroup' | 'nudge' | 'prevSlide' | 'nextSlide' | 'escape' | 'find' | 'findReplace' | 'toggleShortcuts' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'increaseFontSize' | 'decreaseFontSize' | 'copyFormat' | 'pasteFormat' | 'newSlide' | 'hyperlink' | 'clearFormatting' | 'cycleSelectionNext' | 'cycleSelectionPrev' | 'pasteSpecial';
13749
+ //#endregion
13750
+ //#region src/render/options/viewer-options.d.ts
13811
13751
  /**
13812
- * Dropdown ids for the insert-chart menu. Distinct from `PptxChartType`
13813
- * because PowerPoint offers Column (vertical) and Bar (horizontal) as two
13814
- * entries over the same underlying `'bar'` chart type, and because `'pareto'`
13815
- * has no `PptxChartType` of its own: it is a dropdown entry that resolves to
13816
- * `type: 'histogram'` (see docs/guide/limitations.md's ChartEx row) with a
13817
- * frequency-plus-cumulative-percentage default shape. The other six ChartEx
13818
- * ids (`histogram` through `regionMap`) map one-to-one onto their chart type.
13752
+ * Full PowerPoint "File > Options" parity model.
13753
+ *
13754
+ * Groups mirror the ten categories of PowerPoint's Options dialog. Values are
13755
+ * flat primitives per group so the dialog panes can be rendered generically
13756
+ * from `VIEWER_OPTIONS_SCHEMA` in every binding. The legacy six-toggle
13757
+ * `ViewerPreferences` surface stays supported via the mapping helpers below.
13819
13758
  */
13820
- type InsertChartKind = 'column' | 'bar' | 'line' | 'pie' | 'doughnut' | 'area' | 'scatter' | 'histogram' | 'pareto' | 'funnel' | 'treemap' | 'sunburst' | 'boxWhisker' | 'regionMap';
13821
- /** In-memory clipboard payload stored when an element is copied or cut. */
13822
- interface ElementClipboardPayload {
13823
- element: PptxElement;
13824
- isTemplate: boolean;
13825
- }
13826
- //#endregion
13827
- //#region src/render/editor-image-paste.d.ts
13828
- /** A currently editable slide. Return null while loading or outside canvas editing. */
13829
- interface EditorImagePasteTarget {
13830
- documentId: object;
13831
- slideId: string;
13832
- canvasSize: CanvasSize$1;
13833
- }
13834
- interface EditorImagePasteOptions {
13835
- getCanvas(): HTMLElement | null;
13836
- getTarget(): EditorImagePasteTarget | null;
13837
- /** Use the normal editor command so selection, dirty state and Undo stay consistent. */
13838
- insertElement(element: ImagePptxElement): void;
13839
- }
13840
- /** What the "Embed fonts in the file" toggle should look like and do. */
13841
- interface FontEmbeddingDescriptor {
13842
- /** Distinct typeface names the loaded deck currently embeds. */
13843
- embeddedFamilies: string[];
13844
- /**
13845
- * Whether the toggle accepts input. False when the deck embeds nothing,
13846
- * because turning it on could not produce an embedded font.
13847
- */
13848
- interactive: boolean;
13759
+ type ScreenTipStyle = 'descriptions' | 'plain' | 'off';
13760
+ type DisplayOptimization = 'appearance' | 'compatibility';
13761
+ type ImageResolutionPreset = 'highFidelity' | 'ppi330' | 'ppi220' | 'ppi150' | 'ppi96';
13762
+ type OpenDocumentsView = 'savedView' | 'normal' | 'outline' | 'slideSorter' | 'notes';
13763
+ type DefaultExportFormat = 'pptx' | 'pdf' | 'png';
13764
+ type QuickAccessPosition = 'above' | 'below';
13765
+ type FeedbackSoundScheme = 'modern' | 'classic';
13766
+ type OptionsPrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
13767
+ type OptionsPrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
13768
+ interface ViewerGeneralOptions {
13769
+ displayOptimization: DisplayOptimization;
13770
+ showMiniToolbar: boolean;
13771
+ enableLivePreview: boolean;
13772
+ collapseRibbonAutomatically: boolean;
13773
+ collapseSearchByDefault: boolean;
13774
+ screenTipStyle: ScreenTipStyle;
13775
+ userName: string;
13776
+ userInitials: string;
13777
+ showStartScreen: boolean;
13849
13778
  /**
13850
- * The position the toggle must START in so that it describes the file that
13851
- * would be written right now. A deck that arrived with embedded fonts keeps
13852
- * them on save, so the switch has to read "on" from the outset; the previous
13853
- * hardcoded `false` said the opposite of what save actually did.
13779
+ * Lets the user hand a local font file to the viewer so decks authored
13780
+ * with a font the browser lacks render with the real face.
13781
+ *
13782
+ * Off by default. The registration reads a file the user picks and adds it
13783
+ * to the page's font set for the session, which is a capability a host
13784
+ * embedding the viewer should opt into rather than inherit.
13854
13785
  */
13855
- initialEnabled: boolean;
13856
- /** Present only when `interactive` is false. */
13857
- disabledReasonKey?: string;
13858
- }
13859
- //#endregion
13860
- //#region src/render/zoom-return-navigation.d.ts
13861
- /**
13862
- * The navigation-relevant fields of a Zoom click target, independent of
13863
- * `zoomType`.
13864
- *
13865
- * `returnToParent` is already resolved to its EFFECTIVE value here (not the
13866
- * raw, possibly-`undefined` `ZoomPptxElement`/`SummaryZoomTarget` field):
13867
- * `CT_ZoomObjectProperties/@returnToParent` (MS-PPTX) is `<xsd:attribute
13868
- * name="returnToParent" type="xsd:boolean" use="optional" default="true"/>`,
13869
- * so an ABSENT attribute means true, not false. Core deliberately stores
13870
- * `undefined` rather than fabricating `true` (so a round-trip never invents
13871
- * an attribute the source never had), which makes `Boolean(x)` the wrong way
13872
- * to read it; the two `resolve*NavigationTarget` functions below are the only
13873
- * place that distinction should be made.
13874
- */
13875
- interface ZoomNavigationTarget {
13876
- targetSlideIndex: number;
13877
- targetSectionId?: string;
13878
- returnToParent: boolean;
13879
- transitionDurationMs?: number;
13880
- }
13881
- /** A pending "return to the zoom's origin slide" excursion, tracked by the binding across forward-advance steps. */
13882
- interface ZoomExcursion {
13883
- /** The slide to jump back to once `endSlideIndex` is passed (the slide the zoom was clicked from). */
13884
- returnSlideIndex: number;
13885
- /** The last slide index of the zoom's target range; see {@link resolveZoomExcursionEndIndex}. */
13886
- endSlideIndex: number;
13887
- /** The zoom's own `transitionDur`, applied to the jump INTO the target and to the return jump. */
13888
- transitionDurationMs?: number;
13889
- }
13890
- /** Everything a binding needs to render the recovery dialog, and nothing else. */
13891
- interface AutosaveRecoveryPrompt {
13892
- /** IndexedDB key the snapshot is stored under (the deck's file path/name). */
13893
- readonly filePath: string;
13894
- /** When the snapshot was written (epoch ms). */
13895
- readonly timestamp: number;
13896
- /** Snapshot size in bytes. */
13897
- readonly size: number;
13898
- /** Whole minutes since it was written, floored at 0. */
13899
- readonly ageMinutes: number;
13900
- readonly titleKey: string;
13901
- readonly messageKey: string;
13902
- /** `size` is pre-formatted here because byte units are not translated. */
13903
- readonly messageParams: {
13904
- readonly file: string;
13905
- readonly size: string;
13906
- };
13907
- /** Relative age, reusing the existing autosave age keys. */
13908
- readonly ageKey: string;
13909
- readonly ageParams: {
13910
- readonly count: number;
13911
- };
13912
- readonly restoreKey: string;
13913
- readonly discardKey: string;
13914
- }
13915
- type BackstagePage = 'home' | 'new' | 'open' | 'info' | 'save' | 'saveAs' | 'print' | 'share' | 'export' | 'close' | 'account' | 'options';
13916
- //#endregion
13917
- //#region src/render/backstage-cards.d.ts
13918
- /**
13919
- * Every action card the File-tab backstage can show, keyed by the operation it
13920
- * triggers rather than by its wording.
13921
- *
13922
- * The five bindings used to hardcode a title and a body string each, which made
13923
- * the whole backstage untranslatable and let the copy drift: the same card
13924
- * carried four different descriptions depending on which binding you opened it
13925
- * in. Both halves now live here as a dictionary key plus an English fallback,
13926
- * so a wording change lands everywhere at once and a translator only has to
13927
- * translate it once.
13928
- */
13929
- type BackstageCardId = 'protect' | 'inspect' | 'embedFonts' | 'signatures' | 'versionHistory' | 'saveAsPptx' | 'saveAsPpsx' | 'saveAsPptm' | 'saveAsPpt' | 'pdf' | 'png' | 'video' | 'gif' | 'json' | 'copyImage' | 'print' | 'share';
13930
- //#endregion
13931
- //#region src/render/master-view.d.ts
13932
- /** Which part the master view is currently pointed at. */
13933
- interface MasterViewTarget {
13934
- tab: MasterViewTab;
13935
- masterIndex: number;
13936
- /** `null` selects the master itself rather than one of its layouts. */
13937
- layoutIndex: number | null;
13938
- }
13939
- //#endregion
13940
- //#region src/render/virtualized-list.d.ts
13941
- /** Framework-neutral virtual-list range used by every thumbnail sidebar. */
13942
- interface VirtualizedRange {
13943
- startIndex: number;
13944
- endIndex: number;
13945
- totalHeight: number;
13946
- offsetY: number;
13947
- visibleRange: {
13948
- start: number;
13949
- end: number;
13950
- };
13951
- }
13952
- /** Compute the rendered item window for fixed-height virtual lists. */
13953
- declare function computeVirtualRange(totalItems: number, itemHeight: number, scrollTop: number, viewportHeight: number, overscan?: number): VirtualizedRange;
13954
- /**
13955
- * Why the deck is being serialised, which is a separate question from whether
13956
- * the user protected it.
13957
- *
13958
- * - `user-file` (the default): the bytes leave the viewer as a file. Save,
13959
- * Save As, Export, the host-facing `getContent()`. Protection applies.
13960
- * - `recovery-snapshot`: the bytes exist only so the viewer can read them back.
13961
- * The autosave crash-recovery snapshot in IndexedDB, and the internal
13962
- * re-serialise-then-reload cycle behind "apply theme". Protection does NOT
13963
- * apply: these are always written in the clear.
13964
- *
13965
- * ## Why a recovery snapshot must stay plaintext
13966
- *
13967
- * Nothing that reads a snapshot back has a password to give it.
13968
- * `readBackstageRecentFile`, `restoreSessionDeck` and the Version History
13969
- * panel's Restore all hand `record.data` straight to `PptxHandler.load()` with
13970
- * no `password` option, and an encrypted package refuses to open without one
13971
- * (`EncryptedFileError`). So an encrypted snapshot is not an inconvenience, it
13972
- * is unreadable: the moment the user turns on protection their crash-recovery
13973
- * data is silently destroyed, which is the exact opposite of what autosave is
13974
- * for.
13975
- *
13976
- * Encrypting it "properly" is not available either. Decrypting on recovery
13977
- * means the key has to outlive the crash the snapshot exists for, so it would
13978
- * have to sit in the same IndexedDB / localStorage as the snapshot itself,
13979
- * next to the ciphertext it unlocks. That is not a security boundary, it is
13980
- * theatre. Prompting the user instead only works if they remember the password
13981
- * of a deck they lost, which is precisely the moment they will not.
13982
- *
13983
- * ## The tradeoff this accepts (deliberately, not by omission)
13984
- *
13985
- * A password-protected deck DOES leave its content in cleartext at rest in the
13986
- * origin's IndexedDB. Anyone with the browser profile, or any script running on
13987
- * the origin, can read it. What limits the exposure: snapshots are scoped to
13988
- * the origin and profile, aged out by the store, and clearable from
13989
- * File > Account > Storage & Privacy (`clearLocalStorageData`). A user who
13990
- * cannot accept plaintext at rest should switch AutoSave off, which stops the
13991
- * snapshot being written at all.
13992
- *
13993
- * The rejected alternative was "skip autosave entirely while a password is
13994
- * set". It removes the plaintext, but it also removes crash recovery without
13995
- * telling anyone, so a crash loses the whole editing session. Losing data
13996
- * quietly is the failure mode we are fixing, not a fix for it.
13997
- */
13998
- type DeckSavePurpose = 'user-file' | 'recovery-snapshot';
13999
- /** A `p:showPr/p:sldRg` custom range, resolved to 0-based deck indexes. */
14000
- interface AuthoredSlideRange {
14001
- /** First slide of the range, 0-based, inclusive. */
14002
- readonly fromIndex: number;
14003
- /** Last slide of the range, 0-based, inclusive. */
14004
- readonly toIndex: number;
14005
- }
14006
- //#endregion
14007
- //#region src/render/toolbar-actions.d.ts
14008
- /**
14009
- * Toolbar action / ribbon-tab visibility: a single, framework-agnostic
14010
- * catalogue of every top-level toolbar button and ribbon tab a host app can
14011
- * independently hide. Each binding exposes a `hiddenActions?: ToolbarActionId[]`
14012
- * prop, threads it down to the relevant render sites, and gates them with
14013
- * `isActionHidden`. Default (`undefined` / `[]`) hides nothing, matching
14014
- * today's always-visible behaviour.
14015
- *
14016
- * `TOOLBAR_TABS` is also the canonical ribbon-tab list/order, replacing the
14017
- * copy hand-duplicated in each binding (React's `TOOLBAR_SECTIONS`, Vue's
14018
- * `ribbon-constants.ts`, Angular's `RIBBON_TABS`, etc.) so the tab set can't
14019
- * drift between bindings. Per-tab icons stay in each binding (icon libraries
14020
- * differ per framework); only id + i18n key + order are shared here.
14021
- */
14022
- /**
14023
- * A single toolbar button/control that can be hidden independently of the
14024
- * ribbon tab it may also appear inside. `zoom` and `navigation` each cover a
14025
- * whole control cluster (zoom in/out/fit, prev/next) rather than each button
14026
- * in it, matching how hosts actually want to hide/keep them as a unit.
14027
- */
14028
- type ToolbarButtonId = 'share' | 'broadcast' | 'export' | 'undo' | 'redo' | 'record' | 'notes' | 'fullscreen' | 'zoom' | 'navigation' | 'mergeShapes' | 'crop';
14029
- /** A top-level ribbon tab. `record` intentionally shares its id with the quick-access Record button above: both surface the same recording feature, so hiding one hides the other. */
14030
- type ToolbarTabId = 'file' | 'home' | 'insert' | 'draw' | 'design' | 'transitions' | 'animations' | 'slideShow' | 'record' | 'review' | 'view' | 'help';
14031
- type ToolbarActionId = ToolbarButtonId | ToolbarTabId;
14032
- /**
14033
- * PowerPoint's contextual tabs: they join the tab row only while the
14034
- * selection is of their kind (see `contextualTabsForElement` in
14035
- * `ribbon-galleries/`). Kept apart from `ToolbarTabId` because they are not
14036
- * part of the fixed tab order every binding renders.
14037
- */
14038
- type RibbonContextualTabId = 'shapeFormat' | 'pictureFormat' | 'tableDesign' | 'chartDesign' | 'smartArtDesign';
14039
- //#endregion
14040
- //#region src/render/options/viewer-options.d.ts
14041
- /**
14042
- * Full PowerPoint "File > Options" parity model.
14043
- *
14044
- * Groups mirror the ten categories of PowerPoint's Options dialog. Values are
14045
- * flat primitives per group so the dialog panes can be rendered generically
14046
- * from `VIEWER_OPTIONS_SCHEMA` in every binding. The legacy six-toggle
14047
- * `ViewerPreferences` surface stays supported via the mapping helpers below.
14048
- */
14049
- type ScreenTipStyle = 'descriptions' | 'plain' | 'off';
14050
- type DisplayOptimization = 'appearance' | 'compatibility';
14051
- type ImageResolutionPreset = 'highFidelity' | 'ppi330' | 'ppi220' | 'ppi150' | 'ppi96';
14052
- type OpenDocumentsView = 'savedView' | 'normal' | 'outline' | 'slideSorter' | 'notes';
14053
- type DefaultExportFormat = 'pptx' | 'pdf' | 'png';
14054
- type QuickAccessPosition = 'above' | 'below';
14055
- type FeedbackSoundScheme = 'modern' | 'classic';
14056
- type OptionsPrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
14057
- type OptionsPrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
14058
- interface ViewerGeneralOptions {
14059
- displayOptimization: DisplayOptimization;
14060
- showMiniToolbar: boolean;
14061
- enableLivePreview: boolean;
14062
- collapseRibbonAutomatically: boolean;
14063
- collapseSearchByDefault: boolean;
14064
- screenTipStyle: ScreenTipStyle;
14065
- userName: string;
14066
- userInitials: string;
14067
- showStartScreen: boolean;
14068
- /**
14069
- * Lets the user hand a local font file to the viewer so decks authored
14070
- * with a font the browser lacks render with the real face.
14071
- *
14072
- * Off by default. The registration reads a file the user picks and adds it
14073
- * to the page's font set for the session, which is a capability a host
14074
- * embedding the viewer should opt into rather than inherit.
14075
- */
14076
- enableCustomFontUpload: boolean;
13786
+ enableCustomFontUpload: boolean;
14077
13787
  }
14078
13788
  interface ViewerProofingOptions {
14079
13789
  autoCorrectTwoInitialCapitals: boolean;
@@ -14113,6 +13823,8 @@ interface ViewerSaveOptions {
14113
13823
  clearCacheOnClose: boolean;
14114
13824
  }
14115
13825
  interface ViewerAccessibilityOptions {
13826
+ /** Browser speech-recognition language; automatic follows the browser language. */
13827
+ subtitleLanguage?: string;
14116
13828
  showAccessibilityStatus: boolean;
14117
13829
  feedbackWithSound: boolean;
14118
13830
  soundScheme: FeedbackSoundScheme;
@@ -14196,61 +13908,31 @@ interface ViewerOptions {
14196
13908
  type ViewerOptionsGroupId = keyof ViewerOptions;
14197
13909
  type ViewerOptionPrimitive = boolean | number | string;
14198
13910
  //#endregion
14199
- //#region src/export/handout-layout.d.ts
13911
+ //#region src/render/options/viewer-options-controls.d.ts
14200
13912
  /**
14201
- * Pure handout layout calculations, shared by every binding's print path.
14202
- *
14203
- * Handles distributing slides across pages, computing grid dimensions, and
14204
- * positioning cells within A4 page space. No DOM/framework dependency: callers
14205
- * render the resulting rectangles however their view layer prefers.
13913
+ * Control/section/tab descriptor types for the File > Options schema, plus
13914
+ * the terse constructors the tab-definition modules build panes with.
14206
13915
  */
14207
- /** Supported slides-per-page values. */
14208
- type HandoutSlidesPerPage = 1 | 2 | 3 | 4 | 6 | 9;
13916
+ type ViewerOptionsTabId = 'general' | 'proofing' | 'save' | 'language' | 'accessibility' | 'advanced' | 'ribbon' | 'quickAccess' | 'addIns' | 'trust';
14209
13917
  //#endregion
14210
- //#region src/export/print-document.d.ts
14211
- /** What to print. */
14212
- type PrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
14213
- /** Page orientation for the printed output. */
14214
- type PrintOrientation = 'portrait' | 'landscape';
14215
- /** Colour mode for the printed output. */
14216
- type PrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
14217
- /** Slide range mode. */
14218
- type PrintSlideRange = 'all' | 'current' | 'custom';
14219
- /** Resolved print settings emitted on confirm. */
14220
- interface PrintSettings {
14221
- printWhat: PrintWhat;
14222
- orientation: PrintOrientation;
14223
- colorMode: PrintColorMode;
14224
- frameSlides: boolean;
14225
- slidesPerPage: HandoutSlidesPerPage;
14226
- slideRange: PrintSlideRange;
14227
- customRangeFrom: number;
14228
- customRangeTo: number;
14229
- /**
14230
- * PowerPoint's Print > "Scale to Fit Paper". `true` (the default, and the
14231
- * only behavior this printed output ever had before this field existed)
14232
- * shrinks/grows each slide image to fill its page/cell while preserving
14233
- * aspect ratio. `false` prints at the slide's native pixel size instead,
14234
- * which may overflow or under-fill the page, exactly like PowerPoint with
14235
- * the option off. Optional so existing `Partial<PrintSettings>` literals
14236
- * across every binding keep compiling; `validatePrintSettings` defaults it
14237
- * to `true`.
14238
- */
14239
- scaleToFit?: boolean;
13918
+ //#region src/render/customization/host-menu-commands.d.ts
13919
+ /** Snapshot of the slide on which the host command was offered. */
13920
+ interface HostCanvasMenuContext {
13921
+ slideIndex: number;
13922
+ }
13923
+ /** Effective selection, including a single right-clicked element. */
13924
+ interface HostElementMenuContext extends HostCanvasMenuContext {
13925
+ elementIds: readonly string[];
13926
+ }
13927
+ /** Plain text labels work identically in every framework. */
13928
+ interface HostMenuCommand<C> {
13929
+ id: string;
13930
+ label: string;
13931
+ /** Default: a separate group above the built-in commands. */
13932
+ group?: 'top' | 'bottom';
13933
+ disabled?: boolean | ((context: C) => boolean);
13934
+ onSelect: (context: C) => void;
14240
13935
  }
14241
- /** Every command the Edit Points right-click menu can offer. */
14242
- type EditPointsCommandId = 'add-point' | 'delete-point' | 'delete-segment' | 'open-path' | 'close-path' | 'smooth-point' | 'straight-point' | 'corner-point' | 'straight-segment' | 'curved-segment' | 'exit';
14243
- //#endregion
14244
- //#region src/render/edit-points/freeform-tool-geometry.d.ts
14245
- /** The two click-to-place drawing tools. */
14246
- type FreeformToolKind = 'freeformShape' | 'curve';
14247
- //#endregion
14248
- //#region src/render/options/viewer-options-controls.d.ts
14249
- /**
14250
- * Control/section/tab descriptor types for the File > Options schema, plus
14251
- * the terse constructors the tab-definition modules build panes with.
14252
- */
14253
- type ViewerOptionsTabId = 'general' | 'proofing' | 'save' | 'language' | 'accessibility' | 'advanced' | 'ribbon' | 'quickAccess' | 'addIns' | 'trust';
14254
13936
  //#endregion
14255
13937
  //#region src/render/customization/ribbon-control-catalog.d.ts
14256
13938
  declare const RIBBON_CONTROL_CATALOG: {
@@ -14833,6 +14515,9 @@ interface BackstageCustomization {
14833
14515
  }
14834
14516
  /** Right-click menu customisation. */
14835
14517
  interface ContextMenuCustomization {
14518
+ /** Additional host commands, independent of the viewer's AI connection. */
14519
+ extraElementCommands?: readonly HostMenuCommand<HostElementMenuContext>[];
14520
+ extraCanvasCommands?: readonly HostMenuCommand<HostCanvasMenuContext>[];
14836
14521
  /** Entries to remove from the element (right-click on a shape) menu. */
14837
14522
  hiddenElementCommands?: readonly ContextMenuCommandId[];
14838
14523
  /** Entries to remove from the empty-canvas menu. */
@@ -14848,59 +14533,497 @@ interface ContextMenuCustomization {
14848
14533
  disableCanvasMenu?: boolean;
14849
14534
  }
14850
14535
  /**
14851
- * A shortcut chord in the form `Mod+Shift+D`: modifiers `Mod` (Ctrl on
14852
- * Windows/Linux, Cmd on macOS), `Ctrl`, `Meta`, `Alt`, `Shift`, joined by `+`,
14853
- * followed by a `KeyboardEvent.key` value (`D`, `Delete`, `ArrowLeft`, `F2`).
14536
+ * A shortcut chord in the form `Mod+Shift+D`: modifiers `Mod` (Ctrl on
14537
+ * Windows/Linux, Cmd on macOS), `Ctrl`, `Meta`, `Alt`, `Shift`, joined by `+`,
14538
+ * followed by a `KeyboardEvent.key` value (`D`, `Delete`, `ArrowLeft`, `F2`).
14539
+ */
14540
+ type ShortcutChord = string;
14541
+ /** Editor keyboard-shortcut customisation. */
14542
+ interface KeyboardCustomization {
14543
+ /** Turn every editor shortcut off (the host owns the keyboard). */
14544
+ disableAll?: boolean;
14545
+ /** Editor commands whose shortcut is turned off. */
14546
+ disabled?: readonly EditorKeyActionName[];
14547
+ /**
14548
+ * Replacement chords per command. A remapped command no longer answers to
14549
+ * its built-in chord; it answers to the chord(s) given here instead.
14550
+ */
14551
+ remap?: Partial<Record<EditorKeyActionName, ShortcutChord | readonly ShortcutChord[]>>;
14552
+ }
14553
+ /**
14554
+ * Chrome regions a host can remove. Each id maps onto one region in every
14555
+ * binding; see `VIEWER_PANEL_IDS` for the catalogue.
14556
+ */
14557
+ type ViewerPanelId = 'statusBar' | 'slidesPane' | 'inspector' | 'notes' | 'quickAccessToolbar' | 'titleBar';
14558
+ /** Feature areas that can be switched off as a whole. */
14559
+ type ViewerFeatureId = 'ai' | 'collaboration' | 'comments' | 'presentMode' | 'editPoints';
14560
+ /**
14561
+ * The click-to-place drawing tools of Insert > Shapes > Lines: Freeform:
14562
+ * Shape and Curve.
14563
+ */
14564
+ type ViewerDrawingToolId = FreeformToolKind;
14565
+ /** Dialogs (and the entry points that open them) a host can remove. */
14566
+ type ViewerDialogId = 'options' | 'share' | 'broadcast' | 'print' | 'export';
14567
+ /** Export formats offered by the File > Export page. */
14568
+ type ViewerExportFormatId = 'pdf' | 'png' | 'video' | 'gif' | 'json' | 'copyImage';
14569
+ /**
14570
+ * The whole customisation object. Every field is optional; omitted fields hide
14571
+ * nothing and lock nothing.
14572
+ */
14573
+ interface ViewerCustomization {
14574
+ ribbon?: RibbonCustomization;
14575
+ options?: OptionsCustomization;
14576
+ backstage?: BackstageCustomization;
14577
+ contextMenu?: ContextMenuCustomization;
14578
+ keyboard?: KeyboardCustomization;
14579
+ /** Chrome regions to remove (`true` hides). */
14580
+ hiddenPanels?: readonly ViewerPanelId[];
14581
+ /** Feature areas to switch off (their buttons, menus, pages and panels). */
14582
+ disabledFeatures?: readonly ViewerFeatureId[];
14583
+ /** Dialogs to remove, along with every entry point that opens them. */
14584
+ hiddenDialogs?: readonly ViewerDialogId[];
14585
+ /** Export formats to remove from File > Export. */
14586
+ hiddenExportFormats?: readonly ViewerExportFormatId[];
14587
+ /** Drawing tools to remove from the Insert > Shapes gallery. */
14588
+ hiddenDrawingTools?: readonly ViewerDrawingToolId[];
14589
+ }
14590
+ //#endregion
14591
+ //#region src/render/customization/customization-keymap.d.ts
14592
+ /** A parsed `Mod+Shift+D` chord. */
14593
+ interface ParsedShortcutChord {
14594
+ key: string;
14595
+ mod: boolean;
14596
+ ctrl: boolean;
14597
+ meta: boolean;
14598
+ alt: boolean;
14599
+ shift: boolean;
14600
+ }
14601
+ /** The normalised keyboard slice of a resolved customisation. */
14602
+ interface ResolvedKeyboardCustomization {
14603
+ disableAll: boolean;
14604
+ disabled: ReadonlySet<EditorKeyActionName>;
14605
+ remap: ReadonlyMap<EditorKeyActionName, readonly ParsedShortcutChord[]>;
14606
+ }
14607
+ //#endregion
14608
+ //#region src/render/customization/customization-resolve.d.ts
14609
+ /** The normalised, set-based view of a customisation. Treat as immutable. */
14610
+ interface ResolvedCustomization {
14611
+ hiddenActions: ReadonlySet<ToolbarActionId>;
14612
+ /** Contextual tabs (`shapeFormat`, ...) the host never wants shown. */
14613
+ hiddenContextualTabs: ReadonlySet<RibbonContextualTabId>;
14614
+ /** Catalogued ribbon groups to hide (`ribbon.hiddenGroups`). */
14615
+ hiddenRibbonGroups: ReadonlySet<RibbonGroupId>;
14616
+ /** Catalogued ribbon controls to hide (the `<tab>.<group>.<control>` part of `ribbon.hiddenButtons`). */
14617
+ hiddenRibbonControls: ReadonlySet<RibbonControlId>;
14618
+ hiddenOptionsPages: ReadonlySet<OptionsPageId>;
14619
+ hiddenOptionsSections: ReadonlySet<OptionsSectionId>;
14620
+ hiddenSettings: ReadonlySet<OptionsSettingId>;
14621
+ lockedSettings: OptionsSettingValues;
14622
+ defaultSettings: OptionsSettingValues;
14623
+ hiddenBackstagePages: ReadonlySet<BackstagePage>;
14624
+ hiddenBackstageCards: ReadonlySet<BackstageCardId>;
14625
+ hiddenElementCommands: ReadonlySet<ContextMenuCommandId>;
14626
+ extraElementCommands: NonNullable<ViewerCustomization['contextMenu']>['extraElementCommands'];
14627
+ extraCanvasCommands: NonNullable<ViewerCustomization['contextMenu']>['extraCanvasCommands'];
14628
+ hiddenCanvasCommands: ReadonlySet<CanvasContextMenuCommandId>;
14629
+ hiddenEditPointsCommands: ReadonlySet<EditPointsCommandId>;
14630
+ hiddenDrawingTools: ReadonlySet<ViewerDrawingToolId>;
14631
+ elementMenuEnabled: boolean;
14632
+ canvasMenuEnabled: boolean;
14633
+ hiddenPanels: ReadonlySet<ViewerPanelId>;
14634
+ disabledFeatures: ReadonlySet<ViewerFeatureId>;
14635
+ hiddenDialogs: ReadonlySet<ViewerDialogId>;
14636
+ keyboard: ResolvedKeyboardCustomization;
14637
+ }
14638
+ //#endregion
14639
+ //#region src/render/customization/customization-controller.d.ts
14640
+ /** The imperative methods every binding's component handle exposes. */
14641
+ interface ViewerCustomizationApi {
14642
+ /** The current customisation object (a snapshot; do not mutate). */
14643
+ getCustomization(): ViewerCustomization;
14644
+ /** Replace the whole customisation. */
14645
+ setCustomization(next: ViewerCustomization): void;
14646
+ /** Merge a partial customisation (see `mergeCustomization`). */
14647
+ updateCustomization(patch: ViewerCustomization): void;
14648
+ /** Drop every customisation, back to the stock UI. */
14649
+ resetCustomization(): void;
14650
+ /** Hide a fixed tab, or stop a contextual tab (`shapeFormat`, ...) from appearing. */
14651
+ hideRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
14652
+ showRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
14653
+ /** Hide a group inside a tab (`home.font`). */
14654
+ hideRibbonGroup(group: RibbonGroupId): void;
14655
+ showRibbonGroup(group: RibbonGroupId): void;
14656
+ /** Hide a top-level toolbar button or any ribbon control (`home.font.bold`). */
14657
+ hideToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
14658
+ showToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
14659
+ /** Alias of `hideToolbarButton` for a ribbon control id. */
14660
+ hideRibbonControl(control: RibbonControlId): void;
14661
+ showRibbonControl(control: RibbonControlId): void;
14662
+ hideOptionsPage(page: OptionsPageId): void;
14663
+ showOptionsPage(page: OptionsPageId): void;
14664
+ hideOptionsSection(section: OptionsSectionId): void;
14665
+ showOptionsSection(section: OptionsSectionId): void;
14666
+ hideSetting(setting: OptionsSettingId): void;
14667
+ showSetting(setting: OptionsSettingId): void;
14668
+ /** Pin a setting to `value`; `hidden` also removes it from the dialog. */
14669
+ lockSetting(setting: OptionsSettingId, value: ViewerOptionPrimitive, hidden?: boolean): void;
14670
+ unlockSetting(setting: OptionsSettingId): void;
14671
+ /** Set (or with `undefined`, clear) the host default for a setting. */
14672
+ setSettingDefault(setting: OptionsSettingId, value: ViewerOptionPrimitive | undefined): void;
14673
+ hideBackstagePage(page: BackstagePage): void;
14674
+ showBackstagePage(page: BackstagePage): void;
14675
+ hideBackstageCard(card: BackstageCardId): void;
14676
+ showBackstageCard(card: BackstageCardId): void;
14677
+ hideContextMenuCommand(command: ContextMenuCommandId): void;
14678
+ showContextMenuCommand(command: ContextMenuCommandId): void;
14679
+ hideCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
14680
+ showCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
14681
+ disableShortcut(action: EditorKeyActionName): void;
14682
+ enableShortcut(action: EditorKeyActionName): void;
14683
+ /** Move a command onto new chord(s); `undefined` restores the built-in chord. */
14684
+ remapShortcut(action: EditorKeyActionName, chords: ShortcutChord | readonly ShortcutChord[] | undefined): void;
14685
+ setPanelVisible(panel: ViewerPanelId, visible: boolean): void;
14686
+ setFeatureEnabled(feature: ViewerFeatureId, enabled: boolean): void;
14687
+ setDialogAvailable(dialog: ViewerDialogId, available: boolean): void;
14688
+ }
14689
+ //#endregion
14690
+ //#region src/render/p14-transition-keyframes.d.ts
14691
+ /** Part 1: conveyor / doors / ferris / flash / flythrough / gallery / glitter / honeycomb / pan. */
14692
+ declare const P14_TRANSITION_KEYFRAMES = "\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";
14693
+ /** Part 2: prism / reveal / ripple / shred / switch / vortex / warp / wheelReverse / window. */
14694
+ 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";
14695
+ /** Both p14 keyframe blocks concatenated, for single `<style>` injection. */
14696
+ 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";
14697
+ //#endregion
14698
+ //#region src/render/p14-transition-css.d.ts
14699
+ /**
14700
+ * Return CSS animation descriptors for p14 transition types. Returns
14701
+ * `undefined` when the type is not a p14 transition.
14702
+ */
14703
+ declare function getP14TransitionAnimations(type: PptxTransitionType, durationMs: number, direction: string | undefined, orient?: string | undefined, pattern?: string | undefined): SlideTransitionAnimations | undefined;
14704
+ interface SlideSizeEmu {
14705
+ widthEmu: number;
14706
+ heightEmu: number;
14707
+ /** ST_SlideSizeType token, or `''` for a size with no preset. */
14708
+ type: string;
14709
+ }
14710
+ //#endregion
14711
+ //#region src/render/mobile-viewport.d.ts
14712
+ /**
14713
+ * mobile-viewport.ts: framework-agnostic viewport / touch / orientation
14714
+ * detection shared by the React, Vue, and Angular bindings.
14715
+ *
14716
+ * These are the pure predicates and feature-detection helpers behind each
14717
+ * binding's `useIsMobile` / `IsMobileService`. The reactive wiring (React
14718
+ * state, Vue refs, Angular signals) stays in the binding; the breakpoint maths
14719
+ * and DOM capability probes live here so all three frameworks switch chrome at
14720
+ * exactly the same thresholds.
14721
+ *
14722
+ * SSR / test safe: every probe feature-detects `window` / `navigator` /
14723
+ * `screen` and returns a sensible default when absent.
14724
+ */
14725
+ /** Mobile breakpoint: below this width is considered mobile. */
14726
+ declare const MOBILE_BREAKPOINT = 768;
14727
+ /** Tablet breakpoint: below this width (but >= MOBILE) is tablet. */
14728
+ declare const TABLET_BREAKPOINT = 1024;
14729
+ /** Device orientation as reported by the screen / viewport aspect ratio. */
14730
+ type DeviceOrientation = 'portrait' | 'landscape';
14731
+ //#endregion
14732
+ //#region src/render/presentation-session-types.d.ts
14733
+ interface PresentationSnapshot {
14734
+ slideIndex: number;
14735
+ buildStep: number;
14736
+ sequence: number;
14737
+ blackout: 'none' | 'black' | 'white';
14738
+ paused: boolean;
14739
+ elapsedMs: number;
14740
+ zoom?: PresentationZoomState;
14741
+ pointer?: PresentationPointerState;
14742
+ inkStrokes?: PresentationInkStroke[];
14743
+ /**
14744
+ * Whether ink markup is drawn (PowerPoint's Ctrl+M). Undefined means visible,
14745
+ * so existing snapshots keep showing their ink. Hiding never discards the
14746
+ * strokes, which stay in `inkStrokes` and can be kept on exit.
14747
+ */
14748
+ inkMarkupVisible?: boolean;
14749
+ caption?: string;
14750
+ subtitlesVisible?: boolean;
14751
+ }
14752
+ interface PresentationZoomState {
14753
+ scale: number;
14754
+ originX: number;
14755
+ originY: number;
14756
+ }
14757
+ type PresentationPointerTool = 'none' | 'laser' | 'pen' | 'highlighter' | 'eraser';
14758
+ interface PresentationPointerState {
14759
+ tool: PresentationPointerTool;
14760
+ x: number;
14761
+ y: number;
14762
+ color: string;
14763
+ }
14764
+ interface PresentationInkPoint {
14765
+ x: number;
14766
+ y: number;
14767
+ }
14768
+ interface PresentationInkStroke {
14769
+ id: string;
14770
+ slideIndex: number;
14771
+ tool: 'pen' | 'highlighter';
14772
+ color: string;
14773
+ width: number;
14774
+ points: PresentationInkPoint[];
14775
+ }
14776
+ //#endregion
14777
+ //#region src/render/paste-special.d.ts
14778
+ /** The four paste formats PowerPoint's Paste Options / Paste Special offer. */
14779
+ type PasteSpecialFormat = 'keep-source-formatting' | 'use-destination-theme' | 'picture' | 'keep-text-only';
14780
+ //#endregion
14781
+ //#region src/render/find-replace.d.ts
14782
+ /** Identifies a single match of the find query at segment-level precision. */
14783
+ interface FindResult {
14784
+ /** Zero-based index of the slide in the slides array. */
14785
+ slideIndex: number;
14786
+ /** Id of the element that contains the match. */
14787
+ elementId: string;
14788
+ /** Zero-based index of the text segment within the element's `textSegments`. */
14789
+ segmentIndex: number;
14790
+ /** Character offset of the match start within the segment text. */
14791
+ startOffset: number;
14792
+ /** Number of characters matched (equals `query.length`). */
14793
+ length: number;
14794
+ }
14795
+ interface TouchGestureCallbacks {
14796
+ /** Called continuously during a pinch gesture with the new (clamped) scale. */
14797
+ onPinchZoom?: (newScale: number) => void;
14798
+ /** Called when a horizontal swipe is detected. direction: -1 = left, 1 = right. */
14799
+ onSwipe?: (direction: -1 | 1) => void;
14800
+ /** Called when a long-press is detected, with the press coordinates. */
14801
+ onLongPress?: (clientX: number, clientY: number) => void;
14802
+ }
14803
+ //#endregion
14804
+ //#region src/render/insert-chart.d.ts
14805
+ /**
14806
+ * Dropdown ids for the insert-chart menu. Distinct from `PptxChartType`
14807
+ * because PowerPoint offers Column (vertical) and Bar (horizontal) as two
14808
+ * entries over the same underlying `'bar'` chart type, and because `'pareto'`
14809
+ * has no `PptxChartType` of its own: it is a dropdown entry that resolves to
14810
+ * `type: 'histogram'` (see docs/guide/limitations.md's ChartEx row) with a
14811
+ * frequency-plus-cumulative-percentage default shape. The other six ChartEx
14812
+ * ids (`histogram` through `regionMap`) map one-to-one onto their chart type.
14813
+ */
14814
+ type InsertChartKind = 'column' | 'bar' | 'line' | 'pie' | 'doughnut' | 'area' | 'scatter' | 'histogram' | 'pareto' | 'funnel' | 'treemap' | 'sunburst' | 'boxWhisker' | 'regionMap';
14815
+ /** In-memory clipboard payload stored when an element is copied or cut. */
14816
+ interface ElementClipboardPayload {
14817
+ element: PptxElement;
14818
+ isTemplate: boolean;
14819
+ }
14820
+ //#endregion
14821
+ //#region src/render/editor-image-paste.d.ts
14822
+ /** A currently editable slide. Return null while loading or outside canvas editing. */
14823
+ interface EditorImagePasteTarget {
14824
+ documentId: object;
14825
+ slideId: string;
14826
+ canvasSize: CanvasSize$1;
14827
+ }
14828
+ interface EditorImagePasteOptions {
14829
+ getCanvas(): HTMLElement | null;
14830
+ getTarget(): EditorImagePasteTarget | null;
14831
+ /** Use the normal editor command so selection, dirty state and Undo stay consistent. */
14832
+ insertElement(element: ImagePptxElement): void;
14833
+ }
14834
+ /** What the "Embed fonts in the file" toggle should look like and do. */
14835
+ interface FontEmbeddingDescriptor {
14836
+ /** Distinct typeface names the loaded deck currently embeds. */
14837
+ embeddedFamilies: string[];
14838
+ /**
14839
+ * Whether the toggle accepts input. False when the deck embeds nothing,
14840
+ * because turning it on could not produce an embedded font.
14841
+ */
14842
+ interactive: boolean;
14843
+ /**
14844
+ * The position the toggle must START in so that it describes the file that
14845
+ * would be written right now. A deck that arrived with embedded fonts keeps
14846
+ * them on save, so the switch has to read "on" from the outset; the previous
14847
+ * hardcoded `false` said the opposite of what save actually did.
14848
+ */
14849
+ initialEnabled: boolean;
14850
+ /** Present only when `interactive` is false. */
14851
+ disabledReasonKey?: string;
14852
+ }
14853
+ //#endregion
14854
+ //#region src/render/zoom-return-navigation.d.ts
14855
+ /**
14856
+ * The navigation-relevant fields of a Zoom click target, independent of
14857
+ * `zoomType`.
14858
+ *
14859
+ * `returnToParent` is already resolved to its EFFECTIVE value here (not the
14860
+ * raw, possibly-`undefined` `ZoomPptxElement`/`SummaryZoomTarget` field):
14861
+ * `CT_ZoomObjectProperties/@returnToParent` (MS-PPTX) is `<xsd:attribute
14862
+ * name="returnToParent" type="xsd:boolean" use="optional" default="true"/>`,
14863
+ * so an ABSENT attribute means true, not false. Core deliberately stores
14864
+ * `undefined` rather than fabricating `true` (so a round-trip never invents
14865
+ * an attribute the source never had), which makes `Boolean(x)` the wrong way
14866
+ * to read it; the two `resolve*NavigationTarget` functions below are the only
14867
+ * place that distinction should be made.
14868
+ */
14869
+ interface ZoomNavigationTarget {
14870
+ targetSlideIndex: number;
14871
+ targetSectionId?: string;
14872
+ returnToParent: boolean;
14873
+ transitionDurationMs?: number;
14874
+ }
14875
+ /** A pending "return to the zoom's origin slide" excursion, tracked by the binding across forward-advance steps. */
14876
+ interface ZoomExcursion {
14877
+ /** The slide to jump back to once `endSlideIndex` is passed (the slide the zoom was clicked from). */
14878
+ returnSlideIndex: number;
14879
+ /** The last slide index of the zoom's target range; see {@link resolveZoomExcursionEndIndex}. */
14880
+ endSlideIndex: number;
14881
+ /** The zoom's own `transitionDur`, applied to the jump INTO the target and to the return jump. */
14882
+ transitionDurationMs?: number;
14883
+ }
14884
+ /** Everything a binding needs to render the recovery dialog, and nothing else. */
14885
+ interface AutosaveRecoveryPrompt {
14886
+ /** IndexedDB key the snapshot is stored under (the deck's file path/name). */
14887
+ readonly filePath: string;
14888
+ /** When the snapshot was written (epoch ms). */
14889
+ readonly timestamp: number;
14890
+ /** Snapshot size in bytes. */
14891
+ readonly size: number;
14892
+ /** Whole minutes since it was written, floored at 0. */
14893
+ readonly ageMinutes: number;
14894
+ readonly titleKey: string;
14895
+ readonly messageKey: string;
14896
+ /** `size` is pre-formatted here because byte units are not translated. */
14897
+ readonly messageParams: {
14898
+ readonly file: string;
14899
+ readonly size: string;
14900
+ };
14901
+ /** Relative age, reusing the existing autosave age keys. */
14902
+ readonly ageKey: string;
14903
+ readonly ageParams: {
14904
+ readonly count: number;
14905
+ };
14906
+ readonly restoreKey: string;
14907
+ readonly discardKey: string;
14908
+ }
14909
+ //#endregion
14910
+ //#region src/render/master-view.d.ts
14911
+ /** Which part the master view is currently pointed at. */
14912
+ interface MasterViewTarget {
14913
+ tab: MasterViewTab;
14914
+ masterIndex: number;
14915
+ /** `null` selects the master itself rather than one of its layouts. */
14916
+ layoutIndex: number | null;
14917
+ }
14918
+ //#endregion
14919
+ //#region src/render/virtualized-list.d.ts
14920
+ /** Framework-neutral virtual-list range used by every thumbnail sidebar. */
14921
+ interface VirtualizedRange {
14922
+ startIndex: number;
14923
+ endIndex: number;
14924
+ totalHeight: number;
14925
+ offsetY: number;
14926
+ visibleRange: {
14927
+ start: number;
14928
+ end: number;
14929
+ };
14930
+ }
14931
+ /** Compute the rendered item window for fixed-height virtual lists. */
14932
+ declare function computeVirtualRange(totalItems: number, itemHeight: number, scrollTop: number, viewportHeight: number, overscan?: number): VirtualizedRange;
14933
+ /**
14934
+ * Why the deck is being serialised, which is a separate question from whether
14935
+ * the user protected it.
14936
+ *
14937
+ * - `user-file` (the default): the bytes leave the viewer as a file. Save,
14938
+ * Save As, Export, the host-facing `getContent()`. Protection applies.
14939
+ * - `recovery-snapshot`: the bytes exist only so the viewer can read them back.
14940
+ * The autosave crash-recovery snapshot in IndexedDB, and the internal
14941
+ * re-serialise-then-reload cycle behind "apply theme". Protection does NOT
14942
+ * apply: these are always written in the clear.
14943
+ *
14944
+ * ## Why a recovery snapshot must stay plaintext
14945
+ *
14946
+ * Nothing that reads a snapshot back has a password to give it.
14947
+ * `readBackstageRecentFile`, `restoreSessionDeck` and the Version History
14948
+ * panel's Restore all hand `record.data` straight to `PptxHandler.load()` with
14949
+ * no `password` option, and an encrypted package refuses to open without one
14950
+ * (`EncryptedFileError`). So an encrypted snapshot is not an inconvenience, it
14951
+ * is unreadable: the moment the user turns on protection their crash-recovery
14952
+ * data is silently destroyed, which is the exact opposite of what autosave is
14953
+ * for.
14954
+ *
14955
+ * Encrypting it "properly" is not available either. Decrypting on recovery
14956
+ * means the key has to outlive the crash the snapshot exists for, so it would
14957
+ * have to sit in the same IndexedDB / localStorage as the snapshot itself,
14958
+ * next to the ciphertext it unlocks. That is not a security boundary, it is
14959
+ * theatre. Prompting the user instead only works if they remember the password
14960
+ * of a deck they lost, which is precisely the moment they will not.
14961
+ *
14962
+ * ## The tradeoff this accepts (deliberately, not by omission)
14963
+ *
14964
+ * A password-protected deck DOES leave its content in cleartext at rest in the
14965
+ * origin's IndexedDB. Anyone with the browser profile, or any script running on
14966
+ * the origin, can read it. What limits the exposure: snapshots are scoped to
14967
+ * the origin and profile, aged out by the store, and clearable from
14968
+ * File > Account > Storage & Privacy (`clearLocalStorageData`). A user who
14969
+ * cannot accept plaintext at rest should switch AutoSave off, which stops the
14970
+ * snapshot being written at all.
14971
+ *
14972
+ * The rejected alternative was "skip autosave entirely while a password is
14973
+ * set". It removes the plaintext, but it also removes crash recovery without
14974
+ * telling anyone, so a crash loses the whole editing session. Losing data
14975
+ * quietly is the failure mode we are fixing, not a fix for it.
14854
14976
  */
14855
- type ShortcutChord = string;
14856
- /** Editor keyboard-shortcut customisation. */
14857
- interface KeyboardCustomization {
14858
- /** Turn every editor shortcut off (the host owns the keyboard). */
14859
- disableAll?: boolean;
14860
- /** Editor commands whose shortcut is turned off. */
14861
- disabled?: readonly EditorKeyActionName[];
14862
- /**
14863
- * Replacement chords per command. A remapped command no longer answers to
14864
- * its built-in chord; it answers to the chord(s) given here instead.
14865
- */
14866
- remap?: Partial<Record<EditorKeyActionName, ShortcutChord | readonly ShortcutChord[]>>;
14977
+ type DeckSavePurpose = 'user-file' | 'recovery-snapshot';
14978
+ /** A `p:showPr/p:sldRg` custom range, resolved to 0-based deck indexes. */
14979
+ interface AuthoredSlideRange {
14980
+ /** First slide of the range, 0-based, inclusive. */
14981
+ readonly fromIndex: number;
14982
+ /** Last slide of the range, 0-based, inclusive. */
14983
+ readonly toIndex: number;
14867
14984
  }
14985
+ //#endregion
14986
+ //#region src/export/handout-layout.d.ts
14868
14987
  /**
14869
- * Chrome regions a host can remove. Each id maps onto one region in every
14870
- * binding; see `VIEWER_PANEL_IDS` for the catalogue.
14871
- */
14872
- type ViewerPanelId = 'statusBar' | 'slidesPane' | 'inspector' | 'notes' | 'quickAccessToolbar' | 'titleBar';
14873
- /** Feature areas that can be switched off as a whole. */
14874
- type ViewerFeatureId = 'ai' | 'collaboration' | 'comments' | 'presentMode' | 'editPoints';
14875
- /**
14876
- * The click-to-place drawing tools of Insert > Shapes > Lines: Freeform:
14877
- * Shape and Curve.
14878
- */
14879
- type ViewerDrawingToolId = FreeformToolKind;
14880
- /** Dialogs (and the entry points that open them) a host can remove. */
14881
- type ViewerDialogId = 'options' | 'share' | 'broadcast' | 'print' | 'export';
14882
- /** Export formats offered by the File > Export page. */
14883
- type ViewerExportFormatId = 'pdf' | 'png' | 'video' | 'gif' | 'json' | 'copyImage';
14884
- /**
14885
- * The whole customisation object. Every field is optional; omitted fields hide
14886
- * nothing and lock nothing.
14988
+ * Pure handout layout calculations, shared by every binding's print path.
14989
+ *
14990
+ * Handles distributing slides across pages, computing grid dimensions, and
14991
+ * positioning cells within A4 page space. No DOM/framework dependency: callers
14992
+ * render the resulting rectangles however their view layer prefers.
14887
14993
  */
14888
- interface ViewerCustomization {
14889
- ribbon?: RibbonCustomization;
14890
- options?: OptionsCustomization;
14891
- backstage?: BackstageCustomization;
14892
- contextMenu?: ContextMenuCustomization;
14893
- keyboard?: KeyboardCustomization;
14894
- /** Chrome regions to remove (`true` hides). */
14895
- hiddenPanels?: readonly ViewerPanelId[];
14896
- /** Feature areas to switch off (their buttons, menus, pages and panels). */
14897
- disabledFeatures?: readonly ViewerFeatureId[];
14898
- /** Dialogs to remove, along with every entry point that opens them. */
14899
- hiddenDialogs?: readonly ViewerDialogId[];
14900
- /** Export formats to remove from File > Export. */
14901
- hiddenExportFormats?: readonly ViewerExportFormatId[];
14902
- /** Drawing tools to remove from the Insert > Shapes gallery. */
14903
- hiddenDrawingTools?: readonly ViewerDrawingToolId[];
14994
+ /** Supported slides-per-page values. */
14995
+ type HandoutSlidesPerPage = 1 | 2 | 3 | 4 | 6 | 9;
14996
+ //#endregion
14997
+ //#region src/export/print-document.d.ts
14998
+ /** What to print. */
14999
+ type PrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
15000
+ /** Page orientation for the printed output. */
15001
+ type PrintOrientation = 'portrait' | 'landscape';
15002
+ /** Colour mode for the printed output. */
15003
+ type PrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
15004
+ /** Slide range mode. */
15005
+ type PrintSlideRange = 'all' | 'current' | 'custom';
15006
+ /** Resolved print settings emitted on confirm. */
15007
+ interface PrintSettings {
15008
+ printWhat: PrintWhat;
15009
+ orientation: PrintOrientation;
15010
+ colorMode: PrintColorMode;
15011
+ frameSlides: boolean;
15012
+ slidesPerPage: HandoutSlidesPerPage;
15013
+ slideRange: PrintSlideRange;
15014
+ customRangeFrom: number;
15015
+ customRangeTo: number;
15016
+ /**
15017
+ * PowerPoint's Print > "Scale to Fit Paper". `true` (the default, and the
15018
+ * only behavior this printed output ever had before this field existed)
15019
+ * shrinks/grows each slide image to fill its page/cell while preserving
15020
+ * aspect ratio. `false` prints at the slide's native pixel size instead,
15021
+ * which may overflow or under-fill the page, exactly like PowerPoint with
15022
+ * the option off. Optional so existing `Partial<PrintSettings>` literals
15023
+ * across every binding keep compiling; `validatePrintSettings` defaults it
15024
+ * to `true`.
15025
+ */
15026
+ scaleToFit?: boolean;
14904
15027
  }
14905
15028
  //#endregion
14906
15029
  //#region src/render/options/viewer-options-constraints.d.ts
@@ -14963,102 +15086,16 @@ interface ViewerOptionsStore {
14963
15086
  /** True when the host locked `<group>.<key>`. */
14964
15087
  isLocked(group: ViewerOptionsGroupId, key: string): boolean;
14965
15088
  }
14966
- //#endregion
14967
- //#region src/render/customization/customization-keymap.d.ts
14968
- /** A parsed `Mod+Shift+D` chord. */
14969
- interface ParsedShortcutChord {
14970
- key: string;
14971
- mod: boolean;
14972
- ctrl: boolean;
14973
- meta: boolean;
14974
- alt: boolean;
14975
- shift: boolean;
14976
- }
14977
- /** The normalised keyboard slice of a resolved customisation. */
14978
- interface ResolvedKeyboardCustomization {
14979
- disableAll: boolean;
14980
- disabled: ReadonlySet<EditorKeyActionName>;
14981
- remap: ReadonlyMap<EditorKeyActionName, readonly ParsedShortcutChord[]>;
14982
- }
14983
- //#endregion
14984
- //#region src/render/customization/customization-resolve.d.ts
14985
- /** The normalised, set-based view of a customisation. Treat as immutable. */
14986
- interface ResolvedCustomization {
14987
- hiddenActions: ReadonlySet<ToolbarActionId>;
14988
- /** Contextual tabs (`shapeFormat`, ...) the host never wants shown. */
14989
- hiddenContextualTabs: ReadonlySet<RibbonContextualTabId>;
14990
- /** Catalogued ribbon groups to hide (`ribbon.hiddenGroups`). */
14991
- hiddenRibbonGroups: ReadonlySet<RibbonGroupId>;
14992
- /** Catalogued ribbon controls to hide (the `<tab>.<group>.<control>` part of `ribbon.hiddenButtons`). */
14993
- hiddenRibbonControls: ReadonlySet<RibbonControlId>;
14994
- hiddenOptionsPages: ReadonlySet<OptionsPageId>;
14995
- hiddenOptionsSections: ReadonlySet<OptionsSectionId>;
14996
- hiddenSettings: ReadonlySet<OptionsSettingId>;
14997
- lockedSettings: OptionsSettingValues;
14998
- defaultSettings: OptionsSettingValues;
14999
- hiddenBackstagePages: ReadonlySet<BackstagePage>;
15000
- hiddenBackstageCards: ReadonlySet<BackstageCardId>;
15001
- hiddenElementCommands: ReadonlySet<ContextMenuCommandId>;
15002
- hiddenCanvasCommands: ReadonlySet<CanvasContextMenuCommandId>;
15003
- hiddenEditPointsCommands: ReadonlySet<EditPointsCommandId>;
15004
- hiddenDrawingTools: ReadonlySet<ViewerDrawingToolId>;
15005
- elementMenuEnabled: boolean;
15006
- canvasMenuEnabled: boolean;
15007
- hiddenPanels: ReadonlySet<ViewerPanelId>;
15008
- disabledFeatures: ReadonlySet<ViewerFeatureId>;
15009
- hiddenDialogs: ReadonlySet<ViewerDialogId>;
15010
- keyboard: ResolvedKeyboardCustomization;
15089
+ interface SubtitleSettings {
15090
+ spokenLanguage: string;
15011
15091
  }
15012
- //#endregion
15013
- //#region src/render/customization/customization-controller.d.ts
15014
- /** The imperative methods every binding's component handle exposes. */
15015
- interface ViewerCustomizationApi {
15016
- /** The current customisation object (a snapshot; do not mutate). */
15017
- getCustomization(): ViewerCustomization;
15018
- /** Replace the whole customisation. */
15019
- setCustomization(next: ViewerCustomization): void;
15020
- /** Merge a partial customisation (see `mergeCustomization`). */
15021
- updateCustomization(patch: ViewerCustomization): void;
15022
- /** Drop every customisation, back to the stock UI. */
15023
- resetCustomization(): void;
15024
- /** Hide a fixed tab, or stop a contextual tab (`shapeFormat`, ...) from appearing. */
15025
- hideRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
15026
- showRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
15027
- /** Hide a group inside a tab (`home.font`). */
15028
- hideRibbonGroup(group: RibbonGroupId): void;
15029
- showRibbonGroup(group: RibbonGroupId): void;
15030
- /** Hide a top-level toolbar button or any ribbon control (`home.font.bold`). */
15031
- hideToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
15032
- showToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
15033
- /** Alias of `hideToolbarButton` for a ribbon control id. */
15034
- hideRibbonControl(control: RibbonControlId): void;
15035
- showRibbonControl(control: RibbonControlId): void;
15036
- hideOptionsPage(page: OptionsPageId): void;
15037
- showOptionsPage(page: OptionsPageId): void;
15038
- hideOptionsSection(section: OptionsSectionId): void;
15039
- showOptionsSection(section: OptionsSectionId): void;
15040
- hideSetting(setting: OptionsSettingId): void;
15041
- showSetting(setting: OptionsSettingId): void;
15042
- /** Pin a setting to `value`; `hidden` also removes it from the dialog. */
15043
- lockSetting(setting: OptionsSettingId, value: ViewerOptionPrimitive, hidden?: boolean): void;
15044
- unlockSetting(setting: OptionsSettingId): void;
15045
- /** Set (or with `undefined`, clear) the host default for a setting. */
15046
- setSettingDefault(setting: OptionsSettingId, value: ViewerOptionPrimitive | undefined): void;
15047
- hideBackstagePage(page: BackstagePage): void;
15048
- showBackstagePage(page: BackstagePage): void;
15049
- hideBackstageCard(card: BackstageCardId): void;
15050
- showBackstageCard(card: BackstageCardId): void;
15051
- hideContextMenuCommand(command: ContextMenuCommandId): void;
15052
- showContextMenuCommand(command: ContextMenuCommandId): void;
15053
- hideCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
15054
- showCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
15055
- disableShortcut(action: EditorKeyActionName): void;
15056
- enableShortcut(action: EditorKeyActionName): void;
15057
- /** Move a command onto new chord(s); `undefined` restores the built-in chord. */
15058
- remapShortcut(action: EditorKeyActionName, chords: ShortcutChord | readonly ShortcutChord[] | undefined): void;
15059
- setPanelVisible(panel: ViewerPanelId, visible: boolean): void;
15060
- setFeatureEnabled(feature: ViewerFeatureId, enabled: boolean): void;
15061
- setDialogAvailable(dialog: ViewerDialogId, available: boolean): void;
15092
+ interface SubtitleSettingsLabels {
15093
+ title: string;
15094
+ language: string;
15095
+ browserLanguage: string;
15096
+ description: string;
15097
+ apply: string;
15098
+ cancel: string;
15062
15099
  }
15063
15100
  type ReadOnlyRecommendationKind = 'modifyVerifier' | 'markedFinal' | null;
15064
15101
  interface ReadOnlyRecommendation {
@@ -15162,6 +15199,38 @@ interface CropSession {
15162
15199
  absentInsets: readonly (keyof CropInsets)[];
15163
15200
  }
15164
15201
  //#endregion
15202
+ //#region src/render/theme-editor-model.d.ts
15203
+ interface ThemeEditorEdit {
15204
+ name: string;
15205
+ colorScheme: PptxThemeColorScheme;
15206
+ fontScheme: PptxThemeFontScheme;
15207
+ }
15208
+ type ThemeEditorLabels = Record<string, string>;
15209
+ //#endregion
15210
+ //#region src/web-components/theme-editor.d.ts
15211
+ interface PptxUiThemeEditorElement extends HTMLElement {
15212
+ theme: PptxTheme | undefined;
15213
+ labels: ThemeEditorLabels;
15214
+ disabled: boolean;
15215
+ }
15216
+ declare global {
15217
+ interface HTMLElementTagNameMap {
15218
+ 'pptx-ui-theme-editor': PptxUiThemeEditorElement;
15219
+ }
15220
+ }
15221
+ //#endregion
15222
+ //#region src/web-components/subtitle-settings.d.ts
15223
+ interface PptxUiSubtitleSettingsElement extends HTMLElement {
15224
+ settings: SubtitleSettings;
15225
+ labels: SubtitleSettingsLabels;
15226
+ languageDisabled: boolean;
15227
+ }
15228
+ declare global {
15229
+ interface HTMLElementTagNameMap {
15230
+ 'pptx-ui-subtitle-settings': PptxUiSubtitleSettingsElement;
15231
+ }
15232
+ }
15233
+ //#endregion
15165
15234
  //#region src/web-components/select-value.d.ts
15166
15235
  /** Public DOM shape used by all bindings; the element is not a native select. */
15167
15236
  interface PptxUiSelectElement extends HTMLElement {
@@ -18320,6 +18389,7 @@ interface UseThemeHandlersInput {
18320
18389
  bumpHistory: () => void;
18321
18390
  }
18322
18391
  interface ThemeHandlersResult {
18392
+ handleApplyThemeEdit: (edit: ThemeEditorEdit) => Promise<void>;
18323
18393
  handleApplyTheme: (themePath: string, applyToAllMasters: boolean) => Promise<void>;
18324
18394
  handleUpdateThemeColorScheme: (colorScheme: PptxThemeColorScheme) => Promise<void>;
18325
18395
  handleUpdateThemeFontScheme: (fontScheme: PptxThemeFontScheme) => Promise<void>;