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

treemap-customizable

v0.1.2

Published

Customizable treemap visualization component for React

Downloads

11

Readme

Treemap Customizable for React

npm version License: MIT

A highly flexible and customizable treemap visualization component for React, built with TypeScript. It allows you to visualize hierarchical data as a set of nested rectangles, where the area of each rectangle is proportional to its value.

This library offers deep customization through:

  • Generic Data Handling: Use your own data structures.
  • Accessor Props: Define how to extract IDs and values from your data.
  • Custom Rendering: Provide your own React components to render individual treemap nodes and tooltips.
  • Theming: Easily customize colors, fonts, and other styles with a theme object.
  • CSS Classes & Styles: Apply custom CSS classes and inline styles to various elements.

Features

  • Squarified Algorithm: Optimizes for aspect ratios close to 1, making rectangles more square-like.
  • Responsive: Adapts to the size of its container.
  • Customizable Nodes: Full control over the appearance and content of each treemap cell.
  • Customizable Tooltips: Design tooltips to display any information from your data.
  • Theming Support: Easily override default styles.
  • TypeScript Support: Written in TypeScript, providing strong typing.
  • No External CSS Dependencies: Styles are managed via inline styles and a theme object, making it framework-agnostic.

Installation

npm install treemap-customizable
# or
yarn add treemap-customizable

Basic Usage

import React from 'react';
import { CustomTreeMapVisualization, TreemapDataItem } from 'treemap-customizable';

// 1. Define your data structure
interface MyDataType extends TreemapDataItem {
  name: string;
}

const App = () => {
  const data: MyDataType[] = [
    { id: 'a1', value: 100, name: 'Alpha' },
    { id: 'b1', value: 75, name: 'Beta' },
    { id: 'c1', value: 50, name: 'Gamma' },
  ];

  // 2. Define accessor functions
  const valueAccessor = (item: MyDataType) => item.value;
  const idAccessor = (item: MyDataType) => item.id;

  return (
    // Ensure parent has defined dimensions for the treemap
    <div className="w-full h-[500px] border border-gray-300 p-2 rounded-lg shadow">
      <CustomTreeMapVisualization<MyDataType>
        data={data}
        valueAccessor={valueAccessor}
        idAccessor={idAccessor}
        gap={4} // Gap between cells
        // Example: Override default container styling
        // containerClassName="bg-blue-50 rounded-md"
      />
    </div>
  );
};

export default App;

Advanced Customization Example

import React from 'react';
import {
  CustomTreeMapVisualization,
  TreemapDataItem,
  NodeRenderProps,
  TooltipRenderProps,
} from 'treemap-customizable';

interface ProductData extends TreemapDataItem {
  productName: string;
  department: string;
  sales: number;
  imageUrl?: string;
  change: number; // For conditional styling
}

const productDataset: ProductData[] = [
  { id: 'P101', sales: 1200, productName: 'SuperWidget', department: 'Electronics', imageUrl: 'https://via.placeholder.com/60', change: 5.2 },
  { id: 'P102', sales: 850, productName: 'MegaGear', department: 'Appliances', imageUrl: 'https://via.placeholder.com/60', change: -1.5 },
  // ... more products
];

// Custom Node Renderer using Tailwind CSS
const ProductNode: React.FC<NodeRenderProps<ProductData>> = ({ item, width, height, isHovered }) => {
  // Conditional Tailwind classes
  const baseClasses = "p-2 h-full flex flex-col items-center justify-around box-border text-center overflow-hidden rounded transition-all duration-200";
  const colorClasses = item.change > 0 
    ? "bg-emerald-500 hover:bg-emerald-600 text-white" 
    : "bg-rose-500 hover:bg-rose-600 text-white";
  const hoverEffectClasses = isHovered ? "ring-2 ring-offset-1 ring-sky-400 shadow-xl transform scale-105" : "shadow-md";
  
  const showImage = width > 70 && height > 60;

  return (
    <div className={`${baseClasses} ${colorClasses} ${hoverEffectClasses}`}>
      <strong className="text-xs md:text-sm font-semibold truncate w-full px-1">
        {item.productName}
      </strong>
      {showImage && item.imageUrl && 
        <img 
          src={item.imageUrl} 
          alt={item.productName} 
          className="max-h-[40%] max-w-[40%] my-1 object-contain rounded-sm"
        />
      }
      <span className="text-xxs md:text-xs opacity-90">Dept: {item.department}</span>
      <span className="text-sm md:text-base font-bold">${item.sales.toLocaleString()}</span>
    </div>
  );
};

// Custom Tooltip Renderer using Tailwind CSS
const ProductTooltip: React.FC<TooltipRenderProps<ProductData>> = ({ item }) => {
  if (!item) return null;
  return (
    // This content will be wrapped by the library's tooltip wrapper
    // The wrapper itself can be styled via tooltipWrapperBaseClass or tooltipWrapperClassName
    <div className="p-3 text-sm">
      <h4 className="text-base font-bold mb-2">{item.productName} <span className="text-xs opacity-70">({item.id})</span></h4>
      <p className="mb-1">Sales: <span className="font-semibold">${item.sales.toLocaleString()}</span></p>
      <p className="mb-1">Department: {item.department}</p>
      <p className={`font-medium ${item.change > 0 ? 'text-green-400' : 'text-red-400'}`}>
        Change: {item.change.toFixed(1)}%
      </p>
    </div>
  );
};

const MyAdvancedApp = () => {
  return (
    <div className="w-full h-[600px] p-4 bg-slate-100 rounded-xl shadow-lg">
      <h2 className="text-2xl font-bold text-center mb-4 text-slate-700">Product Performance Treemap</h2>
      <CustomTreeMapVisualization<ProductData>
        data={productDataset}
        valueAccessor={d => d.sales}
        idAccessor={d => d.id}
        valueForColoring={d => d.change} // Used by default node logic if renderNode not provided
        positiveThreshold={0}
        gap={6}
        renderNode={ProductNode}
        renderTooltip={ProductTooltip}
        // Override base classes for main container and default tooltip wrapper
        containerBaseClass="relative overflow-hidden w-full h-full bg-slate-200 rounded-lg"
        tooltipWrapperBaseClass="fixed py-2 px-4 shadow-2xl rounded-lg z-[1000] pointer-events-none bg-slate-800 text-slate-100 border border-slate-700"
        // Add specific classes for node wrappers (applied to the div TreeMapNode creates)
        nodeWrapperClassName={(item) => item.sales > 1000 ? "border-2 border-amber-400" : "border border-slate-300"}
      />
    </div>
  );
};

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | data | T[] (where T extends TreemapDataItem) | Required | Array of your data items. | valueAccessor | (item: T) => number | Required | Function to extract the numeric value (>= 0) for area calculation from each item. | idAccessor | (item: T) => string | number | Required | Function to extract a unique ID from each item for keys and tracking. | positiveThreshold | number | 0 | Value above which an item is considered "positive" for default node coloring if valueForColoring is used. | valueForColoring | (item: T) => number | undefined | Optional. Function to extract the value used for determining positive/negative node coloring (uses theme's positive/negative colors). If not provided, the main valueAccessor result is used with positiveThreshold. | gap | number | 4 | Gap between treemap cells in pixels. | width | string | number | '100%' | Width of the treemap container (e.g., '100%', 500, '50em'). | height | string | number | '600px' | Height of the treemap container (e.g., '600px', 400). | theme | Partial | {...} | Object to customize default colors, fonts, etc. Merged with defaultTreemapTheme. | containerClassName | string | undefined | CSS class for the main container div. | containerStyle | React.CSSProperties | undefined | Inline styles for the main container div. | nodeWrapperClassName | string | ((item: LayoutDataPoint) => string) | undefined | CSS class(es) for each node's wrapping div. Can be a function. | nodeWrapperStyle | React.CSSProperties | ((item: LayoutDataPoint) => React.CSSProperties) | undefined | Inline style(s) for each node's wrapping div. Can be a function. | tooltipWrapperClassName | string | undefined | CSS class for the default tooltip's wrapping div. | tooltipWrapperStyle | React.CSSProperties | undefined | Inline styles for the default tooltip's wrapping div. | renderNode | (props: NodeRenderProps) => React.ReactNode | undefined | Custom function to render the content of each treemap node. Takes precedence over default node rendering. renderTooltip | (props: TooltipRenderProps) => React.ReactNode | undefined | Custom function to render the content of the tooltip. Takes precedence over default tooltip.

Data Item Structure

Your data items should at least provide a unique id and a numeric value accessible via your accessor functions.

interface TreemapDataItem {
  id: string | number;
  value: number;       // Non-negative for area calculation
  [key: string]: any;  // Your custom fields
}

Custom Rendering Props

  • NodeRenderProps:
interface NodeRenderProps<T extends TreemapDataItem> {
  item: LayoutDataPoint<T>; // Processed data item with layout info (x, y, width, height)
  isHovered: boolean;
  isPositive: boolean;      // Based on positiveThreshold & valueForColoring/valueAccessor
  width: number;            // Actual display width of the node content area (after gap)
  height: number;           // Actual display height of the node content area (after gap)
}
  • TooltipRenderProps:
interface TooltipRenderProps<T extends TreemapDataItem> {
  item: LayoutDataPoint<T> | null; // The hovered item, or null
  mouseX: number;                  // ClientX of mouse
  mouseY: number;                  // ClientY of mouse
  containerRef: React.RefObject<HTMLDivElement | null>; // Ref to treemap container
}