npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pptx-vanilla-viewer

v0.6.0

Published

Zero-framework PowerPoint viewer: render PPTX slides in the browser with plain DOM, no React/Vue/Angular required.

Downloads

1,287

Readme

pptx-vanilla-viewer

npm version license

Show, edit, and present Microsoft PowerPoint (.pptx) files directly in the browser with zero framework: no React, Vue, or Angular required, no server, no conversion step, no PowerPoint install. Call one factory function, createPptxViewer(container, options), and slides render as real HTML and CSS.

PowerPoint editor UI rendered in the browser

The rendering is done by the framework-agnostic pptx-viewer-core engine, which turns a .pptx file into a structured slide model. This package is the plain-DOM layer that draws that model on screen, and the engine is bundled in, so you install just one package.

▶️ Try the live demo · 📦 npm · 📖 Full docs · 🧩 Core SDK

Install

npm install pptx-vanilla-viewer jszip fast-xml-parser

Usage

import { createPptxViewer } from 'pptx-vanilla-viewer';

const viewer = createPptxViewer(document.getElementById('host')!, {
	source: '/decks/quarterly.pptx', // URL, ArrayBuffer, Uint8Array, Blob, or File
	theme: { colors: { primary: '#e34f26' } },
	locale: 'en',
	initialSlide: 0,
	editable: true, // select, drag, resize, rotate, inline text, undo/redo, save
	showToolbar: true,
	showThumbnails: true,
	onLoad: ({ slideCount }) => console.log(`${slideCount} slides`),
	onSlideChange: (index) => console.log('slide', index + 1),
	onError: (message) => console.error(message),
	onDirtyChange: (dirty) => console.log('unsaved edits:', dirty),
});

// Navigation / zoom
viewer.next();
viewer.prev();
viewer.goToSlide(3);
viewer.setZoom(1.5); // or 'fit'
viewer.zoomToFit();

// Presentation mode (real Fullscreen API; Esc exits)
await viewer.enterPresentation();

// Editing (click/drag/resize/rotate/double-click-to-edit-text happen via the
// DOM; these are the programmatic entry points)
viewer.undo();
viewer.redo();
viewer.deleteSelected();
const bytes = await viewer.save(); // serialise the edited deck to .pptx bytes
await viewer.downloadPptx('quarterly-edited.pptx'); // save() + trigger a download

// Load a different file later
await viewer.loadFile(fileInput.files![0]);
await viewer.loadUrl('/other-deck.pptx');

// Escape hatch: the live pptx-viewer-core handler (save, markdown, archive access)
const handler = viewer.getHandler();

// Tear down DOM, listeners, Blob URLs, and the core handler
viewer.destroy();

The container should have a size (the viewer fills it: width/height: 100%).

Keyboard

Navigation: arrow keys / PageUp / PageDown / Space, Home/End jump to the first or last slide, Esc exits presentation mode. The viewer root is focusable (tabindex="0").

When editable is on and an element is selected: Ctrl/Cmd+Z undoes, Ctrl/Cmd+Shift+Z (or Ctrl+Y) redoes, Delete/Backspace deletes the selection, Ctrl/Cmd+D duplicates it, arrow keys nudge it by 1px (Shift+arrow for 10px), and Escape deselects. Double-click a text-capable element to edit its text inline.

Styling and theming

Styles are injected once per document as a <style id="pptx-vanilla-viewer-styles"> tag, scoped under the .pptxv root class. CSP-strict hosts can import the packaged static stylesheet with import 'pptx-vanilla-viewer/styles.css'. getViewerCss() remains available when the host needs the stylesheet text.

All chrome colors come from the shared --pptx-* CSS custom properties. Pass a ViewerTheme (theme option or setTheme) to override them; the vermilionLightTheme / vermilionDarkTheme presets are re-exported.

Editing

Pass editable: true (or call setEditable(true) at runtime) to turn on:

  • Click to select an element, click empty space to deselect.
  • Drag to move, with snap-to-sibling-edge guides.
  • Resize via 8 handles (Shift locks aspect ratio on the corner handles) and rotate via a rotate handle (Shift snaps to angle increments).
  • Double-click a text-capable element for inline text editing.
  • Undo/redo (100-entry history), delete, and duplicate (Ctrl/Cmd+D).
  • Insert, format, z-order, group, and ungroup elements from the ribbon.
  • Edit inherited master/layout elements by enabling template editing in the View ribbon or calling setEditTemplateMode(true).
  • Rich speaker notes, accessibility checks, autosave, and collaboration.
  • The toolbar's Save button (shown only when editable), which calls downloadPptx() to serialise and download the edited .pptx.

For CSP-strict hosts, import pptx-vanilla-viewer/styles.css instead of using automatic style injection.

Use viewer.getSelectedElementId() and the onSelectionChange / onDirtyChange callbacks to build your own chrome around the selection state.

i18n

All UI strings go through the shared pptx.* dictionary (English built in). Provide messages: { de: { 'pptx.presenter.nextSlide': 'Nächste Folie', ... } } plus locale: 'de' (or call setLocale) for other languages; missing keys fall back to English, then to a humanised label.

Element coverage

Dedicated renderers ship for every element type: text, shape, image/picture, group, connector, table, chart, SmartArt (2D and opt-in 3D), media (video/audio), ink, OLE, content parts, zoom links, and 3D models. Renderers are dispatched through an open registry, so any of them can be overridden without forking:

import { createPptxViewer, type ElementRenderer } from 'pptx-vanilla-viewer';

const renderTable: ElementRenderer = (element, zIndex, context) => {
	/* build and return a DOM node */
};

const viewer = createPptxViewer(host, { source });
viewer.getRegistry().register('table', renderTable);

See src/viewer/render/elements/README.md for the full renderer contract.

License

Apache-2.0. See LICENSE and NOTICE.