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

@shaun1705/advanced-reusable-table

v1.0.11

Published

A powerful, customizable React table component with advanced features like sorting, filtering, grouping, and inline editing

Downloads

67

Readme

@shaun1705/advanced-reusable-table

npm version npm downloads bundle size TypeScript React License: MIT

The React table component that adapts to your data, not the other way around

A powerful, TypeScript-first React table component that handles complex data structures, offers dynamic content rendering, and provides enterprise-grade features while maintaining simplicity and accessibility.

Why Choose This Table?

Smart Data Handling - Automatically adapts to your data types with intelligent filtering, sorting, and display options

🎨 Dynamic Content - Single columns that render different content types based on data (text, collections, custom components)

🔧 Zero Config to Full Control - Works instantly with sensible defaults, scales to complex enterprise requirements

Accessibility First - WCAG 2.1 AA compliant with full keyboard navigation and screen reader support

📱 Performance Focused - Optimized for large datasets (1000+ rows) with efficient rendering and memory usage

✨ What's New in v1.0.9

🎯 Production-Ready API - Stable, well-tested interface with comprehensive TypeScript support

🏷️ Theme Support - Full theming system with CSS custom properties and built-in light/dark modes

🔧 Flexible Column Configuration - Comprehensive column configuration with multiple data types and rendering options

📦 Collection Data Types - Advanced support for checkboxes, chips, tags, and other collection types

⚙️ Advanced Row Selection - Single and multi-row selection with flexible configuration

🚀 Performance Optimized - Built for large datasets with efficient rendering and memory usage

WCAG 2.1 AA Compliant - Full accessibility support with keyboard navigation and screen reader compatibility

✨ What makes it special?

🧠 Dynamic Cell Rendering

Same column, different content types based on row data. Perfect for mixed content scenarios like process plans, user permissions, or dynamic forms.

{
  header: 'Comments',
  accessor: 'comments',
  renderCell: (context) => {
    if (Array.isArray(context.value)) {
      return {
        type: 'collection',
        collectionConfig: {
          type: 'checkbox',
          options: context.value.map(v => ({ value: v, label: v }))
        }
      };
    }
    if (typeof context.value === 'string') {
      return { type: 'text', content: `💬 ${context.value}` };
    }
    return { type: 'text', content: 'No comments' };
  }
}

📦 Collection Data Types

Handle multiple values elegantly with sophisticated UI controls - checkboxes, radio buttons, chips, and tags with flexible display modes.

{
  header: 'Permissions',
  accessor: 'permissions',
  dataType: 'collection',
  collectionConfig: {
    type: 'checkbox',
    inputMode: 'chips',        // Modern chip-based input
    viewDisplayMode: 'inline', // Show chips directly in cell
    options: [
      { value: 'read', label: 'View', description: 'Can view data' },
      { value: 'write', label: 'Edit', description: 'Can modify data' },
      { value: 'admin', label: 'Admin', description: 'Full control' }
    ]
  }
}

🎯 Type-Aware Filtering

Advanced filtering system with operators specific to each data type - text contains/equals, number ranges, date comparisons, and collection matching. All configured through viewConfig.filterConfig.

🔧 Inline Editing

Double-click cells to edit with full validation, supporting text, numbers, dates, toggles, and collection modifications. Updates handled through the onUpdateData callback.

Accessibility First

WCAG 2.1 AA compliant with comprehensive keyboard navigation, screen reader support, focus management, and ARIA attributes.

🎨 Fully Themeable

CSS custom properties with built-in light/dark mode support. Seamlessly integrate with your design system or use provided themes via ThemeProvider.

Performance Optimized

Built for large datasets with intelligent rendering, memoization, virtual scrolling support, and optimized re-renders.

📱 Responsive Design

Works seamlessly across desktop, tablet, and mobile devices with adaptive layouts and touch-friendly interactions.

🚀 Installation & Quick Start

npm install @shaun1705/advanced-reusable-table

Minimal Example - Simplest possible usage:

import { ReusableTable, ThemeProvider, Column } from '@shaun1705/advanced-reusable-table';

interface User {
  name: string;
  email: string;
}

const MinimalTable = () => {
  const columns: Column<User>[] = [
    { header: 'Name', accessor: 'name' },
    { header: 'Email', accessor: 'email' }
  ];

  const data: User[] = [
    { name: 'John Doe', email: '[email protected]' },
    { name: 'Jane Smith', email: '[email protected]' }
  ];

  return (
    <ThemeProvider theme="light">
      <ReusableTable allColumns={columns} data={data} />
    </ThemeProvider>
  );
};

That's it! No viewConfig required - the component auto-generates sensible defaults.


Basic Example - With viewConfig for more control:

import { ReusableTable, ThemeProvider, Column, ViewConfiguration } from '@shaun1705/advanced-reusable-table';

// 1. Define your data type
interface User {
  name: string;
  email: string;
  isActive: boolean;
}

const MyTable = () => {
  // 2. Define columns - each MUST have 'header' and 'accessor'
  const columns: Column<User>[] = [
    { header: 'Name', accessor: 'name', sortable: true, filterable: true },
    { header: 'Email', accessor: 'email', filterable: true },
    { header: 'Active', accessor: 'isActive', cellType: 'toggle', editable: true }
  ];

  // 3. Provide data
  const data: User[] = [
    { name: 'John Doe', email: '[email protected]', isActive: true },
    { name: 'Jane Smith', email: '[email protected]', isActive: false }
  ];

  // 4. Configure view - defines visible columns, sorting, filtering, grouping
  const viewConfig: ViewConfiguration<User> = {
    id: 'default',
    name: 'Default View',
    visibleColumns: ['name', 'email', 'isActive'],
    groupBy: [],        // Column keys to group by
    sortConfig: [],     // Initial sort configuration
    filterConfig: []    // Initial filter configuration
  };

  return (
    <ThemeProvider theme="light">
      <ReusableTable
        allColumns={columns}
        data={data}
        viewConfig={viewConfig}
      />
    </ThemeProvider>
  );
};

Advanced Example - Full feature showcase:

import {
  ReusableTable,
  ThemeProvider,
  useTableSelection,
  Column,
  ViewConfiguration
} from '@shaun1705/advanced-reusable-table';

interface Developer {
  name: string;
  skills: string[];
  department: string;
}

const AdvancedTable = () => {
  const data: Developer[] = [
    { name: 'Alex Chen', skills: ['react', 'vue'], department: 'Engineering' },
    { name: 'Sarah Wilson', skills: ['angular'], department: 'Design' }
  ];

  // Row selection hook - requires data and mode arguments
  const selection = useTableSelection<Developer>({
    data: data,
    mode: 'multiple'
  });

  const columns: Column<Developer>[] = [
    {
      header: 'Developer',
      accessor: 'name',
      filterType: 'text',
      sortable: true,
      filterable: true
    },
    {
      header: 'Skills',
      accessor: 'skills',
      dataType: 'collection',
      collectionConfig: {
        type: 'chips',
        inputMode: 'chips',
        viewDisplayMode: 'inline',
        options: [
          { value: 'react', label: 'React', color: '#61dafb' },
          { value: 'vue', label: 'Vue.js', color: '#4fc08d' },
          { value: 'angular', label: 'Angular', color: '#dd0031' }
        ]
      }
    },
    {
      header: 'Department',
      accessor: 'department',
      filterType: 'select',
      groupable: true
    }
  ];

  // Row selection configuration
  const rowSelection = {
    enabled: true,
    mode: 'multiple' as const,
    onSelectionChange: (rows: Developer[]) => {
      console.log('Selected rows:', rows);
    }
  };

  // View configuration - controls all table behavior
  const viewConfig: ViewConfiguration<Developer> = {
    id: 'advanced',
    name: 'Advanced View',
    visibleColumns: ['name', 'skills', 'department'],
    groupBy: ['department'],
    sortConfig: [{ key: 'name', direction: 'ascending' as const }],
    filterConfig: []
  };

  return (
    <ThemeProvider theme="dark">
      <div>
        <p>Selected: {selection.selectedCount} developers</p>
        <ReusableTable
          allColumns={columns}
          data={data}
          viewConfig={viewConfig}
          rowSelection={rowSelection}
          onUpdateData={(rowIndex, columnId, value) => {
            console.log('Data updated:', { rowIndex, columnId, value });
          }}
        />
      </div>
    </ThemeProvider>
  );
};

📋 Component API

Core Props

The ReusableTable component accepts only 5 props:

interface ReusableTableProps<T extends object> {
  allColumns: Column<T>[];           // All column definitions
  data: T[];                         // Data to display
  viewConfig?: ViewConfiguration<T>; // View configuration (optional, auto-generated if not provided)
  onUpdateData?: (rowIndex: number, columnId: keyof T, value: any) => void;  // Edit callback
  rowSelection?: RowSelectionProp<T>; // Row selection config (optional)
}

allColumns (required)

Array of column definitions. Each column configures how data is displayed and interacted with:

interface Column<T> {
  header: string;                    // Column header text (required)
  accessor: keyof T;                 // Data key (required)

  // Display configuration
  dataType?: 'string' | 'number' | 'currency' | 'date' | 'datetime' | 'collection';
  align?: 'left' | 'center' | 'right';
  cell?: (item: T) => React.ReactNode;  // Custom cell renderer

  // Feature toggles
  sortable?: boolean;                // Enable sorting
  filterable?: boolean;              // Enable filtering
  groupable?: boolean;               // Enable grouping
  editable?: boolean;                // Enable inline editing

  // Filter configuration
  filterType?: 'text' | 'select' | 'date' | 'number' | 'boolean' | 'collection';

  // Type-specific options
  cellType?: 'checkbox' | 'toggle';
  currencyOptions?: { locale: string; currency: string };
  dateOptions?: { locale: string; dateStyle?: string; timeStyle?: string };
  collectionConfig?: CollectionConfig;

  // Dynamic rendering
  renderCell?: (context: CellRenderContext<T>) => CellRenderDecision | React.ReactNode;
}

data (required)

Array of data objects matching your type definition. Can be empty array [].

viewConfig (optional, auto-generated if not provided)

Configuration that controls which columns are visible, sorting, filtering, and grouping. If not provided, the component will auto-generate a default view configuration showing all columns.

interface ViewConfiguration<T> {
  id?: string;                        // Unique view identifier (optional)
  name?: string;                      // Display name (optional)
  visibleColumns?: (keyof T)[];       // Which columns to show (optional, defaults to all columns)
  groupBy?: (keyof T)[];              // Columns to group by (optional, defaults to empty array)
  sortConfig?: SortConfig<T>[];       // Initial sorting (optional, defaults to empty array)
  filterConfig?: FilterConfig<T>[];   // Initial filters (optional, defaults to empty array)
}

Note: All properties of ViewConfiguration are optional. If you omit viewConfig entirely, the component uses sensible defaults with all columns visible.

onUpdateData (optional)

Callback for inline editing:

onUpdateData?: (rowIndex: number, columnId: keyof T, value: any) => void

rowSelection (optional)

Row selection configuration:

// New format (recommended)
interface RowSelectionConfig {
  enabled: boolean;
  mode: 'single' | 'multiple' | 'none';
  maxSelections?: number;
  onSelectionChange?: (selectedRows: any[]) => void;
}

// Usage
const rowSelection = {
  enabled: true,
  mode: 'multiple',
  onSelectionChange: (rows) => console.log('Selected:', rows)
};

🎯 Real-World Examples

Dynamic Content Types with renderCell

The renderCell function enables the same column to display different content types based on row data:

{
  header: 'Comments',
  accessor: 'comments',
  renderCell: (context) => {
    const { value, row } = context;

    // Array of process steps - show as checkboxes
    if (Array.isArray(value) && value.length > 0) {
      return {
        type: 'collection',
        collectionConfig: {
          type: 'checkbox',
          inputMode: 'traditional',
          viewDisplayMode: 'inline',
          options: value.map(step => ({ value: step, label: step }))
        }
      };
    }

    // Text comment - show as editable text
    if (typeof value === 'string' && value.trim()) {
      return { type: 'text', content: `💬 ${value}` };
    }

    // Empty state
    return { type: 'text', content: 'No comments' };
  }
}

User Management with Permissions

const userColumns: Column<User>[] = [
  {
    header: 'User',
    accessor: 'name',
    dataType: 'string',
    sortable: true,
    filterable: true,
    cell: (user) => (
      <div className="flex items-center space-x-3">
        <img src={user.avatar} className="w-8 h-8 rounded-full" />
        <div>
          <div className="font-medium">{user.name}</div>
          <div className="text-sm text-gray-500">@{user.username}</div>
        </div>
      </div>
    )
  },
  {
    header: 'Permissions',
    accessor: 'permissions',
    dataType: 'collection',
    collectionConfig: {
      type: 'checkbox',
      inputMode: 'traditional',
      viewDisplayMode: 'auto',
      options: [
        { value: 'read', label: 'View', description: 'Can view data' },
        { value: 'write', label: 'Edit', description: 'Can modify data' },
        { value: 'admin', label: 'Admin', description: 'Full control' }
      ],
      searchable: true,
      maxSelections: 10
    }
  }
];

Configuring Sorting and Filtering via viewConfig

All table features are configured through viewConfig, not props:

const viewConfig: ViewConfiguration<Product> = {
  id: 'products-view',
  name: 'Products',
  visibleColumns: ['name', 'price', 'category', 'inStock'],

  // Group by category
  groupBy: ['category'],

  // Sort by price descending, then name ascending
  sortConfig: [
    { key: 'price', direction: 'descending' },
    { key: 'name', direction: 'ascending' }
  ],

  // Filter to show only in-stock items over $100
  filterConfig: [
    { key: 'inStock', operator: 'equals', value: 'true' },
    { key: 'price', operator: 'gte', value: '100' }
  ]
};

⚠️ Common Pitfalls & Solutions

Pitfall 1: Missing Required ViewConfig Properties

❌ Wrong:

const viewConfig = {
  visibleColumns: ['name', 'email']  // Missing required properties!
};

✅ Correct:

const viewConfig: ViewConfiguration<User> = {
  id: 'my-view',           // Required - unique identifier
  name: 'My View',         // Required - display name
  visibleColumns: ['name', 'email'],
  groupBy: [],             // Required - empty array if no grouping
  sortConfig: [],          // Required - empty array if no sorting
  filterConfig: []         // Required - empty array if no filters
};

Pitfall 2: Column Accessor Mismatch

❌ Wrong:

interface User {
  name: string;
  email: string;
}

const columns = [
  { header: 'Name', accessor: 'userName' }  // 'userName' doesn't exist in User!
];

✅ Correct:

const columns: Column<User>[] = [
  { header: 'Name', accessor: 'name' }  // Matches User['name']
];

Pitfall 3: visibleColumns References Non-Existent Column

❌ Wrong:

const allColumns = [
  { header: 'Name', accessor: 'name' },
  { header: 'Email', accessor: 'email' }
];

const viewConfig = {
  visibleColumns: ['name', 'email', 'phone']  // 'phone' doesn't exist!
};

✅ Correct:

const viewConfig: ViewConfiguration<User> = {
  id: 'default',
  name: 'Default',
  visibleColumns: ['name', 'email'],  // Only reference existing columns
  groupBy: [],
  sortConfig: [],
  filterConfig: []
};

Quick Checklist Before Using ReusableTable

Column Definition:

  • Each column has both header (string) and accessor (keyof T)
  • All accessors match properties in your data type
  • TypeScript types are properly defined

View Configuration:

  • Has all required properties: id, name, visibleColumns, groupBy, sortConfig, filterConfig
  • visibleColumns only references columns that exist in allColumns
  • Empty arrays ([]) are used for optional config arrays

Data:

  • Is an array (can be empty)
  • Objects in array match your TypeScript interface
  • All required properties are present

Theme Provider:

  • Component is wrapped in <ThemeProvider theme="light"> or <ThemeProvider theme="dark">

🎨 Theming System

Simple Theme Setup

// Built-in themes
<ThemeProvider theme="light">    {/* Clean, professional light theme */}
<ThemeProvider theme="dark">     {/* Modern dark theme */}

// Custom theme object
const customTheme = {
  colors: {
    primary: '#6366f1',
    background: '#ffffff',
    text: '#1f2937'
  },
  borderRadius: '0.5rem'
};

<ThemeProvider theme={customTheme}>
  <ReusableTable {...props} />
</ThemeProvider>

CSS Custom Properties

:root {
  --table-color-primary: #6366f1;
  --table-color-background: #ffffff;
  --table-color-surface: #f8fafc;
  --table-color-text: #1f2937;
  --table-color-border: #e5e7eb;
  --table-border-radius: 0.375rem;
}

🔧 Complete Feature Matrix

| Feature | How It Works | Status | |---------|-------------|--------| | Dynamic Rendering | Configure via column.renderCell | ✅ Complete | | Collection Data | Configure via column.collectionConfig | ✅ Complete | | Advanced Filtering | Configure via viewConfig.filterConfig | ✅ Complete | | Inline Editing | Enable via column.editable + onUpdateData | ✅ Complete | | Multi-Column Sorting | Configure via viewConfig.sortConfig | ✅ Complete | | Grouping | Configure via viewConfig.groupBy | ✅ Complete | | Row Selection | Configure via rowSelection prop | ✅ Complete | | Theming | Configure via ThemeProvider | ✅ Complete | | Accessibility | WCAG 2.1 AA compliant | ✅ Complete | | TypeScript | Full type safety and IntelliSense | ✅ Complete | | Performance | Optimized for 1000+ rows | ✅ Complete |

📊 Bundle Size & Performance

Lightweight & Fast - Only pay for what you use with full tree-shaking support:

| Import | Gzipped Size | Tree Shakeable | Use Case | |--------|--------------|----------------|----------| | Core Table | ~15KB | ✅ Yes | Basic tables & sorting | | + Collections | ~8KB | ✅ Yes | Checkboxes, chips, tags | | + All Features | ~28KB | ✅ Yes | Full enterprise features |

Performance Benchmarks (tested with React 18 & 19):

  • 1000+ rows with smooth scrolling
  • Sub-100ms filter/sort operations
  • <50ms column rendering
  • Zero layout shift with optimized re-renders
  • Mobile optimized with touch-friendly interactions

🏗️ Architecture & Design

Built with modern React patterns and enterprise requirements:

  • 🔧 Functional Components with comprehensive hooks
  • 📘 TypeScript for complete type safety
  • 🧩 Composition over inheritance patterns
  • ⚡ Performance optimizations with React.memo and useMemo
  • ♿ Accessibility built-in from the ground up (WCAG 2.1 AA)
  • 🧪 Testable architecture with comprehensive test coverage
  • 📱 Responsive mobile-first design
  • 🎨 Themeable via CSS custom properties

🌍 Browser Support

  • Modern Browsers: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
  • React: 18.0+ or 19.0+
  • TypeScript: 4.5+ (recommended but not required)
  • Node.js: 16+ for development

🔄 Server-Side Rendering (SSR) Support

✅ Full SSR Compatibility - Works seamlessly with Next.js, Remix, and other SSR frameworks (v1.0.11+)

Next.js App Router

The component works out-of-the-box with Next.js 13+ App Router:

// app/users/page.tsx
import { ReusableTable, ThemeProvider, Column } from '@shaun1705/advanced-reusable-table';

interface User {
  name: string;
  email: string;
}

export default function UsersPage() {
  const columns: Column<User>[] = [
    { header: 'Name', accessor: 'name' },
    { header: 'Email', accessor: 'email' }
  ];

  const data: User[] = [
    { name: 'John Doe', email: '[email protected]' }
  ];

  return (
    <ThemeProvider theme="light">
      <ReusableTable allColumns={columns} data={data} />
    </ThemeProvider>
  );
}

Next.js Pages Router

Works with both SSR and SSG:

// pages/users.tsx
import { ReusableTable, ThemeProvider, Column } from '@shaun1705/advanced-reusable-table';
import type { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async () => {
  const data = await fetchUsers(); // Your data fetching logic
  return { props: { data } };
};

export default function UsersPage({ data }) {
  const columns: Column<User>[] = [
    { header: 'Name', accessor: 'name' },
    { header: 'Email', accessor: 'email' }
  ];

  return (
    <ThemeProvider theme="light">
      <ReusableTable allColumns={columns} data={data} />
    </ThemeProvider>
  );
}

SSR Compatibility Notes

  • v1.0.11+: Full SSR support with stable ID generation (no hydration mismatches)
  • v1.0.10 and earlier: Required client-side only rendering (see workaround below)

Workaround for v1.0.10 and Earlier

If using v1.0.10 or earlier, use dynamic import with SSR disabled:

import dynamic from 'next/dynamic';

const ReusableTable = dynamic(
  () => import('@shaun1705/advanced-reusable-table').then(mod => mod.ReusableTable),
  { ssr: false }
) as typeof import('@shaun1705/advanced-reusable-table').ReusableTable;

Recommendation: Upgrade to v1.0.11+ for full SSR support without workarounds.

🔄 Migration & Alternatives

Why developers are switching to this table:

| From Library | Advantages | Migration Effort | |-------------|-----------|------------------| | react-table | ✅ Dynamic rendering ✅ Collections ✅ Simpler API | 🟢 Easy - Similar patterns | | Ant Design Table | ✅ Better TypeScript ✅ Lighter bundle ✅ Collection types | 🟡 Medium - Different API | | Material-UI DataGrid | ✅ No license fees ✅ Better accessibility ✅ Simpler API | 🟡 Medium - Worth the switch | | AG Grid Community | ✅ No restrictions ✅ Modern React patterns ✅ Dynamic content | 🟢 Easy - Feature parity |

What makes this table special:

  • 🎯 Unique Features - Dynamic cell rendering and collection types not found elsewhere
  • 🪶 Lightweight - 28KB total vs 200KB+ for comparable enterprise solutions
  • Accessibility First - WCAG 2.1 AA compliance built-in, not an afterthought
  • 🔧 Modern React - Hooks-first design with React 18/19 support
  • 🎨 Simple API - Configure everything through 5 props, not dozens

📚 Complete Documentation

🚀 Getting Started

🎛️ Configuration

📖 Feature Guides

🏗️ Advanced Topics

🎨 Examples

🤝 Contributing & Support

We welcome contributions! Please see our Contributing Guide for details on development setup, testing, and PR guidelines.

Need Help?

📄 License

MIT Licensed - Free for personal and commercial use. See LICENSE for details.

🚀 Quick Links

| Resource | Link | Description | |----------|------|-------------| | 📦 NPM Package | npmjs.com | Install and version info | | 💻 GitHub Repo | github.com | Source code and issues | | 📖 Full Documentation | ./docs/ | Complete API reference | | 🎮 Live Examples | ./examples/ | Interactive demos | | 🔄 Changelog | CHANGELOG.md | Release history |


Built with ❤️ for the React community

Supporting modern React applications with enterprise-grade data table functionality

⭐ Star on GitHub📦 View on NPM📖 Read the Docs