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

@taewooyo/heatmap-react

v0.3.0

Published

React SVG heatmaps powered by Volcano's shared Kotlin Multiplatform core

Readme

@taewooyo/heatmap-react

Version 0.3.0 of this pre-1.0 package renders an SVG heatmap using layout and color calculations from Volcano's shared Kotlin/JS core. The package bundles that core, so React consumers do not need Kotlin or Gradle installed.

The current peer range accepts React 18.2–18.x or 19.x; the repository's development dependency is React 19.2.4. Future major versions are not declared compatible until they are tested and the package is updated.

Integration guide · TypeScript API reference · Changelog · Web demo

npm install @taewooyo/heatmap-react

For repository development only, build the Kotlin/JS package from the repository root first:

./gradlew :volcano:jsDevelopmentLibraryCompileSync

Then run from this directory:

npm ci
npm test

Minimal usage:

import { Heatmap } from "@taewooyo/heatmap-react";

<Heatmap
  data={{
    id: "market",
    label: "Market",
    value: 0,
    children: [
      { id: "A", label: "A", value: 60, metric: 4.2 },
      { id: "B", label: "B", value: 40, metric: -2.1 },
    ],
  }}
  width={960}
  height={600}
  metricFormatter={(metric) => `${metric > 0 ? "+" : ""}${metric.toFixed(2)}%`}
  onLeafClick={(node, cell) => console.log(node.id, cell.key)}
/>

value determines area and metric determines the shared red/neutral/green color. The default color range is -10 to +10; set maximumAbsoluteMetric and palette to match your data. Explicit color accepts CSS #RRGGBB or #RRGGBBAA. Width, height, and group header height use integer pixels. Use Heatmap with explicit dimensions, or ResponsiveHeatmap with a bounded-height container that follows its parent size. The responsive wrapper waits until it has a measurable size and supports an optional SSR fallback. Use onGroupClick to control drill-down in your application.

The default SVG cells adapt label and metric size to the available space and animate color changes over 240 ms. Hover tooltips are off by default; configure hover or long-press behavior with interaction. The displayPolicy, style, interaction, and motion objects share Compose's setting names and defaults; dimensions and padding values use SVG pixels. An optional imageUrl is rendered as a circular logo when a cell is large enough; the package does not fetch or cache images itself. selectedId selects a leaf by ID; because IDs may repeat in different groups, use selectedKey with the cell.key passed to onLeafClick when selection must be unambiguous. Set ariaLabel to describe the chart for assistive technology. Source values are included in accessible names and tooltips by default; valueFormatter and valueLabel customize their display. metricFormatter controls metric text; it does not affect layout or color calculations.

onLeafClick and onGroupClick receive the original node and its computed layout cell. Use onGroupClick to control drill-down in your application. The layout cell key is a path-derived key and remains distinct when IDs repeat in separate branches.

For Compose-like state management, create const state = useHeatmapState(data) and pass it as <Heatmap data={data} state={state} ... />. The state exposes visibleNode, breadcrumbs, selection properties, and navigation/selection methods. style, displayPolicy, interaction, and motion configuration objects use the same names and defaults as Compose, with SVG pixel numbers in place of Dp. Existing flat props remain supported.

Use palette={{ negative: "#e53935", neutral: "#9ca3af", positive: "#16a34a" }} to match the mobile and desktop demos. Palette colors use the same CSS hex formats as explicit node colors.

When values change, pass a new immutable data tree. Mutating the existing tree in place will not invalidate the component's layout memoization.

Props

| Prop | Default | Description | | --- | --- | --- | | data | required | Immutable tree of nodes with id, label, value, optional metric, color, imageUrl, and children. | | width, height | required | Positive integer dimensions in SVG pixels. | | groupHeaderHeight | 20 | Group header height in pixels. | | maximumAbsoluteMetric | 10 | Absolute metric value mapped to the palette's positive or negative endpoint. | | palette | core default | Negative, neutral, and positive CSS hex colors. | | cellGap | 1 | Inset between neighboring cells in SVG units. | | metricFormatter | signed number | Formats the metric displayed in cells and tooltips. | | valueFormatter | source number | Formats the source value included in cell descriptions and tooltips. | | valueLabel | Value | Label paired with the formatted value in accessible names and tooltips. | | emptyContent | No data | Content shown when no positive visualization values remain. | | onLeafClick, onGroupClick | — | Click handlers receiving (node, layoutCell). | | selectedId, selectedKey | null | Selected leaf by ID or unambiguous path key. selectedKey takes precedence. | | selectedBorderColor | #0f172a | Outline color for the selected leaf. | | tooltipHoverDelayMs | 400 | Hover delay before showing the tooltip. | | logoMaxSize | 48 | Maximum rendered image size in SVG pixels. | | ariaLabel | Heatmap | Accessible name for the SVG chart. | | className | — | Class applied to the root SVG element. |

The hover tooltip is pointer-based, so provide onLeafClick or another app-level detail affordance for touch users.

Live updates, navigation and responsive containers (0.3.0)

Keep root and sibling IDs stable. useHeatmapState retains the valid group path and resolves selection to the latest leaf object on refresh. Removed groups fall back to the nearest surviving group, removed selections clear, and changing the root ID resets both. Use state.reset() for an explicit return to the overview. state.navigateToPath(["sector", "industry"]) opens an exact root-relative group path. state.drillDown(node) opens any group from the current data tree; state.drillDown("id") still addresses a direct child.

const state = useHeatmapState(data);
<ResponsiveHeatmap
  data={data}
  state={state}
  containerStyle={{ height: 360 }}
  emptyContent="No matching items"
  valueFormatter={(value) => value.toLocaleString()}
  motion={{ enabled: false }}
/>;

Import ResponsiveHeatmap alongside useHeatmapState. Give the container a bounded height. The wrapper waits when hidden or unmeasured, supports SSR with an optional fallback, and observes size changes. Use Heatmap directly for explicit pixel dimensions.

Interactive charts have one Tab stop. Arrow keys move through cells in data order; Home/End go to the first/last target and Enter/Space activate it. These are logical-order movements, not spatial nearest-neighbor navigation. The selected outline defaults to #0f172a; use selectedBorderColor="transparent" to opt out. emptyContent replaces an empty chart, and valueFormatter adds the area value to cell descriptions and tooltips. Reduced motion disables all built-in transitions when motion.enabled is false.

The source value is included in accessible names and tooltips by default. Set valueLabel to localize the accessible label (default: "Value"), and provide valueFormatter when values need domain units or locale-specific formatting.