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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@21jumpclick/data-table

v1.0.0-beta.14

Published

Custom data table made with MUI and TanStack table

Downloads

53

Readme

21 DataTable

🚀 A powerful and customizable React data table library built with Material-UI and TanStack Table, designed to handle everything from simple data display to complex enterprise-grade table requirements.

npm version TypeScript License: MIT

🎯 Why Choose 21 DataTable?

All-in-one solution - From basic data display to advanced enterprise features, this library provides everything you need for modern data tables without the complexity.

⚡ Ready-to-use Components

  • BasicDataTable - Perfect for static data with client-side operations
  • ClientDataTable - Integrates seamlessly with React Query for data fetching
  • ServerDataTable - Handles server-side pagination, sorting, and filtering

🎨 Advanced Features Out of the Box

  • Smart column management - Sorting, filtering, grouping, aggregation, pinning, resizing
  • Intelligent search - Global search + advanced smart filters
  • Modern UX - Loading states, pagination, row selection, hover effects
  • Developer-friendly - TypeScript support, extensive customization, URL state sharing

📦 Quick Installation

npm install @21jumpclick/data-table

Required peer dependencies:

npm install @mui/material @mui/icons-material @emotion/react @emotion/styled
npm install @tanstack/react-table @tanstack/react-query  # For ClientDataTable/ServerDataTable

🚀 Quick Start

1. Setup the Provider

import { DataTableProvider, frTranslations } from '@21jumpclick/data-table';
import { ThemeProvider } from '@mui/material';

function App() {
  return (
    <ThemeProvider theme={yourTheme}>
      <DataTableProvider values={{
        translations: frTranslations, // or enTranslations
        columnTypeDefs: [], // Your custom column types
        // ... other global options
      }}>
        <YourApp />
      </DataTableProvider>
    </ThemeProvider>
  );
}

2. Create Your First Table

import { BasicDataTable } from '@21jumpclick/data-table';
import type { ColumnDef } from '@tanstack/react-table';

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

const columns: ColumnDef<User>[] = [
  { accessorKey: 'name', header: 'Name' },
  { accessorKey: 'email', header: 'Email' },
  { accessorKey: 'role', header: 'Role' },
];

function UsersTable() {
  return (
    <BasicDataTable
      columns={columns}
      data={users}
      enableRowSelection
      onRowClick={(row) => console.log('Clicked:', row)}
    />
  );
}

📊 Table Variants

BasicDataTable - Static Data

Perfect for displaying arrays of data with all features handled client-side.

<BasicDataTable
  columns={columns}
  data={staticData}
  isLoading={false}
/>

ClientDataTable - React Query Integration

Handles data fetching with React Query, processes all features client-side.

<ClientDataTable
  columns={columns}
  useTableQuery={() => useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers
  })}
/>

ServerDataTable - Server-Side Processing

Delegates pagination, sorting, and filtering to your backend for optimal performance.

<ServerDataTable
  columns={columns}
  useTableQuery={(params) => useQuery({
    queryKey: ['users', params],
    queryFn: () => fetchUsersFromServer(params)
  })}
/>

🎨 Theming & Customization

Built-in Themes

Choose from pre-designed themes or create your own:

import { 
  borderedThemeOptions,
  strippedThemeOptions, 
  mergeThemeOptions 
} from '@21jumpclick/data-table';

const customThemeOptions = mergeThemeOptions(
  borderedThemeOptions,    // Add borders
  strippedThemeOptions,    // Alternate row colors
  {
    // Your custom overrides
    components: {
      DTTableRow: {
        styleOverrides: {
          root: ({ theme }) => ({
            '&:hover': {
              backgroundColor: theme.palette.action.hover,
            },
          }),
        },
      },
    },
  }
);

💡 Pro tip: Use mergeThemeOptions to properly combine theme functions - it handles styleOverrides function merging automatically!

Complete Theme Example

See our comprehensive theme implementation with light/dark mode support.

🔧 Advanced Features

Column Types - Smart Column Formatting

Column types provide automatic formatting and behavior for specific data types. Instead of manually configuring each column, simply specify a columnType and get intelligent defaults.

Built-in Column Types

const columns: ColumnDef<Product>[] = [
  {
    accessorKey: 'name',
    header: 'Product Name',
    columnType: 'string' // Default string handling
  },
  {
    accessorKey: 'price',
    header: 'Price',
    columnType: 'currency' // Automatic currency formatting
  },
  {
    accessorKey: 'quantity',
    header: 'Stock',
    columnType: 'number' // Number formatting with aggregation
  },
  {
    accessorKey: 'releaseDate',
    header: 'Release Date',
    columnType: 'date' // Date formatting and date-specific filters
  },
  {
    accessorKey: 'isActive',
    header: 'Active',
    columnType: 'boolean' // Boolean display with true/false filters
  },
  {
    accessorKey: 'createdAt',
    header: 'Created',
    columnType: 'dateTime' // Date and time formatting
  }
];

Creating Custom Column Types

Create reusable column types for your specific data structures:

// Example: Custom tags column type
import type { ColumnTypeDef } from '@21jumpclick/data-table';

export const tagsTypeDef: ColumnTypeDef<{ tags: string[] }> = {
  type: 'tags',
  cell: ({ getValue }) => {
    const tags = getValue() as string[];
    return (
      <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
        {tags.map(tag => (
          <Chip key={tag} label={tag} size="small" />
        ))}
      </div>
    );
  },
  enableSorting: false,
  enableAggregation: false
  // ...
};

// Register in DataTableProvider
<DataTableProvider values={{
  columnTypeDefs: [tagsTypeDef],
  // ...
}}>

Then use it in your columns:

{
  accessorKey: 'myTags',
  header: 'My Tags',
  columnType: 'tags' // Uses your custom type
}

Real examples:

Smart Filters - Advanced Column Filtering

Smart filters provide intelligent, type-aware filtering interfaces that understand your data structure. The system works through two main components: Column Types that define which filters are allowed, and Smart Filter Items that implement the actual filtering logic.

How Smart Filters Work

  1. Column Types define which smart filter operations are allowed via allowedSmartFilters
  2. Smart Filter Items implement the filtering logic and UI components
  3. Users can apply multiple smart filters per column through the UI

Built-in Smart Filters

Smart filters are automatically available based on column types:

// String columns get text-based filters:
// - "contains", "equals", "startsWith", "endsWith", "isEmpty", "isNotEmpty"

// Number columns get numeric filters:
// - "equals", "greaterThan", "lessThan", "between", "isEmpty", "isNotEmpty"

// Date columns get date-specific filters:
// - "equals", "before", "after", "between", "isEmpty", "isNotEmpty"

// Boolean columns get boolean filters:
// - "equals" (true/false), "isEmpty", "isNotEmpty"

Creating Custom Smart Filters

Build domain-specific filters for complex data types:

import type { SmartFilterItem } from '@21jumpclick/data-table';

// Step 1: Create the smart filter item
export const userSmartFilterItem: SmartFilterItem = {
  // React component for the filter UI
  component: ({ value, onChange }) => {
    const users = useUsersFromTable(); // Get unique users from table data
    
    return (
      <Autocomplete
        value={value}
        onChange={(_, newValue) => onChange(newValue)}
        options={users}
        getOptionLabel={(user) => user.name}
        renderInput={(params) => (
          <TextField {...params} label="Select User" />
        )}
      />
    );
  },
  
  // Filter logic
  filterFn: (row, columnId, filterValue) => {
    const user = row.getValue(columnId);
    return user?.id === filterValue?.id;
  },
  
  // Display formatter for selected filter
  valueFormatter: (user) => user?.name || '',
  
  // Template for filter chip display
  label: 'User is {{value}}'
};

// Step 2: Register in DataTableProvider
<DataTableProvider values={{
  smartFilterItems: {
    isEqualUser: userSmartFilterItem // Key becomes the operation name
  },
}} />

// Step 4: Use in your columns
{
  accessorKey: 'assignedUser',
  header: 'Assigned To',
  allowedSmartFilters: ['isEqualUser'] // Define allowedSmartFilters for current column
}

Advanced Smart Filter Features

Multiple Filters per Column: Users can apply multiple smart filters to the same column - they are combined with AND logic.

Custom Value Formatters: Format complex values for display in filter chips:

// Single value
valueFormatter: (user) => user?.name || ''

// Multiple values (for "between" filters)
valueFormatter: (values) => values.map(v => v.toString())

Filter Function Helpers: Smart filters can implement resolveFilterValue for preprocessing:

filterFn: (row, columnId, filterValue) => {
  // Your filtering logic
},
resolveFilterValue: (value) => {
  // Preprocess the value before filtering
  return value?.toLowerCase();
}

Real example: User Smart Filter - Autocomplete filter for user objects

Programmatic Control - Table Instance Access

Access the underlying TanStack Table instance and DOM elements for advanced control:

import { useRef } from 'react';
import type { ClientDataTableRef } from '@21jumpclick/data-table';

function AdvancedTable() {
  const tableRef = useRef<ClientDataTableRef<User>>(null);

  const handleExportData = () => {
    // Get filtered and sorted data
    const table = tableRef.current?.table;
    const filteredRows = table?.getFilteredRowModel().rows;
    const data = filteredRows?.map(row => row.original);
    
    // Export logic here
    exportToCsv(data);
  };

  const handleResetFilters = () => {
    const table = tableRef.current?.table;
    table?.resetGlobalFilter();
    table?.resetColumnFilters();
    table?.resetSorting();
    // Reset smart filters
    table?.setSmartFilters([]);
  };

  const handleScrollToTop = () => {
    tableRef.current?.elementsRef.current?.tableRef.current?.scrollIntoView();
  };

  return (
    <>
      <div>
        <Button onClick={handleExportData}>Export Filtered Data</Button>
        <Button onClick={handleResetFilters}>Reset All Filters</Button>
        <Button onClick={handleScrollToTop}>Scroll to Top</Button>
      </div>
      
      <ClientDataTable
        ref={tableRef}
        columns={columns}
        useTableQuery={useUsersQuery}
        additionalTools={{
          end: [() => <Button onClick={handleExportData}>Export</Button>]
        }}
      />
    </>
  );
}

Available Ref Properties

interface ClientDataTableRef<T> {
  // TanStack Table instance - full table control
  table: Table<T>;
  
  // React Query result - data and loading states
  query: UseQueryResult<T[]>;
  
  // DOM element references
  elementsRef: {
    tableRef: RefObject<HTMLDivElement>;      // Table container
    toolbarRef: RefObject<HTMLDivElement>;    // Toolbar
    containerRef: RefObject<HTMLDivElement>;  // Full component
    paginationRef: RefObject<HTMLDivElement>; // Pagination
  };
}

Column Features Configuration

Fine-tune each column's behavior with detailed options:

const columns: ColumnDef<Product>[] = [
  {
    accessorKey: 'name',
    header: 'Product Name',
    columnType: 'string',
    
    // Aggregation control
    enableAggregation: true,
    aggregationFn: 'count',
    
    // Smart filter control (inherited from columnType, can be overridden)
    enableSmartFilter: true,
    
    // Column sizing
    size: 200,
    minSize: 100,
    maxSize: 400,
    
    // Pinning
    enablePinning: true,
    
    // Sorting
    enableSorting: true,
    sortDescFirst: false,
    
    // Filtering
    enableColumnFilter: true,
    enableGlobalFilter: true
  }
];

State Management & URL Sharing

Control table state and enable URL sharing for bookmarkable table states:

<BasicDataTable
  columns={columns}
  data={data}
  
  // Enable URL state persistence
  enableQueryParams={true}
  
  // Initial state
  pagination={{ pageIndex: 0, pageSize: 25 }}
  sortBy={[{ id: 'name', desc: false }]}
  smartFilters={[
    { field: 'status', value: 'active', type: 'equals' }
  ]}
  columnPinning={{ left: ['name'], right: ['actions'] }}
  visibility={{ internalId: false }}
  
  // State change handlers
  onPaginationChange={(pagination) => {
    console.log('Pagination changed:', pagination);
  }}
  onSortingChange={(sorting) => {
    console.log('Sorting changed:', sorting);
  }}
/>

Server-Side Integration

For ServerDataTable, implement server endpoints that handle the query parameters:

// Frontend
<ServerDataTable
  columns={columns}
  useTableQuery={(params) => 
    useQuery({
      queryKey: ['products', params],
      queryFn: () => fetchProducts(params)
    })
  }
/>

// Backend integration example
interface TableQuery {
  offset?: number;        // Skip N rows
  limit?: number;         // Take N rows
  search?: string;        // Global search term
  order?: 'asc' | 'desc' | null; // Sort direction
  orderBy?: string;       // Sort column
  filters?: Filter[];     // Column-specific filters (including smart filters)
}

interface Filter {
  field: string;          // Column identifier
  value: any;             // Filter value
  type: string;           // Filter operation (equals, contains, isEqualUser, etc.)
}

// Your API should return:
interface TableResult<T> {
  data: T[];              // Current page data
  count: number;          // Total records (for pagination)
}

🌍 Internationalization

Full i18n support with multiple localization layers:

import { frTranslations, enTranslations } from '@21jumpclick/data-table';
import { fr } from 'date-fns/locale';
import { frFR } from '@mui/material/locale';

<DataTableProvider values={{
  translations: frTranslations,        // UI labels
  dateFnsLocale: fr,                   // Date formatting
  i18nLocale: 'fra',                   // ISO 639-2 code
}}>
  <ThemeProvider theme={createTheme({}, frFR)}> {/* MUI locale */}
    <YourApp />
  </ThemeProvider>
</DataTableProvider>

📋 Feature Matrix

| Feature | BasicDataTable | ClientDataTable | ServerDataTable | |---------|---------------|-----------------|------------| | Column sorting | ✅ | ✅ | ✅ | | Column filtering | ✅ | ✅ | ✅| | Global search | ✅ | ✅ | ✅| | Pagination | ✅ | ✅ | ✅| | Smart filters | ✅ | ✅ | ✅| | Row selection | ✅ | ✅ | ✅ | | Column grouping | ✅ | ✅ | ✅ | | Column aggregation | ✅ | ✅ | ✅ | | Column pinning | ✅ | ✅ | ✅ | | URL state sharing | ✅ | ✅ | ✅ | | Loading states | - | ✅ | ✅ | | Refresh button | - | ✅ | ✅ |

🔗 TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type { 
  ColumnDef,
  BasicDataTableProps,
  ClientDataTableRef,
  DefaultTableState 
} from '@21jumpclick/data-table';

// All components are fully typed
// IntelliSense works out of the box
// Type-safe column definitions
// Proper ref typing

📚 Examples & Documentation

🛠 Built With

📄 License

MIT © 21JumpClick


Ready to build amazing data tables? Start with our Quick Start guide or explore the live examples to see all features in action! 🚀