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

vexy-stax-js

v3.1.11

Published

Browser renderer for the vexy-stax shared scene format: 3D glass plates in two views, with morphable opacity. Ships as ESM, Web Component, and a classic-script global.

Downloads

74

Readme

vexy-stax-js

Browser renderer for the vexy-stax shared scene format: a deck of layered PNG slides drawn as 3D glass plates in two views (expanded / compact) with morphable per-slide opacity. Built on three.js. Ships three ways — an ESM module, a <vexy-stax> Web Component, and a classic-script global.

Scene parser, view geometry (mirrors the Python package exactly), a working three.js stage (plates + floor + reflections + captions), and the three entry points. Render ops: a static view, image export (toImage), a playable transition, video export (toVideo, WebCodecs with a MediaRecorder fallback), and a scroll-driven scrollspy (IntersectionObserver + scroll, honouring prefers-reduced-motion).

Quick start

npm install
npm run dev          # vite dev server
npm run build        # -> dist/vexy-stax.element.js + dist/vexy-stax.global.js
npm run test:unit    # node --test (scene.js + geometry.js + transition/scrollspy math)
npm test             # unit + playwright E2E (mount, views, image/video, transition, scrollspy)

# HARD render gate: render compact + expanded stills of the airbl example in
# headless chromium and assert real pixel variance (not a blank canvas):
node verify/run.mjs && python3 verify/gate.py

Usage

Three ways to drop a deck on a page, easiest first (issues 341 / 342).

Web Component — just a list of slides

<script type="module" src="./dist/vexy-stax.element.js"></script>

<!-- The `slides` attribute: a space/newline-separated list of image URLs (local, data:, or
     remote http(s)). Captions off by default; mode="playable" plays the transition once. -->
<vexy-stax
  slides="layer-0.png layer-1.png https://example.com/layer-2.png"
  view="compact" mode="playable">
</vexy-stax>

<!-- …or point at a full scene JSON (with captions, camera, transition, …): -->
<vexy-stax scene="scene.json" view="expanded"></vexy-stax>

<!-- …or drop the WHOLE scene inline, right where you load the component (issue 701) —
     a `<script type="application/json">` child, no external URL: -->
<vexy-stax view="compact" mode="playable" aspect="3">
  <script type="application/json">
  { "version": 1, "transition": { "kind": "expand_collapse" },
    "slides": [ { "src": "https://example.com/layer-0.png" },
                { "src": "https://example.com/layer-1.png" } ] }
  </script>
</vexy-stax>

Click-to-toggle is on by default (issue 342): clicking anywhere inside a <vexy-stax> fluently toggles compact↔expanded. Opt out with click-toggle="false".

Scene-in-init (issue 342/701): supply an inline scene without a URL three ways — assign a JS object (el.scene = { version: 1, slides: [{ src: "a.png" }, …] } or the config property), a JSON-string config attribute, or a child <script type="application/json"> holding the whole scene (shown above; the no-escaping way to "specify the full scene right where you load the component"). Inline slide src paths resolve against the host page, so use absolute URLs when the images live elsewhere.

Aspect / size (issue 701): the aspect attribute shapes the box via CSS aspect-ratio so a deck is easy to make short and wide — aspect="3" (or "3/1", "3:1", "16:9") gives a 3:1 box; the camera reframes the deck to fit. width/height still set an explicit CSS size, and the scene's own size controls the internal plate aspect. createStax(el, { aspect: "3" }) is the ESM equivalent.

ES Module — createStax

import { createStax, makeScene, VexyStax, loadScene } from "vexy-stax-js";

// One call: build a scene from a URL list, mount, wait for ready.
const stax = await createStax("#stage", {
  slides: ["layer-0.png", "https://example.com/layer-1.png"],
  gap: 480, transition: "expand_collapse", mode: "playable",
});

await stax.toggleView();          // fluent compact↔expanded (the default click behavior)
const mp4 = await stax.toVideo(); // seekable mp4

// createStax also accepts an inline scene object (scene-in-init):
await createStax("#hero", { scene: { version: 1, slides: [{ src: "a.png" }] }, view: "expanded" });

// makeScene builds a valid scene from a bare URL list, filling sensible defaults:
const scene = makeScene(["a.png", "b.png", "c.png"], { gap: 480, transition: "expand_collapse" });
const low  = new VexyStax(container, scene); // the low-level path is still available

createStax(elOrSelector, opts)opts accepts { slides | scene, view, mode, trigger, width, height, aspect, clickToggle, baseUrl, …sceneOverrides }. Any remaining key (size, camera, gap, transition, background, captions, floor, edge, …) is forwarded to makeScene.

Global script — window.VexyStax

<script src="./dist/vexy-stax.global.js"></script>
<script>
  VexyStax.create("#stage", { slides: ["a.png", "b.png", "c.png"] });
</script>

CDN (no build step)

Every snippet above also works verbatim from the jsDelivr CDN — swap the local bundle path for:

<!-- Web Component / ESM -->
<script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vexy-stax.element.js"></script>
<!-- Global script -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vexy-stax.global.js"></script>

Remote slide images

Slide src may be a local path, a data: URI, or a remote http(s) URL. The texture loader requests cross-origin images with crossOrigin="anonymous", so a server that sends CORS headers lets the image load and keeps the canvas exportable (toImage / toVideo).

Live demos & how-to pages

npm run build:docs emits a docs site: a landing page, the Animated (playable.html) and Scrollspy (scrollable.html) demos, plus three side-by-side "how to use" pages — demo-component.html, demo-module.html, demo-library.html — each showing the minimal code beside the live result (modeled on i.vexy.art/dev/lines-nano).

Layout

src/
├── index.js       # ESM public API (VexyStax: setView/toImage/transition/toVideo/scrollspy)
├── element.js     # <vexy-stax> custom element (auto-registers; mode=static|playable|scrollspy)
├── global.js      # window.VexyStax IIFE entry
├── scene.js       # strict scene parser (mirrors vexy_stax/scene.py)
├── geometry.js    # view math (mirrors vexy_stax/geometry.py exactly) + frameStateAt
├── stage.js       # three.js plates + floor + reflections + captions + camera (two views)
├── transition.js  # rAF morph driver + timeline/progress math (pure, testable)
├── scrollspy.js   # scroll→progress mapping (IntersectionObserver; reduced-motion)
└── export.js      # canvas→PNG; WebCodecs/MediaRecorder video capture
src_docs/          # MaterialX docs pipeline → https://vexy.dev/vexy-stax-js/
├── mkdocs.yaml    #   build: vexy-mkdocs-tools build
└── md/            #   api.md · web-component.md · scene-format.md
tests/             # node --test (scene/geometry/transition/scrollspy) + playwright E2E
verify/            # HARD render gate: harness.html + run.mjs (chromium) + gate.py (PIL)

The numeric outputs of geometry.js match vexy-stax-py/src/vexy_stax/geometry.py for the same scene; both are tested against the same fixture vectors.

License

Apache-2.0 — Copyright 2026 Fontlab Ltd.