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

@hexane/plotlib

v0.2.0

Published

A React component library for building interactive scientific figures.

Readme

plotlib

A React component library for building interactive scientific figures. Plots are rendered as SVG, layout is solved by a Cassowary constraint engine, and interactivity (zoom, pan) is driven by Jotai atoms — giving a declarative, composable API that fits naturally into any React application.

Features

  • Declarative figure API — define axes once on <Figure>, reference them by name across any number of <Plot> panels; the layout engine keeps them aligned automatically
  • Constraint-based layout — panel sizing uses a Cassowary solver (@lume/kiwi), supporting proportional sizes, shared axis dimensions, and flexible multi-panel grids
  • Interactive zoom & pan — scroll to zoom, drag to pan, with configurable zoom extent, translate extent, and optional fixed aspect ratio
  • Composable marksPlotLine renders line series inside a Plot.Clip region; more mark types planned
  • Color scaleslinear and log scales support numeric→color mapping via d3-interpolate piecewise interpolation
  • Scalebar — auto-ranging physical scale bar with SI prefix selection, zoom-aware
  • Theming — lightweight CSS-module-backed theme system; components accept style override props

Installation

npm install plotlib

Peer dependencies — install these alongside plotlib if not already present:

npm install react react-dom jotai

Then import the default stylesheet once in your application:

import 'plotlib/styles.css';

Quick Start

import React from 'react';
import { Figure, Plot, PlotLine, layout } from 'plotlib';
import type { AxisSpec } from 'plotlib';
import 'plotlib/styles.css';

const axes = new Map<string, AxisSpec>([
    ['x', { domain: [0, 10], size: '400px' }],
    ['y', { domain: [0, 4], size: '200px' }],
]);

const xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ys = xs.map(Math.sqrt);

export function MyFigure() {
    return (
        <Figure axes={axes} width="600px">
            <Plot xaxis="x" yaxis="y" zoom>
                <Plot.Clip>
                    <PlotLine xs={xs} ys={ys} />
                </Plot.Clip>
            </Plot>
        </Figure>
    );
}

Multi-Panel Figures

Axes declared on <Figure> are shared across panels by name. Placing two <Plot> components with the same xaxis key aligns them horizontally and links their zoom state.

const axes = new Map<string, AxisSpec>([
    ['x',      { domain: [0, 10], size: '400px', show: 'one' }],
    ['signal', { domain: [-1, 1], size: '150px', show: 'one' }],
    ['error',  { domain: [0, 0.5], size: '150px', show: 'one' }],
]);

<Figure axes={axes} width="600px">
    <layout.FlexBox flexDirection="column" rowGap="8px">
        <Plot xaxis="x" yaxis="signal" zoom>
            <Plot.Clip><PlotLine xs={xs} ys={signal} /></Plot.Clip>
        </Plot>
        <Plot xaxis="x" yaxis="error" zoom>
            <Plot.Clip><PlotLine xs={xs} ys={error} /></Plot.Clip>
        </Plot>
    </layout.FlexBox>
</Figure>

show: 'one' suppresses duplicate axis labels when panels share an axis — only the outermost panel renders it.

Core Concepts

Axes

Each axis is declared as an AxisSpec in the axes map passed to <Figure>:

| Property | Type | Description | |---|---|---| | domain | [number, number] | Data range | | size | string \| number | CSS length or solver variable expression | | show | boolean \| 'one' | Whether to render the axis; 'one' shows it only on the first/last panel in a grid | | translateExtent | [number, number] \| boolean | Pan boundary; true clamps to domain | | label | string | Axis label text |

Scales

Standalone scale constructors are available for use outside the component tree:

import { linear, log } from 'plotlib/scale';

const s = linear([0, 100], [0, 500]);   // data → pixels
s.transform(50);                         // → 250
s.ticks(5);                              // → [0, 25, 50, 75, 100]

const color = linear([0, 1], ['blue', 'red']);
color.transform(0.5);                    // → interpolated color string

Layout

The layout export exposes the constraint-based layout primitives directly, for building custom compositions:

| Component | Purpose | |---|---| | layout.FlexBox | Flex-like arrangement of child plots | | layout.MarginBox | Adds fixed or proportional margins | | layout.Centered | Centers content within parent bounds | | layout.Decorated | Attaches decorations (axis, label) to any edge | | layout.Constrained | SVG root; feeds container size into the solver |

Development

# build the library
npm run build

# watch mode
npm run watch

# run tests
npm run test

The examples/simple_plots directory contains a Vite app that imports from the local build and is a convenient testbed during development.

Further Reading

  • ARCHITECTURE.md — component hierarchy, scale system, layout engine, zoom system, and context/atom graph
  • TODO.md — planned features and known cleanup items