← All formats

PPTX

Render .pptx decks to Canvas, your way.

Every demo below is the real library rendering a sample PowerPoint deck (.pptx) live in your browser — and the exact code that produces it. The same patterns power the Storybook stories.

Story · Demo

Single viewer with navigation

Hand PptxViewer a canvas and it manages parsing, rendering and the current slide. Step through with the built-in nextSlide() / prevSlide().

sample-1.pptx live · WASM
import { PptxViewer } from '@silurus/ooxml/pptx';

// The built-in viewer tracks the current slide for you.
const viewer = new PptxViewer(canvas, { width: 960, useGoogleFonts: true });
await viewer.load('/sample.pptx');

nextBtn.addEventListener('click', () => viewer.nextSlide());
prevBtn.addEventListener('click', () => viewer.prevSlide());

Story · ScrollView

Scroll through every slide

Drive the headless PptxPresentation engine to render each slide into its own canvas, stacked in a scroll container — no built-in viewer required.

sample-1.pptx live · WASM
import { PptxPresentation } from '@silurus/ooxml/pptx';

// Headless engine — render every slide into a canvas you control.
const doc = await PptxPresentation.load('/sample.pptx');

for (let i = 0; i < doc.slideCount; i++) {
  const canvas = document.createElement('canvas');
  scroller.appendChild(canvas);
  await doc.renderSlide(canvas, i, { width: 1100 });
}

Story · ThumbnailGrid

Thumbnail overview

The same engine renders slides at any size. Drop them into a grid at thumbnail width and wire up click handlers for navigation.

sample-1.pptx live · WASM
import { PptxPresentation } from '@silurus/ooxml/pptx';

// Render each slide small, wire up navigation.
const doc = await PptxPresentation.load('/sample.pptx');

for (let i = 0; i < doc.slideCount; i++) {
  const thumb = document.createElement('canvas');
  thumb.addEventListener('click', () => open(i));
  grid.appendChild(thumb);
  await doc.renderSlide(thumb, i, { width: 320 });
}

Story · MasterDetail

Thumbnail rail + large preview

Combine both: a PptxPresentation for the thumbnail rail and a PptxViewer for the detail pane. Click a thumbnail to jump the preview with goToSlide().

sample-1.pptx live · WASM
import { PptxPresentation, PptxViewer } from '@silurus/ooxml/pptx';

// A large preview viewer on the right…
const viewer = new PptxViewer(detailCanvas, { width: 960, enableTextSelection: true });

// …and a thumbnail rail on the left, sharing the same file.
const [doc] = await Promise.all([
  PptxPresentation.load('/sample.pptx'),
  viewer.load('/sample.pptx'),
]);

for (let i = 0; i < doc.slideCount; i++) {
  const thumb = document.createElement('canvas');
  thumb.addEventListener('click', () => viewer.goToSlide(i));  // jump the preview
  rail.appendChild(thumb);
  await doc.renderSlide(thumb, i, { width: 200 });
}

In your framework

Mount it in a canvas

The viewer is a plain TypeScript class — no framework runtime, no peer deps. Create it on mount, call load(), and let it go on unmount.

import { useEffect, useRef } from 'react';
import { PptxViewer } from '@silurus/ooxml/pptx';

export function Viewer({ src }: { src: string }) {
  const ref = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const viewer = new PptxViewer(canvas, { width: 960 });
    void viewer.load(src);
    return () => viewer.destroy();
  }, [src]);

  return <canvas ref={ref} />;
}

API reference

Options & methods

Every public option and method, straight from the source. Types omitted for brevity are exported from the package — your editor will autocomplete the rest.

PptxViewer

Opinionated single-canvas viewer. Hand it a <canvas>; it owns parsing, rendering and the current slide.

new PptxViewer(canvas: HTMLCanvasElement, options?: PptxViewerOptions)

Options

OptionTypeDefaultDescription
width number 960 Canvas CSS width in px; height is derived from the slide aspect ratio.
dpr number devicePixelRatio Device pixel ratio for the backing store (crispness on HiDPI).
useGoogleFonts boolean false Load metric-compatible webfonts from Google Fonts so layout matches Office without the fonts installed. Off by default for privacy.
enableTextSelection boolean false Overlay a transparent text layer so users can select & copy slide text.
enableMediaPlayback boolean false Make embedded audio/video interactive (the viewer draws its own play chrome).
maxZipEntryBytes number 512 MiB Per-entry ZIP decompression cap (zip-bomb guard). Lower it for untrusted input.
math MathRenderer undefined Opt-in OMML equation engine (MathJax + STIX Two Math, ~3 MB). Import it from the separate @silurus/ooxml/math entry — `import { math } from "@silurus/ooxml/math"` — and pass it to render equations. Omit it and equations are skipped — the engine tree-shakes away entirely.
onSlideChange (index: number, total: number) => void Called after a slide finishes rendering.
onError (err: Error) => void Called on parse or render errors.

Methods

load(source: string | ArrayBuffer): Promise<void> Load from a URL or ArrayBuffer and render the first slide.
goToSlide(index: number): Promise<void> Render a specific slide (0-indexed, clamped).
nextSlide(): Promise<void> Advance one slide.
prevSlide(): Promise<void> Go back one slide.
get slideIndex(): number Current slide index.
get slideCount(): number Total slides (0 until loaded).
get canvasElement(): HTMLCanvasElement The underlying canvas.
destroy(): void Tear down the worker and release resources.

PptxPresentation

Headless engine — parse once, render any slide into any canvas you supply (scroll views, thumbnail grids, master–detail).

await PptxPresentation.load(source, options?)

Options

OptionTypeDefaultDescription
useGoogleFonts boolean false Load metric-compatible webfonts from Google Fonts so layout matches Office without the fonts installed. Off by default for privacy.
maxZipEntryBytes number 512 MiB Per-entry ZIP decompression cap (zip-bomb guard). Lower it for untrusted input.

Methods

static load(source, options?): Promise<PptxPresentation> Parse a deck from a URL or ArrayBuffer.
get slideCount(): number Total slides.
renderSlide(canvas, index, opts?: { width?, dpr?, math? }): Promise<void> Render one slide into the given canvas at the given width. Pass `math` (from `@silurus/ooxml/math`) to render OMML equations; omit it and equations are skipped.
destroy(): void Release the worker.