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

@vysmo/flipbook

v0.2.0

Published

WebGL flipbook driven by the @vysmo/transitions page-curl mesh shader. Click halves, keyboard nav, drag corners to scrub mid-flip. Drop-in component or headless API.

Readme

@vysmo/flipbook

WebGL flipbook driven by the @vysmo/transitions page-curl mesh shader. Click halves, keyboard nav, drag corners to scrub mid-flip — the page-curl shader's progress follows your pointer, release past 50% to commit the flip, less to revert. Drop-in component or headless API.

Live demo + playground · Source

Install

pnpm add @vysmo/flipbook @vysmo/transitions @vysmo/animations @vysmo/easings

(Peers ship separately so you can pin them per-project. They're transitive deps; npm install @vysmo/flipbook pulls them in automatically — just add to your own package.json if you want explicit version control.)

Quick start

import { createFlipbook } from "@vysmo/flipbook";

const flip = createFlipbook({
  container: document.querySelector("#book")!,
  pages: [
    "/p1.jpg",
    "/p2.jpg",
    "/p3.jpg",
    "/p4.jpg",
  ],
  axis: "horizontal", // or "vertical"
  loop: true,
});

// Click halves / drag corners / arrow keys are all wired by default.
flip.next();
flip.prev();
flip.goTo(2);

Lazy mode for long books

createFlipbook eagerly decodes every page by default. For books with many pages, set lazy: true and only the current page + preloadWindow neighbours on each side are loaded onto the GPU at a time. The runner's LRU evicts URL textures outside the window automatically.

import { createFlipbook } from "@vysmo/flipbook";

// Any length — only ~3 textures held on the GPU at a time.
const pages = Array.from({ length: 80 }, (_, i) => `/pages/${i}.jpg`);

createFlipbook({
  container: document.querySelector("#book")!,
  pages,
  lazy: true,
  preloadWindow: 1,         // current + N each side; default 1
});

DOM-source pages (HTMLImageElement, HTMLCanvasElement) mixed in a lazy pages array are always considered loaded — they're in memory by definition. Only URL strings go through the lazy load path.

For Next.js — pass next/image optimizer URLs straight into pages. See the Vysmo + Next.js guide.

Pages

pages accepts:

  • Image URLs (string)
  • HTMLImageElement (already-loaded)
  • HTMLCanvasElement / OffscreenCanvas
  • HTMLVideoElement
  • Any other TextureSource (per @vysmo/transitions)

The flipbook resolves URL strings into images for you and uploads each page to the GPU via TextureCache.

Drag-scrub

The signature feature: when you drag a corner of the book mid-flip, the page-curl shader's progress follows your pointer in real time. Release past 50% to commit; less to revert with a spring tween back to the previous page. This is what differentiates the component from a CSS-only flipbook — there's no equivalent without the shader.

Disable with enableDrag: false if you only want click + keyboard navigation.

Options

// @no-check
type FlipbookOptions = {
  container: HTMLElement;
  pages: PageSource[];
  axis?: "horizontal" | "vertical";   // default "horizontal"
  loop?: boolean;                     // wrap last → first
  duration?: number;                  // ms per flip (default 900)
  ease?: EasingFn;                    // default cubicInOut
  radius?: number;                    // page-curl radius (default 0.35)
  tilt?: number;                      // page-curl tilt (default 0.12)
  backColor?: [number, number, number]; // back-of-page tint (default warm white)
  enableDrag?: boolean;               // default true
  dragCommit?: number;                // 0..1 — release threshold (default 0.5)
  enableKeyboard?: boolean;           // default true
  autoplay?: boolean | number;        // true → 4s; number → custom ms
  // ... and a few more
};

Events

flip.on("change", (current, previous) => /* … */);
flip.on("flipstart", (from, to) => /* … */);
flip.on("flipend", (from, to) => /* … */);

Disposal

flip.dispose(); // releases GPU resources, removes listeners

Characteristics

  • DOM-only. Requires HTMLCanvasElement and pointer / keyboard events.
  • WebGL2 only (transitive — driven by @vysmo/transitions).
  • SSR-safe at module load. Module imports cleanly in Node; constructing requires a live DOM.
  • Bundle: ~3 KB gzipped (peers external).

License

MIT.