pptx-vanilla-viewer 0.5.1 → 0.7.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.
package/dist/index.d.cts DELETED
@@ -1,2918 +0,0 @@
1
- import { n, o, m, P, a, e, f, X, p, q, r, s, t, u, v, w, x, y, z, A, B, D, E, F, G, H, J, K, L, i, j, l, k, g, h, a0, ca } from './presentation-BfnrtJV1.js';
2
- export { a as PptxElement, P as PptxSlide } from './presentation-BfnrtJV1.js';
3
- import { ViewerTheme } from './theme/index.js';
4
- export { ViewerTheme, ViewerThemeColors, defaultCssVars, defaultRadius, defaultThemeColors, themeToCssVars, vermilionDarkTheme, vermilionLightTheme } from './theme/index.js';
5
- export { TranslationKey, keyToLabel, translationsEn } from 'pptx-viewer-shared/i18n';
6
-
7
- /**
8
- * Built-in theme presets modelled after common PowerPoint themes.
9
- *
10
- * Each preset provides:
11
- * - A display name
12
- * - A 12-colour scheme (dk1, dk2, lt1, lt2, accent1-6, hlink, folHlink)
13
- * - A font scheme (major/heading + minor/body font families)
14
- *
15
- * These presets can be passed directly to
16
- * {@link PptxHandlerCore.switchTheme} or the React `useThemeSwitching` hook
17
- * to apply a complete theme in one step.
18
- *
19
- * @module pptx-types/theme-presets
20
- */
21
-
22
- /**
23
- * A complete theme preset that can be applied to a presentation.
24
- *
25
- * @example
26
- * ```ts
27
- * import { THEME_PRESETS } from "pptx-viewer-core";
28
- *
29
- * const office = THEME_PRESETS.find(p => p.id === "office");
30
- * await handler.switchTheme(office.colorScheme, office.fontScheme, office.name);
31
- * ```
32
- */
33
- interface PptxThemePreset {
34
- /** Unique identifier for the preset. */
35
- id: string;
36
- /** Human-readable display name. */
37
- name: string;
38
- /** The 12-colour scheme. */
39
- colorScheme: e;
40
- /** Heading and body font families. */
41
- fontScheme: f;
42
- }
43
-
44
- /**
45
- * SDK input types for the headless PPTX builder API.
46
- *
47
- * These types provide a simplified, ergonomic interface for creating
48
- * presentation elements programmatically. Internal types (PptxElement,
49
- * ShapeStyle, TextStyle) are the canonical model; these types are
50
- * convenience wrappers that get mapped to the internal model by
51
- * the builder functions.
52
- *
53
- * @module sdk/types
54
- */
55
-
56
- /** Position and size in pixels. Converted to EMU internally when needed. */
57
- interface ElementPosition {
58
- x: number;
59
- y: number;
60
- width: number;
61
- height: number;
62
- rotation?: number;
63
- }
64
- type FillInput = {
65
- type: 'solid';
66
- color: string;
67
- opacity?: number;
68
- } | {
69
- type: 'gradient';
70
- angle?: number;
71
- gradientType?: 'linear' | 'radial';
72
- stops: Array<{
73
- color: string;
74
- position: number;
75
- opacity?: number;
76
- }>;
77
- } | {
78
- type: 'pattern';
79
- preset: string;
80
- foreground?: string;
81
- background?: string;
82
- } | {
83
- type: 'image';
84
- url: string;
85
- mode?: 'stretch' | 'tile';
86
- } | {
87
- type: 'none';
88
- };
89
- interface StrokeInput {
90
- color?: string;
91
- width?: number;
92
- dash?: i;
93
- opacity?: number;
94
- join?: 'round' | 'bevel' | 'miter';
95
- cap?: 'flat' | 'rnd' | 'sq';
96
- }
97
- interface ShadowInput {
98
- color?: string;
99
- blur?: number;
100
- offsetX?: number;
101
- offsetY?: number;
102
- opacity?: number;
103
- }
104
- interface TextStyleInput {
105
- fontSize?: number;
106
- fontFamily?: string;
107
- bold?: boolean;
108
- italic?: boolean;
109
- underline?: boolean;
110
- strikethrough?: boolean;
111
- color?: string;
112
- alignment?: 'left' | 'center' | 'right' | 'justify';
113
- verticalAlignment?: 'top' | 'middle' | 'bottom';
114
- lineSpacing?: number;
115
- spaceBefore?: number;
116
- spaceAfter?: number;
117
- }
118
- interface TextSegmentInput {
119
- text: string;
120
- style?: Partial<TextStyleInput>;
121
- }
122
- interface TextOptions extends Partial<ElementPosition> {
123
- fontSize?: number;
124
- fontFamily?: string;
125
- bold?: boolean;
126
- italic?: boolean;
127
- underline?: boolean;
128
- strikethrough?: boolean;
129
- color?: string;
130
- alignment?: 'left' | 'center' | 'right' | 'justify';
131
- verticalAlignment?: 'top' | 'middle' | 'bottom';
132
- lineSpacing?: number;
133
- fill?: FillInput;
134
- stroke?: StrokeInput;
135
- shadow?: ShadowInput;
136
- opacity?: number;
137
- }
138
- interface ShapeOptions extends Partial<ElementPosition> {
139
- fill?: FillInput;
140
- stroke?: StrokeInput;
141
- text?: string;
142
- textStyle?: Partial<TextStyleInput>;
143
- adjustments?: Record<string, number>;
144
- shadow?: ShadowInput;
145
- opacity?: number;
146
- }
147
- interface ImageOptions extends Partial<ElementPosition> {
148
- altText?: string;
149
- cropLeft?: number;
150
- cropTop?: number;
151
- cropRight?: number;
152
- cropBottom?: number;
153
- opacity?: number;
154
- }
155
- interface TableInput {
156
- rows: TableRowInput[];
157
- columnWidths?: number[];
158
- style?: string;
159
- bandRows?: boolean;
160
- bandColumns?: boolean;
161
- firstRow?: boolean;
162
- lastRow?: boolean;
163
- firstCol?: boolean;
164
- lastCol?: boolean;
165
- }
166
- interface TableRowInput {
167
- cells: TableCellInput[];
168
- height?: number;
169
- }
170
- interface TableCellInput {
171
- text: string;
172
- style?: Partial<TextStyleInput>;
173
- fill?: FillInput;
174
- gridSpan?: number;
175
- rowSpan?: number;
176
- }
177
- interface TableOptions extends Partial<ElementPosition> {
178
- }
179
- interface ChartSeriesInput {
180
- name: string;
181
- values: number[];
182
- color?: string;
183
- }
184
- interface ChartInput {
185
- series: ChartSeriesInput[];
186
- categories: string[];
187
- title?: string;
188
- hasLegend?: boolean;
189
- legendPosition?: 't' | 'b' | 'l' | 'r' | 'tr';
190
- grouping?: 'clustered' | 'stacked' | 'percentStacked';
191
- }
192
- interface ChartOptions extends Partial<ElementPosition> {
193
- }
194
- interface ConnectorOptions extends Partial<ElementPosition> {
195
- type?: 'straight' | 'bent' | 'curved';
196
- stroke?: StrokeInput;
197
- startArrow?: j;
198
- endArrow?: j;
199
- from?: {
200
- elementId: string;
201
- site: number;
202
- };
203
- to?: {
204
- elementId: string;
205
- site: number;
206
- };
207
- }
208
- interface MediaOptions extends Partial<ElementPosition> {
209
- autoPlay?: boolean;
210
- loop?: boolean;
211
- volume?: number;
212
- trimStartMs?: number;
213
- trimEndMs?: number;
214
- posterFrame?: string;
215
- }
216
- interface GroupOptions extends Partial<ElementPosition> {
217
- }
218
- type BackgroundInput = {
219
- type: 'solid';
220
- color: string;
221
- } | {
222
- type: 'gradient';
223
- angle?: number;
224
- stops: Array<{
225
- color: string;
226
- position: number;
227
- }>;
228
- } | {
229
- type: 'image';
230
- source: string;
231
- };
232
- interface TransitionInput {
233
- type: k;
234
- duration?: number;
235
- direction?: string;
236
- advanceAfterMs?: number;
237
- }
238
- interface AnimationInput {
239
- preset: g;
240
- trigger?: h;
241
- duration?: number;
242
- delay?: number;
243
- }
244
- interface PresentationOptions {
245
- /** Slide width in EMU. Default: 12192000 (16:9 widescreen). */
246
- width?: number;
247
- /** Slide height in EMU. Default: 6858000 (16:9 widescreen). */
248
- height?: number;
249
- /** Theme configuration. */
250
- theme?: PresentationThemeInput;
251
- /** Presentation title (stored in docProps/core.xml). */
252
- title?: string;
253
- /** Presentation author. */
254
- creator?: string;
255
- /**
256
- * Number of blank slides to include in the initial presentation.
257
- * Default: 0 (no slides). Slides use the "Blank" layout.
258
- */
259
- initialSlideCount?: number;
260
- }
261
- interface PresentationThemeInput {
262
- name?: string;
263
- colors?: {
264
- dk1?: string;
265
- lt1?: string;
266
- dk2?: string;
267
- lt2?: string;
268
- accent1?: string;
269
- accent2?: string;
270
- accent3?: string;
271
- accent4?: string;
272
- accent5?: string;
273
- accent6?: string;
274
- hlink?: string;
275
- folHlink?: string;
276
- };
277
- fonts?: {
278
- majorFont?: string;
279
- minorFont?: string;
280
- };
281
- }
282
-
283
- /**
284
- * Fluent builder for constructing slides with elements.
285
- *
286
- * Provides a chainable API for adding elements, setting slide properties,
287
- * and building a complete {@link PptxSlide}.
288
- *
289
- * @module sdk/SlideBuilder
290
- */
291
-
292
- /**
293
- * Fluent builder for a single slide.
294
- *
295
- * @example
296
- * ```ts
297
- * const slide = new SlideBuilder(1)
298
- * .addText("Hello World", { fontSize: 36, bold: true, x: 100, y: 50 })
299
- * .addShape("roundRect", { fill: { type: "solid", color: "#4472C4" } })
300
- * .setNotes("Remember to mention key points")
301
- * .setBackground({ type: "solid", color: "#F5F5F5" })
302
- * .build();
303
- * ```
304
- */
305
- declare class SlideBuilder {
306
- private readonly slide;
307
- /**
308
- * @param slideNumber - 1-based slide number.
309
- * @param layoutPath - Optional layout archive path.
310
- * @param layoutName - Optional layout display name.
311
- */
312
- constructor(slideNumber: number, layoutPath?: string, layoutName?: string);
313
- /** Add a text box to the slide. */
314
- addText(text: string | TextSegmentInput[], options?: TextOptions): this;
315
- /** Add a shape to the slide. */
316
- addShape(shapeType: string, options?: ShapeOptions): this;
317
- /** Add a connector (line) to the slide. */
318
- addConnector(options?: ConnectorOptions): this;
319
- /** Add an image to the slide. */
320
- addImage(source: string, options?: ImageOptions): this;
321
- /** Add a table to the slide. */
322
- addTable(input: TableInput, options?: TableOptions): this;
323
- /** Add a chart to the slide. */
324
- addChart(chartType: l, input: ChartInput, options?: ChartOptions): this;
325
- /** Add a media element (video or audio) to the slide. */
326
- addMedia(mediaType: 'video' | 'audio', source: string, options?: MediaOptions): this;
327
- /** Add a group of elements to the slide. */
328
- addGroup(children: a[], options?: GroupOptions): this;
329
- /** Add a pre-built element directly. */
330
- addElement(element: a): this;
331
- /** Set slide background. */
332
- setBackground(bg: BackgroundInput): this;
333
- /** Set slide transition. */
334
- setTransition(input: TransitionInput): this;
335
- /** Add an animation to an element on this slide. */
336
- addAnimation(elementId: string, input: AnimationInput): this;
337
- /** Set speaker notes. */
338
- setNotes(text: string): this;
339
- /** Mark the slide as hidden. */
340
- setHidden(hidden: boolean): this;
341
- /** Assign the slide to a section. */
342
- setSection(name: string, id?: string): this;
343
- /**
344
- * Add a freeform shape from SVG path data.
345
- *
346
- * Creates a custom-geometry shape element using the provided SVG path
347
- * string and appends it to the slide's element list.
348
- *
349
- * @param pathData - An SVG path data string (e.g. `"M 0 0 L 100 50 L 50 100 Z"`).
350
- * @param options - Optional position, styling, and size overrides.
351
- * @returns The builder instance for chaining.
352
- *
353
- * @example
354
- * ```ts
355
- * new SlideBuilder(1)
356
- * .addFreeform("M 0 0 C 33 0 66 100 100 100", {
357
- * stroke: { color: "#FF0000", width: 2 },
358
- * })
359
- * .build();
360
- * ```
361
- */
362
- addFreeform(pathData: string, options?: ShapeOptions): this;
363
- /**
364
- * Add a pre-built element from any element builder (calls `.build()` for you).
365
- *
366
- * Accepts any object with a `build()` method that returns a {@link PptxElement},
367
- * such as {@link TextBuilder}, {@link ShapeBuilder}, {@link ImageBuilder}, etc.
368
- *
369
- * @param builder - An element builder with a `.build()` method.
370
- * @returns The builder instance for chaining.
371
- *
372
- * @example
373
- * ```ts
374
- * const title = TextBuilder.create("Hello").fontSize(36).bold();
375
- * new SlideBuilder(1).addBuilderElement(title).build();
376
- * ```
377
- */
378
- addBuilderElement(builder: {
379
- build(): a;
380
- }): this;
381
- /**
382
- * Remove an element by its ID.
383
- *
384
- * Filters out the element with the given ID from the slide's element list.
385
- * If no element matches, the slide is left unchanged.
386
- *
387
- * @param elementId - The unique ID of the element to remove.
388
- * @returns The builder instance for chaining.
389
- *
390
- * @example
391
- * ```ts
392
- * const slide = new SlideBuilder(1)
393
- * .addText("temp", { x: 0, y: 0 })
394
- * .removeElement("txt_abc123_1")
395
- * .build();
396
- * ```
397
- */
398
- removeElement(elementId: string): this;
399
- /**
400
- * Get the current list of elements on this slide.
401
- *
402
- * Returns a readonly view of the elements array. Useful for inspecting
403
- * what has been added so far during the build process.
404
- *
405
- * @returns A readonly array of the slide's current elements.
406
- *
407
- * @example
408
- * ```ts
409
- * const builder = new SlideBuilder(1).addText("Hi");
410
- * console.log(builder.getElements().length); // 1
411
- * ```
412
- */
413
- getElements(): readonly a[];
414
- /**
415
- * Get the number of elements on this slide.
416
- *
417
- * @returns The count of elements currently added to the slide.
418
- *
419
- * @example
420
- * ```ts
421
- * const builder = new SlideBuilder(1)
422
- * .addText("A").addText("B");
423
- * console.log(builder.elementCount); // 2
424
- * ```
425
- */
426
- get elementCount(): number;
427
- /**
428
- * Get the last added element (useful for getting its ID for animations).
429
- *
430
- * Returns `undefined` if the slide has no elements yet.
431
- *
432
- * @returns The most recently added element, or `undefined`.
433
- *
434
- * @example
435
- * ```ts
436
- * const builder = new SlideBuilder(1).addShape("rect");
437
- * const shape = builder.getLastElement();
438
- * if (shape) {
439
- * builder.addAnimation(shape.id, { preset: "fadeIn" });
440
- * }
441
- * ```
442
- */
443
- getLastElement(): a | undefined;
444
- /**
445
- * Set the slide name/title for organizational purposes.
446
- *
447
- * Stores an arbitrary name string on the slide object. This is useful
448
- * for labeling slides in tooling or custom workflows.
449
- *
450
- * @param name - The display name to assign to the slide.
451
- * @returns The builder instance for chaining.
452
- *
453
- * @example
454
- * ```ts
455
- * new SlideBuilder(1)
456
- * .setName("Introduction")
457
- * .addText("Welcome!")
458
- * .build();
459
- * ```
460
- */
461
- setName(name: string): this;
462
- /** Return the built {@link PptxSlide}. */
463
- build(): P;
464
- }
465
-
466
- /**
467
- * Factory for creating PPTX presentations from scratch.
468
- *
469
- * Generates a minimal valid OpenXML package (ZIP) containing all
470
- * required parts (presentation.xml, theme, slide master, layouts,
471
- * content types, relationships, and document properties). The
472
- * generated package is then loaded by {@link PptxHandler} so that
473
- * all existing editing and save operations work transparently.
474
- *
475
- * @module sdk/PresentationBuilder
476
- */
477
-
478
- /** Result returned by {@link PresentationBuilder.create}. */
479
- interface PresentationBuilderResult {
480
- /** Initialized handler ready for editing and saving. */
481
- handler: PptxHandler;
482
- /** Parsed presentation data. */
483
- data: m;
484
- /** Convenience slide builder factory. */
485
- createSlide: (layoutName?: string) => SlideBuilder;
486
- }
487
-
488
- /**
489
- * Fluent interface for navigating and mutating a {@link PptxData} structure.
490
- * Provides method-chaining access to slides, elements, and notes.
491
- */
492
- interface IPptxXmlBuilder {
493
- /** Navigate to a slide by zero-based index (Pascal-case alias). */
494
- Slides(index: number): PptxSlideBuilder;
495
- /** Navigate to a slide by zero-based index. */
496
- slide(index: number): PptxSlideBuilder;
497
- /** Navigate to a slide by zero-based index (plural alias). */
498
- slides(index: number): PptxSlideBuilder;
499
- /** Return the underlying presentation data. */
500
- project(): m;
501
- }
502
- /**
503
- * Root builder of the fluent PPTX editing API.
504
- *
505
- * Wraps a {@link PptxData} object and provides chainable accessors
506
- * to navigate into slides, elements, and notes for in-place mutation.
507
- */
508
- declare class PptxXmlBuilder implements IPptxXmlBuilder {
509
- /** The presentation data being mutated. */
510
- private readonly data;
511
- /** @param data - The presentation data to wrap. */
512
- constructor(data: m);
513
- /**
514
- * Factory method to create a builder from presentation data.
515
- * @param data - The presentation data to wrap.
516
- * @returns A new {@link PptxXmlBuilder} instance.
517
- */
518
- static from(data: m): PptxXmlBuilder;
519
- /** @inheritdoc */
520
- Slides(index: number): PptxSlideBuilder;
521
- /**
522
- * Navigate to a slide by zero-based index.
523
- * @param index - Zero-based slide index.
524
- * @returns A {@link PptxSlideBuilder} for the requested slide.
525
- * @throws Error if index is not an integer or is out of range.
526
- */
527
- slide(index: number): PptxSlideBuilder;
528
- /** @inheritdoc */
529
- slides(index: number): PptxSlideBuilder;
530
- /** Return the underlying {@link PptxData}. */
531
- project(): m;
532
- /** Pascal-case alias for {@link project}. */
533
- Project(): m;
534
- }
535
- /**
536
- * Fluent builder scoped to a single slide.
537
- * Provides navigation to the slide's elements and notes.
538
- */
539
- declare class PptxSlideBuilder {
540
- /** The slide being operated on. */
541
- private readonly slideValue;
542
- /** Reference back to the root builder for chaining. */
543
- private readonly rootBuilder;
544
- /**
545
- * @param slideValue - The slide data.
546
- * @param rootBuilder - The parent builder.
547
- */
548
- constructor(slideValue: P, rootBuilder: PptxXmlBuilder);
549
- /** Navigate to the slide's notes builder (getter). */
550
- get Notes(): PptxSlideNotesBuilder;
551
- /** Navigate to the slide's notes builder. */
552
- notes(): PptxSlideNotesBuilder;
553
- /** Navigate to the slide's elements builder. */
554
- elements(): PptxSlideElementsBuilder;
555
- /** Return the underlying slide data. */
556
- project(): P;
557
- /** Pascal-case alias for {@link project}. */
558
- Project(): P;
559
- /** Navigate back to the root builder. */
560
- done(): PptxXmlBuilder;
561
- /** Pascal-case alias for {@link done}. */
562
- Done(): PptxXmlBuilder;
563
- }
564
- /**
565
- * Fluent builder for manipulating the elements array of a single slide.
566
- * Supports adding, removing, and updating elements by ID.
567
- */
568
- declare class PptxSlideElementsBuilder {
569
- private readonly slideValue;
570
- private readonly slideBuilder;
571
- /**
572
- * @param slideValue - The slide whose elements are being modified.
573
- * @param slideBuilder - The parent slide builder for chaining.
574
- */
575
- constructor(slideValue: P, slideBuilder: PptxSlideBuilder);
576
- /**
577
- * Append an element to the slide's element list.
578
- * @param element - The element to add.
579
- * @returns This builder for chaining.
580
- */
581
- add(element: a): this;
582
- /**
583
- * Remove an element from the slide by its ID.
584
- * @param elementId - The ID of the element to remove.
585
- * @returns This builder for chaining.
586
- */
587
- removeById(elementId: string): this;
588
- /**
589
- * Update an element in-place by ID using a transform function.
590
- * @param elementId - The ID of the element to update.
591
- * @param updater - A function that receives the current element and returns the replacement.
592
- * @returns This builder for chaining.
593
- */
594
- updateById(elementId: string, updater: (current: a) => a): this;
595
- /** Return the current elements array. */
596
- project(): a[];
597
- /** Navigate back to the slide builder. */
598
- done(): PptxSlideBuilder;
599
- }
600
- /**
601
- * Fluent builder for manipulating speaker notes on a single slide.
602
- * Supports adding, setting, clearing, and retrieving notes text.
603
- */
604
- declare class PptxSlideNotesBuilder {
605
- private readonly slideValue;
606
- private readonly slideBuilder;
607
- /**
608
- * @param slideValue - The slide whose notes are being modified.
609
- * @param slideBuilder - The parent slide builder for chaining.
610
- */
611
- constructor(slideValue: P, slideBuilder: PptxSlideBuilder);
612
- /**
613
- * Append text to existing notes (separated by newline).
614
- * @param text - The text to append.
615
- * @returns This builder for chaining.
616
- */
617
- add(text: string): this;
618
- /** Pascal-case alias for {@link add}. */
619
- Add(text: string): this;
620
- /**
621
- * Replace all notes with the given text.
622
- * @param text - The replacement notes text. Empty string clears notes.
623
- * @returns This builder for chaining.
624
- */
625
- set(text: string): this;
626
- /** Pascal-case alias for {@link set}. */
627
- Set(text: string): this;
628
- /** Remove all notes from the slide. */
629
- clear(): this;
630
- /** Pascal-case alias for {@link clear}. */
631
- Clear(): this;
632
- /** Return the current notes text, or `undefined` if none. */
633
- get(): string | undefined;
634
- /** Pascal-case alias for {@link get}. */
635
- Get(): string | undefined;
636
- /** Navigate back to the slide builder. */
637
- done(): PptxSlideBuilder;
638
- /** Pascal-case alias for {@link done}. */
639
- Done(): PptxSlideBuilder;
640
- /**
641
- * Synchronize the `notesSegments` array from the plain-text notes string.
642
- * Splits text on newlines and creates corresponding {@link TextSegment} entries
643
- * with paragraph break markers between lines.
644
- */
645
- private syncSegmentsFromNotes;
646
- }
647
-
648
- interface PptxHandlerLoadOptions {
649
- eagerDecodeImages?: boolean;
650
- password?: string;
651
- /**
652
- * Maximum total uncompressed bytes accepted from the input ZIP archive.
653
- * Defaults to 500 MiB. When the sum of `_data.uncompressedSize` across
654
- * all archive entries exceeds this cap, `load()` rejects with a
655
- * {@link ZipBombError}. A hard cap of 65 536 archive entries also
656
- * applies.
657
- */
658
- maxUncompressedBytes?: number;
659
- /**
660
- * When `false` (default), relationship targets that resolve to
661
- * `http://` or `https://` URLs are dropped from rendered slides
662
- * (image, picture, background). Set to `true` to allow external image
663
- * URLs to flow through to `<img src>`.
664
- *
665
- * Disabled by default to mitigate SSRF / privacy-leak vectors in
666
- * server-side rendering and headless export pipelines.
667
- */
668
- allowExternalImages?: boolean;
669
- }
670
- /** Output format for the save pipeline. */
671
- type PptxSaveFormat = 'pptx' | 'ppsx' | 'pptm';
672
- interface PptxHandlerSaveOptions {
673
- headerFooter?: r;
674
- presentationProperties?: s;
675
- customShows?: t[];
676
- sections?: u[];
677
- coreProperties?: v;
678
- appProperties?: w;
679
- customProperties?: x[];
680
- /** Updated notes master data to save back to notesMaster1.xml. */
681
- notesMaster?: y;
682
- /** Updated handout master data to save back to handoutMaster1.xml. */
683
- handoutMaster?: z;
684
- /**
685
- * Updated slide masters to save back to ppt/slideMasters/slideMaster*.xml.
686
- * Each entry in the array applies typed mutations (clrMap, hf flags,
687
- * background) to the master at its `path`. Masters not listed here pass
688
- * through verbatim from the original load.
689
- */
690
- slideMasters?: A[];
691
- /**
692
- * Updated slide layouts to save back to ppt/slideLayouts/slideLayout*.xml.
693
- * Each entry applies typed mutations (clrMapOverride, attrs, hf flags,
694
- * background) to the layout at its `path`. Layouts not listed here pass
695
- * through verbatim from the original load.
696
- */
697
- slideLayouts?: B[];
698
- /** Updated tag collections to save back to ppt/tags/tag*.xml. */
699
- tags?: D[];
700
- /** Photo album metadata to save back to `p:photoAlbum`. */
701
- photoAlbum?: E;
702
- /** East Asian line-break settings to save back to `p:kinsoku`. */
703
- kinsoku?: F;
704
- /** Write-protection verifier. Set to `null` to remove, `undefined` to preserve existing. */
705
- modifyVerifier?: G | null;
706
- /** View properties to save back to ppt/viewProps.xml. */
707
- viewProperties?: H;
708
- /**
709
- * Table style edits to save back to `ppt/tableStyles.xml`. Pass the
710
- * `tableStyleMap` from `PptxData` (optionally with edited entries)
711
- * to persist user edits. The `def` GUID and any unmodelled XML are
712
- * preserved verbatim. Omitting the option round-trips the original
713
- * part untouched.
714
- */
715
- tableStyles?: J;
716
- /**
717
- * Target output format.
718
- * - `'pptx'` (default): Standard presentation.
719
- * - `'ppsx'`: Slide-show file (opens in presentation mode).
720
- * - `'pptm'`: Macro-enabled presentation (requires VBA data).
721
- */
722
- outputFormat?: PptxSaveFormat;
723
- /**
724
- * Embedded fonts to write back (or add) to the saved PPTX.
725
- *
726
- * Pass the `embeddedFonts` array from `PptxData` to preserve existing
727
- * embedded fonts during save. You can also add new fonts by including
728
- * entries with `rawFontData` populated.
729
- *
730
- * When omitted, the save pipeline will automatically re-embed any
731
- * fonts that were loaded from the original PPTX and have `rawFontData`
732
- * preserved (i.e. the default is lossless round-trip).
733
- */
734
- embeddedFonts?: K[];
735
- /**
736
- * OOXML conformance class for the saved output.
737
- * - `'preserve'` (default): use the same conformance as the loaded file.
738
- * - `'strict'`: force Strict Open XML (ISO/IEC 29500) namespace URIs.
739
- * - `'transitional'`: force Transitional (ECMA-376) namespace URIs.
740
- */
741
- conformance?: 'strict' | 'transitional' | 'preserve';
742
- }
743
- interface IPptxHandlerRuntime {
744
- /**
745
- * Release all resources held by this runtime (Blob URLs, caches, ZIP).
746
- * After calling, the runtime cannot be used further.
747
- */
748
- dispose(): void;
749
- /**
750
- * Revoke all Blob URLs created during image loading.
751
- */
752
- revokeBlobUrls(): void;
753
- getCompatibilityWarnings(): n[];
754
- getLayoutOptions(): o[];
755
- createXmlBuilder(data: m): PptxXmlBuilder;
756
- Builder(data: m): PptxXmlBuilder;
757
- setTemplateBackground(path: string, backgroundColor: string | undefined): void;
758
- setPresentationTheme(themePath: string, applyToAllMasters?: boolean): Promise<void>;
759
- getTemplateBackgroundColor(path: string): string | undefined;
760
- updateThemeColorScheme(colorScheme: e): Promise<void>;
761
- updateThemeFontScheme(fontScheme: f): Promise<void>;
762
- updateThemeName(name: string): Promise<void>;
763
- applyTheme(colorScheme: e, fontScheme: f, themeName?: string): Promise<void>;
764
- load(data: ArrayBuffer, options?: PptxHandlerLoadOptions): Promise<m>;
765
- getChartDataForGraphicFrame(slidePath: string, graphicFrame: X | undefined): Promise<p | undefined>;
766
- getSmartArtDataForGraphicFrame(slidePath: string, graphicFrame: X | undefined): Promise<q | undefined>;
767
- getImageData(imagePath: string): Promise<string | undefined>;
768
- /**
769
- * Extract a media file from the PPTX archive as an ArrayBuffer.
770
- * Returns undefined if the file is not found.
771
- */
772
- getMediaArrayBuffer(mediaPath: string): Promise<ArrayBuffer | undefined>;
773
- save(slides: P[], options?: PptxHandlerSaveOptions): Promise<Uint8Array>;
774
- exportSlides(slides: P[], options: L): Promise<Map<number, Uint8Array>>;
775
- /**
776
- * Get the available slide layouts for a specific slide, based on the
777
- * slide's master. Scans the slide master's relationships to find all
778
- * layouts that belong to it.
779
- *
780
- * @param slideIndex - Zero-based slide index.
781
- * @param slides - Current slides array.
782
- * @returns Array of layout options belonging to the same slide master.
783
- */
784
- getAvailableLayoutsForSlide(slideIndex: number, slides: P[]): Promise<o[]>;
785
- /**
786
- * Resolve the editable template (master + layout) elements a slide
787
- * inherits, each carrying a `master-` / `layout-` prefixed id. Excludes
788
- * placeholders; returns only decorative shapes/pictures/graphic frames.
789
- *
790
- * @param slideId - The slide's archive path (`PptxSlide.id`).
791
- */
792
- getTemplateElementsForSlide(slideId: string): Promise<a[]>;
793
- /**
794
- * Scan the loaded PPTX archive for all theme parts.
795
- */
796
- getAvailableThemes(): Promise<Array<{
797
- path: string;
798
- name?: string;
799
- }>>;
800
- /**
801
- * Apply a different layout to an existing slide by updating the slide's
802
- * relationship to point to the new layout and re-parsing layout
803
- * placeholders / background.
804
- *
805
- * @param slideIndex - Zero-based slide index.
806
- * @param layoutPath - Archive path of the target layout
807
- * (e.g. `ppt/slideLayouts/slideLayout2.xml`).
808
- * @param slides - Current slides array.
809
- * @returns The updated slide with new layout path, name, and background.
810
- */
811
- applyLayoutToSlide(slideIndex: number, layoutPath: string, slides: P[]): Promise<P>;
812
- }
813
-
814
- /**
815
- * Abstract factory contract for creating {@link IPptxHandlerRuntime}
816
- * instances.
817
- *
818
- * Implement this interface to supply a custom runtime (e.g. a
819
- * WASM-backed or test-double runtime) to {@link PptxHandlerCore}.
820
- */
821
- interface IPptxHandlerRuntimeFactory {
822
- /** Instantiate and return a new runtime implementation. */
823
- createRuntime(): IPptxHandlerRuntime;
824
- }
825
-
826
- /**
827
- * Type definitions for OOXML encryption and decryption.
828
- *
829
- * Contains all interfaces and type aliases used by the OOXML crypto modules.
830
- *
831
- * @module ooxml-crypto-types
832
- */
833
- /** Supported encryption algorithms. */
834
- type EncryptionAlgorithm = 'AES128' | 'AES256';
835
- /** Encryption options for creating encrypted files. */
836
- interface EncryptionOptions {
837
- /** The encryption algorithm to use (defaults to AES256). */
838
- algorithm?: EncryptionAlgorithm;
839
- /** Number of hash iterations for key derivation (defaults to 100000). Lower values speed up tests. */
840
- spinCount?: number;
841
- }
842
-
843
- /**
844
- * Dependency injection options for {@link PptxHandlerCore}.
845
- *
846
- * Provide either `runtime` (an already-constructed runtime) or
847
- * `runtimeFactory` (a factory that will be called once). When neither
848
- * is supplied the default runtime is created automatically.
849
- *
850
- * @example
851
- * ```ts
852
- * // Use the default runtime:
853
- * const core = new PptxHandlerCore();
854
- *
855
- * // Inject a custom runtime:
856
- * const core = new PptxHandlerCore({ runtime: myRuntime });
857
- *
858
- * // Supply a factory for lazy creation:
859
- * const core = new PptxHandlerCore({ runtimeFactory: myFactory });
860
- * // => PptxHandlerCore instance with injected runtime
861
- * ```
862
- */
863
- interface PptxHandlerCoreDependencies {
864
- runtime?: IPptxHandlerRuntime;
865
- runtimeFactory?: IPptxHandlerRuntimeFactory;
866
- }
867
- /**
868
- * Thin facade over the PPTX runtime implementation.
869
- *
870
- * All heavy parsing, serialisation, and XML manipulation is delegated to an
871
- * {@link IPptxHandlerRuntime}. This surface stays stable and small so that
872
- * callers remain decoupled from the runtime internals and host-specific
873
- * runtime swaps (e.g. WASM vs Node) can be done transparently.
874
- *
875
- * @remarks
876
- * - Constructed once per open document.
877
- * - Errors from encrypted files are caught at `load()` time via
878
- * {@link EncryptedFileError}.
879
- * - `PptxXmlBuilder` instances returned by `createXmlBuilder()` / `Builder()`
880
- * operate directly on the runtime’s in-memory ZIP.
881
- *
882
- * @example
883
- * ```ts
884
- * const handler = new PptxHandlerCore();
885
- * const data = await handler.load(arrayBuffer);
886
- * // ... mutate slides ...
887
- * const out = await handler.save(data.slides);
888
- * // => Uint8Array of the modified .pptx file
889
- * ```
890
- */
891
- declare class PptxHandlerCore {
892
- private readonly runtime;
893
- /**
894
- * Create a new handler, optionally injecting a custom runtime.
895
- *
896
- * Resolution order:
897
- * 1. `dependencies.runtime` — use as-is.
898
- * 2. `dependencies.runtimeFactory` — call `createRuntime()` once.
899
- * 3. Fall back to {@link createDefaultPptxHandlerRuntime}.
900
- *
901
- * @param dependencies - Optional runtime or factory override.
902
- *
903
- * @example
904
- * ```ts
905
- * const core = new PptxHandlerCore();
906
- * // => PptxHandlerCore instance with default runtime
907
- * ```
908
- */
909
- constructor(dependencies?: PptxHandlerCoreDependencies);
910
- /**
911
- * Release all resources held by this handler instance.
912
- *
913
- * Revokes every Blob URL created for images/media, clears all
914
- * in-memory caches, and releases the in-memory ZIP archive.
915
- *
916
- * Call this when the handler is no longer needed (e.g. component
917
- * unmount) to free memory immediately rather than waiting for GC.
918
- *
919
- * After calling `dispose()`, do not call any other methods — create
920
- * a new `PptxHandler` instance instead.
921
- */
922
- dispose(): void;
923
- /**
924
- * Return any compatibility warnings detected during the most recent load.
925
- *
926
- * Warnings indicate features the editor cannot fully represent (e.g.
927
- * SmartArt, 3-D effects, embedded OLE objects).
928
- *
929
- * @returns Array of {@link PptxCompatibilityWarning} objects.
930
- */
931
- getCompatibilityWarnings(): n[];
932
- /**
933
- * Get the slide layout options available in the loaded presentation.
934
- *
935
- * Each option maps to a `<p:sldLayout>` inside the PPTX archive.
936
- *
937
- * @returns Array of {@link PptxLayoutOption} entries.
938
- */
939
- getLayoutOptions(): o[];
940
- /**
941
- * Create a fluent XML builder scoped to the given presentation data.
942
- *
943
- * The builder provides a chainable API for constructing and inserting
944
- * OpenXML nodes directly into the runtime’s in-memory ZIP.
945
- *
946
- * @param data - The parsed {@link PptxData} to bind the builder to.
947
- * @returns A new {@link PptxXmlBuilder} instance.
948
- */
949
- createXmlBuilder(data: m): PptxXmlBuilder;
950
- /**
951
- * Shorthand alias for {@link createXmlBuilder}.
952
- *
953
- * @param data - Parsed presentation data.
954
- * @returns A {@link PptxXmlBuilder} instance.
955
- */
956
- Builder(data: m): PptxXmlBuilder;
957
- /**
958
- * Register a background image for a specific template layout path.
959
- *
960
- * @param path - The internal PPTX path (e.g. `ppt/slideLayouts/slideLayout1.xml`).
961
- * @param backgroundColor - Optional hex colour to render behind the image.
962
- */
963
- setTemplateBackground(path: string, backgroundColor: string | undefined): void;
964
- /**
965
- * Retrieve the background colour previously set for a template layout.
966
- *
967
- * @param path - The internal PPTX layout path.
968
- * @returns Hex colour string, or `undefined` if none was set.
969
- */
970
- getTemplateBackgroundColor(path: string): string | undefined;
971
- /**
972
- * Replace the presentation’s theme by loading an external `.thmx` file.
973
- *
974
- * @param themePath - Absolute or relative path to the `.thmx` file.
975
- * @param applyToAllMasters - Apply to every slide master (default `true`).
976
- *
977
- * @example
978
- * ```ts
979
- * await handler.setPresentationTheme("./themes/corporate.thmx");
980
- * // => void — theme XML replaced in the in-memory ZIP
981
- * ```
982
- */
983
- setPresentationTheme(themePath: string, applyToAllMasters?: boolean): Promise<void>;
984
- /**
985
- * Modify the theme’s colour scheme (accent colours, background, text, etc.).
986
- *
987
- * @param colorScheme - A {@link PptxThemeColorScheme} with hex colour values.
988
- *
989
- * @example
990
- * ```ts
991
- * await handler.updateThemeColorScheme({
992
- * dk1: "#1A1A2E", dk2: "#16213E",
993
- * lt1: "#FFFFFF", lt2: "#E8E8E8",
994
- * accent1: "#0F3460", accent2: "#533483",
995
- * accent3: "#E94560", accent4: "#F0A500",
996
- * });
997
- * // => void — colour scheme updated in the in-memory theme XML
998
- * ```
999
- */
1000
- updateThemeColorScheme(colorScheme: e): Promise<void>;
1001
- /**
1002
- * Update the theme’s font scheme (heading + body typefaces).
1003
- *
1004
- * @param fontScheme - A {@link PptxThemeFontScheme} with font family names.
1005
- *
1006
- * @example
1007
- * ```ts
1008
- * await handler.updateThemeFontScheme({
1009
- * majorFont: "Montserrat",
1010
- * minorFont: "Open Sans",
1011
- * });
1012
- * // => void — font scheme updated in the in-memory theme XML
1013
- * ```
1014
- */
1015
- updateThemeFontScheme(fontScheme: f): Promise<void>;
1016
- /**
1017
- * Rename the presentation theme.
1018
- *
1019
- * @param name - New display name for the theme.
1020
- */
1021
- updateThemeName(name: string): Promise<void>;
1022
- /**
1023
- * Apply a complete theme in one call (colour scheme + font scheme + optional name).
1024
- *
1025
- * This is a convenience wrapper over {@link updateThemeColorScheme},
1026
- * {@link updateThemeFontScheme}, and {@link updateThemeName}.
1027
- *
1028
- * @param colorScheme - Colour definitions.
1029
- * @param fontScheme - Font definitions.
1030
- * @param themeName - Optional theme display name.
1031
- *
1032
- * @example
1033
- * ```ts
1034
- * await handler.applyTheme(
1035
- * { dk1: "#000", lt1: "#FFF", accent1: "#0066CC", /* … *\/ },
1036
- * { majorFont: "Helvetica", minorFont: "Arial" },
1037
- * "Corporate 2025",
1038
- * );
1039
- * // => void — colour scheme, font scheme, and name applied atomically
1040
- * ```
1041
- */
1042
- applyTheme(colorScheme: e, fontScheme: f, themeName?: string): Promise<void>;
1043
- /**
1044
- * Switch the presentation's theme, updating both the underlying XML and
1045
- * re-resolving all element colours in-place.
1046
- *
1047
- * This is the high-level API for theme switching: it updates the theme
1048
- * data in the ZIP, then patches all resolved colours in the provided
1049
- * `PptxData` so that elements immediately reflect the new colour scheme
1050
- * without requiring a re-parse.
1051
- *
1052
- * @param data - The current parsed presentation data (mutated in-place for
1053
- * convenience, but a new `PptxData` object is also returned).
1054
- * @param colorScheme - New colour scheme (12 colours).
1055
- * @param fontScheme - Optional new font scheme.
1056
- * @param themeName - Optional theme display name.
1057
- * @returns The updated PptxData with re-resolved colours.
1058
- *
1059
- * @example
1060
- * ```ts
1061
- * import { THEME_PRESETS } from "pptx-viewer-core";
1062
- *
1063
- * const ion = THEME_PRESETS.find(p => p.id === "ion")!;
1064
- * const newData = await handler.switchTheme(
1065
- * data,
1066
- * ion.colorScheme,
1067
- * ion.fontScheme,
1068
- * ion.name,
1069
- * );
1070
- * // => PptxData with all colours updated to the Ion theme
1071
- * ```
1072
- */
1073
- switchTheme(data: m, colorScheme: e, fontScheme?: f, themeName?: string): Promise<m>;
1074
- /**
1075
- * Apply a built-in theme preset to the presentation.
1076
- *
1077
- * Convenience wrapper around {@link switchTheme} that accepts a
1078
- * {@link PptxThemePreset} directly.
1079
- *
1080
- * @param data - The current parsed presentation data.
1081
- * @param preset - One of the built-in presets from {@link THEME_PRESETS}.
1082
- * @returns The updated PptxData.
1083
- *
1084
- * @example
1085
- * ```ts
1086
- * import { THEME_PRESETS } from "pptx-viewer-core";
1087
- *
1088
- * const preset = THEME_PRESETS.find(p => p.id === "facet")!;
1089
- * const newData = await handler.switchThemePreset(data, preset);
1090
- * ```
1091
- */
1092
- switchThemePreset(data: m, preset: PptxThemePreset): Promise<m>;
1093
- /**
1094
- * Parse a PPTX file from an `ArrayBuffer` and return structured data.
1095
- *
1096
- * If the file is encrypted and a `password` is provided in `options`,
1097
- * the file will be decrypted before parsing. If no password is provided
1098
- * for an encrypted file, throws {@link EncryptedFileError}.
1099
- *
1100
- * @param data - Raw bytes of the `.pptx` file (may be encrypted OLE2).
1101
- * @param options - Optional load-time settings, including `password`.
1102
- * @returns Parsed {@link PptxData} containing slides, theme, layouts, etc.
1103
- *
1104
- * @example
1105
- * ```ts
1106
- * // Load an unencrypted file:
1107
- * const pptx = await handler.load(buf.buffer);
1108
- *
1109
- * // Load a password-protected file:
1110
- * const pptx = await handler.load(buf.buffer, { password: "secret" });
1111
- * console.log(`${pptx.slides.length} slides loaded`);
1112
- * ```
1113
- */
1114
- load(data: ArrayBuffer, options?: PptxHandlerLoadOptions): Promise<m>;
1115
- /**
1116
- * Extract chart data from a graphic-frame XML node.
1117
- *
1118
- * @param slidePath - Internal archive path of the slide (e.g. `ppt/slides/slide1.xml`).
1119
- * @param graphicFrame - Parsed XML object for the `<p:graphicFrame>` node.
1120
- * @returns Chart data, or `undefined` if the frame is not a chart.
1121
- */
1122
- getChartDataForGraphicFrame(slidePath: string, graphicFrame: X | undefined): Promise<p | undefined>;
1123
- /**
1124
- * Extract SmartArt data from a graphic-frame XML node.
1125
- *
1126
- * @param slidePath - Internal archive path of the slide.
1127
- * @param graphicFrame - Parsed XML object for the `<p:graphicFrame>` node.
1128
- * @returns SmartArt data, or `undefined` if the frame is not SmartArt.
1129
- */
1130
- getSmartArtDataForGraphicFrame(slidePath: string, graphicFrame: X | undefined): Promise<q | undefined>;
1131
- /**
1132
- * Get the base64-encoded data URL for an embedded image.
1133
- *
1134
- * @param imagePath - Archive-relative path (e.g. `ppt/media/image1.png`).
1135
- * @returns A `data:image/...;base64,...` string, or `undefined` if not found.
1136
- */
1137
- getImageData(imagePath: string): Promise<string | undefined>;
1138
- /**
1139
- * Extract a media file from the PPTX archive as an ArrayBuffer.
1140
- * Avoids the 33% base64 overhead of getImageData — prefer this for
1141
- * audio/video media that will be played via Blob URLs.
1142
- */
1143
- getMediaArrayBuffer(mediaPath: string): Promise<ArrayBuffer | undefined>;
1144
- /**
1145
- * Serialise current slides back into a PPTX byte array.
1146
- *
1147
- * @param slides - The (possibly mutated) slide array.
1148
- * @param options - Optional save-time settings (e.g. thumbnail generation).
1149
- * @returns `Uint8Array` of the complete `.pptx` file.
1150
- *
1151
- * @example
1152
- * ```ts
1153
- * const bytes = await handler.save(data.slides);
1154
- * await fs.writeFile("output.pptx", Buffer.from(bytes));
1155
- * // => Uint8Array written to disk as a valid .pptx file
1156
- * ```
1157
- */
1158
- save(slides: P[], options?: PptxHandlerSaveOptions): Promise<Uint8Array>;
1159
- /**
1160
- * Serialise slides and then encrypt the output with a password.
1161
- *
1162
- * This is a convenience method that calls {@link save} followed by
1163
- * {@link encryptPptx}. The result is an OLE2 container suitable for
1164
- * opening in Microsoft PowerPoint with a password prompt.
1165
- *
1166
- * @param slides - The (possibly mutated) slide array.
1167
- * @param password - The password to encrypt with.
1168
- * @param options - Optional save-time and encryption settings.
1169
- * @returns `Uint8Array` of the encrypted OLE2 file.
1170
- *
1171
- * @example
1172
- * ```ts
1173
- * const bytes = await handler.saveEncrypted(data.slides, "secret");
1174
- * await fs.writeFile("protected.pptx", Buffer.from(bytes));
1175
- * // => Encrypted OLE2 file requiring password to open
1176
- * ```
1177
- */
1178
- saveEncrypted(slides: P[], password: string, options?: PptxHandlerSaveOptions & {
1179
- encryption?: EncryptionOptions;
1180
- }): Promise<Uint8Array>;
1181
- /**
1182
- * Get the slide layouts available for a specific slide.
1183
- *
1184
- * Returns layouts belonging to the same slide master as the given slide.
1185
- * This is useful for building a layout picker UI scoped to the current
1186
- * slide's master.
1187
- *
1188
- * @param slideIndex - Zero-based slide index.
1189
- * @param slides - Current slides array.
1190
- * @returns Array of {@link PptxLayoutOption} entries for the slide's master.
1191
- *
1192
- * @example
1193
- * ```ts
1194
- * const layouts = await handler.getAvailableLayoutsForSlide(0, data.slides);
1195
- * console.log(layouts.map(l => l.name));
1196
- * // => ["Title Slide", "Title and Content", "Blank", ...]
1197
- * ```
1198
- */
1199
- getAvailableLayoutsForSlide(slideIndex: number, slides: P[]): Promise<o[]>;
1200
- /**
1201
- * Resolve the editable template (master + layout) elements a slide
1202
- * inherits, each carrying a `master-` / `layout-` prefixed id.
1203
- *
1204
- * This is the foundation for an "edit template/master" feature. The
1205
- * returned elements are the decorative master/layout shapes the loader
1206
- * already merges behind slide-authored content (master shapes behind,
1207
- * layout shapes on top); placeholders are excluded. The same elements are
1208
- * shared by every slide inheriting the layout/master, so editing one and
1209
- * saving updates the shared part.
1210
- *
1211
- * To persist an edit, keep the mutated template element inside the
1212
- * `slide.elements` array passed to {@link save}; the save writer reads
1213
- * template elements from there and writes their shape XML back into the
1214
- * owning layout/master `p:spTree`.
1215
- *
1216
- * @param slideId - The slide's archive path (the `PptxSlide.id`).
1217
- * @returns Master + layout elements with prefixed ids (may be empty).
1218
- *
1219
- * @example
1220
- * ```ts
1221
- * const templateEls = await handler.getTemplateElementsForSlide(slide.id);
1222
- * const logo = templateEls.find((e) => e.id.startsWith("master-"));
1223
- * if (logo) {
1224
- * logo.x += 10;
1225
- * slide.elements = [...slide.elements, logo];
1226
- * await handler.save(data.slides);
1227
- * }
1228
- * ```
1229
- */
1230
- getTemplateElementsForSlide(slideId: string): Promise<a[]>;
1231
- /**
1232
- * Apply a different layout to an existing slide.
1233
- *
1234
- * Updates the slide's relationship to point to the new layout and
1235
- * refreshes layout-derived properties (background, layout name).
1236
- * The slide's own content elements are preserved.
1237
- *
1238
- * @param slideIndex - Zero-based slide index.
1239
- * @param layoutPath - Archive path of the target layout
1240
- * (e.g. `ppt/slideLayouts/slideLayout2.xml`).
1241
- * @param slides - Current slides array (the slide at `slideIndex`
1242
- * is replaced in-place).
1243
- * @returns The updated {@link PptxSlide} with new layout metadata.
1244
- *
1245
- * @example
1246
- * ```ts
1247
- * const updated = await handler.applyLayoutToSlide(
1248
- * 0,
1249
- * "ppt/slideLayouts/slideLayout3.xml",
1250
- * data.slides,
1251
- * );
1252
- * console.log(updated.layoutName);
1253
- * // => "Two Content"
1254
- * ```
1255
- */
1256
- applyLayoutToSlide(slideIndex: number, layoutPath: string, slides: P[]): Promise<P>;
1257
- /**
1258
- * Scan the loaded PPTX archive for all theme parts (`ppt/theme/theme*.xml`)
1259
- * and return their paths and display names.
1260
- */
1261
- getAvailableThemes(): Promise<Array<{
1262
- path: string;
1263
- name?: string;
1264
- }>>;
1265
- /**
1266
- * Export selected slides as individual PPTX files.
1267
- *
1268
- * Each entry in the returned map is keyed by slide index and contains a
1269
- * standalone `Uint8Array` PPTX with only that slide.
1270
- *
1271
- * @param slides - Full slide array.
1272
- * @param options - Export options (slide indexes, format, etc.).
1273
- * @returns A `Map<slideIndex, Uint8Array>` of exported files.
1274
- *
1275
- * @example
1276
- * ```ts
1277
- * const exports = await handler.exportSlides(data.slides, {
1278
- * slideIndexes: [0, 2],
1279
- * });
1280
- * for (const [idx, bytes] of exports) {
1281
- * await fs.writeFile(`slide_${idx}.pptx`, Buffer.from(bytes));
1282
- * }
1283
- * // => Map<number, Uint8Array> — one standalone .pptx per exported slide
1284
- * ```
1285
- */
1286
- exportSlides(slides: P[], options: L): Promise<Map<number, Uint8Array>>;
1287
- }
1288
-
1289
- /**
1290
- * Public facade for the PPTX editor handler.
1291
- *
1292
- * The implementation lives in `PptxHandlerCore` so this surface can stay small,
1293
- * stable, and easy to replace with alternate implementations in the future.
1294
- */
1295
- declare class PptxHandler extends PptxHandlerCore {
1296
- /**
1297
- * Create a new blank PPTX presentation from scratch.
1298
- *
1299
- * This is a convenience static method that delegates to
1300
- * {@link PresentationBuilder.create}. The returned handler is fully
1301
- * initialized and ready for editing, adding slides, and saving.
1302
- *
1303
- * @param options - Optional slide dimensions, theme, and metadata.
1304
- * @returns Handler, parsed data, and a slide builder factory.
1305
- *
1306
- * @example
1307
- * ```ts
1308
- * const { handler, data, createSlide } = await PptxHandler.createBlank({
1309
- * title: "My Deck",
1310
- * theme: { colors: { accent1: "#FF6B6B" } },
1311
- * });
1312
- *
1313
- * data.slides.push(
1314
- * createSlide("Blank")
1315
- * .addText("Hello", { fontSize: 36 })
1316
- * .build()
1317
- * );
1318
- *
1319
- * const bytes = await handler.save(data.slides);
1320
- * ```
1321
- */
1322
- static createBlank(options?: PresentationOptions): Promise<PresentationBuilderResult>;
1323
- /**
1324
- * Create a new PPTX presentation from scratch.
1325
- *
1326
- * Alias for {@link createBlank}. Generates a valid minimal OpenXML
1327
- * package and returns a fully initialized handler ready for editing,
1328
- * adding slides, and saving.
1329
- *
1330
- * @param options - Optional slide dimensions, theme, metadata,
1331
- * and initial slide count.
1332
- * @returns Handler, parsed data, and a slide builder factory.
1333
- *
1334
- * @example
1335
- * ```ts
1336
- * const { handler, data, createSlide } = await PptxHandler.create({
1337
- * title: "Q4 Report",
1338
- * initialSlideCount: 3,
1339
- * theme: { colors: { accent1: "#FF6B6B" } },
1340
- * });
1341
- *
1342
- * // The presentation already has 3 blank slides
1343
- * console.log(data.slides.length); // => 3
1344
- *
1345
- * // Add more slides with content
1346
- * data.slides.push(
1347
- * createSlide("Blank")
1348
- * .addText("Hello", { fontSize: 36 })
1349
- * .build()
1350
- * );
1351
- *
1352
- * const bytes = await handler.save(data.slides);
1353
- * ```
1354
- */
1355
- static create(options?: PresentationOptions): Promise<PresentationBuilderResult>;
1356
- }
1357
-
1358
- /**
1359
- * Framework-agnostic public types shared by the viewer bindings.
1360
- *
1361
- * These were duplicated in the React (`types-ui.ts`) and Vue (`viewer/types.ts`)
1362
- * packages; this is the canonical copy. Each binding layers its own
1363
- * framework-specific prop/event/handle types on top of these.
1364
- */
1365
-
1366
- /** Canvas dimensions in pixels. */
1367
- interface CanvasSize {
1368
- width: number;
1369
- height: number;
1370
- }
1371
- /** Collaboration role within a session. */
1372
- type CollaborationRole = 'owner' | 'collaborator' | 'viewer';
1373
- /**
1374
- * Collaboration transport.
1375
- *
1376
- * - `'websocket'` (default): y-websocket against `serverUrl`.
1377
- * - `'webrtc'`: y-webrtc peer-to-peer; needs no document server. Peers meet
1378
- * through the `signaling` servers (WebRTC signaling only, no document data)
1379
- * and same-browser tabs additionally sync via BroadcastChannel even without
1380
- * any signaling server, which makes this mode usable from static hosting.
1381
- */
1382
- type CollaborationTransport = 'websocket' | 'webrtc';
1383
- /**
1384
- * Real-time collaboration configuration.
1385
- *
1386
- * The same shape is accepted by the React, Vue, and Angular bindings.
1387
- */
1388
- interface CollaborationConfig {
1389
- /** Unique identifier for the collaboration room (alphanumeric, hyphens, underscores). */
1390
- roomId: string;
1391
- /**
1392
- * WebSocket server URL for the Yjs provider (e.g. "wss://collab.example.com").
1393
- * Ignored (may be empty) when `transport` is `'webrtc'`.
1394
- */
1395
- serverUrl: string;
1396
- /** Transport to use. Defaults to `'websocket'`. */
1397
- transport?: CollaborationTransport;
1398
- /**
1399
- * WebRTC signaling server URLs (only used when `transport` is `'webrtc'`).
1400
- * Defaults to y-webrtc's built-in public signaling list. Same-browser tabs
1401
- * sync via BroadcastChannel regardless of signaling availability.
1402
- */
1403
- signaling?: string[];
1404
- /** Display name for the local user. */
1405
- userName: string;
1406
- /** Avatar URL for the local user (optional). */
1407
- userAvatar?: string;
1408
- /** Hex colour for the local user's cursor/presence indicator. */
1409
- userColor?: string;
1410
- /** Optional authentication token sent with the WebSocket handshake. */
1411
- authToken?: string;
1412
- /** Role in the session; defaults to `'collaborator'`. */
1413
- role?: CollaborationRole;
1414
- /**
1415
- * Elected-writer write-back callback (Area 3 of the C3 hardening plan).
1416
- *
1417
- * When the local user has `role: 'owner'`, the binding debounces changes and
1418
- * serializes the current Y.Doc state to a PPTX byte array, then calls this
1419
- * callback so the host can persist the snapshot. Only one writer (the owner)
1420
- * does this; other collaborators never trigger write-back, eliminating the
1421
- * last-save-wins problem.
1422
- */
1423
- onWriteBack?: (bytes: Uint8Array) => void;
1424
- /**
1425
- * Debounce delay (ms) between the last Y.Doc change and the write-back
1426
- * invocation. Defaults to 5000 ms. Set to 0 to write back on every change
1427
- * (not recommended for large documents).
1428
- */
1429
- writeBackDebounceMs?: number;
1430
- }
1431
- /** A neutral CSS map (framework `CSSProperties` are structurally compatible). */
1432
- type CssStyleMap = Record<string, string | number>;
1433
-
1434
- /**
1435
- * `animation-authoring` — pure, immutable helpers for the editor's element
1436
- * animation authoring UI (the Animations ribbon tab / animation panel).
1437
- *
1438
- * Animation data lives on the SLIDE (`PptxSlide.animations`), keyed by
1439
- * `elementId`, NOT on the element itself. The authoring UI reads and emits the
1440
- * entire slide-level `animations` array. Every function here returns a new
1441
- * `PptxElementAnimation[]` without mutating its input, so they're trivially
1442
- * unit-testable and safe to drive editor undo/redo from.
1443
- *
1444
- * Two families coexist here, both used across the bindings:
1445
- *
1446
- * - **Granular field setters** (`setAnimationEntrance` / `setTrigger` /
1447
- * `setDuration` / … plus `reorderAnimationUp` / `removeAnimation`): the
1448
- * Angular authoring panel + React's `useAnimationHandlers` model. They
1449
- * upsert a single field on the element's entry, creating the entry with
1450
- * sensible defaults when absent and removing it when all three effect
1451
- * buckets become empty.
1452
- * - **Group preset apply/remove** (`applyAnimationPreset` /
1453
- * `removeElementAnimation`): the Vue ribbon model, a coarser
1454
- * "set one of entrance/emphasis/exit, keep the rest" upsert.
1455
- *
1456
- * The option *catalogs* here are intentionally **value-only** (preset id +
1457
- * nothing else): the human label / icon / i18n key for each option is
1458
- * framework-specific (React uses `react-icons` + label keys, Angular uses
1459
- * Unicode arrow glyphs + plain labels), so each binding maps these ids to its
1460
- * own display metadata.
1461
- *
1462
- * Pure: imports only `pptx-viewer-core` types; no framework, no DOM.
1463
- *
1464
- * @module render/animation-authoring
1465
- */
1466
-
1467
- /** One of the three animation buckets a preset can occupy on an element. */
1468
- type AnimationGroup = 'entrance' | 'emphasis' | 'exit';
1469
-
1470
- /**
1471
- * Pure geometry helpers for the align / distribute editor operations.
1472
- *
1473
- * These functions operate over a list of slide elements (anything carrying the
1474
- * `{ id, x, y, width, height }` bounding-box fields of {@link PptxElement}) and
1475
- * return a `Map` keyed by element `id` describing the *new* position(s) for the
1476
- * elements that need to move. Elements that already sit on the target edge (or
1477
- * the two outer-most elements during distribution) are still included with
1478
- * their unchanged coordinate so callers can apply the whole map uniformly — the
1479
- * map only ever contains the axis that the operation touches.
1480
- *
1481
- * The helpers are deliberately framework-agnostic: no DOM, no Vue reactivity,
1482
- * no side effects. The host wires them into the editor by feeding the current
1483
- * selection in and applying the returned `Map` via its element-transform
1484
- * operation (one batched history entry per call).
1485
- */
1486
- /** Edge / centre that {@link alignElements} can snap a selection to. */
1487
- type AlignEdge = 'left' | 'centerH' | 'right' | 'top' | 'middle' | 'bottom';
1488
-
1489
- /**
1490
- * "Change Case" text mutation (PowerPoint's Aa dropdown: Sentence case, lower,
1491
- * UPPER, Capitalize Each Word, tOGGLE cASE). Unlike `textCaps` (a purely
1492
- * visual `text-transform`-style render hint), these modes rewrite the actual
1493
- * characters, matching PowerPoint's own behaviour. Framework-agnostic; no
1494
- * framework imports.
1495
- */
1496
-
1497
- type ChangeCaseMode = 'sentence' | 'lower' | 'upper' | 'capitalize' | 'toggle';
1498
-
1499
- /**
1500
- * collaboration-presence.ts: Pure, framework-agnostic logic for the real-time
1501
- * collaboration subsystem (Yjs-backed presence + remote cursors).
1502
- *
1503
- * Everything here is a plain function with no framework / Yjs dependency, so it
1504
- * can be unit-tested in isolation and shared across the React, Vue, and Angular
1505
- * bindings. The bindings own the stateful provider lifecycle (creating the
1506
- * Y.Doc / WebsocketProvider, wiring awareness listeners) and call into these
1507
- * helpers to validate config, sanitise inbound awareness data, and project it
1508
- * into render-ready view-models.
1509
- *
1510
- * Responsibilities:
1511
- * - Validate the room id and detect mixed-content (ws:// from https) up front.
1512
- * - Sanitise inbound awareness data (XSS, bounds, colour, avatar, room id).
1513
- * - Map awareness state into a `RemoteCursor` view-model for rendering.
1514
- * - Derive the presence list (remote users only, stale entries dropped).
1515
- * - Deterministic per-user colour assignment + cursor label formatting.
1516
- *
1517
- * This mirrors the React `sanitize.ts` / `usePresenceTracking.ts` helpers and
1518
- * the Angular `collaboration-helpers.ts` (which predates this shared copy).
1519
- */
1520
-
1521
- /** Connection lifecycle states for the Yjs WebSocket provider. */
1522
- type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error';
1523
- /** A single remote collaborator's cursor, in unscaled slide coordinates. */
1524
- interface RemoteCursor {
1525
- /** Stable id for the remote client (awareness clientId or peer id). */
1526
- clientId: number | string;
1527
- /** Display name shown in the label chip. */
1528
- userName: string;
1529
- /** Cursor + chip colour (any CSS colour string). */
1530
- color: string;
1531
- /** Unscaled slide-space X coordinate (px). */
1532
- x: number;
1533
- /** Unscaled slide-space Y coordinate (px). */
1534
- y: number;
1535
- /** Optional ids of elements this user has selected. */
1536
- selectionIds?: string[];
1537
- }
1538
- /**
1539
- * Presence data for a remote collaborator, sanitised from the awareness
1540
- * protocol. Returned by {@link sanitizePresence}; coordinates are in unscaled
1541
- * slide pixels, clamped to the supplied canvas bounds.
1542
- */
1543
- interface SanitizedPresence {
1544
- clientId: number;
1545
- userName: string;
1546
- userAvatar?: string;
1547
- userColor: string;
1548
- activeSlideIndex: number;
1549
- cursorX: number;
1550
- cursorY: number;
1551
- lastUpdated: string;
1552
- selectedElementId?: string;
1553
- role?: CollaborationRole;
1554
- }
1555
-
1556
- /**
1557
- * Pure, framework-agnostic helpers for freehand ink drawing, shared by every
1558
- * binding. No framework imports, so these can be unit-tested without TestBed.
1559
- */
1560
-
1561
- /** A 2D point in stage-local coordinates. */
1562
- interface InkPoint {
1563
- x: number;
1564
- y: number;
1565
- }
1566
- /** Options for {@link strokeToInkElement}. */
1567
- interface StrokeToInkElementOpts {
1568
- points: InkPoint[];
1569
- color: string;
1570
- width: number;
1571
- tool: 'pen' | 'highlighter' | 'freeform';
1572
- }
1573
-
1574
- /**
1575
- * Pure helpers for the gradient picker editor control, shared by every binding.
1576
- *
1577
- * Readers extract current gradient values from a PptxElement (falling back to
1578
- * sensible defaults), and patch-builders produce shallow-merge-ready
1579
- * `Partial<PptxElement>` objects safe to pass to each binding's element-update
1580
- * action.
1581
- *
1582
- * No framework imports; every type is concrete or `unknown` + narrowed.
1583
- */
1584
-
1585
- /** A single gradient stop, mirroring the ShapeStyle array item shape. */
1586
- interface GradientStop {
1587
- color: string;
1588
- position: number;
1589
- opacity?: number;
1590
- }
1591
- /** The editable gradient state surfaced to the component. */
1592
- interface GradientState {
1593
- type: 'linear' | 'radial';
1594
- /** Angle in degrees (only meaningful for linear). */
1595
- angle: number;
1596
- stops: GradientStop[];
1597
- }
1598
- /** In-memory clipboard payload stored when an element is copied or cut. */
1599
- interface ElementClipboardPayload {
1600
- element: a;
1601
- isTemplate: boolean;
1602
- }
1603
-
1604
- /**
1605
- * shape-preset-catalog.ts: the Insert > Shape picker catalogue shared by every
1606
- * binding's toolbar/inspector.
1607
- *
1608
- * Pure data: each entry carries the preset geometry `type` (OOXML `a:prstGeom`
1609
- * value the editor can insert), an English fallback `label`, the shared-i18n
1610
- * `i18nKey`, and a framework-neutral icon descriptor ({@link ShapePresetGlyph}
1611
- * name + optional utility-class modifier for rotation/skew). Each binding maps
1612
- * the glyph name onto its own icon component/SVG.
1613
- *
1614
- * Order matters: bindings surface the first 12 entries as the quick "top
1615
- * shapes" row, so new presets should be appended, not inserted.
1616
- *
1617
- * @module render/shape-preset-catalog
1618
- */
1619
- /** Shape preset geometry types offered by the insert picker. */
1620
- type ShapePresetType = 'rect' | 'roundRect' | 'ellipse' | 'cylinder' | 'rtArrow' | 'leftArrow' | 'upArrow' | 'downArrow' | 'triangle' | 'rtTriangle' | 'diamond' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'hexagon' | 'octagon' | 'chevron' | 'star5' | 'star6' | 'star8' | 'plus' | 'heart' | 'cloud' | 'sun' | 'moon' | 'pie' | 'plaque' | 'teardrop' | 'line' | 'connector';
1621
- interface AutosaveRecord {
1622
- key: string;
1623
- data: Uint8Array;
1624
- timestamp: number;
1625
- size: number;
1626
- }
1627
-
1628
- /**
1629
- * Pure handout layout calculations, shared by every binding's print path.
1630
- *
1631
- * Handles distributing slides across pages, computing grid dimensions, and
1632
- * positioning cells within A4 page space. No DOM/framework dependency: callers
1633
- * render the resulting rectangles however their view layer prefers.
1634
- */
1635
- /** Supported slides-per-page values. */
1636
- type HandoutSlidesPerPage = 1 | 2 | 3 | 4 | 6 | 9;
1637
-
1638
- /**
1639
- * Pure print helpers shared by every binding's print path: settings validation,
1640
- * slide-range / colour-filter resolution, page-count estimation, HTML markup
1641
- * builders, escaping, and the full print-document assembler.
1642
- *
1643
- * No DOM side effects and no `window.print()`: everything is deterministic and
1644
- * the binding writes the returned HTML string into a print window. The handout
1645
- * grid geometry lives in `handout-layout`; this module reuses it.
1646
- *
1647
- * ng-packagr constraint honoured here (the Angular binding inlines this source
1648
- * and compiles it through ng-packagr): NO `String.prototype.replaceAll`
1649
- * (`escapeHtml` uses `.split(x).join(y)` instead).
1650
- */
1651
-
1652
- /** What to print. */
1653
- type PrintWhat = 'slides' | 'handouts' | 'notes' | 'outline';
1654
- /** Page orientation for the printed output. */
1655
- type PrintOrientation = 'portrait' | 'landscape';
1656
- /** Colour mode for the printed output. */
1657
- type PrintColorMode = 'color' | 'grayscale' | 'blackAndWhite';
1658
- /** Slide range mode. */
1659
- type PrintSlideRange = 'all' | 'current' | 'custom';
1660
- /** Resolved print settings emitted on confirm. */
1661
- interface PrintSettings {
1662
- printWhat: PrintWhat;
1663
- orientation: PrintOrientation;
1664
- colorMode: PrintColorMode;
1665
- frameSlides: boolean;
1666
- slidesPerPage: HandoutSlidesPerPage;
1667
- slideRange: PrintSlideRange;
1668
- customRangeFrom: number;
1669
- customRangeTo: number;
1670
- }
1671
-
1672
- /**
1673
- * A tiny framework-free reactive store: `get` / `set(patch)` / `subscribe`.
1674
- *
1675
- * This is deliberately minimal (a few dozen lines, no external deps). It only
1676
- * carries the vanilla binding's *view state*; all domain logic (parsing,
1677
- * styles, geometry, text building) stays in `pptx-viewer-core` and
1678
- * `pptx-viewer-shared`.
1679
- */
1680
- /** Listener invoked after every state change with the next and previous state. */
1681
- type StoreListener<T> = (state: T, previous: T) => void;
1682
- interface Store<T extends object> {
1683
- /** Current state snapshot (do not mutate). */
1684
- get(): T;
1685
- /** Shallow-merge a partial patch into the state and notify subscribers. */
1686
- set(patch: Partial<T>): void;
1687
- /** Subscribe to state changes; returns an unsubscribe function. */
1688
- subscribe(listener: StoreListener<T>): () => void;
1689
- }
1690
-
1691
- /** `zoom` is either an explicit scale factor (1 = 100%) or fit-to-viewport. */
1692
- type ZoomLevel = number | 'fit';
1693
- /**
1694
- * The Draw ribbon tab's active tool. `'select'` means normal editing gestures
1695
- * (move/resize/rotate/inline-edit) apply on the stage; every other value
1696
- * routes stage pointer events to the ink-drawing gesture controller instead
1697
- * (see `editor-draw-gestures.ts`).
1698
- */
1699
- type DrawTool = 'select' | 'pen' | 'highlighter' | 'eraser';
1700
- /**
1701
- * The vanilla viewer's reactive view state. Kept intentionally flat and small;
1702
- * everything here is what the DOM render layer consumes.
1703
- */
1704
- interface ViewerState {
1705
- /** Parsed slides (image/media URLs already patched in by the load pipeline). */
1706
- slides: P[];
1707
- /** Slide canvas size in CSS pixels. */
1708
- canvasSize: CanvasSize;
1709
- /** Archive-path to displayable URL map for media + poster frames. */
1710
- mediaDataUrls: Map<string, string>;
1711
- /** Zero-based index of the visible slide. */
1712
- currentSlide: number;
1713
- /** Requested zoom (explicit factor or fit-to-viewport). */
1714
- zoom: ZoomLevel;
1715
- /** True while a load is in flight. */
1716
- loading: boolean;
1717
- /** Error message from the last failed load, or null. */
1718
- error: string | null;
1719
- /** True while presentation (fullscreen) mode is active. */
1720
- presenting: boolean;
1721
- /** True when editing interactions (select/move/resize/...) are enabled. */
1722
- editable: boolean;
1723
- /** Id of the selected element on the current slide, or null. */
1724
- selectedElementId: string | null;
1725
- /** True when the document has unsaved edits (cleared by a save). */
1726
- dirty: boolean;
1727
- /**
1728
- * True while a pointer gesture (drag/resize/rotate) is in flight. Thumbnail
1729
- * re-renders are deferred until the gesture ends.
1730
- */
1731
- interactionActive: boolean;
1732
- /**
1733
- * True when the speaker-notes panel body is expanded. Persists across slide
1734
- * navigation for the life of the viewer instance (in-memory only).
1735
- */
1736
- notesExpanded: boolean;
1737
- /** Remote collaborators currently in the session (empty when not collaborating). */
1738
- remotePresences: SanitizedPresence[];
1739
- /** Remote cursors visible on the current slide, projected from `remotePresences`. */
1740
- cursors: RemoteCursor[];
1741
- /** Client id of the peer the local user is following, or null when free. */
1742
- followedClientId: number | null;
1743
- /** In-memory clipboard payload from the last copy/cut, or null. */
1744
- clipboardPayload: ElementClipboardPayload | null;
1745
- /** Active Draw ribbon tool; `'select'` disables the ink-drawing gesture controller. */
1746
- drawTool: DrawTool;
1747
- /** Stroke colour for the pen/highlighter tools. */
1748
- drawColor: string;
1749
- /** Stroke width (px) for the pen/highlighter tools. */
1750
- drawWidth: number;
1751
- }
1752
-
1753
- /**
1754
- * Element-animation actions for the ribbon's Animations tab.
1755
- *
1756
- * Animation data lives on the SLIDE (`PptxSlide.animations`, keyed by
1757
- * `elementId`), not on the element itself, matching how the presentation
1758
- * playback state machine reads it (`buildClickGroups(slide.animations)` in
1759
- * `animation/presentation-playback.ts`). Both actions target the currently
1760
- * selected element and route through the shared `animation-authoring.ts`
1761
- * "coarse group preset" model (`applyAnimationPreset` / `removeElementAnimation`),
1762
- * the same one the Vue ribbon uses: applying a preset sets one of
1763
- * entrance/emphasis/exit without touching the others; remove drops the whole
1764
- * entry.
1765
- */
1766
- interface AnimationActions {
1767
- addAnimation(group: AnimationGroup, preset: g): void;
1768
- removeAnimation(): void;
1769
- }
1770
-
1771
- /**
1772
- * Z-order, align, flip, and group/ungroup actions for the ribbon's
1773
- * Home > Arrange group.
1774
- *
1775
- * Align/distribute: the vanilla editor's selection model is single-element
1776
- * only (see `state/viewer-state.ts`), so `alignElements` reaches the
1777
- * single-selection "align to slide" mode ({@link alignToCanvas}), matching
1778
- * PowerPoint's own behaviour when nothing else is selected. Multi-selection
1779
- * "align to selection bounding box" / distribute (needing >= 2 / >= 3
1780
- * elements, see `editor-arrange-mutations.ts`) is unreachable until a
1781
- * multi-select model lands; `canDistribute` is therefore always `false` today
1782
- * (see `editing-chrome-sync.ts`), a documented limitation rather than a bug.
1783
- *
1784
- * Group: needs >= 2 selected elements to be meaningful, so it too is
1785
- * unreachable under single selection; `groupSelected` is a deliberate no-op
1786
- * kept only so the ribbon button (permanently disabled, with an explanatory
1787
- * title) has something to call. Ungroup works today: it applies to whichever
1788
- * single `group` element is selected.
1789
- */
1790
- interface ArrangeActions {
1791
- bringForward(): void;
1792
- sendBackward(): void;
1793
- bringToFront(): void;
1794
- sendToBack(): void;
1795
- alignElements(edge: AlignEdge): void;
1796
- flipHorizontal(): void;
1797
- flipVertical(): void;
1798
- groupSelected(): void;
1799
- ungroupSelected(): void;
1800
- }
1801
-
1802
- /**
1803
- * Slide-background actions for the ribbon's Design > Format Background panel.
1804
- * Solid-colour fill only (matches the docked panel's scope: a single colour
1805
- * input); clearing removes every background field so the slide falls back to
1806
- * its layout/master background. Both mutations are history-integrated,
1807
- * mirroring `editor-slide-actions.ts`.
1808
- */
1809
- interface SlideBackgroundActions {
1810
- setSlideBackgroundColor(color: string): void;
1811
- clearSlideBackground(): void;
1812
- }
1813
-
1814
- /**
1815
- * Cut/copy/paste actions for the ribbon's Home > Clipboard group, backed by
1816
- * the shared `element-clipboard.ts` codec. The in-memory clipboard payload
1817
- * lives on `ViewerState.clipboardPayload` (not a module-level variable) so
1818
- * the ribbon's selection sync can reactively enable/disable the Paste button.
1819
- */
1820
- interface ClipboardActions {
1821
- copy(): void;
1822
- cut(): void;
1823
- paste(): void;
1824
- }
1825
-
1826
- /**
1827
- * Ink stroke actions for the Draw ribbon tab: commit a freehand pen/
1828
- * highlighter stroke as a new `InkPptxElement`, or erase an existing one.
1829
- * Both mutations are history-integrated (push -> mutate -> commit), mirroring
1830
- * `editor-background-actions.ts` and the `insertElement` helper in
1831
- * `editor-edit-ops.ts`. The pointer-event lifecycle that accumulates a
1832
- * stroke's points lives separately in `editor-draw-gestures.ts`; this module
1833
- * only owns the resulting slide/history mutation.
1834
- */
1835
- interface InkActions {
1836
- /**
1837
- * Build an `InkPptxElement` from a completed stroke (via the shared
1838
- * `strokeToInkElement`) and append it to the current slide, selected.
1839
- * A no-op when not editable, there is no current slide, or the stroke has
1840
- * fewer than 2 points (shared helper returns `null`, matching a plain tap).
1841
- */
1842
- commitStroke(stroke: StrokeToInkElementOpts): void;
1843
- /**
1844
- * Remove the ink element with `id` from the current slide (Draw tab's
1845
- * eraser tool). Returns `true` when an ink element was found and removed;
1846
- * `false` for a missing id, a non-ink element, or a read-only viewer (safe
1847
- * to call from a generic stage hit-test without a pre-check).
1848
- */
1849
- eraseInkElement(id: string): boolean;
1850
- }
1851
-
1852
- /**
1853
- * Insert-element factories for the vanilla editor.
1854
- *
1855
- * The pure builders wrap the framework-agnostic core/shared factories
1856
- * (`createTextElement`, `createShapeElement`, `createConnectorElement`,
1857
- * `newTableElement`) and centre the new element on the slide canvas. The one
1858
- * async helper (`pickImageElement`) owns the file-picker + `FileReader` DOM
1859
- * side effects needed to turn a chosen image file into a data-URL image
1860
- * element; it too returns a centred, ready-to-insert element.
1861
- */
1862
- /** The element kinds the Insert ribbon tab can create directly. */
1863
- type InsertKind = 'text' | 'table' | 'shape';
1864
-
1865
- /**
1866
- * Element-type-aware inspector actions: text vertical-align/wrap/autofit,
1867
- * gradient fill + fill/stroke opacity, image brightness/contrast/saturation +
1868
- * crop, and table-level header-row/banded-rows/cell-padding. Every method is a
1869
- * thin `applyToSelected` wrapper around pure builders from `pptx-viewer-shared`
1870
- * (or the local `patchShapeStyle`), mirroring `editor-text-actions.ts`.
1871
- *
1872
- * These extend the base position/size/rotation + flat fill/stroke inspector
1873
- * that `editor-edit-ops.ts` already exposes; see `ui/inspector/` for the
1874
- * per-element-type panels that call these.
1875
- */
1876
- interface InspectorActions {
1877
- setTextVerticalAlign(vAlign: NonNullable<a0['vAlign']>): void;
1878
- setTextWrap(wrap: NonNullable<a0['textWrap']>): void;
1879
- setAutoFitMode(mode: NonNullable<a0['autoFitMode']>): void;
1880
- setFillOpacity(opacity: number): void;
1881
- setStrokeOpacity(opacity: number): void;
1882
- setGradientFill(state: GradientState): void;
1883
- addGradientStop(color: string, position: number): void;
1884
- removeGradientStop(index: number): void;
1885
- updateGradientStop(index: number, changes: Partial<GradientState['stops'][number]>): void;
1886
- setImageBrightness(value: number): void;
1887
- setImageContrast(value: number): void;
1888
- setImageSaturation(value: number): void;
1889
- setImageCrop(edge: 'left' | 'top' | 'right' | 'bottom', value: number): void;
1890
- setTableHeaderRow(enabled: boolean): void;
1891
- setTableBandedRows(enabled: boolean): void;
1892
- setTableCellPadding(padding: number): void;
1893
- }
1894
-
1895
- /**
1896
- * New/duplicate/delete-slide actions for the ribbon's Home > Slides group,
1897
- * backed by the shared `slide-operations.ts` factory. Every mutation is
1898
- * history-integrated (matches the element-level actions in `editor-edit-ops`)
1899
- * and renumbers `slideNumber` across the whole deck so it always matches the
1900
- * array index (mirrors the Vue `useSlideOperations` contract).
1901
- */
1902
- interface SlideActions {
1903
- addSlide(): void;
1904
- duplicateSlide(): void;
1905
- deleteSlide(): void;
1906
- }
1907
-
1908
- /**
1909
- * Character + paragraph formatting actions for the ribbon's Home > Font and
1910
- * Home > Paragraph groups. Every method is a thin `applyToSelected` wrapper
1911
- * around the pure builders in `editor-format-mutations.ts` /
1912
- * `editor-paragraph-mutations.ts`; this file owns none of the mutation logic
1913
- * itself, only the selection/history wiring shared by the whole action set.
1914
- */
1915
- interface TextActions {
1916
- toggleBold(): void;
1917
- toggleItalic(): void;
1918
- toggleUnderline(): void;
1919
- toggleStrikethrough(): void;
1920
- toggleTextShadow(): void;
1921
- changeFontSize(delta: number): void;
1922
- setFontSize(size: number): void;
1923
- setFontFamily(family: string): void;
1924
- setTextColor(color: string): void;
1925
- setHighlightColor(color: string): void;
1926
- setCharacterSpacing(value: number): void;
1927
- changeCase(mode: ChangeCaseMode): void;
1928
- clearFormatting(): void;
1929
- toggleBulletList(): void;
1930
- toggleNumberedList(): void;
1931
- increaseIndent(): void;
1932
- decreaseIndent(): void;
1933
- setTextAlign(align: a0['align']): void;
1934
- setLineSpacing(value: number): void;
1935
- }
1936
-
1937
- /**
1938
- * Slide-transition actions for the ribbon's Transitions tab. Playback already
1939
- * reads `PptxSlide.transition` (see `animation/presentation-playback.ts`), so
1940
- * this only needs to write that same field, history-integrated like every
1941
- * other ribbon mutation.
1942
- *
1943
- * `applyTransition` covers both the preset gallery buttons and the duration
1944
- * input (the tab re-applies the currently-selected preset whenever the
1945
- * duration changes), plus the "Apply to All Slides" checkbox: when
1946
- * `applyToAll` is true every slide gets the same fresh `{ type, durationMs }`
1947
- * transition; otherwise only the current slide is patched, preserving any
1948
- * advanced fields (direction, sound, ...) it already carried.
1949
- */
1950
- interface TransitionActions {
1951
- applyTransition(type: k, durationMs: number, applyToAll: boolean): void;
1952
- }
1953
-
1954
- /** A geometry patch from the inspector (all fields optional). */
1955
- interface GeometryPatch {
1956
- x?: number;
1957
- y?: number;
1958
- width?: number;
1959
- height?: number;
1960
- rotation?: number;
1961
- }
1962
- /**
1963
- * The full set of formatting / insert / arrange / clipboard / slide actions
1964
- * exposed to the editing chrome (ribbon, inspector). Composed from the
1965
- * focused per-concern action files (`editor-text-actions.ts`,
1966
- * `editor-arrange-actions.ts`, `editor-clipboard-actions.ts`,
1967
- * `editor-slide-actions.ts`) plus the shape/geometry/insert actions owned
1968
- * directly here. Every mutating action is history-integrated (push -> mutate
1969
- * -> commit) via the shared {@link EditorOps}.
1970
- */
1971
- interface EditActions extends TextActions, ArrangeActions, ClipboardActions, SlideActions, SlideBackgroundActions, TransitionActions, AnimationActions, InspectorActions, InkActions {
1972
- setShapeFill(color: string): void;
1973
- setShapeStroke(color: string): void;
1974
- setShapeStrokeWidth(width: number): void;
1975
- /** Commit an inspector geometry edit (X/Y/W/H/rotation). */
1976
- setGeometry(patch: GeometryPatch): void;
1977
- insert(kind: InsertKind, shapeType?: ShapePresetType): void;
1978
- insertImage(): Promise<void>;
1979
- insertMedia(): Promise<void>;
1980
- insertChart(chartType: l): void;
1981
- insertSmartArt(layout: ca, defaultItems: string[]): void;
1982
- insertEquation(omml: Record<string, unknown>): void;
1983
- insertActionButton(shapeType: string): void;
1984
- insertField(fieldType: string, value?: string): void;
1985
- duplicateSelected(): void;
1986
- deleteSelected(): void;
1987
- }
1988
-
1989
- /**
1990
- * Find & Replace actions for the ribbon's Home > Editing group, backed by the
1991
- * shared `find-replace.ts` helpers. A lean, docked-panel implementation:
1992
- * `search` reports a match count for the query, `replaceCurrent` replaces the
1993
- * first match, and `replaceAll` replaces every match; there is no in-canvas
1994
- * match highlighting or "next/previous match" cursor (that needs per-match
1995
- * selection/scroll wiring into the renderer, out of scope for this wave).
1996
- * Every replace is history-integrated like every other editor action.
1997
- */
1998
- interface FindReplaceActions {
1999
- /** Count occurrences of `query` across all slides (does not mutate). */
2000
- search(query: string, matchCase: boolean): number;
2001
- /** Replace the first match of `query`; returns the number replaced (0 or 1). */
2002
- replaceCurrent(query: string, replacement: string, matchCase: boolean): number;
2003
- /** Replace every match of `query`; returns the number replaced. */
2004
- replaceAll(query: string, replacement: string, matchCase: boolean): number;
2005
- }
2006
-
2007
- /**
2008
- * Minimal i18n for the vanilla binding.
2009
- *
2010
- * The other bindings delegate to their framework's i18n runtime (react-i18next,
2011
- * vue-i18n, ngx-translate) fed by the shared `pptx.*` dictionary. The vanilla
2012
- * binding has no framework, so this module provides the one missing piece: a
2013
- * `t(key, params)` lookup with `{{param}}` interpolation over the same shared
2014
- * English dictionary, plus per-locale overrides supplied by the host.
2015
- *
2016
- * Resolution order: host dictionary for the active locale, then the built-in
2017
- * English dictionary, then a humanised fallback derived from the key (shared
2018
- * `keyToLabel`), so a missing key never renders as a raw `pptx.*` string.
2019
- */
2020
- /** Translate a dotted `pptx.*` key with optional `{{param}}` interpolation. */
2021
- type Translator = (key: string, params?: Record<string, string | number>) => string;
2022
- /** Locale to flat `key: message` dictionary map supplied by the host. */
2023
- type TranslationMessages = Record<string, Record<string, string>>;
2024
- /**
2025
- * Build a {@link Translator} for a locale. `messages[locale]` (when provided)
2026
- * wins over the built-in English dictionary; English is always the fallback.
2027
- */
2028
- declare function createTranslator(locale?: string, messages?: TranslationMessages): Translator;
2029
-
2030
- /** Selection-derived state the inspector reflects, computed by `buildInspectorState`. */
2031
- interface InspectorState {
2032
- hasSelection: boolean;
2033
- canShape: boolean;
2034
- canText: boolean;
2035
- isImage: boolean;
2036
- isTable: boolean;
2037
- x: number;
2038
- y: number;
2039
- width: number;
2040
- height: number;
2041
- rotation: number;
2042
- fillColor: string | undefined;
2043
- strokeColor: string | undefined;
2044
- strokeWidth: number;
2045
- fillOpacity: number;
2046
- strokeOpacity: number;
2047
- gradientEnabled: boolean;
2048
- gradient: GradientState;
2049
- vAlign: 'top' | 'middle' | 'bottom';
2050
- textWrap: 'square' | 'none';
2051
- autoFitMode: 'shrink' | 'normal' | 'none';
2052
- imageBrightness: number;
2053
- imageContrast: number;
2054
- imageSaturation: number;
2055
- cropLeft: number;
2056
- cropTop: number;
2057
- cropRight: number;
2058
- cropBottom: number;
2059
- tableHeaderRow: boolean;
2060
- tableBandedRows: boolean;
2061
- tableCellPadding: number;
2062
- }
2063
- interface Inspector {
2064
- el: HTMLElement;
2065
- update(state: InspectorState): void;
2066
- setEditable(editable: boolean): void;
2067
- }
2068
-
2069
- /** State the panel needs to reflect: the slide to read notes from, and whether edits are allowed. */
2070
- interface NotesPanelUpdate {
2071
- slide: P | undefined;
2072
- editable: boolean;
2073
- }
2074
- interface NotesPanel {
2075
- el: HTMLElement;
2076
- /**
2077
- * Sync the panel to the given slide/editable state. The textarea's value is
2078
- * only reseeded when the slide id actually changes (never on every render),
2079
- * so an in-progress edit is never interrupted mid-typing.
2080
- */
2081
- update(update: NotesPanelUpdate): void;
2082
- /** Expand or collapse the notes body (header stays visible either way). */
2083
- setExpanded(expanded: boolean): void;
2084
- }
2085
-
2086
- /** Draw tab state to reflect (current tool/colour/width). */
2087
- interface RibbonDrawState {
2088
- tool: DrawTool;
2089
- color: string;
2090
- width: number;
2091
- }
2092
- /** Nav-row state (prev/next/counter/zoom label). */
2093
- interface RibbonNavState {
2094
- current: number;
2095
- total: number;
2096
- zoomPercent: number;
2097
- }
2098
- /** Primary-row + tab-bar visibility state. */
2099
- interface RibbonEditState {
2100
- editable: boolean;
2101
- canUndo: boolean;
2102
- canRedo: boolean;
2103
- }
2104
- /** Selection-derived state the Home tab's Font/Paragraph/Arrange groups reflect. */
2105
- interface RibbonSelectionState {
2106
- hasClipboard: boolean;
2107
- slideCount: number;
2108
- }
2109
-
2110
- interface Ribbon {
2111
- el: HTMLElement;
2112
- update(state: RibbonNavState): void;
2113
- setEditState(state: RibbonEditState): void;
2114
- setNotesExpanded(expanded: boolean): void;
2115
- setAutosaveStatus(label: string, kind: 'idle' | 'saving' | 'saved' | 'error'): void;
2116
- /** Show/hide the whole editing surface (Home/Insert tab content + find/replace). */
2117
- setEditable(editable: boolean): void;
2118
- /** Reflect the current selection across the Home tab's Font/Paragraph/Arrange groups. */
2119
- updateSelection(selectedElement: a | undefined, extra: RibbonSelectionState): void;
2120
- /** Reflect the current Draw tab tool/colour/width (store-driven). */
2121
- setDrawState(state: RibbonDrawState): void;
2122
- }
2123
-
2124
- interface ThumbnailRail {
2125
- el: HTMLElement;
2126
- /** Rebuild the rail for a new slide list (uses `renderStage` per slide). */
2127
- render(slides: P[], canvasSize: CanvasSize, renderStage: (slide: P, scale: number) => HTMLElement): void;
2128
- /** Highlight the active slide and scroll it into view. */
2129
- setActive(index: number): void;
2130
- /** Show or hide the rail. */
2131
- setVisible(visible: boolean): void;
2132
- }
2133
-
2134
- /** The viewer's static DOM skeleton plus the mutable overlay controls. */
2135
- interface ViewerChrome {
2136
- /** `.pptxv` root (focusable; keyboard navigation attaches here). */
2137
- root: HTMLElement;
2138
- /** The tabbed ribbon (primary row, nav row, tab bar + File/Home/Insert/View content); null when disabled. */
2139
- ribbon: Ribbon | null;
2140
- /** Property inspector panel; null when disabled. */
2141
- inspector: Inspector | null;
2142
- thumbnails: ThumbnailRail | null;
2143
- /** Scrollable centring viewport around the stage. */
2144
- viewport: HTMLElement;
2145
- /** Box sized to `canvasSize * scale`; the rendered stage goes inside. */
2146
- stageWrap: HTMLElement;
2147
- /** Collapsible speaker-notes panel docked below the slide area. */
2148
- notes: NotesPanel;
2149
- setLoading(loading: boolean): void;
2150
- setError(message: string | null): void;
2151
- setEmpty(empty: boolean): void;
2152
- setPresenting(presenting: boolean): void;
2153
- }
2154
-
2155
- interface PresentationController {
2156
- /** Enter presentation mode (real Fullscreen API on the target element). */
2157
- enter(): Promise<void>;
2158
- /** Exit presentation mode. */
2159
- exit(): Promise<void>;
2160
- /** True while the target is the fullscreen element. */
2161
- isActive(): boolean;
2162
- /** Remove listeners. */
2163
- dispose(): void;
2164
- }
2165
-
2166
- interface EditorController {
2167
- /** (Re)wire listeners + overlay into the current chrome (after mount). */
2168
- attachChrome(): void;
2169
- detachChrome(): void;
2170
- /** Called by the render controller after every stage render. */
2171
- onStageRendered(): void;
2172
- /** True while editing owns the keyboard (selection or inline editing). */
2173
- capturesKeyboard(): boolean;
2174
- /** Drop history/selection/dirty state (new content loaded). */
2175
- reset(): void;
2176
- setEditable(editable: boolean): void;
2177
- undo(): void;
2178
- redo(): void;
2179
- canUndo(): boolean;
2180
- canRedo(): boolean;
2181
- deleteSelected(): void;
2182
- duplicateSelected(): string | null;
2183
- getSelectedElementId(): string | null;
2184
- /** Switch the Draw ribbon tab's active tool (also clears selection when leaving `'select'`). */
2185
- setDrawTool(tool: DrawTool): void;
2186
- /** Set the pen/highlighter stroke colour used by the next committed stroke. */
2187
- setDrawColor(color: string): void;
2188
- /** Set the pen/highlighter stroke width used by the next committed stroke. */
2189
- setDrawWidth(width: number): void;
2190
- /** The formatting / insert / arrange actions for the editing chrome. */
2191
- getEditActions(): EditActions;
2192
- /** The Find & Replace actions for the ribbon's docked panel. */
2193
- getFindReplaceActions(): FindReplaceActions;
2194
- /** Commit the speaker-notes textarea's plain text onto the current slide. */
2195
- commitNotes(notes: string): void;
2196
- save(): Promise<Uint8Array>;
2197
- downloadPptx(fileName?: string): Promise<void>;
2198
- destroy(): void;
2199
- }
2200
-
2201
- /** Everything the controller needs after a stage (re)render. */
2202
- interface SyncStageParams {
2203
- doc: Document;
2204
- /** The stage host (position: relative), for layering a transition overlay. */
2205
- stageWrap: HTMLElement;
2206
- /** The freshly rendered, fully-visible main stage node. */
2207
- stage: HTMLElement;
2208
- /** The slide the stage renders, or `undefined` when empty. */
2209
- slide: P | undefined;
2210
- /** Zero-based index of the rendered slide. */
2211
- slideIndex: number;
2212
- /** True only when the live (fullscreen) presentation stage is active. */
2213
- presenting: boolean;
2214
- }
2215
- /**
2216
- * The presentation-mode playback state machine for the vanilla binding.
2217
- *
2218
- * It owns the click-stepped animation cursor and the slide-transition overlay,
2219
- * both driven by the shared framework-agnostic helpers. It is consulted from
2220
- * two seams in the rebuild-per-change render flow:
2221
- *
2222
- * - {@link PresentationPlayback.syncStage} runs after every stage render:
2223
- * on a slide entry it rebuilds the click groups, resets the step, hides
2224
- * pending entrances, and (when the slide changed mid-show) plays the
2225
- * incoming slide's transition over a snapshot of the outgoing stage.
2226
- * - {@link PresentationPlayback.advance} runs on each forward navigation
2227
- * key/tap while presenting: it reveals the next animation build in place
2228
- * (no rebuild) and reports whether a build remained, so the caller only
2229
- * advances the slide once the timeline is exhausted.
2230
- */
2231
- interface PresentationPlayback {
2232
- /**
2233
- * Reveal the next on-click animation build for the current slide. Returns
2234
- * `true` if a build was revealed (stay on the slide); `false` when the
2235
- * slide's builds are exhausted (the caller should advance to the next slide).
2236
- */
2237
- advance(): boolean;
2238
- /** True when every click group on the current slide has been revealed. */
2239
- isComplete(): boolean;
2240
- /** Sync playback + transitions after a stage (re)render. */
2241
- syncStage(params: SyncStageParams): void;
2242
- /** Cancel any running transition and forget all per-slide state. */
2243
- reset(): void;
2244
- }
2245
-
2246
- /** Discriminant values of the {@link PptxElement} union (`'text'`, `'chart'`, ...). */
2247
- type PptxElementType = a['type'];
2248
- /**
2249
- * Everything an element renderer may need, passed to every renderer call.
2250
- *
2251
- * The context is immutable per slide render. Renderers must create DOM through
2252
- * `context.document` (never the global `document`) so slides can render into
2253
- * detached documents (tests, export pipelines).
2254
- */
2255
- interface ElementRenderContext {
2256
- /** Document used for all DOM creation. */
2257
- readonly document: Document;
2258
- /** The slide being rendered. */
2259
- readonly slide: P;
2260
- /** Full slide canvas size in CSS px (elements are positioned in this space). */
2261
- readonly canvasSize: CanvasSize;
2262
- /**
2263
- * The scale the stage is rendered at (1 = 100%). The stage applies it via a
2264
- * CSS transform, so renderers should lay out in unscaled canvas px; `scale`
2265
- * is informational (e.g. for raster density decisions).
2266
- */
2267
- readonly scale: number;
2268
- /** Archive-path to displayable URL map for media + poster frames. */
2269
- readonly mediaDataUrls: ReadonlyMap<string, string>;
2270
- /** Shared-dictionary translator (`pptx.*` keys). */
2271
- readonly t: Translator;
2272
- /**
2273
- * Opt-in flag: render `smartArt` elements as an extruded Three.js scene
2274
- * instead of flat SVG (see `PptxViewerOptions.smartArt3D`). Defaults to
2275
- * `false` when the option is unset.
2276
- */
2277
- readonly smartArt3D: boolean;
2278
- /**
2279
- * True only for the live presentation stage (real Fullscreen API active):
2280
- * media renderers use this to autoplay once mounted, matching PowerPoint's
2281
- * slideshow behaviour. `false` for the editor canvas and thumbnail rail.
2282
- */
2283
- readonly presenting: boolean;
2284
- /** The registry in effect, for renderers that need to inspect it. */
2285
- readonly registry: ElementRendererRegistry;
2286
- /**
2287
- * Render a child element through the registry (used by the group renderer
2288
- * for recursion; custom renderers may nest elements the same way).
2289
- */
2290
- renderElement(element: a, zIndex: number): HTMLElement | SVGElement | null;
2291
- }
2292
- /**
2293
- * Renders one slide element to a DOM node (or `null` to render nothing).
2294
- *
2295
- * Contract:
2296
- * - Position absolutely within the stage: apply the shared
2297
- * `getContainerStyle(element, zIndex)` map (or equivalent) to the returned
2298
- * root node.
2299
- * - Set `dataset.elementId = element.id` on the root node.
2300
- * - Create all DOM via `context.document`.
2301
- * - Never mutate `element` or anything on the context.
2302
- */
2303
- type ElementRenderer = (element: a, zIndex: number, context: ElementRenderContext) => HTMLElement | SVGElement | null;
2304
- /**
2305
- * Registry dispatching elements to renderers by their `type` discriminant.
2306
- *
2307
- * Additional element types are supported by registering a renderer for the
2308
- * type; unregistered types fall through to the fallback renderer (a typed
2309
- * placeholder box by default). See `render/elements/README.md` for the
2310
- * step-by-step contract.
2311
- */
2312
- interface ElementRendererRegistry {
2313
- /** Register (or replace) the renderer for an element type. */
2314
- register(type: PptxElementType, renderer: ElementRenderer): void;
2315
- /** Remove the renderer for an element type (falls back afterwards). */
2316
- unregister(type: PptxElementType): void;
2317
- /** The renderer registered for a type, or `undefined`. */
2318
- get(type: PptxElementType): ElementRenderer | undefined;
2319
- /** True when a dedicated (non-fallback) renderer is registered. */
2320
- has(type: PptxElementType): boolean;
2321
- /** Replace the fallback renderer used for unregistered types. */
2322
- setFallback(renderer: ElementRenderer): void;
2323
- /** The renderer to use for a type: registered renderer or fallback. */
2324
- resolve(type: PptxElementType): ElementRenderer;
2325
- /** All types with a dedicated renderer (sorted, for tests/debugging). */
2326
- registeredTypes(): PptxElementType[];
2327
- }
2328
-
2329
- /**
2330
- * Create an empty {@link ElementRendererRegistry}.
2331
- *
2332
- * The default fallback renders nothing; `createDefaultRegistry()` (in
2333
- * `./elements`) installs the built-in renderers plus the typed placeholder
2334
- * fallback.
2335
- */
2336
- declare function createElementRendererRegistry(): ElementRendererRegistry;
2337
-
2338
- /**
2339
- * Apply a shared `CssStyleMap` to an element. The shared builders emit a mix
2340
- * of camelCase (`backgroundColor`) and kebab-case (`background-color`) keys;
2341
- * both are normalised to `style.setProperty` calls.
2342
- */
2343
- declare function applyStyleMap(el: HTMLElement | SVGElement, style: CssStyleMap): void;
2344
- /** Create an element with an optional class and style map. */
2345
- declare function createEl<K extends keyof HTMLElementTagNameMap>(doc: Document, tag: K, className?: string, style?: CssStyleMap): HTMLElementTagNameMap[K];
2346
- /** Create a namespaced SVG element with optional attributes. */
2347
- declare function createSvgEl<K extends keyof SVGElementTagNameMap>(doc: Document, tag: K, attrs?: Record<string, string | number | undefined>): SVGElementTagNameMap[K];
2348
-
2349
- interface SlideStageOptions {
2350
- document: Document;
2351
- slide: P;
2352
- canvasSize: CanvasSize;
2353
- mediaDataUrls: ReadonlyMap<string, string>;
2354
- registry: ElementRendererRegistry;
2355
- t: Translator;
2356
- /** Scale applied via CSS transform (default 1). */
2357
- scale?: number;
2358
- /** Opt-in WebGL SmartArt renderer flag; see `PptxViewerOptions.smartArt3D`. */
2359
- smartArt3D?: boolean;
2360
- /** True only for the live presentation stage; see `ElementRenderContext.presenting`. */
2361
- presenting?: boolean;
2362
- /**
2363
- * True only for the main (interactive) canvas, never the thumbnail rail.
2364
- * Marks every rendered element (recursively, including group children) with
2365
- * `data-pptx-element="true"` and the stage itself with
2366
- * `role="region" aria-roledescription="slide"` - the framework-neutral e2e
2367
- * test hooks the React/Vue/Angular bindings also emit. Defaults to `false`.
2368
- */
2369
- interactive?: boolean;
2370
- }
2371
- /**
2372
- * Render one slide as a fixed-size stage: the resolved slide background plus
2373
- * every element dispatched through the registry, scaled with a CSS transform
2374
- * (`transform-origin: top left`), exactly like the other bindings' stages.
2375
- *
2376
- * The returned node is `canvasSize * scale` ON SCREEN but laid out at the
2377
- * unscaled canvas size, so the caller should wrap it in a box sized to
2378
- * `canvasSize * scale` (the viewer's stage host and thumbnails both do).
2379
- */
2380
- declare function renderSlideStage(options: SlideStageOptions): HTMLElement;
2381
-
2382
- /**
2383
- * The registry the viewer uses by default.
2384
- *
2385
- * Dedicated renderers: `text`, `shape`, `image`, `picture`, `group`,
2386
- * `connector`, `table`, `chart`, `smartArt`, `media`, `ink`, `ole`. The
2387
- * remaining types (`contentPart`, `zoom`, `model3d`, `unknown`) fall through
2388
- * to the typed placeholder fallback until their renderers land; see
2389
- * `./README.md` for the contract to add one.
2390
- */
2391
- declare function createDefaultRegistry(): ElementRendererRegistry;
2392
-
2393
- interface RenderController {
2394
- /** Re-render everything (used after a chrome rebuild). */
2395
- renderAll(): void;
2396
- /** Re-render the main stage + toolbar counters at the current state. */
2397
- renderStage(): void;
2398
- /** Rebuild the thumbnail rail from the current slide list. */
2399
- renderThumbnails(): void;
2400
- /** Resolve the requested zoom into a concrete scale factor. */
2401
- effectiveScale(): number;
2402
- /**
2403
- * Presentation-mode animation/transition playback, driven by the stage
2404
- * rebuild flow. Navigation (`viewer-controls`) consults `advance()` so a
2405
- * "next" first steps the on-click animation timeline before advancing slides.
2406
- */
2407
- readonly presentationPlayback: PresentationPlayback;
2408
- }
2409
-
2410
- /**
2411
- * Debounced autosave for the vanilla viewer, layered on the shared IndexedDB
2412
- * recovery store (`pptx-viewer-shared/autosave-store`).
2413
- *
2414
- * Semantics mirror the React/Vue bindings: a local edit marks the document
2415
- * dirty; a debounce timer then re-serializes the deck through
2416
- * `PptxHandler.save` and persists it under `filePath` via
2417
- * `saveAutosaveSnapshot` (evicting the oldest record on quota exhaustion). The
2418
- * recovery blob is a crash-safety net only; it never clears the editor's dirty
2419
- * flag or stands in for the user's real Save.
2420
- *
2421
- * On construction it probes `getAutosaveSnapshot(filePath)` and, when a snapshot
2422
- * from a previous session exists, offers it back through `onRecovery` so the
2423
- * host can decide whether to restore it (e.g. via `loadFile`).
2424
- */
2425
- type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'error';
2426
-
2427
- /**
2428
- * share-helpers.ts: pure (framework-free) helpers for the Share dialog.
2429
- *
2430
- * Mirrors the Vue `ShareDialog.vue` / Angular `share-helpers.ts` form
2431
- * validation and config-assembly logic (see `useCollaborationWiring.onShareStart`
2432
- * for the `role: 'collaborator'` config this produces). No DOM here so it is
2433
- * trivially unit-testable; the DOM builder lives in `ui/share-dialog.ts`.
2434
- */
2435
- /** Prefilled values for the Share form fields. */
2436
- interface ShareDefaults {
2437
- roomId?: string;
2438
- userName?: string;
2439
- serverUrl?: string;
2440
- }
2441
-
2442
- /** Per-slide progress callback: `(currentSlideIndex, totalSlides)`. */
2443
- type ExportProgress = (current: number, total: number) => void;
2444
-
2445
- /**
2446
- * Animated-GIF export for the vanilla binding. All slides are captured (one
2447
- * frame per slide) via the injected `rasterizeSlide`, then encoded with the
2448
- * shared pure-JS GIF89a encoder (`pptx-viewer-shared` `gif-encoder`: median-cut
2449
- * quantisation + LZW). Frame timing comes from the shared `planGifFrames`
2450
- * planner and oversized captures are downscaled via `clampGifDimensions`; only
2451
- * the DOM capture / canvas scaling / Blob download driver lives here.
2452
- */
2453
- /** Options for the animated-GIF export (all slides, one frame per slide). */
2454
- interface ExportGifOptions {
2455
- /**
2456
- * Duration each slide is shown, in milliseconds (default 2000). Per-slide
2457
- * overrides can be supplied via {@link ExportGifOptions.slideTimingsMs}.
2458
- */
2459
- slideDurationMs?: number;
2460
- /**
2461
- * Per-slide duration overrides in milliseconds (index maps to slide index,
2462
- * e.g. rehearsed timings). Flows through the shared `planGifFrames` plan
2463
- * into per-frame GIF delays.
2464
- */
2465
- slideTimingsMs?: number[];
2466
- /**
2467
- * Cap on the longer side of the encoded frames, in pixels (default 1920).
2468
- * Captured canvases larger than this are downscaled before quantisation,
2469
- * keeping encode time and file size manageable.
2470
- */
2471
- maxDimension?: number;
2472
- /** Capture-phase progress callback: `(currentSlide, totalSlides)`. */
2473
- onProgress?: ExportProgress;
2474
- /** Abort the export early; the capture loop checks this between slides. */
2475
- signal?: AbortSignal;
2476
- }
2477
-
2478
- /**
2479
- * Print for the vanilla binding, assembled entirely from the shared print
2480
- * module (`pptx-viewer-shared` `print-document`): `validatePrintSettings`,
2481
- * `computeSlideIndices` / `computeColorFilter`, the `build*Html` body markup
2482
- * builders, and the DOMPurify-hardened `buildPrintHtmlDocument` assembler.
2483
- * Only the drivers live here: rasterising the selected slides to data URLs and
2484
- * writing the document into a print window. Vanilla port of Vue's `usePrint`
2485
- * raster path (slides / notes / handouts / outline).
2486
- */
2487
- /**
2488
- * Open a print window for a complete HTML document and trigger printing.
2489
- * Returns `false` when the window could not be opened (popup blocker).
2490
- */
2491
- type OpenPrintWindow = (htmlDocument: string) => boolean;
2492
- /**
2493
- * Options for `print`: any subset of the shared `PrintSettings` (unspecified
2494
- * fields fall back to `DEFAULT_PRINT_SETTINGS`, i.e. all slides, landscape,
2495
- * full colour) plus progress/abort and a print-window override.
2496
- */
2497
- interface PrintOptions extends Partial<PrintSettings> {
2498
- /** Rasterisation progress callback: `(currentSlide, totalSlidesToPrint)`. */
2499
- onProgress?: ExportProgress;
2500
- /** Abort before the window opens; checked between slide captures. */
2501
- signal?: AbortSignal;
2502
- /**
2503
- * Override how the assembled document is opened (e.g. write it into a
2504
- * hidden iframe). Popup-blocker caveat: the default opener uses
2505
- * `window.open`, which browsers typically only allow inside a user
2506
- * gesture, so call `print()` from a click handler; when the popup is
2507
- * blocked the returned promise resolves `false`.
2508
- */
2509
- openPrintWindow?: OpenPrintWindow;
2510
- }
2511
-
2512
- /**
2513
- * WebM video export for the vanilla binding, driven by the shared `video-plan`
2514
- * module: `planVideoSegments` (per-slide segment timing + frame counts),
2515
- * `fpsToFrameIntervalMs` (draw-loop pacing), and `pickSupportedMimeType` over
2516
- * `WEBM_MIME_CANDIDATES` (MediaRecorder codec selection). Only the browser
2517
- * driver lives here: capture each slide to a canvas, replay the canvases onto
2518
- * a recording canvas fed to `captureStream()` + `MediaRecorder`, and download
2519
- * the resulting Blob. Vanilla port of React's `exportAllSlidesAsVideo`.
2520
- */
2521
- /** Options for the WebM video export (all slides). */
2522
- interface ExportVideoOptions {
2523
- /** Duration each slide is held, in milliseconds (default 3000). */
2524
- slideDurationMs?: number;
2525
- /** Per-slide duration overrides in milliseconds (index maps to slide index). */
2526
- slideTimingsMs?: number[];
2527
- /** Recording frame rate in frames per second (default 30). */
2528
- fps?: number;
2529
- /** MediaRecorder video bitrate in bits per second (default 5,000,000). */
2530
- videoBitsPerSecond?: number;
2531
- /** Capture-phase progress callback: `(currentSlide, totalSlides)`. */
2532
- onProgress?: ExportProgress;
2533
- /** Recording-phase progress callback: `(currentSlide, totalSlides)`. */
2534
- onRecordProgress?: ExportProgress;
2535
- /** Abort the export early; checked between slides and between frames. */
2536
- signal?: AbortSignal;
2537
- }
2538
-
2539
- /** Options for the multi-slide PDF export (progress + cooperative cancel). */
2540
- interface ExportPdfOptions {
2541
- /** Capture-phase progress callback: `(currentSlide, totalSlides)`. */
2542
- onProgress?: ExportProgress;
2543
- /** Abort the export early; the loop checks this between slides. */
2544
- signal?: AbortSignal;
2545
- }
2546
-
2547
- /**
2548
- * Content sources accepted by the vanilla viewer: raw bytes, a Blob/File, or
2549
- * a URL string to fetch.
2550
- */
2551
- type PptxViewerSource = ArrayBuffer | Uint8Array | Blob | string;
2552
-
2553
- /** Callbacks mirroring the Vue component's emits. */
2554
- interface PptxViewerCallbacks {
2555
- /** Fired after a presentation loads successfully. */
2556
- onLoad?: (info: {
2557
- slideCount: number;
2558
- canvasSize: CanvasSize;
2559
- }) => void;
2560
- /** Fired when a load fails (message is already localised/best-effort). */
2561
- onError?: (message: string, error: unknown) => void;
2562
- /** Fired when the active slide changes (zero-based index). */
2563
- onSlideChange?: (index: number) => void;
2564
- /** Fired when the effective zoom scale changes (1 = 100%). */
2565
- onZoomChange?: (scale: number) => void;
2566
- /** Fired when presentation (fullscreen) mode is entered or exited. */
2567
- onPresentationChange?: (presenting: boolean) => void;
2568
- /** Fired after any document mutation (move, resize, edit, undo, ...). */
2569
- onChange?: () => void;
2570
- /** Fired when the unsaved-edits flag flips (a save resets it). */
2571
- onDirtyChange?: (dirty: boolean) => void;
2572
- /** Fired when the selected element changes (`null` = no selection). */
2573
- onSelectionChange?: (elementId: string | null) => void;
2574
- /** Fired on every autosave lifecycle transition (`saving`/`saved`/`error`). */
2575
- onAutosaveStatus?: (status: AutosaveStatus) => void;
2576
- /**
2577
- * Offered a recovery snapshot found in the shared IndexedDB store on start
2578
- * (a previous session's autosave for the same `autosaveFilePath`). The host
2579
- * decides whether to restore it, e.g. `viewer.loadFile(record.data)`.
2580
- */
2581
- onAutosaveRecovery?: (record: AutosaveRecord) => void;
2582
- /** Fired on every collaboration connection-status transition. */
2583
- onCollaborationStatus?: (status: ConnectionStatus) => void;
2584
- }
2585
- interface PptxViewerOptions extends PptxViewerCallbacks {
2586
- /**
2587
- * The presentation to open: raw `.pptx` bytes (ArrayBuffer / Uint8Array),
2588
- * a Blob/File, or a URL string to fetch. Omit to start empty and call
2589
- * `loadFile` / `loadUrl` later.
2590
- */
2591
- source?: PptxViewerSource;
2592
- /** Viewer chrome theme (shared `ViewerTheme`: colors, radius, CSS vars). */
2593
- theme?: ViewerTheme;
2594
- /** UI locale (default `'en'`). Dictionaries come from `messages`. */
2595
- locale?: string;
2596
- /**
2597
- * Per-locale `pptx.*` message dictionaries. English falls back to the
2598
- * built-in shared dictionary; other locales fall back to English.
2599
- */
2600
- messages?: TranslationMessages;
2601
- /** Zero-based slide to show after load (default 0). */
2602
- initialSlide?: number;
2603
- /**
2604
- * Enable editing (default `false`): click to select, drag/resize/rotate,
2605
- * inline text editing, keyboard shortcuts, undo/redo, and the toolbar
2606
- * Save button. Toggle later via `setEditable`.
2607
- */
2608
- editable?: boolean;
2609
- /**
2610
- * Legacy flag superseded by {@link editable}; kept so existing option
2611
- * objects stay type-valid. It has no effect.
2612
- */
2613
- readOnly?: boolean;
2614
- /** Show the toolbar (default `true`). */
2615
- showToolbar?: boolean;
2616
- /** Show the thumbnail sidebar (default `true`). */
2617
- showThumbnails?: boolean;
2618
- /**
2619
- * Build the editing format toolbar row (bold/fill/insert/z-order); default
2620
- * `true`. The row is only *visible* while editing is enabled.
2621
- */
2622
- showFormatToolbar?: boolean;
2623
- /**
2624
- * Build the property inspector panel (position/size/fill/line); default
2625
- * `true`. Only *visible* while editing is enabled.
2626
- */
2627
- showInspector?: boolean;
2628
- /**
2629
- * Custom element-renderer registry. Defaults to `createDefaultRegistry()`;
2630
- * pass your own (or mutate the default via `getRegistry()`) to add or
2631
- * override element renderers.
2632
- */
2633
- registry?: ElementRendererRegistry;
2634
- /**
2635
- * Opt-in WebGL SmartArt renderer (default `false`): renders `smartArt`
2636
- * elements as an extruded Three.js scene instead of the flat SVG layout.
2637
- * `three` is an optional peer dependency, lazily imported only when this is
2638
- * `true`; when it is unavailable or the scene fails to mount, the SVG
2639
- * renderer is used instead. Set once at construction (no runtime setter,
2640
- * mirroring the Vue/React/Angular bindings).
2641
- */
2642
- smartArt3D?: boolean;
2643
- /**
2644
- * Enable debounced autosave (default `false`): after each local edit the deck
2645
- * is re-serialized and stashed in the shared IndexedDB recovery store as a
2646
- * crash-safety net (it never replaces the user's real Save). The toolbar shows
2647
- * a small status pill; a snapshot from a prior session is offered through
2648
- * {@link PptxViewerCallbacks.onAutosaveRecovery}.
2649
- */
2650
- autosave?: boolean;
2651
- /** Debounce window (ms) between an edit and the persisted snapshot (default 2000). */
2652
- autosaveIntervalMs?: number;
2653
- /** IndexedDB recovery key for autosave (default `'presentation.pptx'`). */
2654
- autosaveFilePath?: string;
2655
- /**
2656
- * Start a real-time collaboration session immediately (Yjs over y-websocket
2657
- * or serverless y-webrtc). Local edits publish to peers and remote edits
2658
- * merge in granularly; a `role: 'viewer'` config forces read-only. Start or
2659
- * stop a session later with {@link PptxViewerInstance.startCollaboration} /
2660
- * {@link PptxViewerInstance.stopCollaboration}.
2661
- *
2662
- * Note: media/OLE/3D/ink binary payloads are not carried over the wire (a
2663
- * shared codec limitation), and a remote update replaces the whole local
2664
- * slide array, so a joiner's host-provided media can degrade.
2665
- */
2666
- collaboration?: CollaborationConfig;
2667
- /**
2668
- * Prefilled values for the built-in Share/Broadcast dialogs' form fields
2669
- * (e.g. a host-generated display name), mirroring the Vue binding's
2670
- * `shareDefaults` prop. The broadcast dialog uses `userName` as the
2671
- * presenter's display name.
2672
- */
2673
- shareDefaults?: ShareDefaults;
2674
- }
2675
- /** The viewer handle returned by `createPptxViewer`. */
2676
- interface PptxViewerInstance {
2677
- /** Load a presentation from bytes or a Blob/File (replaces the current one). */
2678
- loadFile(file: Blob | ArrayBuffer | Uint8Array): Promise<void>;
2679
- /** Fetch and load a presentation from a URL. */
2680
- loadUrl(url: string): Promise<void>;
2681
- /** Go to the next slide (no-op on the last slide). */
2682
- next(): void;
2683
- /** Go to the previous slide (no-op on the first slide). */
2684
- prev(): void;
2685
- /** Jump to a zero-based slide index (clamped). */
2686
- goToSlide(index: number): void;
2687
- /** Number of slides in the loaded presentation (0 when none). */
2688
- getSlideCount(): number;
2689
- /** Zero-based index of the visible slide. */
2690
- getCurrentSlide(): number;
2691
- /** Effective zoom scale (1 = 100%), after fit resolution. */
2692
- getZoom(): number;
2693
- /** Set an explicit zoom scale, or `'fit'` for fit-to-viewport. */
2694
- setZoom(zoom: ZoomLevel): void;
2695
- zoomIn(): void;
2696
- zoomOut(): void;
2697
- zoomToFit(): void;
2698
- /** Apply a new viewer theme (pass `undefined` to reset to defaults). */
2699
- setTheme(theme: ViewerTheme | undefined): void;
2700
- /** Switch the UI locale (rebuilds the chrome labels). */
2701
- setLocale(locale: string): void;
2702
- /** Enter presentation mode (real Fullscreen API). */
2703
- enterPresentation(): Promise<void>;
2704
- /** Exit presentation mode. */
2705
- exitPresentation(): Promise<void>;
2706
- /** Enable or disable editing at runtime (disabling clears the selection). */
2707
- setEditable(editable: boolean): void;
2708
- /** Undo the last edit (no-op when the undo stack is empty). */
2709
- undo(): void;
2710
- /** Redo the last undone edit (no-op when the redo stack is empty). */
2711
- redo(): void;
2712
- canUndo(): boolean;
2713
- canRedo(): boolean;
2714
- /** Serialise the (edited) presentation to `.pptx` bytes and clear dirty. */
2715
- save(): Promise<Uint8Array>;
2716
- /** `save()` + trigger a browser download (default `presentation.pptx`). */
2717
- downloadPptx(fileName?: string): Promise<void>;
2718
- /** Delete the selected element (no-op without a selection). */
2719
- deleteSelected(): void;
2720
- /** Id of the selected element, or `null`. */
2721
- getSelectedElementId(): string | null;
2722
- /**
2723
- * Export a slide as a PNG download (defaults to the current slide). Renders
2724
- * the slide off-screen at scale 1 and rasterises it with `html2canvas-pro`
2725
- * (dynamically imported), so the first call pays a one-time load cost.
2726
- */
2727
- exportSlidePng(index?: number): Promise<void>;
2728
- /**
2729
- * Export every slide as a multi-page PDF download (one slide per page).
2730
- * `jspdf` is dynamically imported on first use.
2731
- */
2732
- exportPdf(options?: ExportPdfOptions): Promise<void>;
2733
- /**
2734
- * Export every slide as an animated GIF download (one frame per slide,
2735
- * `slideDurationMs` per frame). Slides are captured off-screen like
2736
- * `exportSlidePng` and encoded with the shared pure-JS GIF89a encoder.
2737
- */
2738
- exportGif(options?: ExportGifOptions): Promise<void>;
2739
- /**
2740
- * Export every slide as a WebM video download: each captured slide is held
2741
- * for its configured duration on a canvas stream recorded by
2742
- * `MediaRecorder` (codec picked from the shared WebM candidates).
2743
- */
2744
- exportVideo(options?: ExportVideoOptions): Promise<void>;
2745
- /**
2746
- * Assemble the printable document (slides / notes / handouts / outline)
2747
- * and open it in a new print window. Resolves `false` when the popup was
2748
- * blocked: browsers typically only allow `window.open` inside a user
2749
- * gesture, so call this from a click handler (or pass a custom
2750
- * `openPrintWindow` that writes into an iframe you own).
2751
- */
2752
- print(options?: PrintOptions): Promise<boolean>;
2753
- /** The element-renderer registry in effect (extension point). */
2754
- getRegistry(): ElementRendererRegistry;
2755
- /**
2756
- * Escape hatch: the live `pptx-viewer-core` handler for the loaded file
2757
- * (or `null`). Enables advanced operations (save, markdown conversion,
2758
- * archive access) without extra APIs here.
2759
- */
2760
- getHandler(): PptxHandler | null;
2761
- /**
2762
- * Start (or restart) a real-time collaboration session. Resolves once the
2763
- * transport is created; connection status arrives via
2764
- * {@link PptxViewerCallbacks.onCollaborationStatus}.
2765
- */
2766
- startCollaboration(config: CollaborationConfig): Promise<void>;
2767
- /** Stop the active collaboration session (no-op when none is running). */
2768
- stopCollaboration(): void;
2769
- /** Current collaboration connection status (`'disconnected'` when inactive). */
2770
- getCollaborationStatus(): ConnectionStatus;
2771
- /** Force an immediate autosave snapshot (no-op when autosave is disabled). */
2772
- autosaveNow(): Promise<void>;
2773
- /** Tear down DOM, listeners, Blob URLs, and the core handler. */
2774
- destroy(): void;
2775
- }
2776
-
2777
- /** The mutable pieces `PptxViewer` owns for one chrome mount lifecycle. */
2778
- interface ChromeLifecycle {
2779
- chrome: ViewerChrome;
2780
- presentation: PresentationController;
2781
- detachKeyboard: () => void;
2782
- resizeObserver: ResizeObserver | null;
2783
- appliedThemeVars: string[];
2784
- }
2785
- /** The subset of `PptxViewer` needed to build its `MountChromeDeps`. */
2786
- interface ChromeHost {
2787
- doc: Document;
2788
- container: HTMLElement;
2789
- t: Translator;
2790
- options: PptxViewerOptions;
2791
- store: Store<ViewerState>;
2792
- renderer: RenderController;
2793
- lifecycle: ChromeLifecycle;
2794
- editor: {
2795
- commitNotes(notes: string): void;
2796
- getEditActions(): EditActions;
2797
- getFindReplaceActions(): FindReplaceActions;
2798
- setDrawTool(tool: DrawTool): void;
2799
- setDrawColor(color: string): void;
2800
- setDrawWidth(width: number): void;
2801
- };
2802
- prev(): void;
2803
- next(): void;
2804
- zoomIn(): void;
2805
- zoomOut(): void;
2806
- zoomToFit(): void;
2807
- undo(): void;
2808
- redo(): void;
2809
- downloadPptx(): Promise<void>;
2810
- toggleNotes(): void;
2811
- goToSlide(index: number): void;
2812
- getSlideCount(): number;
2813
- enterPresentation(): Promise<void>;
2814
- exitPresentation(): Promise<void>;
2815
- exportSlidePng(): Promise<void>;
2816
- exportPdf(): Promise<void>;
2817
- exportGif(): Promise<void>;
2818
- exportVideo(): Promise<void>;
2819
- print(): Promise<boolean>;
2820
- setTheme(theme: ViewerTheme | undefined): void;
2821
- }
2822
-
2823
- /** The export slice of the public viewer API (see `PptxViewerInstance`). */
2824
- interface ViewerExportApi {
2825
- /** Export a single slide as a PNG download. Defaults to the current slide. */
2826
- exportSlidePng(index?: number): Promise<void>;
2827
- /** Export every slide as a multi-page PDF download (one slide per page). */
2828
- exportPdf(options?: ExportPdfOptions): Promise<void>;
2829
- /** Export every slide as an animated GIF download (one frame per slide). */
2830
- exportGif(options?: ExportGifOptions): Promise<void>;
2831
- /** Export every slide as a WebM video download (MediaRecorder). */
2832
- exportVideo(options?: ExportVideoOptions): Promise<void>;
2833
- /** Open the assembled print document in a print window (`false` = blocked). */
2834
- print(options?: PrintOptions): Promise<boolean>;
2835
- }
2836
- interface ExportLifecycle extends ViewerExportApi {
2837
- /** Remove the off-screen capture stage from the DOM. */
2838
- destroy(): void;
2839
- }
2840
- /**
2841
- * Base class implementing the export slice of `PptxViewerInstance` by
2842
- * delegating to the instance's {@link ExportLifecycle}. `PptxViewer` extends
2843
- * this, so new export formats are wired here (and in the export controller)
2844
- * without growing the size-capped `PptxViewer.ts`.
2845
- */
2846
- declare abstract class ViewerExportHost implements ViewerExportApi {
2847
- protected abstract readonly exporter: ExportLifecycle;
2848
- exportSlidePng(index?: number): Promise<void>;
2849
- exportPdf(options?: ExportPdfOptions): Promise<void>;
2850
- exportGif(options?: ExportGifOptions): Promise<void>;
2851
- exportVideo(options?: ExportVideoOptions): Promise<void>;
2852
- print(options?: PrintOptions): Promise<boolean>;
2853
- }
2854
-
2855
- /**
2856
- * The zero-framework PowerPoint viewer. Construct via {@link createPptxViewer}:
2857
- * builds chrome inside `container`, loads `options.source` when given, and
2858
- * re-renders through a tiny reactive store.
2859
- */
2860
- declare class PptxViewer extends ViewerExportHost implements PptxViewerInstance, ChromeHost {
2861
- readonly container: HTMLElement;
2862
- readonly doc: Document;
2863
- readonly options: PptxViewerOptions;
2864
- readonly store: Store<ViewerState>;
2865
- readonly renderer: RenderController;
2866
- t: Translator;
2867
- lifecycle: ChromeLifecycle;
2868
- editor: EditorController;
2869
- protected readonly exporter: ExportLifecycle;
2870
- private readonly loading;
2871
- private readonly registry;
2872
- private readonly sessions;
2873
- private readonly controls;
2874
- private destroyed;
2875
- constructor(container: HTMLElement, options?: PptxViewerOptions);
2876
- loadFile(file: Blob | ArrayBuffer | Uint8Array): Promise<void>;
2877
- loadUrl(url: string): Promise<void>;
2878
- next(): void;
2879
- prev(): void;
2880
- goToSlide(index: number): void;
2881
- getSlideCount(): number;
2882
- getCurrentSlide(): number;
2883
- getZoom(): number;
2884
- setZoom(zoom: ZoomLevel): void;
2885
- zoomIn(): void;
2886
- zoomOut(): void;
2887
- zoomToFit(): void;
2888
- /** Expand/collapse the speaker-notes panel; persists for the instance's life. */
2889
- toggleNotes(): void;
2890
- setTheme(theme: ViewerTheme | undefined): void;
2891
- setLocale(locale: string): void;
2892
- setEditable(editable: boolean): void;
2893
- undo(): void;
2894
- redo(): void;
2895
- canUndo(): boolean;
2896
- canRedo(): boolean;
2897
- save(): Promise<Uint8Array>;
2898
- downloadPptx(fileName?: string): Promise<void>;
2899
- deleteSelected(): void;
2900
- getSelectedElementId(): string | null;
2901
- enterPresentation(): Promise<void>;
2902
- exitPresentation(): Promise<void>;
2903
- getRegistry(): ElementRendererRegistry;
2904
- getHandler(): PptxHandler | null;
2905
- startCollaboration(config: CollaborationConfig): Promise<void>;
2906
- stopCollaboration(): void;
2907
- getCollaborationStatus(): ConnectionStatus;
2908
- autosaveNow(): Promise<void>;
2909
- destroy(): void;
2910
- private remountChrome;
2911
- }
2912
- /** Create a PowerPoint viewer inside `container` (see {@link PptxViewerOptions}). */
2913
- declare function createPptxViewer(container: HTMLElement, options?: PptxViewerOptions): PptxViewerInstance;
2914
-
2915
- /** The complete viewer stylesheet text (for hosts that self-manage CSS). */
2916
- declare function getViewerCss(): string;
2917
-
2918
- export { type AutosaveRecord, type AutosaveStatus, type CollaborationConfig, type CollaborationRole, type CollaborationTransport, type ConnectionStatus, type CssStyleMap, type ElementRenderContext, type ElementRenderer, type ElementRendererRegistry, type ExportGifOptions, type ExportPdfOptions, type ExportProgress, type ExportVideoOptions, type OpenPrintWindow, type PptxElementType, PptxHandler, PptxViewer, type PptxViewerCallbacks, type PptxViewerInstance, type PptxViewerOptions, type PptxViewerSource, type PrintOptions, type SlideStageOptions, type TranslationMessages, type Translator, type ViewerState, type ZoomLevel, applyStyleMap, createDefaultRegistry, createEl, createElementRendererRegistry, createPptxViewer, createSvgEl, createTranslator, getViewerCss, renderSlideStage };