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

cantal

v0.0.12

Published

Cantal is a lightweight but powerful grid library for React. Its primary responsibilities are rendering an accessible layout of the grid and exposing grid events. It comes with sane defaults and it's highly customizable.

Readme

Cantal

Overview

Cantal is a lightweight but powerful grid library for React. Its primary responsibilities are rendering an accessible layout of the grid and exposing grid events. It comes with sane defaults and it's highly customizable.

Quick start

import { Grid } from "cantal";
import "cantal/dist/cantal.css"; // optional styling

function MyGrid() {
  return (
    <Grid
      columnDefs={[
        { field: "x", title: "Latitude" },
        { field: "y", title: "Longitude" },
      ]}
      data={[
        { x: 40.77, y: -73.97 },
        { x: 40.35, y: -74.66 },
      ]}
    />
  );
}

Motivation

I wanted to create a grid library that delegates layout rendering to CSS using the Grid and Subgrid display properties. The result is a very lightweight but capable package. Cantal is in line with the render capabilities Tanstack Table and the write capabilities of AG-Grid.

Features

  • Accessible
  • Lightweight (~10kb gzipped)
  • Column filtering
  • Column grouping
  • Column pinning
  • Column resizing
  • Multi-column sorting
  • Row spanning
  • Column spanning
  • Focus management
  • Cell, row, and range selection
  • Advanced copy / paste
  • Cell editing
  • Custom styling
  • Virtualization

Grid props

| Prop name | Description | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | body | A function that returns the body component | | columnDefs | An array of objects containing properties that determine the number of columns and their behavior. See the Column definitions section below for details | | columnFilters | An object that tracks the state of each column's current filter value. The object keys represent the column and the values represent the filter value | | columnSorts | An object that tracks the state of each column's current sort mode. The object keys represent the column and the values represent the sort mode | | columnSpans | A reference to the key of the column spanning definitions on the row data object, e.g. "columnSpansKey" where the data object might look like { fieldA: 1, ..., columnSpansKey: [{ field: 'spanIdOrField', from: 0, to: 1 }] }. See the Column spanning section below for details | | data | An array of objects where each object represents a row of data | | focusedCell | Represents the cell that currently has focus. TODO | | gap | Defines the spacing (in pixels) between each cell. Accepts an integer or an object, e.g. { columnGap: 1, rowGap: 1 } | | handleColumnFilter | Invoked when a column's filter control changes | | handleColumnResize | Invoked when a column's width is being resized. The new width value is in pixels | | handleColumnSort | Invoked when a column's sort mode is changed | | handleEdit | Invoked when a cell edit has been commited via a cell editor or a paste operation. An object keyed by the row id or row index and its changed values is passed as an argument | | handleEditCellChange | Invoked when a cell edit is started, commited, cancelled or when the editor value changes, depending on the editor | | handleFocusedCellChange | Invoked when focus changes cells | | handleKeyDown | Invoked when the keydown event fires on the grid body. Invoke defaultHanlder inside the function body to perform default grid behavior such as cell navigation or cell editing on printable characters | | handlePointerDown | Invoked when the pointerdown event fires on the grid body. Invoke defaultHandler inside the function body to perform default grid behavior such as changing cell focus and range selection | | handleSelection | Invoked when a selection event occurs using either the keyboard or pointer drag | | header | Accepts custom header components | | id | Sets the id attribute on the grid's container element | | overscanColumns | Number of columns to render to the left and right of grid viewport for virtualized grids | | overscanRows | Number of columns to render above and below the grid viewport for virtualized grids | | rowHeight | Row height in pixels | | rowId | A key whose value is unique to each row of data. It's used to indicate the changed rows in handleEdit. It's important to assign this to an immutable property in your data to ensure its row value remains unique. The index of the data array will be used if this prop isn't provided | | selectedRanges | An array of Range objects representing selected cells | | selectionFollowsFocus | Updates the selected range whenever focusedCell changes. This is especially useful for grids with row spanning as it will expand the selected ranges to fully enclose a spanned cell | | styles | An object representing the grid elements and their corresponding styles | | virtual | Renders only a subset of columns and/or rows based on the size of the grid viewport (and overscan props overscanColumns and overscanRows). Using this prop can have dramatic performance improvements for large datasets |

Column definitions

Column definitions determine a lot of the behavior of the grid. Below is a list of all the column definition properties Cantal knows about:

| Key | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | allowEditCellOverflow | Allows the cell editor to overflow the cell boundary. This is particularly useful for editors that may require more space such as a textarea editor | | ariaCellLabel | Sets the aria-label attribute of the cells in the column | | ariaHeaderCellLabel | Sets the aria-label attribute of the column header cells | | cellClassNames | Adds class names to your cells based on their current state. Accepts an object or a function. See the styling story for details | | editable | Determines whether a cell is editable | | editor | Used for defining your own custom editor component that's displayed during edit mode | | field | A required property that's used to look up the value from the data row object | | filterable | Determines whether the filter control is displayed in the column header | | filterer | Used for defining your own custom filter component that's displayed in the column header | | headerCellClassNames | Adds custom classes to the various elements that comprise a header cell. Accepts an object or a function. See the styling story for details | | minWidth | Minimum width (in pixels) of the column | | pinned | Determines whether a column is pinned to one side of the grid or the other | | resizable | Allows the column to be resized by rendering a resizer element in the column header | | rowSpanComparator | A function that compares adjacent cells in the same column and determines where row span boundaries lie | | rowSpanning | Determines whether a column has the ability to span rows | | sortable | Determines whether the sort control is displayed in the column header | | sortStates | The list of sort modes to cycle through when sorting a column | | subcolumns | The list of child column definitions that fall under the defining column definition | | title | The column header label text | | valueParser | Invoked when a cell edit is being commited or when a paste from the clipboard is performed | | valueRenderer | A function that's responsible for the rendered output of the cell | | width | Sets the initial width of the column |

Constraints

CSS Grid layout is the underlying technology used to render your grid data. Browser impose a limits on the number of rows/columns one can render for a grid. Therefore, you'll likely see warnings if you're rendering cells in thousands. If you're attempting to render thousands of cells, it's recommended to use the virtual prop to improve performance by limiting the number of cells rendered at any given time.

Column spanning

Column spanning is one of the few features that is defined by a data row object.

More examples

Clone the repo, install the dependencies and run:

npm run stories

There are dozens of stories that illustrate all the features and expose the code for how to implement it yourself.