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

ruviz

v0.14.2

Published

Browser-first JS/TS SDK for ruviz WebAssembly rendering

Readme

ruviz

ruviz is the published browser-first JS/TS SDK for the ruviz plotting runtime.

It wraps the raw wasm-bindgen bridge in the Rust crate ruviz-web with a higher-level API for static export, interactive canvas sessions, worker-backed rendering, and reactive demos.

Install

npm install ruviz

The package ships as ESM. Browser apps should use a bundler or runtime that can load WebAssembly and module workers from package-relative import.meta.url references.

The public package entrypoints are:

import { createPlot, createWorkerSession } from "ruviz";
import initRaw, { JsPlot } from "ruviz/raw";

await initRaw();
const rawPlot = new JsPlot();

Quick Start

import { createPlot } from "ruviz";

const plot = createPlot()
  .line({ x: [0, 1, 2, 3], y: [0, 1, 4, 9] })
  .title("Quadratic")
  .setXLabel("x")
  .setYLabel("y = x^2");

await plot.save({ format: "png", fileName: "quadratic.png" });

Interactive Canvas Sessions

Mount a plot into a normal HTML canvas:

import { createCanvasSession, createPlot } from "ruviz";

const canvas = document.querySelector("canvas")!;
const session = await createCanvasSession(canvas);
await session.setPlot(
  createPlot().line({ x: [0, 1, 2], y: [0, 1, 0] }).title("Interactive Plot"),
);
session.render();

Use createWorkerSession(...) when you want OffscreenCanvas worker rendering:

import { createPlot, createWorkerSession } from "ruviz";

const canvas = document.querySelector("canvas")!;
const session = await createWorkerSession(canvas, {
  backendPreference: "auto",
  fallbackToMainThread: true,
});
await session.setPlot(createPlot().scatter({ x: [0, 1, 2], y: [2, 1, 3] }));
session.render();

When Worker, OffscreenCanvas, or transferControlToOffscreen() is missing, createWorkerSession() returns a WorkerSession in mode === "main-thread" by default. Pass { fallbackToMainThread: false } to throw instead.

Both createCanvasSession() and createWorkerSession() default to autoResize: true and bindInput: true, so pointer, wheel, and resize events are wired automatically unless you disable them.

WebGPU 3D

Create and mount a 3D plot in one fluent expression:

import { surface } from "ruviz";

const canvas = document.querySelector("canvas")!;
const session = await surface(
  [-1, 0, 1],
  [-1, 0, 1],
  [
    [2, 1, 2],
    [1, 0, 1],
    [2, 1, 2],
  ],
)
  .title("z = x² + y²")
  .mount(canvas);

// Optional: the session already renders after mount, input, and resize.
session.render();

Use .axisAspect(1, 2, 1).stableScale() for a fixed X:Y:Z plotting box that keeps its framing while rotating. Use .equalScale().stableScale() when equal data units must have equal lengths, such as physical geometry. Fixed box ratios and equal data units differ when axis ranges differ. Stable scale reserves room for every orientation; explicit zoom and resize still change the view.

The top-level scatter3d(x, y, z), line3d(x, y, z), surface(x, y, z), and wireframe(x, y, z) factories accept arrays or typed arrays. createPlot3d() exposes the same series methods on a discoverable builder. Surface grids may be a flat row-major array or one row per y value as above. Mounting an HTMLCanvasElement binds input and resize handling automatically. Series methods append, matching Rust: surface(...).wireframe(...) keeps both. For replacement, call builder.clearSeries().surface(...). Existing mounted sessions keep their own scene when the builder changes.

Pass onError: (error) => ... to mount() to handle scheduled rendering and browser-input failures. session.error retains the last failure and clears after a successful frame. Call session.render() to retry a transient failure; if session.needsRecreate() is true, call dispose() and mount a fresh session. Failures preserve the last presented frame where the browser surface remains available. Initial mounting failures reject the mount() promise. Without an error callback, scheduled failures are logged to the console.

The same builder works inside a worker after the main thread transfers its canvas:

import { createPlot3d } from "ruviz";

declare const offscreenCanvas: OffscreenCanvas;
declare const devicePixelRatioFromMainThread: number;

const x = [0, 1, 2];
const y = [0, 1, 0];
const z = [1, 2, 3];

const session = await createPlot3d()
  .scatter3d(x, y, z)
  .mount(offscreenCanvas, { scaleFactor: devicePixelRatioFromMainThread });

Worker code forwards input and resize messages through the session's camel-cased methods such as pointerMove(...), wheel(...), and resize(...). Rendering requests are coalesced to one submission per animation frame.

Plot Types

The fluent builder currently supports:

  • line({ x, y }) and scatter({ x, y })
  • bar({ categories, values, style: { orientation: "horizontal" } }) (orientation is optional; "vertical" is the default)
  • histogram(values) and boxplot(values) (box plots accept the same optional style.orientation bars do)
  • heatmap(rows) where rows is a rectangular number[][]
  • errorBars({ x, y, yErrors })
  • errorBarsXY({ x, y, xErrors, yErrors })
  • kde(values) and ecdf(values)
  • contour({ x, y, z }) where z.length === x.length * y.length
  • pie(values, labels?)
  • radar({ labels, series })
  • violin(values)
  • polarLine({ r, theta })

number[], Float64Array, and other ArrayLike<number> values are accepted for numeric inputs. createObservable(...) can drive line, scatter, bar, histogram, boxplot, and error-bar inputs. createSineSignal(...) can be used as the y input for line and scatter plots.

Reactive Helpers

The package also exports:

  • createObservable(...) for mutable numeric series
  • createSineSignal(...) for time-varying demo inputs
  • createPlotFromSnapshot(...) for rehydrating plot.toSnapshot() output
  • getRuntimeCapabilities() for browser capability checks
  • registerFont(...) for custom browser text faces

Which Package Should You Use?

  • Use npm ruviz for browser apps in JS/TS.
  • Use the Rust crate ruviz-web if you need the raw wasm bridge.
  • Use the root Rust crate ruviz for native Rust plotting.

Docs and Examples

Local Development

From the repository root:

bun install
bun run --cwd packages/ruviz build:js
bun run --cwd packages/ruviz build
bun run --cwd packages/ruviz docs:dev

build:js runs the TypeScript build against existing generated wasm bindings. build also rebuilds the wasm package before compiling TypeScript.

Session cleanup

Use detach() on a 2D CanvasSession or WorkerSession to clear its plot while keeping input and resize bindings. Call setPlot(...) to attach another plot. Use dispose() when removing the session from your application; it removes bindings and terminates a worker. Dispose a 3D session before mounting a replacement.

destroy() remains a compatibility alias: it means detach() for 2D and dispose() for 3D. New code should use the explicit names above.