pptx-react-viewer 1.25.5 → 2.0.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 (230) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +1 -1
  3. package/dist/AiChatPanel-BRGQCYZM.mjs +1087 -0
  4. package/dist/AiChatPanel-BRGQCYZM.mjs.br +0 -0
  5. package/dist/AiChatPanel-BRGQCYZM.mjs.gz +0 -0
  6. package/dist/AiChatPanel-PW5OT25Z.js +1089 -0
  7. package/dist/AiChatPanel-PW5OT25Z.js.br +0 -0
  8. package/dist/AiChatPanel-PW5OT25Z.js.gz +0 -0
  9. package/dist/{GLTFLoader-NMAS6VRH.mjs → GLTFLoader-374ZNTXW.mjs} +1 -1
  10. package/dist/GLTFLoader-374ZNTXW.mjs.br +0 -0
  11. package/dist/GLTFLoader-374ZNTXW.mjs.gz +0 -0
  12. package/dist/{GLTFLoader-GP55DVVS.js → GLTFLoader-Q7BHCGAW.js} +1 -1
  13. package/dist/GLTFLoader-Q7BHCGAW.js.br +0 -0
  14. package/dist/GLTFLoader-Q7BHCGAW.js.gz +0 -0
  15. package/dist/{Model3DScene-Y5ABLO7K.js → Model3DScene-JCGYRKXM.js} +4 -4
  16. package/dist/Model3DScene-JCGYRKXM.js.br +0 -0
  17. package/dist/Model3DScene-JCGYRKXM.js.gz +0 -0
  18. package/dist/{Model3DScene-XVYOISVJ.mjs → Model3DScene-TEF362W2.mjs} +3 -3
  19. package/dist/Model3DScene-TEF362W2.mjs.br +0 -0
  20. package/dist/Model3DScene-TEF362W2.mjs.gz +0 -0
  21. package/dist/{OrbitControls-VH6KILH7.js → OrbitControls-SMYCPLXO.js} +1 -1
  22. package/dist/OrbitControls-SMYCPLXO.js.br +3 -0
  23. package/dist/OrbitControls-SMYCPLXO.js.gz +0 -0
  24. package/dist/{OrbitControls-F5XPYD2Z.mjs → OrbitControls-ZTGHPI5G.mjs} +1 -1
  25. package/dist/OrbitControls-ZTGHPI5G.mjs.br +0 -0
  26. package/dist/{OrbitControls-F5XPYD2Z.mjs.gz → OrbitControls-ZTGHPI5G.mjs.gz} +0 -0
  27. package/dist/{PowerPointViewer-CnADroqZ.d.ts → PowerPointViewer-gmU5rc7K.d.ts} +2 -2
  28. package/dist/PowerPointViewer-gmU5rc7K.d.ts.map +1 -0
  29. package/dist/{SmartArt3DScene-WQIDFZ7X.mjs → SmartArt3DScene-XCFVGCXE.mjs} +1 -1
  30. package/dist/SmartArt3DScene-XCFVGCXE.mjs.br +0 -0
  31. package/dist/SmartArt3DScene-XCFVGCXE.mjs.gz +0 -0
  32. package/dist/{SmartArt3DScene-HCQBDRAM.js → SmartArt3DScene-ZO3KFDI2.js} +1 -1
  33. package/dist/SmartArt3DScene-ZO3KFDI2.js.br +0 -0
  34. package/dist/SmartArt3DScene-ZO3KFDI2.js.gz +0 -0
  35. package/dist/{SurfaceChart3DScene-WMY5JTW4.js → SurfaceChart3DScene-2SHCYZVC.js} +4 -4
  36. package/dist/{SurfaceChart3DScene-WMY5JTW4.js.br → SurfaceChart3DScene-2SHCYZVC.js.br} +0 -0
  37. package/dist/SurfaceChart3DScene-2SHCYZVC.js.gz +0 -0
  38. package/dist/{SurfaceChart3DScene-RXZADECL.mjs → SurfaceChart3DScene-UPDCIMJM.mjs} +3 -3
  39. package/dist/SurfaceChart3DScene-UPDCIMJM.mjs.br +0 -0
  40. package/dist/SurfaceChart3DScene-UPDCIMJM.mjs.gz +0 -0
  41. package/dist/{animation-timeline-CEJJLFqK.d.ts → animation-timeline-eb5z0SHW.d.ts} +250 -8
  42. package/dist/animation-timeline-eb5z0SHW.d.ts.map +1 -0
  43. package/dist/{chunk-M3SIFXWD.mjs → chunk-2X72MOPZ.mjs} +65 -0
  44. package/dist/chunk-2X72MOPZ.mjs.br +0 -0
  45. package/dist/chunk-2X72MOPZ.mjs.gz +0 -0
  46. package/dist/{chunk-QGM4M3NI.js → chunk-4VNS5WPM.js} +5 -0
  47. package/dist/chunk-4VNS5WPM.js.br +0 -0
  48. package/dist/chunk-4VNS5WPM.js.gz +0 -0
  49. package/dist/{chunk-F4WPQRZU.mjs → chunk-5XLLRPMV.mjs} +6901 -14355
  50. package/dist/chunk-5XLLRPMV.mjs.br +0 -0
  51. package/dist/chunk-5XLLRPMV.mjs.gz +0 -0
  52. package/dist/{chunk-FOMF7POV.mjs → chunk-6YXLGMTN.mjs} +2493 -1588
  53. package/dist/chunk-6YXLGMTN.mjs.br +0 -0
  54. package/dist/chunk-6YXLGMTN.mjs.gz +0 -0
  55. package/dist/chunk-B6NRDUHJ.mjs +8029 -0
  56. package/dist/chunk-B6NRDUHJ.mjs.br +0 -0
  57. package/dist/chunk-B6NRDUHJ.mjs.gz +0 -0
  58. package/dist/chunk-BHVCED34.mjs +16664 -0
  59. package/dist/chunk-BHVCED34.mjs.br +0 -0
  60. package/dist/chunk-BHVCED34.mjs.gz +0 -0
  61. package/dist/{chunk-IPYAN574.js → chunk-CLNGAVNH.js} +2495 -1587
  62. package/dist/chunk-CLNGAVNH.js.br +0 -0
  63. package/dist/chunk-CLNGAVNH.js.gz +0 -0
  64. package/dist/{chunk-2EFVXYNA.js → chunk-CUUYYYC5.js} +65 -0
  65. package/dist/chunk-CUUYYYC5.js.br +0 -0
  66. package/dist/chunk-CUUYYYC5.js.gz +0 -0
  67. package/dist/{chunk-L4ZADJOM.mjs → chunk-L63RAVM7.mjs} +1285 -150
  68. package/dist/chunk-L63RAVM7.mjs.br +0 -0
  69. package/dist/chunk-L63RAVM7.mjs.gz +0 -0
  70. package/dist/{chunk-7CSBUYRN.js → chunk-LFXG7SGG.js} +2073 -938
  71. package/dist/chunk-LFXG7SGG.js.br +0 -0
  72. package/dist/chunk-LFXG7SGG.js.gz +0 -0
  73. package/dist/{chunk-TEN35NUX.js → chunk-OKOJVSKJ.js} +3512 -403
  74. package/dist/chunk-OKOJVSKJ.js.br +0 -0
  75. package/dist/chunk-OKOJVSKJ.js.gz +0 -0
  76. package/dist/{chunk-FVQDRA5N.mjs → chunk-R2N2UYT7.mjs} +3455 -362
  77. package/dist/chunk-R2N2UYT7.mjs.br +0 -0
  78. package/dist/chunk-R2N2UYT7.mjs.gz +0 -0
  79. package/dist/chunk-SYPHGLIB.js +16701 -0
  80. package/dist/chunk-SYPHGLIB.js.br +0 -0
  81. package/dist/chunk-SYPHGLIB.js.gz +0 -0
  82. package/dist/{chunk-6DZX6EAA.mjs → chunk-XGB3TDIC.mjs} +5 -1
  83. package/dist/chunk-XGB3TDIC.mjs.br +0 -0
  84. package/dist/chunk-XGB3TDIC.mjs.gz +0 -0
  85. package/dist/chunk-ZB4NZRCI.js +11111 -0
  86. package/dist/chunk-ZB4NZRCI.js.br +0 -0
  87. package/dist/chunk-ZB4NZRCI.js.gz +0 -0
  88. package/dist/chunk-ZKDE3HJI.js +8121 -0
  89. package/dist/chunk-ZKDE3HJI.js.br +0 -0
  90. package/dist/chunk-ZKDE3HJI.js.gz +0 -0
  91. package/dist/{dist-755SJ3ZH.js → dist-4LUVI3SW.js} +578 -566
  92. package/dist/dist-4LUVI3SW.js.br +0 -0
  93. package/dist/dist-4LUVI3SW.js.gz +0 -0
  94. package/dist/dist-J6PC54PZ.mjs +2 -0
  95. package/dist/dist-J6PC54PZ.mjs.br +0 -0
  96. package/dist/dist-J6PC54PZ.mjs.gz +0 -0
  97. package/dist/i18n.js +5 -5
  98. package/dist/i18n.js.br +0 -0
  99. package/dist/i18n.js.gz +0 -0
  100. package/dist/i18n.mjs +2 -2
  101. package/dist/i18n.mjs.br +0 -0
  102. package/dist/i18n.mjs.gz +0 -0
  103. package/dist/{index-J6IuHQ2_.d.ts → index-a8wcFjRJ.d.ts} +4 -4
  104. package/dist/{index-J6IuHQ2_.d.ts.map → index-a8wcFjRJ.d.ts.map} +1 -1
  105. package/dist/index.d.ts +3030 -220
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +41 -39
  108. package/dist/index.js.br +0 -0
  109. package/dist/index.js.gz +0 -0
  110. package/dist/index.mjs +8 -6
  111. package/dist/index.mjs.br +0 -0
  112. package/dist/index.mjs.gz +0 -0
  113. package/dist/{hooks-unstable.d.ts → internals.d.ts} +1238 -974
  114. package/dist/internals.d.ts.map +1 -0
  115. package/dist/{hooks-unstable.js → internals.js} +81 -80
  116. package/dist/internals.js.br +0 -0
  117. package/dist/internals.js.gz +0 -0
  118. package/dist/{hooks-unstable.mjs → internals.mjs} +6 -5
  119. package/dist/internals.mjs.br +0 -0
  120. package/dist/internals.mjs.gz +0 -0
  121. package/dist/pptx-viewer.css +1 -1
  122. package/dist/pptx-viewer.css.br +0 -0
  123. package/dist/pptx-viewer.css.gz +0 -0
  124. package/dist/{three.module-7CXEVRKB.mjs → three.module-AC7ESV4W.mjs} +1 -1
  125. package/dist/three.module-AC7ESV4W.mjs.br +0 -0
  126. package/dist/three.module-AC7ESV4W.mjs.gz +0 -0
  127. package/dist/{three.module-CPZZFD2Q.js → three.module-GNNNRIMK.js} +1 -1
  128. package/dist/three.module-GNNNRIMK.js.br +0 -0
  129. package/dist/three.module-GNNNRIMK.js.gz +0 -0
  130. package/dist/{useViewerBuildingBlocks-ll3_ncCH.d.ts → useViewerBuildingBlocks-CjureTRf.d.ts} +185 -174
  131. package/dist/useViewerBuildingBlocks-CjureTRf.d.ts.map +1 -0
  132. package/dist/viewer/index.d.ts +469 -52
  133. package/dist/viewer/index.d.ts.map +1 -1
  134. package/dist/viewer/index.js +35 -33
  135. package/dist/viewer/index.js.br +0 -0
  136. package/dist/viewer/index.js.gz +0 -0
  137. package/dist/viewer/index.mjs +8 -6
  138. package/dist/viewer/index.mjs.br +0 -0
  139. package/dist/viewer/index.mjs.gz +0 -0
  140. package/dist/{y-webrtc-6CRYHAXH.mjs → y-webrtc-DGVURJIF.mjs} +1 -1
  141. package/dist/y-webrtc-DGVURJIF.mjs.br +0 -0
  142. package/dist/y-webrtc-DGVURJIF.mjs.gz +0 -0
  143. package/dist/{y-webrtc-QCZF75JW.js → y-webrtc-YN53KW3J.js} +5 -5
  144. package/dist/y-webrtc-YN53KW3J.js.br +0 -0
  145. package/dist/y-webrtc-YN53KW3J.js.gz +0 -0
  146. package/dist/{y-websocket-QJEM6VOB.js → y-websocket-HZCIQLM6.js} +1 -1
  147. package/dist/y-websocket-HZCIQLM6.js.br +0 -0
  148. package/dist/y-websocket-HZCIQLM6.js.gz +0 -0
  149. package/dist/{y-websocket-57Q3RNHC.mjs → y-websocket-P5LTAJ5T.mjs} +1 -1
  150. package/dist/y-websocket-P5LTAJ5T.mjs.br +0 -0
  151. package/dist/y-websocket-P5LTAJ5T.mjs.gz +0 -0
  152. package/dist/{yjs-Y7IYUWOG.mjs → yjs-FKGX4QHS.mjs} +1 -1
  153. package/dist/yjs-FKGX4QHS.mjs.br +0 -0
  154. package/dist/yjs-FKGX4QHS.mjs.gz +0 -0
  155. package/dist/{yjs-UH3EPF3C.js → yjs-HBLSEMHP.js} +1 -1
  156. package/dist/yjs-HBLSEMHP.js.br +0 -0
  157. package/dist/yjs-HBLSEMHP.js.gz +0 -0
  158. package/package.json +19 -7
  159. package/dist/GLTFLoader-GP55DVVS.js.br +0 -0
  160. package/dist/GLTFLoader-GP55DVVS.js.gz +0 -0
  161. package/dist/GLTFLoader-NMAS6VRH.mjs.br +0 -0
  162. package/dist/GLTFLoader-NMAS6VRH.mjs.gz +0 -0
  163. package/dist/Model3DScene-XVYOISVJ.mjs.br +0 -0
  164. package/dist/Model3DScene-XVYOISVJ.mjs.gz +0 -0
  165. package/dist/Model3DScene-Y5ABLO7K.js.br +0 -0
  166. package/dist/Model3DScene-Y5ABLO7K.js.gz +0 -0
  167. package/dist/OrbitControls-F5XPYD2Z.mjs.br +0 -0
  168. package/dist/OrbitControls-VH6KILH7.js.br +0 -2
  169. package/dist/OrbitControls-VH6KILH7.js.gz +0 -0
  170. package/dist/PowerPointViewer-CnADroqZ.d.ts.map +0 -1
  171. package/dist/SmartArt3DScene-HCQBDRAM.js.br +0 -0
  172. package/dist/SmartArt3DScene-HCQBDRAM.js.gz +0 -0
  173. package/dist/SmartArt3DScene-WQIDFZ7X.mjs.br +0 -0
  174. package/dist/SmartArt3DScene-WQIDFZ7X.mjs.gz +0 -0
  175. package/dist/SurfaceChart3DScene-RXZADECL.mjs.br +0 -0
  176. package/dist/SurfaceChart3DScene-RXZADECL.mjs.gz +0 -0
  177. package/dist/SurfaceChart3DScene-WMY5JTW4.js.gz +0 -0
  178. package/dist/animation-timeline-CEJJLFqK.d.ts.map +0 -1
  179. package/dist/chunk-2EFVXYNA.js.br +0 -0
  180. package/dist/chunk-2EFVXYNA.js.gz +0 -0
  181. package/dist/chunk-6DZX6EAA.mjs.br +0 -0
  182. package/dist/chunk-6DZX6EAA.mjs.gz +0 -0
  183. package/dist/chunk-7CSBUYRN.js.br +0 -0
  184. package/dist/chunk-7CSBUYRN.js.gz +0 -0
  185. package/dist/chunk-E55Q4AC7.js +0 -18639
  186. package/dist/chunk-E55Q4AC7.js.br +0 -0
  187. package/dist/chunk-E55Q4AC7.js.gz +0 -0
  188. package/dist/chunk-F4WPQRZU.mjs.br +0 -0
  189. package/dist/chunk-F4WPQRZU.mjs.gz +0 -0
  190. package/dist/chunk-FOMF7POV.mjs.br +0 -0
  191. package/dist/chunk-FOMF7POV.mjs.gz +0 -0
  192. package/dist/chunk-FVQDRA5N.mjs.br +0 -0
  193. package/dist/chunk-FVQDRA5N.mjs.gz +0 -0
  194. package/dist/chunk-IPYAN574.js.br +0 -0
  195. package/dist/chunk-IPYAN574.js.gz +0 -0
  196. package/dist/chunk-L4ZADJOM.mjs.br +0 -0
  197. package/dist/chunk-L4ZADJOM.mjs.gz +0 -0
  198. package/dist/chunk-M3SIFXWD.mjs.br +0 -0
  199. package/dist/chunk-M3SIFXWD.mjs.gz +0 -0
  200. package/dist/chunk-QGM4M3NI.js.br +0 -0
  201. package/dist/chunk-QGM4M3NI.js.gz +0 -0
  202. package/dist/chunk-TEN35NUX.js.br +0 -0
  203. package/dist/chunk-TEN35NUX.js.gz +0 -0
  204. package/dist/dist-755SJ3ZH.js.br +0 -0
  205. package/dist/dist-755SJ3ZH.js.gz +0 -0
  206. package/dist/dist-FFWP5NQZ.mjs +0 -2
  207. package/dist/dist-FFWP5NQZ.mjs.br +0 -0
  208. package/dist/dist-FFWP5NQZ.mjs.gz +0 -0
  209. package/dist/hooks-unstable.d.ts.map +0 -1
  210. package/dist/hooks-unstable.js.br +0 -0
  211. package/dist/hooks-unstable.js.gz +0 -0
  212. package/dist/hooks-unstable.mjs.br +0 -0
  213. package/dist/hooks-unstable.mjs.gz +0 -0
  214. package/dist/three.module-7CXEVRKB.mjs.br +0 -0
  215. package/dist/three.module-7CXEVRKB.mjs.gz +0 -0
  216. package/dist/three.module-CPZZFD2Q.js.br +0 -0
  217. package/dist/three.module-CPZZFD2Q.js.gz +0 -0
  218. package/dist/useViewerBuildingBlocks-ll3_ncCH.d.ts.map +0 -1
  219. package/dist/y-webrtc-6CRYHAXH.mjs.br +0 -0
  220. package/dist/y-webrtc-6CRYHAXH.mjs.gz +0 -0
  221. package/dist/y-webrtc-QCZF75JW.js.br +0 -0
  222. package/dist/y-webrtc-QCZF75JW.js.gz +0 -0
  223. package/dist/y-websocket-57Q3RNHC.mjs.br +0 -0
  224. package/dist/y-websocket-57Q3RNHC.mjs.gz +0 -0
  225. package/dist/y-websocket-QJEM6VOB.js.br +0 -0
  226. package/dist/y-websocket-QJEM6VOB.js.gz +0 -0
  227. package/dist/yjs-UH3EPF3C.js.br +0 -0
  228. package/dist/yjs-UH3EPF3C.js.gz +0 -0
  229. package/dist/yjs-Y7IYUWOG.mjs.br +0 -0
  230. package/dist/yjs-Y7IYUWOG.mjs.gz +0 -0
@@ -1,4 +1,4 @@
1
- import { MIN_ELEMENT_SIZE, guideEmuToPx, THEME_COLOR_SCHEME_KEYS, hasShapeProperties, hasTextProperties, createChartElement, getShapeClipPath, getAdjustmentAwareShapeClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, hslToRgb, PRESET_COLOR_MAP, isImageLikeElement, stripXmlOrderSuffix, orderedXmlKey, createBuiltinVariables, resolveCoordinate, applyDrawingColorTransforms } from './chunk-FOMF7POV.mjs';
1
+ import { THEME_PRESETS, MIN_ELEMENT_SIZE, guideEmuToPx, hasShapeProperties, THEME_COLOR_SCHEME_KEYS, hasTextProperties, createChartElement, getShapeClipPath, getAdjustmentAwareShapeClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, hslToRgb, PRESET_COLOR_MAP, isImageLikeElement, stripXmlOrderSuffix, orderedXmlKey, createBuiltinVariables, resolveCoordinate, applyDrawingColorTransforms } from './chunk-6YXLGMTN.mjs';
2
2
  import DOMPurify from 'dompurify';
3
3
 
4
4
  var defaultThemeColors = {
@@ -231,6 +231,113 @@ var THEME_CATALOG = [
231
231
  function resolveThemeCatalogEntry(key, catalog = THEME_CATALOG) {
232
232
  return catalog.find((entry) => entry.key === key)?.theme;
233
233
  }
234
+ function corePreset(id) {
235
+ const preset = THEME_PRESETS.find((p) => p.id === id);
236
+ if (!preset) {
237
+ throw new Error(`theme-gallery-presets: core THEME_PRESETS is missing "${id}"`);
238
+ }
239
+ return preset;
240
+ }
241
+ var WISP_PRESET = {
242
+ id: "wisp",
243
+ name: "Wisp",
244
+ colorScheme: {
245
+ dk1: "#000000",
246
+ lt1: "#FFFFFF",
247
+ dk2: "#46393B",
248
+ lt2: "#E8DCD8",
249
+ accent1: "#A53010",
250
+ accent2: "#DE7E18",
251
+ accent3: "#9F8351",
252
+ accent4: "#728653",
253
+ accent5: "#92AA4C",
254
+ accent6: "#6AAC91",
255
+ hlink: "#FB4F14",
256
+ folHlink: "#E25839"
257
+ },
258
+ fontScheme: {
259
+ majorFont: { latin: "Century Gothic" },
260
+ minorFont: { latin: "Century Gothic" }
261
+ }
262
+ };
263
+ var BERLIN_PRESET = {
264
+ id: "berlin",
265
+ name: "Berlin",
266
+ colorScheme: {
267
+ dk1: "#000000",
268
+ lt1: "#FFFFFF",
269
+ dk2: "#3E5C61",
270
+ lt2: "#D5E0D0",
271
+ accent1: "#F09415",
272
+ accent2: "#C1B56B",
273
+ accent3: "#89C2A3",
274
+ accent4: "#729BBE",
275
+ accent5: "#9A90C2",
276
+ accent6: "#BE8DBE",
277
+ hlink: "#25A0DA",
278
+ folHlink: "#FF7F00"
279
+ },
280
+ fontScheme: {
281
+ majorFont: { latin: "Trebuchet MS" },
282
+ minorFont: { latin: "Trebuchet MS" }
283
+ }
284
+ };
285
+ var SLICE_PRESET = {
286
+ id: "slice",
287
+ name: "Slice",
288
+ colorScheme: {
289
+ dk1: "#000000",
290
+ lt1: "#FFFFFF",
291
+ dk2: "#2E3B4C",
292
+ lt2: "#C7CDD3",
293
+ accent1: "#E2751D",
294
+ accent2: "#C53B23",
295
+ accent3: "#A13D69",
296
+ accent4: "#58599E",
297
+ accent5: "#36749D",
298
+ accent6: "#4EA39A",
299
+ hlink: "#FD6B32",
300
+ folHlink: "#D14D0F"
301
+ },
302
+ fontScheme: {
303
+ majorFont: { latin: "Century Gothic" },
304
+ minorFont: { latin: "Century Gothic" }
305
+ }
306
+ };
307
+ var DIVIDEND_PRESET = {
308
+ id: "dividend",
309
+ name: "Dividend",
310
+ colorScheme: {
311
+ dk1: "#000000",
312
+ lt1: "#FFFFFF",
313
+ dk2: "#3D3D3D",
314
+ lt2: "#E1E1E1",
315
+ accent1: "#4D1434",
316
+ accent2: "#903163",
317
+ accent3: "#B2324B",
318
+ accent4: "#D34817",
319
+ accent5: "#E8971C",
320
+ accent6: "#FDCB00",
321
+ hlink: "#A03068",
322
+ folHlink: "#C34882"
323
+ },
324
+ fontScheme: {
325
+ majorFont: { latin: "Gill Sans MT" },
326
+ minorFont: { latin: "Gill Sans MT" }
327
+ }
328
+ };
329
+ [
330
+ corePreset("office"),
331
+ corePreset("facet"),
332
+ corePreset("integral"),
333
+ corePreset("ion"),
334
+ corePreset("retrospect"),
335
+ corePreset("organic"),
336
+ WISP_PRESET,
337
+ BERLIN_PRESET,
338
+ SLICE_PRESET,
339
+ DIVIDEND_PRESET
340
+ ];
234
341
  function collectMediaElements(elements, collector) {
235
342
  for (const element of elements) {
236
343
  if (element.type === "media") {
@@ -542,6 +649,42 @@ function buildShapePathGradient(stops, focalPoint, fillToRect) {
542
649
  const posY = focalPoint ? `${Math.round(cy)}%` : "center";
543
650
  return `radial-gradient(farthest-side at ${posX} ${posY}, ${stopStr})`;
544
651
  }
652
+ function getGradientTileFlipCss(mode) {
653
+ if (!mode || mode === "none") {
654
+ return void 0;
655
+ }
656
+ switch (mode) {
657
+ case "x":
658
+ return { backgroundSize: "50% 100%", backgroundRepeat: "repeat-x" };
659
+ case "y":
660
+ return { backgroundSize: "100% 50%", backgroundRepeat: "repeat-y" };
661
+ case "xy":
662
+ return { backgroundSize: "50% 50%", backgroundRepeat: "repeat" };
663
+ default:
664
+ return void 0;
665
+ }
666
+ }
667
+ function getGradientTileRectCss(tileRect) {
668
+ if (!tileRect) {
669
+ return void 0;
670
+ }
671
+ const { l, t, r, b } = tileRect;
672
+ const sizeW = 1 - l - r;
673
+ const sizeH = 1 - t - b;
674
+ if (sizeW <= 0 || sizeH <= 0) {
675
+ return void 0;
676
+ }
677
+ if (Math.abs(sizeW - 1) < 1e-3 && Math.abs(sizeH - 1) < 1e-3) {
678
+ return void 0;
679
+ }
680
+ const posX = 1 - sizeW > 1e-3 ? l / (1 - sizeW) * 100 : 0;
681
+ const posY = 1 - sizeH > 1e-3 ? t / (1 - sizeH) * 100 : 0;
682
+ return {
683
+ backgroundSize: `${Math.round(sizeW * 100)}% ${Math.round(sizeH * 100)}%`,
684
+ backgroundPosition: `${Math.round(posX)}% ${Math.round(posY)}%`,
685
+ backgroundRepeat: "no-repeat"
686
+ };
687
+ }
545
688
  function buildReflectedGradientStops(stops) {
546
689
  if (stops.length === 0) {
547
690
  return [];
@@ -860,6 +1003,23 @@ function getPatternSvg(preset, fg, bg) {
860
1003
  return null;
861
1004
  }
862
1005
  }
1006
+ function buildPatternFill(pattern, elementId) {
1007
+ if (!pattern || pattern.fillMode !== "pattern" || !pattern.fillPatternPreset) {
1008
+ return void 0;
1009
+ }
1010
+ const fg = normalizeHexColor(pattern.fillColor, "#000000");
1011
+ const bg = normalizeHexColor(pattern.fillPatternBackgroundColor, "#ffffff");
1012
+ const preset = pattern.fillPatternPreset;
1013
+ const svgPattern = getPatternSvg(preset, fg, bg);
1014
+ if (!svgPattern) {
1015
+ return void 0;
1016
+ }
1017
+ const encoded = encodeURIComponent(svgPattern);
1018
+ return {
1019
+ backgroundImage: `url("data:image/svg+xml,${encoded}")`,
1020
+ backgroundColor: bg
1021
+ };
1022
+ }
863
1023
  function buildPatternFillCss(style) {
864
1024
  if (!style || style.fillMode !== "pattern" || !style.fillPatternPreset) {
865
1025
  return void 0;
@@ -934,6 +1094,81 @@ var OOXML_PATTERN_PRESETS = [
934
1094
  "trellis",
935
1095
  "zigZag"
936
1096
  ];
1097
+ function getComputedFillStyle(element, parentGroupFill) {
1098
+ if (!hasShapeProperties(element)) {
1099
+ return void 0;
1100
+ }
1101
+ const ss = element.shapeStyle;
1102
+ if (!ss) {
1103
+ return {};
1104
+ }
1105
+ if (ss.fillMode === "group") {
1106
+ return parentGroupFill ? resolveComputedFill(parentGroupFill, element) : {};
1107
+ }
1108
+ return resolveComputedFill(ss, element);
1109
+ }
1110
+ function resolveComputedFill(ss, element) {
1111
+ const imageFillUrl = ss.fillMode === "image" && ss.fillImageUrl ? ss.fillImageUrl : void 0;
1112
+ if (imageFillUrl) {
1113
+ const tile = ss.fillImageMode === "tile";
1114
+ return {
1115
+ backgroundColor: "transparent",
1116
+ backgroundImage: `url(${imageFillUrl})`,
1117
+ backgroundRepeat: tile ? "repeat" : "no-repeat",
1118
+ backgroundSize: tile ? "auto" : "100% 100%"
1119
+ };
1120
+ }
1121
+ const geometry = {
1122
+ rotation: element.rotation,
1123
+ width: element.width,
1124
+ height: element.height
1125
+ };
1126
+ const gradient = buildGradientCss(ss, geometry) ?? (ss.fillMode === "gradient" ? ss.fillGradient : void 0);
1127
+ if (gradient) {
1128
+ const isStructuredLinear = ss.fillMode === "gradient" && (ss.fillGradientType || "linear") === "linear" && sanitizeGradientStops(ss.fillGradientStops).length > 0;
1129
+ const tileFlip = isStructuredLinear ? getGradientTileFlipCss(ss.fillGradientFlip) : void 0;
1130
+ if (tileFlip) {
1131
+ return {
1132
+ backgroundImage: gradient,
1133
+ backgroundSize: tileFlip.backgroundSize,
1134
+ backgroundRepeat: tileFlip.backgroundRepeat
1135
+ };
1136
+ }
1137
+ const tileRect = ss.fillMode === "gradient" ? getGradientTileRectCss(ss.fillGradientTileRect) : void 0;
1138
+ if (tileRect) {
1139
+ return {
1140
+ backgroundImage: gradient,
1141
+ backgroundSize: tileRect.backgroundSize,
1142
+ backgroundPosition: tileRect.backgroundPosition,
1143
+ backgroundRepeat: tileRect.backgroundRepeat
1144
+ };
1145
+ }
1146
+ return { backgroundImage: gradient };
1147
+ }
1148
+ const pattern = buildPatternFill(ss, element.id);
1149
+ if (pattern) {
1150
+ return {
1151
+ backgroundColor: pattern.backgroundColor,
1152
+ backgroundImage: pattern.backgroundImage,
1153
+ backgroundRepeat: "repeat",
1154
+ backgroundSize: "auto",
1155
+ svgFilter: pattern.svgFilter
1156
+ };
1157
+ }
1158
+ if (ss.fillColor && ss.fillColor !== "transparent" && ss.fillMode !== "none") {
1159
+ return { backgroundColor: colorWithOpacity(ss.fillColor, ss.fillOpacity) };
1160
+ }
1161
+ return {};
1162
+ }
1163
+ function getGroupChildParentFill(group) {
1164
+ return group.type === "group" ? group.groupFill : void 0;
1165
+ }
1166
+ function resolveGroupChildFill(child2, parentGroupFill) {
1167
+ if (!parentGroupFill || !hasShapeProperties(child2) || child2.shapeStyle?.fillMode !== "group") {
1168
+ return void 0;
1169
+ }
1170
+ return getComputedFillStyle(child2, parentGroupFill);
1171
+ }
937
1172
  function normalizeStrokeDashType(value) {
938
1173
  const normalized = String(value || "").trim().toLowerCase();
939
1174
  if (!normalized) {
@@ -1144,8 +1379,8 @@ function parseDrawingColorChoice(colorNode, schemeColorOverrides) {
1144
1379
  const green = parseDrawingPercent(scrgb["@_g"]);
1145
1380
  const blue = parseDrawingPercent(scrgb["@_b"]);
1146
1381
  if (red !== void 0 && green !== void 0 && blue !== void 0) {
1147
- const toHex = (value) => Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
1148
- const base = `#${toHex(red * 255)}${toHex(green * 255)}${toHex(blue * 255)}`;
1382
+ const toHex2 = (value) => Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
1383
+ const base = `#${toHex2(red * 255)}${toHex2(green * 255)}${toHex2(blue * 255)}`;
1149
1384
  return applyDrawingColorTransforms2(base, scrgb);
1150
1385
  }
1151
1386
  }
@@ -1185,8 +1420,8 @@ function parseDrawingColorChoice(colorNode, schemeColorOverrides) {
1185
1420
  const s = clampUnitInterval(satRaw / 1e5);
1186
1421
  const l = clampUnitInterval(lumRaw / 1e5);
1187
1422
  const rgb = hslToRgb(h, s, l);
1188
- const toHex = (value) => Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
1189
- const base = `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`;
1423
+ const toHex2 = (value) => Math.min(255, Math.max(0, Math.round(value))).toString(16).padStart(2, "0").toUpperCase();
1424
+ const base = `#${toHex2(rgb.r)}${toHex2(rgb.g)}${toHex2(rgb.b)}`;
1190
1425
  return applyDrawingColorTransforms2(base, hslNode);
1191
1426
  }
1192
1427
  }
@@ -1358,6 +1593,9 @@ function hasDistinctScriptFonts(fonts) {
1358
1593
  }
1359
1594
  var DEFAULT_SHADOW_COLOR = "#000000";
1360
1595
  var DEFAULT_GLOW_COLOR = "#ffff00";
1596
+ function escapeSvgAttr(value) {
1597
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1598
+ }
1361
1599
  function clampUnitInterval2(value) {
1362
1600
  return Math.min(1, Math.max(0, value));
1363
1601
  }
@@ -1405,10 +1643,23 @@ function getOuterShadowCss(style) {
1405
1643
  }
1406
1644
  const blur = typeof style.shadowBlur === "number" && Number.isFinite(style.shadowBlur) ? Math.max(0, style.shadowBlur) : 6;
1407
1645
  const opacity = typeof style.shadowOpacity === "number" && Number.isFinite(style.shadowOpacity) ? clampUnitInterval2(style.shadowOpacity) : 0.35;
1408
- return `${Math.round(offsetX)}px ${Math.round(offsetY)}px ${Math.round(blur)}px ${colorWithOpacity2(
1646
+ const spread = getShadowScaleSpread(style.shadowScaleX, style.shadowScaleY, blur);
1647
+ const color = colorWithOpacity2(
1409
1648
  normalizeHexColor2(style.shadowColor, DEFAULT_SHADOW_COLOR),
1410
1649
  opacity
1411
- )}`;
1650
+ );
1651
+ const geometry = `${Math.round(offsetX)}px ${Math.round(offsetY)}px ${Math.round(blur)}px`;
1652
+ return spread === 0 ? `${geometry} ${color}` : `${geometry} ${spread}px ${color}`;
1653
+ }
1654
+ function getShadowScaleSpread(scaleX, scaleY, blur) {
1655
+ const sx = typeof scaleX === "number" && Number.isFinite(scaleX) ? scaleX / 1e5 : 1;
1656
+ const sy = typeof scaleY === "number" && Number.isFinite(scaleY) ? scaleY / 1e5 : 1;
1657
+ const avgScale = (sx + sy) / 2;
1658
+ if (avgScale === 1) {
1659
+ return 0;
1660
+ }
1661
+ const base = Math.max(blur, 4);
1662
+ return Math.round(base * (avgScale - 1));
1412
1663
  }
1413
1664
  function getInnerShadowCss(style) {
1414
1665
  if (!style?.innerShadowColor || style.innerShadowColor === "transparent") {
@@ -1457,6 +1708,32 @@ function getGlowBoxShadowCss(color, radius, opacity) {
1457
1708
  const c3 = colorWithOpacity2(normalizedColor, baseOpacity * 0.3);
1458
1709
  return `0 0 ${r1}px ${c1}, 0 0 ${r2}px ${c2}, 0 0 ${r3}px ${c3}`;
1459
1710
  }
1711
+ function getBoxShadowCss(style, options = {}) {
1712
+ if (!style) {
1713
+ return void 0;
1714
+ }
1715
+ const parts = [];
1716
+ const multiLayer = getMultiLayerShadowCss(style);
1717
+ if (multiLayer) {
1718
+ parts.push(multiLayer);
1719
+ } else {
1720
+ const outer = getOuterShadowCss(style);
1721
+ if (outer) {
1722
+ parts.push(outer);
1723
+ }
1724
+ }
1725
+ const inner = getInnerShadowCss(style);
1726
+ if (inner) {
1727
+ parts.push(inner);
1728
+ }
1729
+ if (options.includeGlow !== false) {
1730
+ const glow = getGlowBoxShadowCss(style.glowColor, style.glowRadius, style.glowOpacity);
1731
+ if (glow) {
1732
+ parts.push(glow);
1733
+ }
1734
+ }
1735
+ return parts.length > 0 ? parts.join(", ") : void 0;
1736
+ }
1460
1737
  var buildShadowCssFromShapeStyle = getOuterShadowCss;
1461
1738
  var buildInnerShadowCssFromShapeStyle = getInnerShadowCss;
1462
1739
  var buildMultiLayerShadowCss = getMultiLayerShadowCss;
@@ -1508,18 +1785,164 @@ function getEffectDagCssFilter(style, elementId) {
1508
1785
  return filters.length > 0 ? filters.join(" ") : void 0;
1509
1786
  }
1510
1787
  var getEffectDagFilter = getEffectDagCssFilter;
1511
- function buildReflectionCssValue(distance, startOpacity, endOpacity, fadeLength, blurRadius = 0) {
1788
+ function getEffectFilterCss(style, elementId) {
1789
+ if (!style) {
1790
+ return void 0;
1791
+ }
1792
+ const parts = [];
1793
+ if (style.glowColor && style.glowColor !== "transparent" && style.glowRadius) {
1794
+ const glowOpacity = typeof style.glowOpacity === "number" ? style.glowOpacity : 0.75;
1795
+ const glowRad = Math.round(Math.max(0, style.glowRadius));
1796
+ const glowCol = colorWithOpacity2(
1797
+ normalizeHexColor2(style.glowColor, DEFAULT_GLOW_COLOR),
1798
+ glowOpacity
1799
+ );
1800
+ parts.push(`drop-shadow(0 0 ${glowRad}px ${glowCol})`);
1801
+ }
1802
+ if (typeof style.softEdgeRadius === "number" && style.softEdgeRadius > 0) {
1803
+ if (elementId) {
1804
+ parts.push(`url(#${getSoftEdgeFilterId(elementId)})`);
1805
+ } else {
1806
+ parts.push(`blur(${Math.min(2, Math.round(style.softEdgeRadius))}px)`);
1807
+ }
1808
+ }
1809
+ if (typeof style.blurRadius === "number" && style.blurRadius > 0) {
1810
+ parts.push(`blur(${Math.round(style.blurRadius)}px)`);
1811
+ }
1812
+ const dagFilter = getEffectDagCssFilter(style, elementId);
1813
+ if (dagFilter) {
1814
+ parts.push(dagFilter);
1815
+ }
1816
+ return parts.length > 0 ? parts.join(" ") : void 0;
1817
+ }
1818
+ function buildReflectionCssValue(distance, startOpacity, endOpacity, fadeLength, blurRadius = 0, startOffset = 0) {
1512
1819
  const effectiveFadeLength = fadeLength + blurRadius * 2;
1513
1820
  const midOpacity = (startOpacity + endOpacity) / 2;
1514
1821
  const midPoint = Math.round(effectiveFadeLength * 0.5);
1822
+ const holdPx = Math.round(Math.max(0, Math.min(startOffset, effectiveFadeLength - 1)));
1823
+ const holdStop = holdPx > 0 ? `rgba(255,255,255,${startOpacity}) ${holdPx}px, ` : "";
1515
1824
  if (blurRadius > 0) {
1516
- return `below ${Math.round(distance)}px linear-gradient(to bottom, rgba(255,255,255,${startOpacity}), rgba(255,255,255,${midOpacity}) ${midPoint}px, rgba(255,255,255,${endOpacity}) ${effectiveFadeLength}px)`;
1825
+ return `below ${Math.round(distance)}px linear-gradient(to bottom, rgba(255,255,255,${startOpacity}), ${holdStop}rgba(255,255,255,${midOpacity}) ${midPoint}px, rgba(255,255,255,${endOpacity}) ${effectiveFadeLength}px)`;
1826
+ }
1827
+ return `below ${Math.round(distance)}px linear-gradient(to bottom, rgba(255,255,255,${startOpacity}), ${holdStop}rgba(255,255,255,${endOpacity}) ${fadeLength}px)`;
1828
+ }
1829
+ function getReflectionCss(style, elementHeight) {
1830
+ if (!style) {
1831
+ return void 0;
1832
+ }
1833
+ const hasReflection = typeof style.reflectionStartOpacity === "number" && style.reflectionStartOpacity > 0 || typeof style.reflectionDistance === "number" && style.reflectionDistance > 0 || typeof style.reflectionBlurRadius === "number" && style.reflectionBlurRadius > 0;
1834
+ if (!hasReflection) {
1835
+ return void 0;
1836
+ }
1837
+ const distance = style.reflectionDistance ?? 0;
1838
+ const startOpacity = typeof style.reflectionStartOpacity === "number" ? style.reflectionStartOpacity : 0.5;
1839
+ const endOpacity = typeof style.reflectionEndOpacity === "number" ? style.reflectionEndOpacity : 0;
1840
+ const fadeLength = typeof style.reflectionEndPosition === "number" ? Math.round(style.reflectionEndPosition * Math.max(elementHeight, 1)) : 100;
1841
+ const blurRadius = typeof style.reflectionBlurRadius === "number" ? style.reflectionBlurRadius : 0;
1842
+ const startOffset = typeof style.reflectionStartPosition === "number" && style.reflectionStartPosition > 0 ? Math.round(clampUnitInterval2(style.reflectionStartPosition) * fadeLength) : 0;
1843
+ return {
1844
+ webkitBoxReflect: buildReflectionCssValue(
1845
+ distance,
1846
+ startOpacity,
1847
+ endOpacity,
1848
+ fadeLength,
1849
+ blurRadius,
1850
+ startOffset
1851
+ ),
1852
+ distance,
1853
+ startOpacity,
1854
+ endOpacity,
1855
+ fadeLength,
1856
+ blurRadius
1857
+ };
1858
+ }
1859
+ function getEffectDagOpacity(style) {
1860
+ if (!style || typeof style.dagAlphaModFix !== "number") {
1861
+ return void 0;
1517
1862
  }
1518
- return `below ${Math.round(distance)}px linear-gradient(to bottom, rgba(255,255,255,${startOpacity}), rgba(255,255,255,${endOpacity}) ${fadeLength}px)`;
1863
+ return clampUnitInterval2(style.dagAlphaModFix / 100);
1864
+ }
1865
+ function getEffectDagBlendMode(blend) {
1866
+ switch (blend) {
1867
+ case "mult":
1868
+ return "multiply";
1869
+ case "screen":
1870
+ return "screen";
1871
+ case "darken":
1872
+ return "darken";
1873
+ case "lighten":
1874
+ return "lighten";
1875
+ default:
1876
+ return void 0;
1877
+ }
1878
+ }
1879
+ function getEffectDagFillOverlay(style) {
1880
+ if (!style?.dagFillOverlayColor || style.dagFillOverlayColor === "transparent") {
1881
+ return void 0;
1882
+ }
1883
+ const blendMode = getEffectDagBlendMode(style.dagFillOverlayBlend) ?? "normal";
1884
+ const color = colorWithOpacity2(
1885
+ normalizeHexColor2(style.dagFillOverlayColor, DEFAULT_SHADOW_COLOR),
1886
+ style.dagFillOverlayOpacity
1887
+ );
1888
+ return { color, blendMode };
1519
1889
  }
1520
1890
  function getDuotoneFilterId(elementId) {
1521
1891
  return `dag-duotone-${elementId}`;
1522
1892
  }
1893
+ function getSoftEdgeFilterId(elementId) {
1894
+ return `soft-edge-${elementId}`;
1895
+ }
1896
+ function getSoftEdgeSvgFilter(style, elementId) {
1897
+ if (!style || typeof style.softEdgeRadius !== "number" || style.softEdgeRadius <= 0) {
1898
+ return void 0;
1899
+ }
1900
+ const id = getSoftEdgeFilterId(elementId);
1901
+ const radius = Math.round(style.softEdgeRadius);
1902
+ const filterMarkup = [
1903
+ `<filter id="${escapeSvgAttr(id)}" x="-20%" y="-20%" width="140%" height="140%" color-interpolation-filters="sRGB">`,
1904
+ `<feGaussianBlur in="SourceAlpha" stdDeviation="${radius}" result="softEdgeAlpha"/>`,
1905
+ `<feComposite in="SourceGraphic" in2="softEdgeAlpha" operator="in"/>`,
1906
+ `</filter>`
1907
+ ].join("");
1908
+ return { id, cssReference: `url(#${id})`, filterMarkup };
1909
+ }
1910
+ function getComputedEffectStyle(element, options = {}) {
1911
+ const style = "shapeStyle" in element ? element.shapeStyle : void 0;
1912
+ const result = {};
1913
+ if (!style) {
1914
+ return result;
1915
+ }
1916
+ const boxShadow = getBoxShadowCss(style, { includeGlow: options.includeGlowBoxShadow });
1917
+ if (boxShadow) {
1918
+ result.boxShadow = boxShadow;
1919
+ }
1920
+ const filter = getEffectFilterCss(style, element.id);
1921
+ if (filter) {
1922
+ result.filter = filter;
1923
+ }
1924
+ const reflection = getReflectionCss(style, element.height);
1925
+ if (reflection) {
1926
+ result.webkitBoxReflect = reflection.webkitBoxReflect;
1927
+ }
1928
+ const opacity = getEffectDagOpacity(style);
1929
+ if (opacity !== void 0) {
1930
+ result.opacity = opacity;
1931
+ }
1932
+ const overlay = getEffectDagFillOverlay(style);
1933
+ if (overlay) {
1934
+ result.fillOverlay = overlay;
1935
+ } else {
1936
+ const blend = getEffectDagBlendMode(style.dagFillOverlayBlend);
1937
+ if (blend) {
1938
+ result.mixBlendMode = blend;
1939
+ }
1940
+ }
1941
+ if (style.blurGrow && typeof style.blurRadius === "number" && style.blurRadius > 0) {
1942
+ result.overflowVisible = true;
1943
+ }
1944
+ return result;
1945
+ }
1523
1946
  function clamp(value, minimum, maximum) {
1524
1947
  return Math.min(maximum, Math.max(minimum, value));
1525
1948
  }
@@ -3169,11 +3592,11 @@ function mergeSiblings(nodes) {
3169
3592
  for (const [key] of entries) {
3170
3593
  counts.set(key, (counts.get(key) ?? 0) + 1);
3171
3594
  }
3172
- const ordered = {};
3595
+ const ordered2 = {};
3173
3596
  for (const [position, [key, value]] of entries.entries()) {
3174
- ordered[(counts.get(key) ?? 0) > 1 ? orderedXmlKey(key, position) : key] = value;
3597
+ ordered2[(counts.get(key) ?? 0) > 1 ? orderedXmlKey(key, position) : key] = value;
3175
3598
  }
3176
- return ordered;
3599
+ return ordered2;
3177
3600
  }
3178
3601
  const result = {};
3179
3602
  for (const [key, value] of entries) {
@@ -3789,8 +4212,8 @@ function hexToRgb(hex) {
3789
4212
  ];
3790
4213
  }
3791
4214
  function rgbToHex(r, g, b) {
3792
- const clamp7 = (v) => Math.max(0, Math.min(255, Math.round(v)));
3793
- return `#${clamp7(r).toString(16).padStart(2, "0")}${clamp7(g).toString(16).padStart(2, "0")}${clamp7(b).toString(16).padStart(2, "0")}`;
4215
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
4216
+ return `#${clamp8(r).toString(16).padStart(2, "0")}${clamp8(g).toString(16).padStart(2, "0")}${clamp8(b).toString(16).padStart(2, "0")}`;
3794
4217
  }
3795
4218
  function tint(hex, amount) {
3796
4219
  const [r, g, b] = hexToRgb(hex);
@@ -4184,6 +4607,26 @@ function splitSeriesByAxis(series, axes) {
4184
4607
  }
4185
4608
  return { primary, secondary };
4186
4609
  }
4610
+ function hexToRgb2(hex) {
4611
+ const h = hex.replace("#", "");
4612
+ return [
4613
+ parseInt(h.substring(0, 2), 16),
4614
+ parseInt(h.substring(2, 4), 16),
4615
+ parseInt(h.substring(4, 6), 16)
4616
+ ];
4617
+ }
4618
+ function rgbToHex2(r, g, b) {
4619
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
4620
+ return `#${clamp8(r).toString(16).padStart(2, "0")}${clamp8(g).toString(16).padStart(2, "0")}${clamp8(b).toString(16).padStart(2, "0")}`;
4621
+ }
4622
+ function tint2(hex, amount) {
4623
+ const [r, g, b] = hexToRgb2(hex);
4624
+ return rgbToHex2(r + (255 - r) * amount, g + (255 - g) * amount, b + (255 - b) * amount);
4625
+ }
4626
+ function shade2(hex, amount) {
4627
+ const [r, g, b] = hexToRgb2(hex);
4628
+ return rgbToHex2(r * (1 - amount), g * (1 - amount), b * (1 - amount));
4629
+ }
4187
4630
  function findDataPoint(series, pointIndex) {
4188
4631
  return series.dataPoints?.find((p) => p.idx === pointIndex);
4189
4632
  }
@@ -4198,6 +4641,134 @@ function resolveDataPointExplosion(series, pointIndex) {
4198
4641
  const point = findDataPoint(series, pointIndex);
4199
4642
  return point?.explosion ?? series.explosion ?? 0;
4200
4643
  }
4644
+ var DEFAULT_ROT_X = 15;
4645
+ var DEFAULT_ROT_Y = 20;
4646
+ var MIN_DEPTH_PX = 5;
4647
+ var MAX_DEPTH_PX = 22;
4648
+ function computeDepthVector(view3D) {
4649
+ const rotX = view3D?.rotX ?? DEFAULT_ROT_X;
4650
+ const rotY = view3D?.rotY ?? DEFAULT_ROT_Y;
4651
+ const depthScale = Math.min(Math.max((view3D?.depthPercent ?? 100) / 100, 0.4), 2);
4652
+ const magnitude = Math.min(Math.max(13 * depthScale, MIN_DEPTH_PX), MAX_DEPTH_PX);
4653
+ const rx = rotX * Math.PI / 180;
4654
+ const ry = rotY * Math.PI / 180;
4655
+ return {
4656
+ dx: Math.sin(ry) * magnitude,
4657
+ dy: -Math.sin(rx) * magnitude,
4658
+ magnitude
4659
+ };
4660
+ }
4661
+ function barExtrusion(rect, depth) {
4662
+ const { x, y, w, h, fill } = rect;
4663
+ const { dx, dy } = depth;
4664
+ const topFace = {
4665
+ kind: "polygon",
4666
+ points: `${x},${y} ${x + w},${y} ${x + w + dx},${y + dy} ${x + dx},${y + dy}`,
4667
+ fill: tint2(fill, 0.22),
4668
+ stroke: "none",
4669
+ strokeWidth: 0
4670
+ };
4671
+ const sideFace = {
4672
+ kind: "polygon",
4673
+ points: `${x + w},${y} ${x + w},${y + h} ${x + w + dx},${y + h + dy} ${x + w + dx},${y + dy}`,
4674
+ fill: shade2(fill, 0.25),
4675
+ stroke: "none",
4676
+ strokeWidth: 0
4677
+ };
4678
+ return [topFace, sideFace];
4679
+ }
4680
+ function translateSlicePath(d, dx, dy) {
4681
+ const tokens = d.match(/[MLAZ][^MLAZ]*/gu);
4682
+ if (!tokens) {
4683
+ return d;
4684
+ }
4685
+ return tokens.map((token) => {
4686
+ const cmd = token[0];
4687
+ const nums = token.slice(1).trim().split(/[ ,]+/u).filter((s) => s.length > 0).map(Number);
4688
+ if (cmd === "M" || cmd === "L") {
4689
+ const out = [];
4690
+ for (let i = 0; i < nums.length; i += 2) {
4691
+ out.push(nums[i] + dx, nums[i + 1] + dy);
4692
+ }
4693
+ return `${cmd}${pairs(out)}`;
4694
+ }
4695
+ if (cmd === "A") {
4696
+ const head = nums.slice(0, 5);
4697
+ const ex = nums[5] + dx;
4698
+ const ey = nums[6] + dy;
4699
+ return `A${head.join(",")},${ex},${ey}`;
4700
+ }
4701
+ return "Z";
4702
+ }).join("");
4703
+ }
4704
+ function pairs(nums) {
4705
+ const out = [];
4706
+ for (let i = 0; i < nums.length; i += 2) {
4707
+ out.push(`${nums[i]},${nums[i + 1]}`);
4708
+ }
4709
+ return out.join(" ");
4710
+ }
4711
+ function pieExtrusion(paths, depth) {
4712
+ const offsetY = Math.max(depth.magnitude, 6);
4713
+ return paths.map((p) => ({
4714
+ kind: "path",
4715
+ d: translateSlicePath(p.d, 0, offsetY),
4716
+ fill: shade2(p.fill, 0.32),
4717
+ stroke: shade2(p.fill, 0.4),
4718
+ strokeWidth: 0.5
4719
+ }));
4720
+ }
4721
+ function ribbonExtrusion(prims, depth) {
4722
+ const out = [];
4723
+ for (const prim of prims) {
4724
+ if (prim.kind === "polyline") {
4725
+ const pl = prim;
4726
+ out.push({
4727
+ ...pl,
4728
+ points: shiftPoints(pl.points, depth.dx, depth.dy),
4729
+ stroke: shade2(pl.stroke, 0.3),
4730
+ fill: "none",
4731
+ part: void 0
4732
+ });
4733
+ } else if (prim.kind === "polygon") {
4734
+ const pg = prim;
4735
+ out.push({
4736
+ ...pg,
4737
+ points: shiftPoints(pg.points, depth.dx, depth.dy),
4738
+ fill: shade2(pg.fill === "none" ? "#888888" : pg.fill, 0.3),
4739
+ part: void 0
4740
+ });
4741
+ }
4742
+ }
4743
+ return out;
4744
+ }
4745
+ function shiftPoints(points, dx, dy) {
4746
+ return points.trim().split(/\s+/u).map((pair) => {
4747
+ const [px3, py] = pair.split(",").map(Number);
4748
+ return `${px3 + dx},${py + dy}`;
4749
+ }).join(" ");
4750
+ }
4751
+ function applyChart3DDepth(vm, chartType, view3D) {
4752
+ const depth = computeDepthVector(view3D);
4753
+ let extrusion = [];
4754
+ if (chartType === "bar3D") {
4755
+ const bars = vm.primitives.filter(
4756
+ (p) => p.kind === "rect" && p.part?.role === "dataPoint"
4757
+ );
4758
+ extrusion = bars.flatMap((r) => barExtrusion(r, depth));
4759
+ } else if (chartType === "pie3D") {
4760
+ const slices = vm.primitives.filter((p) => p.kind === "path");
4761
+ extrusion = pieExtrusion(slices, depth);
4762
+ } else if (chartType === "line3D" || chartType === "area3D") {
4763
+ extrusion = ribbonExtrusion(vm.primitives, depth);
4764
+ } else {
4765
+ return vm;
4766
+ }
4767
+ if (extrusion.length === 0) {
4768
+ return vm;
4769
+ }
4770
+ return { ...vm, primitives: [...extrusion, ...vm.primitives] };
4771
+ }
4201
4772
  function clamp3(value, min, max) {
4202
4773
  return Math.min(Math.max(value, min), max);
4203
4774
  }
@@ -4219,7 +4790,7 @@ function horizontalAxisY(valueAxis, range, layout, fallback) {
4219
4790
  }
4220
4791
  return fallback === "top" ? layout.plotTop : layout.plotBottom;
4221
4792
  }
4222
- function verticalAxisX(categoryAxis, categoryCount, layout, fallback, dateValues) {
4793
+ function verticalAxisX(categoryAxis, categoryCount2, layout, fallback, dateValues) {
4223
4794
  if (categoryAxis?.crosses === "max") {
4224
4795
  return layout.plotRight;
4225
4796
  }
@@ -4233,8 +4804,8 @@ function verticalAxisX(categoryAxis, categoryCount, layout, fallback, dateValues
4233
4804
  const ratio2 = max === min ? 0.5 : (clamp3(categoryAxis.crossesAt, min, max) - min) / (max - min);
4234
4805
  return layout.plotLeft + ratio2 * layout.plotWidth;
4235
4806
  }
4236
- const index = clamp3(categoryAxis.crossesAt - 1, 0, Math.max(categoryCount - 1, 0));
4237
- const ratio = categoryCount <= 1 ? 0.5 : index / (categoryCount - 1);
4807
+ const index = clamp3(categoryAxis.crossesAt - 1, 0, Math.max(categoryCount2 - 1, 0));
4808
+ const ratio = categoryCount2 <= 1 ? 0.5 : index / (categoryCount2 - 1);
4238
4809
  return layout.plotLeft + ratio * layout.plotWidth;
4239
4810
  }
4240
4811
  return fallback === "right" ? layout.plotRight : layout.plotLeft;
@@ -4526,7 +5097,7 @@ function hasRicherAxisFeatures(chartData) {
4526
5097
  )
4527
5098
  );
4528
5099
  }
4529
- function buildCartesianAxes(chartData, layout, primaryRange, secondaryRange, categoryCount) {
5100
+ function buildCartesianAxes(chartData, layout, primaryRange, secondaryRange, categoryCount2) {
4530
5101
  if (!hasRicherAxisFeatures(chartData)) {
4531
5102
  const { gridlines, axisLabels } = buildGridlinesAndLabels(primaryRange, layout);
4532
5103
  return { gridlines, axisLabels, secondaryGridlines: void 0, secondaryAxisLabels: void 0 };
@@ -4537,7 +5108,7 @@ function buildCartesianAxes(chartData, layout, primaryRange, secondaryRange, cat
4537
5108
  );
4538
5109
  const axisX = (axisId, fallback) => verticalAxisX(
4539
5110
  categoryAxisFor(axisId),
4540
- categoryCount,
5111
+ categoryCount2,
4541
5112
  layout,
4542
5113
  fallback,
4543
5114
  chartData.dateCategories?.values
@@ -4744,6 +5315,62 @@ function pushClusteredStackedLabels(series, sourceIndices2, catCount, layout, ra
4744
5315
  }
4745
5316
  }
4746
5317
  }
5318
+ function interpolate(values, blank) {
5319
+ const out = [...values];
5320
+ for (let i = 0; i < out.length; i++) {
5321
+ if (!blank[i]) {
5322
+ continue;
5323
+ }
5324
+ let prev = i - 1;
5325
+ while (prev >= 0 && blank[prev]) {
5326
+ prev--;
5327
+ }
5328
+ let next = i + 1;
5329
+ while (next < out.length && blank[next]) {
5330
+ next++;
5331
+ }
5332
+ const hasPrev = prev >= 0;
5333
+ const hasNext = next < out.length;
5334
+ if (hasPrev && hasNext) {
5335
+ const t = (i - prev) / (next - prev);
5336
+ out[i] = values[prev] + (values[next] - values[prev]) * t;
5337
+ } else if (hasPrev) {
5338
+ out[i] = values[prev];
5339
+ } else if (hasNext) {
5340
+ out[i] = values[next];
5341
+ }
5342
+ }
5343
+ return out;
5344
+ }
5345
+ function resolveBlankDisplay(values, blanks, mode) {
5346
+ const visible = values.map(() => true);
5347
+ if (!blanks || !blanks.some(Boolean) || mode === void 0 || mode === "zero") {
5348
+ return { values: [...values], visible };
5349
+ }
5350
+ if (mode === "span") {
5351
+ return { values: interpolate(values, blanks), visible };
5352
+ }
5353
+ return {
5354
+ values: [...values],
5355
+ visible: values.map((_v, i) => !blanks[i])
5356
+ };
5357
+ }
5358
+ function visibleRuns(visible) {
5359
+ const runs = [];
5360
+ let current = [];
5361
+ for (let i = 0; i < visible.length; i++) {
5362
+ if (visible[i]) {
5363
+ current.push(i);
5364
+ } else if (current.length > 0) {
5365
+ runs.push(current);
5366
+ current = [];
5367
+ }
5368
+ }
5369
+ if (current.length > 0) {
5370
+ runs.push(current);
5371
+ }
5372
+ return runs;
5373
+ }
4747
5374
  function smoothLinePath(points) {
4748
5375
  if (points.length === 0) {
4749
5376
  return "";
@@ -4887,7 +5514,13 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
4887
5514
  continue;
4888
5515
  }
4889
5516
  const activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange;
4890
- const displayValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
5517
+ const rawValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
5518
+ const displayBlanks = sourceIndices2.map((sourceIndex) => series.blanks?.[sourceIndex] ?? false);
5519
+ const { values: displayValues, visible } = resolveBlankDisplay(
5520
+ rawValues,
5521
+ displayBlanks,
5522
+ chartData.chartChrome?.dispBlanksAs
5523
+ );
4891
5524
  const pts = computeLinePoints(displayValues, catCount, layout, activeRange).map(
4892
5525
  (point, index) => ({
4893
5526
  ...point,
@@ -4896,24 +5529,44 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
4896
5529
  );
4897
5530
  const c = seriesColor2(series, si, chartData.colorPalette);
4898
5531
  const seriesPart = { role: "series", seriesIndex: si };
4899
- primitives.push(
4900
- series.smooth ? {
4901
- kind: "path",
4902
- d: smoothLinePath(pts),
4903
- stroke: c,
4904
- strokeWidth: 2.4,
4905
- fill: "none",
4906
- part: seriesPart
4907
- } : {
4908
- kind: "polyline",
4909
- points: linePointsToSvgString(pts),
4910
- stroke: c,
4911
- strokeWidth: 2.4,
4912
- fill: "none",
4913
- part: seriesPart
5532
+ const allVisible = visible.every(Boolean);
5533
+ if (allVisible) {
5534
+ primitives.push(
5535
+ series.smooth ? {
5536
+ kind: "path",
5537
+ d: smoothLinePath(pts),
5538
+ stroke: c,
5539
+ strokeWidth: 2.4,
5540
+ fill: "none",
5541
+ part: seriesPart
5542
+ } : {
5543
+ kind: "polyline",
5544
+ points: linePointsToSvgString(pts),
5545
+ stroke: c,
5546
+ strokeWidth: 2.4,
5547
+ fill: "none",
5548
+ part: seriesPart
5549
+ }
5550
+ );
5551
+ } else {
5552
+ for (const run of visibleRuns(visible)) {
5553
+ if (run.length < 2) {
5554
+ continue;
5555
+ }
5556
+ primitives.push({
5557
+ kind: "polyline",
5558
+ points: linePointsToSvgString(run.map((i) => pts[i])),
5559
+ stroke: c,
5560
+ strokeWidth: 2.4,
5561
+ fill: "none",
5562
+ part: seriesPart
5563
+ });
4914
5564
  }
4915
- );
5565
+ }
4916
5566
  pts.forEach((pt, displayIndex) => {
5567
+ if (!visible[displayIndex]) {
5568
+ return;
5569
+ }
4917
5570
  const idx = sourceIndices2[displayIndex] ?? displayIndex;
4918
5571
  const part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
4919
5572
  pushMarker(
@@ -4929,7 +5582,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
4929
5582
  if (showLabels) {
4930
5583
  displayValues.forEach((val2, displayIndex) => {
4931
5584
  const pt = pts[displayIndex];
4932
- if (!pt) {
5585
+ if (!pt || !visible[displayIndex]) {
4933
5586
  return;
4934
5587
  }
4935
5588
  dataLabels.push({
@@ -5916,9 +6569,9 @@ function computeTrendlinePoints2(trendline, values, catCount, layout, range, mod
5916
6569
  sum += yVals[j];
5917
6570
  }
5918
6571
  const avgVal = sum / period;
5919
- const px2 = xToPixel2(i, catCount, layout, mode);
6572
+ const px3 = xToPixel2(i, catCount, layout, mode);
5920
6573
  const py = valueToY2(avgVal, range, layout.plotTop, layout.plotBottom);
5921
- maPoints.push({ x: px2, y: py });
6574
+ maPoints.push({ x: px3, y: py });
5922
6575
  }
5923
6576
  return {
5924
6577
  points: maPoints,
@@ -5936,9 +6589,9 @@ function computeTrendlinePoints2(trendline, values, catCount, layout, range, mod
5936
6589
  if (!Number.isFinite(yVal)) {
5937
6590
  continue;
5938
6591
  }
5939
- const px2 = xToPixel2(xVal, catCount, layout, mode);
6592
+ const px3 = xToPixel2(xVal, catCount, layout, mode);
5940
6593
  const py = valueToY2(yVal, range, layout.plotTop, layout.plotBottom);
5941
- points.push({ x: px2, y: py });
6594
+ points.push({ x: px3, y: py });
5942
6595
  }
5943
6596
  return { points, equation, rSquared };
5944
6597
  }
@@ -7369,26 +8022,311 @@ function buildSunburstViewModel(element, chartData, categoryLabels) {
7369
8022
  legendAnchor: "middle"
7370
8023
  };
7371
8024
  }
7372
- function normalizedLevels(levels, pointCount) {
7373
- return levels.map((level) => {
7374
- let previous = "";
7375
- return Array.from({ length: pointCount }, (_, index) => {
7376
- const label = level[index]?.trim() ?? "";
7377
- if (label) {
7378
- previous = label;
8025
+ function resolveSecondaryIndices(values, options) {
8026
+ const n = values.length;
8027
+ const result = /* @__PURE__ */ new Set();
8028
+ if (n <= 1) {
8029
+ return result;
8030
+ }
8031
+ const splitType = options.splitType ?? "auto";
8032
+ if (splitType === "cust") {
8033
+ for (const idx of options.custSplit ?? []) {
8034
+ if (idx >= 0 && idx < n) {
8035
+ result.add(idx);
8036
+ }
8037
+ }
8038
+ } else if (splitType === "val") {
8039
+ const threshold = options.splitPos ?? 0;
8040
+ values.forEach((v, i) => {
8041
+ if (v < threshold) {
8042
+ result.add(i);
8043
+ }
8044
+ });
8045
+ } else if (splitType === "percent") {
8046
+ const total = values.reduce((s, v) => s + Math.abs(v), 0) || 1;
8047
+ const threshold = options.splitPos ?? 0;
8048
+ values.forEach((v, i) => {
8049
+ if (Math.abs(v) / total * 100 < threshold) {
8050
+ result.add(i);
7379
8051
  }
7380
- return label || previous;
7381
8052
  });
8053
+ } else {
8054
+ const count = Math.min(Math.max(Math.round(options.splitPos ?? 2), 1), n - 1);
8055
+ for (let i = n - count; i < n; i++) {
8056
+ result.add(i);
8057
+ }
8058
+ }
8059
+ if (result.size >= n) {
8060
+ result.delete(0);
8061
+ }
8062
+ return result;
8063
+ }
8064
+ function sliceAngles(values) {
8065
+ const total = values.reduce((s, v) => s + Math.abs(v), 0) || 1;
8066
+ let cursor = -Math.PI / 2;
8067
+ return values.map((v) => {
8068
+ const span = Math.abs(v) / total * Math.PI * 2;
8069
+ const start = cursor;
8070
+ cursor += span;
8071
+ return { start, end: cursor, mid: (start + cursor) / 2 };
7382
8072
  });
7383
8073
  }
7384
- function findOrAddParent(children, label, colorIndex, parentLabelLayout) {
7385
- const existing = children.find((child2) => child2.children && child2.label === label);
7386
- if (existing) {
7387
- return existing;
7388
- }
7389
- const parent = {
7390
- label,
7391
- weight: 0,
8074
+ function computeOfPieGeom(element, secondPieSize) {
8075
+ const svgWidth = Math.max(element.width, 320);
8076
+ const svgHeight = Math.max(element.height, 180);
8077
+ const primaryR = Math.max(Math.min(svgWidth * 0.28, svgHeight * 0.4), 4);
8078
+ const secScale = Math.min(Math.max(secondPieSize / 100, 0.3), 1.4);
8079
+ return {
8080
+ svgWidth,
8081
+ svgHeight,
8082
+ primaryCx: svgWidth * 0.3,
8083
+ primaryCy: svgHeight * 0.52,
8084
+ primaryR,
8085
+ secondaryCx: svgWidth * 0.76,
8086
+ secondaryCy: svgHeight * 0.52,
8087
+ secondaryR: Math.max(primaryR * secScale, 4)
8088
+ };
8089
+ }
8090
+ function sliceLabel(x, y, value) {
8091
+ return {
8092
+ kind: "text",
8093
+ x,
8094
+ y,
8095
+ text: formatAxisValue2(value),
8096
+ fontSize: 8,
8097
+ fill: "#ffffff",
8098
+ textAnchor: "middle",
8099
+ fontWeight: "bold",
8100
+ dominantBaseline: "central"
8101
+ };
8102
+ }
8103
+ function buildSecondaryPie(geom, secondaryValues, fills, showLabels) {
8104
+ const angles = sliceAngles(secondaryValues);
8105
+ const primitives = [];
8106
+ const labels = [];
8107
+ angles.forEach((a, i) => {
8108
+ const geoSlice = computePieSlicePath(
8109
+ geom.secondaryCx,
8110
+ geom.secondaryCy,
8111
+ geom.secondaryR,
8112
+ 0,
8113
+ a.start,
8114
+ a.end
8115
+ );
8116
+ primitives.push({
8117
+ kind: "path",
8118
+ d: geoSlice.d,
8119
+ fill: fills[i],
8120
+ stroke: "#ffffff",
8121
+ strokeWidth: 1.5
8122
+ });
8123
+ if (showLabels) {
8124
+ labels.push(sliceLabel(geoSlice.labelX, geoSlice.labelY, secondaryValues[i]));
8125
+ }
8126
+ });
8127
+ return { primitives, labels };
8128
+ }
8129
+ function buildSecondaryBar(geom, secondaryValues, fills, showLabels) {
8130
+ const total = secondaryValues.reduce((s, v) => s + Math.abs(v), 0) || 1;
8131
+ const barW = geom.secondaryR * 1.1;
8132
+ const barH = geom.secondaryR * 2;
8133
+ const barX = geom.secondaryCx - barW / 2;
8134
+ const barTop = geom.secondaryCy - barH / 2;
8135
+ const primitives = [];
8136
+ const labels = [];
8137
+ let cursorY = barTop;
8138
+ secondaryValues.forEach((v, i) => {
8139
+ const h = Math.max(Math.abs(v) / total * barH, 1);
8140
+ primitives.push({ kind: "rect", x: barX, y: cursorY, w: barW, h, fill: fills[i] });
8141
+ if (showLabels) {
8142
+ labels.push(sliceLabel(geom.secondaryCx, cursorY + h / 2, v));
8143
+ }
8144
+ cursorY += h;
8145
+ });
8146
+ return { primitives, labels };
8147
+ }
8148
+ function buildSerLines(geom, otherAngle) {
8149
+ const rimStart = {
8150
+ x: geom.primaryCx + geom.primaryR * Math.cos(otherAngle.start),
8151
+ y: geom.primaryCy + geom.primaryR * Math.sin(otherAngle.start)
8152
+ };
8153
+ const rimEnd = {
8154
+ x: geom.primaryCx + geom.primaryR * Math.cos(otherAngle.end),
8155
+ y: geom.primaryCy + geom.primaryR * Math.sin(otherAngle.end)
8156
+ };
8157
+ const targetX = geom.secondaryCx - geom.secondaryR * 1.05;
8158
+ const line2 = (from, ty) => ({
8159
+ kind: "line",
8160
+ x1: from.x,
8161
+ y1: from.y,
8162
+ x2: targetX,
8163
+ y2: ty,
8164
+ stroke: "#94a3b8",
8165
+ strokeWidth: 1,
8166
+ dashArray: "3 2"
8167
+ });
8168
+ return [
8169
+ line2(rimStart, geom.secondaryCy - geom.secondaryR),
8170
+ line2(rimEnd, geom.secondaryCy + geom.secondaryR)
8171
+ ];
8172
+ }
8173
+ function buildPrimarySlices(geom, primaryValues, fills, showLabels) {
8174
+ const angles = sliceAngles(primaryValues);
8175
+ const primitives = [];
8176
+ const labels = [];
8177
+ angles.forEach((a, i) => {
8178
+ const geoSlice = computePieSlicePath(
8179
+ geom.primaryCx,
8180
+ geom.primaryCy,
8181
+ geom.primaryR,
8182
+ 0,
8183
+ a.start,
8184
+ a.end
8185
+ );
8186
+ primitives.push({
8187
+ kind: "path",
8188
+ d: geoSlice.d,
8189
+ fill: fills[i],
8190
+ stroke: "#ffffff",
8191
+ strokeWidth: 1.5,
8192
+ part: { role: "dataPoint", seriesIndex: 0, pointIndex: i }
8193
+ });
8194
+ if (showLabels) {
8195
+ labels.push(sliceLabel(geoSlice.labelX, geoSlice.labelY, primaryValues[i]));
8196
+ }
8197
+ });
8198
+ return { primitives, labels };
8199
+ }
8200
+ function buildOfPieViewModel(element, chartData, categoryLabels) {
8201
+ const options = chartData.ofPieOptions ?? { ofPieType: "pie" };
8202
+ const series = chartData.series[0];
8203
+ const values = series?.values ?? [];
8204
+ const palette = chartData.colorPalette;
8205
+ const showLabels = chartData.style?.hasDataLabels === true;
8206
+ const secondaryIdx = resolveSecondaryIndices(values, options);
8207
+ const keptIndices = values.map((_v, i) => i).filter((i) => !secondaryIdx.has(i));
8208
+ const secondaryIndices = values.map((_v, i) => i).filter((i) => secondaryIdx.has(i));
8209
+ const geom = computeOfPieGeom(element, options.secondPieSize ?? 75);
8210
+ const pointFill = (i) => series ? resolveVaryColorFill(series, i, paletteColor2(i, palette)) : paletteColor2(i, palette);
8211
+ const keptFills = keptIndices.map(pointFill);
8212
+ const secondaryFills = secondaryIndices.map(pointFill);
8213
+ const otherFill = paletteColor2(values.length, palette);
8214
+ const otherSum = secondaryIndices.reduce((s, i) => s + Math.abs(values[i]), 0);
8215
+ const primaryValues = [...keptIndices.map((i) => Math.abs(values[i])), otherSum];
8216
+ const primaryFills = [...keptFills, otherFill];
8217
+ const primary = buildPrimarySlices(geom, primaryValues, primaryFills, showLabels);
8218
+ const secondaryValues = secondaryIndices.map((i) => Math.abs(values[i]));
8219
+ const toBar = options.ofPieType === "bar";
8220
+ const secondary = secondaryValues.length > 0 ? toBar ? buildSecondaryBar(geom, secondaryValues, secondaryFills, showLabels) : buildSecondaryPie(geom, secondaryValues, secondaryFills, showLabels) : { primitives: [], labels: [] };
8221
+ const primitives = [];
8222
+ if (options.serLines !== false && secondaryValues.length > 0) {
8223
+ const primaryAngles = sliceAngles(primaryValues);
8224
+ primitives.push(...buildSerLines(geom, primaryAngles[primaryAngles.length - 1]));
8225
+ }
8226
+ primitives.push(...primary.primitives, ...secondary.primitives);
8227
+ const dataLabels = [...primary.labels, ...secondary.labels];
8228
+ const legend = categoryLabels.map((label, i) => ({
8229
+ color: paletteColor2(i, palette),
8230
+ label
8231
+ }));
8232
+ const title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
8233
+ return {
8234
+ svgWidth: geom.svgWidth,
8235
+ svgHeight: geom.svgHeight,
8236
+ title,
8237
+ titleX: geom.svgWidth / 2,
8238
+ titleY: 14,
8239
+ gridlines: [],
8240
+ axisLabels: [],
8241
+ zeroLine: void 0,
8242
+ categoryLabels: [],
8243
+ primitives,
8244
+ dataLabels,
8245
+ legend: chartData.style?.hasLegend ? legend : [],
8246
+ legendX: geom.svgWidth / 2,
8247
+ legendY: geom.svgHeight - 8,
8248
+ legendAnchor: "middle"
8249
+ };
8250
+ }
8251
+ var LEADER_LENGTH = 14;
8252
+ function isOutsidePosition(position) {
8253
+ return position === "outEnd" || position === "bestFit";
8254
+ }
8255
+ function buildPieDataLabels(params) {
8256
+ const { slices, values, cx, cy, outerR, position, showLeaderLines } = params;
8257
+ const outside = isOutsidePosition(position);
8258
+ const labels = [];
8259
+ const leaderLines = [];
8260
+ slices.forEach((slice, i) => {
8261
+ const val2 = values[i];
8262
+ if (val2 === void 0) {
8263
+ return;
8264
+ }
8265
+ if (!outside) {
8266
+ labels.push({
8267
+ kind: "text",
8268
+ x: slice.labelX,
8269
+ y: slice.labelY,
8270
+ text: formatAxisValue2(val2),
8271
+ fontSize: 8,
8272
+ fill: "#ffffff",
8273
+ textAnchor: "middle",
8274
+ fontWeight: "bold",
8275
+ dominantBaseline: "central"
8276
+ });
8277
+ return;
8278
+ }
8279
+ const cos = Math.cos(slice.midAngle);
8280
+ const sin = Math.sin(slice.midAngle);
8281
+ const rimX = cx + outerR * cos;
8282
+ const rimY = cy + outerR * sin;
8283
+ const labelX = cx + (outerR + LEADER_LENGTH) * cos;
8284
+ const labelY = cy + (outerR + LEADER_LENGTH) * sin;
8285
+ const anchor = cos >= 0 ? "start" : "end";
8286
+ labels.push({
8287
+ kind: "text",
8288
+ x: labelX + (cos >= 0 ? 2 : -2),
8289
+ y: labelY,
8290
+ text: formatAxisValue2(val2),
8291
+ fontSize: 8,
8292
+ fill: "#334155",
8293
+ textAnchor: anchor,
8294
+ dominantBaseline: "central"
8295
+ });
8296
+ if (showLeaderLines !== false) {
8297
+ leaderLines.push({
8298
+ kind: "line",
8299
+ x1: rimX,
8300
+ y1: rimY,
8301
+ x2: labelX,
8302
+ y2: labelY,
8303
+ stroke: "#94a3b8",
8304
+ strokeWidth: 0.75
8305
+ });
8306
+ }
8307
+ });
8308
+ return { labels, leaderLines };
8309
+ }
8310
+ function normalizedLevels(levels, pointCount) {
8311
+ return levels.map((level) => {
8312
+ let previous = "";
8313
+ return Array.from({ length: pointCount }, (_, index) => {
8314
+ const label = level[index]?.trim() ?? "";
8315
+ if (label) {
8316
+ previous = label;
8317
+ }
8318
+ return label || previous;
8319
+ });
8320
+ });
8321
+ }
8322
+ function findOrAddParent(children, label, colorIndex, parentLabelLayout) {
8323
+ const existing = children.find((child2) => child2.children && child2.label === label);
8324
+ if (existing) {
8325
+ return existing;
8326
+ }
8327
+ const parent = {
8328
+ label,
8329
+ weight: 0,
7392
8330
  children: [],
7393
8331
  colorIndex,
7394
8332
  parentLabelLayout
@@ -7755,6 +8693,84 @@ function buildTreemapViewModel(element, chartData, categoryLabels) {
7755
8693
  legendAnchor
7756
8694
  };
7757
8695
  }
8696
+ var EMU_PER_PIXEL = 9525;
8697
+ function shapeBox(shape, svgWidth, svgHeight) {
8698
+ const x = shape.from.x * svgWidth;
8699
+ const y = shape.from.y * svgHeight;
8700
+ if (shape.anchor === "rel" && shape.to) {
8701
+ return {
8702
+ x,
8703
+ y,
8704
+ w: Math.max((shape.to.x - shape.from.x) * svgWidth, 0),
8705
+ h: Math.max((shape.to.y - shape.from.y) * svgHeight, 0)
8706
+ };
8707
+ }
8708
+ const ext = shape.ext ?? { cx: 0, cy: 0 };
8709
+ return { x, y, w: ext.cx / EMU_PER_PIXEL, h: ext.cy / EMU_PER_PIXEL };
8710
+ }
8711
+ function textPrimitives(shape, box) {
8712
+ if (!shape.paragraphs || shape.paragraphs.length === 0) {
8713
+ return [];
8714
+ }
8715
+ const lineH = 12;
8716
+ const totalH = shape.paragraphs.length * lineH;
8717
+ let cursorY = box.y + Math.max((box.h - totalH) / 2, 0) + lineH * 0.75;
8718
+ const out = [];
8719
+ for (const para of shape.paragraphs) {
8720
+ if (para.text.length === 0) {
8721
+ cursorY += lineH;
8722
+ continue;
8723
+ }
8724
+ const align = para.align ?? "ctr";
8725
+ const anchor = align === "l" ? "start" : align === "r" ? "end" : "middle";
8726
+ const tx = align === "l" ? box.x + 2 : align === "r" ? box.x + box.w - 2 : box.x + box.w / 2;
8727
+ out.push({
8728
+ kind: "text",
8729
+ x: tx,
8730
+ y: cursorY,
8731
+ text: para.text,
8732
+ fontSize: para.fontSize ?? 9,
8733
+ fill: para.color ?? "#1e293b",
8734
+ textAnchor: anchor,
8735
+ fontWeight: para.bold ? "bold" : "normal"
8736
+ });
8737
+ cursorY += lineH;
8738
+ }
8739
+ return out;
8740
+ }
8741
+ function projectShape(shape, svgWidth, svgHeight) {
8742
+ const box = shapeBox(shape, svgWidth, svgHeight);
8743
+ const primitives = [];
8744
+ if (shape.kind === "cxnSp") {
8745
+ primitives.push({
8746
+ kind: "line",
8747
+ x1: box.x,
8748
+ y1: box.y,
8749
+ x2: box.x + box.w,
8750
+ y2: box.y + box.h,
8751
+ stroke: shape.stroke ?? "#000000",
8752
+ strokeWidth: shape.strokeWidth ?? 1
8753
+ });
8754
+ return primitives;
8755
+ }
8756
+ if ((shape.fill || shape.stroke) && box.w > 0 && box.h > 0) {
8757
+ primitives.push({
8758
+ kind: "polygon",
8759
+ points: `${box.x},${box.y} ${box.x + box.w},${box.y} ${box.x + box.w},${box.y + box.h} ${box.x},${box.y + box.h}`,
8760
+ fill: shape.fill ?? "none",
8761
+ stroke: shape.stroke ?? "none",
8762
+ strokeWidth: shape.strokeWidth ?? (shape.stroke ? 1 : 0)
8763
+ });
8764
+ }
8765
+ primitives.push(...textPrimitives(shape, box));
8766
+ return primitives;
8767
+ }
8768
+ function buildChartUserShapeOverlay(userShapes, svgWidth, svgHeight) {
8769
+ if (!userShapes || userShapes.length === 0) {
8770
+ return [];
8771
+ }
8772
+ return userShapes.flatMap((shape) => projectShape(shape, svgWidth, svgHeight));
8773
+ }
7758
8774
  function sourceIndices(indices, length) {
7759
8775
  return Array.from({ length }, (_, position) => indices?.[position] ?? position);
7760
8776
  }
@@ -8035,7 +9051,7 @@ function resolveRegionCode(label) {
8035
9051
  return REGION_ALIAS_MAP[normalized];
8036
9052
  }
8037
9053
  function lerpColor(a, b, t) {
8038
- const clamp7 = (v) => Math.max(0, Math.min(255, Math.round(v)));
9054
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
8039
9055
  const ha = a.replace("#", "");
8040
9056
  const hb = b.replace("#", "");
8041
9057
  const r1 = parseInt(ha.substring(0, 2), 16);
@@ -8044,11 +9060,11 @@ function lerpColor(a, b, t) {
8044
9060
  const r2 = parseInt(hb.substring(0, 2), 16);
8045
9061
  const g2 = parseInt(hb.substring(2, 4), 16);
8046
9062
  const b2 = parseInt(hb.substring(4, 6), 16);
8047
- const r = clamp7(r1 + (r2 - r1) * t);
8048
- const g = clamp7(g1 + (g2 - g1) * t);
8049
- const bl = clamp7(b1 + (b2 - b1) * t);
8050
- const toHex = (n) => n.toString(16).padStart(2, "0");
8051
- return `#${toHex(r)}${toHex(g)}${toHex(bl)}`;
9063
+ const r = clamp8(r1 + (r2 - r1) * t);
9064
+ const g = clamp8(g1 + (g2 - g1) * t);
9065
+ const bl = clamp8(b1 + (b2 - b1) * t);
9066
+ const toHex2 = (n) => n.toString(16).padStart(2, "0");
9067
+ return `#${toHex2(r)}${toHex2(g)}${toHex2(bl)}`;
8052
9068
  }
8053
9069
  function sequentialColorScale(t) {
8054
9070
  const clamped = Math.max(0, Math.min(1, t));
@@ -8964,6 +9980,30 @@ function buildChartViewModel(element) {
8964
9980
  }
8965
9981
  const longestLen = chartData.series.reduce((m, s) => Math.max(m, s.values.length), 0);
8966
9982
  const categoryLabels = chartData.categories.length > 0 ? chartData.categories : Array.from({ length: longestLen }, (_, i) => String(i + 1));
9983
+ if (chartType === "ofPie") {
9984
+ return withUserShapeOverlay(buildOfPieViewModel(element, chartData, categoryLabels), chartData);
9985
+ }
9986
+ const flat = buildFlatViewModel(element, chartData, categoryLabels, kind);
9987
+ if (is3DChartType(chartType)) {
9988
+ return withUserShapeOverlay(applyChart3DDepth(flat, chartType, chartData.view3D), chartData);
9989
+ }
9990
+ return withUserShapeOverlay(flat, chartData);
9991
+ }
9992
+ function withUserShapeOverlay(vm, chartData) {
9993
+ const overlay = buildChartUserShapeOverlay(chartData.userShapes, vm.svgWidth, vm.svgHeight);
9994
+ if (overlay.length === 0) {
9995
+ return vm;
9996
+ }
9997
+ return {
9998
+ ...vm,
9999
+ primitives: [...vm.primitives, ...overlay],
10000
+ userShapes: overlay
10001
+ };
10002
+ }
10003
+ function is3DChartType(chartType) {
10004
+ return chartType === "bar3D" || chartType === "pie3D" || chartType === "line3D" || chartType === "area3D";
10005
+ }
10006
+ function buildFlatViewModel(element, chartData, categoryLabels, kind) {
8967
10007
  if (kind === "pie" || kind === "doughnut") {
8968
10008
  return buildPieViewModel(element, chartData, categoryLabels, kind === "doughnut");
8969
10009
  }
@@ -9072,23 +10112,17 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
9072
10112
  );
9073
10113
  const dataLabels = [];
9074
10114
  if (chartData.style?.hasDataLabels) {
9075
- slices.forEach(({ labelX, labelY }, i) => {
9076
- const val2 = values[i];
9077
- if (val2 === void 0) {
9078
- return;
9079
- }
9080
- dataLabels.push({
9081
- kind: "text",
9082
- x: labelX,
9083
- y: labelY,
9084
- text: formatAxisValue2(val2),
9085
- fontSize: 8,
9086
- fill: "#ffffff",
9087
- textAnchor: "middle",
9088
- fontWeight: "bold",
9089
- dominantBaseline: "central"
9090
- });
10115
+ const labelResult = buildPieDataLabels({
10116
+ slices,
10117
+ values,
10118
+ cx,
10119
+ cy,
10120
+ outerR,
10121
+ position: chartData.style.dataLabels?.position,
10122
+ showLeaderLines: chartData.style.dataLabels?.showLeaderLines
9091
10123
  });
10124
+ dataLabels.push(...labelResult.labels);
10125
+ primitives.push(...labelResult.leaderLines);
9092
10126
  }
9093
10127
  const legendPos = chartData.style?.legendPosition ?? "b";
9094
10128
  const legend = categoryLabels.map((label, i) => ({
@@ -9357,8 +10391,12 @@ var PRESET_ID_TO_EFFECT = {
9357
10391
  9: "dissolveIn",
9358
10392
  10: "fadeIn",
9359
10393
  12: "flashIn",
10394
+ 14: "randomBarsIn",
9360
10395
  16: "peekIn",
9361
- 17: "randomBarsIn",
10396
+ // entr.17 = Split per MS-OI29500 / the catalog. (Previously this id was
10397
+ // mislabelled randomBarsIn, so imported Split entrances rendered as
10398
+ // Random Bars.) entr.14 above is Random Bars.
10399
+ 17: "splitIn",
9362
10400
  22: "wipeIn",
9363
10401
  23: "zoomIn",
9364
10402
  26: "riseUp",
@@ -9384,12 +10422,33 @@ var PRESET_ID_TO_EFFECT = {
9384
10422
  1: "boldFlash",
9385
10423
  2: "wave",
9386
10424
  6: "growShrink",
10425
+ 7: "flash",
10426
+ // Blink: an opacity blink, closest existing keyframe.
9387
10427
  8: "spin",
9388
10428
  9: "transparency",
9389
10429
  14: "teeter",
9390
10430
  26: "pulse"
9391
10431
  }
9392
10432
  };
10433
+ var EMPH_FILTER_PRESETS = {
10434
+ 3: { name: "desaturate", filterMid: "saturate(0.15)" },
10435
+ 4: { name: "darken", filterMid: "brightness(0.55)" },
10436
+ 5: { name: "lighten", filterMid: "brightness(1.6)" }
10437
+ };
10438
+ function emphasisFilterKeyframeCss(presetId, name) {
10439
+ if (presetId === void 0) {
10440
+ return void 0;
10441
+ }
10442
+ const preset = EMPH_FILTER_PRESETS[presetId];
10443
+ if (!preset) {
10444
+ return void 0;
10445
+ }
10446
+ return `@keyframes ${name} {
10447
+ 0% { filter: none; }
10448
+ 50% { filter: ${preset.filterMid}; }
10449
+ 100% { filter: none; }
10450
+ }`;
10451
+ }
9393
10452
  var FLY_SUBTYPE_TO_EDGE = {
9394
10453
  1: "top",
9395
10454
  2: "right",
@@ -9634,8 +10693,8 @@ function hexToRgb3(hex) {
9634
10693
  };
9635
10694
  }
9636
10695
  function rgbToHex3(r, g, b) {
9637
- const clamp7 = (v) => Math.max(0, Math.min(255, Math.round(v)));
9638
- return `#${clamp7(r).toString(16).padStart(2, "0")}${clamp7(g).toString(16).padStart(2, "0")}${clamp7(b).toString(16).padStart(2, "0")}`;
10696
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
10697
+ return `#${clamp8(r).toString(16).padStart(2, "0")}${clamp8(g).toString(16).padStart(2, "0")}${clamp8(b).toString(16).padStart(2, "0")}`;
9639
10698
  }
9640
10699
  function rgbToHsl(r, g, b) {
9641
10700
  const rn = r / 255;
@@ -9721,22 +10780,33 @@ function interpolateColor(from, to, t, colorSpace, direction) {
9721
10780
  const rgb = hslToRgb2(h, s, l);
9722
10781
  return rgbToHex3(rgb.r, rgb.g, rgb.b);
9723
10782
  }
9724
- var ATTR_NAME_TO_CSS_PROPERTY = {
9725
- fillcolor: "backgroundColor",
9726
- "fill.color": "backgroundColor",
9727
- "style.color": "color",
9728
- "stroke.color": "borderColor",
9729
- "stroke.dashstyle": "borderColor",
9730
- "style.visibility": "color",
9731
- ppt_c: "color",
9732
- ppt_x: "color",
9733
- ppt_y: "color"
10783
+ var ATTR_NAME_TO_CSS_PROPERTIES = {
10784
+ fillcolor: ["fill", "background-color", "backgroundColor"],
10785
+ "fill.color": ["fill", "background-color", "backgroundColor"],
10786
+ "style.color": ["color"],
10787
+ "stroke.color": ["stroke", "border-color", "borderColor"],
10788
+ "stroke.dashstyle": ["stroke", "border-color", "borderColor"],
10789
+ "style.visibility": ["color"],
10790
+ ppt_c: ["color"],
10791
+ ppt_x: ["color"],
10792
+ ppt_y: ["color"]
9734
10793
  };
9735
- function resolveCssProperty(attrName) {
10794
+ function resolveCssProperties(attrName) {
9736
10795
  if (!attrName) {
9737
- return "color";
10796
+ return ["color"];
10797
+ }
10798
+ return ATTR_NAME_TO_CSS_PROPERTIES[attrName] ?? ["color"];
10799
+ }
10800
+ function resolveColorAnimationTargets(targetAttribute) {
10801
+ const cssProperties = resolveCssProperties(targetAttribute);
10802
+ const targets = [];
10803
+ if (cssProperties.includes("fill")) {
10804
+ targets.push("fill");
9738
10805
  }
9739
- return ATTR_NAME_TO_CSS_PROPERTY[attrName] ?? "color";
10806
+ if (cssProperties.includes("stroke")) {
10807
+ targets.push("stroke");
10808
+ }
10809
+ return targets;
9740
10810
  }
9741
10811
  function buildColorAnimationKeyframes(colorAnim, keyframeName, steps = 10) {
9742
10812
  const { colorSpace, direction, fromColor, toColor, byColor, targetAttribute } = colorAnim;
@@ -9756,99 +10826,335 @@ function buildColorAnimationKeyframes(colorAnim, keyframeName, steps = 10) {
9756
10826
  } else {
9757
10827
  return void 0;
9758
10828
  }
9759
- const cssProperty = resolveCssProperty(targetAttribute);
10829
+ const cssProperties = resolveCssProperties(targetAttribute);
9760
10830
  const lines = [];
9761
10831
  const actualSteps = Math.max(2, steps);
9762
10832
  for (let i = 0; i <= actualSteps; i++) {
9763
10833
  const t = i / actualSteps;
9764
10834
  const pct = Math.round(t * 100);
9765
10835
  const color = interpolateColor(effectiveFrom, effectiveTo, t, colorSpace, direction);
9766
- lines.push(` ${pct}% { ${cssProperty}: ${color}; }`);
10836
+ const decls = cssProperties.map((prop) => `${prop}: ${color};`).join(" ");
10837
+ lines.push(` ${pct}% { ${decls} }`);
9767
10838
  }
9768
10839
  return `@keyframes ${keyframeName} {
9769
10840
  ${lines.join("\n")}
9770
10841
  }`;
9771
10842
  }
9772
- function resolveEffect(anim) {
9773
- const cls = anim.presetClass;
9774
- const id = anim.presetId;
9775
- if (cls === void 0 || id === void 0) {
9776
- return void 0;
10843
+ function resolveChartBuildMode(token) {
10844
+ switch (token) {
10845
+ case "series":
10846
+ return "bySeries";
10847
+ case "category":
10848
+ return "byCategory";
10849
+ case "seriesElement":
10850
+ case "seriesEl":
10851
+ case "categoryElement":
10852
+ case "categoryEl":
10853
+ return "byElement";
10854
+ default:
10855
+ return "asOne";
10856
+ }
10857
+ }
10858
+ function resolveDiagramBuildMode(token) {
10859
+ switch (token) {
10860
+ case void 0:
10861
+ case "whole":
10862
+ case "allAtOnce":
10863
+ return "asOne";
10864
+ case "lvlOne":
10865
+ return "byLvl";
10866
+ case "lvlAtOnce":
10867
+ return "byLvlAtOnce";
10868
+ default:
10869
+ return "byOne";
9777
10870
  }
9778
- if (cls === "entr") {
9779
- return applyFlyDirection(PRESET_ID_TO_EFFECT.entr[id], anim.presetSubtype);
10871
+ }
10872
+ function resolveStepBuildDescriptor(anim) {
10873
+ const graphic = anim.graphicBuildProperties;
10874
+ if (graphic && graphic.mode === "sub") {
10875
+ if (graphic.kind === "chart") {
10876
+ const mode2 = resolveChartBuildMode(graphic.build);
10877
+ return mode2 === "asOne" ? void 0 : { kind: "chart", mode: mode2 };
10878
+ }
10879
+ const mode = resolveDiagramBuildMode(graphic.build);
10880
+ return mode === "asOne" ? void 0 : { kind: "diagram", mode };
9780
10881
  }
9781
- if (cls === "exit") {
9782
- return applyFlyDirection(PRESET_ID_TO_EFFECT.exit[id], anim.presetSubtype);
10882
+ if (anim.oleChartBuild !== void 0) {
10883
+ const mode = resolveChartBuildMode(anim.oleChartBuild);
10884
+ return mode === "asOne" ? void 0 : { kind: "chart", mode };
9783
10885
  }
9784
- if (cls === "emph") {
9785
- return PRESET_ID_TO_EFFECT.emph[id];
10886
+ if (anim.smartArtBuild !== void 0) {
10887
+ const mode = resolveDiagramBuildMode(anim.smartArtBuild);
10888
+ return mode === "asOne" ? void 0 : { kind: "diagram", mode };
9786
10889
  }
9787
10890
  return void 0;
9788
10891
  }
9789
- function applyFlyDirection(effect, subtype) {
9790
- if (effect !== "flyInBottom" && effect !== "flyOutBottom") {
9791
- return effect;
10892
+ function clamp01(value) {
10893
+ return Math.max(0, Math.min(1, value));
10894
+ }
10895
+ function computeBuildProgress(timing, elapsedMs) {
10896
+ if (timing.durationMs <= 0) {
10897
+ return elapsedMs >= timing.delayMs ? 1 : 0;
9792
10898
  }
9793
- if (subtype === void 0) {
9794
- return effect;
10899
+ return clamp01((elapsedMs - timing.delayMs) / timing.durationMs);
10900
+ }
10901
+ function revealedStageCount(progress, totalStages) {
10902
+ if (totalStages <= 0) {
10903
+ return 0;
9795
10904
  }
9796
- const edge = FLY_SUBTYPE_TO_EDGE[subtype];
9797
- if (!edge) {
9798
- return effect;
10905
+ const p = clamp01(progress);
10906
+ if (p <= 0) {
10907
+ return 0;
9799
10908
  }
9800
- const prefix = effect === "flyInBottom" ? "flyIn" : "flyOut";
9801
- const suffix = `${edge.charAt(0).toUpperCase()}${edge.slice(1)}`;
9802
- return `${prefix}${suffix}`;
10909
+ return Math.min(totalStages, Math.ceil(p * totalStages));
9803
10910
  }
9804
- function parseMotionPathPoints(motionPath) {
9805
- const cmds = motionPath.replace(/\s+/gu, " ").trim().split(/(?=[MLCZ])/iu).filter(Boolean);
9806
- const points = [];
9807
- for (const cmd of cmds) {
9808
- const type = cmd.charAt(0).toUpperCase();
9809
- if (type === "Z") {
9810
- continue;
10911
+ function applyStepBuildMetadata(state, step, options) {
10912
+ if (!step) {
10913
+ return;
10914
+ }
10915
+ if (step.build) {
10916
+ const progress = options?.elapsedMs === void 0 ? 1 : computeBuildProgress(step, options.elapsedMs);
10917
+ state.build = { ...step.build, progress };
10918
+ }
10919
+ if (step.colorTargets) {
10920
+ if (step.colorTargets.includes("fill")) {
10921
+ state.animatesFill = true;
9811
10922
  }
9812
- const nums = cmd.slice(1).trim().split(/[\s,]+/u).map(Number);
9813
- for (let i = 0; i + 1 < nums.length; i += 2) {
9814
- points.push({ x: nums[i] * 100, y: nums[i + 1] * 100 });
10923
+ if (step.colorTargets.includes("stroke")) {
10924
+ state.animatesStroke = true;
9815
10925
  }
9816
10926
  }
9817
- return points;
9818
10927
  }
9819
- function buildDynamicKeyframe(anim, uid) {
9820
- if (anim.motionPath) {
9821
- const name = `pptx-tl-motion-${uid}`;
9822
- const points = parseMotionPathPoints(anim.motionPath);
9823
- if (points.length < 2) {
9824
- return void 0;
10928
+ function categoryCount(chartData) {
10929
+ const longest = chartData.series.reduce((max, s) => Math.max(max, s.values.length), 0);
10930
+ return Math.max(chartData.categories.length, longest);
10931
+ }
10932
+ function applyChartBuildReveal(chartData, build) {
10933
+ const { series } = chartData;
10934
+ if (build.mode === "asOne" || series.length === 0) {
10935
+ return chartData;
10936
+ }
10937
+ if (build.mode === "bySeries") {
10938
+ const shown = revealedStageCount(build.progress, series.length);
10939
+ if (shown >= series.length) {
10940
+ return chartData;
9825
10941
  }
9826
- const lines = [];
9827
- for (let i = 0; i < points.length; i++) {
9828
- const pct = Math.round(i / (points.length - 1) * 100);
9829
- const tx = points[i].x.toFixed(2);
9830
- const ty = points[i].y.toFixed(2);
9831
- if (anim.motionPathRotateAuto) {
9832
- const next = i < points.length - 1 ? points[i + 1] : points[i];
9833
- const prev = i > 0 ? points[i - 1] : points[i];
9834
- const dx = i < points.length - 1 ? next.x - points[i].x : points[i].x - prev.x;
9835
- const dy = i < points.length - 1 ? next.y - points[i].y : points[i].y - prev.y;
9836
- const angleDeg = Math.atan2(dy, dx) * (180 / Math.PI);
9837
- lines.push(
9838
- ` ${pct}% { transform: translate(${tx}%, ${ty}%) rotate(${angleDeg.toFixed(2)}deg); }`
9839
- );
9840
- } else {
9841
- lines.push(` ${pct}% { transform: translate(${tx}%, ${ty}%); }`);
9842
- }
10942
+ return { ...chartData, series: series.slice(0, shown) };
10943
+ }
10944
+ const catCount = categoryCount(chartData);
10945
+ if (catCount === 0) {
10946
+ return chartData;
10947
+ }
10948
+ if (build.mode === "byCategory") {
10949
+ const shown = revealedStageCount(build.progress, catCount);
10950
+ if (shown >= catCount) {
10951
+ return chartData;
9843
10952
  }
9844
10953
  return {
9845
- keyframeName: name,
9846
- css: `@keyframes ${name} {
9847
- ${lines.join("\n")}
9848
- }`
10954
+ ...chartData,
10955
+ series: series.map((s) => ({ ...s, values: s.values.slice(0, shown) }))
9849
10956
  };
9850
10957
  }
9851
- if (anim.rotationBy !== void 0) {
10958
+ const total = series.length * catCount;
10959
+ const shownCells = revealedStageCount(build.progress, total);
10960
+ if (shownCells >= total) {
10961
+ return chartData;
10962
+ }
10963
+ return {
10964
+ ...chartData,
10965
+ series: series.map((s, si) => {
10966
+ const visibleInSeries = Math.max(0, Math.min(catCount, shownCells - si * catCount));
10967
+ return { ...s, values: s.values.slice(0, visibleInSeries) };
10968
+ })
10969
+ };
10970
+ }
10971
+ function nodeLevels(nodes) {
10972
+ const byId = /* @__PURE__ */ new Map();
10973
+ for (const node of nodes) {
10974
+ byId.set(node.id, node);
10975
+ }
10976
+ return nodes.map((node) => {
10977
+ let depth = 0;
10978
+ let current = node;
10979
+ const seen = /* @__PURE__ */ new Set();
10980
+ while (current?.parentId && !seen.has(current.id)) {
10981
+ seen.add(current.id);
10982
+ const parent = byId.get(current.parentId);
10983
+ if (!parent) {
10984
+ break;
10985
+ }
10986
+ depth++;
10987
+ current = parent;
10988
+ }
10989
+ return depth;
10990
+ });
10991
+ }
10992
+ function revealedSmartArtNodeCount(nodes, build) {
10993
+ if (build.mode === "asOne" || nodes.length === 0) {
10994
+ return nodes.length;
10995
+ }
10996
+ if (build.mode === "byLvlAtOnce") {
10997
+ const levels = nodeLevels(nodes);
10998
+ const uniqueLevels = [...new Set(levels)].sort((a, b) => a - b);
10999
+ const shownLevels = revealedStageCount(build.progress, uniqueLevels.length);
11000
+ if (shownLevels >= uniqueLevels.length) {
11001
+ return nodes.length;
11002
+ }
11003
+ const allowed = new Set(uniqueLevels.slice(0, shownLevels));
11004
+ return levels.filter((level) => allowed.has(level)).length;
11005
+ }
11006
+ return revealedStageCount(build.progress, nodes.length);
11007
+ }
11008
+ var BEZIER_SAMPLES = 8;
11009
+ function cubicAt(p0, c1, c2, p3, t) {
11010
+ const mt = 1 - t;
11011
+ return mt * mt * mt * p0 + 3 * mt * mt * t * c1 + 3 * mt * t * t * c2 + t * t * t * p3;
11012
+ }
11013
+ function allFinite(values) {
11014
+ return values.every((v) => Number.isFinite(v));
11015
+ }
11016
+ function parseMotionPathPoints(motionPath) {
11017
+ const tokens = motionPath.match(/[MLCZmlcz]|-?\d*\.?\d+(?:[eE][-+]?\d+)?/gu);
11018
+ if (!tokens) {
11019
+ return [];
11020
+ }
11021
+ const points = [];
11022
+ let curX = 0;
11023
+ let curY = 0;
11024
+ let startX = 0;
11025
+ let startY = 0;
11026
+ let i = 0;
11027
+ let cmd = "";
11028
+ const nextNum = () => Number(tokens[i++]);
11029
+ const push = (x, y) => {
11030
+ points.push({ x: x * 100, y: y * 100 });
11031
+ };
11032
+ while (i < tokens.length) {
11033
+ const tok = tokens[i];
11034
+ if (/^[MLCZmlcz]$/u.test(tok)) {
11035
+ cmd = tok;
11036
+ i++;
11037
+ if (cmd === "Z" || cmd === "z") {
11038
+ curX = startX;
11039
+ curY = startY;
11040
+ }
11041
+ continue;
11042
+ }
11043
+ const rel = cmd === cmd.toLowerCase();
11044
+ const upper = cmd.toUpperCase();
11045
+ if (upper === "M" || upper === "L") {
11046
+ let x = nextNum();
11047
+ let y = nextNum();
11048
+ if (!allFinite([x, y])) {
11049
+ break;
11050
+ }
11051
+ if (rel) {
11052
+ x += curX;
11053
+ y += curY;
11054
+ }
11055
+ curX = x;
11056
+ curY = y;
11057
+ if (upper === "M") {
11058
+ startX = x;
11059
+ startY = y;
11060
+ cmd = rel ? "l" : "L";
11061
+ }
11062
+ push(x, y);
11063
+ } else if (upper === "C") {
11064
+ let c1x = nextNum();
11065
+ let c1y = nextNum();
11066
+ let c2x = nextNum();
11067
+ let c2y = nextNum();
11068
+ let ex = nextNum();
11069
+ let ey = nextNum();
11070
+ if (!allFinite([c1x, c1y, c2x, c2y, ex, ey])) {
11071
+ break;
11072
+ }
11073
+ if (rel) {
11074
+ c1x += curX;
11075
+ c1y += curY;
11076
+ c2x += curX;
11077
+ c2y += curY;
11078
+ ex += curX;
11079
+ ey += curY;
11080
+ }
11081
+ for (let s = 1; s <= BEZIER_SAMPLES; s++) {
11082
+ const t = s / BEZIER_SAMPLES;
11083
+ push(cubicAt(curX, c1x, c2x, ex, t), cubicAt(curY, c1y, c2y, ey, t));
11084
+ }
11085
+ curX = ex;
11086
+ curY = ey;
11087
+ } else {
11088
+ i++;
11089
+ }
11090
+ }
11091
+ return points;
11092
+ }
11093
+ function resolveEffect(anim) {
11094
+ const cls = anim.presetClass;
11095
+ const id = anim.presetId;
11096
+ if (cls === void 0 || id === void 0) {
11097
+ return void 0;
11098
+ }
11099
+ if (cls === "entr") {
11100
+ return applyFlyDirection(PRESET_ID_TO_EFFECT.entr[id], anim.presetSubtype);
11101
+ }
11102
+ if (cls === "exit") {
11103
+ return applyFlyDirection(PRESET_ID_TO_EFFECT.exit[id], anim.presetSubtype);
11104
+ }
11105
+ if (cls === "emph") {
11106
+ return PRESET_ID_TO_EFFECT.emph[id];
11107
+ }
11108
+ return void 0;
11109
+ }
11110
+ function applyFlyDirection(effect, subtype) {
11111
+ if (effect !== "flyInBottom" && effect !== "flyOutBottom") {
11112
+ return effect;
11113
+ }
11114
+ if (subtype === void 0) {
11115
+ return effect;
11116
+ }
11117
+ const edge = FLY_SUBTYPE_TO_EDGE[subtype];
11118
+ if (!edge) {
11119
+ return effect;
11120
+ }
11121
+ const prefix = effect === "flyInBottom" ? "flyIn" : "flyOut";
11122
+ const suffix = `${edge.charAt(0).toUpperCase()}${edge.slice(1)}`;
11123
+ return `${prefix}${suffix}`;
11124
+ }
11125
+ function buildDynamicKeyframe(anim, uid) {
11126
+ if (anim.motionPath) {
11127
+ const name = `pptx-tl-motion-${uid}`;
11128
+ const points = parseMotionPathPoints(anim.motionPath);
11129
+ if (points.length < 2) {
11130
+ return void 0;
11131
+ }
11132
+ const lines = [];
11133
+ for (let i = 0; i < points.length; i++) {
11134
+ const pct = Math.round(i / (points.length - 1) * 100);
11135
+ const tx = points[i].x.toFixed(2);
11136
+ const ty = points[i].y.toFixed(2);
11137
+ if (anim.motionPathRotateAuto) {
11138
+ const next = i < points.length - 1 ? points[i + 1] : points[i];
11139
+ const prev = i > 0 ? points[i - 1] : points[i];
11140
+ const dx = i < points.length - 1 ? next.x - points[i].x : points[i].x - prev.x;
11141
+ const dy = i < points.length - 1 ? next.y - points[i].y : points[i].y - prev.y;
11142
+ const angleDeg = Math.atan2(dy, dx) * (180 / Math.PI);
11143
+ lines.push(
11144
+ ` ${pct}% { transform: translate(${tx}%, ${ty}%) rotate(${angleDeg.toFixed(2)}deg); }`
11145
+ );
11146
+ } else {
11147
+ lines.push(` ${pct}% { transform: translate(${tx}%, ${ty}%); }`);
11148
+ }
11149
+ }
11150
+ return {
11151
+ keyframeName: name,
11152
+ css: `@keyframes ${name} {
11153
+ ${lines.join("\n")}
11154
+ }`
11155
+ };
11156
+ }
11157
+ if (anim.rotationBy !== void 0) {
9852
11158
  const name = `pptx-tl-rotate-${uid}`;
9853
11159
  return {
9854
11160
  keyframeName: name,
@@ -9877,6 +11183,13 @@ ${lines.join("\n")}
9877
11183
  return { keyframeName: name, css };
9878
11184
  }
9879
11185
  }
11186
+ if (anim.presetClass === "emph") {
11187
+ const filterName = `pptx-tl-emph-${uid}`;
11188
+ const filterCss = emphasisFilterKeyframeCss(anim.presetId, filterName);
11189
+ if (filterCss) {
11190
+ return { keyframeName: filterName, css: filterCss };
11191
+ }
11192
+ }
9880
11193
  return void 0;
9881
11194
  }
9882
11195
  function cssKeyframeName(effect) {
@@ -10202,19 +11515,122 @@ function getAnimationInitialStyle(preset, nativeAnimation) {
10202
11515
  }
10203
11516
  return {};
10204
11517
  }
10205
- function cssEasingForAnimation(anim) {
10206
- const hasAccel = anim.accel !== void 0 && anim.accel > 0;
10207
- const hasDecel = anim.decel !== void 0 && anim.decel > 0;
10208
- if (hasAccel && hasDecel) {
10209
- return "ease-in-out";
11518
+ var WIPE_LIKE = /* @__PURE__ */ new Set([
11519
+ "wipeIn",
11520
+ "peekIn",
11521
+ "blindsIn",
11522
+ "wipeOut"
11523
+ ]);
11524
+ var SPLIT_LIKE = /* @__PURE__ */ new Set(["splitIn"]);
11525
+ function wipeStartInset(edge) {
11526
+ switch (edge) {
11527
+ case "left":
11528
+ return "inset(0 100% 0 0)";
11529
+ case "right":
11530
+ return "inset(0 0 0 100%)";
11531
+ case "top":
11532
+ return "inset(0 0 100% 0)";
11533
+ case "bottom":
11534
+ default:
11535
+ return "inset(100% 0 0 0)";
11536
+ }
11537
+ }
11538
+ function wipeRevealCss(name, edge) {
11539
+ return `@keyframes ${name} {
11540
+ from { clip-path: ${wipeStartInset(edge)}; opacity: 1; }
11541
+ to { clip-path: inset(0 0 0 0); opacity: 1; }
11542
+ }`;
11543
+ }
11544
+ function wipeHideCss(name, edge) {
11545
+ return `@keyframes ${name} {
11546
+ from { clip-path: inset(0 0 0 0); opacity: 1; }
11547
+ to { clip-path: ${wipeStartInset(edge)}; opacity: 0; }
11548
+ }`;
11549
+ }
11550
+ function splitRevealCss(name, orientation) {
11551
+ const start = orientation === "vertical" ? "inset(0 50% 0 50%)" : "inset(50% 0 50% 0)";
11552
+ return `@keyframes ${name} {
11553
+ from { clip-path: ${start}; opacity: 1; }
11554
+ to { clip-path: inset(0 0 0 0); opacity: 1; }
11555
+ }`;
11556
+ }
11557
+ function buildDirectionalKeyframe(effect, subtype, uid) {
11558
+ if (subtype === void 0) {
11559
+ return void 0;
11560
+ }
11561
+ const edge = FLY_SUBTYPE_TO_EDGE[subtype];
11562
+ if (!edge) {
11563
+ return void 0;
11564
+ }
11565
+ const name = `pptx-tl-dir-${uid}`;
11566
+ if (SPLIT_LIKE.has(effect)) {
11567
+ const orientation = edge === "left" || edge === "right" ? "vertical" : "horizontal";
11568
+ return { keyframeName: name, css: splitRevealCss(name, orientation) };
11569
+ }
11570
+ if (WIPE_LIKE.has(effect)) {
11571
+ const css = effect === "wipeOut" ? wipeHideCss(name, edge) : wipeRevealCss(name, edge);
11572
+ return { keyframeName: name, css };
11573
+ }
11574
+ return void 0;
11575
+ }
11576
+ function isMediaCommandAnimation(anim) {
11577
+ return typeof anim.commandString === "string" && anim.commandString.trim().length > 0;
11578
+ }
11579
+ function buildStepCommand(anim) {
11580
+ if (!isMediaCommandAnimation(anim)) {
11581
+ return void 0;
11582
+ }
11583
+ const command = (anim.commandString ?? "").trim();
11584
+ return {
11585
+ type: anim.commandType,
11586
+ command,
11587
+ targetId: anim.targetId ?? ""
11588
+ };
11589
+ }
11590
+ function parseMediaCommand(commandString) {
11591
+ const raw = commandString.trim();
11592
+ if (!raw) {
11593
+ return void 0;
11594
+ }
11595
+ const playFromMatch = raw.match(/^playfrom\s*\(\s*(-?\d*\.?\d+)?\s*\)$/i);
11596
+ if (playFromMatch) {
11597
+ const seconds = playFromMatch[1] !== void 0 ? Number.parseFloat(playFromMatch[1]) : 0;
11598
+ return { verb: "playFrom", seekSeconds: Number.isFinite(seconds) ? Math.max(0, seconds) : 0 };
10210
11599
  }
10211
- if (hasAccel) {
10212
- return "ease-in";
11600
+ const lower = raw.toLowerCase();
11601
+ if (lower === "play" || lower === "resume") {
11602
+ return { verb: "play" };
11603
+ }
11604
+ if (lower === "pause") {
11605
+ return { verb: "pause" };
11606
+ }
11607
+ if (lower === "stop" || lower === "stopmedia") {
11608
+ return { verb: "stop" };
11609
+ }
11610
+ if (lower === "toggleplay") {
11611
+ return { verb: "togglePlay" };
11612
+ }
11613
+ return void 0;
11614
+ }
11615
+ function clamp012(value) {
11616
+ return Math.max(0, Math.min(1, value));
11617
+ }
11618
+ function cssEasingForAnimation(anim) {
11619
+ const accel = anim.accel !== void 0 && anim.accel > 0 ? clamp012(anim.accel) : 0;
11620
+ const decel = anim.decel !== void 0 && anim.decel > 0 ? clamp012(anim.decel) : 0;
11621
+ if (accel === 0 && decel === 0) {
11622
+ return "ease";
10213
11623
  }
10214
- if (hasDecel) {
10215
- return "ease-out";
11624
+ const x1 = accel.toFixed(3);
11625
+ const x2 = (1 - decel).toFixed(3);
11626
+ return `cubic-bezier(${x1}, 0, ${x2}, 1)`;
11627
+ }
11628
+ function stepColorTargets(anim) {
11629
+ if (!anim.colorAnimation) {
11630
+ return void 0;
10216
11631
  }
10217
- return "ease";
11632
+ const targets = resolveColorAnimationTargets(anim.colorAnimation.targetAttribute);
11633
+ return targets.length > 0 ? targets : void 0;
10218
11634
  }
10219
11635
  function fallbackEffectForClass(presetClass) {
10220
11636
  if (presetClass === "entr") {
@@ -10223,6 +11639,9 @@ function fallbackEffectForClass(presetClass) {
10223
11639
  if (presetClass === "exit") {
10224
11640
  return "fadeOut";
10225
11641
  }
11642
+ if (presetClass === "emph") {
11643
+ return "pulse";
11644
+ }
10226
11645
  return void 0;
10227
11646
  }
10228
11647
  function buildTimeline(nativeAnimations) {
@@ -10260,27 +11679,39 @@ function buildTimeline(nativeAnimations) {
10260
11679
  const expandedSteps = expandIterateAnimation(anim);
10261
11680
  for (const singleAnim of expandedSteps) {
10262
11681
  let effect = resolveEffect(singleAnim);
10263
- const dynamic = effect ? void 0 : buildDynamicKeyframe(singleAnim, dynamicUid++);
10264
- if (!effect && !dynamic) {
11682
+ let dynamic = effect ? void 0 : buildDynamicKeyframe(singleAnim, dynamicUid++);
11683
+ if (effect) {
11684
+ const directional = buildDirectionalKeyframe(effect, singleAnim.presetSubtype, dynamicUid);
11685
+ if (directional) {
11686
+ dynamic = directional;
11687
+ effect = void 0;
11688
+ dynamicUid++;
11689
+ }
11690
+ }
11691
+ const isCommand = !effect && !dynamic && isMediaCommandAnimation(singleAnim);
11692
+ if (!effect && !dynamic && !isCommand) {
10265
11693
  effect = fallbackEffectForClass(singleAnim.presetClass);
10266
11694
  if (!effect) {
10267
11695
  continue;
10268
11696
  }
10269
11697
  }
10270
- const keyframe = effect ? cssKeyframeName(effect) : dynamic.keyframeName;
11698
+ let keyframe = "";
11699
+ if (!isCommand) {
11700
+ keyframe = effect ? cssKeyframeName(effect) : dynamic.keyframeName;
11701
+ }
10271
11702
  if (effect) {
10272
11703
  neededKeyframes.add(effect);
10273
11704
  }
10274
11705
  if (dynamic) {
10275
11706
  dynamicBlocks.push(dynamic.css);
10276
11707
  }
10277
- const elementId = singleAnim.targetId ?? "";
11708
+ const elementId = isCommand ? "" : singleAnim.targetId ?? "";
10278
11709
  const effective = resolveAnimationStart(singleAnim);
10279
11710
  const trigger = effective.trigger;
10280
- const duration = singleAnim.durationMs ?? defaultDuration(singleAnim.presetClass);
11711
+ const duration = isCommand ? 0 : singleAnim.durationMs ?? defaultDuration(singleAnim.presetClass);
10281
11712
  const animDelay = singleAnim.delayMs ?? 0;
10282
11713
  const triggerDelay = singleAnim.startConditions && singleAnim.startConditions.length > 0 ? effective.delayMs : singleAnim.triggerDelayMs ?? 0;
10283
- const presetClass = singleAnim.presetClass ?? "entr";
11714
+ const presetClass = isCommand ? "emph" : singleAnim.presetClass ?? "entr";
10284
11715
  const fill = fillModeForClass(singleAnim.presetClass);
10285
11716
  const iterCount = singleAnim.repeatCount ?? 1;
10286
11717
  const direction = singleAnim.autoReverse ? "alternate" : "normal";
@@ -10312,7 +11743,7 @@ function buildTimeline(nativeAnimations) {
10312
11743
  }
10313
11744
  const iterStr = iterCount === Infinity ? "infinite" : String(iterCount);
10314
11745
  const easing = cssEasingForAnimation(singleAnim);
10315
- const cssAnimation = `${keyframe} ${duration}ms ${easing} ${delayMs}ms ${iterStr} ${direction} ${fill}`;
11746
+ const cssAnimation = isCommand ? "" : `${keyframe} ${duration}ms ${easing} ${delayMs}ms ${iterStr} ${direction} ${fill}`;
10316
11747
  currentGroup.push({
10317
11748
  elementId,
10318
11749
  cssAnimation,
@@ -10323,7 +11754,10 @@ function buildTimeline(nativeAnimations) {
10323
11754
  fillMode: fill,
10324
11755
  presetClass,
10325
11756
  soundPath: singleAnim.soundPath,
10326
- stopSound: singleAnim.stopSound
11757
+ stopSound: singleAnim.stopSound,
11758
+ command: isCommand ? buildStepCommand(singleAnim) : void 0,
11759
+ build: isCommand ? void 0 : resolveStepBuildDescriptor(singleAnim),
11760
+ colorTargets: isCommand ? void 0 : stepColorTargets(singleAnim)
10327
11761
  });
10328
11762
  }
10329
11763
  }
@@ -10450,7 +11884,9 @@ function buildSequenceGroups(animsByKey, entranceIds, neededKeyframes, dynamicBl
10450
11884
  fillMode: fill,
10451
11885
  presetClass,
10452
11886
  soundPath: anim.soundPath,
10453
- stopSound: anim.stopSound
11887
+ stopSound: anim.stopSound,
11888
+ build: resolveStepBuildDescriptor(anim),
11889
+ colorTargets: stepColorTargets(anim)
10454
11890
  });
10455
11891
  }
10456
11892
  if (seqGroup.length > 0) {
@@ -10499,6 +11935,12 @@ var TimelineEngine = class _TimelineEngine {
10499
11935
  * that have been triggered so far (cumulative).
10500
11936
  */
10501
11937
  activeAnimations;
11938
+ /**
11939
+ * Map of elementId → the most recently applied step carrying a staged-build
11940
+ * or colour-target descriptor. Used to surface `build` / `animatesFill` /
11941
+ * `animatesStroke` on {@link ElementAnimationState}.
11942
+ */
11943
+ activeSteps;
10502
11944
  /**
10503
11945
  * Set of element IDs whose entrance animation has played.
10504
11946
  * These elements become visible.
@@ -10523,6 +11965,7 @@ var TimelineEngine = class _TimelineEngine {
10523
11965
  this.timeline = timeline;
10524
11966
  this.currentGroupIndex = -1;
10525
11967
  this.activeAnimations = /* @__PURE__ */ new Map();
11968
+ this.activeSteps = /* @__PURE__ */ new Map();
10526
11969
  this.revealedElements = /* @__PURE__ */ new Set();
10527
11970
  this.exitedElements = /* @__PURE__ */ new Set();
10528
11971
  this.interactiveGroupIndexes = /* @__PURE__ */ new Map();
@@ -10620,13 +12063,15 @@ var TimelineEngine = class _TimelineEngine {
10620
12063
  * Build a snapshot of the current animation state for all elements.
10621
12064
  * Returns a map: elementId → { visible, cssAnimation }.
10622
12065
  */
10623
- getElementStates(elementIds) {
12066
+ getElementStates(elementIds, options) {
10624
12067
  const states = /* @__PURE__ */ new Map();
10625
12068
  for (const id of elementIds) {
10626
- states.set(id, {
12069
+ const state = {
10627
12070
  visible: this.isElementVisible(id),
10628
12071
  cssAnimation: this.activeAnimations.get(id)
10629
- });
12072
+ };
12073
+ applyStepBuildMetadata(state, this.activeSteps.get(id), options);
12074
+ states.set(id, state);
10630
12075
  }
10631
12076
  return states;
10632
12077
  }
@@ -10705,6 +12150,7 @@ var TimelineEngine = class _TimelineEngine {
10705
12150
  reset() {
10706
12151
  this.currentGroupIndex = -1;
10707
12152
  this.activeAnimations.clear();
12153
+ this.activeSteps.clear();
10708
12154
  this.revealedElements.clear();
10709
12155
  this.exitedElements.clear();
10710
12156
  this.interactiveGroupIndexes.clear();
@@ -10716,6 +12162,9 @@ var TimelineEngine = class _TimelineEngine {
10716
12162
  applyGroupSteps(group) {
10717
12163
  for (const step of group.steps) {
10718
12164
  this.activeAnimations.set(step.elementId, step.cssAnimation);
12165
+ if (step.build || step.colorTargets) {
12166
+ this.activeSteps.set(step.elementId, step);
12167
+ }
10719
12168
  if (step.presetClass === "entr") {
10720
12169
  this.revealedElements.add(step.elementId);
10721
12170
  }
@@ -10725,6 +12174,151 @@ var TimelineEngine = class _TimelineEngine {
10725
12174
  }
10726
12175
  }
10727
12176
  };
12177
+ function buildSegmentCounts(slide, nativeAnims) {
12178
+ const segmentCounts = /* @__PURE__ */ new Map();
12179
+ for (const anim of nativeAnims) {
12180
+ if (anim.buildType && anim.buildType !== "allAtOnce" && anim.targetId) {
12181
+ const el = slide.elements.find((e) => e.id === anim.targetId);
12182
+ if (el && hasTextProperties(el) && el.textSegments && el.textSegments.length > 0) {
12183
+ segmentCounts.set(anim.targetId, countTextSegments(el.textSegments));
12184
+ }
12185
+ }
12186
+ }
12187
+ return segmentCounts;
12188
+ }
12189
+ var PresentationAnimationController = class _PresentationAnimationController {
12190
+ engine;
12191
+ keyframes;
12192
+ interactiveIds;
12193
+ hoverIds;
12194
+ ids;
12195
+ constructor(engine, elementIds) {
12196
+ this.engine = engine;
12197
+ this.keyframes = engine.getTimeline().keyframesCss;
12198
+ this.interactiveIds = engine.getInteractiveTriggerShapeIds();
12199
+ this.hoverIds = engine.getHoverTriggerShapeIds();
12200
+ this.ids = elementIds;
12201
+ }
12202
+ /**
12203
+ * Build a controller from a slide. Expands staged text-build animations into
12204
+ * per-segment sub-animations before constructing the {@link TimelineEngine},
12205
+ * then caches the keyframes CSS, trigger-shape id sets, and the full element
12206
+ * id list (base element ids + text-build sub-element ids) to track.
12207
+ */
12208
+ static fromSlide(slide) {
12209
+ const nativeAnims = slide.nativeAnimations ?? [];
12210
+ const segmentCounts = buildSegmentCounts(slide, nativeAnims);
12211
+ const expandedAnims = segmentCounts.size > 0 ? expandTextBuildAnimations(nativeAnims, segmentCounts) : nativeAnims;
12212
+ const engine = TimelineEngine.fromAnimations(expandedAnims);
12213
+ const elementIds = slide.elements.map((element) => element.id);
12214
+ for (const anim of expandedAnims) {
12215
+ if (anim.targetId && anim.targetId.includes(TEXT_BUILD_ID_SEP)) {
12216
+ elementIds.push(anim.targetId);
12217
+ }
12218
+ }
12219
+ return new _PresentationAnimationController(engine, elementIds);
12220
+ }
12221
+ /** The `@keyframes` CSS blocks a binding injects once per slide. */
12222
+ get keyframesCss() {
12223
+ return this.keyframes;
12224
+ }
12225
+ /** Shape ids that trigger an interactive (`onShapeClick`) sequence. */
12226
+ get interactiveTriggerShapeIds() {
12227
+ return this.interactiveIds;
12228
+ }
12229
+ /** Shape ids that trigger a hover (`onHover`) sequence. */
12230
+ get hoverTriggerShapeIds() {
12231
+ return this.hoverIds;
12232
+ }
12233
+ /** Every element id (plus text-build sub-element ids) tracked for state. */
12234
+ get elementIds() {
12235
+ return this.ids;
12236
+ }
12237
+ // -----------------------------------------------------------------------
12238
+ // Main click-group stepping (delegated to the engine)
12239
+ // -----------------------------------------------------------------------
12240
+ /** True when more click-groups remain to play. */
12241
+ hasMoreSteps() {
12242
+ return this.engine.hasMoreSteps();
12243
+ }
12244
+ /** Advance to the next click-group; `null` when none remain. */
12245
+ advance() {
12246
+ return this.engine.advance();
12247
+ }
12248
+ /** Peek at the next click-group without advancing. */
12249
+ peekNext() {
12250
+ return this.engine.peekNext();
12251
+ }
12252
+ /** True when the next click-group should auto-play without a click. */
12253
+ shouldAutoAdvance() {
12254
+ return this.engine.shouldAutoAdvance();
12255
+ }
12256
+ /** Auto-advance delay (ms) for the next group; 0 when not applicable. */
12257
+ getAutoAdvanceDelay() {
12258
+ return this.engine.getAutoAdvanceDelay();
12259
+ }
12260
+ /** Reset all playback state to the slide's initial (nothing played). */
12261
+ reset() {
12262
+ this.engine.reset();
12263
+ }
12264
+ // -----------------------------------------------------------------------
12265
+ // Interactive + hover sequences (delegated to the engine)
12266
+ // -----------------------------------------------------------------------
12267
+ /** True when `shapeId` triggers an interactive sequence. */
12268
+ hasInteractiveSequence(shapeId) {
12269
+ return this.engine.hasInteractiveSequence(shapeId);
12270
+ }
12271
+ /** Advance the interactive sequence for `shapeId`; `null` when exhausted. */
12272
+ advanceInteractive(shapeId) {
12273
+ return this.engine.advanceInteractive(shapeId);
12274
+ }
12275
+ /** True when `shapeId` triggers a hover sequence. */
12276
+ hasHoverSequence(shapeId) {
12277
+ return this.engine.hasHoverSequence(shapeId);
12278
+ }
12279
+ /** Advance the hover sequence for `shapeId`; `null` when exhausted. */
12280
+ advanceHover(shapeId) {
12281
+ return this.engine.advanceHover(shapeId);
12282
+ }
12283
+ /** Reset the hover sequence for `shapeId` so the next hover replays it. */
12284
+ resetHover(shapeId) {
12285
+ this.engine.resetHover(shapeId);
12286
+ }
12287
+ // -----------------------------------------------------------------------
12288
+ // State snapshots
12289
+ // -----------------------------------------------------------------------
12290
+ /**
12291
+ * Snapshot the current animation state for every tracked element id.
12292
+ * Pass `{ elapsedMs }` to project staged-build `progress` at that playback
12293
+ * time (see the module header's build-reveal contract).
12294
+ */
12295
+ computeStates(options) {
12296
+ return this.engine.getElementStates(this.ids, options);
12297
+ }
12298
+ /**
12299
+ * Snapshot the animation state for a specific subset of element ids. Used by
12300
+ * a binding's staged-build requestAnimationFrame loop to re-read only the
12301
+ * build elements' `build` descriptor at the current `elapsedMs`.
12302
+ */
12303
+ computeStatesFor(elementIds, options) {
12304
+ return this.engine.getElementStates(elementIds, options);
12305
+ }
12306
+ /**
12307
+ * Element ids of the steps in a click-group that reveal a staged chart /
12308
+ * SmartArt build (`p:bldChart` / `p:bldDgm`). A non-empty result tells a
12309
+ * binding the group needs a requestAnimationFrame reveal loop; an empty result
12310
+ * means ordinary discrete click-advance is enough.
12311
+ */
12312
+ static collectBuildStepIds(group) {
12313
+ const ids = [];
12314
+ for (const step of group.steps) {
12315
+ if (step.build) {
12316
+ ids.push(step.elementId);
12317
+ }
12318
+ }
12319
+ return ids;
12320
+ }
12321
+ };
10728
12322
  var PRESET_TO_EFFECT = {
10729
12323
  fadeIn: "fadeIn",
10730
12324
  flyIn: "flyInBottom",
@@ -11289,6 +12883,21 @@ var LIGHT_RIG_MAP = {
11289
12883
  filter: "contrast(1.1)"
11290
12884
  }
11291
12885
  };
12886
+ function safeHexColor(color) {
12887
+ if (!color) {
12888
+ return void 0;
12889
+ }
12890
+ const candidate = color.startsWith("#") ? color : `#${color}`;
12891
+ if (/^#[0-9a-fA-F]{6}$/u.test(candidate)) {
12892
+ return candidate;
12893
+ }
12894
+ const short = /^#(?<r>[0-9a-fA-F])(?<g>[0-9a-fA-F])(?<b>[0-9a-fA-F])$/u.exec(candidate);
12895
+ if (short?.groups) {
12896
+ const { r, g, b } = short.groups;
12897
+ return `#${r}${r}${g}${g}${b}${b}`;
12898
+ }
12899
+ return void 0;
12900
+ }
11292
12901
  function getLightDirectionAngle(direction) {
11293
12902
  switch (direction) {
11294
12903
  case "t":
@@ -11448,7 +13057,7 @@ function getExtrusionDirection(rotateX, rotateY) {
11448
13057
  }
11449
13058
  return { dx, dy };
11450
13059
  }
11451
- function getExtrusionBoxShadow(shape3d, cameraRotX = 0, cameraRotY = 0) {
13060
+ function getExtrusionBoxShadow(shape3d, cameraRotX = 0, cameraRotY = 0, fillColorFallback) {
11452
13061
  if (!shape3d?.extrusionHeight || shape3d.extrusionHeight <= 0) {
11453
13062
  return void 0;
11454
13063
  }
@@ -11458,7 +13067,7 @@ function getExtrusionBoxShadow(shape3d, cameraRotX = 0, cameraRotY = 0) {
11458
13067
  }
11459
13068
  const layerCount = Math.min(rawDepthPx, MAX_EXTRUSION_LAYERS);
11460
13069
  const step = rawDepthPx / layerCount;
11461
- const extColor = shape3d.extrusionColor || "#888888";
13070
+ const extColor = safeHexColor(shape3d.extrusionColor) ?? safeHexColor(fillColorFallback) ?? "#888888";
11462
13071
  const { dx, dy } = getExtrusionDirection(cameraRotX, cameraRotY);
11463
13072
  const depthShadows = [];
11464
13073
  for (let i = 1; i <= layerCount; i++) {
@@ -11474,12 +13083,12 @@ function getExtrusionBoxShadow(shape3d, cameraRotX = 0, cameraRotY = 0) {
11474
13083
  );
11475
13084
  return depthShadows.join(", ");
11476
13085
  }
11477
- function getContourBoxShadow(shape3d) {
13086
+ function getContourBoxShadow(shape3d, lineColorFallback) {
11478
13087
  if (!shape3d?.contourWidth || shape3d.contourWidth <= 0) {
11479
13088
  return void 0;
11480
13089
  }
11481
13090
  const widthPx = Math.max(1, Math.round(shape3d.contourWidth / EMU_PER_PX));
11482
- const color = shape3d.contourColor || "#000000";
13091
+ const color = safeHexColor(shape3d.contourColor) ?? safeHexColor(lineColorFallback) ?? "#000000";
11483
13092
  return `0 0 0 ${widthPx}px ${color}`;
11484
13093
  }
11485
13094
  function get3DBevelShadow(shape3d) {
@@ -11499,7 +13108,7 @@ function get3DBevelShadow(shape3d) {
11499
13108
  }
11500
13109
  return parts.length > 0 ? parts.join(", ") : void 0;
11501
13110
  }
11502
- function apply3dEffects(base, scene3d, shape3d) {
13111
+ function apply3dEffects(base, scene3d, shape3d, fillColorFallback) {
11503
13112
  if (!scene3d && !shape3d) {
11504
13113
  return;
11505
13114
  }
@@ -11532,11 +13141,11 @@ function apply3dEffects(base, scene3d, shape3d) {
11532
13141
  base.willChange = "transform";
11533
13142
  base.transformStyle = "preserve-3d";
11534
13143
  }
11535
- const extrusionShadow = getExtrusionBoxShadow(shape3d, rotateX, rotateY);
13144
+ const extrusionShadow = getExtrusionBoxShadow(shape3d, rotateX, rotateY, fillColorFallback);
11536
13145
  if (extrusionShadow) {
11537
13146
  base.boxShadow = base.boxShadow ? `${base.boxShadow}, ${extrusionShadow}` : extrusionShadow;
11538
13147
  }
11539
- const contourShadow = getContourBoxShadow(shape3d);
13148
+ const contourShadow = getContourBoxShadow(shape3d, fillColorFallback);
11540
13149
  if (contourShadow) {
11541
13150
  base.boxShadow = base.boxShadow ? `${base.boxShadow}, ${contourShadow}` : contourShadow;
11542
13151
  }
@@ -11571,29 +13180,242 @@ function apply3dEffects(base, scene3d, shape3d) {
11571
13180
  base.backgroundImage = base.backgroundImage ? `${lightRig.backgroundImage}, ${base.backgroundImage}` : lightRig.backgroundImage;
11572
13181
  }
11573
13182
  }
11574
- function ooxmlDashToCssBorderStyle(dashVal) {
11575
- if (!dashVal) {
11576
- return "solid";
13183
+ function collectSections(entry, tableData, pos) {
13184
+ const { rowIndex, cellIndex, rowCount, columnCount } = pos;
13185
+ const isTop = rowIndex === 0;
13186
+ const isBottom = rowIndex === rowCount - 1;
13187
+ const isLeft = cellIndex === 0;
13188
+ const isRight = cellIndex === columnCount - 1;
13189
+ const sections = [];
13190
+ const push = (borders, regionTop, regionBottom, regionLeft, regionRight) => {
13191
+ if (borders) {
13192
+ sections.push({ borders, regionTop, regionBottom, regionLeft, regionRight });
13193
+ }
13194
+ };
13195
+ push(entry.wholeTblBorders, isTop, isBottom, isLeft, isRight);
13196
+ if (tableData.bandedRows) {
13197
+ const bandStartRow = tableData.firstRowHeader ? 1 : 0;
13198
+ const bandEndRow = tableData.lastRow ? rowCount - 1 : rowCount;
13199
+ if (rowIndex >= bandStartRow && rowIndex < bandEndRow) {
13200
+ const rowCycle = Math.max(tableData.bandRowCycle ?? 1, 1);
13201
+ const bandGroup = Math.floor((rowIndex - bandStartRow) / rowCycle) % 2;
13202
+ push(
13203
+ bandGroup === 0 ? entry.band1HBorders : entry.band2HBorders,
13204
+ true,
13205
+ true,
13206
+ isLeft,
13207
+ isRight
13208
+ );
13209
+ }
11577
13210
  }
11578
- switch (dashVal) {
11579
- case "dot":
11580
- case "sysDot":
11581
- return "dotted";
11582
- case "dash":
11583
- case "sysDash":
11584
- case "lgDash":
11585
- case "dashDot":
11586
- case "lgDashDot":
11587
- case "sysDashDot":
11588
- case "lgDashDotDot":
11589
- case "sysDashDotDot":
11590
- return "dashed";
11591
- default:
11592
- return "solid";
13211
+ if (tableData.bandedColumns) {
13212
+ const colStart = tableData.firstCol ? 1 : 0;
13213
+ const colEnd = tableData.lastCol ? columnCount - 1 : columnCount;
13214
+ if (cellIndex >= colStart && cellIndex < colEnd) {
13215
+ const colCycle = Math.max(tableData.bandColCycle ?? 1, 1);
13216
+ const colGroup = Math.floor((cellIndex - colStart) / colCycle) % 2;
13217
+ push(colGroup === 0 ? entry.band1VBorders : entry.band2VBorders, isTop, isBottom, true, true);
13218
+ }
13219
+ }
13220
+ if (tableData.firstRowHeader && isTop) {
13221
+ push(entry.firstRowBorders, true, true, isLeft, isRight);
13222
+ }
13223
+ if (tableData.lastRow && isBottom) {
13224
+ push(entry.lastRowBorders, true, true, isLeft, isRight);
11593
13225
  }
13226
+ if (tableData.firstCol && isLeft) {
13227
+ push(entry.firstColBorders, isTop, isBottom, true, true);
13228
+ }
13229
+ if (tableData.lastCol && isRight) {
13230
+ push(entry.lastColBorders, isTop, isBottom, true, true);
13231
+ }
13232
+ return sections;
11594
13233
  }
11595
- function computeBoundingRect(cells) {
11596
- if (cells.length === 0) {
13234
+ function resolveStyleDiagonalBorders(entry, tableData, pos, resolve) {
13235
+ if (!entry) {
13236
+ return void 0;
13237
+ }
13238
+ const sections = collectSections(entry, tableData, pos);
13239
+ if (sections.length === 0) {
13240
+ return void 0;
13241
+ }
13242
+ let tl2br;
13243
+ let bl2tr;
13244
+ for (const section of sections) {
13245
+ if (section.borders.tl2br) {
13246
+ tl2br = section.borders.tl2br;
13247
+ }
13248
+ if (section.borders.bl2tr) {
13249
+ bl2tr = section.borders.bl2tr;
13250
+ }
13251
+ }
13252
+ const info = {};
13253
+ let applied = false;
13254
+ if (tl2br && !tl2br.noFill) {
13255
+ info.diagDownColor = tl2br.color ?? resolve(tl2br.fill) ?? "#000000";
13256
+ info.diagDownWidth = tl2br.width ?? 1;
13257
+ applied = true;
13258
+ }
13259
+ if (bl2tr && !bl2tr.noFill) {
13260
+ info.diagUpColor = bl2tr.color ?? resolve(bl2tr.fill) ?? "#000000";
13261
+ info.diagUpWidth = bl2tr.width ?? 1;
13262
+ applied = true;
13263
+ }
13264
+ return applied ? info : void 0;
13265
+ }
13266
+ function hexToRgb4(hex) {
13267
+ const clean = hex.replace(/^#/u, "");
13268
+ return {
13269
+ r: parseInt(clean.substring(0, 2), 16),
13270
+ g: parseInt(clean.substring(2, 4), 16),
13271
+ b: parseInt(clean.substring(4, 6), 16)
13272
+ };
13273
+ }
13274
+ function rgbToHex4(r, g, b) {
13275
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
13276
+ return `#${clamp8(r).toString(16).padStart(2, "0").toUpperCase()}${clamp8(g).toString(16).padStart(2, "0").toUpperCase()}${clamp8(b).toString(16).padStart(2, "0").toUpperCase()}`;
13277
+ }
13278
+ function tintColor(hex, tintFactor) {
13279
+ const { r, g, b } = hexToRgb4(hex);
13280
+ return rgbToHex4(
13281
+ r + (255 - r) * tintFactor,
13282
+ g + (255 - g) * tintFactor,
13283
+ b + (255 - b) * tintFactor
13284
+ );
13285
+ }
13286
+ function shadeColor(hex, shadeFactor) {
13287
+ const { r, g, b } = hexToRgb4(hex);
13288
+ return rgbToHex4(r * (1 - shadeFactor), g * (1 - shadeFactor), b * (1 - shadeFactor));
13289
+ }
13290
+ function applyTintShade(base, fill) {
13291
+ let color = base;
13292
+ if (fill.tint !== void 0 && fill.tint > 0) {
13293
+ color = tintColor(color, fill.tint / 1e5);
13294
+ }
13295
+ if (fill.shade !== void 0 && fill.shade > 0) {
13296
+ color = shadeColor(color, 1 - fill.shade / 1e5);
13297
+ }
13298
+ return color;
13299
+ }
13300
+ function resolveStyleFillColor(fill, colorScheme) {
13301
+ if (!fill) {
13302
+ return void 0;
13303
+ }
13304
+ let base;
13305
+ if (fill.schemeColor && colorScheme) {
13306
+ base = colorScheme[fill.schemeColor];
13307
+ }
13308
+ if (!base && fill.color) {
13309
+ base = fill.color;
13310
+ }
13311
+ if (!base) {
13312
+ return void 0;
13313
+ }
13314
+ return applyTintShade(base, fill);
13315
+ }
13316
+ function resolveFontRefIdx(idx, fontScheme) {
13317
+ if (!idx || !fontScheme) {
13318
+ return void 0;
13319
+ }
13320
+ if (idx === "minor") {
13321
+ return fontScheme.minorFont?.latin;
13322
+ }
13323
+ if (idx === "major") {
13324
+ return fontScheme.majorFont?.latin;
13325
+ }
13326
+ return void 0;
13327
+ }
13328
+ var BEVEL_LIGHT_OFFSETS = {
13329
+ tl: { x: 1, y: 1 },
13330
+ t: { x: 0, y: 1 },
13331
+ tr: { x: -1, y: 1 },
13332
+ r: { x: -1, y: 0 },
13333
+ br: { x: -1, y: -1 },
13334
+ b: { x: 0, y: -1 },
13335
+ bl: { x: 1, y: -1 },
13336
+ l: { x: 1, y: 0 }
13337
+ };
13338
+ function cell3DBevelCss(cell3D) {
13339
+ const size = Math.max(cell3D.bevelHeight ?? cell3D.bevelWidth ?? 4, 1);
13340
+ const dir = cell3D.lightRigDirection ?? "tl";
13341
+ const off = BEVEL_LIGHT_OFFSETS[dir] ?? BEVEL_LIGHT_OFFSETS.tl;
13342
+ const highlight = `inset ${off.x * size}px ${off.y * size}px ${size}px rgba(255,255,255,0.55)`;
13343
+ const shadow = `inset ${-off.x * size}px ${-off.y * size}px ${size}px rgba(0,0,0,0.4)`;
13344
+ return { boxShadow: `${highlight}, ${shadow}` };
13345
+ }
13346
+ function resolveTableStyleEntry(tableStyleId, tableStyleMap) {
13347
+ if (!tableStyleId || !tableStyleMap) {
13348
+ return void 0;
13349
+ }
13350
+ const direct = tableStyleMap[tableStyleId];
13351
+ if (direct) {
13352
+ return direct;
13353
+ }
13354
+ const normalised = tableStyleId.trim().toUpperCase();
13355
+ const withBraces = normalised.startsWith("{") ? normalised : `{${normalised}}`;
13356
+ return tableStyleMap[withBraces];
13357
+ }
13358
+ function ooxmlDashToCssBorderStyle(dashVal) {
13359
+ if (!dashVal) {
13360
+ return "solid";
13361
+ }
13362
+ switch (dashVal) {
13363
+ case "dot":
13364
+ case "sysDot":
13365
+ return "dotted";
13366
+ case "dash":
13367
+ case "sysDash":
13368
+ case "lgDash":
13369
+ case "dashDot":
13370
+ case "lgDashDot":
13371
+ case "sysDashDot":
13372
+ case "lgDashDotDot":
13373
+ case "sysDashDotDot":
13374
+ return "dashed";
13375
+ default:
13376
+ return "solid";
13377
+ }
13378
+ }
13379
+ function getDiagonalBorders(style, styleDiagonals) {
13380
+ const cellHasDown = Boolean(style?.borderDiagDownColor && style?.borderDiagDownWidth);
13381
+ const cellHasUp = Boolean(style?.borderDiagUpColor && style?.borderDiagUpWidth);
13382
+ const styleHasDown = Boolean(styleDiagonals?.diagDownColor && styleDiagonals?.diagDownWidth);
13383
+ const styleHasUp = Boolean(styleDiagonals?.diagUpColor && styleDiagonals?.diagUpWidth);
13384
+ if (!cellHasDown && !cellHasUp && !styleHasDown && !styleHasUp) {
13385
+ return null;
13386
+ }
13387
+ const info = {};
13388
+ if (cellHasDown) {
13389
+ info.diagDownColor = style?.borderDiagDownColor;
13390
+ info.diagDownWidth = style?.borderDiagDownWidth;
13391
+ } else if (styleHasDown) {
13392
+ info.diagDownColor = styleDiagonals?.diagDownColor;
13393
+ info.diagDownWidth = styleDiagonals?.diagDownWidth;
13394
+ }
13395
+ if (cellHasUp) {
13396
+ info.diagUpColor = style?.borderDiagUpColor;
13397
+ info.diagUpWidth = style?.borderDiagUpWidth;
13398
+ } else if (styleHasUp) {
13399
+ info.diagUpColor = styleDiagonals?.diagUpColor;
13400
+ info.diagUpWidth = styleDiagonals?.diagUpWidth;
13401
+ }
13402
+ return info;
13403
+ }
13404
+ function getCellDiagonalBorders(style, tableData, pos, styleCtx) {
13405
+ let styleDiagonals;
13406
+ if (tableData) {
13407
+ const entry = resolveTableStyleEntry(tableData.tableStyleId, styleCtx?.tableStyleMap);
13408
+ styleDiagonals = resolveStyleDiagonalBorders(
13409
+ entry,
13410
+ tableData,
13411
+ pos,
13412
+ (fill) => resolveStyleFillColor(fill, styleCtx?.colorScheme)
13413
+ );
13414
+ }
13415
+ return getDiagonalBorders(style, styleDiagonals);
13416
+ }
13417
+ function computeBoundingRect(cells) {
13418
+ if (cells.length === 0) {
11597
13419
  return void 0;
11598
13420
  }
11599
13421
  let startRow = cells[0].row;
@@ -13309,6 +15131,7 @@ function generateTicks(slideLengthPx, scale, unit) {
13309
15131
  }
13310
15132
  return ticks;
13311
15133
  }
15134
+ Array.from({ length: 46 }, (_v, i) => i).filter((i) => i !== 3620 - 3585 && i !== 3622 - 3585).map((i) => String.fromCodePoint(3585 + i));
13312
15135
  function resolvePictureBullet(info, baseFontSize) {
13313
15136
  if (!info.imageDataUrl && !info.imageRelId && !info.imageBlipFillXml) {
13314
15137
  return void 0;
@@ -14148,8 +15971,8 @@ function hexToRgb6(hex) {
14148
15971
  };
14149
15972
  }
14150
15973
  function rgbToHex5(r, g, b) {
14151
- const clamp7 = (v) => Math.max(0, Math.min(255, Math.round(v)));
14152
- return `#${clamp7(r).toString(16).padStart(2, "0").toUpperCase()}${clamp7(g).toString(16).padStart(2, "0").toUpperCase()}${clamp7(b).toString(16).padStart(2, "0").toUpperCase()}`;
15974
+ const clamp8 = (v) => Math.max(0, Math.min(255, Math.round(v)));
15975
+ return `#${clamp8(r).toString(16).padStart(2, "0").toUpperCase()}${clamp8(g).toString(16).padStart(2, "0").toUpperCase()}${clamp8(b).toString(16).padStart(2, "0").toUpperCase()}`;
14153
15976
  }
14154
15977
  function tintColor2(hex, tintFactor) {
14155
15978
  const { r, g, b } = hexToRgb6(hex);
@@ -14567,7 +16390,7 @@ function rerouteConnectorsForMovedElements(elements, movedElementIds) {
14567
16390
  }
14568
16391
  return rerouted;
14569
16392
  }
14570
- function computeConnectorGeometry(connector, startConn, endConn, elementMap) {
16393
+ function computeConnectorGeometry(connector2, startConn, endConn, elementMap) {
14571
16394
  let sx;
14572
16395
  let sy;
14573
16396
  if (startConn?.shapeId) {
@@ -14581,8 +16404,8 @@ function computeConnectorGeometry(connector, startConn, endConn, elementMap) {
14581
16404
  sx = startShape.x + site.x;
14582
16405
  sy = startShape.y + site.y;
14583
16406
  } else {
14584
- sx = connector.x;
14585
- sy = connector.y;
16407
+ sx = connector2.x;
16408
+ sy = connector2.y;
14586
16409
  }
14587
16410
  let ex;
14588
16411
  let ey;
@@ -14597,13 +16420,13 @@ function computeConnectorGeometry(connector, startConn, endConn, elementMap) {
14597
16420
  ex = endShape.x + site.x;
14598
16421
  ey = endShape.y + site.y;
14599
16422
  } else {
14600
- ex = connector.x + connector.width;
14601
- ey = connector.y + connector.height;
16423
+ ex = connector2.x + connector2.width;
16424
+ ey = connector2.y + connector2.height;
14602
16425
  }
14603
16426
  const flipHorizontal = ex < sx;
14604
16427
  const flipVertical = ey < sy;
14605
16428
  return {
14606
- id: connector.id,
16429
+ id: connector2.id,
14607
16430
  x: Math.min(sx, ex),
14608
16431
  y: Math.min(sy, ey),
14609
16432
  width: Math.abs(ex - sx) || 1,
@@ -15085,6 +16908,16 @@ var ASSET_REF_KEYS = {
15085
16908
  var REV_ASSET_REF_KEYS = Object.fromEntries(
15086
16909
  Object.entries(ASSET_REF_KEYS).map(([field, ref]) => [ref, field])
15087
16910
  );
16911
+ var ASSET_VERSION_SUFFIX = "__v";
16912
+ function assetVersionKey(fieldName) {
16913
+ return `${fieldName}${ASSET_VERSION_SUFFIX}`;
16914
+ }
16915
+ function isAssetVersionKey(key) {
16916
+ if (!key.endsWith(ASSET_VERSION_SUFFIX)) {
16917
+ return false;
16918
+ }
16919
+ return ASSET_ELEMENT_FIELDS.has(key.slice(0, -ASSET_VERSION_SUFFIX.length));
16920
+ }
15088
16921
  function assetKey(elementId, fieldName) {
15089
16922
  return `${elementId}:${fieldName}`;
15090
16923
  }
@@ -15114,6 +16947,9 @@ function reconcileAssetFields(elementId, rec, ymap, assets) {
15114
16947
  const key = assetKey(elementId, field);
15115
16948
  if (assets.get(key) !== value) {
15116
16949
  assets.set(key, value);
16950
+ const vKey = assetVersionKey(field);
16951
+ const currentVersion = ymap.get(vKey);
16952
+ ymap.set(vKey, (typeof currentVersion === "number" ? currentVersion : 0) + 1);
15117
16953
  }
15118
16954
  if (ymap.get(refKey) !== key) {
15119
16955
  ymap.set(refKey, key);
@@ -15488,6 +17324,7 @@ var COMPLEX_SLIDE_FIELDS = {
15488
17324
  guides: "_gu",
15489
17325
  customerData: "_cu",
15490
17326
  activeXControls: "_ax",
17327
+ legacyVmlElements: "_lvml",
15491
17328
  backgroundPattern: "_bp",
15492
17329
  modernCommentPart: "_mc",
15493
17330
  headerFooterFlags: "_hff",
@@ -15523,7 +17360,7 @@ function readElementFromYMap(ymap, assets) {
15523
17360
  if (isYTextLike(value)) {
15524
17361
  element.textSegments = decodeTextBody(value);
15525
17362
  }
15526
- } else if (isAssetRefKey(key)) ;
17363
+ } else if (isAssetRefKey(key) || isAssetVersionKey(key)) ;
15527
17364
  else if (REV_COMPLEX_ELEMENT[key]) {
15528
17365
  try {
15529
17366
  element[REV_COMPLEX_ELEMENT[key]] = JSON.parse(value);
@@ -15597,6 +17434,9 @@ function observeYDocSlides(ydoc, onChange) {
15597
17434
  arr.observeDeep(onChange);
15598
17435
  return () => arr.unobserveDeep(onChange);
15599
17436
  }
17437
+ function shouldAutoFollowBroadcaster(input) {
17438
+ return input.localRole === "viewer" && input.broadcasterRole === "owner";
17439
+ }
15600
17440
  function isYTextEditable(value) {
15601
17441
  return isYTextLike(value) && typeof value.delete === "function" && typeof value.format === "function";
15602
17442
  }
@@ -16473,6 +18313,186 @@ var P14_TRANSITION_KEYFRAMES_2 = `
16473
18313
  `;
16474
18314
  var P14_TRANSITION_KEYFRAMES_ALL = `${P14_TRANSITION_KEYFRAMES}
16475
18315
  ${P14_TRANSITION_KEYFRAMES_2}`;
18316
+ function threeDPair(prefix, dir, dur, outgoingOnTop) {
18317
+ return {
18318
+ outgoing: `${prefix}-out-${dir} ${dur} ${EASE} forwards`,
18319
+ incoming: `${prefix}-in-${dir} ${dur} ${EASE} forwards`,
18320
+ outgoingOnTop
18321
+ };
18322
+ }
18323
+ function getCinematicTransitionAnimations(type, durationMs, direction, orient) {
18324
+ const dur = `${durationMs}ms`;
18325
+ switch (type) {
18326
+ case "cube":
18327
+ return threeDPair("pptx-tr-cube", resolveDirection(direction, "left"), dur, false);
18328
+ case "orbit":
18329
+ return threeDPair("pptx-tr-orbit", resolveDirection(direction, "left"), dur, false);
18330
+ case "flip":
18331
+ return threeDPair("pptx-tr-flip", resolveDirection(direction, "left"), dur, true);
18332
+ case "rotate": {
18333
+ const d = resolveDirection(direction, "left");
18334
+ const spin = d === "right" || d === "down" ? "cw" : "ccw";
18335
+ return {
18336
+ outgoing: `pptx-tr-rotate-out-${spin} ${dur} ${EASE} forwards`,
18337
+ incoming: `pptx-tr-rotate-in-${spin} ${dur} ${EASE} forwards`,
18338
+ outgoingOnTop: true
18339
+ };
18340
+ }
18341
+ case "fallOver":
18342
+ return {
18343
+ outgoing: `pptx-tr-fallover-out ${dur} ${EASE} forwards`,
18344
+ incoming: `pptx-tr-fallover-in ${dur} ${EASE} forwards`,
18345
+ outgoingOnTop: false
18346
+ };
18347
+ case "drape":
18348
+ return {
18349
+ outgoing: "none",
18350
+ incoming: `pptx-tr-drape-in ${dur} ${EASE} forwards`,
18351
+ outgoingOnTop: false
18352
+ };
18353
+ case "curtains":
18354
+ return {
18355
+ outgoing: `pptx-tr-curtains-out ${dur} ${EASE} forwards`,
18356
+ incoming: "none",
18357
+ outgoingOnTop: true
18358
+ };
18359
+ case "wind": {
18360
+ const d = resolveDirection(direction, "left");
18361
+ const side = d === "right" ? "right" : "left";
18362
+ return {
18363
+ outgoing: `pptx-tr-wind-out-${side} ${dur} ${EASE} forwards`,
18364
+ incoming: `pptx-tr-fade-in ${dur} ${EASE} forwards`,
18365
+ outgoingOnTop: true
18366
+ };
18367
+ }
18368
+ case "prestige":
18369
+ return {
18370
+ outgoing: `pptx-tr-prestige-out ${dur} ${EASE} forwards`,
18371
+ incoming: `pptx-tr-prestige-in ${dur} ${EASE} forwards`,
18372
+ outgoingOnTop: true
18373
+ };
18374
+ case "fracture":
18375
+ return {
18376
+ outgoing: `pptx-tr-fracture-out ${dur} ${EASE} forwards`,
18377
+ incoming: `pptx-tr-fade-in ${dur} ${EASE} forwards`,
18378
+ outgoingOnTop: true
18379
+ };
18380
+ case "crush":
18381
+ return {
18382
+ outgoing: `pptx-tr-crush-out ${dur} ${EASE} forwards`,
18383
+ incoming: `pptx-tr-crush-in ${dur} ${EASE} forwards`,
18384
+ outgoingOnTop: true
18385
+ };
18386
+ case "peelOff":
18387
+ return {
18388
+ outgoing: `pptx-tr-peeloff-out ${dur} ${EASE} forwards`,
18389
+ incoming: "none",
18390
+ outgoingOnTop: true
18391
+ };
18392
+ case "pageCurlSingle":
18393
+ return {
18394
+ outgoing: `pptx-tr-pagecurl-out ${dur} ${EASE} forwards`,
18395
+ incoming: "none",
18396
+ outgoingOnTop: true
18397
+ };
18398
+ case "pageCurlDouble":
18399
+ return {
18400
+ outgoing: `pptx-tr-pagecurl-out ${dur} ${EASE} forwards`,
18401
+ incoming: `pptx-tr-pagecurl-double-in ${dur} ${EASE} forwards`,
18402
+ outgoingOnTop: true
18403
+ };
18404
+ case "airplane":
18405
+ return {
18406
+ outgoing: `pptx-tr-airplane-out ${dur} ${EASE} forwards`,
18407
+ incoming: `pptx-tr-fade-in ${dur} ${EASE} forwards`,
18408
+ outgoingOnTop: true
18409
+ };
18410
+ case "origami":
18411
+ return {
18412
+ outgoing: `pptx-tr-origami-out ${dur} ${EASE} forwards`,
18413
+ incoming: `pptx-tr-origami-in ${dur} ${EASE} forwards`,
18414
+ outgoingOnTop: true
18415
+ };
18416
+ default:
18417
+ return void 0;
18418
+ }
18419
+ }
18420
+ var CINEMATIC_TRANSITION_KEYFRAMES = `
18421
+ /* \u2500\u2500 Cube (rotate off one edge onto the next face) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18422
+ @keyframes pptx-tr-cube-out-left { from { transform: perspective(1400px) translateX(0) rotateY(0deg); } to { transform: perspective(1400px) translateX(-50%) rotateY(-90deg); opacity: .5; } }
18423
+ @keyframes pptx-tr-cube-in-left { from { transform: perspective(1400px) translateX(50%) rotateY(90deg); opacity: .5; } to { transform: perspective(1400px) translateX(0) rotateY(0deg); opacity: 1; } }
18424
+ @keyframes pptx-tr-cube-out-right { from { transform: perspective(1400px) translateX(0) rotateY(0deg); } to { transform: perspective(1400px) translateX(50%) rotateY(90deg); opacity: .5; } }
18425
+ @keyframes pptx-tr-cube-in-right { from { transform: perspective(1400px) translateX(-50%) rotateY(-90deg); opacity: .5; } to { transform: perspective(1400px) translateX(0) rotateY(0deg); opacity: 1; } }
18426
+ @keyframes pptx-tr-cube-out-up { from { transform: perspective(1400px) translateY(0) rotateX(0deg); } to { transform: perspective(1400px) translateY(-50%) rotateX(90deg); opacity: .5; } }
18427
+ @keyframes pptx-tr-cube-in-up { from { transform: perspective(1400px) translateY(50%) rotateX(-90deg); opacity: .5; } to { transform: perspective(1400px) translateY(0) rotateX(0deg); opacity: 1; } }
18428
+ @keyframes pptx-tr-cube-out-down { from { transform: perspective(1400px) translateY(0) rotateX(0deg); } to { transform: perspective(1400px) translateY(50%) rotateX(-90deg); opacity: .5; } }
18429
+ @keyframes pptx-tr-cube-in-down { from { transform: perspective(1400px) translateY(-50%) rotateX(90deg); opacity: .5; } to { transform: perspective(1400px) translateY(0) rotateX(0deg); opacity: 1; } }
18430
+
18431
+ /* \u2500\u2500 Orbit (swing the faces through depth) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18432
+ @keyframes pptx-tr-orbit-out-left { from { transform: perspective(1600px) translateZ(0) rotateY(0deg); opacity: 1; } to { transform: perspective(1600px) translateZ(-700px) rotateY(-105deg); opacity: 0; } }
18433
+ @keyframes pptx-tr-orbit-in-left { from { transform: perspective(1600px) translateZ(-700px) rotateY(105deg); opacity: 0; } to { transform: perspective(1600px) translateZ(0) rotateY(0deg); opacity: 1; } }
18434
+ @keyframes pptx-tr-orbit-out-right { from { transform: perspective(1600px) translateZ(0) rotateY(0deg); opacity: 1; } to { transform: perspective(1600px) translateZ(-700px) rotateY(105deg); opacity: 0; } }
18435
+ @keyframes pptx-tr-orbit-in-right { from { transform: perspective(1600px) translateZ(-700px) rotateY(-105deg); opacity: 0; } to { transform: perspective(1600px) translateZ(0) rotateY(0deg); opacity: 1; } }
18436
+ @keyframes pptx-tr-orbit-out-up { from { transform: perspective(1600px) translateZ(0) rotateX(0deg); opacity: 1; } to { transform: perspective(1600px) translateZ(-700px) rotateX(105deg); opacity: 0; } }
18437
+ @keyframes pptx-tr-orbit-in-up { from { transform: perspective(1600px) translateZ(-700px) rotateX(-105deg); opacity: 0; } to { transform: perspective(1600px) translateZ(0) rotateX(0deg); opacity: 1; } }
18438
+ @keyframes pptx-tr-orbit-out-down { from { transform: perspective(1600px) translateZ(0) rotateX(0deg); opacity: 1; } to { transform: perspective(1600px) translateZ(-700px) rotateX(-105deg); opacity: 0; } }
18439
+ @keyframes pptx-tr-orbit-in-down { from { transform: perspective(1600px) translateZ(-700px) rotateX(105deg); opacity: 0; } to { transform: perspective(1600px) translateZ(0) rotateX(0deg); opacity: 1; } }
18440
+
18441
+ /* \u2500\u2500 Flip (card flip; opacity hides the back face) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18442
+ @keyframes pptx-tr-flip-out-left { from { transform: perspective(1400px) rotateY(0deg); opacity: 1; } to { transform: perspective(1400px) rotateY(90deg); opacity: 0; } }
18443
+ @keyframes pptx-tr-flip-in-left { from { transform: perspective(1400px) rotateY(-90deg); opacity: 0; } to { transform: perspective(1400px) rotateY(0deg); opacity: 1; } }
18444
+ @keyframes pptx-tr-flip-out-right { from { transform: perspective(1400px) rotateY(0deg); opacity: 1; } to { transform: perspective(1400px) rotateY(-90deg); opacity: 0; } }
18445
+ @keyframes pptx-tr-flip-in-right { from { transform: perspective(1400px) rotateY(90deg); opacity: 0; } to { transform: perspective(1400px) rotateY(0deg); opacity: 1; } }
18446
+ @keyframes pptx-tr-flip-out-up { from { transform: perspective(1400px) rotateX(0deg); opacity: 1; } to { transform: perspective(1400px) rotateX(-90deg); opacity: 0; } }
18447
+ @keyframes pptx-tr-flip-in-up { from { transform: perspective(1400px) rotateX(90deg); opacity: 0; } to { transform: perspective(1400px) rotateX(0deg); opacity: 1; } }
18448
+ @keyframes pptx-tr-flip-out-down { from { transform: perspective(1400px) rotateX(0deg); opacity: 1; } to { transform: perspective(1400px) rotateX(90deg); opacity: 0; } }
18449
+ @keyframes pptx-tr-flip-in-down { from { transform: perspective(1400px) rotateX(-90deg); opacity: 0; } to { transform: perspective(1400px) rotateX(0deg); opacity: 1; } }
18450
+
18451
+ /* \u2500\u2500 Rotate (in-plane spin + zoom) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18452
+ @keyframes pptx-tr-rotate-out-cw { from { transform: rotate(0deg) scale(1); opacity: 1; } to { transform: rotate(90deg) scale(.4); opacity: 0; } }
18453
+ @keyframes pptx-tr-rotate-in-cw { from { transform: rotate(-90deg) scale(.4); opacity: 0; } to { transform: rotate(0deg) scale(1); opacity: 1; } }
18454
+ @keyframes pptx-tr-rotate-out-ccw { from { transform: rotate(0deg) scale(1); opacity: 1; } to { transform: rotate(-90deg) scale(.4); opacity: 0; } }
18455
+ @keyframes pptx-tr-rotate-in-ccw { from { transform: rotate(90deg) scale(.4); opacity: 0; } to { transform: rotate(0deg) scale(1); opacity: 1; } }
18456
+
18457
+ /* \u2500\u2500 Fall Over (incoming board topples down over outgoing) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18458
+ @keyframes pptx-tr-fallover-out { from { transform: translateZ(0); opacity: 1; } to { transform: perspective(1400px) rotateX(5deg) scale(.94); opacity: .25; } }
18459
+ @keyframes pptx-tr-fallover-in { 0% { transform: perspective(1400px) rotateX(-100deg); transform-origin: top center; opacity: .4; } 70% { transform: perspective(1400px) rotateX(8deg); transform-origin: top center; opacity: 1; } 100% { transform: perspective(1400px) rotateX(0deg); transform-origin: top center; opacity: 1; } }
18460
+
18461
+ /* \u2500\u2500 Drape (fabric draping down into place) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18462
+ @keyframes pptx-tr-drape-in { from { transform: perspective(1600px) rotateX(-55deg) scale(1.15); transform-origin: top center; opacity: 0; } to { transform: perspective(1600px) rotateX(0deg) scale(1); transform-origin: top center; opacity: 1; } }
18463
+
18464
+ /* \u2500\u2500 Curtains (outgoing lifts to reveal incoming) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18465
+ @keyframes pptx-tr-curtains-out { from { transform: scaleY(1); transform-origin: top center; opacity: 1; } to { transform: scaleY(0); transform-origin: top center; opacity: .3; } }
18466
+
18467
+ /* \u2500\u2500 Wind (outgoing blows away with skew + blur) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18468
+ @keyframes pptx-tr-wind-out-left { from { transform: translateX(0) skewX(0deg); opacity: 1; filter: blur(0); } to { transform: translateX(-120%) skewX(25deg); opacity: 0; filter: blur(6px); } }
18469
+ @keyframes pptx-tr-wind-out-right { from { transform: translateX(0) skewX(0deg); opacity: 1; filter: blur(0); } to { transform: translateX(120%) skewX(-25deg); opacity: 0; filter: blur(6px); } }
18470
+
18471
+ /* \u2500\u2500 Prestige (magic vanish then reappear) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18472
+ @keyframes pptx-tr-prestige-out { from { transform: scale(1) rotate(0deg); opacity: 1; filter: blur(0); } to { transform: scale(1.4) rotate(6deg); opacity: 0; filter: blur(8px); } }
18473
+ @keyframes pptx-tr-prestige-in { from { transform: scale(.6) rotate(-6deg); opacity: 0; filter: blur(8px); } to { transform: scale(1) rotate(0deg); opacity: 1; filter: blur(0); } }
18474
+
18475
+ /* \u2500\u2500 Fracture (shatter into contrast + blur) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18476
+ @keyframes pptx-tr-fracture-out { 0% { transform: scale(1); opacity: 1; filter: contrast(1) blur(0); } 55% { transform: scale(1.04) rotate(1deg); opacity: 1; filter: contrast(1.7) brightness(1.15); } 100% { transform: scale(1.15) rotate(-2deg); opacity: 0; filter: contrast(2.2) blur(4px); } }
18477
+
18478
+ /* \u2500\u2500 Crush (squash flat, then new slide expands) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18479
+ @keyframes pptx-tr-crush-out { from { transform: scaleY(1); transform-origin: bottom; opacity: 1; } to { transform: scaleY(0); transform-origin: bottom; opacity: .2; } }
18480
+ @keyframes pptx-tr-crush-in { from { transform: scaleY(0); transform-origin: bottom; opacity: .2; } to { transform: scaleY(1); transform-origin: bottom; opacity: 1; } }
18481
+
18482
+ /* \u2500\u2500 Peel Off (peel away from a corner) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18483
+ @keyframes pptx-tr-peeloff-out { from { transform: perspective(1400px) rotate3d(1, 1, 0, 0deg); transform-origin: top right; opacity: 1; } to { transform: perspective(1400px) rotate3d(1, 1, 0, 110deg); transform-origin: top right; opacity: .15; } }
18484
+
18485
+ /* \u2500\u2500 Page Curl (curl off the right edge; double curls new in) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18486
+ @keyframes pptx-tr-pagecurl-out { from { transform: perspective(1600px) rotateY(0deg); transform-origin: right center; opacity: 1; } to { transform: perspective(1600px) rotateY(-155deg); transform-origin: right center; opacity: .25; } }
18487
+ @keyframes pptx-tr-pagecurl-double-in { from { transform: perspective(1600px) rotateY(155deg); transform-origin: left center; opacity: .25; } to { transform: perspective(1600px) rotateY(0deg); transform-origin: left center; opacity: 1; } }
18488
+
18489
+ /* \u2500\u2500 Airplane (fly off like a paper plane) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18490
+ @keyframes pptx-tr-airplane-out { 0% { transform: perspective(1200px) translate3d(0, 0, 0) rotate3d(1, -1, 0, 0deg) scale(1); opacity: 1; } 40% { transform: perspective(1200px) translate3d(10%, -10%, 0) rotate3d(1, -1, 0, 25deg) scale(.85); opacity: 1; } 100% { transform: perspective(1200px) translate3d(150%, -70%, 0) rotate3d(1, -1, 1, 70deg) scale(.05); opacity: 0; } }
18491
+
18492
+ /* \u2500\u2500 Origami (fold out / unfold in) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
18493
+ @keyframes pptx-tr-origami-out { from { transform: perspective(1600px) rotateY(0deg) scaleX(1); transform-origin: left center; opacity: 1; } to { transform: perspective(1600px) rotateY(75deg) scaleX(.25); transform-origin: left center; opacity: .2; } }
18494
+ @keyframes pptx-tr-origami-in { from { transform: perspective(1600px) rotateY(-75deg) scaleX(.25); transform-origin: right center; opacity: .2; } to { transform: perspective(1600px) rotateY(0deg) scaleX(1); transform-origin: right center; opacity: 1; } }
18495
+ `;
16476
18496
  var CORE_SLIDE_TRANSITION_KEYFRAMES = `
16477
18497
  /* \u2500\u2500 Fade \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
16478
18498
  @keyframes pptx-tr-fade-in {
@@ -16737,7 +18757,8 @@ var CORE_SLIDE_TRANSITION_KEYFRAMES = `
16737
18757
  }
16738
18758
  `;
16739
18759
  var SLIDE_TRANSITION_KEYFRAMES = `${CORE_SLIDE_TRANSITION_KEYFRAMES}
16740
- ${P14_TRANSITION_KEYFRAMES_ALL}`;
18760
+ ${P14_TRANSITION_KEYFRAMES_ALL}
18761
+ ${CINEMATIC_TRANSITION_KEYFRAMES}`;
16741
18762
  function resolveLR(direction) {
16742
18763
  if (direction === "l" || direction === "r") {
16743
18764
  return direction;
@@ -16973,6 +18994,10 @@ function getSlideTransitionAnimations(type, durationMs, direction, orient, spoke
16973
18994
  if (p14) {
16974
18995
  return p14;
16975
18996
  }
18997
+ const cinematic = getCinematicTransitionAnimations(type, durationMs, direction);
18998
+ if (cinematic) {
18999
+ return cinematic;
19000
+ }
16976
19001
  switch (type) {
16977
19002
  case "none":
16978
19003
  case "cut":
@@ -17178,9 +19203,9 @@ function getSlideTransitionAnimations(type, durationMs, direction, orient, spoke
17178
19203
  // flythrough/gallery/glitter/honeycomb/pan/prism/reveal/ripple/shred/
17179
19204
  // switch/vortex/warp/wheelReverse/window) is handled faithfully above via
17180
19205
  // `getP14TransitionAnimations` and never reaches this switch.
17181
- // Fallback (unknown / not-yet-mapped type, e.g. the p15 cinematic set:
17182
- // cube/flip/rotate/orbit/fracture/peelOff/pageCurl*/airplane/origami)
17183
- // symmetrical cross-fade.
19206
+ // Fallback (genuinely unknown / not-yet-mapped type). The p14 exotic set
19207
+ // and the p15 cinematic set are handled above and never reach here.
19208
+ // Symmetrical cross-fade.
17184
19209
  default:
17185
19210
  return {
17186
19211
  outgoing: `pptx-tr-fade-out ${dur} ${EASE} forwards`,
@@ -17286,14 +19311,14 @@ function treeDepth(t) {
17286
19311
  }
17287
19312
  function flattenNodes(roots) {
17288
19313
  const out = [];
17289
- const walk = (n) => {
19314
+ const walk2 = (n) => {
17290
19315
  out.push(n);
17291
19316
  for (const c of n.children ?? []) {
17292
- walk(c);
19317
+ walk2(c);
17293
19318
  }
17294
19319
  };
17295
19320
  for (const r of roots) {
17296
- walk(r);
19321
+ walk2(r);
17297
19322
  }
17298
19323
  return out;
17299
19324
  }
@@ -17757,154 +19782,1078 @@ function computePyramidLayout(nodes, box, palette, style, elementId) {
17757
19782
  return {
17758
19783
  nodes: renderedNodes,
17759
19784
  connectors: [],
17760
- shadowFilter: styleShadow(style),
17761
- viewBox: `0 0 ${w} ${h}`,
17762
- family: "pyramid"
19785
+ shadowFilter: styleShadow(style),
19786
+ viewBox: `0 0 ${w} ${h}`,
19787
+ family: "pyramid"
19788
+ };
19789
+ }
19790
+ function computeVennLayout(nodes, box, palette, style, elementId) {
19791
+ const { width: w, height: h } = box;
19792
+ const shadow = styleShadow(style);
19793
+ if (nodes.length <= 4) {
19794
+ const cx = w / 2;
19795
+ const cy2 = h / 2;
19796
+ const r2 = Math.min(w, h) * 0.28;
19797
+ const spread = r2 * 0.55;
19798
+ const renderedNodes2 = nodes.map((node, i) => {
19799
+ const angle = i / Math.max(1, nodes.length) * Math.PI * 2 - Math.PI / 2;
19800
+ const nx = cx + spread * Math.cos(angle);
19801
+ const ny = cy2 + spread * Math.sin(angle);
19802
+ const fontSize = fitFontSize(node.text, r2 * 1.2, r2 * 2, 11);
19803
+ const result = {
19804
+ kind: "circle",
19805
+ key: `${elementId}-venn-${node.id}-${i}`,
19806
+ cx: nx,
19807
+ cy: ny,
19808
+ r: r2,
19809
+ fill: nodeFill(node, i, palette),
19810
+ stroke: "none",
19811
+ strokeWidth: 0,
19812
+ opacity: 0.35,
19813
+ text: truncate(node.text, 20),
19814
+ fontSize
19815
+ };
19816
+ return result;
19817
+ });
19818
+ return {
19819
+ nodes: renderedNodes2,
19820
+ connectors: [],
19821
+ shadowFilter: shadow,
19822
+ viewBox: `0 0 ${w} ${h}`,
19823
+ family: "venn"
19824
+ };
19825
+ }
19826
+ const r = Math.min(h * 0.38, w / (nodes.length * 0.9));
19827
+ const overlap = r * 0.5;
19828
+ const totalW = nodes.length * (r * 2 - overlap) + overlap;
19829
+ const offsetX = (w - totalW) / 2 + r;
19830
+ const cy = h / 2;
19831
+ const renderedNodes = nodes.map((node, i) => {
19832
+ const nx = offsetX + i * (r * 2 - overlap);
19833
+ const fontSize = fitFontSize(node.text, r * 1.2, r * 2, 10);
19834
+ const result = {
19835
+ kind: "circle",
19836
+ key: `${elementId}-venn-${node.id}-${i}`,
19837
+ cx: nx,
19838
+ cy,
19839
+ r,
19840
+ fill: nodeFill(node, i, palette),
19841
+ stroke: "none",
19842
+ strokeWidth: 0,
19843
+ opacity: 0.35,
19844
+ text: truncate(node.text, 20),
19845
+ fontSize
19846
+ };
19847
+ return result;
19848
+ });
19849
+ return {
19850
+ nodes: renderedNodes,
19851
+ connectors: [],
19852
+ shadowFilter: shadow,
19853
+ viewBox: `0 0 ${w} ${h}`,
19854
+ family: "venn"
19855
+ };
19856
+ }
19857
+ function computeFunnelLayout(nodes, box, palette, style, elementId) {
19858
+ const { width: w, height: h } = box;
19859
+ const pad = 8;
19860
+ const usableW = w - pad * 2;
19861
+ const stageH = nodes.length > 0 ? (h - pad * 2) / nodes.length : h - pad * 2;
19862
+ const sw = styleStroke(style);
19863
+ const stroke = strokeFor(sw);
19864
+ const renderedNodes = nodes.map((node, i) => {
19865
+ const topWidth = usableW * (1 - i / Math.max(1, nodes.length));
19866
+ const bottomWidth = usableW * (1 - (i + 1) / Math.max(1, nodes.length));
19867
+ const y = pad + i * stageH;
19868
+ const topLeft = (w - topWidth) / 2;
19869
+ const topRight = topLeft + topWidth;
19870
+ const bottomLeft = (w - bottomWidth) / 2;
19871
+ const bottomRight = bottomLeft + bottomWidth;
19872
+ const points = [
19873
+ `${topLeft},${y}`,
19874
+ `${topRight},${y}`,
19875
+ `${bottomRight},${y + stageH}`,
19876
+ `${bottomLeft},${y + stageH}`
19877
+ ].join(" ");
19878
+ const fontSize = fitFontSize(node.text, topWidth * 0.85, stageH, 11);
19879
+ const result = {
19880
+ kind: "polygon",
19881
+ key: `${elementId}-funnel-${node.id}-${i}`,
19882
+ points,
19883
+ fill: nodeFill(node, i, palette),
19884
+ stroke: nodeStroke(node, stroke),
19885
+ strokeWidth: sw,
19886
+ opacity: nodeOpacity(i, nodes.length, style),
19887
+ text: truncate(node.text, 30),
19888
+ fontSize,
19889
+ textX: w / 2,
19890
+ textY: y + stageH / 2
19891
+ };
19892
+ return result;
19893
+ });
19894
+ return {
19895
+ nodes: renderedNodes,
19896
+ connectors: [],
19897
+ shadowFilter: styleShadow(style),
19898
+ viewBox: `0 0 ${w} ${h}`,
19899
+ family: "funnel"
19900
+ };
19901
+ }
19902
+ function computeTargetLayout(nodes, box, palette, style, elementId) {
19903
+ const { width: w, height: h } = box;
19904
+ const cx = w * 0.4;
19905
+ const cy = h / 2;
19906
+ const maxR = Math.min(cx - 8, cy - 8);
19907
+ const shadow = styleShadow(style);
19908
+ const renderedNodes = nodes.map((node, i) => {
19909
+ const r = maxR * ((nodes.length - i) / Math.max(1, nodes.length));
19910
+ const result = {
19911
+ kind: "circle",
19912
+ key: `${elementId}-target-${node.id}-${i}`,
19913
+ cx,
19914
+ cy,
19915
+ r: Math.max(r, 4),
19916
+ fill: nodeFill(node, i, palette),
19917
+ stroke: "none",
19918
+ strokeWidth: 0,
19919
+ opacity: nodeOpacity(i, nodes.length, style),
19920
+ text: truncate(node.text, 30),
19921
+ fontSize: Math.max(7, Math.min(10, maxR / Math.max(1, nodes.length + 1)))
19922
+ };
19923
+ return result;
19924
+ });
19925
+ return {
19926
+ nodes: renderedNodes,
19927
+ connectors: [],
19928
+ shadowFilter: shadow,
19929
+ viewBox: `0 0 ${w} ${h}`,
19930
+ family: "target"
19931
+ };
19932
+ }
19933
+ var localName = (key) => key.split(":").pop() ?? key;
19934
+ var NODE_POINT_TYPES = /* @__PURE__ */ new Set(["node", "norm", "nonNorm", "asst", "nonAsst", "doc", "all"]);
19935
+ var CHOOSE_ALG_TYPES = /* @__PURE__ */ new Set(["lin", "cycle", "pyra", "snake"]);
19936
+ function firstNumber(values) {
19937
+ const value = values?.[0];
19938
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
19939
+ }
19940
+ function drivingIterator(node) {
19941
+ const list = node.forEach;
19942
+ if (!list || list.length === 0) {
19943
+ return void 0;
19944
+ }
19945
+ const nodeIter = list.find((each) => each.pointTypes?.some((type) => NODE_POINT_TYPES.has(type)));
19946
+ if (nodeIter) {
19947
+ return nodeIter;
19948
+ }
19949
+ const axisIter = list.find(
19950
+ (each) => each.axis?.some((axis) => axis === "ch" || axis === "des" || axis === "self")
19951
+ );
19952
+ return axisIter ?? list[0];
19953
+ }
19954
+ function selectArrangedNodes(node, flat) {
19955
+ const iter = drivingIterator(node);
19956
+ if (!iter) {
19957
+ return flat;
19958
+ }
19959
+ const start = firstNumber(iter.start);
19960
+ const st0 = start !== void 0 ? Math.max(0, start - 1) : 0;
19961
+ const stepRaw = firstNumber(iter.step);
19962
+ const step = stepRaw !== void 0 && stepRaw > 0 ? stepRaw : 1;
19963
+ const cnt = firstNumber(iter.count) ?? 0;
19964
+ const selected = [];
19965
+ for (let i = st0; i < flat.length; i += step) {
19966
+ selected.push(flat[i]);
19967
+ if (cnt > 0 && selected.length >= cnt) {
19968
+ break;
19969
+ }
19970
+ }
19971
+ if (iter.hideLastTransition?.[0] === true && selected.length > 0) {
19972
+ selected.pop();
19973
+ }
19974
+ return selected;
19975
+ }
19976
+ function toNumber(value) {
19977
+ const parsed = Number(value);
19978
+ return Number.isFinite(parsed) ? parsed : void 0;
19979
+ }
19980
+ function evaluateWhen(when, nodeCount) {
19981
+ if (when.function !== "cnt") {
19982
+ return void 0;
19983
+ }
19984
+ const threshold = toNumber(when.value);
19985
+ if (threshold === void 0) {
19986
+ return void 0;
19987
+ }
19988
+ switch (when.operator) {
19989
+ case "equ":
19990
+ return nodeCount === threshold;
19991
+ case "neq":
19992
+ return nodeCount !== threshold;
19993
+ case "gt":
19994
+ return nodeCount > threshold;
19995
+ case "lt":
19996
+ return nodeCount < threshold;
19997
+ case "gte":
19998
+ return nodeCount >= threshold;
19999
+ case "lte":
20000
+ return nodeCount <= threshold;
20001
+ default:
20002
+ return void 0;
20003
+ }
20004
+ }
20005
+ function activeBranch(choose, nodeCount) {
20006
+ for (const when of choose.when) {
20007
+ const result = evaluateWhen(when, nodeCount);
20008
+ if (result === void 0) {
20009
+ return void 0;
20010
+ }
20011
+ if (result) {
20012
+ return when.rawXml;
20013
+ }
20014
+ }
20015
+ return choose.otherwise?.rawXml ?? void 0;
20016
+ }
20017
+ function branchAlgType(raw) {
20018
+ if (!raw) {
20019
+ return void 0;
20020
+ }
20021
+ let found;
20022
+ const visit = (value) => {
20023
+ if (found !== void 0 || !value || typeof value !== "object") {
20024
+ return;
20025
+ }
20026
+ if (Array.isArray(value)) {
20027
+ value.forEach(visit);
20028
+ return;
20029
+ }
20030
+ for (const [key, entry] of Object.entries(value)) {
20031
+ if (found !== void 0) {
20032
+ return;
20033
+ }
20034
+ if (key.startsWith("@_")) {
20035
+ continue;
20036
+ }
20037
+ if (localName(key) === "alg") {
20038
+ for (const candidate of Array.isArray(entry) ? entry : [entry]) {
20039
+ const type = candidate && typeof candidate === "object" ? String(candidate["@_type"] ?? "") : "";
20040
+ if (CHOOSE_ALG_TYPES.has(type)) {
20041
+ found = type;
20042
+ return;
20043
+ }
20044
+ }
20045
+ } else {
20046
+ visit(entry);
20047
+ }
20048
+ }
20049
+ };
20050
+ visit(raw);
20051
+ return found;
20052
+ }
20053
+ function chooseAlgType(node, nodeCount) {
20054
+ if (!node.choose || node.choose.length === 0) {
20055
+ return void 0;
20056
+ }
20057
+ for (const choose of node.choose) {
20058
+ const type = branchAlgType(activeBranch(choose, nodeCount));
20059
+ if (type !== void 0) {
20060
+ return type;
20061
+ }
20062
+ }
20063
+ return void 0;
20064
+ }
20065
+ var PRIMARY_ALG = {
20066
+ lin: "linear",
20067
+ cycle: "cycle",
20068
+ pyra: "pyramid",
20069
+ snake: "snake",
20070
+ composite: "composite",
20071
+ conn: "conn",
20072
+ sp: "spacer",
20073
+ tx: "text"
20074
+ };
20075
+ var STRUCTURAL = /* @__PURE__ */ new Set(["linear", "cycle", "pyramid", "snake"]);
20076
+ var SLOT_CONSTRAINTS = /* @__PURE__ */ new Set(["l", "t", "w", "h", "ctrX", "ctrY"]);
20077
+ function mapsSlots(node) {
20078
+ return (node.children ?? []).some(
20079
+ (child2) => (child2.constraints ?? []).some((constraint) => SLOT_CONSTRAINTS.has(constraint.type))
20080
+ );
20081
+ }
20082
+ function isMeaningfulAux(node) {
20083
+ return (node.constraints?.length ?? 0) > 0 || (node.children?.length ?? 0) > 0;
20084
+ }
20085
+ function walk(node, visit) {
20086
+ visit(node);
20087
+ for (const child2 of node.children ?? []) {
20088
+ walk(child2, visit);
20089
+ }
20090
+ }
20091
+ function discoverArrangement(definition, nodeCount) {
20092
+ let hierarchy;
20093
+ let chosen;
20094
+ let compositeSlot;
20095
+ let structural;
20096
+ let aux;
20097
+ walk(definition.rootNode, (node) => {
20098
+ if (!chosen && nodeCount !== void 0 && node.choose && node.choose.length > 0) {
20099
+ const type2 = chooseAlgType(node, nodeCount);
20100
+ const kind2 = type2 ? PRIMARY_ALG[type2] : void 0;
20101
+ if (kind2 && STRUCTURAL.has(kind2)) {
20102
+ const arranger = node.children?.find((child2) => child2.algorithm?.type === type2) ?? node;
20103
+ chosen = { kind: kind2, node: arranger };
20104
+ }
20105
+ }
20106
+ const type = node.algorithm?.type;
20107
+ if (!type) {
20108
+ return;
20109
+ }
20110
+ if (type === "hierRoot" || type === "hierChild") {
20111
+ hierarchy ??= node;
20112
+ return;
20113
+ }
20114
+ const kind = PRIMARY_ALG[type];
20115
+ if (!kind) {
20116
+ return;
20117
+ }
20118
+ if (kind === "composite") {
20119
+ if (!compositeSlot && mapsSlots(node)) {
20120
+ compositeSlot = node;
20121
+ }
20122
+ return;
20123
+ }
20124
+ if (STRUCTURAL.has(kind)) {
20125
+ structural ??= { kind, node };
20126
+ return;
20127
+ }
20128
+ if (!aux && isMeaningfulAux(node)) {
20129
+ aux = { kind, node };
20130
+ }
20131
+ });
20132
+ if (hierarchy) {
20133
+ return { kind: "hierarchy", node: hierarchy };
20134
+ }
20135
+ if (chosen) {
20136
+ return chosen;
20137
+ }
20138
+ if (compositeSlot) {
20139
+ return { kind: "composite", node: compositeSlot };
20140
+ }
20141
+ return structural ?? aux;
20142
+ }
20143
+ function itemNode(arranger) {
20144
+ return arranger.children?.[0];
20145
+ }
20146
+ function findConstraint(constraints, type, forRel) {
20147
+ return constraints?.find(
20148
+ (constraint) => constraint.type === type && (forRel === void 0)
20149
+ );
20150
+ }
20151
+ function constraintRatio(constraint) {
20152
+ if (typeof constraint.factor === "number" && Number.isFinite(constraint.factor)) {
20153
+ return Math.max(0, constraint.factor);
20154
+ }
20155
+ if (typeof constraint.value === "number" && Number.isFinite(constraint.value) && constraint.value >= 0 && constraint.value < 1) {
20156
+ return constraint.value;
20157
+ }
20158
+ return void 0;
20159
+ }
20160
+ function clampByRules(value, rules, type) {
20161
+ return value;
20162
+ }
20163
+ function ratioConstraint(constraints, types, fallback, rules) {
20164
+ for (const type of types) {
20165
+ const matches = (constraints ?? []).filter((constraint) => constraint.type === type);
20166
+ const ordered2 = [
20167
+ ...matches.filter((constraint) => constraint.for === "ch"),
20168
+ ...matches.filter((constraint) => constraint.for !== "ch")
20169
+ ];
20170
+ for (const constraint of ordered2) {
20171
+ const ratio = constraintRatio(constraint);
20172
+ if (ratio !== void 0) {
20173
+ return clampByRules(ratio);
20174
+ }
20175
+ }
20176
+ }
20177
+ return fallback;
20178
+ }
20179
+ function algorithmParam(node, type) {
20180
+ return node.algorithm?.parameters?.find((param) => param.type === type)?.value;
20181
+ }
20182
+ function numericParam(node, type, fallback) {
20183
+ const raw = algorithmParam(node, type);
20184
+ if (raw === void 0) {
20185
+ return fallback;
20186
+ }
20187
+ const parsed = Number(raw);
20188
+ return Number.isFinite(parsed) ? parsed : fallback;
20189
+ }
20190
+ function resolveFlowDirection(arranger, presLayoutVars) {
20191
+ const linDir = algorithmParam(arranger, "linDir");
20192
+ const vertical = linDir === "fromT" || linDir === "fromB";
20193
+ let reverse = linDir === "fromR" || linDir === "fromB";
20194
+ if (presLayoutVars?.direction === "rev") {
20195
+ reverse = !reverse;
20196
+ }
20197
+ return { orientation: vertical ? "vertical" : "horizontal", reverse };
20198
+ }
20199
+ function styleContext(style) {
20200
+ const strokeWidth = styleStroke(style);
20201
+ return { strokeWidth, stroke: strokeFor(strokeWidth), shadow: styleShadow(style) };
20202
+ }
20203
+ function rectNode(params) {
20204
+ const { x, y, width, height, node, index, total, palette, style, ctx } = params;
20205
+ return {
20206
+ kind: "rect",
20207
+ key: params.key,
20208
+ x,
20209
+ y,
20210
+ width,
20211
+ height,
20212
+ rx: Math.min(6, height * 0.15),
20213
+ fill: nodeFill(node, index, palette),
20214
+ stroke: nodeStroke(node, ctx.stroke),
20215
+ strokeWidth: ctx.strokeWidth,
20216
+ opacity: nodeOpacity(index, total, style),
20217
+ text: truncate(node.text, 40),
20218
+ fontSize: fitFontSize(node.text, width * 0.9, height, 12),
20219
+ textX: x + width / 2,
20220
+ textY: y + height / 2
20221
+ };
20222
+ }
20223
+ function circleNode(params) {
20224
+ const { cx, cy, r, node, index, total, palette, style, ctx } = params;
20225
+ return {
20226
+ kind: "circle",
20227
+ key: params.key,
20228
+ cx,
20229
+ cy,
20230
+ r,
20231
+ fill: nodeFill(node, index, palette),
20232
+ stroke: nodeStroke(node, ctx.stroke),
20233
+ strokeWidth: ctx.strokeWidth,
20234
+ opacity: nodeOpacity(index, total, style),
20235
+ text: truncate(node.text, 20),
20236
+ fontSize: fitFontSize(node.text, r * 1.4, r * 2, 11)
20237
+ };
20238
+ }
20239
+ function polygonNode(params) {
20240
+ const { points, textX, textY, node, index, total, palette, style, ctx } = params;
20241
+ return {
20242
+ kind: "polygon",
20243
+ key: params.key,
20244
+ points,
20245
+ fill: nodeFill(node, index, palette),
20246
+ stroke: nodeStroke(node, ctx.stroke),
20247
+ strokeWidth: ctx.strokeWidth,
20248
+ opacity: nodeOpacity(index, total, style),
20249
+ text: truncate(node.text, 25),
20250
+ fontSize: fitFontSize(node.text, params.fontWidth, params.fontHeight, 12),
20251
+ textX,
20252
+ textY
20253
+ };
20254
+ }
20255
+ var INSET = 6;
20256
+ function itemAspect(plan) {
20257
+ const item = itemNode(plan.node);
20258
+ const constraints = item?.constraints;
20259
+ const height = findConstraint(constraints, "h");
20260
+ if (height?.referenceType === "w" && typeof height.factor === "number" && height.factor > 0) {
20261
+ return height.factor;
20262
+ }
20263
+ const width = findConstraint(constraints, "w");
20264
+ if (typeof height?.value === "number" && typeof width?.value === "number" && width.value > 0 && height.value > 0) {
20265
+ return height.value / width.value;
20266
+ }
20267
+ return void 0;
20268
+ }
20269
+ function ordered(nodes, flow) {
20270
+ return flow.reverse ? [...nodes].reverse() : nodes;
20271
+ }
20272
+ function arrangeLinear(plan, flow, nodes, box, palette, style, elementId) {
20273
+ const { width: w, height: h } = box;
20274
+ const ctx = styleContext(style);
20275
+ const constraints = plan.node.constraints;
20276
+ const sib = ratioConstraint(constraints, ["sibSp", "sp"], 0.25);
20277
+ const begPad = ratioConstraint(constraints, ["begPad"], 0);
20278
+ const endPad = ratioConstraint(constraints, ["endPad"], 0);
20279
+ const aspect = itemAspect(plan);
20280
+ const flow2 = ordered(nodes, flow);
20281
+ const n = flow2.length;
20282
+ const horizontal = flow.orientation === "horizontal";
20283
+ const usableMain = (horizontal ? w : h) - INSET * 2;
20284
+ const usableCross = (horizontal ? h : w) - INSET * 2;
20285
+ const denom = begPad + endPad + n + Math.max(0, n - 1) * sib;
20286
+ const mainExtent = n > 0 ? usableMain / denom : usableMain;
20287
+ const gap = sib * mainExtent;
20288
+ const crossDefault = Math.min(usableCross, mainExtent * 0.62);
20289
+ const crossExtent = aspect ? Math.min(usableCross, Math.max(12, mainExtent * aspect)) : crossDefault;
20290
+ const crossPos = INSET + (usableCross - crossExtent) / 2;
20291
+ const start = INSET + begPad * mainExtent;
20292
+ const renderedNodes = flow2.map((node, i) => {
20293
+ const mainPos = start + i * (mainExtent + gap);
20294
+ return rectNode({
20295
+ key: `${elementId}-lin-${node.id}-${i}`,
20296
+ x: horizontal ? mainPos : crossPos,
20297
+ y: horizontal ? crossPos : mainPos,
20298
+ width: horizontal ? mainExtent : crossExtent,
20299
+ height: horizontal ? crossExtent : mainExtent,
20300
+ node,
20301
+ index: i,
20302
+ total: n,
20303
+ palette,
20304
+ style,
20305
+ ctx
20306
+ });
20307
+ });
20308
+ return {
20309
+ nodes: renderedNodes,
20310
+ connectors: [],
20311
+ shadowFilter: ctx.shadow,
20312
+ viewBox: `0 0 ${w} ${h}`,
20313
+ family: "list"
20314
+ };
20315
+ }
20316
+ function arrangeSnake(plan, nodes, box, palette, style, elementId) {
20317
+ const { width: w, height: h } = box;
20318
+ const ctx = styleContext(style);
20319
+ const n = nodes.length;
20320
+ const sib = ratioConstraint(plan.node.constraints, ["sibSp", "sp"], 0.15);
20321
+ const cols = Math.max(1, Math.round(Math.sqrt(n * Math.max(0.2, w / Math.max(1, h)))));
20322
+ const rows = Math.max(1, Math.ceil(n / cols));
20323
+ const usableW = w - INSET * 2;
20324
+ const usableH = h - INSET * 2;
20325
+ const cellW = usableW / (cols + Math.max(0, cols - 1) * sib);
20326
+ const cellH = usableH / (rows + Math.max(0, rows - 1) * sib);
20327
+ const gapX = sib * cellW;
20328
+ const gapY = sib * cellH;
20329
+ const renderedNodes = nodes.map((node, i) => {
20330
+ const row = Math.floor(i / cols);
20331
+ const posInRow = i % cols;
20332
+ const col = row % 2 === 1 ? cols - 1 - posInRow : posInRow;
20333
+ return rectNode({
20334
+ key: `${elementId}-snake-${node.id}-${i}`,
20335
+ x: INSET + col * (cellW + gapX),
20336
+ y: INSET + row * (cellH + gapY),
20337
+ width: cellW,
20338
+ height: cellH,
20339
+ node,
20340
+ index: i,
20341
+ total: n,
20342
+ palette,
20343
+ style,
20344
+ ctx
20345
+ });
20346
+ });
20347
+ return {
20348
+ nodes: renderedNodes,
20349
+ connectors: [],
20350
+ shadowFilter: ctx.shadow,
20351
+ viewBox: `0 0 ${w} ${h}`,
20352
+ family: "matrix"
20353
+ };
20354
+ }
20355
+ var INSET2 = 6;
20356
+ var ARROW_WING = 4;
20357
+ var ARROW_HEAD = 7;
20358
+ function arrowPath(x0, y0, x1, y1) {
20359
+ const dx = x1 - x0;
20360
+ const dy = y1 - y0;
20361
+ const len = Math.hypot(dx, dy);
20362
+ const line2 = `M${x0},${y0} L${x1},${y1}`;
20363
+ if (len < 1e-6) {
20364
+ return line2;
20365
+ }
20366
+ const ux = dx / len;
20367
+ const uy = dy / len;
20368
+ const bx = x1 - ux * ARROW_HEAD;
20369
+ const by = y1 - uy * ARROW_HEAD;
20370
+ const px3 = -uy;
20371
+ const py = ux;
20372
+ const w1x = bx + px3 * ARROW_WING;
20373
+ const w1y = by + py * ARROW_WING;
20374
+ const w2x = bx - px3 * ARROW_WING;
20375
+ const w2y = by - py * ARROW_WING;
20376
+ return `${line2} M${w1x},${w1y} L${x1},${y1} L${w2x},${w2y}`;
20377
+ }
20378
+ function connectPoints(from, to, horizontal) {
20379
+ const fromCx = from.x + from.width / 2;
20380
+ const fromCy = from.y + from.height / 2;
20381
+ const toCx = to.x + to.width / 2;
20382
+ const toCy = to.y + to.height / 2;
20383
+ if (horizontal) {
20384
+ const leftFirst = fromCx <= toCx;
20385
+ return leftFirst ? { x0: from.x + from.width, y0: fromCy, x1: to.x, y1: toCy } : { x0: from.x, y0: fromCy, x1: to.x + to.width, y1: toCy };
20386
+ }
20387
+ const topFirst = fromCy <= toCy;
20388
+ return topFirst ? { x0: fromCx, y0: from.y + from.height, x1: toCx, y1: to.y } : { x0: fromCx, y0: from.y, x1: toCx, y1: to.y + to.height };
20389
+ }
20390
+ function arrangeConn(plan, nodes, box, palette, style, elementId) {
20391
+ if (nodes.length === 0) {
20392
+ return void 0;
20393
+ }
20394
+ const flow = resolveFlowDirection(plan.node, void 0);
20395
+ const base = arrangeLinear(plan, flow, nodes, box, palette, style, elementId);
20396
+ const rects = base.nodes.filter((node) => node.kind === "rect");
20397
+ const horizontal = flow.orientation === "horizontal";
20398
+ const connectors = [];
20399
+ for (let i = 0; i < rects.length - 1; i++) {
20400
+ const { x0, y0, x1, y1 } = connectPoints(rects[i], rects[i + 1], horizontal);
20401
+ connectors.push({ key: `${elementId}-conn-${i}`, d: arrowPath(x0, y0, x1, y1) });
20402
+ }
20403
+ return { ...base, connectors, family: "process" };
20404
+ }
20405
+ function arrangeSpacer(_plan, _nodes, box, _palette, style, _elementId) {
20406
+ const ctx = styleContext(style);
20407
+ return {
20408
+ nodes: [],
20409
+ connectors: [],
20410
+ shadowFilter: ctx.shadow,
20411
+ viewBox: `0 0 ${box.width} ${box.height}`,
20412
+ family: "list"
20413
+ };
20414
+ }
20415
+ function arrangeText(_plan, nodes, box, palette, style, elementId) {
20416
+ const node = nodes[0];
20417
+ if (!node) {
20418
+ return void 0;
20419
+ }
20420
+ const { width: w, height: h } = box;
20421
+ const ctx = styleContext(style);
20422
+ const rect = rectNode({
20423
+ key: `${elementId}-tx-${node.id}`,
20424
+ x: INSET2,
20425
+ y: INSET2,
20426
+ width: Math.max(0, w - INSET2 * 2),
20427
+ height: Math.max(0, h - INSET2 * 2),
20428
+ node,
20429
+ index: 0,
20430
+ total: 1,
20431
+ palette,
20432
+ style,
20433
+ ctx
20434
+ });
20435
+ return {
20436
+ nodes: [rect],
20437
+ connectors: [],
20438
+ shadowFilter: ctx.shadow,
20439
+ viewBox: `0 0 ${w} ${h}`,
20440
+ family: "list"
20441
+ };
20442
+ }
20443
+ function axisExtent(referenceType, box, fallback) {
20444
+ if (referenceType === "w") {
20445
+ return box.width;
20446
+ }
20447
+ if (referenceType === "h") {
20448
+ return box.height;
20449
+ }
20450
+ return fallback;
20451
+ }
20452
+ function defaultExtent(type, box) {
20453
+ return type === "h" || type === "t" || type === "ctrY" || type === "b" ? box.height : box.width;
20454
+ }
20455
+ function dimOf(constraints, type, box) {
20456
+ const constraint = findConstraint(constraints, type);
20457
+ if (!constraint) {
20458
+ return void 0;
20459
+ }
20460
+ const extent = axisExtent(constraint.referenceType, box, defaultExtent(type, box));
20461
+ if (typeof constraint.factor === "number" && Number.isFinite(constraint.factor)) {
20462
+ return { px: constraint.factor * extent };
20463
+ }
20464
+ if (typeof constraint.value === "number" && Number.isFinite(constraint.value)) {
20465
+ if (constraint.value >= 0 && constraint.value <= 1) {
20466
+ return { px: constraint.value * extent };
20467
+ }
20468
+ if (constraint.value > 1) {
20469
+ return { abs: constraint.value };
20470
+ }
20471
+ }
20472
+ return void 0;
20473
+ }
20474
+ function isPositioned(dims) {
20475
+ return dims.l !== void 0 || dims.t !== void 0 || dims.w !== void 0 || dims.h !== void 0 || dims.ctrX !== void 0 || dims.ctrY !== void 0;
20476
+ }
20477
+ function readSlots(children, box) {
20478
+ const slots = [];
20479
+ for (const child2 of children) {
20480
+ const c = child2.constraints;
20481
+ const dims = {
20482
+ l: dimOf(c, "l", box),
20483
+ t: dimOf(c, "t", box),
20484
+ w: dimOf(c, "w", box),
20485
+ h: dimOf(c, "h", box),
20486
+ ctrX: dimOf(c, "ctrX", box),
20487
+ ctrY: dimOf(c, "ctrY", box)
20488
+ };
20489
+ if (isPositioned(dims)) {
20490
+ slots.push(dims);
20491
+ }
20492
+ }
20493
+ return slots;
20494
+ }
20495
+ function absOf(dim) {
20496
+ return typeof dim?.abs === "number" ? dim.abs : 0;
20497
+ }
20498
+ function axisAbsMax(slots, pos, ctr, size) {
20499
+ let max = 0;
20500
+ for (const slot of slots) {
20501
+ const s = absOf(slot[size]);
20502
+ const edge = Math.max(absOf(slot[pos]) + s, absOf(slot[ctr]) + s / 2, s);
20503
+ if (edge > max) {
20504
+ max = edge;
20505
+ }
20506
+ }
20507
+ return max;
20508
+ }
20509
+ function px2(dim, absScale) {
20510
+ if (!dim) {
20511
+ return void 0;
20512
+ }
20513
+ if (typeof dim.px === "number") {
20514
+ return dim.px;
20515
+ }
20516
+ if (typeof dim.abs === "number") {
20517
+ return dim.abs * absScale;
20518
+ }
20519
+ return void 0;
20520
+ }
20521
+ function clamp5(v, min, max) {
20522
+ if (max <= min) {
20523
+ return min;
20524
+ }
20525
+ return Math.min(max, Math.max(min, v));
20526
+ }
20527
+ function resolveSlot(dims, box, absX, absY) {
20528
+ const rawW = px2(dims.w, absX);
20529
+ const rawH = px2(dims.h, absY);
20530
+ const width = clamp5(rawW ?? box.width, 1, box.width);
20531
+ const height = clamp5(rawH ?? box.height, 1, box.height);
20532
+ const l = px2(dims.l, absX);
20533
+ const ctrX = px2(dims.ctrX, absX);
20534
+ let x;
20535
+ if (l !== void 0) {
20536
+ x = l;
20537
+ } else if (ctrX !== void 0) {
20538
+ x = ctrX - width / 2;
20539
+ } else {
20540
+ x = (box.width - width) / 2;
20541
+ }
20542
+ const t = px2(dims.t, absY);
20543
+ const ctrY = px2(dims.ctrY, absY);
20544
+ let y;
20545
+ if (t !== void 0) {
20546
+ y = t;
20547
+ } else if (ctrY !== void 0) {
20548
+ y = ctrY - height / 2;
20549
+ } else {
20550
+ y = (box.height - height) / 2;
20551
+ }
20552
+ return {
20553
+ x: clamp5(x, 0, box.width - width),
20554
+ y: clamp5(y, 0, box.height - height),
20555
+ width,
20556
+ height
20557
+ };
20558
+ }
20559
+ function arrangeComposite(plan, nodes, box, palette, style, elementId) {
20560
+ const children = plan.node.children;
20561
+ if (!children || children.length === 0 || nodes.length === 0) {
20562
+ return void 0;
20563
+ }
20564
+ const slotDims = readSlots(children, box);
20565
+ if (slotDims.length === 0) {
20566
+ return void 0;
20567
+ }
20568
+ const absMaxX = axisAbsMax(slotDims, "l", "ctrX", "w");
20569
+ const absMaxY = axisAbsMax(slotDims, "t", "ctrY", "h");
20570
+ const absX = absMaxX > 0 ? box.width / absMaxX : 1;
20571
+ const absY = absMaxY > 0 ? box.height / absMaxY : 1;
20572
+ const slots = slotDims.map((dims) => resolveSlot(dims, box, absX, absY));
20573
+ const ctx = styleContext(style);
20574
+ const count = Math.min(slots.length, nodes.length);
20575
+ const renderedNodes = [];
20576
+ for (let i = 0; i < count; i++) {
20577
+ const slot = slots[i];
20578
+ const node = nodes[i];
20579
+ renderedNodes.push(
20580
+ rectNode({
20581
+ key: `${elementId}-comp-${node.id}-${i}`,
20582
+ x: slot.x,
20583
+ y: slot.y,
20584
+ width: slot.width,
20585
+ height: slot.height,
20586
+ node,
20587
+ index: i,
20588
+ total: count,
20589
+ palette,
20590
+ style,
20591
+ ctx
20592
+ })
20593
+ );
20594
+ }
20595
+ return {
20596
+ nodes: renderedNodes,
20597
+ connectors: [],
20598
+ shadowFilter: ctx.shadow,
20599
+ viewBox: `0 0 ${box.width} ${box.height}`,
20600
+ family: "list"
17763
20601
  };
17764
20602
  }
17765
- function computeVennLayout(nodes, box, palette, style, elementId) {
20603
+ var DEG_TO_RAD2 = Math.PI / 180;
20604
+ function pointAngle(index, count, startDeg, spanDeg) {
20605
+ const full = Math.abs(spanDeg) >= 360;
20606
+ const step = full ? spanDeg / count : count > 1 ? spanDeg / (count - 1) : 0;
20607
+ return (startDeg + index * step - 90) * DEG_TO_RAD2;
20608
+ }
20609
+ function arrangeCycle(plan, nodes, box, palette, style, elementId) {
17766
20610
  const { width: w, height: h } = box;
17767
- const shadow = styleShadow(style);
17768
- if (nodes.length <= 4) {
17769
- const cx = w / 2;
17770
- const cy2 = h / 2;
17771
- const r2 = Math.min(w, h) * 0.28;
17772
- const spread = r2 * 0.55;
17773
- const renderedNodes2 = nodes.map((node, i) => {
17774
- const angle = i / Math.max(1, nodes.length) * Math.PI * 2 - Math.PI / 2;
17775
- const nx = cx + spread * Math.cos(angle);
17776
- const ny = cy2 + spread * Math.sin(angle);
17777
- const fontSize = fitFontSize(node.text, r2 * 1.2, r2 * 2, 11);
17778
- const result = {
17779
- kind: "circle",
17780
- key: `${elementId}-venn-${node.id}-${i}`,
17781
- cx: nx,
17782
- cy: ny,
17783
- r: r2,
17784
- fill: nodeFill(node, i, palette),
17785
- stroke: "none",
17786
- strokeWidth: 0,
17787
- opacity: 0.35,
17788
- text: truncate(node.text, 20),
17789
- fontSize
17790
- };
17791
- return result;
17792
- });
20611
+ const ctx = styleContext(style);
20612
+ const n = nodes.length;
20613
+ const size = Math.min(w, h);
20614
+ const cx = w / 2;
20615
+ const cy = h / 2;
20616
+ const startDeg = numericParam(plan.node, "stAng", 0);
20617
+ const spanDeg = numericParam(plan.node, "spanAng", 360);
20618
+ const nodeR = Math.max(size * 0.06, Math.min(size * 0.12, 200 / Math.max(1, n)));
20619
+ const radius = Math.max(nodeR, size * 0.5 - nodeR - 4);
20620
+ const centre = (index) => {
20621
+ const angle = pointAngle(index, n, startDeg, spanDeg);
20622
+ return { x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) };
20623
+ };
20624
+ const full = Math.abs(spanDeg) >= 360;
20625
+ const connectorCount = full ? n : Math.max(0, n - 1);
20626
+ const connectors = Array.from({ length: connectorCount }, (_, i) => {
20627
+ const from = centre(i);
20628
+ const to = centre((i + 1) % n);
20629
+ const midX = (from.x + to.x) / 2;
20630
+ const midY = (from.y + to.y) / 2;
20631
+ const pull = 1 + radius * 0.15 / Math.max(1, Math.hypot(midX - cx, midY - cy));
20632
+ const controlX = cx + (midX - cx) * pull;
20633
+ const controlY = cy + (midY - cy) * pull;
17793
20634
  return {
17794
- nodes: renderedNodes2,
17795
- connectors: [],
17796
- shadowFilter: shadow,
17797
- viewBox: `0 0 ${w} ${h}`,
17798
- family: "venn"
20635
+ key: `${elementId}-cycle-conn-${i}`,
20636
+ d: `M${from.x},${from.y} Q${controlX},${controlY} ${to.x},${to.y}`
17799
20637
  };
17800
- }
17801
- const r = Math.min(h * 0.38, w / (nodes.length * 0.9));
17802
- const overlap = r * 0.5;
17803
- const totalW = nodes.length * (r * 2 - overlap) + overlap;
17804
- const offsetX = (w - totalW) / 2 + r;
17805
- const cy = h / 2;
20638
+ });
17806
20639
  const renderedNodes = nodes.map((node, i) => {
17807
- const nx = offsetX + i * (r * 2 - overlap);
17808
- const fontSize = fitFontSize(node.text, r * 1.2, r * 2, 10);
17809
- const result = {
17810
- kind: "circle",
17811
- key: `${elementId}-venn-${node.id}-${i}`,
17812
- cx: nx,
17813
- cy,
17814
- r,
17815
- fill: nodeFill(node, i, palette),
17816
- stroke: "none",
17817
- strokeWidth: 0,
17818
- opacity: 0.35,
17819
- text: truncate(node.text, 20),
17820
- fontSize
17821
- };
17822
- return result;
20640
+ const { x, y } = centre(i);
20641
+ return circleNode({
20642
+ key: `${elementId}-cycle-${node.id}-${i}`,
20643
+ cx: x,
20644
+ cy: y,
20645
+ r: nodeR,
20646
+ node,
20647
+ index: i,
20648
+ total: n,
20649
+ palette,
20650
+ style,
20651
+ ctx
20652
+ });
17823
20653
  });
17824
20654
  return {
17825
20655
  nodes: renderedNodes,
17826
- connectors: [],
17827
- shadowFilter: shadow,
20656
+ connectors,
20657
+ shadowFilter: ctx.shadow,
17828
20658
  viewBox: `0 0 ${w} ${h}`,
17829
- family: "venn"
20659
+ family: "cycle"
17830
20660
  };
17831
20661
  }
17832
- function computeFunnelLayout(nodes, box, palette, style, elementId) {
17833
- const { width: w, height: h } = box;
17834
- const pad = 8;
17835
- const usableW = w - pad * 2;
17836
- const stageH = nodes.length > 0 ? (h - pad * 2) / nodes.length : h - pad * 2;
17837
- const sw = styleStroke(style);
17838
- const stroke = strokeFor(sw);
17839
- const renderedNodes = nodes.map((node, i) => {
17840
- const topWidth = usableW * (1 - i / Math.max(1, nodes.length));
17841
- const bottomWidth = usableW * (1 - (i + 1) / Math.max(1, nodes.length));
17842
- const y = pad + i * stageH;
17843
- const topLeft = (w - topWidth) / 2;
17844
- const topRight = topLeft + topWidth;
17845
- const bottomLeft = (w - bottomWidth) / 2;
17846
- const bottomRight = bottomLeft + bottomWidth;
17847
- const points = [
17848
- `${topLeft},${y}`,
17849
- `${topRight},${y}`,
17850
- `${bottomRight},${y + stageH}`,
17851
- `${bottomLeft},${y + stageH}`
17852
- ].join(" ");
17853
- const fontSize = fitFontSize(node.text, topWidth * 0.85, stageH, 11);
17854
- const result = {
17855
- kind: "polygon",
17856
- key: `${elementId}-funnel-${node.id}-${i}`,
17857
- points,
17858
- fill: nodeFill(node, i, palette),
17859
- stroke: nodeStroke(node, stroke),
17860
- strokeWidth: sw,
17861
- opacity: nodeOpacity(i, nodes.length, style),
17862
- text: truncate(node.text, 30),
17863
- fontSize,
17864
- textX: w / 2,
17865
- textY: y + stageH / 2
17866
- };
17867
- return result;
20662
+ var INSET3 = 6;
20663
+ function isHanging(presLayoutVars) {
20664
+ const branch = presLayoutVars?.hierarchyBranch;
20665
+ return branch === "l" || branch === "r" || branch === "hang";
20666
+ }
20667
+ function connector(hc, from, fx, fy, cx, cy) {
20668
+ const midY = fy + (cy - fy) / 2;
20669
+ hc.connectors.push({
20670
+ key: `${hc.elementId}-hier-conn-${from.node.id}-${cx}-${cy}`,
20671
+ d: `M${fx},${fy} L${fx},${midY} L${cx},${midY} L${cx},${cy}`
17868
20672
  });
20673
+ }
20674
+ function pushNode(hc, node, x, y) {
20675
+ const index = hc.counter.value++;
20676
+ hc.nodes.push(
20677
+ rectNode({
20678
+ key: `${hc.elementId}-hier-${node.id}-${index}`,
20679
+ x,
20680
+ y,
20681
+ width: hc.boxW,
20682
+ height: hc.boxH,
20683
+ node,
20684
+ index,
20685
+ total: hc.total,
20686
+ palette: hc.palette,
20687
+ style: hc.style,
20688
+ ctx: hc.ctx
20689
+ })
20690
+ );
20691
+ return index;
20692
+ }
20693
+ function placeStandard(hc, t, xOffset, level, cellW, cellH) {
20694
+ const spanW = treeWidth(t);
20695
+ const cx = (xOffset + spanW / 2) * cellW;
20696
+ const cy = level * cellH + cellH / 2;
20697
+ pushNode(hc, t.node, cx - hc.boxW / 2, cy - hc.boxH / 2);
20698
+ let childOffset = xOffset;
20699
+ for (const child2 of t.children) {
20700
+ const childW = treeWidth(child2);
20701
+ const childCx = (childOffset + childW / 2) * cellW;
20702
+ const childCy = (level + 1) * cellH + cellH / 2;
20703
+ connector(hc, t, cx, cy + hc.boxH / 2, childCx, childCy - hc.boxH / 2);
20704
+ placeStandard(hc, child2, childOffset, level + 1, cellW, cellH);
20705
+ childOffset += childW;
20706
+ }
20707
+ }
20708
+ function placeHanging(hc, t, x, indent, vGap, cursor) {
20709
+ const y = cursor.y;
20710
+ cursor.y += hc.boxH + vGap;
20711
+ pushNode(hc, t.node, x, y);
20712
+ for (const child2 of t.children) {
20713
+ const childY = cursor.y;
20714
+ connector(hc, t, x + hc.boxH / 2, y + hc.boxH, x + indent, childY + hc.boxH / 2);
20715
+ placeHanging(hc, child2, x + indent, indent, vGap, cursor);
20716
+ }
20717
+ }
20718
+ function baseContext(nodeCount, elementId, palette, style, boxW, boxH) {
17869
20719
  return {
17870
- nodes: renderedNodes,
20720
+ elementId,
20721
+ palette,
20722
+ style,
20723
+ ctx: styleContext(style),
20724
+ total: nodeCount,
20725
+ boxW,
20726
+ boxH,
20727
+ nodes: [],
17871
20728
  connectors: [],
17872
- shadowFilter: styleShadow(style),
20729
+ counter: { value: 0 }
20730
+ };
20731
+ }
20732
+ function arrangeHierarchy(nodes, box, palette, style, elementId, presLayoutVars) {
20733
+ const { width: w, height: h } = box;
20734
+ const roots = buildTree(nodes);
20735
+ if (isHanging(presLayoutVars)) {
20736
+ const boxW2 = Math.min(w * 0.42, 160);
20737
+ const boxH2 = Math.min(h * 0.16, 30);
20738
+ const indent = boxW2 * 0.35;
20739
+ const vGap = boxH2 * 0.55;
20740
+ const hc2 = baseContext(nodes.length, elementId, palette, style, boxW2, boxH2);
20741
+ const cursor = { y: INSET3 };
20742
+ for (const root of roots) {
20743
+ placeHanging(hc2, root, INSET3, indent, vGap, cursor);
20744
+ }
20745
+ return {
20746
+ nodes: hc2.nodes,
20747
+ connectors: hc2.connectors,
20748
+ shadowFilter: hc2.ctx.shadow,
20749
+ viewBox: `0 0 ${w} ${h}`,
20750
+ family: "hierarchy"
20751
+ };
20752
+ }
20753
+ const totalLeaves = roots.reduce((sum, r) => sum + treeWidth(r), 0);
20754
+ const depth = roots.length > 0 ? Math.max(...roots.map(treeDepth)) : 1;
20755
+ const cellW = w / Math.max(1, totalLeaves);
20756
+ const cellH = h / Math.max(1, depth);
20757
+ const boxW = Math.min(cellW * 0.8, 150);
20758
+ const boxH = Math.min(cellH * 0.4, 40);
20759
+ const hc = baseContext(nodes.length, elementId, palette, style, boxW, boxH);
20760
+ let offset = 0;
20761
+ for (const root of roots) {
20762
+ placeStandard(hc, root, offset, 0, cellW, cellH);
20763
+ offset += treeWidth(root);
20764
+ }
20765
+ return {
20766
+ nodes: hc.nodes,
20767
+ connectors: hc.connectors,
20768
+ shadowFilter: hc.ctx.shadow,
17873
20769
  viewBox: `0 0 ${w} ${h}`,
17874
- family: "funnel"
20770
+ family: "hierarchy"
17875
20771
  };
17876
20772
  }
17877
- function computeTargetLayout(nodes, box, palette, style, elementId) {
20773
+ var INSET4 = 8;
20774
+ function arrangePyramid(plan, nodes, box, palette, style, elementId) {
17878
20775
  const { width: w, height: h } = box;
17879
- const cx = w * 0.4;
17880
- const cy = h / 2;
17881
- const maxR = Math.min(cx - 8, cy - 8);
17882
- const shadow = styleShadow(style);
20776
+ const ctx = styleContext(style);
20777
+ const n = nodes.length;
20778
+ const cx = w / 2;
20779
+ const maxW = w - INSET4 * 2;
20780
+ const gapRatio = ratioConstraint(plan.node.constraints, ["sibSp", "sp"], 0.06);
20781
+ const usableH = h - INSET4 * 2;
20782
+ const bandH = n > 0 ? usableH / (n + Math.max(0, n - 1) * gapRatio) : usableH;
20783
+ const gap = gapRatio * bandH;
17883
20784
  const renderedNodes = nodes.map((node, i) => {
17884
- const r = maxR * ((nodes.length - i) / Math.max(1, nodes.length));
17885
- const result = {
17886
- kind: "circle",
17887
- key: `${elementId}-target-${node.id}-${i}`,
17888
- cx,
17889
- cy,
17890
- r: Math.max(r, 4),
17891
- fill: nodeFill(node, i, palette),
17892
- stroke: "none",
17893
- strokeWidth: 0,
17894
- opacity: nodeOpacity(i, nodes.length, style),
17895
- text: truncate(node.text, 30),
17896
- fontSize: Math.max(7, Math.min(10, maxR / Math.max(1, nodes.length + 1)))
17897
- };
17898
- return result;
20785
+ const yTop = INSET4 + i * (bandH + gap);
20786
+ const yBot = yTop + bandH;
20787
+ const fTop = i / n;
20788
+ const fBot = (i + 1) / n;
20789
+ const halfTop = maxW * fTop / 2;
20790
+ const halfBot = maxW * fBot / 2;
20791
+ const points = [
20792
+ `${cx - halfTop},${yTop}`,
20793
+ `${cx + halfTop},${yTop}`,
20794
+ `${cx + halfBot},${yBot}`,
20795
+ `${cx - halfBot},${yBot}`
20796
+ ].join(" ");
20797
+ return polygonNode({
20798
+ key: `${elementId}-pyra-${node.id}-${i}`,
20799
+ points,
20800
+ textX: cx,
20801
+ textY: (yTop + yBot) / 2,
20802
+ fontWidth: Math.max(20, halfBot * 1.4),
20803
+ fontHeight: bandH,
20804
+ node,
20805
+ index: i,
20806
+ total: n,
20807
+ palette,
20808
+ style,
20809
+ ctx
20810
+ });
17899
20811
  });
17900
20812
  return {
17901
20813
  nodes: renderedNodes,
17902
20814
  connectors: [],
17903
- shadowFilter: shadow,
20815
+ shadowFilter: ctx.shadow,
17904
20816
  viewBox: `0 0 ${w} ${h}`,
17905
- family: "target"
20817
+ family: "pyramid"
17906
20818
  };
17907
20819
  }
20820
+ function interpretSmartArtLayout(input) {
20821
+ const { layoutDefinition, nodes, flat, box, palette, style, elementId, presLayoutVars } = input;
20822
+ if (!layoutDefinition || flat.length === 0) {
20823
+ return void 0;
20824
+ }
20825
+ const plan = discoverArrangement(layoutDefinition, flat.length);
20826
+ if (!plan) {
20827
+ return void 0;
20828
+ }
20829
+ if (plan.kind === "hierarchy") {
20830
+ return arrangeHierarchy(nodes, box, palette, style, elementId, presLayoutVars);
20831
+ }
20832
+ const arranged = selectArrangedNodes(plan.node, flat);
20833
+ if (arranged.length === 0) {
20834
+ return void 0;
20835
+ }
20836
+ switch (plan.kind) {
20837
+ case "linear": {
20838
+ const flow = resolveFlowDirection(plan.node, presLayoutVars);
20839
+ return arrangeLinear(plan, flow, arranged, box, palette, style, elementId);
20840
+ }
20841
+ case "snake":
20842
+ return arrangeSnake(plan, arranged, box, palette, style, elementId);
20843
+ case "cycle":
20844
+ return arrangeCycle(plan, arranged, box, palette, style, elementId);
20845
+ case "pyramid":
20846
+ return arrangePyramid(plan, arranged, box, palette, style, elementId);
20847
+ case "composite":
20848
+ return arrangeComposite(plan, arranged, box, palette, style, elementId);
20849
+ case "conn":
20850
+ return arrangeConn(plan, arranged, box, palette, style, elementId);
20851
+ case "spacer":
20852
+ return arrangeSpacer(plan, arranged, box, palette, style);
20853
+ case "text":
20854
+ return arrangeText(plan, arranged, box, palette, style, elementId);
20855
+ }
20856
+ }
17908
20857
  function interpolateSmartArtPalette(palette, count, method, hueDirection) {
17909
20858
  if (count <= 0 || palette.length === 0) {
17910
20859
  return [];
@@ -17920,10 +20869,23 @@ function interpolateSmartArtPalette(palette, count, method, hueDirection) {
17920
20869
  return interpolateColor(palette[lower], palette[lower + 1], frac, "hsl", hueDirection);
17921
20870
  });
17922
20871
  }
17923
- function computeSmartArtLayout(nodes, box, palette, style, elementId, resolvedLayoutType, layout, interpolation) {
20872
+ function computeSmartArtLayout(nodes, box, palette, style, elementId, resolvedLayoutType, layout, interpolation, layoutDefinition, presLayoutVars) {
17924
20873
  const flat = flattenNodes(nodes);
17925
20874
  const family = resolveLayoutFamily(nodes, resolvedLayoutType, layout);
17926
20875
  const pal = interpolation?.method === "span" ? interpolateSmartArtPalette(palette, flat.length, "span", interpolation.hueDirection) : palette;
20876
+ const interpreted = interpretSmartArtLayout({
20877
+ layoutDefinition,
20878
+ nodes,
20879
+ flat,
20880
+ box,
20881
+ palette: pal,
20882
+ style,
20883
+ elementId,
20884
+ presLayoutVars
20885
+ });
20886
+ if (interpreted) {
20887
+ return interpreted;
20888
+ }
17927
20889
  switch (family) {
17928
20890
  case "list":
17929
20891
  return computeListLayout(flat, box, pal, style, elementId);
@@ -18293,14 +21255,14 @@ function smartArtLayoutLabel(type) {
18293
21255
  }
18294
21256
  function flattenSmartArtNodes(nodes) {
18295
21257
  const out = [];
18296
- const walk = (n) => {
21258
+ const walk2 = (n) => {
18297
21259
  out.push(n);
18298
21260
  for (const child2 of n.children ?? []) {
18299
- walk(child2);
21261
+ walk2(child2);
18300
21262
  }
18301
21263
  };
18302
21264
  for (const n of nodes) {
18303
- walk(n);
21265
+ walk2(n);
18304
21266
  }
18305
21267
  return out;
18306
21268
  }
@@ -18351,14 +21313,14 @@ var THREE_UNAVAILABLE = {
18351
21313
  var FOV = 50;
18352
21314
  async function loadThree() {
18353
21315
  try {
18354
- return await import('./three.module-7CXEVRKB.mjs');
21316
+ return await import('./three.module-AC7ESV4W.mjs');
18355
21317
  } catch {
18356
21318
  return null;
18357
21319
  }
18358
21320
  }
18359
21321
  async function loadGltfLoaderCtor() {
18360
21322
  try {
18361
- const mod = await import('./GLTFLoader-NMAS6VRH.mjs');
21323
+ const mod = await import('./GLTFLoader-374ZNTXW.mjs');
18362
21324
  return mod.GLTFLoader;
18363
21325
  } catch {
18364
21326
  return null;
@@ -18366,7 +21328,7 @@ async function loadGltfLoaderCtor() {
18366
21328
  }
18367
21329
  async function loadOrbitControlsCtor() {
18368
21330
  try {
18369
- const mod = await import('./OrbitControls-F5XPYD2Z.mjs');
21331
+ const mod = await import('./OrbitControls-ZTGHPI5G.mjs');
18370
21332
  return mod.OrbitControls;
18371
21333
  } catch {
18372
21334
  return null;
@@ -18590,14 +21552,14 @@ var SURFACE_THREE_UNAVAILABLE = {
18590
21552
  var FOV2 = 45;
18591
21553
  async function loadThree2() {
18592
21554
  try {
18593
- return await import('./three.module-7CXEVRKB.mjs');
21555
+ return await import('./three.module-AC7ESV4W.mjs');
18594
21556
  } catch {
18595
21557
  return null;
18596
21558
  }
18597
21559
  }
18598
21560
  async function loadOrbitControlsCtor2() {
18599
21561
  try {
18600
- const mod = await import('./OrbitControls-F5XPYD2Z.mjs');
21562
+ const mod = await import('./OrbitControls-ZTGHPI5G.mjs');
18601
21563
  return mod.OrbitControls;
18602
21564
  } catch {
18603
21565
  return null;
@@ -19205,6 +22167,26 @@ function presentationInkPath(points) {
19205
22167
  ""
19206
22168
  );
19207
22169
  }
22170
+ var HANDOUT_SLIDES_PER_PAGE = [1, 2, 3, 4, 6, 9];
22171
+ function printPropertiesSlidesPerPage(printProperties) {
22172
+ const match = printProperties?.printWhat?.match(/^handouts([123469])$/u);
22173
+ return match ? Number.parseInt(match[1], 10) : 1;
22174
+ }
22175
+ function printPropertiesFrameSlides(printProperties) {
22176
+ return Boolean(printProperties?.frameSlides);
22177
+ }
22178
+ function nearestHandoutCount(value) {
22179
+ return HANDOUT_SLIDES_PER_PAGE.reduce(
22180
+ (best, candidate) => Math.abs(candidate - value) < Math.abs(best - value) ? candidate : best
22181
+ );
22182
+ }
22183
+ function withFrameSlides(printProperties, value) {
22184
+ return { ...printProperties ?? {}, frameSlides: value };
22185
+ }
22186
+ function withSlidesPerPage(printProperties, value) {
22187
+ const count = nearestHandoutCount(value);
22188
+ return { ...printProperties ?? {}, printWhat: `handouts${count}` };
22189
+ }
19208
22190
  var PRESENTATION_CHANNEL_NAME = "pptx-viewer-presenter";
19209
22191
  var PRESENTATION_HASH = "#pptx-audience";
19210
22192
  var PRESENTATION_NONCE_KEY = "nonce";
@@ -19397,6 +22379,108 @@ async function clearPresentationDeck(sessionId) {
19397
22379
  } catch {
19398
22380
  }
19399
22381
  }
22382
+ var DB_NAME2 = "pptx-viewer-audience";
22383
+ var DB_VERSION2 = 1;
22384
+ var STORE_NAME2 = "content";
22385
+ var CONTENT_KEY = "pptx-bytes";
22386
+ var MAX_CONTENT_AGE_MS = 5 * 60 * 1e3;
22387
+ function openDb() {
22388
+ return new Promise((resolve, reject) => {
22389
+ const request = indexedDB.open(DB_NAME2, DB_VERSION2);
22390
+ request.onupgradeneeded = () => {
22391
+ const db = request.result;
22392
+ if (!db.objectStoreNames.contains(STORE_NAME2)) {
22393
+ db.createObjectStore(STORE_NAME2);
22394
+ }
22395
+ };
22396
+ request.onsuccess = () => resolve(request.result);
22397
+ request.onerror = () => reject(request.error);
22398
+ });
22399
+ }
22400
+ async function storeAudienceContent(content, sessionId) {
22401
+ if (sessionId) {
22402
+ return storePresentationDeck(sessionId, content);
22403
+ }
22404
+ const db = await openDb();
22405
+ return new Promise((resolve, reject) => {
22406
+ const tx = db.transaction(STORE_NAME2, "readwrite");
22407
+ const store = tx.objectStore(STORE_NAME2);
22408
+ const bytes = content instanceof Uint8Array ? content : new Uint8Array(content);
22409
+ const record = { bytes, createdAt: Date.now() };
22410
+ store.put(record, CONTENT_KEY);
22411
+ tx.oncomplete = () => {
22412
+ db.close();
22413
+ resolve();
22414
+ };
22415
+ tx.onerror = () => {
22416
+ db.close();
22417
+ reject(tx.error);
22418
+ };
22419
+ });
22420
+ }
22421
+ async function loadAudienceContent(sessionId) {
22422
+ if (sessionId) {
22423
+ return loadPresentationDeck(sessionId);
22424
+ }
22425
+ try {
22426
+ const db = await openDb();
22427
+ return new Promise((resolve, reject) => {
22428
+ const tx = db.transaction(STORE_NAME2, "readonly");
22429
+ const store = tx.objectStore(STORE_NAME2);
22430
+ const request = store.get(CONTENT_KEY);
22431
+ request.onsuccess = () => {
22432
+ db.close();
22433
+ const result = request.result;
22434
+ if (result && typeof result === "object" && "bytes" in result && "createdAt" in result) {
22435
+ const record = result;
22436
+ const age = Date.now() - record.createdAt;
22437
+ if (age > MAX_CONTENT_AGE_MS) {
22438
+ resolve(null);
22439
+ return;
22440
+ }
22441
+ const raw = record.bytes;
22442
+ if (raw instanceof Uint8Array) {
22443
+ resolve(raw);
22444
+ } else if (raw instanceof ArrayBuffer) {
22445
+ resolve(new Uint8Array(raw));
22446
+ } else {
22447
+ resolve(null);
22448
+ }
22449
+ return;
22450
+ }
22451
+ resolve(null);
22452
+ };
22453
+ request.onerror = () => {
22454
+ db.close();
22455
+ reject(request.error);
22456
+ };
22457
+ });
22458
+ } catch {
22459
+ return null;
22460
+ }
22461
+ }
22462
+ async function clearAudienceContent(sessionId) {
22463
+ if (sessionId) {
22464
+ return clearPresentationDeck(sessionId);
22465
+ }
22466
+ try {
22467
+ const db = await openDb();
22468
+ return new Promise((resolve) => {
22469
+ const tx = db.transaction(STORE_NAME2, "readwrite");
22470
+ const store = tx.objectStore(STORE_NAME2);
22471
+ store.delete(CONTENT_KEY);
22472
+ tx.oncomplete = () => {
22473
+ db.close();
22474
+ resolve();
22475
+ };
22476
+ tx.onerror = () => {
22477
+ db.close();
22478
+ resolve();
22479
+ };
22480
+ });
22481
+ } catch {
22482
+ }
22483
+ }
19400
22484
  function formatSlideCounter(currentSlide, totalSlides) {
19401
22485
  return `${currentSlide + 1} / ${totalSlides}`;
19402
22486
  }
@@ -19810,12 +22894,12 @@ function replacePixels(data, fromColor, toColor, threshold, toTransparent) {
19810
22894
  }
19811
22895
  }
19812
22896
  var DEFAULT_COLOR_CHANGE_TOLERANCE = 12;
19813
- function applyColorChange(imageDataUrl, fromHex, toHex, tolerancePct = DEFAULT_COLOR_CHANGE_TOLERANCE, toTransparent = false) {
22897
+ function applyColorChange(imageDataUrl, fromHex, toHex2, tolerancePct = DEFAULT_COLOR_CHANGE_TOLERANCE, toTransparent = false) {
19814
22898
  return new Promise((resolve, reject) => {
19815
22899
  const fromColor = parseHexToRgb(fromHex);
19816
- const toColor = parseHexToRgb(toHex);
22900
+ const toColor = parseHexToRgb(toHex2);
19817
22901
  if (!fromColor || !toColor) {
19818
- reject(new Error(`Invalid hex colour: from="${fromHex}" to="${toHex}"`));
22902
+ reject(new Error(`Invalid hex colour: from="${fromHex}" to="${toHex2}"`));
19819
22903
  return;
19820
22904
  }
19821
22905
  const img = new Image();
@@ -19853,9 +22937,9 @@ function applyColorChange(imageDataUrl, fromHex, toHex, tolerancePct = DEFAULT_C
19853
22937
  }
19854
22938
  var colorChangeCache = /* @__PURE__ */ new Map();
19855
22939
  var CACHE_MAX = 64;
19856
- function buildCacheKey(src, fromHex, toHex, tolerancePct, toTransparent) {
22940
+ function buildCacheKey(src, fromHex, toHex2, tolerancePct, toTransparent) {
19857
22941
  const srcKey = src.length > 64 ? src.slice(0, 64) : src;
19858
- return `${srcKey}|${fromHex}|${toHex}|${tolerancePct}|${toTransparent}`;
22942
+ return `${srcKey}|${fromHex}|${toHex2}|${tolerancePct}|${toTransparent}`;
19859
22943
  }
19860
22944
  function getCachedResult(key) {
19861
22945
  return colorChangeCache.get(key);
@@ -20449,12 +23533,12 @@ function createDefaultChartElement(chartType = DEFAULT_INSERT_CHART_TYPE, positi
20449
23533
  );
20450
23534
  }
20451
23535
  function polygonBounds(points) {
20452
- const pairs = points.trim().split(/\s+/u);
23536
+ const pairs2 = points.trim().split(/\s+/u);
20453
23537
  let minX = Infinity;
20454
23538
  let minY = Infinity;
20455
23539
  let maxX = -Infinity;
20456
23540
  let maxY = -Infinity;
20457
- for (const pair of pairs) {
23541
+ for (const pair of pairs2) {
20458
23542
  const comma = pair.indexOf(",");
20459
23543
  if (comma < 0) {
20460
23544
  continue;
@@ -20666,6 +23750,15 @@ function cloneElementForPaste(element, options = {}) {
20666
23750
  clone.y += options.offsetY ?? PASTE_OFFSET_PX;
20667
23751
  return clone;
20668
23752
  }
23753
+ var DEFAULT_PREVIEW_ELEMENT_CAP = 500;
23754
+ function buildPreviewElements(slide, templateElements = [], options) {
23755
+ const cap = options?.cap ?? DEFAULT_PREVIEW_ELEMENT_CAP;
23756
+ const merged = [...templateElements, ...slide.elements];
23757
+ if (cap > 0 && merged.length > cap) {
23758
+ return merged.slice(0, cap);
23759
+ }
23760
+ return merged;
23761
+ }
20669
23762
  var SHAPE_PRESET_DEFS = [
20670
23763
  {
20671
23764
  type: "rect",
@@ -24108,4 +27201,4 @@ function segmentFrameCount(durationMs, fps) {
24108
27201
  return Math.max(1, Math.ceil(durationMs / (1e3 / fps)));
24109
27202
  }
24110
27203
 
24111
- export { ACTION_BUTTON_PRESETS, ARTISTIC_EFFECTS, AVATAR_COLOR_SWATCHES, BACKSTAGE_NAV, BACKSTAGE_TEMPLATES, BROADCAST_THROTTLE_MS, CATEGORIES, CONNECTION_TIMEOUT_MS, DEFAULT_BROADCAST_SERVER_URL, DEFAULT_COLOR_CHANGE_TOLERANCE, DEFAULT_INSERT_CHART_TYPE, DEFAULT_QUICK_ACCESS_COMMAND_IDS, DEFAULT_ROW_HEIGHT, DEFAULT_VIEWER_OPTIONS, DEFAULT_VIEWER_PROFILE, DEFAULT_VIRTUAL_OVERSCAN, DIRECTIONAL_PRESETS, DUOTONE_PRESETS, EQUATION_TEMPLATES, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, FILL_MODE_OPTIONS, GRADIENT_TYPE_OPTIONS, HANDOUT_OPTIONS, INK_REPLAY_KEYFRAMES, INSERT_CHART_TYPES, LBL, LOCAL_SYNC_ORIGIN, MOBILE_BREAKPOINT, NOTES_FONT_SIZE_DEFAULT, NOTES_FONT_SIZE_MAX, NOTES_FONT_SIZE_MIN, NOTES_FONT_SIZE_STEP, NUM, PATTERN_OPTIONS, PRESENTATION_CHANNEL_NAME, PRESENTATION_HASH, PRESENTATION_MESSAGE_ORIGIN, PRESENTATION_NONCE_KEY, PRESETS, QUICK_ACCESS_COMMAND_CATALOG, RULER_FONT_SIZE, RULER_THICKNESS, SECTION_HEADING, SEL, SHAPE_PRESET_DEFS, SHORTCUT_REFERENCE_ITEMS, SLIDE_TRANSITION_KEYFRAMES, SLIDE_VIRTUALIZATION_THRESHOLD, TABLET_BREAKPOINT, TABLE_STYLE_PRESETS, TAB_ROW_ACTION_CLASSES, TEXT_BUILD_ID_SEP, THEME_CATALOG, THEME_COLOR_LABELS, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, TOOLBAR_TABS, TimelineEngine, VIEWER_OPTIONS_TABS, VIEWER_PREFS_STORAGE_KEY, WEBM_MIME_CANDIDATES, activateModalFocus, addQuickAccessCommand, addSection, alignElements, appendPresentationInkPoint, apply3dEffects, applyAcceptAllSlides, applyAcceptSlide, applyCaseTransformToSegments, applyColorChange, applyDuotone, applyFormatToElement, applyPreferenceToOptions, applyRehearsalTimings, applyReroutedConnectors, applyResize, applyStyleToSelectedSegments, availableQuickAccessCommands, bringForward, bringToFront, build3DExtrusionData, buildBroadcastViewerUrl, buildCacheKey, buildChartViewModel, buildCollaborationShareUrl, buildCreateCollaborationConfig, buildCssGradientFromShapeStyle, buildDuotoneCacheKey, buildElementClipboardPayload, buildGlowBoxShadow, buildHandoutsHtml, buildInitialGuides, buildInnerShadowCssFromShapeStyle, buildJoinCollaborationConfig, buildMultiLayerShadowCss, buildNotesHtml, buildNotesPdfBytes, buildOutlineHtml, buildPatternFillCss, buildPresentationAudienceUrl, buildPreviewAnimation, buildPrintDocument, buildPrintHtmlDocument, buildReflectionCss, buildShadowCssFromShapeStyle, buildSlidesHtml, buildSlidesPdfBytes, buildSmartArt3DModel, buildSmartArtA11y, buildSmartArtPresetData, buildSummaryZoomView, buildTextBody3DSceneStyle, buildTextFillCss, buildTextReflectionCss, buildTextRunFilterChain, buildTextShadowCss, buildThemeColorGrid, buildUserFontFaceStyles, canvasToJpegData, chartPartToAttrs, clampCropValue, clampNotesFontSize, clampPercent, clampUnitInterval, clearAllLocalViewerData, clearPresentationDeck, clearStoredViewerPrefs, cloneElementForPaste, cloneHistorySnapshot, cloneSlide, cloneTemplateElementsBySlideId, collectImagePaths, collectMediaElements, collectUsedFonts, colorWithOpacity, comparePresentation, computeAllNotesPages, computeAutoFitTextStyle, computeColumnBoundaries, computeEntranceAnimationDelay, computeHandoutLayout, computeInlineEditorRect, computeKeyboardInset, computeLayout, computeLayoutOptions, computeMarqueeHitIds, computeMergeCellDown, computeMergeCellRight, computeResizedColumnWidths, computeResizedRowHeight, computeScrollDelta, computeSelectionRect, computeSmartArtLayout, computeSnapToShape, computeSplitCell, computeValueRange, computeValueRangeForChart, computeVirtualRange, convertLatexToOmml, convertOmmlToLatex, convertOmmlToMathMl, copyFormatFromElement, countTextSegments, createBackstagePresentation, createBlankSlide, createDefaultChartElement, createInitialPresentationSnapshot, createPresentationSessionId, createPresenterTimer, createSyncGate, createTouchGestureRecognizer, createViewerOptionsStore, defaultCssVars, defaultRadius, defaultThemeColors, deleteAutosaveSnapshot, deleteSection, deleteTableColumn, deleteTableRow, derivePresenceList, detectOrientation, detectTouchDevice, distributeElements, downloadBlob, downloadDataUrl, dragAnchorViewY, dragValueForPart, encodeGif, erasePresentationInkAt, expandTextBuildAnimations, extractPathPoints, filterCommands, findChartPartTarget, findSmartArtNodeText, formatAxisValue, formatAxisValueWithUnits, formatBackstageDate, formatBackstageSize, formatBytes, formatCommentTimestamp, formatElapsed, formatMobileElapsed, formatRelativeTime, formatSlideCounter, formatTime, formatVersionTimestamp, fpsToFrameIntervalMs, generateBroadcastRoomId, generateElementId, generateLogTicks, generateNoteLineCount, generatePackageReadme, generatePressureCircles, generateTicks, getAnimationInitialStyle, getAriaLabel, getAriaRole, getAriaRoleDescription, getCachedResult, getChartStylePalette, getCommentMarkerPosition, getCompoundLineBorderWidth, getCompoundLineBoxShadow, getCompoundLineOffsets, getCompoundLineWidths, getConnectionSites, getContentPartReplayStyles, getCssBorderDashStyle, getDisplayUnitLabel, getDuotoneCachedResult, getEffectDagFilter, getElementLabel, getElementTransform, getElementTransformWithoutRotation, getImageColorWashStyle, getImageEffectsFilter, getImageEffectsOpacity, getImageSvgFilters, getInkReplayStyles, getInlineEditorSelection, getKinsokuLineBreakStyles, getLocalStorageUsageSummary, getNotesPrintableArea, getOleBadgeLabel, getOleTypeColor, getOleTypeLabel, getPatternSvg, getPendingSelectionRestore, getPrintableArea, getResolvedShapeClipPath, getRoundRectRadiusPx, getSecondaryValueAxis, getShapeAdjustmentHandleDescriptor, getSlideBackgroundStyle, getSlideTransitionAnimations, getSvgStrokeDasharray, getTextAlphaOpacity, getTextCompensationTransform, getWarpPath, groupElements, groupIntoParagraphs, groupSlidesBySection, hasCopyableFormat, hasDistinctScriptFonts, hasPressureVariation, insertTableColumn, insertTableRow, isActionHidden, isBrowserOpenableMime, isCellInRect, isEditableTextElement, isExportAbortError, isFirstSlide, isKeyboardOpen, isLastSlide, isMixedContentBlocked, isMobileViewport, isPpactionUrl, isPresentationSessionMessage, isTemplateElement, isTemplateElementId, isUrlSafe, listAutosaveSnapshots, listBackstageRecentFiles, loadPresentationDeck, makeCloneId, makeSlideId, mergeAdditiveSelection, mergeCells, mergePresentationSnapshot, mobileElapsedSince, mobileSlideCounter, mountModel3D, mountSurfaceChart3D, movePresenterPointer, moveQuickAccessCommand, moveSectionDown, moveSectionUp, moveSlidesToSection, newTableElement, normalizeColorsForCapture, normalizeHexColor, normalizeStrokeDashType, normalizeValue, notesSegmentsToSpans, observeYDocSlides, ooxmlDashToCssBorderStyle, openPptxFile, openUrlInNewTab, paletteColor, parseDrawingColor, parseDrawingColorOpacity, parsePpactionUrl, pickSupportedMimeType, placeAudienceWindow, preprocessCssForCapture, presentationInkPath, presenterElapsed, pressuresToWidths, readBackstageRecentFile, readSlidesFromYDoc, readStoredViewerPrefs, readViewportMetrics, rebuildDrawingShapesIfCleared, reconcileSlidesInYDoc, recordProgressPercent, rectToCells, remapTextToSegments, removeQuickAccessCommand, renameSection, rerouteConnectorsForMovedElements, resetPresenterTimer, resolveAudienceScreenPlacement, resolveCssTextAlign, resolveDrawingShapeNodeId, resolveFontForScript, resolveInkColor, resolveInkOpacity, resolveInkWidth, resolveLineHeight, resolveOleType, resolveParagraphAlign, resolveParagraphRtl, resolvePictureBullet, resolveProfileInitial, resolveRegionCode, resolveThemeCatalogEntry, resolveTitleBarStatusKey, resolveTransitionDurationMs, resolveTransportForServerUrl, resolveUnderlineDecorationStyle, resolveViewerAddinRows, restoreSegmentSelection, safeOpenUrl, sanitizeColor, sanitizeDownloadFilename, sanitizeMathMl, saveAutosaveSnapshot, saveViewerProfile, scanAvailableFontFamilies, segmentByScript, segmentFrameCount, sendBackward, sendToBack, sequentialColorScale, seriesColor, setCachedResult, setDuotoneCachedResult, setPendingSelectionRestore, shadeColor2, shouldCommitSmartArtNodeText, shouldConfirmExternalHyperlink, shouldLoopContinuously, shouldUseSvgWarp, slideProgressPercent, slideStatusLabel, snapBoxToGrid, splitCell, splitSeriesByAxis, stepPresenterZoom, storePresentationDeck, substituteFieldText, svgLineCap, swapPresentationWindows, themeToCssVars, tintColor2, toCssTextOrientation, toCssVerticalDirection, toCssWritingMode, togglePresenterTimer, transformTextCase, validateRoomId, valueToY, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius, viewerOptionsToPreferences, withChartPointValue, withChartTitle, writeStoredViewerPrefs };
27204
+ export { ACTION_BUTTON_PRESETS, ARTISTIC_EFFECTS, AVATAR_COLOR_SWATCHES, BACKSTAGE_NAV, BACKSTAGE_TEMPLATES, BROADCAST_THROTTLE_MS, CATEGORIES, CONNECTION_TIMEOUT_MS, DEFAULT_BROADCAST_SERVER_URL, DEFAULT_COLOR_CHANGE_TOLERANCE, DEFAULT_INSERT_CHART_TYPE, DEFAULT_QUICK_ACCESS_COMMAND_IDS, DEFAULT_ROW_HEIGHT, DEFAULT_VIEWER_OPTIONS, DEFAULT_VIEWER_PROFILE, DEFAULT_VIRTUAL_OVERSCAN, DIRECTIONAL_PRESETS, DUOTONE_PRESETS, EQUATION_TEMPLATES, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, FILL_MODE_OPTIONS, GRADIENT_TYPE_OPTIONS, HANDOUT_OPTIONS, INK_REPLAY_KEYFRAMES, INSERT_CHART_TYPES, LBL, LOCAL_SYNC_ORIGIN, MOBILE_BREAKPOINT, NOTES_FONT_SIZE_DEFAULT, NOTES_FONT_SIZE_MAX, NOTES_FONT_SIZE_MIN, NOTES_FONT_SIZE_STEP, NUM, PATTERN_OPTIONS, PRESENTATION_CHANNEL_NAME, PRESENTATION_HASH, PRESENTATION_MESSAGE_ORIGIN, PRESENTATION_NONCE_KEY, PRESETS, PresentationAnimationController, QUICK_ACCESS_COMMAND_CATALOG, RULER_FONT_SIZE, RULER_THICKNESS, SECTION_HEADING, SEL, SHAPE_PRESET_DEFS, SHORTCUT_REFERENCE_ITEMS, SLIDE_TRANSITION_KEYFRAMES, SLIDE_VIRTUALIZATION_THRESHOLD, TABLET_BREAKPOINT, TABLE_STYLE_PRESETS, TAB_ROW_ACTION_CLASSES, TEXT_BUILD_ID_SEP, THEME_CATALOG, THEME_COLOR_LABELS, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, TOOLBAR_TABS, VIEWER_OPTIONS_TABS, VIEWER_PREFS_STORAGE_KEY, WEBM_MIME_CANDIDATES, activateModalFocus, addQuickAccessCommand, addSection, alignElements, appendPresentationInkPoint, apply3dEffects, applyAcceptAllSlides, applyAcceptSlide, applyCaseTransformToSegments, applyChartBuildReveal, applyColorChange, applyDuotone, applyFormatToElement, applyPreferenceToOptions, applyRehearsalTimings, applyReroutedConnectors, applyResize, applyStyleToSelectedSegments, availableQuickAccessCommands, bringForward, bringToFront, build3DExtrusionData, buildBroadcastViewerUrl, buildCacheKey, buildChartViewModel, buildCollaborationShareUrl, buildCreateCollaborationConfig, buildCssGradientFromShapeStyle, buildDuotoneCacheKey, buildElementClipboardPayload, buildGlowBoxShadow, buildHandoutsHtml, buildInitialGuides, buildInnerShadowCssFromShapeStyle, buildJoinCollaborationConfig, buildMultiLayerShadowCss, buildNotesHtml, buildNotesPdfBytes, buildOutlineHtml, buildPatternFillCss, buildPresentationAudienceUrl, buildPreviewAnimation, buildPreviewElements, buildPrintDocument, buildPrintHtmlDocument, buildReflectionCss, buildShadowCssFromShapeStyle, buildSlidesHtml, buildSlidesPdfBytes, buildSmartArt3DModel, buildSmartArtA11y, buildSmartArtPresetData, buildSummaryZoomView, buildTextBody3DSceneStyle, buildTextFillCss, buildTextReflectionCss, buildTextRunFilterChain, buildTextShadowCss, buildThemeColorGrid, buildUserFontFaceStyles, canvasToJpegData, cell3DBevelCss, chartPartToAttrs, clampCropValue, clampNotesFontSize, clampPercent, clampUnitInterval, clearAllLocalViewerData, clearAudienceContent, clearStoredViewerPrefs, cloneElementForPaste, cloneHistorySnapshot, cloneSlide, cloneTemplateElementsBySlideId, collectImagePaths, collectMediaElements, collectUsedFonts, colorWithOpacity, comparePresentation, computeAllNotesPages, computeAutoFitTextStyle, computeColumnBoundaries, computeEntranceAnimationDelay, computeHandoutLayout, computeInlineEditorRect, computeKeyboardInset, computeLayout, computeLayoutOptions, computeMarqueeHitIds, computeMergeCellDown, computeMergeCellRight, computeResizedColumnWidths, computeResizedRowHeight, computeScrollDelta, computeSelectionRect, computeSmartArtLayout, computeSnapToShape, computeSplitCell, computeValueRange, computeValueRangeForChart, computeVirtualRange, convertLatexToOmml, convertOmmlToLatex, convertOmmlToMathMl, copyFormatFromElement, createBackstagePresentation, createBlankSlide, createDefaultChartElement, createInitialPresentationSnapshot, createPresentationSessionId, createPresenterTimer, createSyncGate, createTouchGestureRecognizer, createViewerOptionsStore, defaultCssVars, defaultRadius, defaultThemeColors, deleteAutosaveSnapshot, deleteSection, deleteTableColumn, deleteTableRow, derivePresenceList, detectOrientation, detectTouchDevice, distributeElements, downloadBlob, downloadDataUrl, dragAnchorViewY, dragValueForPart, encodeGif, erasePresentationInkAt, extractPathPoints, filterCommands, findChartPartTarget, findSmartArtNodeText, formatAxisValue, formatAxisValueWithUnits, formatBackstageDate, formatBackstageSize, formatBytes, formatCommentTimestamp, formatElapsed, formatMobileElapsed, formatRelativeTime, formatSlideCounter, formatTime, formatVersionTimestamp, fpsToFrameIntervalMs, generateBroadcastRoomId, generateElementId, generateLogTicks, generateNoteLineCount, generatePackageReadme, generatePressureCircles, generateTicks, getAnimationInitialStyle, getAriaLabel, getAriaRole, getAriaRoleDescription, getCachedResult, getCellDiagonalBorders, getChartStylePalette, getCommentMarkerPosition, getCompoundLineBorderWidth, getCompoundLineBoxShadow, getCompoundLineOffsets, getCompoundLineWidths, getComputedEffectStyle, getConnectionSites, getContentPartReplayStyles, getCssBorderDashStyle, getDisplayUnitLabel, getDuotoneCachedResult, getEffectDagFilter, getElementLabel, getElementTransform, getElementTransformWithoutRotation, getGroupChildParentFill, getImageColorWashStyle, getImageEffectsFilter, getImageEffectsOpacity, getImageSvgFilters, getInkReplayStyles, getInlineEditorSelection, getKinsokuLineBreakStyles, getLocalStorageUsageSummary, getNotesPrintableArea, getOleBadgeLabel, getOleTypeColor, getOleTypeLabel, getPatternSvg, getPendingSelectionRestore, getPrintableArea, getResolvedShapeClipPath, getRoundRectRadiusPx, getSecondaryValueAxis, getShapeAdjustmentHandleDescriptor, getSlideBackgroundStyle, getSlideTransitionAnimations, getSoftEdgeFilterId, getSoftEdgeSvgFilter, getSvgStrokeDasharray, getTextAlphaOpacity, getTextCompensationTransform, getWarpPath, groupElements, groupIntoParagraphs, groupSlidesBySection, hasCopyableFormat, hasDistinctScriptFonts, hasPressureVariation, hexToRgbChannels, insertTableColumn, insertTableRow, isActionHidden, isBrowserOpenableMime, isCellInRect, isEditableTextElement, isExportAbortError, isFirstSlide, isKeyboardOpen, isLastSlide, isMixedContentBlocked, isMobileViewport, isPpactionUrl, isPresentationSessionMessage, isTemplateElement, isTemplateElementId, isUrlSafe, listAutosaveSnapshots, listBackstageRecentFiles, loadAudienceContent, makeCloneId, makeSlideId, mergeAdditiveSelection, mergeCells, mergePresentationSnapshot, mobileElapsedSince, mobileSlideCounter, mountModel3D, mountSurfaceChart3D, movePresenterPointer, moveQuickAccessCommand, moveSectionDown, moveSectionUp, moveSlidesToSection, newTableElement, normalizeColorsForCapture, normalizeHexColor, normalizeStrokeDashType, normalizeValue, notesSegmentsToSpans, observeYDocSlides, ooxmlDashToCssBorderStyle, openPptxFile, openUrlInNewTab, paletteColor, parseDrawingColor, parseDrawingColorOpacity, parseMediaCommand, parsePpactionUrl, pickSupportedMimeType, placeAudienceWindow, preprocessCssForCapture, presentationInkPath, presenterElapsed, pressuresToWidths, printPropertiesFrameSlides, printPropertiesSlidesPerPage, readBackstageRecentFile, readSlidesFromYDoc, readStoredViewerPrefs, readViewportMetrics, rebuildDrawingShapesIfCleared, reconcileSlidesInYDoc, recordProgressPercent, rectToCells, remapTextToSegments, removeQuickAccessCommand, renameSection, rerouteConnectorsForMovedElements, resetPresenterTimer, resolveAudienceScreenPlacement, resolveCssTextAlign, resolveDrawingShapeNodeId, resolveFontForScript, resolveFontRefIdx, resolveGroupChildFill, resolveInkColor, resolveInkOpacity, resolveInkWidth, resolveLineHeight, resolveOleType, resolveParagraphAlign, resolveParagraphRtl, resolvePictureBullet, resolveProfileInitial, resolveRegionCode, resolveThemeCatalogEntry, resolveTitleBarStatusKey, resolveTransitionDurationMs, resolveTransportForServerUrl, resolveUnderlineDecorationStyle, resolveViewerAddinRows, restoreSegmentSelection, revealedSmartArtNodeCount, safeOpenUrl, sanitizeColor, sanitizeDownloadFilename, sanitizeMathMl, saveAutosaveSnapshot, saveViewerProfile, scanAvailableFontFamilies, segmentByScript, segmentFrameCount, sendBackward, sendToBack, sequentialColorScale, seriesColor, setCachedResult, setDuotoneCachedResult, setPendingSelectionRestore, shadeColor2, shouldAutoFollowBroadcaster, shouldCommitSmartArtNodeText, shouldConfirmExternalHyperlink, shouldLoopContinuously, shouldUseSvgWarp, slideProgressPercent, slideStatusLabel, snapBoxToGrid, splitCell, splitSeriesByAxis, stepPresenterZoom, storeAudienceContent, substituteFieldText, svgLineCap, swapPresentationWindows, themeToCssVars, tintColor2, toCssTextOrientation, toCssVerticalDirection, toCssWritingMode, togglePresenterTimer, transformTextCase, validateRoomId, valueToY, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius, viewerOptionsToPreferences, withChartPointValue, withChartTitle, withFrameSlides, withSlidesPerPage, writeStoredViewerPrefs };