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

@cascivo/charts

v1.9.0

Published

Chart components built from scratch — scales, shapes, and signal-driven rendering, zero dependencies. Colors come from @cascivo/themes; components from @cascivo/react. Docs offline: npx @cascivo/docs

Readme

npm downloads license types

npm · cascivo.com · Docs · Storybook · GitHub


Accessible, signal-driven chart library for cascivo — AreaChart, BarChart, LineChart, Sparkline, Heatmap, and more. All charts are keyboard-navigable with aria-live tooltips. CVD-safe palettes (Okabe-Ito, oklch) verified in CI across all 12 themes.

Docs offline? The full cascivo reference ships as an npm package — npx -y @cascivo/docs, no website needed.

Install

pnpm add @cascivo/charts @preact/signals-react

react, react-dom, and @preact/signals-react are peer dependencies — install them in your app.

Usage

import { AreaChart, BarChart, LineChart, Sparkline } from '@cascivo/charts'
import '@cascivo/charts/styles.css' // required — maps to the dist `charts.css`
import '@cascivo/themes/dark.css' // any cascivo theme drives the chart colors

export function Traffic() {
  return (
    <LineChart
      data={[
        { x: 0, y: 12 },
        { x: 1, y: 28 },
        { x: 2, y: 19 },
      ]}
    />
  )
}

Charts are CSS-token-themed: drop them inside any element carrying a data-theme (or import a theme stylesheet) and they pick up the same palette, radii, and typography as the rest of cascivo.

Sizing — responsive by default

Omit width and the chart fills and tracks its container (a ResizeObserver watches the slot), so a chart drops cleanly into a responsive Card or grid cell with no measuring on your part. height defaults to 300 (px); set it to change the aspect.

Pass an explicit width only for a fixed-size export — and even then it is clamped to the container (max-inline-size: 100%), so an over-wide width scales down instead of overflowing and clipping data. To size another element to match a chart, or to build a custom chart, use the exported useChartSize() hook.

<Card>
  <LineChart data={data} />           {/* fills the card, resizes with it */}
</Card>
<LineChart data={data} height={160} /> {/* shorter, still full-width */}

Vite SSR (TanStack Start, Remix, vite-ssr, workerd)? Like the rest of cascivo, the chart CSS ships as side-effect imports a bare server loader can't resolve — mark ssr: { noExternal: [/^@cascivo\//] } (the pattern already covers @cascivo/charts) and import @cascivo/charts/styles.css once in your root entry. Full recipe: USING-WITH-VITE-SSR.md.

React apps must subscribe to signals

The charts are signal-driven. In a plain React app (no Babel signals transform), call useSignals() from @cascivo/core as the first statement of any component that reads a signal during render. The docs app (Preact) does not need this.

One sparkline, without the engine

import { Sparkline } from '@cascivo/charts' pulls in the whole charting engine — tooltips, voronoi hit-testing, a canvas layer, zoom/pan, a toolbox, PNG/SVG export — because Sparkline is built on the same frame as every other chart. An adopter measured 44.87 kB / 14.84 kB gzip for a single trend line on a landing page.

For a page that wants a sparkline and draws no other charts, there is a subpath that does not:

import { Sparkline } from '@cascivo/charts/sparkline' // ~3.5 kB gzip, no engine

Identical props, identical markup, identical styling — asserted by a DOM-parity test, and the size is held by a budget in CI. One difference: no hover tooltip, because the tooltip is what requires the engine.

Use the main entry when the page draws other charts anyway: the engine is already paid for and the subpath saves nothing.

Coloring

By default every slice/series/layer is colored from the positional palette (--cascivo-chart-1 … --cascivo-chart-8, theme-driven and CVD-safe). To pin a specific color, set color on the datum (PieChartDatum) or series (BarChartSeries) — not on the chart component. Any CSS color works, including a token:

<PieChart
  title="Task status"
  data={[
    { id: 'done', label: 'Done', value: 92, color: 'var(--cascivo-color-success)' },
    { id: 'blocked', label: 'Blocked', value: 16, color: 'var(--cascivo-color-destructive)' },
  ]}
/>

Omit color and the slice falls back to its positional palette entry.

Donut with a center label

Pass donut, then centerValue/centerLabel (or arbitrary centerSlot content) to fill the hole. thickness (ring width, px) or innerRadius (px, wins over thickness) tune the ring; size is a square width/height shorthand:

<PieChart
  donut
  size={220}
  thickness={28}
  centerValue="142"
  centerLabel="Total tasks"
  title="Task status"
  data={data}
/>

Empty data renders a visible placeholder ("No data", override with emptyLabel).

Stacked bars from row data

toStackedSeries(rows) pivots row-oriented { label, segments: [{ key, value, color? }] } data into the series + x/y shape BarChart consumes, preserving per-segment color. Spread the result in:

import { BarChart, toStackedSeries } from '@cascivo/charts'

const rows = [
  { label: 'Mon', segments: [
    { key: 'Done', value: 5, color: 'var(--cascivo-color-success)' },
    { key: 'Blocked', value: 2, color: 'var(--cascivo-color-destructive)' },
  ] },
  { label: 'Tue', segments: [
    { key: 'Done', value: 8, color: 'var(--cascivo-color-success)' },
    { key: 'Blocked', value: 1, color: 'var(--cascivo-color-destructive)' },
  ] },
]

<BarChart mode="stacked" tooltip {...toStackedSeries(rows)} title="Throughput" />

The stacked tooltip lists label · total then each non-zero layer in its color; pass tooltipFormat to override, or xLabelEvery={n} to thin a crowded x-axis.

Install

pnpm add @cascivo/charts

cascivo.com · Docs · Storybook · GitHub · AI agents: read llms.txt (install steps + component index, plain text) or use @cascivo/mcp and registry.json · MIT