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

bento-layout

v0.2.0

Published

Lightweight CSS flexbox, grid, and block layout engine in plain TypeScript — no WASM, no dependencies

Readme

bento-layout

A flexbox, CSS Grid, and block layout engine in plain TypeScript. Style data goes in, pixel positions come out — and that is the whole transaction. No WASM binary to load, no async initialization, no engine instance to register nodes with, no free() or destroy() to remember: nodes are ordinary JavaScript objects with ordinary lifetimes, and an unreferenced subtree is just garbage collected. Zero runtime dependencies.

import { LayoutNode, computeLayout } from 'bento-layout';

const left = LayoutNode.make({ flexGrow: 1 });
const right = LayoutNode.make({ flexGrow: 1 });
const root = LayoutNode.make({ width: 400, height: 300 }, [left, right]);

computeLayout(root, { width: 'max-content', height: 'max-content' });

left.layout.size; // { width: 200, height: 300 }
right.layout.location; // { x: 200, y: 0 }

That is the entire setup, and it runs the same in Node, a browser, a worker, or an edge runtime. The engine computes geometry, full stop — it does not paint, own a DOM, or parse CSS strings — which makes it the layout half of a canvas renderer, a terminal UI, a PDF generator, or an SVG diagram, without dragging in the rest of a browser.

Why

If you want spec-grade flexbox and CSS Grid in a JavaScript project today, your options each carry a tax. Yoga is the battle-tested standard, but every published release is flexbox-only (Grid is an open, unmerged PR: facebook/yoga#1865), and the npm package is C++-compiled WASM behind an async loader. The Rust engines have excellent flexbox, grid, and block algorithms, but using one from JS means a WASM build and a binding layer with manual lifetime bookkeeping. Hand-rolled layout math is a slow leak: every alignment mode and percentage edge case is another divergence from CSS-trained intuition.

bento-layout fills the gap those leave: one plain-TypeScript package where flexbox, grid, and block all work, verified against a browser, that installs and runs with the ceremony of lodash. Those engines remain better choices when their strengths are your constraints — React Native, or Rust. This is the choice for when you are writing TypeScript and want layout to be a small, boring dependency.

What it computes

  • Flexbox, CSS Grid, and block layout (with CSS 2.2 margin collapsing), composing freely in one tree — a grid inside a flex row inside a block page is the normal case.
  • The full box model: min/max constraints, aspect ratios, percentages, auto margins, absolute positioning, RTL, both box-sizing modes, gaps, alignment including the safe variants, and scrollbar gutters.
  • Content-driven sizing: leaf nodes take a measure callback, so text and images report their own size.
  • Browser-faithful rounding: results snap to whole pixels the way browsers round — cumulatively, so adjacent boxes never gap or overlap — or stay unrounded, your choice.

Styles are structured data (16, '50%', { fr: 1 }), not CSS strings, in flat camelCase properties with the same spelling as element.style. Uniform shorthands (padding: 16, gap: { column: 8 }) expand in cascade order. Styles change through setStyle (a per-property merge), structure through appendChild / insertChild / removeChild. A removed subtree is a live tree of its own: lay it out, re-attach it, or drop it and let the GC take it.

Conformance: Chrome is the oracle

Correctness is defined as agreement with a pinned Chrome:

  • 5,304 conformance fixtures — geometry extracted from headless Chrome by an in-repo pipeline (pnpm gentest) and asserted at 0.1px tolerance, each in four variants (both box-sizing modes × LTR and RTL). pnpm test replays them browserless, in seconds.
  • A differential fuzzer (pnpm fuzz) generates random trees, compares the engine against Chrome, shrinks every disagreement to a minimal reproduction, and commits findings as permanent regression fixtures.
  • A WPT scoreboard imports a spec-organized subset of web-platform-tests (css-flexbox, css-grid, css-sizing, css-align) through the same pipeline, with failures quarantined in the open rather than dropped from the denominator.
  • Zero silent divergence: any engine-vs-Chrome disagreement is either fixed or documented with a spec citation in KNOWN_DIVERGENCES.md — currently one class-level entry (cyclic percentage resolution) and no fixture-level ones.

Documentation

The full documentation — a getting-started tutorial, guides for measuring content, grid, and renderer integration, a complete style-property reference, and the conformance story — lives in the docs site (cd docs && pnpm dev), with live, editable demos running the real engine.

Non-goals

  • Rendering, styling cascade, or a DOM — the engine computes geometry from resolved style data.
  • CSS string parsing — styles are structured data; the docs playground owns the CSS-ish syntax instead.
  • Beating native performance — parity with native code is not the target; BENCHMARKS.md keeps honest numbers and their limits.
  • The full CSS layout surface — floats, inline layout, calc(), named grid lines/areas, and subgrid are out of scope, so that what is claimed is browser-verified rather than approximate.
  • Matching another engine's API — the API is designed for TypeScript idioms (GC lifetimes, structural types, per-property merge), not for symmetry with any existing engine.

Acknowledgements

Thanks to Taffy (MIT), a major reference while this engine was being built.

License

MIT