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

@dataset.sh/data-grid

v0.0.3

Published

A production-grade, feature-rich data grid component for React that serves as a modern replacement for AG Grid

Readme

@dataset.sh/data-grid

A production-grade, feature-rich data grid component library for React that serves as a modern replacement for AG Grid. Built with React, TypeScript, TanStack Table v8, and TanStack Virtual for optimal performance and flexibility.

✨ Features

Core Features

  • 🚀 High Performance - Virtual scrolling for both rows and columns, handles 10,000+ rows smoothly
  • 📊 Advanced Sorting - Single and multi-column sorting with visual indicators (↑↓)
  • 🔍 Smart Filtering - Column-specific filters:
    • Text: String contains filter
    • Number: Min/max range filter
    • Date: Date range picker
    • Boolean: Dropdown selector
  • 📌 Column Pinning - Pin columns to left or right for always-visible data
  • ↔️ Column Resizing - Drag to resize with min/max constraints
  • 🔄 Column Reordering - Drag and drop with live preview showing real-time data movement
  • ✏️ Cell Editing - Inline editing with built-in and custom editors
  • ☑️ Row Selection - None, single, or multi-row selection with checkboxes
  • 📱 Responsive - Auto-adapts to container size
  • 🎨 Theming - Full CSS variable theming support

Advanced Features

  • 🎯 Column Menu - Per-column actions (sort, pin, hide, auto-size)
  • 🗂️ Side Panels - Filters panel and columns panel for bulk operations
  • 📊 Status Bar - Row count, selection info, and numeric aggregations
  • 📋 CSV Export - Export all, filtered, or selected data
  • 🔧 Custom Renderers - Custom cell, header, and editor components
  • 🎭 Visual Feedback - Hover effects, drag indicators, and drop zones
  • Optimized Rendering - Only renders visible cells with overscan

🚀 Quick Start

Installation

# Using pnpm (recommended)
pnpm add @dataset.sh/data-grid

# Using npm
npm install @dataset.sh/data-grid

# Using yarn
yarn add @dataset.sh/data-grid

Basic Usage

import { DataGrid } from '@dataset.sh/data-grid';
import type { GridColumnDef } from '@dataset.sh/data-grid';
import '@dataset.sh/data-grid/styles';

interface Person {
  id: number;
  firstName: string;
  lastName: string;
  age: number;
  email: string;
  active: boolean;
}

const columns: GridColumnDef<Person>[] = [
  {
    id: 'select',
    headerName: '',
    width: 50,
    enableSorting: false,
    enableFiltering: false,
    enableResizing: false,
    cell: ({ row }) => (
      <input type="checkbox" />
    ),
  },
  {
    accessorKey: 'id',
    headerName: 'ID',
    type: 'number',
    width: 90,
    minWidth: 80,
  },
  {
    accessorKey: 'firstName',
    headerName: 'First Name',
    type: 'text',
    width: 120,
    editable: true,
  },
  {
    accessorKey: 'lastName',
    headerName: 'Last Name',
    type: 'text',
    width: 120,
    editable: true,
  },
  {
    accessorKey: 'age',
    headerName: 'Age',
    type: 'number',
    width: 80,
  },
  {
    accessorKey: 'email',
    headerName: 'Email',
    type: 'text',
    width: 200,
  },
  {
    accessorKey: 'active',
    headerName: 'Active',
    type: 'boolean',
    width: 100,
  },
];

function App() {
  const [data] = useState<Person[]>(generateData(1000));
  
  return (
    <div style={{ height: '600px' }}>
      <DataGrid
        data={data}
        columns={columns}
        selectionMode="multi"
        enableColumnReorder
        enableColumnResize
        sideBar
        statusBar
        pagination={{
          pageSize: 50,
          pageSizeOptions: [10, 20, 50, 100],
        }}
        onStateChange={(state) => {
          console.log('Grid state changed:', state);
        }}
      />
    </div>
  );
}

📖 API Reference

DataGrid Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | data | TData[] | Required | Array of data objects | | columns | GridColumnDef<TData>[] | Required | Column definitions | | height | number \| string | '100%' | Grid height | | width | number \| string | '100%' | Grid width | | selectionMode | 'none' \| 'single' \| 'multi' | 'none' | Row selection mode | | enableColumnReorder | boolean | false | Enable column drag and drop | | enableColumnResize | boolean | false | Enable column resizing | | sideBar | boolean \| SideBarConfig | false | Show side panel | | statusBar | boolean \| StatusBarConfig | false | Show status bar | | pagination | false \| PaginationConfig | false | Pagination configuration | | rowHeight | number | 40 | Row height in pixels | | overscanRows | number | 8 | Rows to render outside viewport | | overscanCols | number | 2 | Columns to render outside viewport | | onStateChange | (state: GridState) => void | - | State change callback | | onSelectionChange | (selection: Set<string>) => void | - | Selection change callback | | getRowId | (row: TData, index: number) => string | - | Custom row ID function |

Column Definition

interface GridColumnDef<TData> {
  // Identification
  id?: string;                    // Unique column ID
  accessorKey?: keyof TData;       // Data property key
  
  // Display
  headerName?: string;             // Header display text
  type?: 'text' | 'number' | 'date' | 'boolean' | 'select';
  
  // Sizing
  width?: number;                  // Initial width
  minWidth?: number;               // Minimum width (default: 80)
  maxWidth?: number;               // Maximum width (default: 500)
  
  // Features
  enableSorting?: boolean;         // Enable sorting (default: true)
  enableFiltering?: boolean;       // Enable filtering (default: true)
  enableResizing?: boolean;        // Enable resizing (default: true)
  enablePinning?: boolean;         // Enable pinning (default: true)
  enableReordering?: boolean;      // Enable reordering (default: true)
  editable?: boolean;              // Enable editing (default: false)
  
  // Custom rendering
  cell?: (props: {                // Custom cell renderer
    value: any;
    row: TData;
    column: Column<TData>;
  }) => ReactNode;
  
  header?: (props: {              // Custom header renderer
    column: Column<TData>;
    table: Table<TData>;
  }) => ReactNode;
  
  editor?: CellEditor<TData>;     // Custom cell editor
  
  // Styling
  cellClass?: string | ((row: TData) => string);
  headerClass?: string;
}

🎨 Features in Detail

Sorting

  • Click header to sort ascending → descending → unsorted
  • Hold Shift for multi-column sorting
  • Visual indicators show sort direction (↑ ascending, ↓ descending)
  • Access through column menu or header click

Filtering

Each column type has optimized filter UI:

  • Text: Contains filter with text input
  • Number: Range filter with min/max inputs
  • Date: Date range picker with from/to dates
  • Boolean: Dropdown with All/True/False options

Filter features:

  • Column header filter button with popover
  • Side panel for managing all filters
  • Clear individual or all filters
  • Visual indicator when filter is active (blue highlight)

Column Operations

Resizing

  • Drag column edge to resize
  • Respects min/max width constraints
  • Visual feedback during resize
  • Auto-size option in column menu

Reordering

  • Drag column header to reorder
  • Live preview: Entire column (header + data) moves in real-time
  • Visual feedback:
    • Dragged column becomes semi-transparent
    • Drop target shows blue highlight
    • Blue border indicates drop position
    • Move cursor on draggable columns

Pinning

  • Pin columns to left or right
  • Pinned columns stay visible during horizontal scroll
  • Visual separator between pinned and scrollable areas
  • Manage through column menu or columns panel

Row Selection

  • Checkbox column for multi-select mode
  • Click row for single-select mode
  • Keyboard support: Shift+click for range selection
  • Selection count in status bar
  • Export selected rows only

Cell Editing

  • Double-click or Enter to edit
  • Built-in editors for each column type
  • Custom editor support
  • Tab/Enter navigation between cells
  • Escape to cancel edit

🚀 Performance

Optimized for large datasets with:

  • Virtual scrolling: Only renders visible rows/columns
  • Memoization: Prevents unnecessary re-renders
  • Debounced operations: Filters, resizing
  • Efficient state updates: Granular updates
  • Lazy rendering: On-demand cell rendering

Tested with 10,000+ rows maintaining 60fps scrolling.

Performance Tips

// For very large datasets (10,000+ rows)
<DataGrid
  data={largeData}
  columns={columns}
  
  // Increase overscan for smoother scrolling
  overscanRows={10}
  overscanCols={3}
  
  // Disable features if not needed
  enableColumnReorder={false}
  
  // Use fixed row height
  rowHeight={40}
  
  // Provide getRowId for efficient updates
  getRowId={(row) => row.id}
/>

🎨 Theming

Customize appearance with CSS variables:

:root {
  /* Colors */
  --dg-primary: #2196f3;
  --dg-border: #e5e7eb;
  --dg-header-bg: #f9fafb;
  --dg-row-bg: white;
  --dg-row-hover: #f3f4f6;
  --dg-row-selected: #eff6ff;
  --dg-text: #374151;
  --dg-text-secondary: #6b7280;
  
  /* Sizing */
  --dg-row-height: 40px;
  --dg-header-height: 40px;
  --dg-font-size: 14px;
  
  /* Borders */
  --dg-border-width: 1px;
  --dg-border-style: solid;
  
  /* Animations */
  --dg-transition: all 0.2s ease;
}

/* Dark theme example */
[data-theme="dark"] {
  --dg-border: #374151;
  --dg-header-bg: #1f2937;
  --dg-row-bg: #111827;
  --dg-row-hover: #1f2937;
  --dg-text: #f3f4f6;
}

🛠️ Development

If you want to contribute to the library:

# Clone the repository
git clone https://github.com/dataset-sh/datagrid.git
cd datagrid

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Start Storybook
pnpm storybook

# Run tests
pnpm test

# Build library for production
pnpm build:lib

# Type check
pnpm typecheck

# Lint
pnpm lint

📦 Package Info

🏗️ Architecture

Built with modern React patterns:

  • Headless architecture with TanStack Table core
  • Composition pattern for extensibility
  • Context API for state management
  • Virtual scrolling with TanStack Virtual
  • Accessible components with Radix UI
  • Type-safe with TypeScript

🌐 Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • Mobile browsers (responsive)

🤝 Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add/update tests
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details

🙏 Acknowledgments

Built with excellent libraries: