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

@casoon/opengrid

v0.13.0

Published

Accessible data grid, table and pivot as web components, driven by a portable Rust/WASM query engine — with React, Vue and Svelte components.

Readme

opengrid

npm licence

Data grid, table and pivot as Web Components, built to be accessible and machine-readable — driven by one query engine that runs in the browser (WebAssembly), on a server (PostgreSQL), or split between the two, with the same results everywhere.

  • <opengrid-grid> — sorting, filtering, search, facets, grouping with totals, selection, editing, virtualized or paged; operated from the keyboard.
  • <opengrid-table> — a plain semantic <table> for displaying data.
  • <opengrid-pivot> — a pivot with subtotals and a grand total, from a server or from the engine in the tab.
  • Column titles — the page names its columns, in its own language, wherever the grid names them.
  • Export — what the reader sees, every match of it, as CSV or JSON; XLSX from the server.
  • A resource report — every answer as an event (where it ran, how long, how big), and what the engine holds in memory.
  • Data without JavaScript — a page can put its own <table> inside an element, for readers and crawlers that run no script.
  • Five built-in looks — theme="paper", your own --og-* properties on top, and ::part for every element.

Live demos

The same 17 demos in every framework, each with its source, its data and options to change live:

| JavaScript | React | Vue | Svelte | Angular | | :-: | :-: | :-: | :-: | :-: |

Start with the overview, the grouping, the 100,000 rows in a worker or the looks.

Install

npm install @casoon/opengrid

The package holds the elements and the query engine. With a bundler, import from @casoon/opengrid; without one, see Installation.

Data in the browser

The engine reads a CSV against a schema — it never guesses types.

<opengrid-grid label="Orders" datasource="orders" columns="id,customer,amount"></opengrid-grid>

<script type="module">
  import { connect, createLocalProvider } from "@casoon/opengrid";
  import init, { Engine } from "@casoon/opengrid/engine/opengrid_wasm.js";

  await init();
  const engine = new Engine();
  const csv = await (await fetch("/orders.csv")).arrayBuffer();
  const schema = await (await fetch("/orders.schema.json")).text();
  engine.load_csv("orders", new Uint8Array(csv), schema);

  connect(document.querySelector("opengrid-grid"), {
    provider: createLocalProvider(engine),
  });
</script>
{
  "fields": [
    { "name": "id", "type": "int64", "nullable": false },
    { "name": "customer", "type": "utf8", "nullable": true },
    { "name": "amount", "type": { "decimal": { "precision": 12, "scale": 2 } }, "nullable": true }
  ]
}

createWorkerProvider() runs the same engine in a worker instead.

Data from a server

opengrid-server answers the same queries on a server — the browser sends a query object, never SQL, and the server enforces tokens, a per-tenant row filter and a field allowlist. It knows no database: your program hands it its sources as connectors, and PostgreSQL is one reference among them.

import { connect, createRestProvider } from "@casoon/opengrid";

connect(document.querySelector("opengrid-grid"), {
  provider: createRestProvider({ url: "https://example.org", source: "orders", token: "…" }),
});

See Where queries run.

React, Vue, Svelte

One package: the components are its subpaths, and the framework is an optional peer.

npm install @casoon/opengrid react   # or vue, svelte
import { OpengridGrid } from "@casoon/opengrid/react";   // or /vue, /svelte

<OpengridGrid label="Orders" datasource="orders" columns="id,customer,amount"
              provider={provider} view={view} onViewChange={setView} />

Angular, Astro and server-rendered pages use connect directly — Frameworks.

Looks

A grid without any page CSS wears Base. theme picks another of the five built-in looks — base, paper, violet, orange, dark — on all three elements:

<opengrid-grid theme="dark" label="Orders" datasource="orders"></opengrid-grid>
/* The page's own properties win over the look. */
opengrid-grid { --og-accent: #0f766e; --og-row-height: 36px; }

The focus ring, the selection bar and the forced-colours palette stay what they are in every look. The fonts are named, not loaded: a page that wants Geist or IBM Plex Sans hosts them. See Styling.

Export

import { loadOpengrid, exportRows } from "@casoon/opengrid";

const { module } = await loadOpengrid();
const query = module.get_query(grid);               // the reader's view, without a window
const blob = await exportRows(provider, query, { format: "csv" });

CSV per RFC 4180 with a guard against formula injection, or JSON; through createRestProvider also XLSX, written by the server (format: "xlsx"). A pivot exports as shown with get_pivot. See Export.

Documentation

Accessible and machine-readable: the aim

opengrid is meant to be more than a WebAssembly engine that draws a grid. Its data should reach everyone and everything that reads a page: a person using a keyboard or a screen reader, and a program — a test, a browser agent, an export. How it is built toward that:

  • One structure for people and programs. A native <table> where reading is all there is to do, role="grid" (or treegrid when grouped) where interaction needs it: row and column headers, aria-rowcount for the whole result behind a virtualized window, aria-sort, aria-selected, a name for every control. The accessibility tree a screen reader reads is the one an automation tool or an AI agent reads.
  • Designed for the keyboard. The WAI-ARIA grid pattern for the keys, nothing that needs dragging, and one polite live region for every change of state.
  • Open data at every step. The schema is a JSON document, a query is a JSON AST, the view is JSON, an export is CSV, JSON or XLSX, and a page can write its data as a plain table inside the element for readers that run no script.
  • Tested, not assumed. axe-core runs over every state of the end-to-end suite; target sizes, reflow at 320 px and forced colours are tests; the announcements are recorded in order.

This is not a statement of conformance yet. A pass with a screen reader is still to come (#5), and a conformance report follows it. What is tested and what is not: Accessibility.

Status

Pre-1.0: a minor version may change the API, a patch version does not (CHANGELOG).

Licence

MIT OR Apache-2.0.