pptx-angular-viewer 3.12.0 → 3.14.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.
@@ -6,9 +6,9 @@ import { Signal, WritableSignal, OnDestroy, OnInit, AfterViewInit, OnChanges, Si
6
6
  import * as AiSdk from 'ai';
7
7
  import { LanguageModel, ChatTransport, UIMessage, ToolSet } from 'ai';
8
8
  import * as pptx_angular_viewer from 'pptx-angular-viewer';
9
+ import { SafeHtml } from '@angular/platform-browser';
9
10
  import { TranslateService } from '@ngx-translate/core';
10
11
  import { Options } from 'html2canvas-pro';
11
- import { SafeHtml } from '@angular/platform-browser';
12
12
 
13
13
  /**
14
14
  * Theme configuration types for the PowerPoint viewer.
@@ -4591,7 +4591,9 @@ interface SlideTransitionAnimations {
4591
4591
  * The faithful Office 2010 (`p14`) keyframes are appended (via
4592
4592
  * {@link P14_TRANSITION_KEYFRAMES_ALL}) so the exotic / 3-D transitions routed
4593
4593
  * through `getP14TransitionAnimations` animate wherever this block is injected,
4594
- * with no per-binding wiring.
4594
+ * with no per-binding wiring. {@link FRAGMENT_TRANSITION_KEYFRAMES} is appended
4595
+ * last, backing the seven multi-fragment cinematic presets resolved by
4596
+ * `getFragmentedTransitionDescriptor` (`slide-transition-fragments.ts`).
4595
4597
  *
4596
4598
  * @module render/slide-transition-keyframes
4597
4599
  */
@@ -4644,6 +4646,68 @@ declare const SLIDE_TRANSITION_KEYFRAMES: string;
4644
4646
  */
4645
4647
  declare function getSlideTransitionAnimations(type: PptxTransitionType, durationMs: number, direction: string | undefined, orient?: string | undefined, spokes?: number | undefined, pattern?: string | undefined): SlideTransitionAnimations;
4646
4648
 
4649
+ /**
4650
+ * `slide-transition-fragment-types` - shared types and small pure helpers for
4651
+ * the multi-fragment cinematic transitions (`vortex`, `honeycomb`, `glitter`,
4652
+ * `shred`, `fracture`, `curtains`, `airplane`).
4653
+ *
4654
+ * These seven presets render in real PowerPoint as many independent
4655
+ * fragments, tiles, particles, or (for `airplane`) folded panels, not a
4656
+ * single animated layer - see `slide-transition-fragments.ts` for the
4657
+ * COM `CreateVideo` measurement writeup. A `FragmentedTransitionDescriptor`
4658
+ * is the pure, framework-neutral output every binding maps onto N clipped
4659
+ * copies of its own `SlideLayer`/`SlideCanvas` component: each fragment is a
4660
+ * full-size copy of the outgoing or incoming slide, clipped with `clip-path`
4661
+ * to its slice and animated with a shared `@keyframes` block (from
4662
+ * {@link FRAGMENT_TRANSITION_KEYFRAMES}) parameterised per fragment via CSS
4663
+ * custom properties, so the whole set is transform/opacity-only and
4664
+ * GPU-composited with no per-frame JS.
4665
+ *
4666
+ * @module render/slide-transition-fragment-types
4667
+ */
4668
+ /** One fragment: a clipped, independently-animated copy of a slide layer. */
4669
+ interface TransitionFragment {
4670
+ /** Stable id for keys / `data-*` attributes; unique within its layer. */
4671
+ id: string;
4672
+ /** `clip-path` value, in percentages of the full (unscaled) slide box. */
4673
+ clipPath: string;
4674
+ /**
4675
+ * CSS custom properties consumed by the shared `@keyframes` named by the
4676
+ * owning {@link FragmentedLayer.keyframesName}. Values are pre-formatted
4677
+ * (already unit-suffixed, e.g. `'34deg'`, `'-120%'`) so bindings can copy
4678
+ * them verbatim into an inline `style` object.
4679
+ */
4680
+ vars: Readonly<Record<string, string>>;
4681
+ /** `animation-delay`, in ms. */
4682
+ delayMs: number;
4683
+ /** `transform-origin`, e.g. `'50% 50%'`, so rotate/scale pivot correctly. */
4684
+ transformOrigin: string;
4685
+ }
4686
+ /** One layer (outgoing or incoming) rendered as N independent fragments. */
4687
+ interface FragmentedLayer {
4688
+ /** Name of the shared `@keyframes` block every fragment in this layer runs. */
4689
+ keyframesName: string;
4690
+ /** Per-fragment `animation-duration`, in ms. */
4691
+ durationMs: number;
4692
+ /** Per-fragment `animation-timing-function`. */
4693
+ easing: string;
4694
+ fragments: readonly TransitionFragment[];
4695
+ }
4696
+ /**
4697
+ * Resolved fragment plan for a cinematic transition. Either layer may be
4698
+ * absent: a layer with no entry here renders as a single, non-fragmented
4699
+ * copy exactly like every other transition (typically driven by the
4700
+ * existing {@link getCinematicTransitionAnimations} / p14 resolvers, which
4701
+ * remain the single-layer fallback for previews and any consumer that has
4702
+ * not adopted fragment rendering).
4703
+ */
4704
+ interface FragmentedTransitionDescriptor {
4705
+ outgoing?: FragmentedLayer;
4706
+ incoming?: FragmentedLayer;
4707
+ /** Same semantics as `SlideTransitionAnimations.outgoingOnTop`. */
4708
+ outgoingOnTop: boolean;
4709
+ }
4710
+
4647
4711
  /**
4648
4712
  * `slide-transition-options` - the pure option catalogues backing every
4649
4713
  * binding's slide-transition inspector section.
@@ -7651,6 +7715,17 @@ interface ViewerAdvancedOptions {
7651
7715
  * for their machine. See `resolve3DRenderingFlags`.
7652
7716
  */
7653
7717
  disable3DRendering: boolean;
7718
+ /**
7719
+ * `p:animEffect/@filter="pixelate"` defaults to snapping the element to
7720
+ * its end state (`cutIn`/`cutOut`), matching PowerPoint's own behaviour
7721
+ * (COM `CreateVideo` frame-diffing shows PowerPoint performs no animation
7722
+ * at all for this filter value). This turns on the blocky mosaic reveal
7723
+ * this renderer can build instead, for a viewer that would rather show
7724
+ * something animating than PowerPoint's own instant swap. See
7725
+ * `resolveFilterEffect` in `animation-filter-effects.ts` and
7726
+ * `docs/guide/visual-effects.md`.
7727
+ */
7728
+ pixelateMosaicAnimation: boolean;
7654
7729
  openDocumentsView: OpenDocumentsView;
7655
7730
  slideShowShowMenuOnRightClick: boolean;
7656
7731
  slideShowShowPopupToolbar: boolean;
@@ -8062,6 +8137,36 @@ interface CompatibilityWarningToast {
8062
8137
  readonly params?: Readonly<Record<string, string>>;
8063
8138
  }
8064
8139
 
8140
+ /**
8141
+ * run-program-notice.ts: turn a resolved `ppaction://program` command string
8142
+ * into the non-blocking notice a binding should show during a running show.
8143
+ *
8144
+ * PowerPoint's "Run program" action (`a:hlinkClick` -> `ppaction://program`,
8145
+ * `packages/shared/src/render/presentation-action.ts`'s `runProgram` intent)
8146
+ * names a free-text "Program to run:" command the author typed, e.g.
8147
+ * `notepad.exe C:\temp\notes.txt`. Path and arguments are ONE unstructured
8148
+ * string; OOXML has no separate arguments field, so this module does not try
8149
+ * to split one out.
8150
+ *
8151
+ * A browser cannot launch a local executable, so the honest behavior on
8152
+ * click is: show the presenter a small, dismissible notice naming the exact
8153
+ * command PowerPoint would have run, with a Copy button, rather than doing
8154
+ * nothing (silently) or blocking the show with a modal dialog.
8155
+ *
8156
+ * Framework-agnostic: no React, Vue, Angular, Svelte or DOM imports.
8157
+ */
8158
+ /** A run-program notice ready for a binding's toast/notice UI to render. */
8159
+ interface RunProgramNotice {
8160
+ /** Stable id for this invocation, so a binding can dedupe/key a toast list. */
8161
+ readonly id: string;
8162
+ /** The exact resolved command string (path plus whatever arguments the author typed). */
8163
+ readonly target: string;
8164
+ /** i18n key for the notice body. Interpolates `{{target}}`. */
8165
+ readonly messageKey: string;
8166
+ /** i18n key for the Copy button label. */
8167
+ readonly copyLabelKey: string;
8168
+ }
8169
+
8065
8170
  /**
8066
8171
  * Inspector option lists + pure patch builders for the three OOXML chart
8067
8172
  * subtype flags parsed/serialized in this wave: bar3D column/bar shape
@@ -8255,6 +8360,49 @@ declare function fpsToFrameIntervalMs(fps: number): number;
8255
8360
  */
8256
8361
  declare function segmentFrameCount(durationMs: number, fps: number): number;
8257
8362
 
8363
+ /**
8364
+ * Strategy selection for rasterising one export window (the whole slide for
8365
+ * a non-tiled export, or one tile's rectangle for a tiled export). Tries, in
8366
+ * order: the SVG `foreignObject` path (preserves `backdrop-filter`, custom
8367
+ * properties, 3D transforms because the browser's own engine paints it),
8368
+ * then the existing vector-SVG export pipeline rasterised the same way
8369
+ * (covers the case a resource could not be embedded as `data:`, so
8370
+ * `foreignObject` would taint the canvas), then `html2canvas-pro` as the
8371
+ * documented last resort. Every binding's `renderToCanvas` wrapper calls
8372
+ * this once per window; only the `html2canvasFallback` driver (the
8373
+ * `html2canvas-pro` import itself) stays per-binding.
8374
+ */
8375
+
8376
+ /** Which path actually produced the tile, for telemetry/tests. */
8377
+ type RasterStrategy = 'foreignObject' | 'vectorSvg' | 'html2canvas';
8378
+
8379
+ /** One rasterised tile: its full-raster position/size plus the canvas and strategy that produced it. */
8380
+ interface RasterizedTile {
8381
+ /** 0-based column index (tiles in the same row share increasing `col`). */
8382
+ col: number;
8383
+ /** 0-based row index. */
8384
+ row: number;
8385
+ /** Left edge, in full-raster device pixels. */
8386
+ x: number;
8387
+ /** Top edge, in full-raster device pixels. */
8388
+ y: number;
8389
+ width: number;
8390
+ height: number;
8391
+ canvas: HTMLCanvasElement;
8392
+ strategy: RasterStrategy;
8393
+ }
8394
+ /** The full set of tiles covering one element's export, tiled or not. */
8395
+ interface RasterizeElementTilesResult {
8396
+ /** Full raster width in device pixels (sum of every column's width). */
8397
+ fullWidth: number;
8398
+ /** Full raster height in device pixels (sum of every row's height). */
8399
+ fullHeight: number;
8400
+ /** `false` when a single tile already covers the whole export. */
8401
+ tiled: boolean;
8402
+ /** Every tile, row-major order. Exactly one entry when `tiled` is `false`. */
8403
+ tiles: RasterizedTile[];
8404
+ }
8405
+
8258
8406
  /**
8259
8407
  * Thin re-export shim → vendored `pptx-viewer-shared` (`render/embedded-fonts`).
8260
8408
  *
@@ -11230,6 +11378,124 @@ declare class ViewerDocumentPropertiesService {
11230
11378
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
11231
11379
  }
11232
11380
 
11381
+ declare class ExportService {
11382
+ private static readonly PRESENTATION_MIME;
11383
+ /** Build a resolution-independent SVG string directly from slide data. */
11384
+ exportSlideToSvg(slide: PptxSlide, width: number, height: number, options?: SvgExportOptions): string;
11385
+ /** Build an SVG Blob directly from slide data. */
11386
+ exportSlideToSvgBlob(slide: PptxSlide, width: number, height: number, options?: SvgExportOptions): Blob;
11387
+ /** Build SVG strings for all selected slides in a parsed presentation. */
11388
+ exportAllSlidesToSvg(data: PptxData, options?: SvgExportOptions): string[];
11389
+ /**
11390
+ * Trigger a browser download of serialized `.pptx` bytes.
11391
+ *
11392
+ * @param bytes - The serialized presentation (from the viewer's `getContent`).
11393
+ * @param fileName - Suggested download file name (unsafe chars are stripped).
11394
+ */
11395
+ savePptx(bytes: Uint8Array, fileName: string): void;
11396
+ /** Download serialized presentation bytes using the matching package MIME type. */
11397
+ savePresentation(bytes: Uint8Array, fileName: string, format: PptxSaveFormat): void;
11398
+ /**
11399
+ * Rasterize a single DOM element to PNG and trigger a browser download.
11400
+ *
11401
+ * @param el - The element to capture (e.g. the `.pptx-ng-canvas-stage`).
11402
+ * @param fileName - Suggested download file name (unsafe chars are stripped).
11403
+ * @param scale - Device-pixel ratio multiplier (default 2 for sharp output).
11404
+ */
11405
+ exportElementToPng(el: HTMLElement, fileName: string, scale?: number): Promise<void>;
11406
+ /** Rasterize an element and copy it to the system clipboard as a PNG image. */
11407
+ copyElementAsPng(el: HTMLElement, scale?: number): Promise<void>;
11408
+ /**
11409
+ * Rasterize `el` to a PNG `Blob` via the shared `foreignObject` -> vector-SVG
11410
+ * -> html2canvas fallback chain (preserves backdrop-filter, CSS custom
11411
+ * properties and 3D transforms html2canvas cannot), tiling transparently
11412
+ * for a resolution beyond the browser's canvas cap. Implementation in
11413
+ * `export-raster-tiles.ts`, next to the other shared-driver entry points.
11414
+ */
11415
+ private rasterizeElementToPngBlob;
11416
+ /**
11417
+ * Rasterize a single element to a single full-resolution canvas via the
11418
+ * shared `foreignObject` fidelity pipeline, tiling and stitching
11419
+ * transparently (never reducing the requested scale) so the result is
11420
+ * always one canvas - for GIF/video/print, which can only consume one
11421
+ * image per frame/page. `html2canvas-pro` is kept only as the documented
11422
+ * fallback driver. Capture each slide's canvas *while that slide is the
11423
+ * live DOM*: the viewer reuses one stage node, so a deferred capture would
11424
+ * yield the same (last) slide for every page. Implementation in
11425
+ * `export-raster-tiles.ts` (kept this file under the size budget).
11426
+ */
11427
+ renderElement(el: HTMLElement, scale?: number): Promise<HTMLCanvasElement>;
11428
+ /**
11429
+ * Rasterize a single element to its raw per-tile canvases via the shared
11430
+ * `foreignObject` fidelity pipeline, tiling transparently when the
11431
+ * requested resolution exceeds the browser's canvas cap - for PDF pages,
11432
+ * which have no canvas-size limit of their own and so can place several
11433
+ * small tile images instead of needing one oversized canvas.
11434
+ */
11435
+ renderElementToTiles(el: HTMLElement, scale?: number): Promise<RasterizeElementTilesResult>;
11436
+ /**
11437
+ * Assemble a multi-page PDF from pre-rendered per-slide tile sets (one page
11438
+ * per entry) and trigger a download. See `buildTiledPdf` in
11439
+ * `export-raster-tiles.ts` for the full behaviour (placement, degrade to
11440
+ * one-image-per-page for a single-tile slide, cap-escaping rationale).
11441
+ *
11442
+ * @param pages - One entry per slide, in order, each captured while
11443
+ * its slide was the live stage (`renderElementToTiles`).
11444
+ * @param canvasWidth - Slide canvas width in pixels (for aspect ratio).
11445
+ * @param canvasHeight - Slide canvas height in pixels (for aspect ratio).
11446
+ * @param fileName - Suggested download file name (unsafe chars stripped).
11447
+ */
11448
+ exportTiledPagesToPdf(pages: RasterizeElementTilesResult[], canvasWidth: number, canvasHeight: number, fileName: string): void;
11449
+ /**
11450
+ * Downscale a captured slide canvas to `maxSide` (via the shared
11451
+ * `clampGifDimensions`) and extract its RGBA pixels. GIF encoding cost
11452
+ * grows with pixel count (every pixel is matched against a 256-colour
11453
+ * palette per frame), so every binding bounds its capture before
11454
+ * quantising; see `resolveExportCaptureDecision`'s `postCaptureMaxSide`.
11455
+ */
11456
+ private static frameFromCanvas;
11457
+ /**
11458
+ * Assemble an animated GIF from pre-rendered slide canvases (one frame per
11459
+ * slide) and trigger a download. Frame delay is derived from
11460
+ * `slideDurationMs` via the pure {@link planGifFrames} planner. Each
11461
+ * canvas is downscaled to `maxSide` first (see
11462
+ * `resolveExportCaptureDecision`'s `postCaptureMaxSide` for `'gif'`).
11463
+ *
11464
+ * @param canvases - One canvas per slide, in order.
11465
+ * @param slideDurationMs - Display time per slide in milliseconds.
11466
+ * @param fileName - Suggested download file name.
11467
+ * @param maxSide - Longest allowed frame side in pixels after
11468
+ * capture. Defaults to `GIF_POST_CAPTURE_MAX_SIDE`.
11469
+ */
11470
+ exportCanvasesToGif(canvases: HTMLCanvasElement[], slideDurationMs: number, fileName: string, maxSide?: number): void;
11471
+ /**
11472
+ * Record a WebM video from pre-rendered slide canvases (each held for
11473
+ * `slideDurationMs`) via the browser `MediaRecorder` and trigger a download.
11474
+ *
11475
+ * @param canvases - One canvas per slide, in order.
11476
+ * @param slideDurationMs - Display time per slide in milliseconds.
11477
+ * @param fileName - Suggested download file name.
11478
+ * @param signal - Optional abort signal to cancel recording.
11479
+ * @param onProgress - Optional per-slide recording progress callback
11480
+ * `(currentSlide, totalSlides)`.
11481
+ */
11482
+ exportCanvasesToWebm(canvases: HTMLCanvasElement[], slideDurationMs: number, fileName: string, signal?: AbortSignal, onProgress?: (current: number, total: number) => void): Promise<void>;
11483
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ExportService, never>;
11484
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
11485
+ }
11486
+
11487
+ /**
11488
+ * Per-slide capture loops for `ViewerExportService`: flip the live stage to
11489
+ * each slide in turn, let it settle, and rasterise it (plain canvas, raw
11490
+ * tiles, or a PNG data URL), reporting progress and honouring cooperative
11491
+ * cancellation. Split out of `viewer-export.service.ts` to keep that file
11492
+ * under the file-size budget.
11493
+ *
11494
+ * Rasterisation itself is `ExportService`'s job (the shared `foreignObject`
11495
+ * fidelity pipeline, see `export-raster-tiles.ts`); this module only owns
11496
+ * the "make slide N the live DOM, then capture it" choreography.
11497
+ */
11498
+
11233
11499
  /** Live accessors the export loop needs from the host component. */
11234
11500
  interface ExportHost {
11235
11501
  /** The component's active-slide index (read + written to flip the live stage). */
@@ -11243,24 +11509,30 @@ interface ExportHost {
11243
11509
  /**
11244
11510
  * File > Options > Advanced > "Image Size and Quality"
11245
11511
  * (`resolveImageResolutionScale`), read fresh for every PNG/PDF capture.
11246
- * Not applied to GIF/video (those intentionally stay at their own fixed
11247
- * capture resolution). Defaults to 2 (the pre-existing hardcoded value)
11248
- * when omitted.
11512
+ * Defaults to 2 (the pre-existing hardcoded value) when omitted.
11249
11513
  */
11250
11514
  readonly imageExportScale?: () => number;
11515
+ /**
11516
+ * The raw `resolveImageResolutionScale` multiplier (without the PNG/PDF 2x
11517
+ * baseline folded in), read fresh for every GIF/video capture and fed into
11518
+ * the shared `resolveExportCaptureDecision`. Defaults to 1 (the "High
11519
+ * fidelity" preset) when omitted.
11520
+ */
11521
+ readonly imageResolutionScale?: () => number;
11251
11522
  }
11523
+
11252
11524
  declare class ViewerExportService {
11253
11525
  private readonly exportSvc;
11254
11526
  private readonly loader;
11255
11527
  private readonly print;
11256
11528
  private readonly translate;
11257
11529
  /** True while a PNG/PDF export is in progress (disables the buttons). */
11258
- readonly exporting: WritableSignal<boolean>;
11530
+ readonly exporting: _angular_core.WritableSignal<boolean>;
11259
11531
  /** Export-progress modal state (PDF / GIF / WebM). */
11260
- readonly modalOpen: WritableSignal<boolean>;
11261
- readonly modalTitle: WritableSignal<string>;
11262
- readonly progress: WritableSignal<number>;
11263
- readonly statusMessage: WritableSignal<string>;
11532
+ readonly modalOpen: _angular_core.WritableSignal<boolean>;
11533
+ readonly modalTitle: _angular_core.WritableSignal<string>;
11534
+ readonly progress: _angular_core.WritableSignal<number>;
11535
+ readonly statusMessage: _angular_core.WritableSignal<string>;
11264
11536
  /** Cooperative cancellation: the capture loop checks `signal.aborted`. */
11265
11537
  private abort;
11266
11538
  private host;
@@ -11296,17 +11568,12 @@ declare class ViewerExportService {
11296
11568
  private beginExport;
11297
11569
  private endExport;
11298
11570
  /**
11299
- * Render every slide to a canvas (each made the live stage in turn), reporting
11300
- * per-slide progress and bailing out cooperatively when `abortSignal.aborted`.
11571
+ * Progress-reporting sink handed to the extracted capture-loop functions
11572
+ * in `viewer-export-capture.ts`, called directly at each export call site
11573
+ * (`captureSlideCanvases`/`captureSlideTiles`/`captureSlideDataUrl`) rather
11574
+ * than via a same-named private wrapper per method.
11301
11575
  */
11302
- private captureSlideCanvases;
11303
- /**
11304
- * Flip the live stage to `index`, let it settle, and capture it to a PNG
11305
- * data URL. `scale` defaults to the host's own Image Size/Quality scale
11306
- * (matching PNG/PDF export); the print notes/handouts path passes a higher
11307
- * value when Options > Advanced > "High quality" is on.
11308
- */
11309
- private captureSlideDataUrl;
11576
+ private readonly progressSinks;
11310
11577
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ViewerExportService, never>;
11311
11578
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
11312
11579
  }
@@ -11682,6 +11949,13 @@ declare class ViewerOptionsService {
11682
11949
  * vanilla/vue/svelte bindings.
11683
11950
  */
11684
11951
  imageExportScale(): number;
11952
+ /**
11953
+ * The raw `resolveImageResolutionScale` multiplier (1 at the default "High
11954
+ * fidelity" preset), without the PNG/PDF-specific 2x baseline folded in.
11955
+ * Fed into GIF/video export's shared `resolveExportCaptureDecision`, which
11956
+ * applies its own baseline.
11957
+ */
11958
+ imageResolutionScale(): number;
11685
11959
  /** Print-dialog seed; `undefined` keeps the dialog's own recents. */
11686
11960
  printDefaults(): Partial<PrintSettings> | undefined;
11687
11961
  /** Option-driven CSS classes for the viewer root (`pptx-ng-*` prefixed). */
@@ -12777,77 +13051,6 @@ declare class EmbeddedFontsService {
12777
13051
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
12778
13052
  }
12779
13053
 
12780
- declare class ExportService {
12781
- private static readonly PRESENTATION_MIME;
12782
- /** Build a resolution-independent SVG string directly from slide data. */
12783
- exportSlideToSvg(slide: PptxSlide, width: number, height: number, options?: SvgExportOptions): string;
12784
- /** Build an SVG Blob directly from slide data. */
12785
- exportSlideToSvgBlob(slide: PptxSlide, width: number, height: number, options?: SvgExportOptions): Blob;
12786
- /** Build SVG strings for all selected slides in a parsed presentation. */
12787
- exportAllSlidesToSvg(data: PptxData, options?: SvgExportOptions): string[];
12788
- /**
12789
- * Trigger a browser download of serialized `.pptx` bytes.
12790
- *
12791
- * @param bytes - The serialized presentation (from the viewer's `getContent`).
12792
- * @param fileName - Suggested download file name (unsafe chars are stripped).
12793
- */
12794
- savePptx(bytes: Uint8Array, fileName: string): void;
12795
- /** Download serialized presentation bytes using the matching package MIME type. */
12796
- savePresentation(bytes: Uint8Array, fileName: string, format: PptxSaveFormat): void;
12797
- /**
12798
- * Rasterize a single DOM element to PNG and trigger a browser download.
12799
- *
12800
- * @param el - The element to capture (e.g. the `.pptx-ng-canvas-stage`).
12801
- * @param fileName - Suggested download file name (unsafe chars are stripped).
12802
- * @param scale - Device-pixel ratio multiplier (default 2 for sharp output).
12803
- */
12804
- exportElementToPng(el: HTMLElement, fileName: string, scale?: number): Promise<void>;
12805
- /** Rasterize an element and copy it to the system clipboard as a PNG image. */
12806
- copyElementAsPng(el: HTMLElement, scale?: number): Promise<void>;
12807
- /**
12808
- * Rasterize a single element to a canvas (passthrough to html2canvas-pro).
12809
- * Capture each slide's canvas *while that slide is the live DOM*: the
12810
- * viewer reuses one stage node, so a deferred capture would yield the same
12811
- * (last) slide for every page.
12812
- */
12813
- renderElement(el: HTMLElement, scale?: number): Promise<HTMLCanvasElement>;
12814
- /**
12815
- * Assemble a multi-page PDF from pre-rendered slide canvases (one page per
12816
- * canvas, sized to the slide aspect ratio in pt) and trigger a download.
12817
- *
12818
- * @param canvases - One canvas per slide, in order, each captured while
12819
- * its slide was the live stage.
12820
- * @param canvasWidth - Slide canvas width in pixels (for aspect ratio).
12821
- * @param canvasHeight - Slide canvas height in pixels (for aspect ratio).
12822
- * @param fileName - Suggested download file name (unsafe chars stripped).
12823
- */
12824
- exportCanvasesToPdf(canvases: HTMLCanvasElement[], canvasWidth: number, canvasHeight: number, fileName: string): void;
12825
- /**
12826
- * Assemble an animated GIF from pre-rendered slide canvases (one frame per
12827
- * slide) and trigger a download. Frame delay is derived from
12828
- * `slideDurationMs` via the pure {@link planGifFrames} planner.
12829
- *
12830
- * @param canvases - One canvas per slide, in order.
12831
- * @param slideDurationMs - Display time per slide in milliseconds.
12832
- * @param fileName - Suggested download file name.
12833
- */
12834
- exportCanvasesToGif(canvases: HTMLCanvasElement[], slideDurationMs: number, fileName: string): void;
12835
- /**
12836
- * Record a WebM video from pre-rendered slide canvases (each held for
12837
- * `slideDurationMs`) via the browser `MediaRecorder` and trigger a download.
12838
- *
12839
- * @param canvases - One canvas per slide, in order.
12840
- * @param slideDurationMs - Display time per slide in milliseconds.
12841
- * @param fileName - Suggested download file name.
12842
- * @param signal - Optional abort signal to cancel recording.
12843
- * @param onProgress - Optional per-slide recording progress callback
12844
- * `(currentSlide, totalSlides)`.
12845
- */
12846
- exportCanvasesToWebm(canvases: HTMLCanvasElement[], slideDurationMs: number, fileName: string, signal?: AbortSignal, onProgress?: (current: number, total: number) => void): Promise<void>;
12847
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ExportService, never>;
12848
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<any>;
12849
- }
12850
-
12851
13054
  /**
12852
13055
  * `FieldContextService`: viewer-scoped source of the OOXML field-substitution
12853
13056
  * context (slide number, date/time, header/footer, slide title, custom doc
@@ -12895,6 +13098,18 @@ declare class GoogleWebfontsService {
12895
13098
  * Pass empty slides / fonts (e.g. before a load) to remove it.
12896
13099
  */
12897
13100
  sync(slides: readonly PptxSlide[], embeddedFonts: readonly PptxEmbeddedFont[]): void;
13101
+ /**
13102
+ * Best-effort glyph-outline bytes for catalogue webfonts. A WordArt
13103
+ * envelope glyph (inflate/deflate/can) in a referenced (not embedded)
13104
+ * family only gets true outline warping once the ACTUAL font file's bytes
13105
+ * are fetched (the `<link>` stylesheet carries no glyph geometry, see
13106
+ * `text-warp-outline-webfont-fetch.ts`). Additive and best-effort: a
13107
+ * failure just leaves the affine-transform fallback in place.
13108
+ * `glyphOutlineFontsTick` is bumped so `text-warp-glyph.ts`'s
13109
+ * `buildGlyphWarpDef` (read inside `glyphWarp`'s `computed()`) recomputes
13110
+ * once bytes land.
13111
+ */
13112
+ private syncOutlineBytes;
12898
13113
  /**
12899
13114
  * Remove the injected `<link>` element and invalidate in-flight resolutions.
12900
13115
  * Called automatically on destroy; safe to call manually.
@@ -14523,6 +14738,12 @@ declare class SlideCanvasComponent implements SlideContext {
14523
14738
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlideCanvasComponent, "pptx-slide-canvas", never, { "slide": { "alias": "slide"; "required": false; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "showGrid": { "alias": "showGrid"; "required": false; "isSignal": true; }; "showRulers": { "alias": "showRulers"; "required": false; "isSignal": true; }; "rulerUnit": { "alias": "rulerUnit"; "required": false; "isSignal": true; }; "showGuides": { "alias": "showGuides"; "required": false; "isSignal": true; }; "snapToGrid": { "alias": "snapToGrid"; "required": false; "isSignal": true; }; "gridSpacing": { "alias": "gridSpacing"; "required": false; "isSignal": true; }; "snapToShape": { "alias": "snapToShape"; "required": false; "isSignal": true; }; "guideCommand": { "alias": "guideCommand"; "required": false; "isSignal": true; }; "spellCheck": { "alias": "spellCheck"; "required": false; "isSignal": true; }; "snapToGuides": { "alias": "snapToGuides"; "required": false; "isSignal": true; }; "autoFit": { "alias": "autoFit"; "required": false; "isSignal": true; }; "transparentBackground": { "alias": "transparentBackground"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "exposeElementIds": { "alias": "exposeElementIds"; "required": false; "isSignal": true; }; "presenting": { "alias": "presenting"; "required": false; "isSignal": true; }; "selectedIds": { "alias": "selectedIds"; "required": false; "isSignal": true; }; "editingId": { "alias": "editingId"; "required": false; "isSignal": true; }; "editTemplateMode": { "alias": "editTemplateMode"; "required": false; "isSignal": true; }; "templateElements": { "alias": "templateElements"; "required": false; "isSignal": true; }; "aiHighlights": { "alias": "aiHighlights"; "required": false; "isSignal": true; }; "aiActive": { "alias": "aiActive"; "required": false; "isSignal": true; }; "aiActiveSlideIndex": { "alias": "aiActiveSlideIndex"; "required": false; "isSignal": true; }; "aiChangeBatch": { "alias": "aiChangeBatch"; "required": false; "isSignal": true; }; "aiPickMode": { "alias": "aiPickMode"; "required": false; "isSignal": true; }; "drawTool": { "alias": "drawTool"; "required": false; "isSignal": true; }; "drawColor": { "alias": "drawColor"; "required": false; "isSignal": true; }; "drawWidth": { "alias": "drawWidth"; "required": false; "isSignal": true; }; }, { "elementSelect": "elementSelect"; "backgroundClick": "backgroundClick"; "transformStart": "transformStart"; "transformUpdate": "transformUpdate"; "transformEnd": "transformEnd"; "adjustUpdate": "adjustUpdate"; "connectorEndpointUpdate": "connectorEndpointUpdate"; "contextMenu": "contextMenu"; "textEditStart": "textEditStart"; "textCommit": "textCommit"; "textInput": "textInput"; "textCancel": "textCancel"; "textFormat": "textFormat"; "rotateUpdate": "rotateUpdate"; "marqueeSelect": "marqueeSelect"; "inkStrokeComplete": "inkStrokeComplete"; "eraserHit": "eraserHit"; "cellCommit": "cellCommit"; "tableChange": "tableChange"; }, never, ["*"], true, never>;
14524
14739
  }
14525
14740
 
14741
+ /** Injectable bevel lighting `<filter>` descriptor: id + sanitized markup. */
14742
+ interface BevelLightingFilterDef {
14743
+ id: string;
14744
+ markup: SafeHtml;
14745
+ }
14746
+
14526
14747
  /**
14527
14748
  * Renderer-injected shape-effect definitions that need a companion DOM node
14528
14749
  * (a soft-edge `<filter>` def, a DAG fill-overlay tint layer), plus the helper
@@ -14578,6 +14799,8 @@ declare class ElementRendererComponent {
14578
14799
  */
14579
14800
  private readonly playback;
14580
14801
  private readonly translate;
14802
+ /** For {@link bevelLightingFilter}'s injected `<filter>` markup. */
14803
+ private readonly sanitizer;
14581
14804
  readonly smartArt3D: _angular_core.Signal<boolean>;
14582
14805
  /** Whether the Selection Pane has hidden this element; see the empty first `@case`. */
14583
14806
  readonly isHidden: _angular_core.Signal<boolean>;
@@ -14687,6 +14910,8 @@ declare class ElementRendererComponent {
14687
14910
  * resolves. Undefined otherwise.
14688
14911
  */
14689
14912
  readonly softEdgeFilter: _angular_core.Signal<SoftEdgeFilterDef | undefined>;
14913
+ /** `a:sp3d` bevel lighting `<filter>` descriptor; see `bevel-lighting-filter.ts`. */
14914
+ readonly bevelLightingFilter: _angular_core.Signal<BevelLightingFilterDef | undefined>;
14690
14915
  /**
14691
14916
  * `a:reflection` mirrored-sibling descriptor, or `undefined`. Used by the
14692
14917
  * `group` branch below (a group reflects its whole composited subtree);
@@ -15851,18 +16076,6 @@ declare class ZoomRendererComponent {
15851
16076
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZoomRendererComponent, "pptx-zoom-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "markElement": { "alias": "markElement"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
15852
16077
  }
15853
16078
 
15854
- /**
15855
- * presentation-overlay-chrome-styles.ts: the fixed-position inline styles for
15856
- * the slide-show overlay's own chrome (close button, edge navigation buttons,
15857
- * slide counter).
15858
- *
15859
- * These are `[ngStyle]` records rather than CSS classes because they must beat
15860
- * whatever the host page's stylesheet does to a `<button>` inside a fullscreen
15861
- * overlay, and because the safe-area `env()` offsets are read straight back by
15862
- * the mobile e2e specs. They are static data with no dependency on component
15863
- * state, so they live here instead of taking up a third of
15864
- * {@link PresentationOverlayComponent}.
15865
- */
15866
16079
  /** Inline style record as Angular's `[ngStyle]` consumes it. */
15867
16080
  type OverlayStyle = Record<string, string>;
15868
16081
 
@@ -15922,6 +16135,14 @@ declare class AnimationPlaybackService {
15922
16135
  slideHeightPx?: number;
15923
16136
  /** The deck's resolved theme colour map, for a scheme-colour (`a:schemeClr`) animation stop. */
15924
16137
  themeColorMap?: Readonly<Record<string, string>>;
16138
+ /**
16139
+ * `viewerOptions.advanced.pixelateMosaicAnimation`. `true` plays the
16140
+ * blocky mosaic reveal for `p:animEffect/@filter="pixelate"`; omitted
16141
+ * or `false` (the default, matching PowerPoint's own behaviour) snaps
16142
+ * the element to its end state. See `resolveFilterEffect`'s doc in
16143
+ * `pptx-viewer-shared`'s `animation-filter-effects.ts`.
16144
+ */
16145
+ pixelateMosaic?: boolean;
15925
16146
  }): void;
15926
16147
  /**
15927
16148
  * True while the active slide shows its builds as already complete because
@@ -16243,6 +16464,14 @@ interface ShowNavigatorDeps {
16243
16464
  };
16244
16465
  /** The deck's resolved theme colour map, for a scheme-colour (`a:schemeClr`) animation stop. */
16245
16466
  themeColorMap?: () => Readonly<Record<string, string>> | undefined;
16467
+ /**
16468
+ * `viewerOptions.advanced.pixelateMosaicAnimation`. `true` plays the
16469
+ * blocky mosaic reveal for `p:animEffect/@filter="pixelate"`; omitted or
16470
+ * `false` (the default, matching PowerPoint's own behaviour) snaps the
16471
+ * element to its end state. See `resolveFilterEffect`'s doc in
16472
+ * `pptx-viewer-shared`'s `animation-filter-effects.ts`.
16473
+ */
16474
+ pixelateMosaicAnimation?: () => boolean | undefined;
16246
16475
  playback: AnimationPlaybackService;
16247
16476
  annotations: PresentationAnnotationsService;
16248
16477
  /** Publish a committed index change to the host's `indexChange` output. */
@@ -16374,6 +16603,14 @@ interface PresentationInputDeps {
16374
16603
  * restores the origin show + slide once the sub-show runs off its end.
16375
16604
  */
16376
16605
  runCustomShow?: (customShowId: string, returnAfter: boolean) => void;
16606
+ /**
16607
+ * `ppaction://program`: PowerPoint's "Run program" action. A browser cannot
16608
+ * launch a local executable, so the host is expected to surface a
16609
+ * non-blocking notice naming the resolved command (see
16610
+ * `buildRunProgramNotice` in `pptx-viewer-shared`) rather than doing
16611
+ * nothing. Omitted means the click is still consumed, just silently.
16612
+ */
16613
+ runProgram?: (target: string) => void;
16377
16614
  }
16378
16615
  declare class PresentationInputController {
16379
16616
  private readonly deps;
@@ -16420,6 +16657,19 @@ declare class PresentationInputController {
16420
16657
  private toggleBlank;
16421
16658
  }
16422
16659
 
16660
+ declare class RunProgramNoticeStore {
16661
+ /** Notices currently on screen, oldest first. */
16662
+ readonly notices: _angular_core.WritableSignal<readonly RunProgramNotice[]>;
16663
+ /**
16664
+ * Build a fresh notice for `target` and append it. Every call adds a new
16665
+ * notice (even for the same target clicked twice in a row): each click is
16666
+ * its own event the presenter may want to copy independently.
16667
+ */
16668
+ add(target: string): void;
16669
+ /** Dismiss one notice by id. */
16670
+ dismiss(id: string): void;
16671
+ }
16672
+
16423
16673
  /**
16424
16674
  * PresentationOverlayComponent: full-viewport black overlay that renders
16425
16675
  * slides in presentation (kiosk) mode.
@@ -16498,6 +16748,12 @@ declare class PresentationOverlayComponent implements OnInit {
16498
16748
  * once instead of sitting on the last slide swallowing every advance.
16499
16749
  */
16500
16750
  readonly endWithBlackSlide: _angular_core.InputSignal<boolean>;
16751
+ /**
16752
+ * File > Options > Advanced > "Show a mosaic effect for Pixelate
16753
+ * transitions" (default false, matching PowerPoint's own instant-swap
16754
+ * behaviour for `p:animEffect/@filter="pixelate"`).
16755
+ */
16756
+ readonly pixelateMosaicAnimation: _angular_core.InputSignal<boolean>;
16501
16757
  /** Whether presenter view is up (tints the toolbar's presenter-view toggle). */
16502
16758
  readonly presenterMode: _angular_core.InputSignal<boolean>;
16503
16759
  /**
@@ -16545,6 +16801,12 @@ declare class PresentationOverlayComponent implements OnInit {
16545
16801
  protected readonly playback: AnimationPlaybackService;
16546
16802
  /** Ink-annotation state (pen/highlighter/eraser/laser) for the show. */
16547
16803
  protected readonly annotations: PresentationAnnotationsService;
16804
+ /**
16805
+ * `ppaction://program` ("Run program") notices: a browser cannot launch the
16806
+ * command, so the click surfaces a dismissible notice naming it instead.
16807
+ * See `run-program-notice-store.ts`.
16808
+ */
16809
+ protected readonly runProgramNotices: RunProgramNoticeStore;
16548
16810
  /**
16549
16811
  * The show's navigation state machine (index, end-of-show screen, slide
16550
16812
  * transition, timed auto-advance). See `presentation-show-navigator.ts`.
@@ -16716,7 +16978,7 @@ declare class PresentationOverlayComponent implements OnInit {
16716
16978
  private runChromeAction;
16717
16979
  private emitClosed;
16718
16980
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PresentationOverlayComponent, never>;
16719
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PresentationOverlayComponent, "pptx-presentation-overlay", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "startIndex": { "alias": "startIndex"; "required": false; "isSignal": true; }; "activeCustomShow": { "alias": "activeCustomShow"; "required": false; "isSignal": true; }; "authoredRange": { "alias": "authoredRange"; "required": false; "isSignal": true; }; "loopContinuously": { "alias": "loopContinuously"; "required": false; "isSignal": true; }; "showWithAnimation": { "alias": "showWithAnimation"; "required": false; "isSignal": true; }; "useTimings": { "alias": "useTimings"; "required": false; "isSignal": true; }; "subtitlesVisible": { "alias": "subtitlesVisible"; "required": false; "isSignal": true; }; "sessionEnded": { "alias": "sessionEnded"; "required": false; "isSignal": true; }; "endWithBlackSlide": { "alias": "endWithBlackSlide"; "required": false; "isSignal": true; }; "presenterMode": { "alias": "presenterMode"; "required": false; "isSignal": true; }; "showMenuOnRightClick": { "alias": "showMenuOnRightClick"; "required": false; "isSignal": true; }; "showPopupToolbar": { "alias": "showPopupToolbar"; "required": false; "isSignal": true; }; }, { "indexChange": "indexChange"; "closed": "closed"; "subtitlesChange": "subtitlesChange"; "presenterViewToggle": "presenterViewToggle"; "annotationsExit": "annotationsExit"; "customShowRequest": "customShowRequest"; "endOfShowChange": "endOfShowChange"; }, never, never, true, never>;
16981
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PresentationOverlayComponent, "pptx-presentation-overlay", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "startIndex": { "alias": "startIndex"; "required": false; "isSignal": true; }; "activeCustomShow": { "alias": "activeCustomShow"; "required": false; "isSignal": true; }; "authoredRange": { "alias": "authoredRange"; "required": false; "isSignal": true; }; "loopContinuously": { "alias": "loopContinuously"; "required": false; "isSignal": true; }; "showWithAnimation": { "alias": "showWithAnimation"; "required": false; "isSignal": true; }; "useTimings": { "alias": "useTimings"; "required": false; "isSignal": true; }; "subtitlesVisible": { "alias": "subtitlesVisible"; "required": false; "isSignal": true; }; "sessionEnded": { "alias": "sessionEnded"; "required": false; "isSignal": true; }; "endWithBlackSlide": { "alias": "endWithBlackSlide"; "required": false; "isSignal": true; }; "pixelateMosaicAnimation": { "alias": "pixelateMosaicAnimation"; "required": false; "isSignal": true; }; "presenterMode": { "alias": "presenterMode"; "required": false; "isSignal": true; }; "showMenuOnRightClick": { "alias": "showMenuOnRightClick"; "required": false; "isSignal": true; }; "showPopupToolbar": { "alias": "showPopupToolbar"; "required": false; "isSignal": true; }; }, { "indexChange": "indexChange"; "closed": "closed"; "subtitlesChange": "subtitlesChange"; "presenterViewToggle": "presenterViewToggle"; "annotationsExit": "annotationsExit"; "customShowRequest": "customShowRequest"; "endOfShowChange": "endOfShowChange"; }, never, never, true, never>;
16720
16982
  }
16721
16983
 
16722
16984
  /**
@@ -20305,7 +20567,7 @@ declare class AccountPageComponent {
20305
20567
  readonly accountAuth: _angular_core.InputSignal<AccountAuthConfig | undefined>;
20306
20568
  private readonly translate;
20307
20569
  protected readonly swatches: readonly string[];
20308
- protected readonly version = "3.11.0";
20570
+ protected readonly version = "3.13.0";
20309
20571
  protected readonly profile: _angular_core.WritableSignal<ViewerProfile>;
20310
20572
  protected readonly initial: _angular_core.Signal<string>;
20311
20573
  protected readonly usage: _angular_core.WritableSignal<LocalStorageUsageSummary | null>;
@@ -20719,34 +20981,6 @@ declare class PresentationToolbarComponent {
20719
20981
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<PresentationToolbarComponent, "pptx-presentation-toolbar", never, { "currentSlideIndex": { "alias": "currentSlideIndex"; "required": true; "isSignal": true; }; "totalSlides": { "alias": "totalSlides"; "required": true; "isSignal": true; }; "presentationStartTime": { "alias": "presentationStartTime"; "required": false; "isSignal": true; }; "presenterMode": { "alias": "presenterMode"; "required": false; "isSignal": true; }; "popupToolbarEnabled": { "alias": "popupToolbarEnabled"; "required": false; "isSignal": true; }; }, { "move": "move"; "endPresentation": "endPresentation"; "presenterViewToggle": "presenterViewToggle"; }, never, never, true, never>;
20720
20982
  }
20721
20983
 
20722
- /**
20723
- * transition-helpers.ts
20724
- *
20725
- * Thin re-export shim over the framework-agnostic slide-transition CSS/keyframe
20726
- * generator in `pptx-viewer-shared` (vendored via `../internal/shared`).
20727
- *
20728
- * The pure logic (direction/orientation resolution, the `pptx-tr-*` keyframe
20729
- * block (`SLIDE_TRANSITION_KEYFRAMES`), and the type→`animation` resolver
20730
- * (`getSlideTransitionAnimations`, including the exotic/3-D 2-D approximations
20731
- * that originated here) now lives in shared and is consumed by every binding.
20732
- *
20733
- * The presentation overlay's duration comes from the shared resolver
20734
- * (`resolveTransitionDurationMs`), exactly as in the other four bindings, so
20735
- * an authored `p14:dur`, the legacy `spd` token and the COM-verified defaults
20736
- * all play at PowerPoint's speed here too. The older local floor/default
20737
- * policy (`MIN_TRANSITION_DURATION_MS` / `DEFAULT_TRANSITION_DURATION_MS` /
20738
- * `resolveTransitionDuration`) stays exported for callers that adopted it, but
20739
- * the overlay no longer consults it.
20740
- */
20741
-
20742
- /**
20743
- * Resolve an effective duration (ms) from an optional authored value, applying
20744
- * the minimum floor and the local default. Kept as a public helper; the
20745
- * presentation overlay resolves through the shared
20746
- * {@link resolveOverlayDurationMs} instead, which is what plays on screen.
20747
- */
20748
- declare function resolveTransitionDuration(durationMs: number | undefined): number;
20749
-
20750
20984
  /** One cross-dissolving pair, as the two single-element slides that paint it. */
20751
20985
  interface MorphCrossfadeGroupSlides {
20752
20986
  key: string;
@@ -20765,6 +20999,7 @@ interface MorphCrossfadeGroupSlides {
20765
20999
  outgoing: PptxSlide;
20766
21000
  incoming: PptxSlide;
20767
21001
  }
21002
+
20768
21003
  /**
20769
21004
  * PresentationTransitionOverlayComponent: plays a PowerPoint slide transition
20770
21005
  * over the presentation stage.
@@ -20825,62 +21060,24 @@ declare class PresentationTransitionOverlayComponent {
20825
21060
  /** Owned `<style>` element carrying the active morph rules, if any. */
20826
21061
  private morphStyle;
20827
21062
  private applyMorphStyle;
20828
- /** Effective transition duration (ms), floored/defaulted. */
21063
+ private readonly state;
20829
21064
  protected readonly resolvedDurationMs: _angular_core.Signal<number>;
20830
- /** Resolved CSS animation descriptors for the outgoing/incoming layers. */
20831
- protected readonly animations: _angular_core.Signal<SlideTransitionAnimations>;
20832
- /**
20833
- * Active Morph plan, or `undefined` for every other transition.
20834
- *
20835
- * Morph travels individual shapes between the two slides rather than wiping
20836
- * the surface, so it changes what this overlay paints: a per-shape copy of
20837
- * the outgoing slide, each one gliding onto its counterpart (dissolving into
20838
- * it when its appearance changed) or fading out in place when it has none.
20839
- * The incoming halves are animated on the live stage by document-level rules
20840
- * (see `morphStyleEffect`).
20841
- */
21065
+ protected readonly animations: _angular_core.Signal<pptx_angular_viewer.SlideTransitionAnimations>;
21066
+ protected readonly fragmented: _angular_core.Signal<FragmentedTransitionDescriptor | undefined>;
21067
+ protected readonly fragmentedOutgoing: _angular_core.Signal<FragmentedLayer | undefined>;
21068
+ protected readonly fragmentedIncoming: _angular_core.Signal<FragmentedLayer | undefined>;
21069
+ protected readonly fragmentedOutgoingZIndex: _angular_core.Signal<number>;
21070
+ protected readonly fragmentedIncomingZIndex: _angular_core.Signal<number>;
21071
+ protected readonly incomingFragmentSlide: _angular_core.Signal<PptxSlide | undefined>;
20842
21072
  protected readonly morphPlan: _angular_core.Signal<MorphTransitionPlan | undefined>;
20843
- /**
20844
- * Whether this overlay is playing a morph.
20845
- *
20846
- * A morph layer paints only the departing slide's paired shapes over the live
20847
- * incoming stage, so its stage background must be dropped
20848
- * (`transparentBackground`). Every other transition animates a whole slide
20849
- * surface out and keeps its own background.
20850
- */
20851
21073
  protected readonly isMorph: _angular_core.Signal<boolean>;
20852
- /** The slide rendered in the animated layer (outgoing + its template). */
20853
21074
  protected readonly layerSlide: _angular_core.Signal<PptxSlide>;
20854
- /**
20855
- * The arriving shapes the morph has to paint over its own ghosts, or
20856
- * `undefined` when there are none (issue #146). They sit on the live stage
20857
- * below this overlay, where the departing layer would hide them for the whole
20858
- * transition; the plan holds that copy invisible and hands them here instead.
20859
- */
20860
21075
  protected readonly liftedSlide: _angular_core.Signal<PptxSlide | undefined>;
20861
- /**
20862
- * The cross-dissolving pairs this overlay paints both halves of, each in its
20863
- * own isolated group so the halves are summed rather than stacked.
20864
- */
20865
21076
  protected readonly crossfadeGroups: _angular_core.Signal<MorphCrossfadeGroupSlides[]>;
20866
- /** Layer container style: animation + stacking relative to the stage. */
20867
- protected readonly layerStyle: _angular_core.Signal<StyleMap>;
20868
- /**
20869
- * The arriving slide rendered ABOVE the outgoing layer for a classic
20870
- * transition, carrying the incoming animation (wipe/cover/fade/push), or
20871
- * `undefined` for morphs and the uncover family (which reveal the live
20872
- * stage instead).
20873
- */
21077
+ protected readonly layerStyle: _angular_core.Signal<pptx_angular_viewer.StyleMap>;
20874
21078
  protected readonly incomingLayerSlide: _angular_core.Signal<PptxSlide | undefined>;
20875
- /** Style for that arriving layer: the incoming animation + its stacking. */
20876
- protected readonly incomingLayerStyle: _angular_core.Signal<StyleMap>;
20877
- /**
20878
- * Slide box sized to the ZOOMED slide footprint, matching the stage's own
20879
- * `pptx-slide-canvas`. The inner canvas renders at the same `zoom` with
20880
- * `autoFit` off, so the outgoing slide is pixel-for-pixel the size of the
20881
- * incoming one for the whole animation.
20882
- */
20883
- protected readonly slideBoxStyle: _angular_core.Signal<StyleMap>;
21079
+ protected readonly incomingLayerStyle: _angular_core.Signal<pptx_angular_viewer.StyleMap>;
21080
+ protected readonly slideBoxStyle: _angular_core.Signal<pptx_angular_viewer.StyleMap>;
20884
21081
  private armCompletion;
20885
21082
  private clearTimer;
20886
21083
  /**
@@ -21085,6 +21282,34 @@ declare class MobilePresenterViewComponent {
21085
21282
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobilePresenterViewComponent, "pptx-mobile-presenter-view", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "currentSlideIndex": { "alias": "currentSlideIndex"; "required": true; "isSignal": true; }; "activeCustomShow": { "alias": "activeCustomShow"; "required": false; "isSignal": true; }; "authoredRange": { "alias": "authoredRange"; "required": false; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "templateElements": { "alias": "templateElements"; "required": false; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "presentationStartTime": { "alias": "presentationStartTime"; "required": false; "isSignal": true; }; }, { "movePresentationSlide": "movePresentationSlide"; "exit": "exit"; }, never, never, true, never>;
21086
21283
  }
21087
21284
 
21285
+ /**
21286
+ * transition-helpers.ts
21287
+ *
21288
+ * Thin re-export shim over the framework-agnostic slide-transition CSS/keyframe
21289
+ * generator in `pptx-viewer-shared` (vendored via `../internal/shared`).
21290
+ *
21291
+ * The pure logic (direction/orientation resolution, the `pptx-tr-*` keyframe
21292
+ * block (`SLIDE_TRANSITION_KEYFRAMES`), and the type→`animation` resolver
21293
+ * (`getSlideTransitionAnimations`, including the exotic/3-D 2-D approximations
21294
+ * that originated here) now lives in shared and is consumed by every binding.
21295
+ *
21296
+ * The presentation overlay's duration comes from the shared resolver
21297
+ * (`resolveTransitionDurationMs`), exactly as in the other four bindings, so
21298
+ * an authored `p14:dur`, the legacy `spd` token and the COM-verified defaults
21299
+ * all play at PowerPoint's speed here too. The older local floor/default
21300
+ * policy (`MIN_TRANSITION_DURATION_MS` / `DEFAULT_TRANSITION_DURATION_MS` /
21301
+ * `resolveTransitionDuration`) stays exported for callers that adopted it, but
21302
+ * the overlay no longer consults it.
21303
+ */
21304
+
21305
+ /**
21306
+ * Resolve an effective duration (ms) from an optional authored value, applying
21307
+ * the minimum floor and the local default. Kept as a public helper; the
21308
+ * presentation overlay resolves through the shared
21309
+ * {@link resolveOverlayDurationMs} instead, which is what plays on screen.
21310
+ */
21311
+ declare function resolveTransitionDuration(durationMs: number | undefined): number;
21312
+
21088
21313
  /**
21089
21314
  * presenter-view-helpers.ts
21090
21315
  *
@@ -21185,6 +21410,15 @@ interface WarpGlyph {
21185
21410
  * The template appends `-s{index}` per slice.
21186
21411
  */
21187
21412
  readonly clipIdPrefix: string;
21413
+ /**
21414
+ * A warped SVG path `d` for this glyph's ACTUAL outline (see
21415
+ * `buildWarpedGlyphOutlinePathD` in pptx-viewer-shared), present only when
21416
+ * a real font file was obtainable for this glyph's family/style. When set,
21417
+ * the template renders `<path d [fill]>` instead of `<text transform>` /
21418
+ * `slices`: exact, since every outline point is already mapped through the
21419
+ * envelope curve at its OWN x.
21420
+ */
21421
+ readonly outlinePath?: string;
21188
21422
  }
21189
21423
  /** Descriptor for the true two-curve envelope renderer. One `<text>` per glyph. */
21190
21424
  interface TextWarpGlyphDef {
@@ -21800,7 +22034,7 @@ declare function patchChartData(element: ChartPptxElement, patch: Partial<PptxCh
21800
22034
  * @module angular-viewer/chart-editor-styles
21801
22035
  */
21802
22036
  /** Shared styles for all chart-editor control components. */
21803
- declare const CHART_EDITOR_STYLES = "\n\t.pptx-chart-card {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.35rem;\n\t\tpadding: 0.5rem 0;\n\t\tborder-top: 1px solid var(--pptx-inspector-border, #333);\n\t}\n\n\t.pptx-chart-card__heading {\n\t\tfont-size: 10px;\n\t\tfont-weight: 600;\n\t\ttext-transform: uppercase;\n\t\tletter-spacing: 0.05em;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t\tmargin: 0;\n\t}\n\n\t.pptx-chart-card__group {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.3rem;\n\t}\n\n\t.pptx-chart-card__group--indent {\n\t\tmargin-left: 0.5rem;\n\t}\n\n\t.pptx-chart-card__subhead {\n\t\tfont-size: 11px;\n\t\tfont-weight: 600;\n\t}\n\n\t.pptx-chart-card__row {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 0.4rem;\n\t\tfont-size: 11px;\n\t}\n\n\t.pptx-chart-card__label {\n\t\tflex: 0 0 auto;\n\t\twidth: 5rem;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t}\n\n\t.pptx-chart-card__label--wide {\n\t\twidth: 6.5rem;\n\t}\n\n\t.pptx-chart-card__name {\n\t\tflex: 1 1 auto;\n\t\tmin-width: 0;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t\twhite-space: nowrap;\n\t}\n\n\t.pptx-chart-card__check {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 0.35rem;\n\t\tfont-size: 11px;\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__input {\n\t\tflex: 1 1 auto;\n\t\tmin-width: 0;\n\t\tbox-sizing: border-box;\n\t\tpadding: 2px 4px;\n\t\tfont-size: 11px;\n\t\tbackground: var(--pptx-inspector-input-bg, #2d2d2d);\n\t\tborder: 1px solid var(--pptx-inspector-border, #444);\n\t\tborder-radius: 3px;\n\t\tcolor: inherit;\n\t\toutline: none;\n\t}\n\n\t.pptx-chart-card__input--num {\n\t\tflex: 0 0 auto;\n\t\twidth: 4rem;\n\t\ttext-align: right;\n\t}\n\n\t.pptx-chart-card__input:focus {\n\t\tborder-color: var(--pptx-inspector-active, #0078d4);\n\t}\n\n\t.pptx-chart-card__input:disabled {\n\t\topacity: 0.6;\n\t\tcursor: not-allowed;\n\t}\n\n\t.pptx-chart-card__color {\n\t\tflex: 0 0 auto;\n\t\twidth: 26px;\n\t\theight: 20px;\n\t\tpadding: 0;\n\t\tborder: 1px solid var(--pptx-inspector-border, #444);\n\t\tborder-radius: 3px;\n\t\tbackground: transparent;\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__color:disabled {\n\t\topacity: 0.6;\n\t\tcursor: not-allowed;\n\t}\n\n\t.pptx-chart-card__clear {\n\t\tflex: 0 0 auto;\n\t\tpadding: 0 2px;\n\t\tfont-size: 12px;\n\t\tline-height: 1;\n\t\tbackground: none;\n\t\tborder: none;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__clear:hover {\n\t\tcolor: var(--pptx-inspector-danger, #f47c7c);\n\t}\n\n\t.pptx-chart-card__input--num::-webkit-outer-spin-button,\n\t.pptx-chart-card__input--num::-webkit-inner-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n";
22037
+ declare const CHART_EDITOR_STYLES = "\n\t.pptx-chart-card {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.35rem;\n\t\tpadding: 0.5rem 0;\n\t\tborder-top: 1px solid var(--pptx-inspector-border, #333);\n\t}\n\n\t.pptx-chart-card__heading {\n\t\tfont-size: 10px;\n\t\tfont-weight: 600;\n\t\ttext-transform: uppercase;\n\t\tletter-spacing: 0.05em;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t\tmargin: 0;\n\t}\n\n\t.pptx-chart-card__group {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.3rem;\n\t}\n\n\t.pptx-chart-card__group--indent {\n\t\tmargin-left: 0.5rem;\n\t}\n\n\t.pptx-chart-card__subhead {\n\t\tfont-size: 11px;\n\t\tfont-weight: 600;\n\t}\n\n\t.pptx-chart-card__row {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 0.4rem;\n\t\tfont-size: 11px;\n\t}\n\n\t.pptx-chart-card__label {\n\t\tflex: 0 0 auto;\n\t\twidth: 5rem;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t}\n\n\t.pptx-chart-card__label--wide {\n\t\twidth: 6.5rem;\n\t}\n\n\t.pptx-chart-card__name {\n\t\tflex: 1 1 auto;\n\t\tmin-width: 0;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t\twhite-space: nowrap;\n\t}\n\n\t.pptx-chart-card__check {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 0.35rem;\n\t\tfont-size: 11px;\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__input {\n\t\tflex: 1 1 auto;\n\t\tmin-width: 0;\n\t\tbox-sizing: border-box;\n\t\tpadding: 2px 4px;\n\t\tfont-size: 11px;\n\t\tbackground: var(--pptx-inspector-input-bg, #2d2d2d);\n\t\tborder: 1px solid var(--pptx-inspector-border, #444);\n\t\tborder-radius: 3px;\n\t\tcolor: inherit;\n\t\toutline: none;\n\t}\n\n\t.pptx-chart-card__input--num {\n\t\tflex: 0 0 auto;\n\t\twidth: 4rem;\n\t\ttext-align: right;\n\t}\n\n\t.pptx-chart-card__input:focus {\n\t\tborder-color: var(--pptx-inspector-active, #0078d4);\n\t}\n\n\t.pptx-chart-card__input:disabled {\n\t\topacity: 0.6;\n\t\tcursor: not-allowed;\n\t}\n\n\t.pptx-chart-card__color {\n\t\tflex: 0 0 auto;\n\t\twidth: 26px;\n\t\theight: 20px;\n\t\tpadding: 0;\n\t\tborder: 1px solid var(--pptx-inspector-border, #444);\n\t\tborder-radius: 3px;\n\t\tbackground: transparent;\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__color:disabled {\n\t\topacity: 0.6;\n\t\tcursor: not-allowed;\n\t}\n\n\t.pptx-chart-card__clear {\n\t\tflex: 0 0 auto;\n\t\tpadding: 0 2px;\n\t\tfont-size: 12px;\n\t\tline-height: 1;\n\t\tbackground: none;\n\t\tborder: none;\n\t\tcolor: var(--pptx-inspector-muted, #888);\n\t\tcursor: pointer;\n\t}\n\n\t.pptx-chart-card__clear:hover {\n\t\tcolor: var(--pptx-inspector-danger, #f47c7c);\n\t}\n\n\t.pptx-chart-card__input--num::-webkit-outer-spin-button,\n\t.pptx-chart-card__input--num::-webkit-inner-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n\n\t/*\n\t * Touch target: matches MIN_TOUCH_TARGET_PX (44) from\n\t * pptx-viewer-shared's render/responsive module. This stylesheet backs\n\t * every chart editor card (Display, Axis, Data Labels, Markers,\n\t * Trendline, Error Bars, ...), so fixing it once here reaches all of\n\t * them instead of each card sizing its own controls.\n\t */\n\t@media (max-width: 767px) {\n\t\t.pptx-chart-card__input {\n\t\t\tmin-height: 44px;\n\t\t}\n\t\t.pptx-chart-card__clear {\n\t\t\tmin-width: 44px;\n\t\t\tmin-height: 44px;\n\t\t}\n\t\t/* chart-user-shape-options.component.html's \"Add text box\" button\n\t\t carries no class of its own. */\n\t\t[data-testid='chart-user-shape-add'] {\n\t\t\tmin-height: 44px;\n\t\t}\n\t}\n";
21804
22038
 
21805
22039
  /**
21806
22040
  * chart-event-helpers.ts: Small typed DOM-event readers shared by the chart