pptx-react-viewer 1.16.1 → 1.17.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 (114) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/{Model3DScene-DDKQ372V.mjs → Model3DScene-QHDYQXL2.mjs} +2 -2
  3. package/dist/Model3DScene-QHDYQXL2.mjs.br +0 -0
  4. package/dist/Model3DScene-QHDYQXL2.mjs.gz +0 -0
  5. package/dist/{Model3DScene-UBHBPNJ2.js → Model3DScene-YA4F63DT.js} +3 -3
  6. package/dist/Model3DScene-YA4F63DT.js.br +0 -0
  7. package/dist/Model3DScene-YA4F63DT.js.gz +0 -0
  8. package/dist/PowerPointViewer-C4d7SKZf.d.ts +21 -0
  9. package/dist/PowerPointViewer-C4d7SKZf.d.ts.map +1 -0
  10. package/dist/{SurfaceChart3DScene-VSUUH2MX.mjs → SurfaceChart3DScene-GUAS2NWQ.mjs} +2 -2
  11. package/dist/SurfaceChart3DScene-GUAS2NWQ.mjs.br +0 -0
  12. package/dist/SurfaceChart3DScene-GUAS2NWQ.mjs.gz +0 -0
  13. package/dist/{SurfaceChart3DScene-MNFDDCYS.js → SurfaceChart3DScene-TGNJHTJQ.js} +3 -3
  14. package/dist/SurfaceChart3DScene-TGNJHTJQ.js.br +0 -0
  15. package/dist/SurfaceChart3DScene-TGNJHTJQ.js.gz +0 -0
  16. package/dist/{chunk-4LRPKUP7.js → chunk-3P6O7ZDM.js} +420 -420
  17. package/dist/chunk-3P6O7ZDM.js.br +0 -0
  18. package/dist/chunk-3P6O7ZDM.js.gz +0 -0
  19. package/dist/{chunk-YARAQWA4.mjs → chunk-G22EWPLH.mjs} +134 -4
  20. package/dist/chunk-G22EWPLH.mjs.br +0 -0
  21. package/dist/chunk-G22EWPLH.mjs.gz +0 -0
  22. package/dist/{chunk-TLGPM7SI.js → chunk-JWS3RQKN.js} +160 -28
  23. package/dist/chunk-JWS3RQKN.js.br +0 -0
  24. package/dist/chunk-JWS3RQKN.js.gz +0 -0
  25. package/dist/{chunk-XOSQDCHZ.mjs → chunk-LLHFNGAF.mjs} +4 -4
  26. package/dist/chunk-LLHFNGAF.mjs.br +0 -0
  27. package/dist/chunk-LLHFNGAF.mjs.gz +0 -0
  28. package/dist/{chunk-YW23L4KK.mjs → chunk-LNSHC2Z5.mjs} +117 -156
  29. package/dist/chunk-LNSHC2Z5.mjs.br +0 -0
  30. package/dist/chunk-LNSHC2Z5.mjs.gz +0 -0
  31. package/dist/{chunk-VMQLQEGG.js → chunk-MGLRKGCH.js} +156 -98
  32. package/dist/chunk-MGLRKGCH.js.br +0 -0
  33. package/dist/chunk-MGLRKGCH.js.gz +0 -0
  34. package/dist/{chunk-AJPW5FS7.mjs → chunk-XRYREYXC.mjs} +156 -98
  35. package/dist/chunk-XRYREYXC.mjs.br +0 -0
  36. package/dist/chunk-XRYREYXC.mjs.gz +0 -0
  37. package/dist/{chunk-YQHPV3VP.js → chunk-XW5OMXW6.js} +915 -954
  38. package/dist/chunk-XW5OMXW6.js.br +0 -0
  39. package/dist/chunk-XW5OMXW6.js.gz +0 -0
  40. package/dist/{dist-55M4L5OI.js → dist-2ZAH7U6U.js} +507 -507
  41. package/dist/dist-2ZAH7U6U.js.br +0 -0
  42. package/dist/dist-2ZAH7U6U.js.gz +0 -0
  43. package/dist/{dist-C5CVVTDM.mjs → dist-MXDC6YTS.mjs} +1 -1
  44. package/dist/dist-MXDC6YTS.mjs.br +0 -0
  45. package/dist/dist-MXDC6YTS.mjs.gz +0 -0
  46. package/dist/hooks-unstable.d.ts +9683 -1886
  47. package/dist/hooks-unstable.d.ts.map +1 -0
  48. package/dist/hooks-unstable.js +74 -74
  49. package/dist/hooks-unstable.js.br +0 -0
  50. package/dist/hooks-unstable.js.gz +0 -0
  51. package/dist/hooks-unstable.mjs +3 -3
  52. package/dist/hooks-unstable.mjs.br +0 -0
  53. package/dist/hooks-unstable.mjs.gz +0 -0
  54. package/dist/i18n.d.ts +27 -1
  55. package/dist/i18n.d.ts.map +1 -0
  56. package/dist/index-XGt7MZpa.d.ts +607 -0
  57. package/dist/index-XGt7MZpa.d.ts.map +1 -0
  58. package/dist/index.d.ts +4753 -10
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +18 -18
  61. package/dist/index.js.br +0 -0
  62. package/dist/index.js.gz +0 -0
  63. package/dist/index.mjs +4 -4
  64. package/dist/index.mjs.br +0 -0
  65. package/dist/index.mjs.gz +0 -0
  66. package/dist/types-BK7Nt13M.d.ts +483 -0
  67. package/dist/types-BK7Nt13M.d.ts.map +1 -0
  68. package/dist/viewer/index.d.ts +8008 -88
  69. package/dist/viewer/index.d.ts.map +1 -0
  70. package/dist/viewer/index.js +19 -19
  71. package/dist/viewer/index.js.br +0 -0
  72. package/dist/viewer/index.js.gz +0 -0
  73. package/dist/viewer/index.mjs +4 -4
  74. package/dist/viewer/index.mjs.br +0 -0
  75. package/dist/viewer/index.mjs.gz +0 -0
  76. package/package.json +6 -5
  77. package/dist/Model3DScene-DDKQ372V.mjs.br +0 -0
  78. package/dist/Model3DScene-DDKQ372V.mjs.gz +0 -0
  79. package/dist/Model3DScene-UBHBPNJ2.js.br +0 -0
  80. package/dist/Model3DScene-UBHBPNJ2.js.gz +0 -0
  81. package/dist/PowerPointViewer-BsaUH3ZT.d.ts +0 -26
  82. package/dist/PowerPointViewer-Nxku67uL.d.mts +0 -26
  83. package/dist/SurfaceChart3DScene-MNFDDCYS.js.br +0 -0
  84. package/dist/SurfaceChart3DScene-MNFDDCYS.js.gz +0 -0
  85. package/dist/SurfaceChart3DScene-VSUUH2MX.mjs.br +0 -0
  86. package/dist/SurfaceChart3DScene-VSUUH2MX.mjs.gz +0 -0
  87. package/dist/chunk-4LRPKUP7.js.br +0 -0
  88. package/dist/chunk-4LRPKUP7.js.gz +0 -0
  89. package/dist/chunk-AJPW5FS7.mjs.br +0 -0
  90. package/dist/chunk-AJPW5FS7.mjs.gz +0 -0
  91. package/dist/chunk-TLGPM7SI.js.br +0 -0
  92. package/dist/chunk-TLGPM7SI.js.gz +0 -0
  93. package/dist/chunk-VMQLQEGG.js.br +0 -0
  94. package/dist/chunk-VMQLQEGG.js.gz +0 -0
  95. package/dist/chunk-XOSQDCHZ.mjs.br +0 -0
  96. package/dist/chunk-XOSQDCHZ.mjs.gz +0 -0
  97. package/dist/chunk-YARAQWA4.mjs.br +0 -0
  98. package/dist/chunk-YARAQWA4.mjs.gz +0 -0
  99. package/dist/chunk-YQHPV3VP.js.br +0 -0
  100. package/dist/chunk-YQHPV3VP.js.gz +0 -0
  101. package/dist/chunk-YW23L4KK.mjs.br +0 -0
  102. package/dist/chunk-YW23L4KK.mjs.gz +0 -0
  103. package/dist/dist-55M4L5OI.js.br +0 -0
  104. package/dist/dist-55M4L5OI.js.gz +0 -0
  105. package/dist/dist-C5CVVTDM.mjs.br +0 -0
  106. package/dist/dist-C5CVVTDM.mjs.gz +0 -0
  107. package/dist/hooks-unstable.d.mts +0 -2300
  108. package/dist/i18n.d.mts +0 -1
  109. package/dist/index.d.mts +0 -46
  110. package/dist/types-ui-NG29h55h.d.mts +0 -712
  111. package/dist/types-ui-NG29h55h.d.ts +0 -712
  112. package/dist/usePresenterWindow-DToCijGy.d.ts +0 -1619
  113. package/dist/usePresenterWindow-DeTm-unp.d.mts +0 -1619
  114. package/dist/viewer/index.d.mts +0 -129
package/dist/index.d.ts CHANGED
@@ -1,14 +1,4601 @@
1
- export { P as PowerPointViewer, g as getAnimationInitialStyle } from './PowerPointViewer-BsaUH3ZT.js';
2
- export { P as PowerPointViewerAPI, a as PowerPointViewerHandle, b as PowerPointViewerProps, V as ViewerMode } from './types-ui-NG29h55h.js';
1
+ import * as react from 'react';
2
+ import react__default from 'react';
3
3
  import { Options } from 'html2canvas-pro';
4
- import * as React$1 from 'react';
5
- import { ViewerTheme } from './theme/index.js';
6
- export { ViewerTheme, ViewerThemeColors, defaultCssVars, defaultRadius, defaultThemeColors, themeToCssVars, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius } from './theme/index.js';
7
- import './presentation-BfnrtJV1.js';
8
4
 
5
+ /**
6
+ * Theme configuration types for the PowerPoint viewer.
7
+ *
8
+ * All color values accept any valid CSS color string:
9
+ * hex (`#6366f1`), rgb (`rgb(99 102 241)`), hsl (`hsl(239 84% 67%)`),
10
+ * oklch (`oklch(0.585 0.233 277)`), named colors, etc.
11
+ *
12
+ * Framework-agnostic — shared by the React, Vue, and Angular bindings.
13
+ */
14
+ /**
15
+ * Semantic color tokens for the viewer UI.
16
+ *
17
+ * These map to CSS custom properties (`--pptx-<token>`) and drive all
18
+ * UI component colors. The naming follows the shadcn/ui convention so
19
+ * that Tailwind + shadcn users get a familiar experience.
20
+ */
21
+ interface ViewerThemeColors {
22
+ /** Page / root background */
23
+ background: string;
24
+ /** Default text color */
25
+ foreground: string;
26
+ /** Card / panel surface */
27
+ card: string;
28
+ /** Text on card surfaces */
29
+ cardForeground: string;
30
+ /** Popover / dropdown surface */
31
+ popover: string;
32
+ /** Text inside popovers */
33
+ popoverForeground: string;
34
+ /** Primary action color (buttons, active indicators) */
35
+ primary: string;
36
+ /** Text on primary-colored backgrounds */
37
+ primaryForeground: string;
38
+ /** Secondary / subdued action color */
39
+ secondary: string;
40
+ /** Text on secondary backgrounds */
41
+ secondaryForeground: string;
42
+ /** Muted / disabled surface */
43
+ muted: string;
44
+ /** Text on muted surfaces (also used for secondary text) */
45
+ mutedForeground: string;
46
+ /** Accent / hover-highlight surface */
47
+ accent: string;
48
+ /** Text on accent surfaces */
49
+ accentForeground: string;
50
+ /** Destructive / danger action color */
51
+ destructive: string;
52
+ /** Text on destructive backgrounds */
53
+ destructiveForeground: string;
54
+ /** Default border color */
55
+ border: string;
56
+ /** Input field border color */
57
+ input: string;
58
+ /** Focus ring color */
59
+ ring: string;
60
+ }
61
+ /**
62
+ * Full viewer theme configuration.
63
+ *
64
+ * Every property is optional — unset values fall back to the built-in
65
+ * dark theme defaults.
66
+ */
67
+ interface ViewerTheme {
68
+ /** Semantic UI colors. Each key maps to a `--pptx-<key>` CSS custom property. */
69
+ colors?: Partial<ViewerThemeColors>;
70
+ /** Base border-radius value (e.g. `"0.5rem"`, `"8px"`). */
71
+ radius?: string;
72
+ /**
73
+ * Escape hatch: arbitrary CSS custom properties to set on the viewer
74
+ * root element. Keys should include the `--` prefix.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * { "--my-custom-shadow": "0 4px 12px rgba(0,0,0,0.5)" }
79
+ * ```
80
+ */
81
+ cssVars?: Record<string, string>;
82
+ }
83
+
84
+ /**
85
+ * Default dark-theme color values.
86
+ *
87
+ * These correspond to the built-in dark UI of the PowerPoint viewer and
88
+ * use Tailwind's gray palette as the neutral scale with indigo as the
89
+ * primary accent.
90
+ */
91
+ declare const defaultThemeColors: ViewerThemeColors;
92
+ /** Default border-radius. */
93
+ declare const defaultRadius = "0.5rem";
94
+
95
+ /**
96
+ * Convert a `ViewerTheme` into a flat `Record<string, string>` of CSS
97
+ * custom properties (including the `--` prefix) ready to be spread onto
98
+ * a `style` attribute.
99
+ *
100
+ * Only properties that differ from the built-in defaults are emitted when
101
+ * `omitDefaults` is true (the default).
102
+ */
103
+ declare function themeToCssVars(theme: ViewerTheme | undefined, omitDefaults?: boolean): Record<string, string>;
104
+ /**
105
+ * Build the complete set of CSS custom properties with all defaults.
106
+ * Useful for generating a full fallback stylesheet.
107
+ */
108
+ declare function defaultCssVars(): Record<string, string>;
109
+
110
+ /**
111
+ * Built-in "vermilion" theme presets.
112
+ *
113
+ * These mirror the pptx-viewer brand used on the documentation site:
114
+ * a warm paper canvas in light mode, a dimmed presenter room in dark
115
+ * mode, and the vermilion accent in both. Pass one to the viewer's
116
+ * `theme` prop (React/Vue) or `provideViewerTheme` (Angular), or spread
117
+ * the color objects to derive your own variant.
118
+ */
119
+ /** Light "paper" palette: a projection screen in a bright room. */
120
+ declare const vermilionLightColors: ViewerThemeColors;
121
+ /** Dark "presenter" palette: the presenter room with the lights down. */
122
+ declare const vermilionDarkColors: ViewerThemeColors;
123
+ /** Shared border-radius for the vermilion presets (slightly sharper than the default). */
124
+ declare const vermilionRadius = "0.375rem";
125
+ /** Light vermilion theme, ready for the viewer's `theme` prop. */
126
+ declare const vermilionLightTheme: ViewerTheme;
127
+ /** Dark vermilion theme, ready for the viewer's `theme` prop. */
128
+ declare const vermilionDarkTheme: ViewerTheme;
129
+
130
+ /**
131
+ * Action types: hyperlinks, slide jumps, macros, and action buttons.
132
+ *
133
+ * @module pptx-types/actions
134
+ */
135
+ /**
136
+ * A parsed shape-level action from `a:hlinkClick` or `a:hlinkHover`.
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * const link: PptxAction = {
141
+ * url: "https://example.com",
142
+ * tooltip: "Visit Example",
143
+ * highlightClick: true,
144
+ * };
145
+ *
146
+ * const slideJump: PptxAction = {
147
+ * action: "ppaction://hlinksldjump",
148
+ * targetSlideIndex: 3,
149
+ * };
150
+ * // => satisfies PptxAction
151
+ * ```
152
+ */
153
+ interface PptxAction {
154
+ /** Relationship ID referencing the action target. */
155
+ rId?: string;
156
+ /** OOXML action string (e.g. `ppaction://hlinksldjump`). */
157
+ action?: string;
158
+ /** Tooltip text shown on hover. */
159
+ tooltip?: string;
160
+ /** Whether the shape should highlight on click. */
161
+ highlightClick?: boolean;
162
+ /** Resolved URL or file path from the slide relationship map. */
163
+ url?: string;
164
+ /** Zero-based index into the slides array for internal slide jumps. */
165
+ targetSlideIndex?: number;
166
+ /** Relationship ID of an optional click sound (`a:snd/@r:embed`). */
167
+ soundRId?: string;
168
+ /** Resolved media target path for the optional click sound. */
169
+ soundPath?: string;
170
+ }
171
+
172
+ /**
173
+ * Shared value types used across the entire PPTX editor type system.
174
+ *
175
+ * Contains primitive enums, small interfaces, and the XML object alias
176
+ * that almost every other type file imports.
177
+ *
178
+ * @module pptx-types/common
179
+ */
180
+ /**
181
+ * Underline style tokens from OOXML `a:rPr/@u`.
182
+ *
183
+ * These map directly to the OpenXML `ST_TextUnderlineType` simple type.
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * const style: UnderlineStyle = "wavy";
188
+ * // => "wavy" — one of: sng | dbl | heavy | dotted | dash | wavy | none | ...
189
+ * ```
190
+ */
191
+ type UnderlineStyle = 'sng' | 'dbl' | 'heavy' | 'dotted' | 'dottedHeavy' | 'dash' | 'dashHeavy' | 'dashLong' | 'dashLongHeavy' | 'dotDash' | 'dotDashHeavy' | 'dotDotDash' | 'dotDotDashHeavy' | 'wavy' | 'wavyHeavy' | 'wavyDbl' | 'none';
192
+ /**
193
+ * Connector connection point reference — links a connector endpoint to a
194
+ * specific shape on the slide.
195
+ *
196
+ * When both `shapeId` and `connectionSiteIndex` are set, the connector
197
+ * end snaps to that shapes’s connection site and “follows” the shape when
198
+ * it is moved.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * const start: ConnectorConnectionPoint = {
203
+ * shapeId: "shape_1",
204
+ * connectionSiteIndex: 2,
205
+ * };
206
+ * // => { shapeId: "shape_1", connectionSiteIndex: 2 } satisfies ConnectorConnectionPoint
207
+ * ```
208
+ */
209
+ interface ConnectorConnectionPoint {
210
+ /** ID of the shape this connector endpoint is attached to. */
211
+ shapeId?: string;
212
+ /** Connection site index on the target shape (0-based). */
213
+ connectionSiteIndex?: number;
214
+ }
215
+ /**
216
+ * Arrow head types for connector start/end.
217
+ *
218
+ * Maps to `a:headEnd/@type` and `a:tailEnd/@type` in OOXML.
219
+ *
220
+ * @example
221
+ * ```ts
222
+ * const arrow: ConnectorArrowType = "triangle";
223
+ * // => "triangle" — one of: none | triangle | stealth | diamond | oval | arrow
224
+ * ```
225
+ */
226
+ type ConnectorArrowType = 'none' | 'triangle' | 'stealth' | 'diamond' | 'oval' | 'arrow';
227
+ /**
228
+ * Stroke dash pattern types for lines and shape outlines.
229
+ *
230
+ * Maps to `a:ln/a:prstDash/@val` in OOXML. Use `"custom"` for
231
+ * user-defined dash/space arrays.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * const dash: StrokeDashType = "dashDot";
236
+ * // => "dashDot" — one of: solid | dot | dash | lgDash | dashDot | custom | ...
237
+ * ```
238
+ */
239
+ type StrokeDashType = 'solid' | 'dot' | 'dash' | 'lgDash' | 'dashDot' | 'lgDashDot' | 'lgDashDotDot' | 'sysDot' | 'sysDash' | 'sysDashDot' | 'sysDashDotDot' | 'custom';
240
+ /**
241
+ * Shadow effect properties for a single shadow layer.
242
+ *
243
+ * Represents parsed values from an `<a:outerShdw>` node. Multiple instances
244
+ * can be stored in {@link ShapeStyle.shadows} for compound shadow effects.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * const shadow: ShadowEffect = {
249
+ * color: "#000000",
250
+ * opacity: 0.4,
251
+ * blur: 6,
252
+ * angle: 315,
253
+ * distance: 4,
254
+ * };
255
+ * // => { color: "#000000", opacity: 0.4, blur: 6, angle: 315, distance: 4 } satisfies ShadowEffect
256
+ * ```
257
+ */
258
+ interface ShadowEffect {
259
+ /** Shadow color as hex string. */
260
+ color: string;
261
+ /** Shadow opacity (0-1). */
262
+ opacity: number;
263
+ /** Blur radius in pixels. */
264
+ blur: number;
265
+ /** Shadow angle in degrees (0-360). */
266
+ angle: number;
267
+ /** Shadow distance in pixels. */
268
+ distance: number;
269
+ /** Whether shadow rotates with shape. */
270
+ rotateWithShape?: boolean;
271
+ }
272
+ /**
273
+ * Strongly-typed parsed XML node from fast-xml-parser.
274
+ *
275
+ * The parser is configured with `attributeNamePrefix: '@_'`,
276
+ * `parseAttributeValue: false`, and `parseTagValue: false`, so attribute and
277
+ * text values are always strings at runtime. This type encodes that:
278
+ *
279
+ * - **Attributes** — keys matching `` `@_${string}` `` return
280
+ * `string | undefined` directly.
281
+ * - **Text content** — `#text` returns `string | undefined`.
282
+ * - **Child elements** — any other string key returns
283
+ * `XmlObject | XmlObject[] | string | undefined`. The union reflects that
284
+ * fast-xml-parser may emit an object (single child), an array (repeated
285
+ * children), or a bare string (text-only element collapsed by the parser).
286
+ *
287
+ * For traversal, prefer the helpers in {@link ./../utils/xml-access} —
288
+ * `xmlChild` / `xmlChildren` / `xmlAttr` / `xmlText` / `xmlPath` — which
289
+ * narrow the union and normalize the single-vs-array duality. Direct
290
+ * indexing works for attributes (typed as string) but chained child access
291
+ * (`obj['p:spPr']?.['a:xfrm']`) requires the helpers or a narrowing cast
292
+ * because TypeScript cannot index into the `XmlObject[] | string` part of
293
+ * the union.
294
+ */
295
+ interface XmlObject {
296
+ /** Attributes (`@_`-prefixed keys) are always strings at runtime. */
297
+ [attr: `@_${string}`]: string | undefined;
298
+ /** Element text content surfaces under `#text` when present. */
299
+ '#text'?: string;
300
+ /**
301
+ * Child elements keyed by their (namespaced) tag name. fast-xml-parser
302
+ * emits a single object for unique elements, an array for repeated ones,
303
+ * and a bare string for elements collapsed to their text content. Use
304
+ * the helpers in `utils/xml-access` to narrow this union.
305
+ */
306
+ [child: string]: XmlObject | XmlObject[] | string | undefined;
307
+ }
308
+ /**
309
+ * Shape lock attributes from `p:cNvSpPr / a:spLocks`.
310
+ *
311
+ * When a flag is `true` the corresponding user interaction is disabled
312
+ * in the editor (e.g. `noRotation` prevents free rotation of the shape).
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * const locks: PptxShapeLocks = { noMove: true, noResize: true };
317
+ * // => { noMove: true, noResize: true } satisfies PptxShapeLocks
318
+ * ```
319
+ */
320
+ interface PptxShapeLocks {
321
+ noGrouping?: boolean;
322
+ noRotation?: boolean;
323
+ noMove?: boolean;
324
+ noResize?: boolean;
325
+ noTextEdit?: boolean;
326
+ noSelect?: boolean;
327
+ noChangeAspect?: boolean;
328
+ noEditPoints?: boolean;
329
+ noAdjustHandles?: boolean;
330
+ noChangeArrowheads?: boolean;
331
+ noChangeShapeType?: boolean;
332
+ }
333
+ /**
334
+ * A drawing guide parsed from OOXML extension lists.
335
+ *
336
+ * Slide-level and presentation-level guides are shown as thin coloured
337
+ * lines that help users align elements.
338
+ *
339
+ * @example
340
+ * ```ts
341
+ * const guide: PptxDrawingGuide = {
342
+ * id: "g1",
343
+ * orientation: "horz",
344
+ * positionEmu: 457200,
345
+ * color: "#FF0000",
346
+ * };
347
+ * // => { id: "g1", orientation: "horz", positionEmu: 457200, color: "#FF0000" } satisfies PptxDrawingGuide
348
+ * ```
349
+ */
350
+ interface PptxDrawingGuide {
351
+ /** Unique identifier (from `@_id` attribute or generated). */
352
+ id: string;
353
+ /** Orientation: horizontal or vertical. */
354
+ orientation: 'horz' | 'vert';
355
+ /** Position in EMU (converted from pos attribute). */
356
+ positionEmu: number;
357
+ /** Optional guide colour as hex string (e.g. "#FF0000"). */
358
+ color?: string;
359
+ }
360
+
361
+ /**
362
+ * Geometry types: adjustment handles, custom geometry points, segments,
363
+ * paths, and custom path properties.
364
+ *
365
+ * @module pptx-types/geometry
366
+ */
367
+ /**
368
+ * Defines an adjustment handle position for a shape geometry.
369
+ *
370
+ * Adjustment handles allow users to interactively reshape preset shapes
371
+ * (e.g. rounding a rectangle corner or adjusting arrow head width).
372
+ *
373
+ * @example
374
+ * ```ts
375
+ * const handle: GeometryAdjustmentHandle = {
376
+ * guideName: "adj",
377
+ * xFraction: 0.25,
378
+ * minValue: 0,
379
+ * maxValue: 50000,
380
+ * };
381
+ * // => satisfies GeometryAdjustmentHandle
382
+ * ```
383
+ */
384
+ interface GeometryAdjustmentHandle {
385
+ /** Name of the adjustment guide this handle controls (e.g. "adj", "adj1"). */
386
+ guideName: string;
387
+ /** X position as a fraction of shape width (0..1), or undefined if the handle only moves vertically. */
388
+ xFraction?: number;
389
+ /** Y position as a fraction of shape height (0..1), or undefined if the handle only moves horizontally. */
390
+ yFraction?: number;
391
+ /** Minimum allowed value for the adjustment guide. */
392
+ minValue?: number;
393
+ /** Maximum allowed value for the adjustment guide. */
394
+ maxValue?: number;
395
+ }
396
+ /**
397
+ * A single point in a custom geometry path.
398
+ *
399
+ * @example
400
+ * ```ts
401
+ * const pt: CustomGeometryPoint = { x: 100, y: 200 };
402
+ * // => satisfies CustomGeometryPoint
403
+ * ```
404
+ */
405
+ interface CustomGeometryPoint {
406
+ x: number;
407
+ y: number;
408
+ }
409
+ /**
410
+ * A segment within a custom geometry path.
411
+ *
412
+ * Discriminated union over `type` — can be a moveTo, lineTo,
413
+ * cubic Bézier, quadratic Bézier, or close command.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * const segments: CustomGeometrySegment[] = [
418
+ * { type: "moveTo", pt: { x: 0, y: 0 } },
419
+ * { type: "lineTo", pt: { x: 100, y: 0 } },
420
+ * { type: "lineTo", pt: { x: 100, y: 100 } },
421
+ * { type: "close" },
422
+ * ];
423
+ * // => satisfies CustomGeometrySegment[]
424
+ * ```
425
+ */
426
+ type CustomGeometrySegment = {
427
+ type: 'moveTo';
428
+ pt: CustomGeometryPoint;
429
+ } | {
430
+ type: 'lineTo';
431
+ pt: CustomGeometryPoint;
432
+ } | {
433
+ type: 'cubicBezTo';
434
+ pts: [CustomGeometryPoint, CustomGeometryPoint, CustomGeometryPoint];
435
+ } | {
436
+ type: 'quadBezTo';
437
+ pts: [CustomGeometryPoint, CustomGeometryPoint];
438
+ } | {
439
+ type: 'arcTo';
440
+ /** Horizontal radius of the ellipse. */
441
+ wR: number;
442
+ /** Vertical radius of the ellipse. */
443
+ hR: number;
444
+ /** Start angle in 60000ths of a degree. */
445
+ stAng: number;
446
+ /** Sweep angle in 60000ths of a degree. */
447
+ swAng: number;
448
+ } | {
449
+ type: 'close';
450
+ };
451
+ /**
452
+ * A single sub-path in a custom geometry definition (maps to one `a:path`).
453
+ *
454
+ * @example
455
+ * ```ts
456
+ * const path: CustomGeometryPath = {
457
+ * width: 100,
458
+ * height: 100,
459
+ * segments: [
460
+ * { type: "moveTo", pt: { x: 0, y: 0 } },
461
+ * { type: "lineTo", pt: { x: 100, y: 100 } },
462
+ * ],
463
+ * };
464
+ * // => satisfies CustomGeometryPath
465
+ * ```
466
+ */
467
+ interface CustomGeometryPath {
468
+ /** Coordinate-space width for this sub-path. */
469
+ width: number;
470
+ /** Coordinate-space height for this sub-path. */
471
+ height: number;
472
+ /** Ordered list of drawing segments. */
473
+ segments: CustomGeometrySegment[];
474
+ /** Path fill mode (`a:path/@fill`): norm, lighten, lightenLess, darken, darkenLess, none. */
475
+ fillMode?: 'norm' | 'lighten' | 'lightenLess' | 'darken' | 'darkenLess' | 'none';
476
+ /** Whether the path is stroked (`a:path/@stroke`). */
477
+ stroke?: boolean;
478
+ /** 3D extrusion compatibility (`a:path/@extrusionOk`). */
479
+ extrusionOk?: boolean;
480
+ }
481
+ /**
482
+ * Auxiliary raw XML preserved from `a:custGeom` for round-trip serialization.
483
+ * These are stored opaquely so adjustment guides, handles, connection sites,
484
+ * and the text rectangle are not lost when a custGeom is edited and saved.
485
+ */
486
+ interface CustomGeometryRawData {
487
+ /** Raw `a:gdLst` XML content (guide list). */
488
+ gdLstXml?: unknown;
489
+ /** Raw `a:ahLst` XML content (adjustment handles). */
490
+ ahLstXml?: unknown;
491
+ /** Raw `a:cxnLst` XML content (connection sites). */
492
+ cxnLstXml?: unknown;
493
+ /** Raw `a:rect` XML content (text rectangle). */
494
+ rectXml?: unknown;
495
+ }
496
+ /**
497
+ * XY-style adjustment handle (`a:ahXY`) on a custom geometry.
498
+ *
499
+ * Allows interactive editing of one or two guide values constrained to a
500
+ * rectangular range. Coordinates are formula references (e.g. `"adj1"`,
501
+ * `"w/2"`, `"0"`) preserved verbatim so they can re-emit unchanged.
502
+ *
503
+ * @example
504
+ * ```ts
505
+ * const handle: AdjustHandleXY = {
506
+ * gdRefX: "adj1",
507
+ * minX: "0",
508
+ * maxX: "w",
509
+ * posX: "adj1",
510
+ * posY: "h/2",
511
+ * };
512
+ * // => satisfies AdjustHandleXY
513
+ * ```
514
+ */
515
+ interface AdjustHandleXY {
516
+ /** Guide reference for the X axis (`@_gdRefX`). */
517
+ gdRefX?: string;
518
+ /** Guide reference for the Y axis (`@_gdRefY`). */
519
+ gdRefY?: string;
520
+ /** Minimum X value, as a formula reference (`@_minX`). */
521
+ minX?: string;
522
+ /** Maximum X value (`@_maxX`). */
523
+ maxX?: string;
524
+ /** Minimum Y value (`@_minY`). */
525
+ minY?: string;
526
+ /** Maximum Y value (`@_maxY`). */
527
+ maxY?: string;
528
+ /** Handle position X (formula or literal) from `a:pos/@_x`. */
529
+ posX?: string;
530
+ /** Handle position Y from `a:pos/@_y`. */
531
+ posY?: string;
532
+ }
533
+ /**
534
+ * Polar-style adjustment handle (`a:ahPolar`) on a custom geometry.
535
+ *
536
+ * Drives a guide via radial distance and angle rather than XY coordinates.
537
+ *
538
+ * @example
539
+ * ```ts
540
+ * const handle: AdjustHandlePolar = {
541
+ * gdRefR: "adj1",
542
+ * gdRefAng: "adj2",
543
+ * posX: "wd2",
544
+ * posY: "hd2",
545
+ * };
546
+ * // => satisfies AdjustHandlePolar
547
+ * ```
548
+ */
549
+ interface AdjustHandlePolar {
550
+ /** Guide reference for the radial distance (`@_gdRefR`). */
551
+ gdRefR?: string;
552
+ /** Guide reference for the angle (`@_gdRefAng`). */
553
+ gdRefAng?: string;
554
+ /** Minimum radial value (`@_minR`). */
555
+ minR?: string;
556
+ /** Maximum radial value (`@_maxR`). */
557
+ maxR?: string;
558
+ /** Minimum angle (`@_minAng`). */
559
+ minAng?: string;
560
+ /** Maximum angle (`@_maxAng`). */
561
+ maxAng?: string;
562
+ /** Handle position X from `a:pos/@_x`. */
563
+ posX?: string;
564
+ /** Handle position Y from `a:pos/@_y`. */
565
+ posY?: string;
566
+ }
567
+ /**
568
+ * Connection site (`a:cxn`) on a custom geometry.
569
+ *
570
+ * Defines a point on a custom shape that connectors may snap to.
571
+ *
572
+ * @example
573
+ * ```ts
574
+ * const cxn: ConnectionSite = { ang: "0", posX: "0", posY: "hd2" };
575
+ * // => satisfies ConnectionSite
576
+ * ```
577
+ */
578
+ interface ConnectionSite {
579
+ /** Approach angle (`@_ang`) — formula or literal degree-1/60000 value. */
580
+ ang?: string;
581
+ /** Site position X from `a:pos/@_x`. */
582
+ posX?: string;
583
+ /** Site position Y from `a:pos/@_y`. */
584
+ posY?: string;
585
+ }
586
+ /**
587
+ * Typed text rectangle (`a:rect`) on a custom geometry.
588
+ *
589
+ * Each edge is the formula or literal string preserved from the source XML
590
+ * (`"l"`, `"t"`, `"r"`, `"b"`, or any guide name / formula).
591
+ */
592
+ interface CustomGeometryTextRect {
593
+ /** Left edge formula reference (`@_l`). */
594
+ l?: string;
595
+ /** Top edge (`@_t`). */
596
+ t?: string;
597
+ /** Right edge (`@_r`). */
598
+ r?: string;
599
+ /** Bottom edge (`@_b`). */
600
+ b?: string;
601
+ }
602
+ /**
603
+ * Custom (non-preset) geometry path — only on shapes and pictures.
604
+ *
605
+ * Contains SVG path data and/or structured custom geometry paths
606
+ * parsed from `a:custGeom/a:pathLst`.
607
+ *
608
+ * @example
609
+ * ```ts
610
+ * const custom: PptxCustomPathProperties = {
611
+ * pathData: "M 0 0 L 100 0 L 100 100 Z",
612
+ * pathWidth: 100,
613
+ * pathHeight: 100,
614
+ * };
615
+ * // => satisfies PptxCustomPathProperties
616
+ * ```
617
+ */
618
+ interface PptxCustomPathProperties {
619
+ /** SVG path data for custom shapes. */
620
+ pathData?: string;
621
+ /** Coordinate-space width for the custom path. */
622
+ pathWidth?: number;
623
+ /** Coordinate-space height for the custom path. */
624
+ pathHeight?: number;
625
+ /** Structured custom geometry paths for editing (maps to a:custGeom/a:pathLst). */
626
+ customGeometryPaths?: CustomGeometryPath[];
627
+ /** Raw a:gdLst/a:ahLst/a:cxnLst/a:rect XML preserved for round-trip serialization. */
628
+ customGeometryRawData?: CustomGeometryRawData;
629
+ /**
630
+ * Typed XY adjustment handles parsed from `a:custGeom/a:ahLst/a:ahXY`.
631
+ * SDK-built shapes can populate this and the writer will emit `<a:ahXY>` entries
632
+ * even when no raw XML was preserved.
633
+ */
634
+ customGeometryAdjustHandlesXY?: AdjustHandleXY[];
635
+ /**
636
+ * Typed polar adjustment handles parsed from `a:custGeom/a:ahLst/a:ahPolar`.
637
+ */
638
+ customGeometryAdjustHandlesPolar?: AdjustHandlePolar[];
639
+ /**
640
+ * Typed connection sites parsed from `a:custGeom/a:cxnLst/a:cxn`.
641
+ */
642
+ customGeometryConnectionSites?: ConnectionSite[];
643
+ /**
644
+ * Typed text rectangle parsed from `a:custGeom/a:rect`. When present this is
645
+ * preferred over {@link customGeometryRawData}'s `rectXml` on save.
646
+ */
647
+ customGeometryTextRect?: CustomGeometryTextRect;
648
+ }
649
+
650
+ /**
651
+ * 3-D effect properties, text warp (WordArt) presets, and scene/shape bevel
652
+ * definitions parsed from OOXML `a:sp3d`, `a:scene3d`, and `a:bodyPr/a:prstTxWarp`.
653
+ *
654
+ * @module pptx-types/three-d
655
+ */
656
+ /**
657
+ * Bevel preset type tokens from OOXML `a:bevelT/@prst` / `a:bevelB/@prst`.
658
+ *
659
+ * @example
660
+ * ```ts
661
+ * const bevel: BevelPresetType = "circle";
662
+ * // => "circle" — one of: "circle" | "relaxedInset" | "cross" | "coolSlant" | "angle" | …
663
+ * ```
664
+ */
665
+ type BevelPresetType = 'circle' | 'relaxedInset' | 'cross' | 'coolSlant' | 'angle' | 'softRound' | 'convex' | 'slope' | 'divot' | 'riblet' | 'hardEdge' | 'artDeco' | 'none';
666
+ /**
667
+ * Material preset type tokens from OOXML `a:sp3d/@prstMaterial`.
668
+ *
669
+ * @example
670
+ * ```ts
671
+ * const mat: MaterialPresetType = "plastic";
672
+ * // => "plastic" — one of: "matte" | "warmMatte" | "plastic" | "metal" | "dkEdge" | …
673
+ * ```
674
+ */
675
+ type MaterialPresetType = 'matte' | 'warmMatte' | 'plastic' | 'metal' | 'dkEdge' | 'softEdge' | 'flat' | 'softmetal' | 'clear' | 'powder' | 'translucentPowder' | 'legacyMatte' | 'legacyPlastic' | 'legacyMetal' | 'legacyWireframe';
676
+ /**
677
+ * 3D text body extrusion/bevel from `a:bodyPr/a:sp3d`.
678
+ *
679
+ * @example
680
+ * ```ts
681
+ * const text3d: Text3DStyle = {
682
+ * extrusionHeight: 57150,
683
+ * presetMaterial: "plastic",
684
+ * bevelTopType: "circle",
685
+ * bevelTopWidth: 25400,
686
+ * bevelTopHeight: 25400,
687
+ * };
688
+ * // => satisfies Text3DStyle
689
+ * ```
690
+ */
691
+ interface Text3DStyle {
692
+ /** Extrusion height (depth) in EMU. */
693
+ extrusionHeight?: number;
694
+ /** Extrusion colour as hex string. */
695
+ extrusionColor?: string;
696
+ /** Preset material, e.g. "matte", "plastic", "metal". */
697
+ presetMaterial?: MaterialPresetType;
698
+ /** Top bevel preset type. */
699
+ bevelTopType?: BevelPresetType;
700
+ /** Top bevel width in EMU. */
701
+ bevelTopWidth?: number;
702
+ /** Top bevel height in EMU. */
703
+ bevelTopHeight?: number;
704
+ /** Bottom bevel preset type. */
705
+ bevelBottomType?: BevelPresetType;
706
+ /** Bottom bevel width in EMU. */
707
+ bevelBottomWidth?: number;
708
+ /** Bottom bevel height in EMU. */
709
+ bevelBottomHeight?: number;
710
+ }
711
+ /**
712
+ * 3D scene/camera properties from `a:scene3d`.
713
+ *
714
+ * @example
715
+ * ```ts
716
+ * const scene: Pptx3DScene = {
717
+ * cameraPreset: "perspectiveFront",
718
+ * lightRigType: "threePt",
719
+ * lightRigDirection: "t",
720
+ * };
721
+ * // => satisfies Pptx3DScene
722
+ * ```
723
+ */
724
+ interface Pptx3DScene {
725
+ /** Camera preset type, e.g. "orthographicFront", "perspectiveFront". */
726
+ cameraPreset?: string;
727
+ /** Camera rotation around X axis in 1/60000 degrees. */
728
+ cameraRotX?: number;
729
+ /** Camera rotation around Y axis in 1/60000 degrees. */
730
+ cameraRotY?: number;
731
+ /** Camera rotation around Z axis in 1/60000 degrees. */
732
+ cameraRotZ?: number;
733
+ /** Light rig type, e.g. "threePt", "balanced", "harsh". */
734
+ lightRigType?: string;
735
+ /** Light rig direction, e.g. "t", "b", "l", "r", "tl". */
736
+ lightRigDirection?: string;
737
+ /** Whether a 3D backdrop plane is present (`a:backdrop`). */
738
+ hasBackdrop?: boolean;
739
+ /** Backdrop plane anchor X in EMU. */
740
+ backdropAnchorX?: number;
741
+ /** Backdrop plane anchor Y in EMU. */
742
+ backdropAnchorY?: number;
743
+ /** Backdrop plane anchor Z in EMU. */
744
+ backdropAnchorZ?: number;
745
+ }
746
+ /**
747
+ * 3D shape extrusion/bevel from `a:sp3d`.
748
+ *
749
+ * @example
750
+ * ```ts
751
+ * const shape3d: Pptx3DShape = {
752
+ * extrusionHeight: 76200,
753
+ * extrusionColor: "#4F81BD",
754
+ * presetMaterial: "metal",
755
+ * bevelTopType: "circle",
756
+ * bevelTopWidth: 12700,
757
+ * bevelTopHeight: 12700,
758
+ * };
759
+ * // => satisfies Pptx3DShape
760
+ * ```
761
+ */
762
+ interface Pptx3DShape {
763
+ /** Extrusion height in EMU. */
764
+ extrusionHeight?: number;
765
+ /** Extrusion colour. */
766
+ extrusionColor?: string;
767
+ /** Contour width in EMU. */
768
+ contourWidth?: number;
769
+ /** Contour colour. */
770
+ contourColor?: string;
771
+ /** Preset material, e.g. "matte", "warmMatte", "metal". */
772
+ presetMaterial?: string;
773
+ /** Top bevel type, e.g. "circle", "relaxedInset". */
774
+ bevelTopType?: string;
775
+ /** Top bevel width in EMU. */
776
+ bevelTopWidth?: number;
777
+ /** Top bevel height in EMU. */
778
+ bevelTopHeight?: number;
779
+ /** Bottom bevel type, e.g. "circle", "relaxedInset". */
780
+ bevelBottomType?: string;
781
+ /** Bottom bevel width in EMU. */
782
+ bevelBottomWidth?: number;
783
+ /** Bottom bevel height in EMU. */
784
+ bevelBottomHeight?: number;
785
+ }
786
+ /**
787
+ * Known OOXML preset text warp types (WordArt transforms).
788
+ *
789
+ * Falls back to `string` for unknown presets not yet catalogued.
790
+ *
791
+ * @example
792
+ * ```ts
793
+ * const warp: PptxTextWarpPreset = "textArchUp";
794
+ * // => "textArchUp" — one of: "textNoShape" | "textPlain" | "textStop" | "textArchUp" | …
795
+ * ```
796
+ */
797
+ type PptxTextWarpPreset = 'textNoShape' | 'textPlain' | 'textStop' | 'textTriangle' | 'textTriangleInverted' | 'textChevron' | 'textChevronInverted' | 'textRingInside' | 'textRingOutside' | 'textArchUp' | 'textArchDown' | 'textCircle' | 'textButton' | 'textArchUpPour' | 'textArchDownPour' | 'textCirclePour' | 'textButtonPour' | 'textCurveUp' | 'textCurveDown' | 'textCanUp' | 'textCanDown' | 'textWave1' | 'textWave2' | 'textWave4' | 'textDoubleWave1' | 'textInflate' | 'textDeflate' | 'textInflateBottom' | 'textDeflateBottom' | 'textInflateTop' | 'textDeflateTop' | 'textFadeRight' | 'textFadeLeft' | 'textFadeUp' | 'textFadeDown' | 'textSlantUp' | 'textSlantDown' | 'textCascadeUp' | 'textCascadeDown' | 'textDeflateInflate' | 'textDeflateInflateDeflate' | string;
798
+
799
+ /**
800
+ * Shape visual styling types: fill, stroke, effects, and connectors.
801
+ *
802
+ * {@link ShapeStyle} is the main type attached to any element that has
803
+ * visible geometry (shapes, connectors, images). It covers:
804
+ * - **Fill**: solid, gradient, pattern, image, and theme fills
805
+ * - **Stroke**: colour, width, dash pattern, line join/cap
806
+ * - **Effects**: shadow, glow, soft-edge, reflection, blur
807
+ * - **Connectors**: arrow-head types and connection points
808
+ * - **3-D**: scene camera and shape extrusion/bevel
809
+ *
810
+ * All spatial values are stored in **pixels** (pre-converted from EMU).
811
+ * Opacity values are normalised to the 0–1 range.
812
+ *
813
+ * @module pptx-types/shape-style
814
+ */
815
+
816
+ /**
817
+ * Comprehensive visual style for a shape, connector, or image element.
818
+ *
819
+ * All fields are optional. When absent, the element inherits from theme
820
+ * or layout defaults. The interface models both simple styling (solid fill +
821
+ * basic stroke) and advanced effects (multiple shadow layers, gradient
822
+ * fills, 3-D extrusion).
823
+ *
824
+ * @example
825
+ * ```ts
826
+ * // Simple blue filled shape with a thin black outline:
827
+ * const simple: ShapeStyle = {
828
+ * fillColor: "#0055AA",
829
+ * fillMode: "solid",
830
+ * strokeColor: "#000000",
831
+ * strokeWidth: 1,
832
+ * };
833
+ *
834
+ * // Gradient fill with a soft shadow:
835
+ * const fancy: ShapeStyle = {
836
+ * fillMode: "gradient",
837
+ * fillGradientType: "linear",
838
+ * fillGradientAngle: 135,
839
+ * fillGradientStops: [
840
+ * { color: "#FF6B6B", position: 0 },
841
+ * { color: "#556270", position: 1 },
842
+ * ],
843
+ * shadowColor: "#000000",
844
+ * shadowBlur: 10,
845
+ * shadowOffsetX: 4,
846
+ * shadowOffsetY: 4,
847
+ * shadowOpacity: 0.3,
848
+ * };
849
+ * // => both satisfy the ShapeStyle interface
850
+ * ```
851
+ */
852
+ interface ShapeStyle {
853
+ fillColor?: string;
854
+ /**
855
+ * Raw XML colour-choice node preserved from `a:solidFill` for round-trip
856
+ * serialisation. Captures `a:schemeClr` / `a:sysClr` / `a:prstClr` /
857
+ * `a:srgbClr` plus colour transforms (`lumMod`, `lumOff`, `tint`,
858
+ * `shade`, `satMod`, `alpha`, …). On save we re-emit verbatim when the
859
+ * resolved {@link fillColor} still matches this node, otherwise we fall
860
+ * back to canonical `<a:srgbClr>`.
861
+ */
862
+ fillColorXml?: XmlObject;
863
+ fillGradient?: string;
864
+ fillMode?: 'solid' | 'gradient' | 'pattern' | 'none' | 'image' | 'theme' | 'group';
865
+ fillPatternPreset?: string;
866
+ fillPatternBackgroundColor?: string;
867
+ /** Raw XML node for pattern fill foreground colour (preserves color transforms). */
868
+ fillPatternFgClrXml?: XmlObject;
869
+ /** Raw XML node for pattern fill background colour (preserves color transforms). */
870
+ fillPatternBgClrXml?: XmlObject;
871
+ /** Data-URI or URL for image fill (when fillMode === "image"). */
872
+ fillImageUrl?: string;
873
+ /** How the image is sized within the shape: stretch to fill, or tile/repeat. */
874
+ fillImageMode?: 'stretch' | 'tile';
875
+ fillGradientStops?: Array<{
876
+ color: string;
877
+ position: number;
878
+ opacity?: number;
879
+ /** Raw XML colour node preserved for round-trip (e.g. a:schemeClr with transforms). */
880
+ originalColorXml?: XmlObject;
881
+ }>;
882
+ fillGradientAngle?: number;
883
+ fillGradientType?: 'linear' | 'radial';
884
+ /** Path gradient sub-type from `a:path/@path` (e.g. "circle", "rect", "shape"). */
885
+ fillGradientPathType?: 'circle' | 'rect' | 'shape';
886
+ /** Focal point for path (radial) gradients, derived from `a:fillToRect`.
887
+ * Values are 0..1 fractions relative to shape bounds. */
888
+ fillGradientFocalPoint?: {
889
+ x: number;
890
+ y: number;
891
+ };
892
+ /** Raw fillToRect LTRB values (0..1 fractions) from `a:fillToRect`.
893
+ * Defines the inner rectangle where the gradient reaches its final stop.
894
+ * l/t are insets from left/top edges; r/b are insets from right/bottom edges. */
895
+ fillGradientFillToRect?: {
896
+ l: number;
897
+ t: number;
898
+ r: number;
899
+ b: number;
900
+ };
901
+ /** Gradient tile flip mode (`a:gradFill/@flip`).
902
+ * `none` = no tiling flip (default), `x|y|xy` = mirror in the named axis. */
903
+ fillGradientFlip?: 'none' | 'x' | 'y' | 'xy';
904
+ /** Whether the gradient rotates with the shape (`a:gradFill/@rotWithShape`).
905
+ * Defaults to true per the schema; preserved for round-trip when the source
906
+ * authored the attribute explicitly. */
907
+ fillGradientRotWithShape?: boolean;
908
+ /** Whether the linear gradient is scaled to the shape (`a:lin/@scaled`).
909
+ * Defaults to true per the schema; preserved for round-trip. */
910
+ fillGradientScaled?: boolean;
911
+ fillOpacity?: number;
912
+ strokeColor?: string;
913
+ /**
914
+ * Raw XML colour-choice node preserved from `a:ln/a:solidFill` for
915
+ * round-trip serialisation. See {@link fillColorXml} for the rationale.
916
+ */
917
+ strokeColorXml?: XmlObject;
918
+ strokeWidth?: number;
919
+ strokeOpacity?: number;
920
+ strokeDash?: StrokeDashType;
921
+ /** Line join style (`a:ln/@join`): round, bevel, or miter. */
922
+ lineJoin?: 'round' | 'bevel' | 'miter';
923
+ /** Miter limit (`a:miter/@lim`) in EMU-percent units (default 800000 = 8.0). Only meaningful when lineJoin is 'miter'. */
924
+ miterLimit?: number;
925
+ /** Line cap style (`a:ln/@cap`): flat, rnd, or sq. */
926
+ lineCap?: 'flat' | 'rnd' | 'sq';
927
+ /** Compound line type (`a:ln/@cmpd`). */
928
+ compoundLine?: 'sng' | 'dbl' | 'thickThin' | 'thinThick' | 'tri';
929
+ /** Pen line alignment (`a:ln/@algn`): `ctr` (centre, default) or `in` (inside). */
930
+ lineAlignment?: 'ctr' | 'in';
931
+ shadowColor?: string;
932
+ shadowBlur?: number;
933
+ shadowOffsetX?: number;
934
+ shadowOffsetY?: number;
935
+ shadowOpacity?: number;
936
+ /** Preset shadow name from `a:prstShdw/@prst` (e.g. "shdw1"..."shdw20"). */
937
+ presetShadowName?: string;
938
+ /** Shadow angle in degrees (0-360). Parsed from `@_dir` (60000ths of a degree). */
939
+ shadowAngle?: number;
940
+ /** Shadow distance in pixels. Parsed from `@_dist` (EMUs). */
941
+ shadowDistance?: number;
942
+ /** Whether shadow rotates with shape. Parsed from `@_rotWithShape`. */
943
+ shadowRotateWithShape?: boolean;
944
+ /** Outer-shadow horizontal scaling (`a:outerShdw/@sx`) in 1000ths of a percent (default 100000 = 100%). */
945
+ shadowScaleX?: number;
946
+ /** Outer-shadow vertical scaling (`a:outerShdw/@sy`). */
947
+ shadowScaleY?: number;
948
+ /** Outer-shadow horizontal skew (`a:outerShdw/@kx`) in 60000ths of a degree. */
949
+ shadowSkewX?: number;
950
+ /** Outer-shadow vertical skew (`a:outerShdw/@ky`). */
951
+ shadowSkewY?: number;
952
+ /** Outer-shadow alignment (`a:outerShdw/@algn`). */
953
+ shadowAlignment?: 'tl' | 't' | 'tr' | 'l' | 'ctr' | 'r' | 'bl' | 'b' | 'br';
954
+ /** Inner-shadow rotateWithShape (`a:innerShdw/@rotWithShape`). */
955
+ innerShadowRotateWithShape?: boolean;
956
+ /** Reflection fade direction (`a:reflection/@fadeDir`) in 60000ths of a degree. */
957
+ reflectionFadeDirection?: number;
958
+ /** Reflection horizontal scaling (`a:reflection/@sx`). */
959
+ reflectionScaleX?: number;
960
+ /** Reflection vertical scaling (`a:reflection/@sy`). */
961
+ reflectionScaleY?: number;
962
+ /** Reflection horizontal skew (`a:reflection/@kx`). */
963
+ reflectionSkewX?: number;
964
+ /** Reflection vertical skew (`a:reflection/@ky`). */
965
+ reflectionSkewY?: number;
966
+ /** Reflection alignment (`a:reflection/@algn`). */
967
+ reflectionAlignment?: 'tl' | 't' | 'tr' | 'l' | 'ctr' | 'r' | 'bl' | 'b' | 'br';
968
+ /** Reflection rotateWithShape (`a:reflection/@rotWithShape`). */
969
+ reflectionRotateWithShape?: boolean;
970
+ /** Reflection start position (`a:reflection/@stPos`) as 0-1 fraction. */
971
+ reflectionStartPosition?: number;
972
+ /** Multiple shadow layers (for advanced effects). */
973
+ shadows?: ShadowEffect[];
974
+ glowColor?: string;
975
+ glowRadius?: number;
976
+ glowOpacity?: number;
977
+ softEdgeRadius?: number;
978
+ /** Inner shadow colour (`a:innerShdw`). */
979
+ innerShadowColor?: string;
980
+ /** Inner shadow opacity (0-1). */
981
+ innerShadowOpacity?: number;
982
+ /** Inner shadow blur radius in px. */
983
+ innerShadowBlur?: number;
984
+ /** Inner shadow horizontal offset in px. */
985
+ innerShadowOffsetX?: number;
986
+ /** Inner shadow vertical offset in px. */
987
+ innerShadowOffsetY?: number;
988
+ /** Reflection effect — distance from shape bottom in px. */
989
+ reflectionBlurRadius?: number;
990
+ /** Reflection start opacity (0-1). */
991
+ reflectionStartOpacity?: number;
992
+ /** Reflection end opacity (0-1). */
993
+ reflectionEndOpacity?: number;
994
+ /** Reflection end position (0-1 fraction of shape height). */
995
+ reflectionEndPosition?: number;
996
+ /** Reflection direction in degrees. */
997
+ reflectionDirection?: number;
998
+ /** Reflection rotation in degrees (`a:reflection/@rot` in 60000ths). */
999
+ reflectionRotation?: number;
1000
+ /** Reflection distance in px. */
1001
+ reflectionDistance?: number;
1002
+ /** Standalone blur effect radius in px (`a:effectLst > a:blur`). */
1003
+ blurRadius?: number;
1004
+ /** Whether the blur effect grows the bounds of the shape (`a:blur/@grow`). */
1005
+ blurGrow?: boolean;
1006
+ connectorStartArrow?: ConnectorArrowType;
1007
+ /** Start arrow width size ('sm' | 'med' | 'lg'). */
1008
+ connectorStartArrowWidth?: 'sm' | 'med' | 'lg';
1009
+ /** Start arrow length size ('sm' | 'med' | 'lg'). */
1010
+ connectorStartArrowLength?: 'sm' | 'med' | 'lg';
1011
+ connectorEndArrow?: ConnectorArrowType;
1012
+ /** End arrow width size ('sm' | 'med' | 'lg'). */
1013
+ connectorEndArrowWidth?: 'sm' | 'med' | 'lg';
1014
+ /** End arrow length size ('sm' | 'med' | 'lg'). */
1015
+ connectorEndArrowLength?: 'sm' | 'med' | 'lg';
1016
+ /** Connection point for the start of a connector. */
1017
+ connectorStartConnection?: ConnectorConnectionPoint;
1018
+ /** Connection point for the end of a connector. */
1019
+ connectorEndConnection?: ConnectorConnectionPoint;
1020
+ /** Custom dash segments array (`a:custDash/a:ds`). Each entry has dash length and space length in EMU. */
1021
+ customDashSegments?: Array<{
1022
+ dash: number;
1023
+ space: number;
1024
+ }>;
1025
+ /** 3D scene/camera settings from `a:scene3d`. */
1026
+ scene3d?: Pptx3DScene;
1027
+ /** 3D shape extrusion/bevel from `a:sp3d`. */
1028
+ shape3d?: Pptx3DShape;
1029
+ /** Line-level shadow colour from `a:ln/a:effectLst/a:outerShdw`. */
1030
+ lineShadowColor?: string;
1031
+ /** Line-level shadow opacity (0-1). */
1032
+ lineShadowOpacity?: number;
1033
+ /** Line-level shadow blur radius in px. */
1034
+ lineShadowBlur?: number;
1035
+ /** Line-level shadow horizontal offset in px. */
1036
+ lineShadowOffsetX?: number;
1037
+ /** Line-level shadow vertical offset in px. */
1038
+ lineShadowOffsetY?: number;
1039
+ /** Line-level glow colour from `a:ln/a:effectLst/a:glow`. */
1040
+ lineGlowColor?: string;
1041
+ /** Line-level glow radius in px. */
1042
+ lineGlowRadius?: number;
1043
+ /** Line-level glow opacity (0-1). */
1044
+ lineGlowOpacity?: number;
1045
+ /** Raw `a:effectDag` XML node preserved for round-trip serialisation. */
1046
+ effectDagXml?: XmlObject;
1047
+ /** Grayscale flag from effectDag `a:grayscl`. */
1048
+ dagGrayscale?: boolean;
1049
+ /** Bi-level threshold (0-100) from effectDag `a:biLevel`. */
1050
+ dagBiLevel?: number;
1051
+ /** Brightness adjustment (-100 to 100) from effectDag `a:lum/@bright`. */
1052
+ dagLumBrightness?: number;
1053
+ /** Contrast adjustment (-100 to 100) from effectDag `a:lum/@contrast`. */
1054
+ dagLumContrast?: number;
1055
+ /** Hue rotation in degrees (0-360) from effectDag `a:hsl/@hue`. */
1056
+ dagHslHue?: number;
1057
+ /** Saturation adjustment from effectDag `a:hsl/@sat`. */
1058
+ dagHslSaturation?: number;
1059
+ /** Luminance adjustment from effectDag `a:hsl/@lum`. */
1060
+ dagHslLuminance?: number;
1061
+ /** Alpha modulation fixed (0-100) from effectDag `a:alphaModFix`. */
1062
+ dagAlphaModFix?: number;
1063
+ /** Tint hue in degrees from effectDag `a:tint/@hue`. */
1064
+ dagTintHue?: number;
1065
+ /** Tint amount (0-100) from effectDag `a:tint/@amt`. */
1066
+ dagTintAmount?: number;
1067
+ /** Duotone colour pair from effectDag `a:duotone`. */
1068
+ dagDuotone?: {
1069
+ color1: string;
1070
+ color2: string;
1071
+ };
1072
+ /** Fill overlay blend mode from effectDag `a:fillOverlay/@blend`. */
1073
+ dagFillOverlayBlend?: 'over' | 'mult' | 'screen' | 'darken' | 'lighten';
1074
+ /** `<a:lnRef @idx>` — 1-based index into the theme's lnStyleLst. */
1075
+ lnRefIdx?: number;
1076
+ /** Raw XML colour child of `<a:lnRef>` (e.g. `<a:schemeClr>` with transforms). */
1077
+ lnRefColorXml?: XmlObject;
1078
+ /** `<a:fillRef @idx>` — 1-based index into fillStyleLst (1-3) or bgFillStyleLst (1001-1003). */
1079
+ fillRefIdx?: number;
1080
+ /** Raw XML colour child of `<a:fillRef>`. */
1081
+ fillRefColorXml?: XmlObject;
1082
+ /** `<a:effectRef @idx>` — 1-based index into the theme's effectStyleLst. */
1083
+ effectRefIdx?: number;
1084
+ /** Raw XML colour child of `<a:effectRef>`. */
1085
+ effectRefColorXml?: XmlObject;
1086
+ /** `<a:fontRef @idx>` — typically `major`, `minor`, or `none`. */
1087
+ fontRefIdx?: string;
1088
+ /** Raw XML colour child of `<a:fontRef>`. */
1089
+ fontRefColorXml?: XmlObject;
1090
+ }
1091
+
1092
+ /**
1093
+ * Text-related types: rich text styles, bullet metadata, and text segments.
1094
+ *
1095
+ * These types model the contents of `<a:r>`, `<a:rPr>`, `<a:pPr>`,
1096
+ * and `<a:bodyPr>` nodes from the OpenXML Drawing namespace.
1097
+ *
1098
+ * @module pptx-types/text
1099
+ */
1100
+
1101
+ /**
1102
+ * Rich text style properties for a text run or paragraph.
1103
+ *
1104
+ * Combines character-level formatting (font, bold, colour …),
1105
+ * paragraph-level controls (alignment, spacing, indentation), and
1106
+ * body-level properties (autofit, insets, text direction). All
1107
+ * fields are optional — unset properties inherit from layout/master
1108
+ * placeholders or theme defaults.
1109
+ *
1110
+ * @remarks
1111
+ * Font sizes are stored in **points**. Spatial measurements (insets,
1112
+ * margins) are in **pixels** (pre-converted from EMU during parsing).
1113
+ *
1114
+ * @example
1115
+ * ```ts
1116
+ * const heading: TextStyle = {
1117
+ * fontFamily: "Montserrat",
1118
+ * fontSize: 36,
1119
+ * bold: true,
1120
+ * color: "#1A1A2E",
1121
+ * align: "center",
1122
+ * lineSpacing: 1.15,
1123
+ * };
1124
+ *
1125
+ * const body: TextStyle = {
1126
+ * fontFamily: "Open Sans",
1127
+ * fontSize: 14,
1128
+ * color: "#444444",
1129
+ * align: "left",
1130
+ * paragraphSpacingAfter: 8,
1131
+ * };
1132
+ * // => both satisfy the TextStyle interface
1133
+ * ```
1134
+ */
1135
+ interface TextStyle {
1136
+ fontFamily?: string;
1137
+ fontSize?: number;
1138
+ /** When true, renderer should shrink text to fit the shape bounds. */
1139
+ autoFit?: boolean;
1140
+ /** Explicit autofit mode from OOXML body properties.
1141
+ * - 'shrink': `a:spAutoFit` — shrink text on overflow
1142
+ * - 'normal': `a:normAutofit` — normal auto-fit (with optional fontScale)
1143
+ * - 'none': `a:noAutofit` — explicitly no auto-fit (text overflows)
1144
+ * - undefined: no autofit element present (inherit from layout/master)
1145
+ */
1146
+ autoFitMode?: 'shrink' | 'normal' | 'none';
1147
+ /** Font scale percentage for normAutofit (e.g. 0.9 = 90%). Only meaningful when autoFit is true. */
1148
+ autoFitFontScale?: number;
1149
+ /** Line spacing reduction for normAutofit (e.g. 0.2 = reduce by 20%). Only meaningful when autoFit is true. */
1150
+ autoFitLineSpacingReduction?: number;
1151
+ bold?: boolean;
1152
+ italic?: boolean;
1153
+ underline?: boolean;
1154
+ /** Specific underline style (e.g. "sng", "dbl", "wavy"). Falls back to "sng" when `underline` is true. */
1155
+ underlineStyle?: UnderlineStyle;
1156
+ /** Underline colour as hex string (`a:uFill` / `a:uLn`). When absent, inherits text colour. */
1157
+ underlineColor?: string;
1158
+ /**
1159
+ * When true, the source authored `<a:u val="none"/>` to explicitly suppress
1160
+ * underline (rather than omitting the attribute entirely). Preserved so the
1161
+ * writer can re-emit the explicit `none` token instead of dropping it.
1162
+ */
1163
+ underlineExplicitNone?: boolean;
1164
+ /**
1165
+ * Underline line properties parsed from `<a:rPr><a:uLn>` — width, dash
1166
+ * preset, and end caps. Captured as a typed object so the writer can
1167
+ * round-trip the line styling that previously was dropped (only the
1168
+ * solidFill colour was carried before).
1169
+ */
1170
+ underlineLine?: {
1171
+ /** Line width in EMU (raw OOXML) for `a:uLn/@w`. */
1172
+ widthEmu?: number;
1173
+ /** Compound line type (`a:uLn/@cmpd`). */
1174
+ compound?: string;
1175
+ /** Cap style (`a:uLn/@cap`). */
1176
+ cap?: string;
1177
+ /** Pen alignment (`a:uLn/@algn`). */
1178
+ algn?: string;
1179
+ /** Preset dash value (`a:uLn/a:prstDash/@val`). */
1180
+ prstDash?: string;
1181
+ /** Raw `a:uLn/a:headEnd` XML preserved verbatim. */
1182
+ headEndXml?: XmlObject;
1183
+ /** Raw `a:uLn/a:tailEnd` XML preserved verbatim. */
1184
+ tailEndXml?: XmlObject;
1185
+ };
1186
+ /** When `<a:uLnTx/>` is present — underline line follows the text run line. */
1187
+ underlineLineFollowsText?: boolean;
1188
+ /** When `<a:uFillTx/>` is present — underline fill follows the text run fill. */
1189
+ underlineFillFollowsText?: boolean;
1190
+ strikethrough?: boolean;
1191
+ /** Specific strike type: single or double from `a:rPr/@strike`. */
1192
+ strikeType?: 'sngStrike' | 'dblStrike';
1193
+ /** Text outline width in px (`a:rPr > a:ln/@w` in EMU). */
1194
+ textOutlineWidth?: number;
1195
+ /** Text outline colour as hex string (`a:rPr > a:ln > a:solidFill`). */
1196
+ textOutlineColor?: string;
1197
+ /** When true, the text body has no fill (`a:rPr > a:noFill`), producing hollow/outline-only text. */
1198
+ textFillNone?: boolean;
1199
+ /** Superscript/subscript baseline shift as percentage (`a:rPr/@baseline`). Positive = super, negative = sub. */
1200
+ baseline?: number;
1201
+ /** Character spacing in hundredths of a point (`a:rPr/@spc`). */
1202
+ characterSpacing?: number;
1203
+ /** Kerning threshold in hundredths of a point (`a:rPr/@kern`). 0 = none. */
1204
+ kerning?: number;
1205
+ /** Text highlight colour as hex string (`a:highlight`). */
1206
+ highlightColor?: string;
1207
+ /** Text-level gradient fill CSS string (from `a:rPr > a:gradFill`). */
1208
+ textFillGradient?: string;
1209
+ /** Structured gradient stops for text fill round-trip serialization. */
1210
+ textFillGradientStops?: Array<{
1211
+ color: string;
1212
+ position: number;
1213
+ opacity?: number;
1214
+ }>;
1215
+ /** Gradient angle in degrees for text fill round-trip. */
1216
+ textFillGradientAngle?: number;
1217
+ /** Gradient type for text fill round-trip ('linear' | 'radial'). */
1218
+ textFillGradientType?: 'linear' | 'radial';
1219
+ /** Text-level pattern fill preset (from `a:rPr > a:pattFill`). */
1220
+ textFillPattern?: string;
1221
+ /** Text-level pattern foreground colour. */
1222
+ textFillPatternForeground?: string;
1223
+ /** Text-level pattern background colour. */
1224
+ textFillPatternBackground?: string;
1225
+ hyperlink?: string;
1226
+ /** Relationship ID for the hyperlink (`a:hlinkClick/@r:id`) — preserved for round-trip serialization. */
1227
+ hyperlinkRId?: string;
1228
+ /** Hyperlink tooltip text (`a:hlinkClick/@tooltip`). */
1229
+ hyperlinkTooltip?: string;
1230
+ /** Hyperlink action type (`a:hlinkClick/@action`). */
1231
+ hyperlinkAction?: string;
1232
+ /** Whether the hyperlink target is an internal slide jump (targetSlideIndex style). */
1233
+ hyperlinkTargetSlideIndex?: number;
1234
+ color?: string;
1235
+ /**
1236
+ * Raw XML colour-choice node preserved from `a:rPr/a:solidFill` for
1237
+ * round-trip serialisation. Captures `a:schemeClr` / `a:sysClr` /
1238
+ * `a:prstClr` / `a:srgbClr` plus colour transforms. On save we re-emit
1239
+ * verbatim when the resolved {@link color} still matches this node.
1240
+ */
1241
+ colorXml?: XmlObject;
1242
+ align?: 'left' | 'center' | 'right' | 'justify' | 'justLow' | 'dist' | 'thaiDist';
1243
+ vAlign?: 'top' | 'middle' | 'bottom';
1244
+ /** Right-to-left paragraph/run direction (`a:pPr/@rtl`, `a:rPr/@rtl`). */
1245
+ rtl?: boolean;
1246
+ /** Body text direction (`a:bodyPr/@vert`).
1247
+ *
1248
+ * Values map to OOXML `a:bodyPr/@vert` attribute values:
1249
+ * - `"horizontal"` — default horizontal text (`horz`)
1250
+ * - `"vertical"` — standard vertical text, right-to-left columns (`vert`)
1251
+ * - `"vertical270"` — text rotated 270 degrees (`vert270`)
1252
+ * - `"eaVert"` — East Asian vertical text with CJK glyphs upright (`eaVert`)
1253
+ * - `"wordArtVert"` — WordArt vertical, each character upright stacked (`wordArtVert`)
1254
+ * - `"wordArtVertRtl"` — WordArt vertical, right-to-left direction (`wordArtVertRtl`)
1255
+ * - `"mongolianVert"` — Mongolian vertical text, left-to-right columns (`mongolianVert`)
1256
+ */
1257
+ textDirection?: 'horizontal' | 'vertical' | 'vertical270' | 'eaVert' | 'wordArtVert' | 'wordArtVertRtl' | 'mongolianVert';
1258
+ /** Body column count (`a:bodyPr/@numCol`). */
1259
+ columnCount?: number;
1260
+ /** Column spacing in px (`a:bodyPr/@spcCol` in EMU). */
1261
+ columnSpacing?: number;
1262
+ /** Horizontal overflow mode from `a:bodyPr/@hOverflow`. */
1263
+ hOverflow?: 'overflow' | 'clip';
1264
+ /** Vertical overflow mode from `a:bodyPr/@vertOverflow`. */
1265
+ vertOverflow?: 'overflow' | 'clip' | 'ellipsis';
1266
+ /** Body text left inset in px (`a:bodyPr/@lIns` in EMU). */
1267
+ bodyInsetLeft?: number;
1268
+ /** Body text top inset in px (`a:bodyPr/@tIns` in EMU). */
1269
+ bodyInsetTop?: number;
1270
+ /** Body text right inset in px (`a:bodyPr/@rIns` in EMU). */
1271
+ bodyInsetRight?: number;
1272
+ /** Body text bottom inset in px (`a:bodyPr/@bIns` in EMU). */
1273
+ bodyInsetBottom?: number;
1274
+ /** Paragraph spacing before in px. */
1275
+ paragraphSpacingBefore?: number;
1276
+ /** Paragraph spacing after in px. */
1277
+ paragraphSpacingAfter?: number;
1278
+ /** Line spacing multiplier (e.g. 1.2 = 120%). Used when mode is proportional (spcPct). */
1279
+ lineSpacing?: number;
1280
+ /** Exact line spacing in points (from `a:lnSpc > a:spcPts`). Takes priority over `lineSpacing` when set. */
1281
+ lineSpacingExactPt?: number;
1282
+ /** Paragraph left margin in px (`a:pPr/@marL` in EMU). */
1283
+ paragraphMarginLeft?: number;
1284
+ /** Paragraph right margin in px (`a:pPr/@marR` in EMU). */
1285
+ paragraphMarginRight?: number;
1286
+ /** Paragraph first-line indent in px (`a:pPr/@indent` in EMU). */
1287
+ paragraphIndent?: number;
1288
+ /** Tab stop positions and alignments (`a:pPr/a:tabLst/a:tab`). */
1289
+ tabStops?: Array<{
1290
+ position: number;
1291
+ align: 'l' | 'ctr' | 'r' | 'dec';
1292
+ leader?: 'none' | 'dot' | 'hyphen' | 'underscore';
1293
+ }>;
1294
+ /** Body text wrapping mode from `a:bodyPr/@wrap`. */
1295
+ textWrap?: 'square' | 'none';
1296
+ /** Preset text warp type from `a:bodyPr/a:prstTxWarp`. */
1297
+ textWarpPreset?: PptxTextWarpPreset;
1298
+ /** Primary adjustment value for text warp (from `a:prstTxWarp/a:avLst/a:gd` with name "adj").
1299
+ * Stored as raw OOXML 1/60000th units (e.g. 50000 = default for many presets). */
1300
+ textWarpAdj?: number;
1301
+ /** Secondary adjustment value for text warp (from `a:prstTxWarp/a:avLst/a:gd` with name "adj2").
1302
+ * Stored as raw OOXML 1/60000th units. */
1303
+ textWarpAdj2?: number;
1304
+ /** Text capitalization style from `a:rPr/@cap`. */
1305
+ textCaps?: 'all' | 'small' | 'none';
1306
+ /**
1307
+ * When true, the source authored `<a:rPr cap="none"/>` explicitly. This
1308
+ * differs from {@link textCaps} = `"none"` only because the writer must
1309
+ * preserve the explicit token rather than collapse it to omission.
1310
+ */
1311
+ textCapsExplicitNone?: boolean;
1312
+ /** Symbol font family from `a:sym`. */
1313
+ symbolFont?: string;
1314
+ /** East Asian font family from `a:ea`. */
1315
+ eastAsiaFont?: string;
1316
+ /** Complex Script font family from `a:cs`. */
1317
+ complexScriptFont?: string;
1318
+ /** Text language from `a:rPr/@lang`. */
1319
+ language?: string;
1320
+ /** Hyperlink mouse-over target from `a:hlinkMouseOver`. */
1321
+ hyperlinkMouseOver?: string;
1322
+ /** Hyperlink invalidUrl attribute (`a:hlinkClick/@invalidUrl`). */
1323
+ hyperlinkInvalidUrl?: string;
1324
+ /** Hyperlink target frame (`a:hlinkClick/@tgtFrame`). */
1325
+ hyperlinkTargetFrame?: string;
1326
+ /** Whether hyperlink history is tracked (`a:hlinkClick/@history`). */
1327
+ hyperlinkHistory?: boolean;
1328
+ /** Whether hyperlink uses highlight-click effect (`a:hlinkClick/@highlightClick`). */
1329
+ hyperlinkHighlightClick?: boolean;
1330
+ /** Whether hyperlink ends a sound (`a:hlinkClick/@endSnd`). */
1331
+ hyperlinkEndSound?: boolean;
1332
+ /** Kumimoji (ideographic text combining) flag for vertical CJK text (`a:rPr/@kumimoji`). */
1333
+ kumimoji?: boolean;
1334
+ /** Normalize height flag (`a:rPr/@normalizeH`). */
1335
+ normalizeHeight?: boolean;
1336
+ /** No proofing flag (`a:rPr/@noProof`). */
1337
+ noProof?: boolean;
1338
+ /** Dirty flag indicating run has been edited (`a:rPr/@dirty`). */
1339
+ dirty?: boolean;
1340
+ /** Error flag indicating spelling error (`a:rPr/@err`). */
1341
+ spellingError?: boolean;
1342
+ /** Smart tag clean flag (`a:rPr/@smtClean`). */
1343
+ smartTagClean?: boolean;
1344
+ /** Bookmark link target (`a:rPr/@bmk`). */
1345
+ bookmark?: string;
1346
+ /** Alternative language for the run (`a:rPr/@altLang`). Populated for runs
1347
+ * authored in mixed-script documents (e.g. Asian/Latin combined). */
1348
+ altLanguage?: string;
1349
+ /** SmartTag (Office grammar tag) GUID id (`a:rPr/@smtId`). Round-tripped
1350
+ * verbatim — the engine doesn't interpret it. */
1351
+ smartTagId?: number;
1352
+ /** Latin font PANOSE classification string from `a:rPr > a:latin/@panose`. */
1353
+ latinFontPanose?: string;
1354
+ /** Latin font pitch + family flag from `a:rPr > a:latin/@pitchFamily`. */
1355
+ latinFontPitchFamily?: number;
1356
+ /** Latin font character set id from `a:rPr > a:latin/@charset`. */
1357
+ latinFontCharset?: number;
1358
+ /** East-Asian font PANOSE from `a:rPr > a:ea/@panose`. */
1359
+ eastAsiaFontPanose?: string;
1360
+ /** East-Asian font pitch + family flag from `a:rPr > a:ea/@pitchFamily`. */
1361
+ eastAsiaFontPitchFamily?: number;
1362
+ /** East-Asian font character set id from `a:rPr > a:ea/@charset`. */
1363
+ eastAsiaFontCharset?: number;
1364
+ /** Complex-script font PANOSE from `a:rPr > a:cs/@panose`. */
1365
+ complexScriptFontPanose?: string;
1366
+ /** Complex-script font pitch + family flag from `a:rPr > a:cs/@pitchFamily`. */
1367
+ complexScriptFontPitchFamily?: number;
1368
+ /** Complex-script font character set id from `a:rPr > a:cs/@charset`. */
1369
+ complexScriptFontCharset?: number;
1370
+ /** Symbol-font PANOSE from `a:rPr > a:sym/@panose`. */
1371
+ symbolFontPanose?: string;
1372
+ /** Symbol-font pitch + family flag from `a:rPr > a:sym/@pitchFamily`. */
1373
+ symbolFontPitchFamily?: number;
1374
+ /** Symbol-font character set id from `a:rPr > a:sym/@charset`. */
1375
+ symbolFontCharset?: number;
1376
+ /** Paragraph list type for toggling bullet / numbered lists via the toolbar.
1377
+ * - `'bullet'` — character bullet (default "•")
1378
+ * - `'numbered'` — auto-numbered list (arabicPeriod)
1379
+ * - `'none'` — explicitly no list
1380
+ */
1381
+ listType?: 'bullet' | 'numbered' | 'none';
1382
+ /** Default tab size in px (`a:pPr/@defTabSz` in EMU). */
1383
+ defaultTabSize?: number;
1384
+ /** East Asian line break flag (`a:pPr/@eaLnBrk`). */
1385
+ eaLineBreak?: boolean;
1386
+ /** Latin line break flag (`a:pPr/@latinLnBrk`). */
1387
+ latinLineBreak?: boolean;
1388
+ /** Font alignment (`a:pPr/@fontAlgn`): 'auto' | 'base' | 'ctr' | 't' | 'b'. */
1389
+ fontAlignment?: string;
1390
+ /** Hanging punctuation flag (`a:pPr/@hangingPunct`). */
1391
+ hangingPunctuation?: boolean;
1392
+ /** Whether to space first and last paragraph from body edges (`a:bodyPr/@spcFirstLastPara`). */
1393
+ spaceFirstLastParagraph?: boolean;
1394
+ /** Right-to-left column flow (`a:bodyPr/@rtlCol`). */
1395
+ rtlColumns?: boolean;
1396
+ /** Whether text originates from WordArt (`a:bodyPr/@fromWordArt`). */
1397
+ fromWordArt?: boolean;
1398
+ /** Whether text anchoring is centered (`a:bodyPr/@anchorCtr`). */
1399
+ anchorCenter?: boolean;
1400
+ /** Force anti-aliasing (`a:bodyPr/@forceAA`). */
1401
+ forceAntiAlias?: boolean;
1402
+ /** Upright text in 3D views (`a:bodyPr/@upright`). */
1403
+ upright?: boolean;
1404
+ /** Compatible line spacing flag (`a:bodyPr/@compatLnSpc`). */
1405
+ compatibleLineSpacing?: boolean;
1406
+ /**
1407
+ * Text body rotation in **degrees** (`a:bodyPr/@rot`).
1408
+ *
1409
+ * OOXML stores the value as 60000ths of a degree. Positive values rotate
1410
+ * the body clockwise. When undefined, the attribute is omitted on save
1411
+ * (PowerPoint treats absent `rot` as inherit/none).
1412
+ */
1413
+ textBodyRotation?: number;
1414
+ /** Text shadow colour as hex string (`a:outerShdw`). */
1415
+ textShadowColor?: string;
1416
+ /** Text shadow blur radius in px. */
1417
+ textShadowBlur?: number;
1418
+ /** Text shadow horizontal offset in px. */
1419
+ textShadowOffsetX?: number;
1420
+ /** Text shadow vertical offset in px. */
1421
+ textShadowOffsetY?: number;
1422
+ /** Text shadow opacity (0-1). */
1423
+ textShadowOpacity?: number;
1424
+ /** Text inner shadow colour (`a:innerShdw`). */
1425
+ textInnerShadowColor?: string;
1426
+ /** Text inner shadow opacity (0-1). */
1427
+ textInnerShadowOpacity?: number;
1428
+ /** Text inner shadow blur radius in px. */
1429
+ textInnerShadowBlur?: number;
1430
+ /** Text inner shadow horizontal offset in px. */
1431
+ textInnerShadowOffsetX?: number;
1432
+ /** Text inner shadow vertical offset in px. */
1433
+ textInnerShadowOffsetY?: number;
1434
+ /** Preset shadow type from `a:prstShdw/@prst` (e.g. "shdw1"..."shdw20"). */
1435
+ textPresetShadowName?: string;
1436
+ /** Preset shadow colour as hex string. */
1437
+ textPresetShadowColor?: string;
1438
+ /** Preset shadow opacity (0-1). */
1439
+ textPresetShadowOpacity?: number;
1440
+ /** Preset shadow distance in px. */
1441
+ textPresetShadowDistance?: number;
1442
+ /** Preset shadow direction in degrees. */
1443
+ textPresetShadowDirection?: number;
1444
+ /** Text blur effect radius in px (`a:blur`). */
1445
+ textBlurRadius?: number;
1446
+ /** Text alpha modulation fixed (0-100) from `a:alphaModFix`. */
1447
+ textAlphaModFix?: number;
1448
+ /** Text alpha modulation from `a:alphaMod` (0-100 percentage). */
1449
+ textAlphaMod?: number;
1450
+ /** Text hue shift in degrees from `a:hsl/@hue`. */
1451
+ textHslHue?: number;
1452
+ /** Text saturation adjustment from `a:hsl/@sat`. */
1453
+ textHslSaturation?: number;
1454
+ /** Text luminance adjustment from `a:hsl/@lum`. */
1455
+ textHslLuminance?: number;
1456
+ /** Text colour change from colour as hex string (`a:clrChange`). */
1457
+ textClrChangeFrom?: string;
1458
+ /** Text colour change to colour as hex string. */
1459
+ textClrChangeTo?: string;
1460
+ /** Text duotone colour pair (`a:duotone`). */
1461
+ textDuotone?: {
1462
+ color1: string;
1463
+ color2: string;
1464
+ };
1465
+ /** Text glow colour as hex string (`a:glow`). */
1466
+ textGlowColor?: string;
1467
+ /** Text glow radius in px. */
1468
+ textGlowRadius?: number;
1469
+ /** Text glow opacity (0-1). */
1470
+ textGlowOpacity?: number;
1471
+ /** Text reflection enabled flag. */
1472
+ textReflection?: boolean;
1473
+ /** Text reflection blur radius in px. */
1474
+ textReflectionBlur?: number;
1475
+ /** Text reflection start opacity (0-1). */
1476
+ textReflectionStartOpacity?: number;
1477
+ /** Text reflection end opacity (0-1). */
1478
+ textReflectionEndOpacity?: number;
1479
+ /** Text reflection offset distance in px. */
1480
+ textReflectionOffset?: number;
1481
+ /** 3D extrusion/bevel settings on the text body. */
1482
+ text3d?: Text3DStyle;
1483
+ /** 3D scene (camera + light rig) settings on the text body (`a:bodyPr/a:scene3d`). */
1484
+ textBodyScene3d?: Pptx3DScene;
1485
+ /**
1486
+ * Raw `<a:extLst>` subtree captured from `<a:bodyPr>`. Preserved verbatim so
1487
+ * authored extensions (e.g. content placeholders, custom application data)
1488
+ * survive a round-trip even though the engine doesn't interpret them.
1489
+ */
1490
+ bodyPropertiesExtLstXml?: XmlObject;
1491
+ /**
1492
+ * Raw `<a:extLst>` subtree captured from `<a:pPr>`. Only meaningful on the
1493
+ * paragraph-level style (paragraphs propagate this via the first segment).
1494
+ */
1495
+ paragraphPropertiesExtLstXml?: XmlObject;
1496
+ /**
1497
+ * Raw `<a:extLst>` subtree captured from `<a:rPr>`. Persisted verbatim on
1498
+ * save when present — covers run-level extensions the typed model doesn't
1499
+ * model (e.g. `a14:hiddenFill` and similar).
1500
+ */
1501
+ runPropertiesExtLstXml?: XmlObject;
1502
+ /**
1503
+ * Raw `<a:defRPr>` XML node captured from `<a:pPr>`. The schema permits
1504
+ * `defRPr` directly inside `pPr` so that paragraph defaults can specify the
1505
+ * end-paragraph run formatting; previously this was dropped on save. We
1506
+ * persist the parsed XML object so it round-trips verbatim.
1507
+ *
1508
+ * Only meaningful on the *first* segment of each paragraph (matches the
1509
+ * convention used for {@link bulletInfo} / {@link endParaRunProperties}).
1510
+ */
1511
+ paragraphDefaultRunPropertiesXml?: XmlObject;
1512
+ }
1513
+ /**
1514
+ * Structured bullet metadata attached to the first {@link TextSegment}
1515
+ * of each paragraph.
1516
+ *
1517
+ * Describes how the paragraph bullet should render: character bullets
1518
+ * (`char`), auto-numbered lists (`autoNumType`), or picture bullets
1519
+ * (`imageRelId` / `imageDataUrl`). Set `none: true` when `a:buNone`
1520
+ * explicitly suppresses the bullet.
1521
+ *
1522
+ * @example
1523
+ * ```ts
1524
+ * // Simple character bullet:
1525
+ * const bullet: BulletInfo = { char: "•", color: "#333333" };
1526
+ *
1527
+ * // Auto-numbered list starting at 1:
1528
+ * const numbered: BulletInfo = {
1529
+ * autoNumType: "arabicPeriod",
1530
+ * autoNumStartAt: 1,
1531
+ * };
1532
+ * // => { char: "•", color: "#333333" } and { autoNumType: "arabicPeriod", autoNumStartAt: 1 }
1533
+ * ```
1534
+ */
1535
+ interface BulletInfo {
1536
+ /** Bullet character (e.g. "•", "-", "»") from `a:buChar`. */
1537
+ char?: string;
1538
+ /** Auto-numbering type (e.g. "arabicPeriod", "romanUcPeriod") from `a:buAutoNum`. */
1539
+ autoNumType?: string;
1540
+ /** Auto-numbering start value. */
1541
+ autoNumStartAt?: number;
1542
+ /** Zero-based paragraph index within the text body (for auto-numbering). */
1543
+ paragraphIndex?: number;
1544
+ /** Bullet font family from `a:buFont`. */
1545
+ fontFamily?: string;
1546
+ /** Bullet size as percentage of text font size from `a:buSzPct`. */
1547
+ sizePercent?: number;
1548
+ /** Bullet size in points from `a:buSzPts`. */
1549
+ sizePts?: number;
1550
+ /** Bullet color as hex string from `a:buClr`. */
1551
+ color?: string;
1552
+ /**
1553
+ * Raw colour-choice XML captured from `<a:buClr>` so that themed bullets
1554
+ * (`a:schemeClr`, `a:sysClr`, `a:prstClr`) round-trip with their original
1555
+ * identity rather than being flattened to `<a:srgbClr/>` on save.
1556
+ */
1557
+ colorXml?: XmlObject;
1558
+ /** True when `a:buNone` explicitly suppresses bullets. */
1559
+ none?: boolean;
1560
+ /** Picture bullet: relationship ID from `a:buBlip` → `a:blip[@r:embed]`. */
1561
+ imageRelId?: string;
1562
+ /** Picture bullet: data URL of the embedded image. */
1563
+ imageDataUrl?: string;
1564
+ /**
1565
+ * Raw `<a:buBlip>` XML captured at parse time. Carries the full blipFill
1566
+ * subtree (`a:tile`, `a:stretch`, `a:srcRect`, `a:blip > a:extLst`) so the
1567
+ * writer can emit the complete original definition rather than the bare
1568
+ * `a:blip[@r:embed]` mapping. When set, the writer prefers it over
1569
+ * {@link imageRelId} for emission.
1570
+ */
1571
+ imageBlipFillXml?: XmlObject;
1572
+ /** When true, `<a:buFontTx/>` was specified — inherit the bullet font from
1573
+ * the run text, not from a buFont declaration. */
1574
+ fontInherit?: boolean;
1575
+ /** When true, `<a:buClrTx/>` was specified — inherit the bullet colour from
1576
+ * the run text. */
1577
+ colorInherit?: boolean;
1578
+ /** When true, `<a:buSzTx/>` was specified — inherit the bullet size from
1579
+ * the run text font size. */
1580
+ sizeInherit?: boolean;
1581
+ }
1582
+ /**
1583
+ * A single text run within a paragraph.
1584
+ *
1585
+ * A text body is decomposed into an array of `TextSegment` objects,
1586
+ * each with its own style. Paragraph breaks are represented as
1587
+ * segments with `isParagraphBreak: true`.
1588
+ *
1589
+ * @example
1590
+ * ```ts
1591
+ * const segments: TextSegment[] = [
1592
+ * { text: "Bold intro ", style: { bold: true, fontSize: 16 } },
1593
+ * { text: "and normal text.", style: { fontSize: 16 } },
1594
+ * { text: "", style: {}, isParagraphBreak: true },
1595
+ * { text: "Second paragraph.", style: { fontSize: 14 } },
1596
+ * ];
1597
+ * // => 4 segments: 2 styled runs, 1 paragraph break, 1 normal run
1598
+ * ```
1599
+ */
1600
+ interface TextSegment {
1601
+ text: string;
1602
+ style: TextStyle;
1603
+ /** When this segment originated from an `a:fld` element, stores the field type (e.g. "slidenum", "datetime"). */
1604
+ fieldType?: string;
1605
+ /** When this segment originated from an `a:fld` element, stores the field GUID. */
1606
+ fieldGuid?: string;
1607
+ /**
1608
+ * Original attribute name used to author the field GUID — `'uuid'` for the
1609
+ * `a:fld/@uuid` form authored by some legacy producers, `'id'` for the
1610
+ * canonical `a:fld/@id` form. Preserved so the writer round-trips whichever
1611
+ * spelling the source used (PowerPoint accepts both). Defaults to `'id'`
1612
+ * on save when undefined.
1613
+ */
1614
+ fieldGuidAttr?: 'uuid' | 'id';
1615
+ /**
1616
+ * Raw per-field paragraph properties (`a:fld > a:pPr`). The schema permits
1617
+ * `pPr` inside an `a:fld` so the field can carry its own paragraph-level
1618
+ * formatting; preserved verbatim on save when present.
1619
+ */
1620
+ fieldParagraphPropertiesXml?: XmlObject;
1621
+ /** Raw OMML XML node for equation segments (from `a14:m` / `m:oMathPara`). */
1622
+ equationXml?: Record<string, unknown>;
1623
+ /**
1624
+ * Optional equation number for numbered equations (e.g. "(1)", "(2.3)").
1625
+ * When present, the equation is rendered centered with the number right-aligned.
1626
+ */
1627
+ equationNumber?: string;
1628
+ /** Whether this segment represents a paragraph break rather than renderable text. */
1629
+ isParagraphBreak?: boolean;
1630
+ /**
1631
+ * Whether this segment represents a soft line break (`a:br`) rather than
1632
+ * a paragraph terminator. Soft line breaks remain inside the same paragraph
1633
+ * but force a line wrap and may carry their own run properties.
1634
+ *
1635
+ * The renderer should treat the segment text as `"\n"` when present.
1636
+ */
1637
+ isLineBreak?: true;
1638
+ /**
1639
+ * Raw `a:rPr` XML for an `a:br` (soft line break) segment, captured verbatim
1640
+ * during parse so the writer can re-emit attributes/colours/fonts that the
1641
+ * typed model doesn't represent. Only meaningful when {@link isLineBreak}
1642
+ * is `true`.
1643
+ */
1644
+ breakRunProperties?: Record<string, unknown>;
1645
+ /** Structured bullet info for the first segment of a paragraph. */
1646
+ bulletInfo?: BulletInfo;
1647
+ /**
1648
+ * Outline level for the paragraph this segment starts (`a:p/@lvl`).
1649
+ *
1650
+ * Only meaningful on the first segment of a paragraph (matching the
1651
+ * convention used for {@link bulletInfo}). Stored as the raw OOXML
1652
+ * value (0 = top level, 1-8 = nested) and serialised back when non-zero.
1653
+ */
1654
+ paragraphLevel?: number;
1655
+ /**
1656
+ * Raw `a:endParaRPr` XML node for the paragraph this segment starts.
1657
+ *
1658
+ * Captured verbatim on parse so attributes and child colours/fonts that
1659
+ * the typed model doesn't represent survive a round-trip. Only meaningful
1660
+ * on the first segment of a paragraph.
1661
+ */
1662
+ endParaRunProperties?: Record<string, unknown>;
1663
+ /**
1664
+ * Phonetic annotation text from `a:ruby > a:rt` (e.g. furigana, pinyin).
1665
+ * When present, the renderer should wrap the base text with an HTML `<ruby>` tag.
1666
+ */
1667
+ rubyText?: string;
1668
+ /**
1669
+ * Ruby text alignment from `a:rubyPr > @val` attribute.
1670
+ * Values: "ctr" (center), "l" (left), "r" (right), "dist" (distribute), "distCat", "distLetter".
1671
+ * @default "ctr"
1672
+ */
1673
+ rubyAlignment?: string;
1674
+ /**
1675
+ * Ruby text font size as a percentage of the base text font size
1676
+ * from `a:rubyPr/@hps` (half-point size) or inferred from rt run font size.
1677
+ * Stored in **points** for consistency with `TextStyle.fontSize`.
1678
+ */
1679
+ rubyFontSize?: number;
1680
+ /**
1681
+ * Style for the ruby (phonetic) text run, parsed from `a:rt > a:r > a:rPr`.
1682
+ * Used by the renderer to apply font family, colour, etc. to the `<rt>` element.
1683
+ */
1684
+ rubyStyle?: TextStyle;
1685
+ }
1686
+
1687
+ /**
1688
+ * Base and mixin interfaces for all PPTX slide elements, plus
1689
+ * placeholder inheritance types.
1690
+ *
1691
+ * Every concrete element variant (text, shape, image …) extends
1692
+ * {@link PptxElementBase}. Text-bearing elements also mix in
1693
+ * {@link PptxTextProperties}, and shapes / connectors / images add
1694
+ * {@link PptxShapeProperties}.
1695
+ *
1696
+ * @module pptx-types/element-base
1697
+ */
1698
+
1699
+ /**
1700
+ * Properties shared by **every** element on a slide.
1701
+ *
1702
+ * Position and size are in pixels (converted from EMU at parse time).
1703
+ * Optional properties apply to subsets of elements or may be absent in
1704
+ * the original OOXML.
1705
+ *
1706
+ * @example
1707
+ * ```ts
1708
+ * const base: PptxElementBase = {
1709
+ * id: "el_001",
1710
+ * x: 100, y: 50,
1711
+ * width: 400, height: 200,
1712
+ * rotation: 15,
1713
+ * opacity: 0.9,
1714
+ * };
1715
+ * // => satisfies PptxElementBase
1716
+ * ```
1717
+ */
1718
+ interface PptxElementBase {
1719
+ id: string;
1720
+ /**
1721
+ * The shape's native OOXML id from `p:cNvPr/@id` (an unsigned integer, as a
1722
+ * string), captured on load. Distinct from {@link id}, which is a synthetic
1723
+ * positional identity (`${slidePath}-shape-${index}`) the loader assigns for
1724
+ * selection / undo / template tracking. Animations target shapes by this
1725
+ * native id (`p:spTgt/@spid`), so it is the stable key used to reconcile an
1726
+ * animation to the element it animates across a save/reload round trip.
1727
+ * Absent on SDK-created elements until one is minted at save time.
1728
+ */
1729
+ shapeId?: string;
1730
+ /** Element name from `cNvPr/@name`. Used for morph transition matching via the `!!` naming convention. */
1731
+ name?: string;
1732
+ x: number;
1733
+ y: number;
1734
+ width: number;
1735
+ height: number;
1736
+ rotation?: number;
1737
+ /** Skew along the X axis in degrees (parsed from `@_skewX` in 1/60000ths of a degree). */
1738
+ skewX?: number;
1739
+ /** Skew along the Y axis in degrees (parsed from `@_skewY` in 1/60000ths of a degree). */
1740
+ skewY?: number;
1741
+ flipHorizontal?: boolean;
1742
+ flipVertical?: boolean;
1743
+ /** Whether this element is hidden (used by the Elements Panel visibility toggle). */
1744
+ hidden?: boolean;
1745
+ /** Element-level opacity (0-1). */
1746
+ opacity?: number;
1747
+ rawXml?: XmlObject;
1748
+ /** Shape-level click action (from `a:hlinkClick` on `p:cNvPr`). */
1749
+ actionClick?: PptxAction;
1750
+ /** Shape-level hover action (from `a:hlinkHover` on `p:cNvPr`). */
1751
+ actionHover?: PptxAction;
1752
+ /** Shape lock attributes parsed from `p:cNvSpPr/a:spLocks`. */
1753
+ locks?: PptxShapeLocks;
1754
+ /**
1755
+ * Opaque `<a:ext>` children captured from the shape's `<a:extLst>` whose
1756
+ * URI is not recognised by a typed extractor (hidden fill/line, image
1757
+ * effects, …). Preserved verbatim and re-emitted on save so unknown
1758
+ * vendor extensions survive a round-trip.
1759
+ *
1760
+ * Mirrors the existing `effectDagXml` / `endParaRunProperties` raw-XML
1761
+ * preservation pattern.
1762
+ */
1763
+ extLstXml?: XmlObject[];
1764
+ }
1765
+ /**
1766
+ * Text content mixin — present on text boxes and shapes.
1767
+ *
1768
+ * Shapes can contain text overlaid on the shape geometry, so both
1769
+ * `TextPptxElement` and `ShapePptxElement` extend this interface.
1770
+ *
1771
+ * @example
1772
+ * ```ts
1773
+ * const props: PptxTextProperties = {
1774
+ * text: "Hello World",
1775
+ * textStyle: { fontSize: 24, bold: true, color: "#333333" },
1776
+ * };
1777
+ * // => satisfies PptxTextProperties
1778
+ * ```
1779
+ */
1780
+ interface PptxTextProperties {
1781
+ text?: string;
1782
+ textStyle?: TextStyle;
1783
+ /** Rich text segments with individual styling. */
1784
+ textSegments?: TextSegment[];
1785
+ /** Per-paragraph indentation (marginLeft, indent) for multi-level bullet support. */
1786
+ paragraphIndents?: Array<{
1787
+ marginLeft?: number;
1788
+ indent?: number;
1789
+ }>;
1790
+ /** Placeholder prompt text inherited from layout/master (e.g. "Click to add title"). Shown as a greyed-out hint when the shape has no user-entered text. */
1791
+ promptText?: string;
1792
+ /** Linked text box chain ID from `a:bodyPr > a:linkedTxbx/@id` or `a:txbx > a:linkedTxbx/@id`. Text overflows from one linked frame to the next. */
1793
+ linkedTxbxId?: number;
1794
+ /** Sequence number within a linked text box chain (0-based). */
1795
+ linkedTxbxSeq?: number;
1796
+ }
1797
+ /**
1798
+ * Shape styling & geometry mixin — present on shapes, connectors, and images.
1799
+ *
1800
+ * @example
1801
+ * ```ts
1802
+ * const props: PptxShapeProperties = {
1803
+ * shapeType: "roundRect",
1804
+ * shapeStyle: { fillColor: "#0055AA", strokeWidth: 2 },
1805
+ * shapeAdjustments: { adj: 16667 },
1806
+ * };
1807
+ * // => satisfies PptxShapeProperties
1808
+ * ```
1809
+ */
1810
+ interface PptxShapeProperties {
1811
+ shapeStyle?: ShapeStyle;
1812
+ /** Preset geometry name, e.g. "rect", "ellipse", "roundRect". */
1813
+ shapeType?: string;
1814
+ /** Geometry adjustment values, e.g. `{ adj: 16667 }`. */
1815
+ shapeAdjustments?: Record<string, number>;
1816
+ /** Adjustment handles for interactive shape modification (yellow diamond handles). */
1817
+ adjustmentHandles?: GeometryAdjustmentHandle[];
1818
+ }
1819
+
1820
+ /**
1821
+ * Chart types: chart categories, series data, style metadata, data tables,
1822
+ * trendlines, error bars, and the composite `PptxChartData`.
1823
+ *
1824
+ * @module pptx-types/chart
1825
+ */
1826
+ /**
1827
+ * Supported chart type discriminators.
1828
+ *
1829
+ * @example
1830
+ * ```ts
1831
+ * const type: PptxChartType = "bar";
1832
+ * // => "bar" — one of: "bar" | "line" | "pie" | "doughnut" | "area" | "scatter" | …
1833
+ * ```
1834
+ */
1835
+ type PptxChartType = 'bar' | 'line' | 'pie' | 'ofPie' | 'doughnut' | 'area' | 'scatter' | 'bubble' | 'radar' | 'stock' | 'bar3D' | 'line3D' | 'pie3D' | 'area3D' | 'surface' | 'histogram' | 'waterfall' | 'funnel' | 'treemap' | 'sunburst' | 'boxWhisker' | 'regionMap' | 'combo' | 'unknown';
1836
+ /**
1837
+ * Supported trendline regression types.
1838
+ *
1839
+ * @example
1840
+ * ```ts
1841
+ * const type: PptxChartTrendlineType = "linear";
1842
+ * // => "linear" — one of: "linear" | "exponential" | "logarithmic" | "polynomial" | "power" | "movingAvg"
1843
+ * ```
1844
+ */
1845
+ type PptxChartTrendlineType = 'linear' | 'exponential' | 'logarithmic' | 'polynomial' | 'power' | 'movingAvg';
1846
+ /**
1847
+ * Configuration for a chart trendline (regression line).
1848
+ *
1849
+ * @example
1850
+ * ```ts
1851
+ * const trendline: PptxChartTrendline = {
1852
+ * trendlineType: "linear",
1853
+ * displayEq: true,
1854
+ * displayRSq: true,
1855
+ * color: "#FF0000",
1856
+ * };
1857
+ * // => satisfies PptxChartTrendline
1858
+ * ```
1859
+ */
1860
+ interface PptxChartTrendline {
1861
+ trendlineType: PptxChartTrendlineType;
1862
+ order?: number;
1863
+ period?: number;
1864
+ forward?: number;
1865
+ backward?: number;
1866
+ intercept?: number;
1867
+ displayRSq?: boolean;
1868
+ displayEq?: boolean;
1869
+ color?: string;
1870
+ }
1871
+ /** Error-bar direction axis. */
1872
+ type PptxChartErrBarDir = 'x' | 'y';
1873
+ /** Error-bar display type (both sides, negative only, or positive only). */
1874
+ type PptxChartErrBarType = 'both' | 'minus' | 'plus';
1875
+ /**
1876
+ * How the error-bar value is calculated.
1877
+ *
1878
+ * @example
1879
+ * ```ts
1880
+ * const valType: PptxChartErrValType = "percentage";
1881
+ * // => "percentage" — one of: "cust" | "fixedVal" | "percentage" | "stdDev" | "stdErr"
1882
+ * ```
1883
+ */
1884
+ type PptxChartErrValType = 'cust' | 'fixedVal' | 'percentage' | 'stdDev' | 'stdErr';
1885
+ /**
1886
+ * Error bars for a chart series.
1887
+ *
1888
+ * @example
1889
+ * ```ts
1890
+ * const bars: PptxChartErrBars = {
1891
+ * direction: "y",
1892
+ * barType: "both",
1893
+ * valType: "percentage",
1894
+ * val: 5,
1895
+ * };
1896
+ * // => satisfies PptxChartErrBars
1897
+ * ```
1898
+ */
1899
+ interface PptxChartErrBars {
1900
+ direction: PptxChartErrBarDir;
1901
+ barType: PptxChartErrBarType;
1902
+ valType: PptxChartErrValType;
1903
+ val?: number;
1904
+ customPlus?: number[];
1905
+ customMinus?: number[];
1906
+ }
1907
+ /**
1908
+ * Visibility flags for the chart data table (axes + legend keys).
1909
+ *
1910
+ * @example
1911
+ * ```ts
1912
+ * const dt: PptxChartDataTable = {
1913
+ * showHorzBorder: true,
1914
+ * showVertBorder: true,
1915
+ * showOutline: true,
1916
+ * showKeys: true,
1917
+ * };
1918
+ * // => satisfies PptxChartDataTable
1919
+ * ```
1920
+ */
1921
+ interface PptxChartDataTable {
1922
+ showHorzBorder?: boolean;
1923
+ showVertBorder?: boolean;
1924
+ showOutline?: boolean;
1925
+ showKeys?: boolean;
1926
+ }
1927
+ /**
1928
+ * Line appearance for chart helper lines (drop lines, hi-low lines).
1929
+ *
1930
+ * @example
1931
+ * ```ts
1932
+ * const style: PptxChartLineStyle = {
1933
+ * color: "#AAAAAA",
1934
+ * width: 1,
1935
+ * dashStyle: "dash",
1936
+ * };
1937
+ * // => satisfies PptxChartLineStyle
1938
+ * ```
1939
+ */
1940
+ interface PptxChartLineStyle {
1941
+ color?: string;
1942
+ width?: number;
1943
+ dashStyle?: string;
1944
+ }
1945
+ /** Marker symbol types for line/scatter chart data points. */
1946
+ type PptxChartMarkerSymbol = 'circle' | 'dash' | 'diamond' | 'dot' | 'none' | 'picture' | 'plus' | 'square' | 'star' | 'triangle' | 'x' | 'auto';
1947
+ /** Shape properties extracted from c:spPr for chart formatting. */
1948
+ interface PptxChartShapeProps {
1949
+ fillColor?: string;
1950
+ strokeColor?: string;
1951
+ strokeWidth?: number;
1952
+ /** Line dash style (a:prstDash/@val), e.g. 'solid', 'dash', 'dot', 'lgDash'. */
1953
+ strokeDashStyle?: string;
1954
+ }
1955
+ /** Marker appearance on a chart series or data point. */
1956
+ interface PptxChartMarker {
1957
+ symbol: PptxChartMarkerSymbol;
1958
+ size?: number;
1959
+ spPr?: PptxChartShapeProps;
1960
+ }
1961
+ /** Per-data-point formatting override (c:dPt). */
1962
+ interface PptxChartDataPoint {
1963
+ idx: number;
1964
+ spPr?: PptxChartShapeProps;
1965
+ explosion?: number;
1966
+ invertIfNegative?: boolean;
1967
+ marker?: PptxChartMarker;
1968
+ }
1969
+ /** Individual data label override (c:dLbl). */
1970
+ interface PptxChartDataLabel {
1971
+ idx: number;
1972
+ showVal?: boolean;
1973
+ showCatName?: boolean;
1974
+ showSerName?: boolean;
1975
+ showPercent?: boolean;
1976
+ showLegendKey?: boolean;
1977
+ showBubbleSize?: boolean;
1978
+ position?: string;
1979
+ text?: string;
1980
+ }
1981
+ /** Axis number format. */
1982
+ interface PptxChartAxisNumFmt {
1983
+ formatCode: string;
1984
+ sourceLinked?: boolean;
1985
+ }
1986
+ /** Axis formatting for category, value, or date axes. */
1987
+ interface PptxChartAxisFormatting {
1988
+ axisType: 'catAx' | 'valAx' | 'dateAx' | 'serAx';
1989
+ /** Axis position: "b" (bottom), "l" (left), "r" (right), "t" (top). */
1990
+ axPos?: 'b' | 'l' | 'r' | 't';
1991
+ /** Unique axis identifier (c:axId/@val) used to link series to axes. */
1992
+ axisId?: number;
1993
+ /** Cross-axis identifier — the axis this axis crosses. */
1994
+ crossAxisId?: number;
1995
+ numFmt?: PptxChartAxisNumFmt;
1996
+ titleText?: string;
1997
+ spPr?: PptxChartShapeProps;
1998
+ fontFamily?: string;
1999
+ fontSize?: number;
2000
+ fontBold?: boolean;
2001
+ fontColor?: string;
2002
+ /** Whether major gridlines are present (`c:majorGridlines`). */
2003
+ majorGridlines?: boolean;
2004
+ /** Whether minor gridlines are present (`c:minorGridlines`). */
2005
+ minorGridlines?: boolean;
2006
+ majorGridlinesSpPr?: PptxChartShapeProps;
2007
+ minorGridlinesSpPr?: PptxChartShapeProps;
2008
+ /** Minimum axis value override (c:min/@val). */
2009
+ min?: number;
2010
+ /** Maximum axis value override (c:max/@val). */
2011
+ max?: number;
2012
+ /** Whether the axis is deleted/hidden (c:delete/@val). */
2013
+ deleted?: boolean;
2014
+ /**
2015
+ * Display units for value axis (c:dispUnits/c:builtInUnit/@val).
2016
+ * When set to 'custom', the actual divisor is in {@link displayUnitsValue}.
2017
+ */
2018
+ displayUnits?: 'hundreds' | 'thousands' | 'tenThousands' | 'hundredThousands' | 'millions' | 'tenMillions' | 'hundredMillions' | 'billions' | 'trillions' | 'custom';
2019
+ /** Custom display unit divisor value (c:dispUnits/c:custUnit/@val). Only used when displayUnits is 'custom'. */
2020
+ displayUnitsValue?: number;
2021
+ /** Display units label text (c:dispUnits/c:dispUnitsLbl). Overrides the built-in default label when present. */
2022
+ displayUnitsLabel?: string;
2023
+ /** Whether logarithmic scaling is enabled (presence of c:scaling/c:logBase). */
2024
+ logScale?: boolean;
2025
+ /** Logarithmic base value (c:scaling/c:logBase/@val), typically 10 or e. */
2026
+ logBase?: number;
2027
+ /** Major-unit interval between primary tick marks (c:majorUnit/@val). */
2028
+ majorUnit?: number;
2029
+ /** Minor-unit interval between secondary tick marks (c:minorUnit/@val). */
2030
+ minorUnit?: number;
2031
+ /** Tick-label position (c:tickLblPos/@val): 'high', 'low', 'nextTo', or 'none'. */
2032
+ tickLblPos?: 'high' | 'low' | 'nextTo' | 'none';
2033
+ }
2034
+ /** 3D wall or floor element formatting. */
2035
+ interface PptxChart3DSurface {
2036
+ thickness?: number;
2037
+ spPr?: PptxChartShapeProps;
2038
+ }
2039
+ /**
2040
+ * A single data series within a chart.
2041
+ *
2042
+ * @example
2043
+ * ```ts
2044
+ * const series: PptxChartSeries = {
2045
+ * name: "Revenue",
2046
+ * values: [100, 120, 140],
2047
+ * color: "#4F81BD",
2048
+ * trendlines: [{ trendlineType: "linear" }],
2049
+ * };
2050
+ * // => satisfies PptxChartSeries
2051
+ * ```
2052
+ */
2053
+ interface PptxChartSeries {
2054
+ name: string;
2055
+ values: number[];
2056
+ color?: string;
2057
+ trendlines?: PptxChartTrendline[];
2058
+ errBars?: PptxChartErrBars[];
2059
+ dataPoints?: PptxChartDataPoint[];
2060
+ marker?: PptxChartMarker;
2061
+ dataLabels?: PptxChartDataLabel[];
2062
+ explosion?: number;
2063
+ /** Axis ID this series is plotted against (links to PptxChartAxisFormatting.axisId). */
2064
+ axisId?: number;
2065
+ /**
2066
+ * Per-series chart type, used for combo charts where individual series are
2067
+ * plotted with different chart types (e.g. a bar series and a line series in
2068
+ * the same chart). Maps to the OOXML chart-type container that holds the
2069
+ * series (`c:barChart`, `c:lineChart`, etc.). Omitted for single-type charts,
2070
+ * where the chart-level {@link PptxChartData.chartType} applies to every
2071
+ * series.
2072
+ */
2073
+ seriesChartType?: PptxChartType;
2074
+ }
2075
+ /**
2076
+ * Chart-level data-label options (`c:dLbls` directly under a chart-type
2077
+ * container, applying to every series). Mirrors the OOXML `c:show*` flags
2078
+ * and `c:dLblPos`.
2079
+ */
2080
+ interface PptxChartDataLabelOptions {
2081
+ /** Show the numeric value (`c:showVal`). */
2082
+ showValue?: boolean;
2083
+ /** Show the category name (`c:showCatName`). */
2084
+ showCategory?: boolean;
2085
+ /** Show the series name (`c:showSerName`). */
2086
+ showSeriesName?: boolean;
2087
+ /** Show the percentage (`c:showPercent`, pie/doughnut). */
2088
+ showPercent?: boolean;
2089
+ /** Show the legend key swatch (`c:showLegendKey`). */
2090
+ showLegendKey?: boolean;
2091
+ /**
2092
+ * Label position (`c:dLblPos`). Valid values depend on the chart type
2093
+ * (`ctr`, `inEnd`, `inBase`, `outEnd`, `bestFit`, `l`, `r`, `t`, `b`).
2094
+ * Omit to let PowerPoint use the type default.
2095
+ */
2096
+ position?: 'ctr' | 'inEnd' | 'inBase' | 'outEnd' | 'bestFit' | 'l' | 'r' | 't' | 'b';
2097
+ }
2098
+ /**
2099
+ * Style / formatting metadata for a chart.
2100
+ *
2101
+ * @example
2102
+ * ```ts
2103
+ * const style: PptxChartStyle = {
2104
+ * styleId: 2,
2105
+ * hasLegend: true,
2106
+ * legendPosition: "b",
2107
+ * hasDataLabels: true,
2108
+ * };
2109
+ * // => satisfies PptxChartStyle
2110
+ * ```
2111
+ */
2112
+ interface PptxChartStyle {
2113
+ /** Chart style index from `c:style/@val`. */
2114
+ styleId?: number;
2115
+ /** Whether the chart has a visible legend. */
2116
+ hasLegend?: boolean;
2117
+ /** Legend position (t, b, l, r, tr). */
2118
+ legendPosition?: string;
2119
+ /** Whether the chart has a title. */
2120
+ hasTitle?: boolean;
2121
+ /** Whether gridlines are visible. */
2122
+ hasGridlines?: boolean;
2123
+ /** Whether data labels are shown. */
2124
+ hasDataLabels?: boolean;
2125
+ /** Chart-level data-label content/position options (when `hasDataLabels`). */
2126
+ dataLabels?: PptxChartDataLabelOptions;
2127
+ }
2128
+ /**
2129
+ * External data source reference for a chart (c:externalData).
2130
+ *
2131
+ * Charts can reference an external Excel workbook via a relationship ID
2132
+ * that points to an external file (TargetMode="External"). The
2133
+ * `autoUpdate` flag indicates whether the chart should refresh its
2134
+ * cached data from the external source on open.
2135
+ *
2136
+ * @example
2137
+ * ```ts
2138
+ * const ext: PptxExternalData = {
2139
+ * relId: "rId2",
2140
+ * targetPath: "file:///C:/Data/budget.xlsx",
2141
+ * autoUpdate: true,
2142
+ * };
2143
+ * // => satisfies PptxExternalData
2144
+ * ```
2145
+ */
2146
+ interface PptxExternalData {
2147
+ /** Relationship ID referencing the external data source in the chart .rels. */
2148
+ relId: string;
2149
+ /** Resolved external file path or URL from the relationship target. */
2150
+ targetPath?: string;
2151
+ /** Whether to auto-update data from the external source on open. */
2152
+ autoUpdate?: boolean;
2153
+ /** Raw binary data of the embedded xlsx workbook (from ppt/embeddings/). */
2154
+ embeddedWorkbookData?: Uint8Array;
2155
+ }
2156
+ /**
2157
+ * Options specific to the OOXML "Pie of Pie" / "Bar of Pie" chart
2158
+ * (`c:ofPieChart`, ECMA-376 §21.2.2.126 / CT_OfPieChart).
2159
+ *
2160
+ * The primary discriminator is {@link ofPieType}: `"pie"` produces a
2161
+ * pie-of-pie chart whose secondary plot is itself a pie, while `"bar"`
2162
+ * produces a bar-of-pie chart whose secondary plot is a horizontal bar.
2163
+ *
2164
+ * - {@link splitType} chooses the split rule.
2165
+ * - {@link splitPos} is the threshold value used by `pos`/`val`/`percent`.
2166
+ * - {@link secondPieSize} controls the secondary plot's size (5–200%).
2167
+ * - {@link serLines} toggles the leader lines connecting the plots.
2168
+ * - {@link gapWidth} is the gap between the plots in percent (0–500).
2169
+ */
2170
+ interface PptxChartOfPieOptions {
2171
+ ofPieType: 'pie' | 'bar';
2172
+ splitType?: 'auto' | 'cust' | 'percent' | 'pos' | 'val';
2173
+ splitPos?: number;
2174
+ custSplit?: number[];
2175
+ secondPieSize?: number;
2176
+ serLines?: boolean;
2177
+ gapWidth?: number;
2178
+ }
2179
+ /**
2180
+ * 3D viewing parameters for a chart (`c:view3D`, ECMA-376 §21.2.2.228 /
2181
+ * CT_View3D).
2182
+ *
2183
+ * All fields are optional and round-trip verbatim.
2184
+ *
2185
+ * - {@link rotX} — X-axis rotation in degrees (-90…90).
2186
+ * - {@link rotY} — Y-axis rotation in degrees (0…360).
2187
+ * - {@link depthPercent} — chart depth as a percentage of base width.
2188
+ * - {@link rAngAx} — `true` if axes meet at right angles.
2189
+ * - {@link perspective} — perspective angle in degrees (0…240).
2190
+ * - {@link hPercent} — height as a percentage of chart width.
2191
+ */
2192
+ interface PptxChartView3D {
2193
+ rotX?: number;
2194
+ rotY?: number;
2195
+ depthPercent?: number;
2196
+ rAngAx?: boolean;
2197
+ perspective?: number;
2198
+ hPercent?: number;
2199
+ }
2200
+ /**
2201
+ * Chart "chrome" flags from `c:chart` that round-trip cleanly even when
2202
+ * rendering ignores them.
2203
+ *
2204
+ * - {@link autoTitleDeleted} — `c:autoTitleDeleted/@val`. Suppresses the
2205
+ * auto-generated title for single-series charts.
2206
+ * - {@link dispBlanksAs} — `c:dispBlanksAs/@val`. How blank cells
2207
+ * render: `"gap"`, `"zero"`, or `"span"`.
2208
+ * - {@link showDLblsOverMax} — `c:showDLblsOverMax/@val`. Keeps data
2209
+ * labels visible for points exceeding the value-axis maximum.
2210
+ *
2211
+ * `c:plotVisOnly` lives on {@link PptxChartData.plotVisibleOnly} and is
2212
+ * intentionally not duplicated here.
2213
+ */
2214
+ interface PptxChartChrome {
2215
+ autoTitleDeleted?: boolean;
2216
+ dispBlanksAs?: 'gap' | 'zero' | 'span';
2217
+ showDLblsOverMax?: boolean;
2218
+ }
2219
+ /** Parsed data extracted from an embedded xlsx workbook. */
2220
+ interface PptxEmbeddedWorkbookData {
2221
+ /** Category labels from the first column/row. */
2222
+ categories: string[];
2223
+ /** Data series extracted from worksheet cells. */
2224
+ series: Array<{
2225
+ name: string;
2226
+ values: number[];
2227
+ }>;
2228
+ }
2229
+ /**
2230
+ * Complete parsed chart data for a {@link ChartPptxElement}.
2231
+ *
2232
+ * @example
2233
+ * ```ts
2234
+ * const chart: PptxChartData = {
2235
+ * title: "Q4 Sales",
2236
+ * chartType: "bar",
2237
+ * categories: ["Jan", "Feb", "Mar"],
2238
+ * series: [
2239
+ * { name: "Revenue", values: [100, 120, 140] },
2240
+ * ],
2241
+ * grouping: "clustered",
2242
+ * style: { hasLegend: true, legendPosition: "b" },
2243
+ * };
2244
+ * // => satisfies PptxChartData
2245
+ * ```
2246
+ */
2247
+ interface PptxChartData {
2248
+ title?: string;
2249
+ chartType: PptxChartType;
2250
+ categories: string[];
2251
+ series: PptxChartSeries[];
2252
+ /** Chart style/formatting metadata. */
2253
+ style?: PptxChartStyle;
2254
+ /** Grouping mode for bar/area/line charts: 'clustered' | 'stacked' | 'percentStacked' */
2255
+ grouping?: 'clustered' | 'stacked' | 'percentStacked';
2256
+ /** Internal: path to the chart XML part in the PPTX archive (for round-trip save). */
2257
+ chartPartPath?: string;
2258
+ /** Internal: relationship ID linking the graphic frame to the chart part. */
2259
+ chartRelationshipId?: string;
2260
+ dataTable?: PptxChartDataTable;
2261
+ dropLines?: PptxChartLineStyle;
2262
+ hiLowLines?: PptxChartLineStyle;
2263
+ axes?: PptxChartAxisFormatting[];
2264
+ floor?: PptxChart3DSurface;
2265
+ sideWall?: PptxChart3DSurface;
2266
+ backWall?: PptxChart3DSurface;
2267
+ /** External data source reference (c:externalData) linking to an external workbook. */
2268
+ externalData?: PptxExternalData;
2269
+ /**
2270
+ * Parsed data from the embedded xlsx workbook (from ppt/embeddings/).
2271
+ *
2272
+ * When a chart references an embedded Excel workbook via `c:externalData`,
2273
+ * the xlsx is parsed to extract categories and series. This data serves as
2274
+ * a fallback when the chart XML's cached series data is empty or incomplete.
2275
+ */
2276
+ embeddedWorkbookData?: PptxEmbeddedWorkbookData;
2277
+ /**
2278
+ * Pivot table data source reference (c:pivotSource).
2279
+ *
2280
+ * When present, the chart's data originates from a PivotTable.
2281
+ * The chart still renders using its cached series data; this field
2282
+ * is metadata about the data origin, preserved for round-trip fidelity.
2283
+ */
2284
+ pivotSource?: {
2285
+ /** Pivot table reference name, e.g. "[workbook.xlsx]Sheet1!PivotTable1". */
2286
+ name: string;
2287
+ /** Format identifier from c:fmtId/@val. */
2288
+ formatId?: number;
2289
+ };
2290
+ /**
2291
+ * Whether only visible cells are plotted (c:plotVisOnly).
2292
+ * When `true` (the default), hidden cells are excluded from the chart.
2293
+ * When `false`, hidden data IS plotted.
2294
+ */
2295
+ plotVisibleOnly?: boolean;
2296
+ /**
2297
+ * Color palette extracted from the chart's Office 2013+ color style part
2298
+ * (`chartColorStyle*.xml`). When present, this palette takes priority over
2299
+ * the `c:style/@val`-derived palette in `getChartStylePalette`.
2300
+ *
2301
+ * Each entry is a resolved hex colour string (e.g. `"#4472C4"`).
2302
+ */
2303
+ colorPalette?: string[];
2304
+ /**
2305
+ * Color cycling method from the chart color style part's `meth` attribute.
2306
+ *
2307
+ * - `"cycle"` — repeat the palette colours in order (default)
2308
+ * - `"withinLinear"` — gradient within each series
2309
+ * - `"acrossLinear"` — gradient across series
2310
+ */
2311
+ colorMethod?: 'cycle' | 'withinLinear' | 'acrossLinear';
2312
+ /**
2313
+ * Pie-of-pie / Bar-of-pie options (`c:ofPieChart`, CT_OfPieChart).
2314
+ *
2315
+ * Present only when {@link chartType} is `"ofPie"`. Carries the split
2316
+ * configuration, secondary plot size, and serLines flag so that an
2317
+ * `ofPieChart` element can be re-emitted on save with full fidelity.
2318
+ */
2319
+ ofPieOptions?: PptxChartOfPieOptions;
2320
+ /**
2321
+ * 3D viewing parameters (`c:view3D`, CT_View3D).
2322
+ *
2323
+ * Parsed from and emitted to `c:chart/c:view3D`. Absent when the
2324
+ * chart XML has no `c:view3D` element.
2325
+ */
2326
+ view3D?: PptxChartView3D;
2327
+ /**
2328
+ * Top-level chart chrome flags (`c:autoTitleDeleted`,
2329
+ * `c:dispBlanksAs`, `c:showDLblsOverMax`).
2330
+ *
2331
+ * Each flag is omitted from the emitted XML when absent on the
2332
+ * source data, so absence does not produce empty `<c:…/>` placeholders.
2333
+ */
2334
+ chartChrome?: PptxChartChrome;
2335
+ /**
2336
+ * Raw `c:userShapes` XML subtree (a drawing tree) preserved verbatim.
2337
+ *
2338
+ * `c:userShapes` references a separate drawing part containing
2339
+ * shapes drawn over the chart. The reference is preserved as-is so
2340
+ * that round-trip save re-emits the original element without
2341
+ * attempting to parse the nested drawing tree.
2342
+ */
2343
+ userShapesXml?: unknown;
2344
+ /**
2345
+ * Raw `c:pivotFmts` XML subtree preserved verbatim.
2346
+ *
2347
+ * `c:pivotFmts` carries a list of `c:pivotFmt` formatting overrides
2348
+ * for charts whose data originates from a PivotTable. Preserved
2349
+ * verbatim for round-trip fidelity.
2350
+ */
2351
+ pivotFmtsXml?: unknown;
2352
+ /**
2353
+ * Color-map override (`c:clrMapOvr`) carrying 12 attributes that
2354
+ * remap theme colour roles for this chart only. Preserved as a flat
2355
+ * `attribute → value` map for round-trip fidelity.
2356
+ */
2357
+ clrMapOvr?: Record<string, string>;
2358
+ }
2359
+
2360
+ /**
2361
+ * Image types: effects, crop shapes, and properties shared by image/picture
2362
+ * elements.
2363
+ *
2364
+ * @module pptx-types/image
2365
+ */
2366
+ /**
2367
+ * Blend mode for `a:blend` container nodes inside an `a:effectDag` (CT_BlendEffect).
2368
+ *
2369
+ * Per ECMA-376 §20.1.8.10, valid values are: `darken`, `lighten`, `mult`,
2370
+ * `over`, `screen`.
2371
+ */
2372
+ type EffectDagBlendMode = 'darken' | 'lighten' | 'mult' | 'over' | 'screen';
2373
+ /**
2374
+ * Container node kind inside an `a:effectDag` (CT_EffectContainer @type).
2375
+ *
2376
+ * Per ECMA-376 §20.1.8.20, `sib` (sibling) draws each child independently
2377
+ * over the same source; `tree` (tree) chains effects so each sees the output
2378
+ * of its siblings.
2379
+ */
2380
+ type EffectDagContainerType = 'sib' | 'tree';
2381
+ /**
2382
+ * Typed model of the directed-acyclic effect graph stored in `a:effectDag`.
2383
+ *
2384
+ * The four "structural" container/transform nodes are typed; any other inner
2385
+ * effect (e.g. `a:outerShdw`, `a:glow`, `a:alphaInv`) is preserved verbatim
2386
+ * as a raw XML object via the {@link EffectDagRawLeaf} variant so we never
2387
+ * have to recurse into the full effect taxonomy.
2388
+ *
2389
+ * @example
2390
+ * ```ts
2391
+ * // <a:effectDag>
2392
+ * // <a:cont type="sib">
2393
+ * // <a:blend blend="mult"><a:cont type="tree" /></a:blend>
2394
+ * // </a:cont>
2395
+ * // </a:effectDag>
2396
+ * const dag: EffectDagContainer = {
2397
+ * kind: "cont",
2398
+ * type: "sib",
2399
+ * children: [{
2400
+ * kind: "blend",
2401
+ * mode: "mult",
2402
+ * container: { kind: "cont", type: "tree", children: [] },
2403
+ * }],
2404
+ * };
2405
+ * ```
2406
+ */
2407
+ type EffectDagNode = EffectDagContainer | EffectDagBlend | EffectDagXfrm | EffectDagRelOff | EffectDagRawLeaf;
2408
+ /** `a:cont` — CT_EffectContainer. Recursive; mirrors the top-level `effectDag`. */
2409
+ interface EffectDagContainer {
2410
+ kind: 'cont';
2411
+ /** `@type` — `sib` or `tree`. */
2412
+ type: EffectDagContainerType;
2413
+ /** Optional `@name` attribute. */
2414
+ name?: string;
2415
+ /** Ordered children. */
2416
+ children: EffectDagNode[];
2417
+ }
2418
+ /** `a:blend` — CT_BlendEffect. Always wraps a single `a:cont` child. */
2419
+ interface EffectDagBlend {
2420
+ kind: 'blend';
2421
+ /** `@blend` attribute. */
2422
+ mode: EffectDagBlendMode;
2423
+ /** Required child `a:cont` container. */
2424
+ container: EffectDagContainer;
2425
+ }
2426
+ /** `a:xfrmEffect` — CT_TransformEffect. Affine transform with no children. */
2427
+ interface EffectDagXfrm {
2428
+ kind: 'xfrmEffect';
2429
+ /** Horizontal scale, percentage * 1000 (e.g. 100000 = 100%). */
2430
+ sx?: number;
2431
+ /** Vertical scale, percentage * 1000. */
2432
+ sy?: number;
2433
+ /** Horizontal skew, degrees * 60000. */
2434
+ kx?: number;
2435
+ /** Vertical skew, degrees * 60000. */
2436
+ ky?: number;
2437
+ /** Horizontal translation in EMU. */
2438
+ tx?: number;
2439
+ /** Vertical translation in EMU. */
2440
+ ty?: number;
2441
+ }
2442
+ /** `a:relOff` — CT_RelativeOffsetEffect. Relative offset in 1000ths of a percent. */
2443
+ interface EffectDagRelOff {
2444
+ kind: 'relOff';
2445
+ /** Horizontal offset, percentage * 1000. */
2446
+ tx?: number;
2447
+ /** Vertical offset, percentage * 1000. */
2448
+ ty?: number;
2449
+ }
2450
+ /**
2451
+ * Catch-all leaf preserving any non-container effect (e.g. `a:outerShdw`,
2452
+ * `a:glow`, `a:alphaInv`) as raw XML. Re-emitted verbatim on save.
2453
+ */
2454
+ interface EffectDagRawLeaf {
2455
+ kind: 'raw';
2456
+ /** Local element name without the `a:` prefix (e.g. `outerShdw`, `glow`). */
2457
+ tag: string;
2458
+ /** Raw XML object captured at load — preserved verbatim on save. */
2459
+ xml: Record<string, unknown>;
2460
+ }
2461
+ /**
2462
+ * Image recolour/adjustment properties parsed from blip extensions.
2463
+ *
2464
+ * These effects are stored in the OpenXML `<a:blip>` extension list
2465
+ * and applied non-destructively to the original image data.
2466
+ *
2467
+ * @example
2468
+ * ```ts
2469
+ * const fx: PptxImageEffects = {
2470
+ * brightness: 20,
2471
+ * contrast: -10,
2472
+ * grayscale: true,
2473
+ * };
2474
+ * // => { brightness: 20, contrast: -10, grayscale: true } satisfies PptxImageEffects
2475
+ * ```
2476
+ */
2477
+ interface PptxImageEffects {
2478
+ /** Brightness adjustment (-100 to 100). */
2479
+ brightness?: number;
2480
+ /** Contrast adjustment (-100 to 100). */
2481
+ contrast?: number;
2482
+ /** Duotone colour pair. */
2483
+ duotone?: {
2484
+ color1: string;
2485
+ color2: string;
2486
+ };
2487
+ /** Grayscale flag. */
2488
+ grayscale?: boolean;
2489
+ /** Saturation adjustment (-100 to 100). */
2490
+ saturation?: number;
2491
+ /** Color wash overlay. */
2492
+ colorWash?: {
2493
+ color: string;
2494
+ opacity: number;
2495
+ };
2496
+ /** Artistic effect name (blur, pencilGrayscale, paintStrokes, etc.). */
2497
+ artisticEffect?: string;
2498
+ /** Artistic effect radius/amount. */
2499
+ artisticRadius?: number;
2500
+ /** Alpha modulation fixed — overall opacity (0-100, where 100 = fully opaque). */
2501
+ alphaModFix?: number;
2502
+ /** Bi-level threshold — converts to 1-bit black/white (0-100). */
2503
+ biLevel?: number;
2504
+ /** Colour change — swap one colour range for another (used for transparency keying). */
2505
+ clrChange?: {
2506
+ clrFrom: string;
2507
+ clrTo: string;
2508
+ /** Whether the target colour is fully transparent (alpha = 0). */
2509
+ clrToTransparent?: boolean;
2510
+ };
2511
+ /**
2512
+ * Alpha inverse effect (`a:alphaInv`). Inverts the alpha channel; an optional
2513
+ * colour child shifts the inversion baseline.
2514
+ */
2515
+ alphaInv?: {
2516
+ /** Optional baseline colour (hex). */
2517
+ color?: string;
2518
+ };
2519
+ /** Alpha ceiling (`a:alphaCeiling`) — clamps any non-zero alpha to fully opaque. Boolean flag. */
2520
+ alphaCeiling?: boolean;
2521
+ /** Alpha floor (`a:alphaFloor`) — clamps any non-fully-opaque alpha to fully transparent. Boolean flag. */
2522
+ alphaFloor?: boolean;
2523
+ /**
2524
+ * Alpha modulate (`a:alphaMod`). The schema requires a single `cont` (effect
2525
+ * container) child; we preserve the inner XML opaquely for round-trip.
2526
+ */
2527
+ alphaMod?: {
2528
+ /** Raw opaque XML for the `a:cont` child to preserve on save. */
2529
+ contRawXml?: Record<string, unknown>;
2530
+ };
2531
+ /** Alpha replace (`a:alphaRepl`) — replaces alpha with the given fixed-percent value (0..100). */
2532
+ alphaRepl?: number;
2533
+ /** Alpha bi-level (`a:alphaBiLevel`) — threshold (0..100) above which alpha becomes fully opaque. */
2534
+ alphaBiLevel?: number;
2535
+ /**
2536
+ * Colour replace (`a:clrRepl`) — replaces all colour information in an image
2537
+ * with the given solid colour. Stores the raw colour child to preserve scheme
2538
+ * colour references and modifiers.
2539
+ */
2540
+ clrRepl?: {
2541
+ /** Resolved hex colour. */
2542
+ color: string;
2543
+ /** Raw opaque colour XML for round-trip. */
2544
+ rawXml?: Record<string, unknown>;
2545
+ };
2546
+ /** Luminance modulation (`a:lum`) — bright/contrast as fixed percentages (0..100). */
2547
+ lum?: {
2548
+ bright?: number;
2549
+ contrast?: number;
2550
+ };
2551
+ /** HSL modulation (`a:hsl`) — hue (0..360 degrees), saturation/luminance (-100..100). */
2552
+ hsl?: {
2553
+ hue?: number;
2554
+ sat?: number;
2555
+ lum?: number;
2556
+ };
2557
+ /** Image-effect tint (`a:tint` inside blip) — hue (0..360), amount (-100..100). */
2558
+ tint?: {
2559
+ hue?: number;
2560
+ amt?: number;
2561
+ };
2562
+ /**
2563
+ * Fill overlay (`a:fillOverlay`) — overlays a fill on top of the blip.
2564
+ * Stores blend mode and the raw inner fill XML for round-trip.
2565
+ */
2566
+ fillOverlay?: {
2567
+ blend: 'over' | 'mult' | 'screen' | 'darken' | 'lighten';
2568
+ /** Raw opaque fill XML preserved for round-trip. */
2569
+ fillRawXml?: Record<string, unknown>;
2570
+ };
2571
+ /** Blur (`a:blur`) — radius in EMU and grow flag. */
2572
+ blur?: {
2573
+ rad?: number;
2574
+ grow?: boolean;
2575
+ };
2576
+ }
2577
+ /**
2578
+ * Shape names used for crop-to-shape (CSS `clip-path` equivalent).
2579
+ *
2580
+ * @example
2581
+ * ```ts
2582
+ * const shape: PptxCropShape = "ellipse";
2583
+ * // => "ellipse" — one of: none | ellipse | roundedRect | triangle | diamond | pentagon | hexagon | star
2584
+ * ```
2585
+ */
2586
+ type PptxCropShape = 'none' | 'ellipse' | 'roundedRect' | 'triangle' | 'diamond' | 'pentagon' | 'hexagon' | 'star';
2587
+ /**
2588
+ * Image content mixin — present on image and picture elements.
2589
+ *
2590
+ * Contains the decoded image data (base64 data URL or archive path),
2591
+ * alt text, crop insets, tiling settings, and image effects.
2592
+ *
2593
+ * @example
2594
+ * ```ts
2595
+ * const props: PptxImageProperties = {
2596
+ * imagePath: "ppt/media/image1.png",
2597
+ * altText: "Company logo",
2598
+ * cropLeft: 0.05,
2599
+ * cropRight: 0.05,
2600
+ * };
2601
+ * // => { imagePath: "ppt/media/image1.png", altText: "Company logo", cropLeft: 0.05, cropRight: 0.05 }
2602
+ * ```
2603
+ */
2604
+ interface PptxImageProperties {
2605
+ /** Base64 data-URL for the decoded image. */
2606
+ imageData?: string;
2607
+ /** Path within the PPTX ZIP archive. */
2608
+ imagePath?: string;
2609
+ /** Base64 data-URL for an SVG variant (from blip extension asvg:svgBlip). Preferred over raster when available. */
2610
+ svgData?: string;
2611
+ /** Path to the SVG file within the PPTX ZIP archive. */
2612
+ svgPath?: string;
2613
+ /** Alt text / description from `p:cNvPr/@descr`. */
2614
+ altText?: string;
2615
+ /** Crop from left edge as 0..1 fraction (OOXML `a:srcRect/@l`). */
2616
+ cropLeft?: number;
2617
+ /** Crop from top edge as 0..1 fraction (OOXML `a:srcRect/@t`). */
2618
+ cropTop?: number;
2619
+ /** Crop from right edge as 0..1 fraction (OOXML `a:srcRect/@r`). */
2620
+ cropRight?: number;
2621
+ /** Crop from bottom edge as 0..1 fraction (OOXML `a:srcRect/@b`). */
2622
+ cropBottom?: number;
2623
+ /** Image tiling offset X in px. */
2624
+ tileOffsetX?: number;
2625
+ /** Image tiling offset Y in px. */
2626
+ tileOffsetY?: number;
2627
+ /** Image tiling scale X as percentage (100 = 100%). */
2628
+ tileScaleX?: number;
2629
+ /** Image tiling scale Y as percentage (100 = 100%). */
2630
+ tileScaleY?: number;
2631
+ /** Image tiling flip mode. */
2632
+ tileFlip?: 'none' | 'x' | 'y' | 'xy';
2633
+ /** Image tiling alignment. */
2634
+ tileAlignment?: string;
2635
+ /** Image recolour/artistic effect properties. */
2636
+ imageEffects?: PptxImageEffects;
2637
+ /** Crop-to-shape — CSS clip-path shape name. */
2638
+ cropShape?: PptxCropShape;
2639
+ }
2640
+ declare module "./index" {
2641
+ interface TextStyle {
2642
+ /**
2643
+ * Raw `a:effectDag` XML node from `a:rPr`, preserved verbatim for
2644
+ * round-trip serialisation. Mirrors the shape-level
2645
+ * {@link import('./shape-style').ShapeStyle.effectDagXml} field.
2646
+ */
2647
+ textEffectDagXml?: XmlObject;
2648
+ /**
2649
+ * Typed effect graph parsed from `textEffectDagXml`. The four structural
2650
+ * container nodes (`a:cont`, `a:blend`, `a:xfrmEffect`, `a:relOff`) are
2651
+ * fully typed; any other leaf effect is captured as
2652
+ * {@link EffectDagRawLeaf} so we never have to recurse into the full
2653
+ * effect taxonomy.
2654
+ */
2655
+ textEffectDagTree?: EffectDagContainer;
2656
+ }
2657
+ }
2658
+ declare module "./index" {
2659
+ interface ShapeStyle {
2660
+ /**
2661
+ * Typed effect graph parsed from {@link ShapeStyle.effectDagXml}. The four
2662
+ * structural container nodes (`a:cont`, `a:blend`, `a:xfrmEffect`,
2663
+ * `a:relOff`) are fully typed; any other leaf effect (e.g. `a:outerShdw`,
2664
+ * `a:glow`, `a:alphaInv`) is captured as {@link EffectDagRawLeaf} so we
2665
+ * never have to recurse into the full effect taxonomy.
2666
+ */
2667
+ effectDagTree?: EffectDagContainer;
2668
+ }
2669
+ }
2670
+
2671
+ /**
2672
+ * Media types: audio/video discriminator, bookmarks, runtime metadata,
2673
+ * and caption/subtitle tracks.
2674
+ *
2675
+ * @module pptx-types/media
2676
+ */
2677
+ /**
2678
+ * Discriminator for embedded media element types.
2679
+ *
2680
+ * @example
2681
+ * ```ts
2682
+ * const kind: PptxMediaType = "video";
2683
+ * // => "video" — one of: "video" | "audio" | "unknown"
2684
+ * ```
2685
+ */
2686
+ type PptxMediaType = 'video' | 'audio' | 'unknown';
2687
+ /**
2688
+ * A named bookmark within a media clip timeline.
2689
+ *
2690
+ * @example
2691
+ * ```ts
2692
+ * const bm: MediaBookmark = {
2693
+ * id: "bm1",
2694
+ * time: 12.5,
2695
+ * label: "Intro ends",
2696
+ * };
2697
+ * // => satisfies MediaBookmark
2698
+ * ```
2699
+ */
2700
+ interface MediaBookmark {
2701
+ id: string;
2702
+ /** Position in seconds from the start of the clip. */
2703
+ time: number;
2704
+ /** User-visible label for this bookmark. */
2705
+ label: string;
2706
+ }
2707
+ /**
2708
+ * Runtime-extracted metadata about a media clip (populated from HTMLMediaElement).
2709
+ *
2710
+ * @example
2711
+ * ```ts
2712
+ * const meta: MediaMetadata = {
2713
+ * duration: 120.5,
2714
+ * videoWidth: 1920,
2715
+ * videoHeight: 1080,
2716
+ * codecInfo: "video/mp4; codecs=\"avc1.640028\"",
2717
+ * };
2718
+ * // => satisfies MediaMetadata
2719
+ * ```
2720
+ */
2721
+ interface MediaMetadata {
2722
+ /** Duration in seconds. */
2723
+ duration?: number;
2724
+ /** Video width in pixels (video only). */
2725
+ videoWidth?: number;
2726
+ /** Video height in pixels (video only). */
2727
+ videoHeight?: number;
2728
+ /** MIME type / codec string reported by the browser. */
2729
+ codecInfo?: string;
2730
+ }
2731
+ /**
2732
+ * A closed-caption / subtitle track associated with a media element.
2733
+ *
2734
+ * @example
2735
+ * ```ts
2736
+ * const track: MediaCaptionTrack = {
2737
+ * id: "t1",
2738
+ * label: "English",
2739
+ * language: "en",
2740
+ * kind: "subtitles",
2741
+ * isDefault: true,
2742
+ * };
2743
+ * // => satisfies MediaCaptionTrack
2744
+ * ```
2745
+ */
2746
+ interface MediaCaptionTrack {
2747
+ /** Unique ID for this track. */
2748
+ id: string;
2749
+ /** Human-readable label (e.g. "English", "Spanish"). */
2750
+ label: string;
2751
+ /** BCP-47 language code (e.g. "en", "es"). */
2752
+ language: string;
2753
+ /** Track kind: subtitles, captions, or descriptions. */
2754
+ kind: 'subtitles' | 'captions' | 'descriptions';
2755
+ /** Data URL or path to the VTT/SRT content within the PPTX archive. */
2756
+ src?: string;
2757
+ /** Inline VTT content (for embedded captions). */
2758
+ content?: string;
2759
+ /** Whether this track is the default/active one. */
2760
+ isDefault?: boolean;
2761
+ }
2762
+
2763
+ /**
2764
+ * SmartArt node types: per-run text, per-node visual override, and the
2765
+ * data-model node itself. Split out of `smart-art.ts` to keep each type file
2766
+ * within the project's per-file line budget. Re-exported from `smart-art.ts`
2767
+ * (and thus the `types` barrel) for backward compatibility, so existing
2768
+ * imports of these symbols continue to work unchanged.
2769
+ *
2770
+ * @module pptx-types/smart-art-node
2771
+ */
2772
+ /**
2773
+ * A single run of text inside a SmartArt node, capturing the run text and the
2774
+ * raw `a:rPr` run-properties object verbatim so per-run formatting (bold,
2775
+ * colour, size, etc.) survives a load -> edit -> save round-trip instead of
2776
+ * collapsing to a single unstyled run.
2777
+ *
2778
+ * @example
2779
+ * ```ts
2780
+ * const run: PptxSmartArtTextRun = {
2781
+ * text: "Bold",
2782
+ * rPr: { "@_b": "1", "@_lang": "en-US" },
2783
+ * };
2784
+ * // => satisfies PptxSmartArtTextRun
2785
+ * ```
2786
+ */
2787
+ interface PptxSmartArtTextRun {
2788
+ /** Run text content. */
2789
+ text: string;
2790
+ /**
2791
+ * Raw parsed `a:rPr` run-properties object, preserved verbatim for
2792
+ * round-trip. Untyped XML, hence the loose record shape.
2793
+ */
2794
+ rPr?: Record<string, unknown>;
2795
+ }
2796
+ /**
2797
+ * Per-node visual override for a SmartArt node.
2798
+ *
2799
+ * Captures the individual fill / line / font colour and the bold / italic
2800
+ * emphasis a user has set on one specific node, independent of the diagram's
2801
+ * colour scheme and quick style. All colours are hex strings (e.g. "#FF0000").
2802
+ * Every field is optional: only the overridden aspects are carried, so an
2803
+ * empty object means "no per-node override".
2804
+ *
2805
+ * The parser reads these from the data point's `spPr` solid fill / line colour
2806
+ * and the first run's `rPr` (b / i / solidFill) when present, and the save path
2807
+ * writes them back so the override survives a load -> edit -> save round-trip.
2808
+ *
2809
+ * @example
2810
+ * ```ts
2811
+ * const style: PptxSmartArtNodeStyle = {
2812
+ * fillColor: "#FF0000",
2813
+ * fontColor: "#FFFFFF",
2814
+ * bold: true,
2815
+ * };
2816
+ * // => satisfies PptxSmartArtNodeStyle
2817
+ * ```
2818
+ */
2819
+ interface PptxSmartArtNodeStyle {
2820
+ /** Solid fill colour override (hex, e.g. "#4F81BD"). */
2821
+ fillColor?: string;
2822
+ /** Outline / line colour override (hex). */
2823
+ lineColor?: string;
2824
+ /** Text (font) colour override (hex). */
2825
+ fontColor?: string;
2826
+ /** Bold emphasis override for the node's runs. */
2827
+ bold?: boolean;
2828
+ /** Italic emphasis override for the node's runs. */
2829
+ italic?: boolean;
2830
+ }
2831
+ /**
2832
+ * A single node in the SmartArt data model.
2833
+ *
2834
+ * @example
2835
+ * ```ts
2836
+ * const node: PptxSmartArtNode = {
2837
+ * id: "1",
2838
+ * text: "CEO",
2839
+ * children: [
2840
+ * { id: "2", text: "VP Marketing", parentId: "1" },
2841
+ * { id: "3", text: "VP Engineering", parentId: "1" },
2842
+ * ],
2843
+ * };
2844
+ * // => satisfies PptxSmartArtNode
2845
+ * ```
2846
+ */
2847
+ interface PptxSmartArtNode {
2848
+ id: string;
2849
+ text: string;
2850
+ parentId?: string;
2851
+ children?: PptxSmartArtNode[];
2852
+ /** Node type from `@_type` attribute (e.g. "doc", "node", "asst", "pres"). */
2853
+ nodeType?: string;
2854
+ /**
2855
+ * Per-run text + run-properties for the node's first paragraph, captured at
2856
+ * parse time. When the joined run text still equals {@link text} (the node
2857
+ * was not edited, or was edited only in ways that preserve the run split),
2858
+ * the save path rebuilds the paragraph from these runs so per-run rich text
2859
+ * is not flattened. When {@link text} diverges, the runs are ignored.
2860
+ */
2861
+ runs?: PptxSmartArtTextRun[];
2862
+ /**
2863
+ * Optional per-node visual override (fill / line / font colour, bold /
2864
+ * italic). Read at parse time from the point's `spPr` / first-run `rPr`, set
2865
+ * by the editing op, honoured by the render path, and written back on save so
2866
+ * it round-trips.
2867
+ */
2868
+ style?: PptxSmartArtNodeStyle;
2869
+ }
2870
+
2871
+ /**
2872
+ * SmartArt types: layout categories, layout presets, colour schemes,
2873
+ * data-model nodes/connections, drawing shapes, chrome, and the composite
2874
+ * `PptxSmartArtData`.
2875
+ *
2876
+ * @module pptx-types/smart-art
2877
+ */
2878
+
2879
+ /**
2880
+ * Resolved SmartArt layout category.
2881
+ *
2882
+ * @example
2883
+ * ```ts
2884
+ * const cat: SmartArtLayoutType = "hierarchy";
2885
+ * // => "hierarchy" — one of: "list" | "process" | "cycle" | "hierarchy" | "relationship" | …
2886
+ * ```
2887
+ */
2888
+ type SmartArtLayoutType = 'list' | 'process' | 'cycle' | 'hierarchy' | 'relationship' | 'matrix' | 'pyramid' | 'funnel' | 'gear' | 'target' | 'timeline' | 'venn' | 'chevron' | 'bending' | 'unknown';
2889
+ /**
2890
+ * Named SmartArt layout presets for creation (subset of PowerPoint layouts).
2891
+ *
2892
+ * @example
2893
+ * ```ts
2894
+ * const layout: SmartArtLayout = "hierarchy";
2895
+ * // => "hierarchy" — one of: "basicBlockList" | "alternatingHexagons" | "hierarchy" | …
2896
+ * ```
2897
+ */
2898
+ type SmartArtLayout = 'basicBlockList' | 'alternatingHexagons' | 'basicChevronProcess' | 'basicCycle' | 'basicPie' | 'basicRadial' | 'basicVenn' | 'continuousBlockProcess' | 'convergingRadial' | 'hierarchy' | 'horizontalBulletList' | 'linearVenn' | 'segmentedProcess' | 'stackedList' | 'tableList' | 'trapezoidList' | 'upwardArrow' | 'basicFunnel' | 'basicTarget' | 'interlockingGears' | 'basicTimeline' | 'basicMatrix' | 'basicPyramid' | 'invertedPyramid' | 'bendingProcess' | 'stepDownProcess' | 'alternatingFlow' | 'descendingProcess' | 'pictureAccentList' | 'verticalBlockList' | 'groupedList' | 'pyramidList' | 'horizontalPictureList' | 'accentProcess' | 'verticalChevronList';
2899
+ /**
2900
+ * SmartArt colour scheme presets.
2901
+ *
2902
+ * @example
2903
+ * ```ts
2904
+ * const scheme: SmartArtColorScheme = "colorful1";
2905
+ * // => "colorful1" — one of: "colorful1" | "colorful2" | "colorful3" | "monochromatic1" | "monochromatic2"
2906
+ * ```
2907
+ */
2908
+ type SmartArtColorScheme = 'colorful1' | 'colorful2' | 'colorful3' | 'monochromatic1' | 'monochromatic2';
2909
+ /**
2910
+ * SmartArt visual style intensity.
2911
+ *
2912
+ * @example
2913
+ * ```ts
2914
+ * const style: SmartArtStyle = "moderate";
2915
+ * // => "moderate" — one of: "flat" | "moderate" | "intense"
2916
+ * ```
2917
+ */
2918
+ type SmartArtStyle = 'flat' | 'moderate' | 'intense';
2919
+ /**
2920
+ * A connection between two SmartArt data-model nodes.
2921
+ *
2922
+ * @example
2923
+ * ```ts
2924
+ * const conn: PptxSmartArtConnection = {
2925
+ * sourceId: "1",
2926
+ * destId: "2",
2927
+ * type: "parOf",
2928
+ * };
2929
+ * // => satisfies PptxSmartArtConnection
2930
+ * ```
2931
+ */
2932
+ interface PptxSmartArtConnection {
2933
+ /** Model ID of the source node. */
2934
+ sourceId: string;
2935
+ /** Model ID of the destination node. */
2936
+ destId: string;
2937
+ /** Connection type (e.g. "parOf", "presOf", "sibTrans"). */
2938
+ type?: string;
2939
+ /** Source index for ordering sibling connections. */
2940
+ srcOrd?: number;
2941
+ /** Destination index for ordering. */
2942
+ destOrd?: number;
2943
+ }
2944
+ /**
2945
+ * A pre-computed shape from `ppt/diagrams/drawing*.xml`.
2946
+ *
2947
+ * @example
2948
+ * ```ts
2949
+ * const shape: PptxSmartArtDrawingShape = {
2950
+ * id: "s1",
2951
+ * shapeType: "roundRect",
2952
+ * x: 100, y: 50, width: 200, height: 80,
2953
+ * fillColor: "#4F81BD",
2954
+ * text: "CEO",
2955
+ * };
2956
+ * // => satisfies PptxSmartArtDrawingShape
2957
+ * ```
2958
+ */
2959
+ interface PptxSmartArtDrawingShape {
2960
+ /** Shape ID within the drawing. */
2961
+ id: string;
2962
+ /** Preset geometry type (e.g. "roundRect", "ellipse"). */
2963
+ shapeType?: string;
2964
+ /** Position and size in EMU-based pixels. */
2965
+ x: number;
2966
+ y: number;
2967
+ width: number;
2968
+ height: number;
2969
+ /** Rotation in degrees. */
2970
+ rotation?: number;
2971
+ /** Skew along the X axis in degrees. */
2972
+ skewX?: number;
2973
+ /** Skew along the Y axis in degrees. */
2974
+ skewY?: number;
2975
+ /** Solid fill colour (hex). */
2976
+ fillColor?: string;
2977
+ /** Stroke colour (hex). */
2978
+ strokeColor?: string;
2979
+ /** Stroke width in points. */
2980
+ strokeWidth?: number;
2981
+ /** Text content of the shape. */
2982
+ text?: string;
2983
+ /** Font size in points. */
2984
+ fontSize?: number;
2985
+ /** Font colour (hex). */
2986
+ fontColor?: string;
2987
+ }
2988
+ /**
2989
+ * Background / outline extracted from `dgm:bg` and `dgm:whole`.
2990
+ *
2991
+ * @example
2992
+ * ```ts
2993
+ * const chrome: PptxSmartArtChrome = {
2994
+ * backgroundColor: "#F0F0F0",
2995
+ * outlineColor: "#333333",
2996
+ * outlineWidth: 1,
2997
+ * };
2998
+ * // => satisfies PptxSmartArtChrome
2999
+ * ```
3000
+ */
3001
+ interface PptxSmartArtChrome {
3002
+ /** Background fill colour (hex). */
3003
+ backgroundColor?: string;
3004
+ /** Outline stroke colour (hex). */
3005
+ outlineColor?: string;
3006
+ /** Outline stroke width in points. */
3007
+ outlineWidth?: number;
3008
+ }
3009
+ /**
3010
+ * Colour transform entry from `ppt/diagrams/colors*.xml`.
3011
+ *
3012
+ * @example
3013
+ * ```ts
3014
+ * const transform: PptxSmartArtColorTransform = {
3015
+ * name: "Colorful - Accent Colors",
3016
+ * fillColors: ["#4F81BD", "#C0504D", "#9BBB59"],
3017
+ * lineColors: ["#385D8A", "#8C3836", "#71893F"],
3018
+ * };
3019
+ * // => satisfies PptxSmartArtColorTransform
3020
+ * ```
3021
+ */
3022
+ interface PptxSmartArtColorTransform {
3023
+ /** Colour scheme name / title. */
3024
+ name?: string;
3025
+ /** Ordered list of fill colours (hex) for each node. */
3026
+ fillColors: string[];
3027
+ /** Ordered list of line colours (hex). */
3028
+ lineColors: string[];
3029
+ }
3030
+ /**
3031
+ * Style entry from `ppt/diagrams/quickStyles*.xml`.
3032
+ *
3033
+ * @example
3034
+ * ```ts
3035
+ * const qs: PptxSmartArtQuickStyle = {
3036
+ * name: "Moderate Effect",
3037
+ * effectIntensity: "moderate",
3038
+ * };
3039
+ * // => satisfies PptxSmartArtQuickStyle
3040
+ * ```
3041
+ */
3042
+ interface PptxSmartArtQuickStyle {
3043
+ /** Style name / title. */
3044
+ name?: string;
3045
+ /** Effect intensity identifier (e.g. "subtle", "moderate", "intense"). */
3046
+ effectIntensity?: string;
3047
+ }
3048
+ /**
3049
+ * Complete parsed SmartArt data for a {@link SmartArtPptxElement}.
3050
+ *
3051
+ * @example
3052
+ * ```ts
3053
+ * const data: PptxSmartArtData = {
3054
+ * resolvedLayoutType: "hierarchy",
3055
+ * layout: "hierarchy",
3056
+ * colorScheme: "colorful1",
3057
+ * style: "moderate",
3058
+ * nodes: [
3059
+ * { id: "1", text: "CEO", children: [
3060
+ * { id: "2", text: "VP Marketing", parentId: "1" },
3061
+ * ]},
3062
+ * ],
3063
+ * };
3064
+ * // => satisfies PptxSmartArtData
3065
+ * ```
3066
+ */
3067
+ interface PptxSmartArtData {
3068
+ layoutType?: string;
3069
+ resolvedLayoutType?: SmartArtLayoutType;
3070
+ /** Named layout preset (used when creating new SmartArt). */
3071
+ layout?: SmartArtLayout;
3072
+ /** Colour scheme for the SmartArt graphic. */
3073
+ colorScheme?: SmartArtColorScheme;
3074
+ /** Visual style intensity. */
3075
+ style?: SmartArtStyle;
3076
+ nodes: PptxSmartArtNode[];
3077
+ /** Connections between data-model nodes. */
3078
+ connections?: PptxSmartArtConnection[];
3079
+ /** Pre-computed shapes from `ppt/diagrams/drawing*.xml`. */
3080
+ drawingShapes?: PptxSmartArtDrawingShape[];
3081
+ /** Background and outline chrome from `dgm:bg` / `dgm:whole`. */
3082
+ chrome?: PptxSmartArtChrome;
3083
+ /** Colour transform from `ppt/diagrams/colors*.xml`. */
3084
+ colorTransform?: PptxSmartArtColorTransform;
3085
+ /** Quick style from `ppt/diagrams/quickStyles*.xml`. */
3086
+ quickStyle?: PptxSmartArtQuickStyle;
3087
+ /** Relationship ID for the diagram data part (for round-trip save). */
3088
+ dataRelId?: string;
3089
+ /** Relationship ID for the drawing part. */
3090
+ drawingRelId?: string;
3091
+ /** Relationship ID for the colours part. */
3092
+ colorsRelId?: string;
3093
+ /** Relationship ID for the quick-styles part. */
3094
+ styleRelId?: string;
3095
+ }
3096
+
3097
+ /**
3098
+ * Table types: cell styling, cell data, rows, table data, and the parsed
3099
+ * table style map from `ppt/tableStyles.xml`.
3100
+ *
3101
+ * @module pptx-types/table
3102
+ */
3103
+ /**
3104
+ * Per-cell visual style for a table cell.
3105
+ *
3106
+ * All fields are optional — unset values inherit from the table style.
3107
+ *
3108
+ * @example
3109
+ * ```ts
3110
+ * const header: PptxTableCellStyle = {
3111
+ * bold: true,
3112
+ * fontSize: 14,
3113
+ * color: "#FFFFFF",
3114
+ * backgroundColor: "#0055AA",
3115
+ * align: "center",
3116
+ * };
3117
+ * // => satisfies PptxTableCellStyle
3118
+ * ```
3119
+ */
3120
+ interface PptxTableCellStyle {
3121
+ fontSize?: number;
3122
+ bold?: boolean;
3123
+ italic?: boolean;
3124
+ underline?: boolean;
3125
+ color?: string;
3126
+ /**
3127
+ * Raw XML colour-choice node preserved from `a:tc/a:txBody/.../a:rPr/a:solidFill`
3128
+ * for round-trip serialisation. Currently unused by the cell-level writer
3129
+ * (cell text colour falls through `writeCellTextFormatting`), reserved for
3130
+ * future expansion alongside the run-properties round-trip path.
3131
+ */
3132
+ colorXml?: XmlObject;
3133
+ backgroundColor?: string;
3134
+ /**
3135
+ * Raw XML colour-choice node preserved from cell `a:tcPr/a:solidFill` for
3136
+ * round-trip serialisation. Re-emitted verbatim when the resolved
3137
+ * {@link backgroundColor} still matches the original colour.
3138
+ */
3139
+ backgroundColorXml?: XmlObject;
3140
+ borderColor?: string;
3141
+ /** Top border width in px. */
3142
+ borderTopWidth?: number;
3143
+ /** Bottom border width in px. */
3144
+ borderBottomWidth?: number;
3145
+ /** Left border width in px. */
3146
+ borderLeftWidth?: number;
3147
+ /** Right border width in px. */
3148
+ borderRightWidth?: number;
3149
+ /** Top border color as hex. */
3150
+ borderTopColor?: string;
3151
+ /** Bottom border color as hex. */
3152
+ borderBottomColor?: string;
3153
+ /** Left border color as hex. */
3154
+ borderLeftColor?: string;
3155
+ /** Right border color as hex. */
3156
+ borderRightColor?: string;
3157
+ align?: 'left' | 'center' | 'right' | 'justify';
3158
+ vAlign?: 'top' | 'middle' | 'bottom';
3159
+ /** Text direction from `a:tcPr/@vert` (spec values from CT_TextVerticalType). */
3160
+ textDirection?: 'vert' | 'vert270' | 'eaVert' | 'wordArtVert' | 'wordArtVertRtl' | 'mongolianVert';
3161
+ /** Cell left margin in px (from a:tcPr > a:tcMar > a:marL). */
3162
+ marginLeft?: number;
3163
+ /** Cell right margin in px. */
3164
+ marginRight?: number;
3165
+ /** Cell top margin in px. */
3166
+ marginTop?: number;
3167
+ /** Cell bottom margin in px. */
3168
+ marginBottom?: number;
3169
+ /** Diagonal border top-left to bottom-right color. */
3170
+ borderDiagDownColor?: string;
3171
+ /** Diagonal border top-left to bottom-right width in px. */
3172
+ borderDiagDownWidth?: number;
3173
+ /** Diagonal border bottom-left to top-right color. */
3174
+ borderDiagUpColor?: string;
3175
+ /** Diagonal border bottom-left to top-right width in px. */
3176
+ borderDiagUpWidth?: number;
3177
+ /** Table cell border dash style (legacy single value). */
3178
+ borderDash?: string;
3179
+ /** Per-edge border dash styles. */
3180
+ borderTopDash?: string;
3181
+ borderBottomDash?: string;
3182
+ borderLeftDash?: string;
3183
+ borderRightDash?: string;
3184
+ /** Cell text shadow colour. */
3185
+ textShadowColor?: string;
3186
+ /** Cell text shadow blur radius in px. */
3187
+ textShadowBlur?: number;
3188
+ /** Cell text shadow horizontal offset in px. */
3189
+ textShadowOffsetX?: number;
3190
+ /** Cell text shadow vertical offset in px. */
3191
+ textShadowOffsetY?: number;
3192
+ /** Cell text shadow opacity (0-1). */
3193
+ textShadowOpacity?: number;
3194
+ /** Cell text glow colour. */
3195
+ textGlowColor?: string;
3196
+ /** Cell text glow radius in px. */
3197
+ textGlowRadius?: number;
3198
+ /** Cell text glow opacity (0-1). */
3199
+ textGlowOpacity?: number;
3200
+ /** Cell fill mode: solid, gradient, pattern, or none. */
3201
+ fillMode?: 'solid' | 'gradient' | 'pattern' | 'none';
3202
+ /** Gradient fill stops (colours with positions). */
3203
+ gradientFillStops?: Array<{
3204
+ color: string;
3205
+ position: number;
3206
+ opacity?: number;
3207
+ }>;
3208
+ /** Gradient angle in degrees. */
3209
+ gradientFillAngle?: number;
3210
+ /** Gradient type: linear or radial. */
3211
+ gradientFillType?: 'linear' | 'radial';
3212
+ /** Path gradient sub-type. */
3213
+ gradientFillPathType?: 'circle' | 'rect' | 'shape';
3214
+ /** Focal point for radial gradients (0–1 fractions). */
3215
+ gradientFillFocalPoint?: {
3216
+ x: number;
3217
+ y: number;
3218
+ };
3219
+ /** Raw fillToRect LTRB values (0–1 fractions) for gradient sizing. */
3220
+ gradientFillFillToRect?: {
3221
+ l: number;
3222
+ t: number;
3223
+ r: number;
3224
+ b: number;
3225
+ };
3226
+ /** Pre-computed CSS gradient string for rendering. */
3227
+ gradientFillCss?: string;
3228
+ /** Pattern fill preset name (e.g. "ltDnDiag"). */
3229
+ patternFillPreset?: string;
3230
+ /** Pattern fill foreground colour. */
3231
+ patternFillForeground?: string;
3232
+ /** Pattern fill background colour. */
3233
+ patternFillBackground?: string;
3234
+ }
3235
+ /**
3236
+ * A single table cell with text content, optional style, and merge info.
3237
+ *
3238
+ * @example
3239
+ * ```ts
3240
+ * const cell: PptxTableCell = {
3241
+ * text: "$1.5M",
3242
+ * style: { bold: true, align: "right" },
3243
+ * gridSpan: 1,
3244
+ * };
3245
+ * // => satisfies PptxTableCell
3246
+ * ```
3247
+ */
3248
+ interface PptxTableCell {
3249
+ text: string;
3250
+ style?: PptxTableCellStyle;
3251
+ /** Column span (defaults to 1). */
3252
+ gridSpan?: number;
3253
+ /** Row span (defaults to 1). */
3254
+ rowSpan?: number;
3255
+ /** Whether this cell is merged vertically with the cell above. */
3256
+ vMerge?: boolean;
3257
+ /** Whether this cell is horizontally merged with the cell to the left (gridSpan continuation). */
3258
+ hMerge?: boolean;
3259
+ /**
3260
+ * Opaque round-trip storage for `a:tcPr` attributes that don't yet have
3261
+ * typed equivalents on {@link PptxTableCellStyle} (e.g. `horzOverflow`,
3262
+ * `anchorCtr`, `headers`, `hideSlicers`, `slicerCacheId`). Keys are the
3263
+ * raw XML attribute names without the `@_` prefix used by
3264
+ * fast-xml-parser. Re-emitted verbatim by the save writer when present.
3265
+ */
3266
+ extraAttributes?: Record<string, string>;
3267
+ }
3268
+ /**
3269
+ * A single table row with an optional height and an array of cells.
3270
+ *
3271
+ * @example
3272
+ * ```ts
3273
+ * const row: PptxTableRow = {
3274
+ * height: 40,
3275
+ * cells: [
3276
+ * { text: "Name" },
3277
+ * { text: "Score" },
3278
+ * ],
3279
+ * };
3280
+ * // => satisfies PptxTableRow
3281
+ * ```
3282
+ */
3283
+ interface PptxTableRow {
3284
+ /** Row height in px. */
3285
+ height?: number;
3286
+ cells: PptxTableCell[];
3287
+ }
3288
+ /**
3289
+ * Complete parsed table data for a {@link TablePptxElement}.
3290
+ *
3291
+ * Includes row/cell data, column widths, banding flags, and the applied
3292
+ * table style ID.
3293
+ *
3294
+ * @example
3295
+ * ```ts
3296
+ * const data: PptxTableData = {
3297
+ * rows: [
3298
+ * { cells: [{ text: "Product" }, { text: "Revenue" }] },
3299
+ * { cells: [{ text: "Widget A" }, { text: "$3.4M" }] },
3300
+ * ],
3301
+ * columnWidths: [0.6, 0.4],
3302
+ * firstRowHeader: true,
3303
+ * bandedRows: true,
3304
+ * };
3305
+ * // => satisfies PptxTableData
3306
+ * ```
3307
+ */
3308
+ interface PptxTableData {
3309
+ rows: PptxTableRow[];
3310
+ /** Column widths as proportion of total (summing to 1). */
3311
+ columnWidths: number[];
3312
+ /** Whether the table has banded rows. */
3313
+ bandedRows?: boolean;
3314
+ /** Whether the first row is a header. */
3315
+ firstRowHeader?: boolean;
3316
+ /** Whether banded columns are enabled. */
3317
+ bandedColumns?: boolean;
3318
+ /** Whether the last row is styled as a total row. */
3319
+ lastRow?: boolean;
3320
+ /** Whether the first column is styled as a header column. */
3321
+ firstCol?: boolean;
3322
+ /** Whether the last column is styled specially. */
3323
+ lastCol?: boolean;
3324
+ /** Table style ID from `a:tblPr/a:tblStyle@val` or `a:tblPr@tblStyle`. */
3325
+ tableStyleId?: string;
3326
+ /** Number of rows per banding group (default 1). */
3327
+ bandRowCycle?: number;
3328
+ /** Number of columns per banding group (default 1). */
3329
+ bandColCycle?: number;
3330
+ /** Right-to-left table layout from `a:tblPr/@rtl`. */
3331
+ rtl?: boolean;
3332
+ }
3333
+
3334
+ /**
3335
+ * A text box — a plain rectangle containing text, typically with no
3336
+ * visible fill or stroke.
3337
+ *
3338
+ * @example
3339
+ * ```ts
3340
+ * const title: TextPptxElement = {
3341
+ * type: "text",
3342
+ * id: "txt_1", x: 50, y: 30, width: 800, height: 60,
3343
+ * text: "Welcome",
3344
+ * textStyle: { fontSize: 36, bold: true },
3345
+ * };
3346
+ * // => satisfies TextPptxElement
3347
+ * ```
3348
+ */
3349
+ interface TextPptxElement extends PptxElementBase, PptxTextProperties, PptxShapeProperties {
3350
+ type: 'text';
3351
+ }
3352
+ /**
3353
+ * A shape — may contain text and custom geometry (preset or freeform).
3354
+ *
3355
+ * @example
3356
+ * ```ts
3357
+ * const rect: ShapePptxElement = {
3358
+ * type: "shape",
3359
+ * id: "shp_1", x: 100, y: 200, width: 300, height: 150,
3360
+ * shapeType: "roundRect",
3361
+ * shapeStyle: { fillColor: "#00AA55" },
3362
+ * text: "OK",
3363
+ * };
3364
+ * // => satisfies ShapePptxElement
3365
+ * ```
3366
+ */
3367
+ interface ShapePptxElement extends PptxElementBase, PptxTextProperties, PptxShapeProperties, PptxCustomPathProperties {
3368
+ type: 'shape';
3369
+ }
3370
+ /**
3371
+ * A connector (straight, bent, or curved line between shapes).
3372
+ *
3373
+ * Connector endpoints can snap to specific shapes via
3374
+ * `shapeStyle.connectorStartConnection` / `connectorEndConnection`.
3375
+ *
3376
+ * @example
3377
+ * ```ts
3378
+ * const line: ConnectorPptxElement = {
3379
+ * type: "connector",
3380
+ * id: "cxn_1", x: 100, y: 100, width: 200, height: 0,
3381
+ * shapeStyle: {
3382
+ * strokeColor: "#333",
3383
+ * connectorEndArrow: "triangle",
3384
+ * },
3385
+ * };
3386
+ * // => satisfies ConnectorPptxElement
3387
+ * ```
3388
+ */
3389
+ interface ConnectorPptxElement extends PptxElementBase, PptxTextProperties, PptxShapeProperties {
3390
+ type: 'connector';
3391
+ }
3392
+ /**
3393
+ * An image element from an OOXML `<p:pic>` node with `type: "image"`.
3394
+ *
3395
+ * @example
3396
+ * ```ts
3397
+ * const img: ImagePptxElement = {
3398
+ * type: "image",
3399
+ * id: "img_1", x: 0, y: 0, width: 960, height: 540,
3400
+ * imagePath: "ppt/media/image1.png",
3401
+ * altText: "Background scenery",
3402
+ * };
3403
+ * // => satisfies ImagePptxElement
3404
+ * ```
3405
+ */
3406
+ interface ImagePptxElement extends PptxElementBase, PptxShapeProperties, PptxCustomPathProperties, PptxImageProperties {
3407
+ type: 'image';
3408
+ }
3409
+ /**
3410
+ * A picture element from an OOXML `<p:pic>` node with `type: "picture"`.
3411
+ *
3412
+ * Functionally identical to {@link ImagePptxElement} but distinguished by
3413
+ * the `type` discriminant for semantic clarity.
3414
+ */
3415
+ interface PicturePptxElement extends PptxElementBase, PptxShapeProperties, PptxCustomPathProperties, PptxImageProperties {
3416
+ type: 'picture';
3417
+ }
3418
+ /**
3419
+ * A single unrecognised `<a:graphicData>/<a:extLst>/<a:ext>` extension on a
3420
+ * graphicFrame, captured verbatim so the round-trip can preserve future or
3421
+ * vendor-specific markup that the parser doesn't yet understand.
3422
+ *
3423
+ * The XML is preserved as a fast-xml-parser object tree (the same shape as
3424
+ * `rawXml` on other elements) so the save layer can re-emit it through the
3425
+ * existing builder without lossy string manipulation.
3426
+ */
3427
+ interface PptxGraphicFrameExtension {
3428
+ /** The `@_uri` attribute identifying the extension (e.g. `{C3CD43...}`). */
3429
+ uri: string;
3430
+ /** Parsed XML payload of the extension, suitable for re-serialization. */
3431
+ xml: XmlObject;
3432
+ }
3433
+ /**
3434
+ * A table embedded via a `<p:graphicFrame>`.
3435
+ *
3436
+ * @example
3437
+ * ```ts
3438
+ * const tbl: TablePptxElement = {
3439
+ * type: "table",
3440
+ * id: "tbl_1", x: 50, y: 200, width: 860, height: 300,
3441
+ * tableData: {
3442
+ * rows: [
3443
+ * { cells: [{ text: "Name" }, { text: "Score" }] },
3444
+ * { cells: [{ text: "Alice" }, { text: "95" }] },
3445
+ * ],
3446
+ * },
3447
+ * };
3448
+ * // => satisfies TablePptxElement
3449
+ * ```
3450
+ */
3451
+ interface TablePptxElement extends PptxElementBase {
3452
+ type: 'table';
3453
+ /** Parsed table cell data for editing. */
3454
+ tableData?: PptxTableData;
3455
+ /**
3456
+ * Unrecognised extensions captured from `a:graphicData/a:extLst` so they
3457
+ * round-trip losslessly. See {@link PptxGraphicFrameExtension}.
3458
+ */
3459
+ extensionXml?: PptxGraphicFrameExtension[];
3460
+ }
3461
+ /**
3462
+ * A chart embedded via a `<p:graphicFrame>`.
3463
+ *
3464
+ * Chart data is parsed from the related `chartN.xml` / `chartExN.xml`
3465
+ * parts inside the PPTX archive.
3466
+ */
3467
+ interface ChartPptxElement extends PptxElementBase {
3468
+ type: 'chart';
3469
+ chartData?: PptxChartData;
3470
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3471
+ extensionXml?: PptxGraphicFrameExtension[];
3472
+ }
3473
+ /**
3474
+ * A SmartArt diagram embedded via a `<p:graphicFrame>`.
3475
+ *
3476
+ * SmartArt data is extracted from `dgm:dataModel` parts. The editor
3477
+ * renders a simplified view; full editing is not supported.
3478
+ */
3479
+ interface SmartArtPptxElement extends PptxElementBase {
3480
+ type: 'smartArt';
3481
+ smartArtData?: PptxSmartArtData;
3482
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3483
+ extensionXml?: PptxGraphicFrameExtension[];
3484
+ }
3485
+ /**
3486
+ * Recognised OLE object application types derived from `progId` / `clsId`.
3487
+ *
3488
+ * Used to show type-specific icons and previews in the editor.
3489
+ */
3490
+ type OleObjectType = 'excel' | 'word' | 'pdf' | 'visio' | 'mathtype' | 'package' | 'unknown';
3491
+ /**
3492
+ * An OLE (Object Linking and Embedding) object.
3493
+ *
3494
+ * OLE objects can be embedded Excel sheets, Word documents, PDFs, Visio
3495
+ * diagrams, MathType equations, or generic "packages". They carry a
3496
+ * preview image for display and optional binary data for extraction.
3497
+ *
3498
+ * @example
3499
+ * ```ts
3500
+ * const ole: OlePptxElement = {
3501
+ * type: "ole",
3502
+ * id: "ole_1", x: 100, y: 200, width: 400, height: 300,
3503
+ * oleObjectType: "excel",
3504
+ * oleProgId: "Excel.Sheet.12",
3505
+ * fileName: "budget.xlsx",
3506
+ * };
3507
+ * // => satisfies OlePptxElement
3508
+ * ```
3509
+ */
3510
+ interface OlePptxElement extends PptxElementBase {
3511
+ type: 'ole';
3512
+ oleTarget?: string;
3513
+ oleProgId?: string;
3514
+ oleName?: string;
3515
+ /** CLSID of the OLE object (from `@_classid`). */
3516
+ oleClsId?: string;
3517
+ /** Detected application type (excel, word, pdf, etc.). */
3518
+ oleObjectType?: OleObjectType;
3519
+ /** File extension for the embedded binary (e.g. "xlsx", "docx"). */
3520
+ oleFileExtension?: string;
3521
+ /** Original file name when available. */
3522
+ fileName?: string;
3523
+ /** Whether this is a linked (vs. embedded) object. */
3524
+ isLinked?: boolean;
3525
+ /** External file path for linked OLE objects (TargetMode="External"). */
3526
+ externalPath?: string;
3527
+ /** Data-URL or path for the OLE preview image. */
3528
+ previewImage?: string;
3529
+ /** Decoded preview image as a data-URL. */
3530
+ previewImageData?: string;
3531
+ /** Whether the OLE object is shown as an icon (`p:oleObj/@showAsIcon`). */
3532
+ oleShowAsIcon?: boolean;
3533
+ /** Authored display width of the OLE object preview, in EMU (`@imgW`). */
3534
+ oleImgW?: number;
3535
+ /** Authored display height of the OLE object preview, in EMU (`@imgH`). */
3536
+ oleImgH?: number;
3537
+ /**
3538
+ * The recovered embedded payload as a data-URL (e.g.
3539
+ * `data:application/vnd...;base64,...`), suitable for download or
3540
+ * open-in-new-tab. For a generic "Package" OLE object this is the unwrapped
3541
+ * inner file; for a plain embedded file (e.g. `.xlsx`) it is that file
3542
+ * directly. Undefined when the embedding is missing or unreadable.
3543
+ *
3544
+ * Stored as a data-URL string to mirror how images store decoded bytes
3545
+ * ({@link ImagePptxElement.imageData}) and to stay serialization-safe.
3546
+ */
3547
+ oleEmbeddedData?: string;
3548
+ /** Original file name of the embedded payload when recoverable. */
3549
+ oleEmbeddedFileName?: string;
3550
+ /** MIME type of the embedded payload, derived from its extension/ProgID. */
3551
+ oleEmbeddedMimeType?: string;
3552
+ /** Size of the embedded payload in bytes. */
3553
+ oleEmbeddedByteSize?: number;
3554
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3555
+ extensionXml?: PptxGraphicFrameExtension[];
3556
+ }
3557
+ /**
3558
+ * An audio or video media element.
3559
+ *
3560
+ * Media elements reference files inside the PPTX archive
3561
+ * (`mediaPath`) and may include trim points, poster frames, and
3562
+ * playback settings for presentation mode.
3563
+ *
3564
+ * @example
3565
+ * ```ts
3566
+ * const video: MediaPptxElement = {
3567
+ * type: "media",
3568
+ * id: "vid_1", x: 50, y: 100, width: 640, height: 360,
3569
+ * mediaType: "video",
3570
+ * mediaPath: "ppt/media/media1.mp4",
3571
+ * autoPlay: true,
3572
+ * volume: 0.8,
3573
+ * };
3574
+ * // => satisfies MediaPptxElement
3575
+ * ```
3576
+ */
3577
+ interface MediaPptxElement extends PptxElementBase {
3578
+ type: 'media';
3579
+ mediaType?: PptxMediaType;
3580
+ mediaPath?: string;
3581
+ mediaData?: string;
3582
+ mediaMimeType?: string;
3583
+ /** Trim start in milliseconds (from p:cMediaNode p:cTn @st). */
3584
+ trimStartMs?: number;
3585
+ /** Trim end in milliseconds (from p:cMediaNode p:cTn @end). */
3586
+ trimEndMs?: number;
3587
+ /** Path to the poster/preview image inside the ZIP. */
3588
+ posterFramePath?: string;
3589
+ /** Base64 data-URL for the poster frame image. */
3590
+ posterFrameData?: string;
3591
+ /** Whether media should play full-screen during presentation. */
3592
+ fullScreen?: boolean;
3593
+ /** Whether media should loop continuously. */
3594
+ loop?: boolean;
3595
+ /** Fade-in duration in seconds. */
3596
+ fadeInDuration?: number;
3597
+ /** Fade-out duration in seconds. */
3598
+ fadeOutDuration?: number;
3599
+ /** Playback volume (0 to 1). */
3600
+ volume?: number;
3601
+ /** Whether media auto-plays on slide entry. */
3602
+ autoPlay?: boolean;
3603
+ /** Whether audio continues playing across slide transitions (presentation mode). */
3604
+ playAcrossSlides?: boolean;
3605
+ /** Hide the element when media is not actively playing. */
3606
+ hideWhenNotPlaying?: boolean;
3607
+ /** Named time bookmarks within the clip. */
3608
+ bookmarks?: MediaBookmark[];
3609
+ /** Playback speed multiplier (1 = normal, 2 = double, 0.5 = half). */
3610
+ playbackSpeed?: number;
3611
+ /** Runtime-extracted metadata (duration, resolution, codec). */
3612
+ metadata?: MediaMetadata;
3613
+ /** Closed caption / subtitle tracks. */
3614
+ captionTracks?: MediaCaptionTrack[];
3615
+ /** Whether the media source is missing/broken (file not found in archive). */
3616
+ mediaMissing?: boolean;
3617
+ /**
3618
+ * Whether the media is linked (external `r:link`) rather than embedded
3619
+ * (`r:embed`). Defaults to embedded when undefined.
3620
+ */
3621
+ isLinked?: boolean;
3622
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3623
+ extensionXml?: PptxGraphicFrameExtension[];
3624
+ }
3625
+ /**
3626
+ * A group container that holds child elements.
3627
+ *
3628
+ * Children inherit the group’s transform, so moving/resizing the group
3629
+ * affects all children proportionally.
3630
+ *
3631
+ * @example
3632
+ * ```ts
3633
+ * const group: GroupPptxElement = {
3634
+ * type: "group",
3635
+ * id: "grp_1", x: 0, y: 0, width: 960, height: 540,
3636
+ * children: [textEl, shapeEl],
3637
+ * };
3638
+ * // => satisfies GroupPptxElement
3639
+ * ```
3640
+ */
3641
+ interface GroupPptxElement extends PptxElementBase {
3642
+ type: 'group';
3643
+ /** Child elements contained within this group. */
3644
+ children: PptxElement[];
3645
+ /** Fill style extracted from the group's `p:grpSpPr`, used for `a:grpFill` inheritance. */
3646
+ groupFill?: ShapeStyle;
3647
+ }
3648
+ /**
3649
+ * A freehand ink / drawing stroke captured with a stylus or mouse.
3650
+ *
3651
+ * Ink strokes are stored as SVG path data strings. Each path may
3652
+ * have independent colour, width, and opacity.
3653
+ */
3654
+ interface InkPptxElement extends PptxElementBase {
3655
+ type: 'ink';
3656
+ /** SVG path data for ink strokes. */
3657
+ inkPaths: string[];
3658
+ /** Per-path stroke colours. */
3659
+ inkColors?: string[];
3660
+ /** Per-path stroke widths. */
3661
+ inkWidths?: number[];
3662
+ /** Per-path opacities (0-1). */
3663
+ inkOpacities?: number[];
3664
+ /** Drawing tool used: pen, highlighter, or eraser. */
3665
+ inkTool?: 'pen' | 'highlighter' | 'eraser';
3666
+ /**
3667
+ * Per-path arrays of per-point pressure values (0-1).
3668
+ *
3669
+ * Each entry corresponds to the path at the same index in `inkPaths`.
3670
+ * Each inner array contains one pressure value per sampled point along
3671
+ * the stroke. When present, the renderer uses these values to produce
3672
+ * variable-width strokes that reflect stylus/pen pressure.
3673
+ */
3674
+ inkPointPressures?: number[][];
3675
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3676
+ extensionXml?: PptxGraphicFrameExtension[];
3677
+ }
3678
+ /**
3679
+ * A single ink stroke within a {@link ContentPartPptxElement}.
3680
+ */
3681
+ interface ContentPartInkStroke {
3682
+ path: string;
3683
+ color: string;
3684
+ width: number;
3685
+ opacity: number;
3686
+ /**
3687
+ * Per-point pressure values (0-1) for this stroke.
3688
+ *
3689
+ * When present, the renderer uses these values to produce
3690
+ * variable-width strokes that reflect stylus/pen pressure.
3691
+ */
3692
+ pressures?: number[];
3693
+ }
3694
+ /**
3695
+ * A content-part element wrapped in `mc:AlternateContent`.
3696
+ *
3697
+ * Typically contains ink strokes from modern PowerPoint pen/highlighter.
3698
+ */
3699
+ interface ContentPartPptxElement extends PptxElementBase {
3700
+ type: 'contentPart';
3701
+ /** Ink strokes contained in this content part. */
3702
+ inkStrokes?: ContentPartInkStroke[];
3703
+ }
3704
+ /**
3705
+ * A Slide Zoom or Section Zoom element (PowerPoint Zoom Object).
3706
+ *
3707
+ * Zoom elements display a live thumbnail of the target slide and
3708
+ * navigate to it on click during presentation mode.
3709
+ *
3710
+ * @example
3711
+ * ```ts
3712
+ * const zoom: ZoomPptxElement = {
3713
+ * type: "zoom",
3714
+ * id: "zm_1", x: 300, y: 200, width: 200, height: 120,
3715
+ * zoomType: "slide",
3716
+ * targetSlideIndex: 5,
3717
+ * };
3718
+ * // => satisfies ZoomPptxElement
3719
+ * ```
3720
+ */
3721
+ interface ZoomPptxElement extends PptxElementBase, PptxImageProperties {
3722
+ type: 'zoom';
3723
+ /** Type of zoom: slide-level or section-level. */
3724
+ zoomType: 'slide' | 'section';
3725
+ /** Zero-based index of the target slide. */
3726
+ targetSlideIndex: number;
3727
+ /** Section ID for section zoom. */
3728
+ targetSectionId?: string;
3729
+ }
3730
+ /**
3731
+ * A 3D model object embedded via `p16:model3D` inside an
3732
+ * `mc:AlternateContent` block (PowerPoint 365+).
3733
+ *
3734
+ * The element carries the path to the `.glb`/`.gltf` binary inside
3735
+ * the ZIP and a poster/fallback image for rendering in viewers that
3736
+ * do not support interactive 3D.
3737
+ */
3738
+ interface Model3DPptxElement extends PptxElementBase, PptxImageProperties {
3739
+ type: 'model3d';
3740
+ /** Path to the 3D model file inside the ZIP. */
3741
+ modelPath?: string;
3742
+ /** Base64 data URL of the 3D model binary. */
3743
+ modelData?: string;
3744
+ /** MIME type of the model (e.g. "model/gltf-binary"). */
3745
+ modelMimeType?: string;
3746
+ /** Poster/preview image shown when 3D rendering is unavailable. */
3747
+ posterImage?: string;
3748
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3749
+ extensionXml?: PptxGraphicFrameExtension[];
3750
+ }
3751
+ /** An element whose type is not recognised by the parser. */
3752
+ interface UnknownPptxElement extends PptxElementBase {
3753
+ type: 'unknown';
3754
+ /** Unrecognised graphicFrame extLst extensions, captured verbatim for round-trip. */
3755
+ extensionXml?: PptxGraphicFrameExtension[];
3756
+ }
3757
+ /**
3758
+ * A single element on a PPTX slide.
3759
+ *
3760
+ * This is a **discriminated union** — narrow on `element.type` to access
3761
+ * variant-specific properties like `imageData` (image/picture), `pathData`
3762
+ * (shape), or `textSegments` (text/shape).
3763
+ */
3764
+ type PptxElement = TextPptxElement | ShapePptxElement | ConnectorPptxElement | ImagePptxElement | PicturePptxElement | TablePptxElement | ChartPptxElement | SmartArtPptxElement | OlePptxElement | MediaPptxElement | GroupPptxElement | InkPptxElement | ContentPartPptxElement | ZoomPptxElement | Model3DPptxElement | UnknownPptxElement;
3765
+ /**
3766
+ * Per-part header/footer flags from `<p:hf>` (CT_HeaderFooter, ECMA-376
3767
+ * §19.3.1.21). Defaults are "all true" — fields are only set on the typed
3768
+ * model when they were explicitly read, so callers can distinguish "unset"
3769
+ * (preserve original XML) from "false" (override).
3770
+ */
3771
+ interface PptxHeaderFooterFlags {
3772
+ /** `@hdr` — show header placeholder. Spec default: `true`. */
3773
+ hasHeader?: boolean;
3774
+ /** `@ftr` — show footer placeholder. Spec default: `true`. */
3775
+ hasFooter?: boolean;
3776
+ /** `@dt` — show date/time placeholder. Spec default: `true`. */
3777
+ hasDateTime?: boolean;
3778
+ /** `@sldNum` — show slide-number placeholder. Spec default: `true`. */
3779
+ hasSlideNumber?: boolean;
3780
+ }
3781
+
3782
+ /**
3783
+ * Animation types: presets, triggers, timing, native parsed animation data,
3784
+ * and the high-level {@link PptxElementAnimation} associated with each element.
3785
+ *
3786
+ * @module pptx-types/animation
3787
+ */
3788
+
3789
+ /**
3790
+ * Built-in animation preset names used for entrance, exit, and emphasis effects.
3791
+ *
3792
+ * @example
3793
+ * ```ts
3794
+ * const preset: PptxAnimationPreset = "fadeIn";
3795
+ * // => "fadeIn" — one of: none | fadeIn | flyIn | zoomIn | fadeOut | flyOut | zoomOut | spin | pulse | ...
3796
+ * ```
3797
+ */
3798
+ type PptxAnimationPreset = 'none' | 'appear' | 'fadeIn' | 'flyIn' | 'zoomIn' | 'bounceIn' | 'wipeIn' | 'splitIn' | 'dissolveIn' | 'wheelIn' | 'blindsIn' | 'boxIn' | 'floatIn' | 'riseUp' | 'swivel' | 'expandIn' | 'checkerboardIn' | 'flashIn' | 'peekIn' | 'randomBarsIn' | 'spinnerIn' | 'growTurnIn' | 'fadeOut' | 'flyOut' | 'zoomOut' | 'bounceOut' | 'wipeOut' | 'shrinkOut' | 'dissolveOut' | 'disappear' | 'spin' | 'pulse' | 'colorWave' | 'bounce' | 'flash' | 'growShrink' | 'teeter' | 'transparency' | 'boldFlash' | 'wave';
3799
+ /** Animation timing curve. */
3800
+ type PptxAnimationTimingCurve = 'ease' | 'ease-in' | 'ease-out' | 'linear';
3801
+ /** Repeat mode for animations. */
3802
+ type PptxAnimationRepeatMode = 'untilNextClick' | 'untilEndOfSlide';
3803
+ /** Animation trigger type from OOXML `p:cTn`. */
3804
+ type PptxAnimationTrigger = 'onClick' | 'onShapeClick' | 'onHover' | 'afterPrevious' | 'withPrevious' | 'afterDelay';
3805
+ /**
3806
+ * Native animation kind. The historic shape-targeted preset animations are
3807
+ * implicitly the default kind (`undefined`). Media animations (`p:audio`,
3808
+ * `p:video`) emit dedicated entries so playback order on the slide timeline
3809
+ * is preserved alongside other animations.
3810
+ */
3811
+ type PptxNativeAnimationKind = 'media';
3812
+ /**
3813
+ * Parsed native animation record from `p:timing / p:tnLst`.
3814
+ *
3815
+ * Represents a single animation node in the OOXML timing tree,
3816
+ * including motion paths, scale transforms, and text build settings.
3817
+ *
3818
+ * @example
3819
+ * ```ts
3820
+ * const anim: PptxNativeAnimation = {
3821
+ * targetId: "shape_1",
3822
+ * presetClass: "entr",
3823
+ * presetId: 10,
3824
+ * trigger: "afterPrevious",
3825
+ * durationMs: 500,
3826
+ * };
3827
+ * // => { targetId: "shape_1", presetClass: "entr", presetId: 10, trigger: "afterPrevious", durationMs: 500 }
3828
+ * ```
3829
+ */
3830
+ interface PptxNativeAnimation {
3831
+ /** Target element/shape ID. */
3832
+ targetId?: string;
3833
+ /** Trigger type. */
3834
+ trigger?: PptxAnimationTrigger;
3835
+ /** Shape ID that triggers this animation when clicked (interactive sequence). */
3836
+ triggerShapeId?: string;
3837
+ /** Effect preset class (entr, exit, emph, path). */
3838
+ presetClass?: 'entr' | 'exit' | 'emph' | 'path';
3839
+ /** Effect preset sub-type identifier. */
3840
+ presetId?: number;
3841
+ /** Duration in milliseconds. */
3842
+ durationMs?: number;
3843
+ /** Delay in milliseconds. */
3844
+ delayMs?: number;
3845
+ /** Trigger delay in milliseconds (for afterDelay). */
3846
+ triggerDelayMs?: number;
3847
+ /** SVG path string for motion path animations (`p:animMotion/@path`). */
3848
+ motionPath?: string;
3849
+ /** Motion origin: "layout" or "parent". */
3850
+ motionOrigin?: string;
3851
+ /** Whether the element auto-rotates to follow the motion path tangent (`p:animMotion/@rAng` = "0"). */
3852
+ motionPathRotateAuto?: boolean;
3853
+ /** Path edit mode from `p:animMotion/@pathEditMode` (e.g. "relative", "fixed"). */
3854
+ motionPathEditMode?: string;
3855
+ /** Comma-separated point-types string from `p:animMotion/@ptsTypes`. */
3856
+ motionPtsTypes?: string;
3857
+ /** Rotation angle in degrees for `p:animRot/@by` (converted from 60000ths). */
3858
+ rotationBy?: number;
3859
+ /** Starting rotation angle in degrees for `p:animRot/@from` (converted from 60000ths). */
3860
+ rotationFrom?: number;
3861
+ /** Ending rotation angle in degrees for `p:animRot/@to` (converted from 60000ths). */
3862
+ rotationTo?: number;
3863
+ /** X scale factor (percentage / 100) for `p:animScale/p:by/@x`. */
3864
+ scaleByX?: number;
3865
+ /** Y scale factor (percentage / 100) for `p:animScale/p:by/@y`. */
3866
+ scaleByY?: number;
3867
+ /** Starting X scale factor for `p:animScale/p:from/@x`. */
3868
+ scaleFromX?: number;
3869
+ /** Starting Y scale factor for `p:animScale/p:from/@y`. */
3870
+ scaleFromY?: number;
3871
+ /** Ending X scale factor for `p:animScale/p:to/@x`. */
3872
+ scaleToX?: number;
3873
+ /** Ending Y scale factor for `p:animScale/p:to/@y`. */
3874
+ scaleToY?: number;
3875
+ /** Whether `p:animScale/@zoomContents` was set ("1"/"true"). */
3876
+ scaleZoomContents?: boolean;
3877
+ /** Parsed `p:tav` keyframes from `p:tavLst` (CT_TLAnimVariantList). */
3878
+ keyframes?: PptxAnimationKeyframe[];
3879
+ /** Repeat count (e.g. `2`, `Infinity` for indefinite). */
3880
+ repeatCount?: number;
3881
+ /** Whether the animation plays in reverse after completion. */
3882
+ autoReverse?: boolean;
3883
+ /** Text build type from `p:bldP/@build` in `p:bldLst`. */
3884
+ buildType?: PptxTextBuildType;
3885
+ /** Build level for multi-level lists from `p:bldP/@bldLvl`. */
3886
+ buildLevel?: number;
3887
+ /** Group ID linking a `p:bldP` entry to its timing animation node. */
3888
+ groupId?: string;
3889
+ /** Sound relationship ID to play when animation triggers (`p:stSnd`). */
3890
+ soundRId?: string;
3891
+ /** Resolved sound file path from relationship. */
3892
+ soundPath?: string;
3893
+ /** Whether to stop any currently playing sound (`p:endSnd`). */
3894
+ stopSound?: boolean;
3895
+ /** Structured start conditions parsed from `p:stCondLst`. */
3896
+ startConditions?: AnimationCondition[];
3897
+ /** Structured end conditions parsed from `p:endCondLst`. */
3898
+ endConditions?: AnimationCondition[];
3899
+ /** Preserved raw `p:endCondLst` XML node for lossless round-trip. */
3900
+ rawEndCondLst?: XmlObject;
3901
+ /** Color animation data from `p:animClr`. */
3902
+ colorAnimation?: PptxColorAnimation;
3903
+ /** Text-level target: character range or paragraph range from `p:txEl`. */
3904
+ textTarget?: PptxTextAnimationTarget;
3905
+ /** Whether this animation is inside an exclusive container (`p:excl`). */
3906
+ exclusive?: boolean;
3907
+ /** Command type from `p:cmd` (@_type: call/evt/verb). */
3908
+ commandType?: string;
3909
+ /** Command string from `p:cmd` (@_cmd). */
3910
+ commandString?: string;
3911
+ /** Iteration configuration from `p:iterate`. */
3912
+ iterate?: PptxAnimationIterate;
3913
+ /**
3914
+ * Discriminator for non-preset animation kinds. When `undefined`, the
3915
+ * entry represents the default shape-effect animation. The `'media'`
3916
+ * kind represents a `p:audio` / `p:video` timing node, captured here so
3917
+ * playback order in the timeline is preserved alongside other animations.
3918
+ */
3919
+ kind?: PptxNativeAnimationKind;
3920
+ /**
3921
+ * For `kind === 'media'`, identifies whether this is an audio or video
3922
+ * media node so writers know which OOXML element to re-emit.
3923
+ */
3924
+ mediaType?: 'audio' | 'video';
3925
+ /**
3926
+ * SmartArt build attribute (`p:bldDgm/@bld`) when this animation is
3927
+ * associated with a SmartArt diagram build. Common values include
3928
+ * `whole`, `one`, `lvlOne`, `lvlAtOnce`.
3929
+ */
3930
+ smartArtBuild?: string;
3931
+ /**
3932
+ * Graphic-frame build attribute (`p:bldGraphic/@bld`) when this animation
3933
+ * is associated with a generic graphic frame build (charts, tables, etc.
3934
+ * that aren't OLE charts).
3935
+ */
3936
+ graphicBuild?: string;
3937
+ /**
3938
+ * Opaque map of `p:cTn` attributes that don't have a typed home on this
3939
+ * interface but must round-trip through parse → save. Keys are stored
3940
+ * verbatim including the `@_` prefix used by the underlying XML parser
3941
+ * (e.g. `@_evtFilter`, `@_display`, `@_masterRel`, `@_nodePh`,
3942
+ * `@_endSync`, `@_progress`). The `subTnLst` child element is also
3943
+ * preserved here under the literal key `p:subTnLst`. The `afterEffect`
3944
+ * attribute is surfaced separately as a typed boolean ({@link afterEffect})
3945
+ * because it changes write semantics for subsequent timing nodes.
3946
+ */
3947
+ cTnAttributes?: Record<string, unknown>;
3948
+ /**
3949
+ * Whether the OOXML `p:cTn/@afterEffect` flag is set. Indicates this node
3950
+ * runs after the parent effect's main body has completed; affects how
3951
+ * subsequent peer nodes are sequenced when serialised back to OOXML.
3952
+ */
3953
+ afterEffect?: boolean;
3954
+ }
3955
+ /**
3956
+ * Single keyframe parsed from a `p:tav` element (CT_TLTimeAnimateValue).
3957
+ *
3958
+ * Each entry in a `p:tavLst` has a time fraction (`@_tm`, in 1000ths of the
3959
+ * total duration; or the literal "indefinite" / "large") and a typed value
3960
+ * child under `p:val/p:strVal|p:boolVal|p:intVal|p:fltVal|p:clrVal`.
3961
+ *
3962
+ * @see ECMA-376 §19.5.30 CT_TLAnimVariantList / §19.5.92 CT_TLTimeAnimateValue
3963
+ */
3964
+ interface PptxAnimationKeyframe {
3965
+ /**
3966
+ * Time fraction. A finite number is the OOXML `@_tm` integer (0–100000
3967
+ * for percentage, where 100000 = 100% of duration). A string preserves
3968
+ * special tokens ("indefinite", "large").
3969
+ */
3970
+ tm: number | string;
3971
+ /** Decoded keyframe value. */
3972
+ value: string | boolean | number;
3973
+ /** Discriminant indicating which `p:val` child carried the value. */
3974
+ valueType: 'str' | 'bool' | 'int' | 'flt' | 'clr';
3975
+ /**
3976
+ * Optional formula carried on `p:tav/@_fmla`. Preserved for round-trip
3977
+ * fidelity; consumers may use it to drive computed animation values.
3978
+ */
3979
+ fmla?: string;
3980
+ }
3981
+ /** Color animation data parsed from `p:animClr`. */
3982
+ interface PptxColorAnimation {
3983
+ /** Color interpolation space: "hsl" or "rgb". */
3984
+ colorSpace: 'hsl' | 'rgb';
3985
+ /** Direction for HSL interpolation: "cw" (clockwise) or "ccw". */
3986
+ direction?: 'cw' | 'ccw';
3987
+ /**
3988
+ * Optional `p:animClr/@path` value preserved for round-trip. When set,
3989
+ * the colour sweep follows a path-based interpolation rather than the
3990
+ * straight cw/ccw arc. ECMA-376 §19.5.13 documents this attribute as a
3991
+ * companion to `@dir` for HSL colour-space animations.
3992
+ */
3993
+ path?: string;
3994
+ /** Starting color as hex string. */
3995
+ fromColor?: string;
3996
+ /** Ending color as hex string. */
3997
+ toColor?: string;
3998
+ /**
3999
+ * Color delta (for "by" animations) as hex string. For HSL colour-space
4000
+ * animations the value encodes a delta over hue/sat/lum and is preserved
4001
+ * verbatim from the source.
4002
+ */
4003
+ byColor?: string;
4004
+ /**
4005
+ * Target attribute from `p:attrNameLst` (e.g. "fillcolor", "style.color",
4006
+ * "stroke.color"). Used to determine which CSS property to animate.
4007
+ */
4008
+ targetAttribute?: string;
4009
+ }
4010
+ /** Text-level animation target from `p:txEl`. */
4011
+ interface PptxTextAnimationTarget {
4012
+ /** Target type: character range or paragraph range. */
4013
+ type: 'charRg' | 'pRg';
4014
+ /** Start index (0-based). */
4015
+ start: number;
4016
+ /** End index (exclusive). */
4017
+ end: number;
4018
+ }
4019
+ /**
4020
+ * Event types for animation conditions from `p:cond/@evt`.
4021
+ *
4022
+ * These map directly to OOXML condition event attribute values
4023
+ * (ISO/IEC 29500-1 S19.5.28 CT_TLTimeCondition).
4024
+ */
4025
+ type AnimationConditionEvent = 'onBegin' | 'onEnd' | 'begin' | 'end' | 'onClick' | 'onMouseOver' | 'onMouseOut' | 'onNext' | 'onPrev' | 'onStopAudio';
4026
+ /**
4027
+ * Structured representation of a single OOXML animation condition
4028
+ * from `p:cond` elements inside `p:stCondLst` or `p:endCondLst`.
4029
+ *
4030
+ * Conditions control when an animation starts or ends, and can reference
4031
+ * events, time delays, and target time node IDs.
4032
+ *
4033
+ * @example
4034
+ * ```ts
4035
+ * const cond: AnimationCondition = {
4036
+ * event: "onClick",
4037
+ * delay: 0,
4038
+ * targetShapeId: "shape_5",
4039
+ * };
4040
+ * ```
4041
+ */
4042
+ interface AnimationCondition {
4043
+ /** Event that triggers the condition. */
4044
+ event?: AnimationConditionEvent;
4045
+ /** Delay in milliseconds (from `@_delay`). "indefinite" is represented as -1. */
4046
+ delay?: number;
4047
+ /** Target time node ID reference (from `@_tn`). */
4048
+ targetTimeNodeId?: number;
4049
+ /** Target shape ID from `p:tgtEl/p:spTgt/@spid`. */
4050
+ targetShapeId?: string;
4051
+ /** Whether the condition targets a slide (from `p:tgtEl/p:sldTgt`). */
4052
+ targetSlide?: boolean;
4053
+ }
4054
+ /** Iteration configuration from `p:iterate`. */
4055
+ interface PptxAnimationIterate {
4056
+ /** Iteration type: el (element), lt (letter), wd (word). */
4057
+ type: 'el' | 'lt' | 'wd';
4058
+ /** Whether to iterate backwards. */
4059
+ backwards?: boolean;
4060
+ /** Timing interval (percentage of total duration, in 1000ths). */
4061
+ tmPct?: number;
4062
+ /** Absolute timing interval in ms. */
4063
+ tmAbs?: number;
4064
+ }
4065
+ /** Build type for text build (paragraph/word/letter) animations from `p:bldP/@build`. */
4066
+ type PptxTextBuildType = 'allAtOnce' | 'byParagraph' | 'byWord' | 'byChar';
4067
+ /** Direction for fly-in / fly-out / wipe effects. */
4068
+ type PptxAnimationDirection = 'fromLeft' | 'fromRight' | 'fromTop' | 'fromBottom' | 'fromTopLeft' | 'fromTopRight' | 'fromBottomLeft' | 'fromBottomRight';
4069
+ /** Sequence mode for paragraph-level animations. */
4070
+ type PptxAnimationSequence = 'asOne' | 'byParagraph' | 'byWord' | 'byLetter';
4071
+ /** Behavior after animation finishes. */
4072
+ type PptxAfterAnimationAction = 'none' | 'hideOnNextClick' | 'hideAfterAnimation' | 'dimToColor';
4073
+ /**
4074
+ * High-level animation data associated with a slide element.
4075
+ *
4076
+ * Combines entrance, exit, and emphasis presets with timing and
4077
+ * trigger configuration. Used by the editor’s animation panel
4078
+ * and the `setPptxElementAnimation` tool.
4079
+ *
4080
+ * @example
4081
+ * ```ts
4082
+ * const anim: PptxElementAnimation = {
4083
+ * elementId: "title_1",
4084
+ * entrance: "fadeIn",
4085
+ * durationMs: 600,
4086
+ * order: 1,
4087
+ * trigger: "afterPrevious",
4088
+ * };
4089
+ * // => { elementId: "title_1", entrance: "fadeIn", durationMs: 600, order: 1, trigger: "afterPrevious" }
4090
+ * ```
4091
+ */
4092
+ interface PptxElementAnimation {
4093
+ elementId: string;
4094
+ entrance?: PptxAnimationPreset;
4095
+ exit?: PptxAnimationPreset;
4096
+ emphasis?: PptxAnimationPreset;
4097
+ durationMs?: number;
4098
+ delayMs?: number;
4099
+ order?: number;
4100
+ trigger?: PptxAnimationTrigger;
4101
+ /** Shape ID that triggers this animation when clicked (interactive sequence). */
4102
+ triggerShapeId?: string;
4103
+ timingCurve?: PptxAnimationTimingCurve;
4104
+ repeatCount?: number;
4105
+ repeatMode?: PptxAnimationRepeatMode;
4106
+ /** Direction for directional effects (fly in/out, wipe, etc.). */
4107
+ direction?: PptxAnimationDirection;
4108
+ /** Sequence mode — animate as one object or by paragraph/word/letter. */
4109
+ sequence?: PptxAnimationSequence;
4110
+ /** What happens after the animation finishes playing. */
4111
+ afterAnimation?: PptxAfterAnimationAction;
4112
+ /** Dim-to color hex (used when afterAnimation is "dimToColor"). */
4113
+ afterAnimationColor?: string;
4114
+ /** SVG motion path string for custom motion path animations. */
4115
+ motionPath?: string;
4116
+ /**
4117
+ * Path edit mode for `p:animMotion/@pathEditMode`. Defaults to "relative"
4118
+ * when emitted without an explicit value.
4119
+ */
4120
+ motionPathEditMode?: string;
4121
+ /** Comma-separated point-types string for `p:animMotion/@ptsTypes`. */
4122
+ motionPtsTypes?: string;
4123
+ /** Sound relationship ID to play when animation triggers (`p:stSnd`). */
4124
+ soundRId?: string;
4125
+ /** Resolved sound file path from relationship. */
4126
+ soundPath?: string;
4127
+ /** Whether to stop any currently playing sound (`p:endSnd`). */
4128
+ stopSound?: boolean;
4129
+ }
4130
+
4131
+ /**
4132
+ * Metadata types: slide comments, compatibility warnings, tags,
4133
+ * custom properties, core/app document properties.
4134
+ *
4135
+ * @module pptx-types/metadata
4136
+ */
4137
+ /**
4138
+ * A slide comment — may be a legacy positional comment or a modern
4139
+ * threaded comment with replies.
4140
+ *
4141
+ * @example
4142
+ * ```ts
4143
+ * const comment: PptxComment = {
4144
+ * id: "c1",
4145
+ * text: "Please update this chart.",
4146
+ * author: "Alice",
4147
+ * createdAt: "2024-06-01T10:00:00Z",
4148
+ * resolved: false,
4149
+ * };
4150
+ * // => satisfies PptxComment
4151
+ * ```
4152
+ */
4153
+ interface PptxComment {
4154
+ id: string;
4155
+ text: string;
4156
+ /** Optional parent comment id for reply threading metadata. */
4157
+ parentId?: string;
4158
+ author?: string;
4159
+ createdAt?: string;
4160
+ x?: number;
4161
+ y?: number;
4162
+ /** Whether this comment has been resolved/marked done. */
4163
+ resolved?: boolean;
4164
+ /** Modern threaded comment support (p15:threadingInfo). */
4165
+ threadId?: string;
4166
+ /** Replies to this comment (for modern threaded comments). */
4167
+ replies?: PptxComment[];
4168
+ /** ID of the element this comment is associated with (if any). */
4169
+ elementId?: string;
4170
+ }
4171
+ /**
4172
+ * A compatibility warning generated during parse or save when the
4173
+ * file uses features not fully supported by the editor.
4174
+ *
4175
+ * @example
4176
+ * ```ts
4177
+ * const warning: PptxCompatibilityWarning = {
4178
+ * code: "UNSUPPORTED_3D",
4179
+ * message: "3D rotation effects may not render accurately.",
4180
+ * severity: "warning",
4181
+ * scope: "element",
4182
+ * slideId: "slide-1",
4183
+ * elementId: "elem-42",
4184
+ * };
4185
+ * // => satisfies PptxCompatibilityWarning
4186
+ * ```
4187
+ */
4188
+ interface PptxCompatibilityWarning {
4189
+ code: string;
4190
+ message: string;
4191
+ severity: 'info' | 'warning';
4192
+ scope: 'presentation' | 'slide' | 'element' | 'save';
4193
+ slideId?: string;
4194
+ elementId?: string;
4195
+ xmlPath?: string;
4196
+ }
4197
+
4198
+ /**
4199
+ * Slide transition types and the {@link PptxSlideTransition} data structure.
4200
+ *
4201
+ * Represents the `<p:transition>` element on each slide, including
4202
+ * transition type, duration, direction, and advance timing.
4203
+ *
4204
+ * @module pptx-types/transition
4205
+ */
4206
+
4207
+ /**
4208
+ * Available slide transition effects.
4209
+ *
4210
+ * Maps to the OOXML child element names under `<p:transition>` / `<p14:transition>`.
4211
+ *
4212
+ * @example
4213
+ * ```ts
4214
+ * const t: PptxTransitionType = "morph";
4215
+ * // => "morph" — one of 40+ transition effects
4216
+ * ```
4217
+ */
4218
+ type PptxTransitionType = 'none' | 'cut' | 'fade' | 'push' | 'wipe' | 'split' | 'randomBar' | 'blinds' | 'checker' | 'circle' | 'comb' | 'cover' | 'diamond' | 'dissolve' | 'plus' | 'pull' | 'random' | 'strips' | 'uncover' | 'wedge' | 'wheel' | 'zoom' | 'newsflash' | 'morph' | 'conveyor' | 'doors' | 'ferris' | 'flash' | 'flythrough' | 'gallery' | 'glitter' | 'honeycomb' | 'pan' | 'prism' | 'reveal' | 'ripple' | 'shred' | 'switch' | 'vortex' | 'warp' | 'wheelReverse' | 'window' | 'cube' | 'flip' | 'rotate' | 'orbit';
4219
+ /** Split orientation from OOXML `@_orient`. */
4220
+ type PptxSplitOrientation = 'horz' | 'vert';
4221
+ /**
4222
+ * Slide transition configuration.
4223
+ *
4224
+ * @example
4225
+ * ```ts
4226
+ * const transition: PptxSlideTransition = {
4227
+ * type: "fade",
4228
+ * durationMs: 700,
4229
+ * advanceOnClick: true,
4230
+ * advanceAfterMs: 5000,
4231
+ * };
4232
+ * // => { type: "fade", durationMs: 700, advanceOnClick: true, advanceAfterMs: 5000 }
4233
+ * ```
4234
+ */
4235
+ interface PptxSlideTransition {
4236
+ type: PptxTransitionType;
4237
+ durationMs?: number;
4238
+ direction?: string;
4239
+ advanceOnClick?: boolean;
4240
+ advanceAfterMs?: number;
4241
+ /** Number of spokes for wheel transition (1-8). */
4242
+ spokes?: number;
4243
+ /** Pattern type for shred transition. */
4244
+ pattern?: string;
4245
+ /** Through-black flag for blinds/checker (OOXML `@_thruBlk`). */
4246
+ thruBlk?: boolean;
4247
+ /** Split orientation (horz/vert) parsed from `@_orient`. */
4248
+ orient?: PptxSplitOrientation;
4249
+ /** Relationship ID of transition sound from `p:sndAc/p:stSnd/@r:embed` when present. */
4250
+ soundRId?: string;
4251
+ /** Resolved transition sound media path within the package. */
4252
+ soundPath?: string;
4253
+ /** Human-readable sound file name (extracted from soundPath). */
4254
+ soundFileName?: string;
4255
+ /**
4256
+ * When true, the transition stops the currently-playing sound (OOXML `p:sndAc/p:endSnd`).
4257
+ * Mutually exclusive with `soundRId`/`soundPath` (which use `p:stSnd`).
4258
+ */
4259
+ stopSound?: boolean;
4260
+ /** Preserved sound-action XML node from `p:sndAc` for lossless round-trip. */
4261
+ rawSoundAction?: XmlObject;
4262
+ /** Preserved extension-list XML node from `p:extLst` within the transition for lossless round-trip. */
4263
+ rawExtLst?: XmlObject;
4264
+ }
4265
+
4266
+ /**
4267
+ * A customer data reference from `p:custDataLst / p:custData`.
4268
+ *
4269
+ * Enterprise add-ins and integrations store custom data parts in the
4270
+ * package and reference them via relationship IDs in the slide or
4271
+ * presentation XML.
4272
+ *
4273
+ * @see ECMA-376 Part 1, §19.2.1.3 (custDataLst), §19.3.1.6 (custData)
4274
+ */
4275
+ interface PptxCustomerData {
4276
+ /** Resolved part path inside the package (e.g. `ppt/customerData/item1.xml`). */
4277
+ id: string;
4278
+ /** Relationship ID referencing the custom data part. */
4279
+ relId: string;
4280
+ /** Raw string content of the custom data part (if resolvable). */
4281
+ data?: string;
4282
+ }
4283
+ /**
4284
+ * An ActiveX control reference from `p:controls / p:control`.
4285
+ *
4286
+ * ActiveX form controls (buttons, text boxes, check boxes, combo boxes, etc.)
4287
+ * are embedded via OLE parts and referenced by relationship ID in the slide XML.
4288
+ *
4289
+ * @see ECMA-376 Part 1, §19.3.1.3 (controls), §19.3.1.2 (control)
4290
+ */
4291
+ interface PptxActiveXControl {
4292
+ /** Relationship ID referencing the ActiveX binary part. */
4293
+ relId: string;
4294
+ /** Control name from @name attribute. */
4295
+ name?: string;
4296
+ /** Shape ID this control is linked to (from @spid). */
4297
+ shapeId?: string;
4298
+ /** Raw XML for round-trip preservation. */
4299
+ rawXml?: XmlObject;
4300
+ }
4301
+ /**
4302
+ * Pattern fill on a slide background.
4303
+ *
4304
+ * Mirrors the `<a:pattFill>` choice inside `<p:bgPr>`. Renderers should
4305
+ * draw a 2-colour preset pattern (e.g. `dkDnDiag`, `pct50`).
4306
+ *
4307
+ * ECMA-376 §20.1.8.47.
4308
+ *
4309
+ * @example
4310
+ * ```ts
4311
+ * const pattern: PptxSlideBackgroundPattern = {
4312
+ * preset: "ltDnDiag",
4313
+ * fgColor: "#4472C4",
4314
+ * bgColor: "#FFFFFF",
4315
+ * };
4316
+ * // => satisfies PptxSlideBackgroundPattern
4317
+ * ```
4318
+ */
4319
+ interface PptxSlideBackgroundPattern {
4320
+ /** DrawingML preset pattern token (`@_prst`). */
4321
+ preset: string;
4322
+ /** Foreground colour resolved to `#RRGGBB`. */
4323
+ fgColor?: string;
4324
+ /** Background colour resolved to `#RRGGBB`. */
4325
+ bgColor?: string;
4326
+ }
4327
+ /**
4328
+ * A single slide in a parsed PPTX presentation.
4329
+ *
4330
+ * Contains the element tree, background settings, notes, comments,
4331
+ * transition / animation data, and metadata like layout path and section.
4332
+ *
4333
+ * @example
4334
+ * ```ts
4335
+ * const slide: PptxSlide = {
4336
+ * id: "slide1",
4337
+ * rId: "rId2",
4338
+ * slideNumber: 1,
4339
+ * elements: [titleTextBox, subtitleTextBox],
4340
+ * backgroundColor: "#FFFFFF",
4341
+ * notes: "Remember to mention quarterly goals.",
4342
+ * };
4343
+ * // => satisfies PptxSlide
4344
+ * ```
4345
+ */
4346
+ interface PptxSlide {
4347
+ id: string;
4348
+ rId: string;
4349
+ sourceSlideId?: string;
4350
+ /** Optional author-supplied slide name (set via `SlideBuilder.setName`). */
4351
+ name?: string;
4352
+ layoutPath?: string;
4353
+ layoutName?: string;
4354
+ slideNumber: number;
4355
+ hidden?: boolean;
4356
+ sectionName?: string;
4357
+ sectionId?: string;
4358
+ elements: PptxElement[];
4359
+ backgroundColor?: string;
4360
+ backgroundImage?: string;
4361
+ backgroundGradient?: string;
4362
+ /**
4363
+ * Pattern fill on the slide background (`<a:pattFill>` inside `<p:bgPr>`).
4364
+ *
4365
+ * When present, renderers should draw a real two-colour pattern using
4366
+ * the named DrawingML preset (e.g. `"ltDnDiag"`, `"pct50"`). The flat
4367
+ * `backgroundColor` field is left set to the foreground colour for
4368
+ * fallback rendering paths that don't understand patterns.
4369
+ *
4370
+ * ECMA-376 §20.1.8.47.
4371
+ */
4372
+ backgroundPattern?: PptxSlideBackgroundPattern;
4373
+ /**
4374
+ * `<p:bgPr/@shadeToTitle>` — boolean flag instructing the renderer to
4375
+ * shade the background toward the title placeholder colour. Captured
4376
+ * for lossless round-trip; the React renderer currently treats it as
4377
+ * a passthrough hint.
4378
+ *
4379
+ * ECMA-376 §19.3.1.2 (CT_BackgroundProperties).
4380
+ */
4381
+ backgroundShadeToTitle?: boolean;
4382
+ transition?: PptxSlideTransition;
4383
+ animations?: PptxElementAnimation[];
4384
+ /** Native OOXML animation data parsed from `p:timing`. */
4385
+ nativeAnimations?: PptxNativeAnimation[];
4386
+ /** Preserved raw `p:timing` XML for lossless round-trip of native animations. */
4387
+ rawTiming?: XmlObject;
4388
+ notes?: string;
4389
+ /** Rich text segments for the slide notes (preserves formatting). */
4390
+ notesSegments?: TextSegment[];
4391
+ /**
4392
+ * Parsed shapes from the notes slide's `<p:cSld>/<p:spTree>` so the full
4393
+ * notes-page shape tree can be inspected and mutated, not just the body
4394
+ * placeholder text. When undefined, the existing notes XML is left
4395
+ * untouched on save and only `notes` / `notesSegments` are written.
4396
+ */
4397
+ notesShapes?: PptxElement[];
4398
+ /**
4399
+ * Per-notes-slide colour map override parsed from `<p:notes>/<p:clrMapOvr>`.
4400
+ * Captured for lossless round-trip of the notes-slide's colour scheme.
4401
+ */
4402
+ notesClrMapOverride?: Record<string, string>;
4403
+ /** Optional `<p:cSld @name>` value of the notes slide, for round-trip. */
4404
+ notesCSldName?: string;
4405
+ comments?: PptxComment[];
4406
+ warnings?: PptxCompatibilityWarning[];
4407
+ rawXml?: XmlObject;
4408
+ /** Per-slide colour map override parsed from `p:clrMapOvr`. */
4409
+ clrMapOverride?: Record<string, string>;
4410
+ /** Whether background animations should play (`p:bg/@showAnimation`). */
4411
+ backgroundShowAnimation?: boolean;
4412
+ /** Whether master slide shapes should be shown on this slide (`p:sld/@showMasterSp`). */
4413
+ showMasterShapes?: boolean;
4414
+ /** Drawing guides parsed from slide extension list. */
4415
+ guides?: PptxDrawingGuide[];
4416
+ /** When explicitly `false`, the slide is unmodified and save can skip re-serialization. */
4417
+ isDirty?: boolean;
4418
+ /** Customer data references from `p:custDataLst` on this slide. */
4419
+ customerData?: PptxCustomerData[];
4420
+ /** ActiveX control references from `p:controls` on this slide. */
4421
+ activeXControls?: PptxActiveXControl[];
4422
+ /** Per-slide header/footer flags from `<p:hf>` (P-H3). */
4423
+ headerFooterFlags?: PptxHeaderFooterFlags;
4424
+ }
4425
+
4426
+ /** Viewer interaction mode: read-only, edit, presentation, or master-view. */
4427
+ type ViewerMode = 'preview' | 'edit' | 'present' | 'master';
4428
+ /**
4429
+ * Framework-agnostic imperative API contract for the PowerPoint viewer.
4430
+ *
4431
+ * Each binding (React `forwardRef` handle, Vue `defineExpose`, Angular public
4432
+ * methods) implements this interface so consumers get a consistent progressive
4433
+ * API regardless of framework.
4434
+ */
4435
+ interface PowerPointViewerAPI {
4436
+ /** Serialise the current presentation to `.pptx` bytes. */
4437
+ getContent: () => Promise<Uint8Array>;
4438
+ /** Navigate to a specific slide by zero-based index. */
4439
+ goTo: (slideIndex: number) => void;
4440
+ /** Navigate to the previous slide. */
4441
+ goPrev: () => void;
4442
+ /** Navigate to the next slide. */
4443
+ goNext: () => void;
4444
+ /** Undo the last editing action. No-op when nothing to undo. */
4445
+ undo: () => void;
4446
+ /** Redo the last undone action. No-op when nothing to redo. */
4447
+ redo: () => void;
4448
+ /** Whether an undo action is available. */
4449
+ canUndo: () => boolean;
4450
+ /** Whether a redo action is available. */
4451
+ canRedo: () => boolean;
4452
+ /** Get the current zoom level (1 = 100%). */
4453
+ getZoom: () => number;
4454
+ /** Set the zoom level (clamped to min/max bounds). */
4455
+ setZoom: (level: number) => void;
4456
+ /** Zoom in by one step. */
4457
+ zoomIn: () => void;
4458
+ /** Zoom out by one step. */
4459
+ zoomOut: () => void;
4460
+ /** Reset zoom to 100%. */
4461
+ zoomReset: () => void;
4462
+ /** Get the current viewer mode. */
4463
+ getMode: () => ViewerMode;
4464
+ /** Switch the viewer mode (e.g. 'edit', 'preview', 'present'). */
4465
+ setMode: (mode: ViewerMode) => void;
4466
+ /** Get the zero-based active slide index. */
4467
+ getActiveSlideIndex: () => number;
4468
+ /** Set the active slide by zero-based index (alias of goTo). */
4469
+ setActiveSlideIndex: (index: number) => void;
4470
+ /** Get the total number of slides. */
4471
+ getSlideCount: () => number;
4472
+ /** Whether the document has unsaved changes. */
4473
+ isDirty: () => boolean;
4474
+ /**
4475
+ * Get the full slide array. Returns the actual `PptxSlide[]` from the
4476
+ * internal model with full type information (elements, notes, transitions,
4477
+ * animations, etc.). The returned reference is a snapshot; mutations are
4478
+ * not reflected back unless done via the manipulation methods.
4479
+ */
4480
+ getSlides: () => readonly PptxSlide[];
4481
+ /** Get a single slide by zero-based index, or undefined if out of range. */
4482
+ getSlide: (index: number) => PptxSlide | undefined;
4483
+ /** Get the currently active slide. */
4484
+ getActiveSlide: () => PptxSlide | undefined;
4485
+ /** Add a blank slide after the given index (or at end if omitted). */
4486
+ addSlide: (afterIndex?: number) => void;
4487
+ /** Delete slides at the given zero-based indexes. At least one slide is kept. */
4488
+ deleteSlides: (indexes: number[]) => void;
4489
+ /** Duplicate slides at the given zero-based indexes. */
4490
+ duplicateSlides: (indexes: number[]) => void;
4491
+ /** Move a slide from one position to another. */
4492
+ moveSlide: (fromIndex: number, toIndex: number) => void;
4493
+ /** Toggle the hidden flag on slides at the given indexes. */
4494
+ toggleHideSlides: (indexes: number[]) => void;
4495
+ /**
4496
+ * Get the elements on a slide. Defaults to the active slide when
4497
+ * `slideIndex` is omitted. Returns the full `PptxElement[]` with
4498
+ * all type-specific properties intact.
4499
+ */
4500
+ getElements: (slideIndex?: number) => readonly PptxElement[];
4501
+ /** Get a single element by ID from the active slide (or a specified slide). */
4502
+ getElementById: (elementId: string, slideIndex?: number) => PptxElement | undefined;
4503
+ /**
4504
+ * Update one or more properties of an element by ID on the active slide.
4505
+ * Accepts a `Partial<PptxElement>` patch (e.g. `{ x: 100, width: 300 }`).
4506
+ */
4507
+ updateElement: (elementId: string, updates: Partial<PptxElement>) => void;
4508
+ /** Delete elements by their IDs from the active slide. */
4509
+ deleteElements: (elementIds: string[]) => void;
4510
+ /**
4511
+ * Duplicate an element on the active slide.
4512
+ * Returns the new element's ID, or undefined if the source was not found.
4513
+ */
4514
+ duplicateElement: (elementId: string) => string | undefined;
4515
+ /** Get the IDs of currently selected elements. */
4516
+ getSelectedElementIds: () => string[];
4517
+ /** Programmatically select elements by their IDs. */
4518
+ selectElements: (ids: string[]) => void;
4519
+ /** Clear the current selection. */
4520
+ clearSelection: () => void;
4521
+ }
4522
+ /** Collaboration role within a session. */
4523
+ type CollaborationRole = 'owner' | 'collaborator' | 'viewer';
4524
+ /**
4525
+ * Collaboration transport.
4526
+ *
4527
+ * - `'websocket'` (default): y-websocket against `serverUrl`.
4528
+ * - `'webrtc'`: y-webrtc peer-to-peer; needs no document server. Peers meet
4529
+ * through the `signaling` servers (WebRTC signaling only, no document data)
4530
+ * and same-browser tabs additionally sync via BroadcastChannel even without
4531
+ * any signaling server, which makes this mode usable from static hosting.
4532
+ */
4533
+ type CollaborationTransport = 'websocket' | 'webrtc';
4534
+ /**
4535
+ * Real-time collaboration configuration.
4536
+ *
4537
+ * The same shape is accepted by the React, Vue, and Angular bindings.
4538
+ */
4539
+ interface CollaborationConfig {
4540
+ /** Unique identifier for the collaboration room (alphanumeric, hyphens, underscores). */
4541
+ roomId: string;
4542
+ /**
4543
+ * WebSocket server URL for the Yjs provider (e.g. "wss://collab.example.com").
4544
+ * Ignored (may be empty) when `transport` is `'webrtc'`.
4545
+ */
4546
+ serverUrl: string;
4547
+ /** Transport to use. Defaults to `'websocket'`. */
4548
+ transport?: CollaborationTransport;
4549
+ /**
4550
+ * WebRTC signaling server URLs (only used when `transport` is `'webrtc'`).
4551
+ * Defaults to y-webrtc's built-in public signaling list. Same-browser tabs
4552
+ * sync via BroadcastChannel regardless of signaling availability.
4553
+ */
4554
+ signaling?: string[];
4555
+ /** Display name for the local user. */
4556
+ userName: string;
4557
+ /** Avatar URL for the local user (optional). */
4558
+ userAvatar?: string;
4559
+ /** Hex colour for the local user's cursor/presence indicator. */
4560
+ userColor?: string;
4561
+ /** Optional authentication token sent with the WebSocket handshake. */
4562
+ authToken?: string;
4563
+ /** Role in the session; defaults to `'collaborator'`. */
4564
+ role?: CollaborationRole;
4565
+ /**
4566
+ * Elected-writer write-back callback (Area 3 of the C3 hardening plan).
4567
+ *
4568
+ * When the local user has `role: 'owner'`, the binding debounces changes and
4569
+ * serializes the current Y.Doc state to a PPTX byte array, then calls this
4570
+ * callback so the host can persist the snapshot. Only one writer (the owner)
4571
+ * does this; other collaborators never trigger write-back, eliminating the
4572
+ * last-save-wins problem.
4573
+ */
4574
+ onWriteBack?: (bytes: Uint8Array) => void;
4575
+ /**
4576
+ * Debounce delay (ms) between the last Y.Doc change and the write-back
4577
+ * invocation. Defaults to 5000 ms. Set to 0 to write back on every change
4578
+ * (not recommended for large documents).
4579
+ */
4580
+ writeBackDebounceMs?: number;
4581
+ }
4582
+ /**
4583
+ * A font supplied by the host application. The package never ships fonts:
4584
+ * applications provide a licensed URL, data URL, or blob URL for their users.
4585
+ */
4586
+ interface ViewerFontSource {
4587
+ family: string;
4588
+ src: string;
4589
+ format?: 'truetype' | 'opentype' | 'woff' | 'woff2';
4590
+ weight?: string | number;
4591
+ style?: 'normal' | 'italic';
4592
+ }
4593
+
4594
+ //#endregion
4595
+ //#region src/theme/context.d.ts
9
4596
  interface ViewerThemeProviderProps {
10
- theme?: ViewerTheme;
11
- children: React.ReactNode;
4597
+ theme?: ViewerTheme;
4598
+ children: React.ReactNode;
12
4599
  }
13
4600
  /**
14
4601
  * Provides a `ViewerTheme` to all descendant viewer components.
@@ -18,13 +4605,168 @@ interface ViewerThemeProviderProps {
18
4605
  * for advanced use-cases where you want to wrap multiple viewers or
19
4606
  * share a theme across a wider subtree.
20
4607
  */
21
- declare function ViewerThemeProvider({ theme, children }: ViewerThemeProviderProps): React$1.JSX.Element;
4608
+ declare function ViewerThemeProvider({ theme, children }: ViewerThemeProviderProps): react.JSX.Element;
22
4609
  /**
23
4610
  * Returns the active `ViewerTheme` (if any) from the nearest
24
4611
  * `ViewerThemeProvider`.
25
4612
  */
26
4613
  declare function useViewerTheme(): ViewerTheme | undefined;
4614
+ //#endregion
4615
+ //#region src/viewer/types-ui.d.ts
4616
+ /**
4617
+ * Base handle interface for file viewer components.
4618
+ * Defined locally to avoid dependency on external file-viewer plugin packages.
4619
+ * Provides a standard `getContent` method used by the host application to
4620
+ * retrieve the current file content (e.g. for saving).
4621
+ */
4622
+ interface FileViewerHandle {
4623
+ /** Get the current content of the file (for saving) */
4624
+ getContent: () => Promise<string | Uint8Array>;
4625
+ }
4626
+ interface PowerPointViewerProps {
4627
+ /** PowerPoint content as Uint8Array */
4628
+ content: Uint8Array;
4629
+ /** Licensed fonts supplied by the host application. No fonts are bundled. */
4630
+ fonts?: ViewerFontSource[];
4631
+ /** Original file path, used for autosave recovery */
4632
+ filePath?: string;
4633
+ /**
4634
+ * Display name of the open document, shown in the PowerPoint-style title
4635
+ * bar (e.g. "quarterly-review.pptx"). Falls back to a generic label.
4636
+ */
4637
+ fileName?: string;
4638
+ /** Callback when content has unsaved changes */
4639
+ onDirtyChange?: (isDirty: boolean) => void;
4640
+ onContentChange?: (content: Uint8Array) => void;
4641
+ /** Callback when active slide changes */
4642
+ onActiveSlideChange?: (slideIndex: number) => void;
4643
+ /** Callback when the viewer mode changes (e.g. edit to present). */
4644
+ onModeChange?: (mode: ViewerMode) => void;
4645
+ /** Callback when the zoom level changes. */
4646
+ onZoomChange?: (zoom: number) => void;
4647
+ /** Callback when element selection changes. */
4648
+ onSelectionChange?: (elementIds: string[]) => void;
4649
+ /** Callback when the total slide count changes (slide added/deleted). */
4650
+ onSlideCountChange?: (count: number) => void;
4651
+ /**
4652
+ * Host override for the File ▸ Open action. When provided, the built-in
4653
+ * native file picker is bypassed and this is invoked instead; the host is
4654
+ * then responsible for supplying a new `content` buffer. When omitted, the
4655
+ * viewer opens its own picker and loads the chosen presentation in place.
4656
+ */
4657
+ onOpenFile?: () => void;
4658
+ /** Whether editing actions are enabled */
4659
+ canEdit?: boolean;
4660
+ /** Optional class name */
4661
+ className?: string;
4662
+ /**
4663
+ * Display name used as the author for comments and annotations.
4664
+ * Falls back to `collaboration.userName` when collaborating, or `'You'`.
4665
+ */
4666
+ authorName?: string;
4667
+ /**
4668
+ * Theme configuration for customising the viewer's appearance.
4669
+ *
4670
+ * Accepts partial color overrides, a custom border-radius, and
4671
+ * arbitrary CSS custom properties. Unset values fall back to the
4672
+ * built-in dark theme.
4673
+ *
4674
+ * @example
4675
+ * ```tsx
4676
+ * <PowerPointViewer
4677
+ * content={bytes}
4678
+ * theme={{
4679
+ * colors: { primary: "#6366f1", background: "#0f172a" },
4680
+ * radius: "0.75rem",
4681
+ * }}
4682
+ * />
4683
+ * ```
4684
+ *
4685
+ * @see {@link ViewerTheme} for the full type definition.
4686
+ */
4687
+ theme?: ViewerTheme;
4688
+ /**
4689
+ * Optional real-time collaboration configuration.
4690
+ *
4691
+ * When provided, the viewer enables collaborative editing with live
4692
+ * cursors, user presence indicators, and CRDT-based state sync via Yjs.
4693
+ * Requires `yjs` and `y-websocket` peer dependencies.
4694
+ *
4695
+ * @example
4696
+ * ```tsx
4697
+ * <PowerPointViewer
4698
+ * content={bytes}
4699
+ * collaboration={{
4700
+ * roomId: "my-room-123",
4701
+ * serverUrl: "wss://collab.example.com",
4702
+ * userName: "Alice",
4703
+ * userColor: "#6366f1",
4704
+ * }}
4705
+ * />
4706
+ * ```
4707
+ */
4708
+ collaboration?: CollaborationConfig;
4709
+ /**
4710
+ * Callback invoked when the user starts a collaboration session from the
4711
+ * Share dialog. The host app should use this to set the `collaboration`
4712
+ * prop with the returned config.
4713
+ */
4714
+ onStartCollaboration?: (config: CollaborationConfig) => void;
4715
+ /**
4716
+ * Callback invoked when the user stops a collaboration session from the
4717
+ * Share dialog. The host app should clear the `collaboration` prop.
4718
+ */
4719
+ onStopCollaboration?: () => void;
4720
+ /**
4721
+ * Default values for the Share dialog fields. The host app should provide
4722
+ * these to control the session name, user display name, and server URL.
4723
+ * If omitted, the Share dialog fields will be empty and require user input.
4724
+ *
4725
+ * @example
4726
+ * ```tsx
4727
+ * <PowerPointViewer
4728
+ * shareDefaults={{
4729
+ * roomId: "session-abc123",
4730
+ * userName: "Alice",
4731
+ * serverUrl: "ws://localhost:1234",
4732
+ * }}
4733
+ * />
4734
+ * ```
4735
+ */
4736
+ shareDefaults?: {
4737
+ roomId?: string;
4738
+ userName?: string;
4739
+ serverUrl?: string;
4740
+ };
4741
+ /**
4742
+ * Opt in to the experimental Three.js SmartArt renderer. When `true`,
4743
+ * SmartArt diagrams render as extruded 3D blocks on a WebGL canvas instead
4744
+ * of flat SVG. Requires the optional `three` peer dependency; when it is not
4745
+ * installed (or the diagram has no geometry), the viewer transparently falls
4746
+ * back to the SVG `SmartArtRenderer`. Default `false`.
4747
+ */
4748
+ smartArt3D?: boolean;
4749
+ }
4750
+ interface PowerPointViewerHandle extends FileViewerHandle, PowerPointViewerAPI {
4751
+ getContent: () => Promise<Uint8Array>;
4752
+ }
4753
+
4754
+ //#region src/viewer/utils/animation-effects.d.ts
4755
+ declare function getAnimationInitialStyle(preset: PptxAnimationPreset | undefined, nativeAnimation?: PptxNativeAnimation): react__default.CSSProperties;
4756
+ //#endregion
4757
+ //#region src/viewer/PowerPointViewer.d.ts
4758
+ /**
4759
+ * Root React component for the PowerPoint viewer/editor.
4760
+ *
4761
+ * Accepts binary `.pptx` content and renders a full-featured editor with
4762
+ * slide canvas, toolbar, inspector panels, presentation mode, and more.
4763
+ *
4764
+ * Uses `forwardRef` to expose a `PowerPointViewerHandle` for imperative
4765
+ * access (e.g. serialising the current content for saving).
4766
+ */
4767
+ declare const PowerPointViewer: react.ForwardRefExoticComponent<PowerPointViewerProps & react.RefAttributes<PowerPointViewerHandle>>;
27
4768
 
4769
+ //#region src/lib/canvas-export.d.ts
28
4770
  /**
29
4771
  * A drop-in replacement for `html2canvas(element, options)` that first
30
4772
  * resolves any oklch / oklab / lch / lab / color() values in the cloned
@@ -43,4 +4785,5 @@ declare function useViewerTheme(): ViewerTheme | undefined;
43
4785
  */
44
4786
  declare function renderToCanvas(element: HTMLElement, options?: Partial<Options>): Promise<HTMLCanvasElement>;
45
4787
 
46
- export { ViewerThemeProvider, renderToCanvas, useViewerTheme };
4788
+ export { PowerPointViewer, ViewerThemeProvider, defaultCssVars, defaultRadius, defaultThemeColors, getAnimationInitialStyle, renderToCanvas, themeToCssVars, useViewerTheme, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius };
4789
+ export type { PowerPointViewerAPI, PowerPointViewerHandle, PowerPointViewerProps, ViewerMode, ViewerTheme, ViewerThemeColors };