pptx-react-viewer 4.14.0 → 4.15.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 (111) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{AiChatPanel-WQUOEVQB.mjs → AiChatPanel-7OVUGUKW.mjs} +4 -4
  3. package/dist/AiChatPanel-7OVUGUKW.mjs.br +0 -0
  4. package/dist/AiChatPanel-7OVUGUKW.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-PULXQTFJ.js → AiChatPanel-CDQWJTWL.js} +28 -28
  6. package/dist/AiChatPanel-CDQWJTWL.js.br +0 -0
  7. package/dist/AiChatPanel-CDQWJTWL.js.gz +0 -0
  8. package/dist/{Model3DScene-HZG33BWN.mjs → Model3DScene-A3CPMFAO.mjs} +1 -1
  9. package/dist/Model3DScene-A3CPMFAO.mjs.br +0 -0
  10. package/dist/Model3DScene-A3CPMFAO.mjs.gz +0 -0
  11. package/dist/{Model3DScene-6MYHPE5N.js → Model3DScene-OLGB7Z7Q.js} +2 -2
  12. package/dist/Model3DScene-OLGB7Z7Q.js.br +0 -0
  13. package/dist/Model3DScene-OLGB7Z7Q.js.gz +0 -0
  14. package/dist/{chunk-6ZR27XTL.js → chunk-2CSRCH4H.js} +2321 -1211
  15. package/dist/chunk-2CSRCH4H.js.br +0 -0
  16. package/dist/chunk-2CSRCH4H.js.gz +0 -0
  17. package/dist/{chunk-RK5UV5HL.js → chunk-6ZPXMS64.js} +1517 -1526
  18. package/dist/chunk-6ZPXMS64.js.br +0 -0
  19. package/dist/chunk-6ZPXMS64.js.gz +0 -0
  20. package/dist/{chunk-ECKXYCP3.mjs → chunk-AHJ4ND7Q.mjs} +1 -1
  21. package/dist/chunk-AHJ4ND7Q.mjs.br +0 -0
  22. package/dist/chunk-AHJ4ND7Q.mjs.gz +0 -0
  23. package/dist/{chunk-UWVRB4Z5.mjs → chunk-AIWEM7VE.mjs} +2312 -1210
  24. package/dist/chunk-AIWEM7VE.mjs.br +0 -0
  25. package/dist/chunk-AIWEM7VE.mjs.gz +0 -0
  26. package/dist/{chunk-55OLQ7HS.mjs → chunk-CJSIEITL.mjs} +3 -0
  27. package/dist/chunk-CJSIEITL.mjs.br +0 -0
  28. package/dist/chunk-CJSIEITL.mjs.gz +0 -0
  29. package/dist/{chunk-DI4YTG3J.js → chunk-CNXVOFUW.js} +197 -197
  30. package/dist/chunk-CNXVOFUW.js.br +0 -0
  31. package/dist/{chunk-DI4YTG3J.js.gz → chunk-CNXVOFUW.js.gz} +0 -0
  32. package/dist/{chunk-EPMT65EN.mjs → chunk-DNWIW75I.mjs} +6 -5
  33. package/dist/chunk-DNWIW75I.mjs.br +0 -0
  34. package/dist/chunk-DNWIW75I.mjs.gz +0 -0
  35. package/dist/{chunk-E6VYR3GM.js → chunk-HGO243GV.js} +818 -816
  36. package/dist/chunk-HGO243GV.js.br +0 -0
  37. package/dist/chunk-HGO243GV.js.gz +0 -0
  38. package/dist/{chunk-AJTFPTSN.mjs → chunk-Q5VQ53R3.mjs} +2 -2
  39. package/dist/chunk-Q5VQ53R3.mjs.br +0 -0
  40. package/dist/chunk-Q5VQ53R3.mjs.gz +0 -0
  41. package/dist/{chunk-WSYKEPW6.mjs → chunk-RQCAXUVQ.mjs} +342 -351
  42. package/dist/chunk-RQCAXUVQ.mjs.br +0 -0
  43. package/dist/chunk-RQCAXUVQ.mjs.gz +0 -0
  44. package/dist/{chunk-XWO367ZG.js → chunk-UP6PJEHM.js} +5 -5
  45. package/dist/chunk-UP6PJEHM.js.br +0 -0
  46. package/dist/chunk-UP6PJEHM.js.gz +0 -0
  47. package/dist/{chunk-HIYK7HPX.js → chunk-XEYB25ZT.js} +3 -0
  48. package/dist/chunk-XEYB25ZT.js.br +0 -0
  49. package/dist/chunk-XEYB25ZT.js.gz +0 -0
  50. package/dist/i18n.js +4 -4
  51. package/dist/i18n.js.br +0 -0
  52. package/dist/i18n.js.gz +0 -0
  53. package/dist/i18n.mjs +1 -1
  54. package/dist/i18n.mjs.br +0 -0
  55. package/dist/i18n.mjs.gz +0 -0
  56. package/dist/index.d.ts +293 -268
  57. package/dist/index.js +63 -63
  58. package/dist/index.js.br +0 -0
  59. package/dist/index.js.gz +0 -0
  60. package/dist/index.mjs +6 -6
  61. package/dist/index.mjs.br +0 -0
  62. package/dist/index.mjs.gz +0 -0
  63. package/dist/internals.d.ts +600 -575
  64. package/dist/internals.js +105 -105
  65. package/dist/internals.js.br +0 -0
  66. package/dist/internals.js.gz +0 -0
  67. package/dist/internals.mjs +4 -4
  68. package/dist/internals.mjs.br +0 -0
  69. package/dist/internals.mjs.gz +0 -0
  70. package/dist/pptx-viewer.css +1 -1
  71. package/dist/pptx-viewer.css.br +0 -0
  72. package/dist/pptx-viewer.css.gz +0 -0
  73. package/dist/viewer/index.d.ts +161 -136
  74. package/dist/viewer/index.js +27 -27
  75. package/dist/viewer/index.js.br +0 -0
  76. package/dist/viewer/index.js.gz +0 -0
  77. package/dist/viewer/index.mjs +6 -6
  78. package/dist/viewer/index.mjs.br +0 -0
  79. package/dist/viewer/index.mjs.gz +0 -0
  80. package/package.json +1 -1
  81. package/dist/AiChatPanel-PULXQTFJ.js.br +0 -0
  82. package/dist/AiChatPanel-PULXQTFJ.js.gz +0 -0
  83. package/dist/AiChatPanel-WQUOEVQB.mjs.br +0 -0
  84. package/dist/AiChatPanel-WQUOEVQB.mjs.gz +0 -0
  85. package/dist/Model3DScene-6MYHPE5N.js.br +0 -0
  86. package/dist/Model3DScene-6MYHPE5N.js.gz +0 -0
  87. package/dist/Model3DScene-HZG33BWN.mjs.br +0 -0
  88. package/dist/Model3DScene-HZG33BWN.mjs.gz +0 -0
  89. package/dist/chunk-55OLQ7HS.mjs.br +0 -0
  90. package/dist/chunk-55OLQ7HS.mjs.gz +0 -0
  91. package/dist/chunk-6ZR27XTL.js.br +0 -0
  92. package/dist/chunk-6ZR27XTL.js.gz +0 -0
  93. package/dist/chunk-AJTFPTSN.mjs.br +0 -0
  94. package/dist/chunk-AJTFPTSN.mjs.gz +0 -0
  95. package/dist/chunk-DI4YTG3J.js.br +0 -0
  96. package/dist/chunk-E6VYR3GM.js.br +0 -0
  97. package/dist/chunk-E6VYR3GM.js.gz +0 -0
  98. package/dist/chunk-ECKXYCP3.mjs.br +0 -0
  99. package/dist/chunk-ECKXYCP3.mjs.gz +0 -0
  100. package/dist/chunk-EPMT65EN.mjs.br +0 -0
  101. package/dist/chunk-EPMT65EN.mjs.gz +0 -0
  102. package/dist/chunk-HIYK7HPX.js.br +0 -0
  103. package/dist/chunk-HIYK7HPX.js.gz +0 -0
  104. package/dist/chunk-RK5UV5HL.js.br +0 -0
  105. package/dist/chunk-RK5UV5HL.js.gz +0 -0
  106. package/dist/chunk-UWVRB4Z5.mjs.br +0 -0
  107. package/dist/chunk-UWVRB4Z5.mjs.gz +0 -0
  108. package/dist/chunk-WSYKEPW6.mjs.br +0 -0
  109. package/dist/chunk-WSYKEPW6.mjs.gz +0 -0
  110. package/dist/chunk-XWO367ZG.js.br +0 -0
  111. 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,12 @@ 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;
14209
- //#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;
14240
- }
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';
13916
+ type ViewerOptionsTabId = 'general' | 'proofing' | 'save' | 'language' | 'accessibility' | 'advanced' | 'ribbon' | 'quickAccess' | 'addIns' | 'trust';
14254
13917
  //#endregion
14255
13918
  //#region src/render/customization/ribbon-control-catalog.d.ts
14256
13919
  declare const RIBBON_CONTROL_CATALOG: {
@@ -14847,60 +14510,496 @@ interface ContextMenuCustomization {
14847
14510
  /** Remove the empty-canvas context menu entirely. */
14848
14511
  disableCanvasMenu?: boolean;
14849
14512
  }
14850
- /**
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`).
14854
- */
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[]>>;
14513
+ /**
14514
+ * A shortcut chord in the form `Mod+Shift+D`: modifiers `Mod` (Ctrl on
14515
+ * Windows/Linux, Cmd on macOS), `Ctrl`, `Meta`, `Alt`, `Shift`, joined by `+`,
14516
+ * followed by a `KeyboardEvent.key` value (`D`, `Delete`, `ArrowLeft`, `F2`).
14517
+ */
14518
+ type ShortcutChord = string;
14519
+ /** Editor keyboard-shortcut customisation. */
14520
+ interface KeyboardCustomization {
14521
+ /** Turn every editor shortcut off (the host owns the keyboard). */
14522
+ disableAll?: boolean;
14523
+ /** Editor commands whose shortcut is turned off. */
14524
+ disabled?: readonly EditorKeyActionName[];
14525
+ /**
14526
+ * Replacement chords per command. A remapped command no longer answers to
14527
+ * its built-in chord; it answers to the chord(s) given here instead.
14528
+ */
14529
+ remap?: Partial<Record<EditorKeyActionName, ShortcutChord | readonly ShortcutChord[]>>;
14530
+ }
14531
+ /**
14532
+ * Chrome regions a host can remove. Each id maps onto one region in every
14533
+ * binding; see `VIEWER_PANEL_IDS` for the catalogue.
14534
+ */
14535
+ type ViewerPanelId = 'statusBar' | 'slidesPane' | 'inspector' | 'notes' | 'quickAccessToolbar' | 'titleBar';
14536
+ /** Feature areas that can be switched off as a whole. */
14537
+ type ViewerFeatureId = 'ai' | 'collaboration' | 'comments' | 'presentMode' | 'editPoints';
14538
+ /**
14539
+ * The click-to-place drawing tools of Insert > Shapes > Lines: Freeform:
14540
+ * Shape and Curve.
14541
+ */
14542
+ type ViewerDrawingToolId = FreeformToolKind;
14543
+ /** Dialogs (and the entry points that open them) a host can remove. */
14544
+ type ViewerDialogId = 'options' | 'share' | 'broadcast' | 'print' | 'export';
14545
+ /** Export formats offered by the File > Export page. */
14546
+ type ViewerExportFormatId = 'pdf' | 'png' | 'video' | 'gif' | 'json' | 'copyImage';
14547
+ /**
14548
+ * The whole customisation object. Every field is optional; omitted fields hide
14549
+ * nothing and lock nothing.
14550
+ */
14551
+ interface ViewerCustomization {
14552
+ ribbon?: RibbonCustomization;
14553
+ options?: OptionsCustomization;
14554
+ backstage?: BackstageCustomization;
14555
+ contextMenu?: ContextMenuCustomization;
14556
+ keyboard?: KeyboardCustomization;
14557
+ /** Chrome regions to remove (`true` hides). */
14558
+ hiddenPanels?: readonly ViewerPanelId[];
14559
+ /** Feature areas to switch off (their buttons, menus, pages and panels). */
14560
+ disabledFeatures?: readonly ViewerFeatureId[];
14561
+ /** Dialogs to remove, along with every entry point that opens them. */
14562
+ hiddenDialogs?: readonly ViewerDialogId[];
14563
+ /** Export formats to remove from File > Export. */
14564
+ hiddenExportFormats?: readonly ViewerExportFormatId[];
14565
+ /** Drawing tools to remove from the Insert > Shapes gallery. */
14566
+ hiddenDrawingTools?: readonly ViewerDrawingToolId[];
14567
+ }
14568
+ //#endregion
14569
+ //#region src/render/customization/customization-keymap.d.ts
14570
+ /** A parsed `Mod+Shift+D` chord. */
14571
+ interface ParsedShortcutChord {
14572
+ key: string;
14573
+ mod: boolean;
14574
+ ctrl: boolean;
14575
+ meta: boolean;
14576
+ alt: boolean;
14577
+ shift: boolean;
14578
+ }
14579
+ /** The normalised keyboard slice of a resolved customisation. */
14580
+ interface ResolvedKeyboardCustomization {
14581
+ disableAll: boolean;
14582
+ disabled: ReadonlySet<EditorKeyActionName>;
14583
+ remap: ReadonlyMap<EditorKeyActionName, readonly ParsedShortcutChord[]>;
14584
+ }
14585
+ //#endregion
14586
+ //#region src/render/customization/customization-resolve.d.ts
14587
+ /** The normalised, set-based view of a customisation. Treat as immutable. */
14588
+ interface ResolvedCustomization {
14589
+ hiddenActions: ReadonlySet<ToolbarActionId>;
14590
+ /** Contextual tabs (`shapeFormat`, ...) the host never wants shown. */
14591
+ hiddenContextualTabs: ReadonlySet<RibbonContextualTabId>;
14592
+ /** Catalogued ribbon groups to hide (`ribbon.hiddenGroups`). */
14593
+ hiddenRibbonGroups: ReadonlySet<RibbonGroupId>;
14594
+ /** Catalogued ribbon controls to hide (the `<tab>.<group>.<control>` part of `ribbon.hiddenButtons`). */
14595
+ hiddenRibbonControls: ReadonlySet<RibbonControlId>;
14596
+ hiddenOptionsPages: ReadonlySet<OptionsPageId>;
14597
+ hiddenOptionsSections: ReadonlySet<OptionsSectionId>;
14598
+ hiddenSettings: ReadonlySet<OptionsSettingId>;
14599
+ lockedSettings: OptionsSettingValues;
14600
+ defaultSettings: OptionsSettingValues;
14601
+ hiddenBackstagePages: ReadonlySet<BackstagePage>;
14602
+ hiddenBackstageCards: ReadonlySet<BackstageCardId>;
14603
+ hiddenElementCommands: ReadonlySet<ContextMenuCommandId>;
14604
+ hiddenCanvasCommands: ReadonlySet<CanvasContextMenuCommandId>;
14605
+ hiddenEditPointsCommands: ReadonlySet<EditPointsCommandId>;
14606
+ hiddenDrawingTools: ReadonlySet<ViewerDrawingToolId>;
14607
+ elementMenuEnabled: boolean;
14608
+ canvasMenuEnabled: boolean;
14609
+ hiddenPanels: ReadonlySet<ViewerPanelId>;
14610
+ disabledFeatures: ReadonlySet<ViewerFeatureId>;
14611
+ hiddenDialogs: ReadonlySet<ViewerDialogId>;
14612
+ keyboard: ResolvedKeyboardCustomization;
14613
+ }
14614
+ //#endregion
14615
+ //#region src/render/customization/customization-controller.d.ts
14616
+ /** The imperative methods every binding's component handle exposes. */
14617
+ interface ViewerCustomizationApi {
14618
+ /** The current customisation object (a snapshot; do not mutate). */
14619
+ getCustomization(): ViewerCustomization;
14620
+ /** Replace the whole customisation. */
14621
+ setCustomization(next: ViewerCustomization): void;
14622
+ /** Merge a partial customisation (see `mergeCustomization`). */
14623
+ updateCustomization(patch: ViewerCustomization): void;
14624
+ /** Drop every customisation, back to the stock UI. */
14625
+ resetCustomization(): void;
14626
+ /** Hide a fixed tab, or stop a contextual tab (`shapeFormat`, ...) from appearing. */
14627
+ hideRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
14628
+ showRibbonTab(tab: ToolbarTabId | RibbonContextualTabId): void;
14629
+ /** Hide a group inside a tab (`home.font`). */
14630
+ hideRibbonGroup(group: RibbonGroupId): void;
14631
+ showRibbonGroup(group: RibbonGroupId): void;
14632
+ /** Hide a top-level toolbar button or any ribbon control (`home.font.bold`). */
14633
+ hideToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
14634
+ showToolbarButton(button: ToolbarButtonId | RibbonControlId): void;
14635
+ /** Alias of `hideToolbarButton` for a ribbon control id. */
14636
+ hideRibbonControl(control: RibbonControlId): void;
14637
+ showRibbonControl(control: RibbonControlId): void;
14638
+ hideOptionsPage(page: OptionsPageId): void;
14639
+ showOptionsPage(page: OptionsPageId): void;
14640
+ hideOptionsSection(section: OptionsSectionId): void;
14641
+ showOptionsSection(section: OptionsSectionId): void;
14642
+ hideSetting(setting: OptionsSettingId): void;
14643
+ showSetting(setting: OptionsSettingId): void;
14644
+ /** Pin a setting to `value`; `hidden` also removes it from the dialog. */
14645
+ lockSetting(setting: OptionsSettingId, value: ViewerOptionPrimitive, hidden?: boolean): void;
14646
+ unlockSetting(setting: OptionsSettingId): void;
14647
+ /** Set (or with `undefined`, clear) the host default for a setting. */
14648
+ setSettingDefault(setting: OptionsSettingId, value: ViewerOptionPrimitive | undefined): void;
14649
+ hideBackstagePage(page: BackstagePage): void;
14650
+ showBackstagePage(page: BackstagePage): void;
14651
+ hideBackstageCard(card: BackstageCardId): void;
14652
+ showBackstageCard(card: BackstageCardId): void;
14653
+ hideContextMenuCommand(command: ContextMenuCommandId): void;
14654
+ showContextMenuCommand(command: ContextMenuCommandId): void;
14655
+ hideCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
14656
+ showCanvasContextMenuCommand(command: CanvasContextMenuCommandId): void;
14657
+ disableShortcut(action: EditorKeyActionName): void;
14658
+ enableShortcut(action: EditorKeyActionName): void;
14659
+ /** Move a command onto new chord(s); `undefined` restores the built-in chord. */
14660
+ remapShortcut(action: EditorKeyActionName, chords: ShortcutChord | readonly ShortcutChord[] | undefined): void;
14661
+ setPanelVisible(panel: ViewerPanelId, visible: boolean): void;
14662
+ setFeatureEnabled(feature: ViewerFeatureId, enabled: boolean): void;
14663
+ setDialogAvailable(dialog: ViewerDialogId, available: boolean): void;
14664
+ }
14665
+ //#endregion
14666
+ //#region src/render/p14-transition-keyframes.d.ts
14667
+ /** Part 1: conveyor / doors / ferris / flash / flythrough / gallery / glitter / honeycomb / pan. */
14668
+ 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";
14669
+ /** Part 2: prism / reveal / ripple / shred / switch / vortex / warp / wheelReverse / window. */
14670
+ 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";
14671
+ /** Both p14 keyframe blocks concatenated, for single `<style>` injection. */
14672
+ 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";
14673
+ //#endregion
14674
+ //#region src/render/p14-transition-css.d.ts
14675
+ /**
14676
+ * Return CSS animation descriptors for p14 transition types. Returns
14677
+ * `undefined` when the type is not a p14 transition.
14678
+ */
14679
+ declare function getP14TransitionAnimations(type: PptxTransitionType, durationMs: number, direction: string | undefined, orient?: string | undefined, pattern?: string | undefined): SlideTransitionAnimations | undefined;
14680
+ interface SlideSizeEmu {
14681
+ widthEmu: number;
14682
+ heightEmu: number;
14683
+ /** ST_SlideSizeType token, or `''` for a size with no preset. */
14684
+ type: string;
14685
+ }
14686
+ //#endregion
14687
+ //#region src/render/mobile-viewport.d.ts
14688
+ /**
14689
+ * mobile-viewport.ts: framework-agnostic viewport / touch / orientation
14690
+ * detection shared by the React, Vue, and Angular bindings.
14691
+ *
14692
+ * These are the pure predicates and feature-detection helpers behind each
14693
+ * binding's `useIsMobile` / `IsMobileService`. The reactive wiring (React
14694
+ * state, Vue refs, Angular signals) stays in the binding; the breakpoint maths
14695
+ * and DOM capability probes live here so all three frameworks switch chrome at
14696
+ * exactly the same thresholds.
14697
+ *
14698
+ * SSR / test safe: every probe feature-detects `window` / `navigator` /
14699
+ * `screen` and returns a sensible default when absent.
14700
+ */
14701
+ /** Mobile breakpoint: below this width is considered mobile. */
14702
+ declare const MOBILE_BREAKPOINT = 768;
14703
+ /** Tablet breakpoint: below this width (but >= MOBILE) is tablet. */
14704
+ declare const TABLET_BREAKPOINT = 1024;
14705
+ /** Device orientation as reported by the screen / viewport aspect ratio. */
14706
+ type DeviceOrientation = 'portrait' | 'landscape';
14707
+ //#endregion
14708
+ //#region src/render/presentation-session-types.d.ts
14709
+ interface PresentationSnapshot {
14710
+ slideIndex: number;
14711
+ buildStep: number;
14712
+ sequence: number;
14713
+ blackout: 'none' | 'black' | 'white';
14714
+ paused: boolean;
14715
+ elapsedMs: number;
14716
+ zoom?: PresentationZoomState;
14717
+ pointer?: PresentationPointerState;
14718
+ inkStrokes?: PresentationInkStroke[];
14719
+ /**
14720
+ * Whether ink markup is drawn (PowerPoint's Ctrl+M). Undefined means visible,
14721
+ * so existing snapshots keep showing their ink. Hiding never discards the
14722
+ * strokes, which stay in `inkStrokes` and can be kept on exit.
14723
+ */
14724
+ inkMarkupVisible?: boolean;
14725
+ caption?: string;
14726
+ subtitlesVisible?: boolean;
14727
+ }
14728
+ interface PresentationZoomState {
14729
+ scale: number;
14730
+ originX: number;
14731
+ originY: number;
14732
+ }
14733
+ type PresentationPointerTool = 'none' | 'laser' | 'pen' | 'highlighter' | 'eraser';
14734
+ interface PresentationPointerState {
14735
+ tool: PresentationPointerTool;
14736
+ x: number;
14737
+ y: number;
14738
+ color: string;
14739
+ }
14740
+ interface PresentationInkPoint {
14741
+ x: number;
14742
+ y: number;
14743
+ }
14744
+ interface PresentationInkStroke {
14745
+ id: string;
14746
+ slideIndex: number;
14747
+ tool: 'pen' | 'highlighter';
14748
+ color: string;
14749
+ width: number;
14750
+ points: PresentationInkPoint[];
14751
+ }
14752
+ //#endregion
14753
+ //#region src/render/paste-special.d.ts
14754
+ /** The four paste formats PowerPoint's Paste Options / Paste Special offer. */
14755
+ type PasteSpecialFormat = 'keep-source-formatting' | 'use-destination-theme' | 'picture' | 'keep-text-only';
14756
+ //#endregion
14757
+ //#region src/render/find-replace.d.ts
14758
+ /** Identifies a single match of the find query at segment-level precision. */
14759
+ interface FindResult {
14760
+ /** Zero-based index of the slide in the slides array. */
14761
+ slideIndex: number;
14762
+ /** Id of the element that contains the match. */
14763
+ elementId: string;
14764
+ /** Zero-based index of the text segment within the element's `textSegments`. */
14765
+ segmentIndex: number;
14766
+ /** Character offset of the match start within the segment text. */
14767
+ startOffset: number;
14768
+ /** Number of characters matched (equals `query.length`). */
14769
+ length: number;
14770
+ }
14771
+ interface TouchGestureCallbacks {
14772
+ /** Called continuously during a pinch gesture with the new (clamped) scale. */
14773
+ onPinchZoom?: (newScale: number) => void;
14774
+ /** Called when a horizontal swipe is detected. direction: -1 = left, 1 = right. */
14775
+ onSwipe?: (direction: -1 | 1) => void;
14776
+ /** Called when a long-press is detected, with the press coordinates. */
14777
+ onLongPress?: (clientX: number, clientY: number) => void;
14778
+ }
14779
+ //#endregion
14780
+ //#region src/render/insert-chart.d.ts
14781
+ /**
14782
+ * Dropdown ids for the insert-chart menu. Distinct from `PptxChartType`
14783
+ * because PowerPoint offers Column (vertical) and Bar (horizontal) as two
14784
+ * entries over the same underlying `'bar'` chart type, and because `'pareto'`
14785
+ * has no `PptxChartType` of its own: it is a dropdown entry that resolves to
14786
+ * `type: 'histogram'` (see docs/guide/limitations.md's ChartEx row) with a
14787
+ * frequency-plus-cumulative-percentage default shape. The other six ChartEx
14788
+ * ids (`histogram` through `regionMap`) map one-to-one onto their chart type.
14789
+ */
14790
+ type InsertChartKind = 'column' | 'bar' | 'line' | 'pie' | 'doughnut' | 'area' | 'scatter' | 'histogram' | 'pareto' | 'funnel' | 'treemap' | 'sunburst' | 'boxWhisker' | 'regionMap';
14791
+ /** In-memory clipboard payload stored when an element is copied or cut. */
14792
+ interface ElementClipboardPayload {
14793
+ element: PptxElement;
14794
+ isTemplate: boolean;
14795
+ }
14796
+ //#endregion
14797
+ //#region src/render/editor-image-paste.d.ts
14798
+ /** A currently editable slide. Return null while loading or outside canvas editing. */
14799
+ interface EditorImagePasteTarget {
14800
+ documentId: object;
14801
+ slideId: string;
14802
+ canvasSize: CanvasSize$1;
14803
+ }
14804
+ interface EditorImagePasteOptions {
14805
+ getCanvas(): HTMLElement | null;
14806
+ getTarget(): EditorImagePasteTarget | null;
14807
+ /** Use the normal editor command so selection, dirty state and Undo stay consistent. */
14808
+ insertElement(element: ImagePptxElement): void;
14809
+ }
14810
+ /** What the "Embed fonts in the file" toggle should look like and do. */
14811
+ interface FontEmbeddingDescriptor {
14812
+ /** Distinct typeface names the loaded deck currently embeds. */
14813
+ embeddedFamilies: string[];
14814
+ /**
14815
+ * Whether the toggle accepts input. False when the deck embeds nothing,
14816
+ * because turning it on could not produce an embedded font.
14817
+ */
14818
+ interactive: boolean;
14819
+ /**
14820
+ * The position the toggle must START in so that it describes the file that
14821
+ * would be written right now. A deck that arrived with embedded fonts keeps
14822
+ * them on save, so the switch has to read "on" from the outset; the previous
14823
+ * hardcoded `false` said the opposite of what save actually did.
14824
+ */
14825
+ initialEnabled: boolean;
14826
+ /** Present only when `interactive` is false. */
14827
+ disabledReasonKey?: string;
14828
+ }
14829
+ //#endregion
14830
+ //#region src/render/zoom-return-navigation.d.ts
14831
+ /**
14832
+ * The navigation-relevant fields of a Zoom click target, independent of
14833
+ * `zoomType`.
14834
+ *
14835
+ * `returnToParent` is already resolved to its EFFECTIVE value here (not the
14836
+ * raw, possibly-`undefined` `ZoomPptxElement`/`SummaryZoomTarget` field):
14837
+ * `CT_ZoomObjectProperties/@returnToParent` (MS-PPTX) is `<xsd:attribute
14838
+ * name="returnToParent" type="xsd:boolean" use="optional" default="true"/>`,
14839
+ * so an ABSENT attribute means true, not false. Core deliberately stores
14840
+ * `undefined` rather than fabricating `true` (so a round-trip never invents
14841
+ * an attribute the source never had), which makes `Boolean(x)` the wrong way
14842
+ * to read it; the two `resolve*NavigationTarget` functions below are the only
14843
+ * place that distinction should be made.
14844
+ */
14845
+ interface ZoomNavigationTarget {
14846
+ targetSlideIndex: number;
14847
+ targetSectionId?: string;
14848
+ returnToParent: boolean;
14849
+ transitionDurationMs?: number;
14850
+ }
14851
+ /** A pending "return to the zoom's origin slide" excursion, tracked by the binding across forward-advance steps. */
14852
+ interface ZoomExcursion {
14853
+ /** The slide to jump back to once `endSlideIndex` is passed (the slide the zoom was clicked from). */
14854
+ returnSlideIndex: number;
14855
+ /** The last slide index of the zoom's target range; see {@link resolveZoomExcursionEndIndex}. */
14856
+ endSlideIndex: number;
14857
+ /** The zoom's own `transitionDur`, applied to the jump INTO the target and to the return jump. */
14858
+ transitionDurationMs?: number;
14859
+ }
14860
+ /** Everything a binding needs to render the recovery dialog, and nothing else. */
14861
+ interface AutosaveRecoveryPrompt {
14862
+ /** IndexedDB key the snapshot is stored under (the deck's file path/name). */
14863
+ readonly filePath: string;
14864
+ /** When the snapshot was written (epoch ms). */
14865
+ readonly timestamp: number;
14866
+ /** Snapshot size in bytes. */
14867
+ readonly size: number;
14868
+ /** Whole minutes since it was written, floored at 0. */
14869
+ readonly ageMinutes: number;
14870
+ readonly titleKey: string;
14871
+ readonly messageKey: string;
14872
+ /** `size` is pre-formatted here because byte units are not translated. */
14873
+ readonly messageParams: {
14874
+ readonly file: string;
14875
+ readonly size: string;
14876
+ };
14877
+ /** Relative age, reusing the existing autosave age keys. */
14878
+ readonly ageKey: string;
14879
+ readonly ageParams: {
14880
+ readonly count: number;
14881
+ };
14882
+ readonly restoreKey: string;
14883
+ readonly discardKey: string;
14884
+ }
14885
+ //#endregion
14886
+ //#region src/render/master-view.d.ts
14887
+ /** Which part the master view is currently pointed at. */
14888
+ interface MasterViewTarget {
14889
+ tab: MasterViewTab;
14890
+ masterIndex: number;
14891
+ /** `null` selects the master itself rather than one of its layouts. */
14892
+ layoutIndex: number | null;
14893
+ }
14894
+ //#endregion
14895
+ //#region src/render/virtualized-list.d.ts
14896
+ /** Framework-neutral virtual-list range used by every thumbnail sidebar. */
14897
+ interface VirtualizedRange {
14898
+ startIndex: number;
14899
+ endIndex: number;
14900
+ totalHeight: number;
14901
+ offsetY: number;
14902
+ visibleRange: {
14903
+ start: number;
14904
+ end: number;
14905
+ };
14867
14906
  }
14907
+ /** Compute the rendered item window for fixed-height virtual lists. */
14908
+ declare function computeVirtualRange(totalItems: number, itemHeight: number, scrollTop: number, viewportHeight: number, overscan?: number): VirtualizedRange;
14868
14909
  /**
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.
14910
+ * Why the deck is being serialised, which is a separate question from whether
14911
+ * the user protected it.
14912
+ *
14913
+ * - `user-file` (the default): the bytes leave the viewer as a file. Save,
14914
+ * Save As, Export, the host-facing `getContent()`. Protection applies.
14915
+ * - `recovery-snapshot`: the bytes exist only so the viewer can read them back.
14916
+ * The autosave crash-recovery snapshot in IndexedDB, and the internal
14917
+ * re-serialise-then-reload cycle behind "apply theme". Protection does NOT
14918
+ * apply: these are always written in the clear.
14919
+ *
14920
+ * ## Why a recovery snapshot must stay plaintext
14921
+ *
14922
+ * Nothing that reads a snapshot back has a password to give it.
14923
+ * `readBackstageRecentFile`, `restoreSessionDeck` and the Version History
14924
+ * panel's Restore all hand `record.data` straight to `PptxHandler.load()` with
14925
+ * no `password` option, and an encrypted package refuses to open without one
14926
+ * (`EncryptedFileError`). So an encrypted snapshot is not an inconvenience, it
14927
+ * is unreadable: the moment the user turns on protection their crash-recovery
14928
+ * data is silently destroyed, which is the exact opposite of what autosave is
14929
+ * for.
14930
+ *
14931
+ * Encrypting it "properly" is not available either. Decrypting on recovery
14932
+ * means the key has to outlive the crash the snapshot exists for, so it would
14933
+ * have to sit in the same IndexedDB / localStorage as the snapshot itself,
14934
+ * next to the ciphertext it unlocks. That is not a security boundary, it is
14935
+ * theatre. Prompting the user instead only works if they remember the password
14936
+ * of a deck they lost, which is precisely the moment they will not.
14937
+ *
14938
+ * ## The tradeoff this accepts (deliberately, not by omission)
14939
+ *
14940
+ * A password-protected deck DOES leave its content in cleartext at rest in the
14941
+ * origin's IndexedDB. Anyone with the browser profile, or any script running on
14942
+ * the origin, can read it. What limits the exposure: snapshots are scoped to
14943
+ * the origin and profile, aged out by the store, and clearable from
14944
+ * File > Account > Storage & Privacy (`clearLocalStorageData`). A user who
14945
+ * cannot accept plaintext at rest should switch AutoSave off, which stops the
14946
+ * snapshot being written at all.
14947
+ *
14948
+ * The rejected alternative was "skip autosave entirely while a password is
14949
+ * set". It removes the plaintext, but it also removes crash recovery without
14950
+ * telling anyone, so a crash loses the whole editing session. Losing data
14951
+ * quietly is the failure mode we are fixing, not a fix for it.
14878
14952
  */
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';
14953
+ type DeckSavePurpose = 'user-file' | 'recovery-snapshot';
14954
+ /** A `p:showPr/p:sldRg` custom range, resolved to 0-based deck indexes. */
14955
+ interface AuthoredSlideRange {
14956
+ /** First slide of the range, 0-based, inclusive. */
14957
+ readonly fromIndex: number;
14958
+ /** Last slide of the range, 0-based, inclusive. */
14959
+ readonly toIndex: number;
14960
+ }
14961
+ //#endregion
14962
+ //#region src/export/handout-layout.d.ts
14884
14963
  /**
14885
- * The whole customisation object. Every field is optional; omitted fields hide
14886
- * nothing and lock nothing.
14964
+ * Pure handout layout calculations, shared by every binding's print path.
14965
+ *
14966
+ * Handles distributing slides across pages, computing grid dimensions, and
14967
+ * positioning cells within A4 page space. No DOM/framework dependency: callers
14968
+ * render the resulting rectangles however their view layer prefers.
14887
14969
  */
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[];
14970
+ /** Supported slides-per-page values. */
14971
+ type HandoutSlidesPerPage = 1 | 2 | 3 | 4 | 6 | 9;
14972
+ //#endregion
14973
+ //#region src/export/print-document.d.ts
14974
+ /** What to print. */
14975
+ type PrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
14976
+ /** Page orientation for the printed output. */
14977
+ type PrintOrientation = 'portrait' | 'landscape';
14978
+ /** Colour mode for the printed output. */
14979
+ type PrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
14980
+ /** Slide range mode. */
14981
+ type PrintSlideRange = 'all' | 'current' | 'custom';
14982
+ /** Resolved print settings emitted on confirm. */
14983
+ interface PrintSettings {
14984
+ printWhat: PrintWhat;
14985
+ orientation: PrintOrientation;
14986
+ colorMode: PrintColorMode;
14987
+ frameSlides: boolean;
14988
+ slidesPerPage: HandoutSlidesPerPage;
14989
+ slideRange: PrintSlideRange;
14990
+ customRangeFrom: number;
14991
+ customRangeTo: number;
14992
+ /**
14993
+ * PowerPoint's Print > "Scale to Fit Paper". `true` (the default, and the
14994
+ * only behavior this printed output ever had before this field existed)
14995
+ * shrinks/grows each slide image to fill its page/cell while preserving
14996
+ * aspect ratio. `false` prints at the slide's native pixel size instead,
14997
+ * which may overflow or under-fill the page, exactly like PowerPoint with
14998
+ * the option off. Optional so existing `Partial<PrintSettings>` literals
14999
+ * across every binding keep compiling; `validatePrintSettings` defaults it
15000
+ * to `true`.
15001
+ */
15002
+ scaleToFit?: boolean;
14904
15003
  }
14905
15004
  //#endregion
14906
15005
  //#region src/render/options/viewer-options-constraints.d.ts
@@ -14963,102 +15062,16 @@ interface ViewerOptionsStore {
14963
15062
  /** True when the host locked `<group>.<key>`. */
14964
15063
  isLocked(group: ViewerOptionsGroupId, key: string): boolean;
14965
15064
  }
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;
15065
+ interface SubtitleSettings {
15066
+ spokenLanguage: string;
15011
15067
  }
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;
15068
+ interface SubtitleSettingsLabels {
15069
+ title: string;
15070
+ language: string;
15071
+ browserLanguage: string;
15072
+ description: string;
15073
+ apply: string;
15074
+ cancel: string;
15062
15075
  }
15063
15076
  type ReadOnlyRecommendationKind = 'modifyVerifier' | 'markedFinal' | null;
15064
15077
  interface ReadOnlyRecommendation {
@@ -15162,6 +15175,18 @@ interface CropSession {
15162
15175
  absentInsets: readonly (keyof CropInsets)[];
15163
15176
  }
15164
15177
  //#endregion
15178
+ //#region src/web-components/subtitle-settings.d.ts
15179
+ interface PptxUiSubtitleSettingsElement extends HTMLElement {
15180
+ settings: SubtitleSettings;
15181
+ labels: SubtitleSettingsLabels;
15182
+ languageDisabled: boolean;
15183
+ }
15184
+ declare global {
15185
+ interface HTMLElementTagNameMap {
15186
+ 'pptx-ui-subtitle-settings': PptxUiSubtitleSettingsElement;
15187
+ }
15188
+ }
15189
+ //#endregion
15165
15190
  //#region src/web-components/select-value.d.ts
15166
15191
  /** Public DOM shape used by all bindings; the element is not a native select. */
15167
15192
  interface PptxUiSelectElement extends HTMLElement {