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

@geovi/the-datagrid

v0.0.1

Published

A modern, feature-rich React data grid component built with shadcn/ui and TanStack Table

Readme

the-datagrid

A modern, feature-rich React data grid built on TanStack Table with a shadcn-aligned look-and-feel and self-contained packaged styles.

Documentation and live examples: https://geo-vi.github.io/the-datagrid/

Features

  • Virtualized rendering for large datasets
  • Sorting (single + multi-column)
  • Filtering with a built-in filter row and operators
  • Column management (reorder, resize, auto-size)
  • Pagination (local + remote)
  • Row selection (checkbox column)
  • Modern shadcn-aligned look-and-feel with packaged styles
  • Fully typed TypeScript API
  • Migration-friendly API inspired by Inovua ReactDataGrid

Installation

npm install @geovi/the-datagrid react react-dom
# or
yarn add @geovi/the-datagrid react react-dom
# or
pnpm add @geovi/the-datagrid react react-dom

That is the normal installation flow for consumers.

You do not need to install:

  • Tailwind CSS
  • shadcn/ui
  • a separate package stylesheet import in normal app setups

This also applies when you use custom grid themes. The grid theme variables are plain CSS variables in the shipped stylesheet, so consumers do not need Tailwind just to use theme="dark", theme="hf-dark", or their own imported grid theme CSS.

Styling

@geovi/the-datagrid ships compiled CSS and loads it automatically from the package entry.

In a typical React app with a modern bundler, this is enough:

  • Vite
  • Next.js
  • Webpack-based apps
  • other setups that support CSS imports from npm packages

The grid keeps a shadcn-aligned look and will inherit app-level shadcn theme variables when they exist (--background, --foreground, --border, --ring, etc.). If they do not exist, the package uses scoped fallback tokens so it still renders correctly.

Theme variables are resolved at runtime from normal CSS, not from the consumer's Tailwind build. Tailwind is only used to build this library, not required to consume it.

Built-in theme behavior:

  • theme="default" follows the nearest .dark ancestor
  • theme="light" forces the light token set
  • theme="dark" forces the dark token set
  • theme="<custom-name>" activates a named custom theme on the grid root via data-theme="<custom-name>"

If your environment does not process CSS imported from package entries, use the exported fallback once in your app:

import "@geovi/the-datagrid/style.css";

Custom named themes

Named themes are configured with CSS variables on the grid root selector. For example, this custom hf-dark theme can be used with theme="hf-dark":

.tdg-root[data-theme="hf-dark"] {
  --tdg-color-background: #191919;
  --tdg-color-foreground: #e5e5e5;
  --tdg-color-accent: #26324a;
  --tdg-grid-bg: #191919;
  --tdg-header-bg: #1e1e1e;
  --tdg-grid-border-color: #2c2c2c;
  --tdg-cell-border-color: #2c2c2c;
  --tdg-header-border-color: #2c2c2c;
  --tdg-row-odd-bg: #191919;
  --tdg-row-even-bg: #191919;
  --tdg-row-odd-hover-bg: #26324a;
  --tdg-row-even-hover-bg: #26324a;
  --tdg-row-selected-bg: #1a2740;
  --tdg-row-selected-hover-bg: #1a2740;
  --tdg-input-bg: #191919;
  --tdg-input-border-color: #383838;
  --tdg-input-border-color-hover: #383838;
  --tdg-input-border-color-focus: #383838;
  --tdg-select-bg: #191919;
  --tdg-select-list-bg: #191919;
  --tdg-select-border-color: #383838;
  --tdg-select-border-color-hover: #383838;
  --tdg-select-border-color-focus: #383838;
  --tdg-select-item-hover-bg: #26324a;
  --tdg-select-item-selected-bg: #26324a;
  --tdg-checkbox-checked-bg: #688ad7;
  --tdg-checkbox-checked-color: #e5e5e5;
  --tdg-checkbox-indeterminate-bg: #688ad7;
  color-scheme: dark;
}

This lets you keep using a migration-friendly theme name such as hf-dark while mapping it to the grid’s internal theme tokens.


Basic usage

import { ReactDataGrid } from "@geovi/the-datagrid";
import type { TypeColumns } from "@geovi/the-datagrid";

export default function App() {
  const columns: TypeColumns = [
    { name: "id", header: "ID", sortable: true, filterable: true },
    { name: "name", header: "Name", sortable: true, filterable: true },
    { name: "email", header: "Email", sortable: true, filterable: true },
  ];

  const rows = [
    { id: 1, name: "John Doe", email: "[email protected]" },
    { id: 2, name: "Jane Smith", email: "[email protected]" },
  ];

  return (
    <ReactDataGrid
      idProperty="id"
      columns={columns}
      dataSource={rows}
      virtualized
      enableFiltering
    />
  );
}

Advanced usage

import { useMemo, useState } from "react";
import { ReactDataGrid } from "@geovi/the-datagrid";
import type {
  TypeColumns,
  TypeFilterValue,
  TypeI18n,
  TypeOnSelectionChangeArg,
  TypeRowSelection,
} from "@geovi/the-datagrid";

export default function App() {
  const [selected, setSelected] = useState<TypeRowSelection>({});
  const [columnOrder, setColumnOrder] = useState<string[]>([]);
  const [filterValue, setFilterValue] = useState<TypeFilterValue | null>(null);

  const columns: TypeColumns = useMemo(
    () => [
      { name: "id", header: "ID", sortable: true, filterable: true },
      { name: "name", header: "Name", sortable: true, filterable: true },
      { name: "email", header: "Email", sortable: true, filterable: true },
    ],
    []
  );

  const rows = useMemo(
    () => [
      { id: 1, name: "John Doe", email: "[email protected]" },
      { id: 2, name: "Jane Smith", email: "[email protected]" },
    ],
    []
  );

  const i18n: TypeI18n = useMemo(
    () => ({
      noRecords: "No records",
      clear: "Clear",
      contains: "Contains",
      sortAsc: "Sort A→Z",
      sortDesc: "Sort Z→A",
    }),
    []
  );

  const onSelectionChange = (config: TypeOnSelectionChangeArg) => {
    setSelected(config.selected);
  };

  return (
    <ReactDataGrid
      theme="default"
      idProperty="id"
      columns={columns}
      columnOrder={columnOrder}
      dataSource={rows}
      enableFiltering
      defaultFilterValue={filterValue ?? undefined}
      onFilterValueChange={(v) => setFilterValue(v)}
      filteredRowsCount={(count) => console.log("Filtered rows:", count)}
      enableColumnFilterContextMenu
      enableColumnAutosize
      skipHeaderOnAutoSize={false}
      onColumnOrderChange={setColumnOrder}
      virtualized
      columnUserSelect
      i18n={i18n}
      showColumnMenuTool={false}
      checkboxColumn
      onSelectionChange={onSelectionChange}
      selected={selected}
    />
  );
}

onSelectionChange still emits the Inovua-style config object. For migration ergonomics, the grid also accepts the emitted object back through selected, so onSelectionChange={setSelectedRows} works with the same state variable used for selected.

Props (high-level)

Note: this is a curated overview. For the complete contract, refer to the exported TypeScript types.

Core

| Prop | Type | Default | Description | | ------------ | ---------------- | ------------ | ------------------------------------------- | | idProperty | string | required | Property name used as unique row identifier | | columns | TypeColumns | required | Column definitions | | dataSource | TypeDataSource | required | Data source (array, function, or promise) |

Display

| Prop | Type | Default | Description | | ------------------ | ----------------------------- | ----------- | ------------------------------ | | theme | string | "default" | Theme name | | rowHeight | number | 44 | Row height in pixels | | headerHeight | number | 40 | Header height in pixels | | filterRowHeight | number | 44 | Filter row height in pixels | | virtualized | boolean | true | Enable virtual scrolling | | columnUserSelect | boolean \| "text" \| "none" | true | Column text selection behavior | | showCellBorders | boolean \| "vertical" \| "horizontal" | true | Cell separator mode; use "horizontal" to disable vertical lines |

Columns

| Prop | Type | Default | Description | | ---------------------- | --------------------------- | ------- | --------------------------------- | | columnOrder | string[] | - | Ordered array of column ids/names | | onColumnOrderChange | (order: string[]) => void | - | Fired when column order changes | | enableColumnAutosize | boolean | true | Auto-calc column widths | | skipHeaderOnAutoSize | boolean | false | Skip header when auto-sizing | | showColumnMenuTool | boolean | false | Show column menu tool in header |

Filtering

| Prop | Type | Default | Description | | ------------------------------- | ---------------------------------- | ------- | --------------------------------- | | enableFiltering | boolean | true | Enable filter row | | filterValue | TypeFilterValue | - | Controlled filter value | | defaultFilterValue | TypeFilterValue | - | Uncontrolled initial filter value | | onFilterValueChange | (value: TypeFilterValue) => void | - | Fired on filter change | | enableColumnFilterContextMenu | boolean | false | Context menu for filter operators | | filteredRowsCount | (count: number) => void | - | Reports filtered row count |

Sorting

| Prop | Type | Default | Description | | ------------------------- | ------------------------------ | ------- | ----------------------------- | | sortInfo | TypeSortInfo | - | Controlled sort state | | defaultSortInfo | TypeSortInfo | - | Uncontrolled initial sort | | onSortInfoChange | (info: TypeSortInfo) => void | - | Fired on sort change | | allowUnsort | boolean | true | Allow returning to “unsorted” | | defaultSortingDirection | "asc" \| "desc" | "asc" | Default sort direction |

Selection

| Prop | Type | Default | Description | | ------------------- | -------------------------------------------- | ------- | ------------------------------ | | checkboxColumn | boolean \| IColumn | false | Enable checkbox column | | selected | TypeRowSelection | - | Controlled selection | | defaultSelected | TypeRowSelection | - | Uncontrolled initial selection | | onSelectionChange | (config: TypeOnSelectionChangeArg) => void | - | Fired on selection changes |

Pagination

| Prop | Type | Default | Description | | --------------- | -------------------------------------- | ---------------------- | ---------------------------- | | pagination | true \| false \| "remote" \| "local" | true | Pagination mode | | skip | number | - | Controlled offset | | defaultSkip | number | 0 | Initial offset | | limit | number | - | Controlled page size | | defaultLimit | number | 10 | Initial page size | | onSkipChange | (skip: number) => void | - | Fired when offset changes | | onLimitChange | (limit: number) => void | - | Fired when page size changes | | pageSizes | number[] | [10, 20, 30, 40, 50] | Allowed page sizes |

Misc

| Prop | Type | Default | Description | | ----------- | -------------------------- | ------- | ---------------------------------------- | | i18n | TypeI18n | - | Text overrides (labels, operators, etc.) | | loading | boolean | - | Loading state | | onReady | (ref: RefObject) => void | - | Called when grid ref is ready | | handle | (ref: RefObject) => void | - | Alias for onReady | | className | string | - | Extra CSS classes | | style | CSSProperties | - | Inline styles |

TypeScript

The package ships full type definitions.

import { ReactDataGrid } from "@geovi/the-datagrid";
import type {
  TypeColumns,
  TypeColumn,
  TypeDataGridProps,
  TypeRowSelection,
  TypeOnSelectionChangeArg,
  TypeFilterValue,
  TypeSortInfo,
  TypeI18n,
} from "@geovi/the-datagrid";