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

@ackplus/react-tanstack-data-table

v1.0.35

Published

A powerful React data table component built with MUI and TanStack Table

Readme

@ackplus/react-tanstack-data-table

A powerful, feature-rich, and highly customizable React data table component built with Material-UI (MUI) and TanStack Table. Perfect for building modern data-intensive applications with advanced table functionality.

🚀 Live Demo

View Live Demo

Experience all the features in action with our interactive demo showcasing advanced table functionality, filtering, sorting, pagination, and more.

✨ Features

  • 🚀 High Performance: Built on TanStack Table for excellent performance with large datasets
  • 🎨 Material Design: Beautiful UI components using MUI with consistent design system
  • 📱 Responsive: Mobile-friendly responsive design with adaptive layouts
  • 🔍 Advanced Filtering: Global search, column filters, and filter components
  • 📊 Multi-Column Sorting: Powerful sorting with multiple columns support
  • 📄 Flexible Pagination: Client-side and server-side pagination options
  • 🎯 Column Management: Show/hide, resize, reorder, and pin columns
  • 📤 Data Export: Export to CSV/Excel with progress tracking and customization
  • 🖱️ Row Selection: Single and multi-row selection with bulk actions
  • Virtualization: Handle large datasets efficiently with row virtualization
  • 🔄 Server Integration: Built-in support for server-side operations
  • 🎛️ Highly Customizable: Extensive customization through slots and props
  • 📝 TypeScript: Full TypeScript support with comprehensive type definitions
  • 🔌 Extensible: Plugin architecture with custom components and hooks
  • 🛠️ Debug Logging: Configurable console instrumentation with global or per-table controls

📦 Installation

npm install @ackplus/react-tanstack-data-table
yarn add @ackplus/react-tanstack-data-table
pnpm add @ackplus/react-tanstack-data-table

🔧 Peer Dependencies

Make sure you have the following peer dependencies installed:

npm install @emotion/react @emotion/styled @mui/icons-material @mui/material @tanstack/react-table @tanstack/react-virtual react react-dom

🚀 Quick Start

import React from 'react';
import { DataTable } from '@ackplus/react-tanstack-data-table';
import { createColumnHelper } from '@tanstack/react-table';

interface User {
  id: number;
  name: string;
  email: string;
  status: 'active' | 'inactive';
  role: string;
}

const columnHelper = createColumnHelper<User>();

const columns = [
  columnHelper.accessor('name', {
    header: 'Name',
    size: 150,
  }),
  columnHelper.accessor('email', {
    header: 'Email',
    size: 200,
  }),
  columnHelper.accessor('status', {
    header: 'Status',
    cell: ({ getValue }) => (
      <Chip 
        label={getValue()} 
        color={getValue() === 'active' ? 'success' : 'default'} 
      />
    ),
  }),
  columnHelper.accessor('role', {
    header: 'Role',
    size: 120,
  }),
];

const data: User[] = [
  { id: 1, name: 'John Doe', email: '[email protected]', status: 'active', role: 'Admin' },
  { id: 2, name: 'Jane Smith', email: '[email protected]', status: 'inactive', role: 'User' },
  // ... more data
];

function MyDataTable() {
  return (
    <DataTable
      columns={columns}
      data={data}
      enableSorting
      enableGlobalFilter
      enablePagination
      enableRowSelection
      enableColumnVisibility
      enableExport
    />
  );
}

📋 Core Props

Basic Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | columns | DataTableColumn<T>[] | Required | Column definitions array | | data | T[] | [] | Array of data objects | | idKey | keyof T | 'id' | Unique identifier key for rows | | loading | boolean | false | Loading state indicator | | emptyMessage | string | 'No data available' | Message when no data |

Data Management

| Prop | Type | Default | Description | |------|------|---------|-------------| | dataMode | 'client' \| 'server' | 'client' | Data management mode | | initialLoadData | boolean | true | Load data on component mount | | onFetchData | (filters) => Promise<{data, total}> | - | Server-side data fetching | | onDataStateChange | (state) => void | - | Called when table state changes | | totalRow | number | 0 | Total rows for server-side pagination |

Selection & Interaction

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableRowSelection | boolean \| ((row) => boolean) | false | Enable row selection | | enableMultiRowSelection | boolean | true | Allow multiple row selection | | selectMode | 'page' \| 'all' | 'page' | Selection scope (page or all data) | | isRowSelectable | (params: {row: T, id: string}) => boolean | - | Control if specific row is selectable | | onSelectionChange | (selection: SelectionState) => void | - | Selection state change callback | | enableBulkActions | boolean | false | Enable bulk actions toolbar | | bulkActions | (selectionState: SelectionState) => ReactNode | - | Custom bulk actions component |

Selection State

The SelectionState interface provides detailed information about the current selection:

interface SelectionState {
  ids: string[];           // Array of selected/excluded row IDs
  type: 'include' | 'exclude';  // Selection mode
}
  • Include mode: ids contains the selected row IDs
  • Exclude mode: ids contains the excluded row IDs (all others are selected)

This allows for efficient handling of large datasets where you might select "all except these few".

Pagination

| Prop | Type | Default | Description | |------|------|---------|-------------| | enablePagination | boolean | true | Enable pagination | | paginationMode | 'client' \| 'server' | 'client' | Pagination mode | | onPaginationChange | (pagination: PaginationState) => void | - | Pagination change callback | | initialState.pagination | {pageIndex: number, pageSize: number} | {pageIndex: 0, pageSize: 50} | Initial pagination state |

Filtering & Search

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableGlobalFilter | boolean | true | Enable global search | | enableColumnFilter | boolean | false | Enable individual column filters | | filterMode | 'client' \| 'server' | 'client' | Filtering mode | | onColumnFiltersChange | (filterState: ColumnFilterState) => void | - | Column filters change callback | | onGlobalFilterChange | (globalFilter: string) => void | - | Global filter change callback | | onColumnFilterChange | (columnFilter: ColumnFilterState) => void | - | Column filter change callback | | extraFilter | ReactNode | - | Additional filter components |

Sorting

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableSorting | boolean | true | Enable column sorting | | sortingMode | 'client' \| 'server' | 'client' | Sorting mode | | onSortingChange | (sorting) => void | - | Sorting change callback |

Column Management

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableColumnVisibility | boolean | true | Show/hide columns control | | enableColumnResizing | boolean | false | Allow column resizing | | columnResizeMode | ColumnResizeMode | 'onChange' | Column resize mode | | enableColumnPinning | boolean | false | Allow column pinning | | enableColumnDragging | boolean | false | Enable column reordering | | onColumnDragEnd | (order: string[]) => void | - | Column reorder callback | | onColumnPinningChange | (pinning: ColumnPinningState) => void | - | Column pinning callback |

Export Features

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableExport | boolean | true | Enable data export | | exportFilename | string | 'export' | Default export filename | | onExportProgress | (progress: {processedRows?, totalRows?, percentage?}) => void | - | Export progress callback | | onExportComplete | (result: {success: boolean, filename: string, totalRows: number}) => void | - | Export completion callback | | onExportError | (error: {message: string, code: string}) => void | - | Export error callback | | onServerExport | (filters?: Partial<TableState>, selection?: SelectionState) => Promise<{data: any[], total: number}> | - | Server-side export handler | | onExportCancel | () => void | - | Export cancellation callback |

Expandable Rows (Enhanced Slot System)

Expandable rows are now fully integrated with the enhanced slot system, providing better customization and type safety.

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableExpanding | boolean | false | Enable row expansion | | getRowCanExpand | (row) => boolean | - | Determine if row can expand | | renderSubComponent | (row) => ReactNode | - | Render expanded row content |

The expanding column is automatically added and can be customized through slotProps.expandColumn (see Special Column Configuration section above).

Styling & Layout

| Prop | Type | Default | Description | |------|------|---------|-------------| | tableSize | 'small' \| 'medium' | 'medium' | Table size/density | | enableHover | boolean | true | Row hover effects | | enableStripes | boolean | false | Alternating row colors | | fitToScreen | boolean | true | Fit table to container width | | enableStickyHeaderOrFooter | boolean | false | Sticky header/footer | | maxHeight | string \| number | '400px' | Max table height | | tableContainerProps | object | {} | Props for table container | | tableProps | object | {} | Props for table element |

Virtualization

| Prop | Type | Default | Description | |------|------|---------|-------------| | enableVirtualization | boolean | false | Enable row virtualization | | estimateRowHeight | number | 52 | Estimated row height for virtualization |

Advanced Customization

| Prop | Type | Default | Description | |------|------|---------|-------------| | slots | Partial<DataTableSlots<T>> | {} | Custom component slots | | slotProps | PartialSlotProps<T> | {} | Props for slot components | | initialState | Partial<TableState> | {} | Initial table state | | skeletonRows | number | 5 | Number of skeleton rows for loading state | | footerFilter | ReactNode | - | Additional filter components in footer |

Special Column Configuration (Enhanced Slot System)

Special columns (selection and expanding) are now handled through the enhanced slot system, providing better customization and type safety.

Selection Column Configuration

The selection column is automatically added when enableRowSelection is true and can be customized through slotProps.selectionColumn:

<DataTable
  data={data}
  columns={columns}
  enableRowSelection
  enableMultiRowSelection
  slotProps={{
    selectionColumn: {
      width: 80,
      pinLeft: true,
      id: 'custom-selection',
      // Custom column configuration
      header: ({ table }) => (
        <Checkbox
          checked={table.getIsAllRowsSelected()}
          indeterminate={table.getIsSomeRowsSelected()}
          onChange={() => table.toggleAllRowsSelected()}
          sx={{ color: 'primary.main' }}
        />
      ),
      cell: ({ row, table }) => (
        <Checkbox
          checked={table.getIsRowSelected(row.id)}
          onChange={() => table.toggleRowSelected(row.id)}
          sx={{ color: 'secondary.main' }}
        />
      ),
    },
  }}
/>

Expanding Column Configuration

The expanding column is automatically added when enableExpanding is true and can be customized through slotProps.expandColumn:

<DataTable
  data={data}
  columns={columns}
  enableExpanding
  getRowCanExpand={(row) => row.original.details != null}
  renderSubComponent={(row) => (
    <Box p={2}>
      <Typography variant="h6">Details</Typography>
      <pre>{JSON.stringify(row.original.details, null, 2)}</pre>
    </Box>
  )}
  slotProps={{
    expandColumn: {
      width: 60,
      pinLeft: true,
      id: 'custom-expand',
      // Custom column configuration
      header: 'Expand',
      cell: ({ row }) => (
        <IconButton
          onClick={row.getToggleExpandedHandler()}
          size="small"
          sx={{ color: 'primary.main' }}
        >
          {row.getIsExpanded() ? <ExpandLessIcon /> : <ExpandMoreIcon />}
        </IconButton>
      ),
    },
  }}
/>

Advanced Special Column Customization

You can completely replace the special column components using the slots system:

import { createSelectionColumn, createExpandingColumn } from '@ackplus/react-tanstack-data-table';

function CustomTable() {
  // Create custom selection column
  const customSelectionColumn = createSelectionColumn({
    width: 100,
    pinLeft: true,
    header: ({ table }) => (
      <Tooltip title="Select All">
        <Checkbox
          checked={table.getIsAllRowsSelected()}
          indeterminate={table.getIsSomeRowsSelected()}
          onChange={() => table.toggleAllRowsSelected()}
          sx={{ 
            color: 'primary.main',
            '&.Mui-checked': { color: 'primary.main' }
          }}
        />
      </Tooltip>
    ),
    cell: ({ row, table }) => (
      <Tooltip title="Select Row">
        <Checkbox
          checked={table.getIsRowSelected(row.id)}
          onChange={() => table.toggleRowSelected(row.id)}
          sx={{ 
            color: 'secondary.main',
            '&.Mui-checked': { color: 'secondary.main' }
          }}
        />
      </Tooltip>
    ),
  });

  // Create custom expanding column
  const customExpandingColumn = createExpandingColumn({
    width: 80,
    pinLeft: true,
    header: 'Details',
    cell: ({ row }) => (
      <Tooltip title={row.getIsExpanded() ? "Collapse" : "Expand"}>
        <IconButton
          onClick={row.getToggleExpandedHandler()}
          size="small"
          sx={{ 
            color: 'primary.main',
            transition: 'transform 0.2s',
            transform: row.getIsExpanded() ? 'rotate(180deg)' : 'rotate(0deg)',
          }}
        >
          <KeyboardArrowDownIcon />
        </IconButton>
      </Tooltip>
    ),
  });

  return (
    <DataTable
      data={data}
      columns={[customSelectionColumn, customExpandingColumn, ...columns]}
      enableRowSelection
      enableExpanding
      // ... other props
    />
  );
}

Special Column Configuration Options

| Property | Type | Default | Description | |----------|------|---------|-------------| | width | number | 60 | Column width in pixels | | pinLeft | boolean | false | Pin column to the left | | id | string | Auto-generated | Custom column ID | | header | ReactNode \| (props) => ReactNode | Default header | Custom header component | | cell | (props) => ReactNode | Default cell | Custom cell component | | sx | SxProps | {} | Custom styling | | className | string | - | Custom CSS class | | style | CSSProperties | - | Custom inline styles |

Utility Functions for Special Columns

The library provides utility functions to create custom special columns:

Note: Special columns are now handled through the enhanced slot system instead of table props. This provides better type safety, more customization options, and consistent behavior with the rest of the component system.

import { createSelectionColumn, createExpandingColumn } from '@ackplus/react-tanstack-data-table';

// Create a custom selection column
const customSelectionColumn = createSelectionColumn({
  width: 100,
  pinLeft: true,
  multiSelect: true, // Enable multi-select
  header: ({ table }) => (
    <Tooltip title="Select All Rows">
      <Checkbox
        checked={table.getIsAllRowsSelected()}
        indeterminate={table.getIsSomeRowsSelected()}
        onChange={() => table.toggleAllRowsSelected()}
        sx={{ color: 'primary.main' }}
      />
    </Tooltip>
  ),
  cell: ({ row, table }) => (
    <Tooltip title="Select Row">
      <Checkbox
        checked={table.getIsRowSelected(row.id)}
        onChange={() => table.toggleRowSelected(row.id)}
        sx={{ color: 'secondary.main' }}
      />
    </Tooltip>
  ),
});

// Create a custom expanding column
const customExpandingColumn = createExpandingColumn({
  width: 80,
  pinLeft: true,
  header: 'Details',
  cell: ({ row }) => (
    <Tooltip title={row.getIsExpanded() ? "Collapse Details" : "Expand Details"}>
      <IconButton
        onClick={row.getToggleExpandedHandler()}
        size="small"
        sx={{ 
          color: 'primary.main',
          transition: 'all 0.2s ease',
          transform: row.getIsExpanded() ? 'rotate(180deg)' : 'rotate(0deg)',
          '&:hover': {
            backgroundColor: 'primary.light',
            color: 'primary.contrastText',
          },
        }}
      >
        <KeyboardArrowDownIcon />
      </IconButton>
    </Tooltip>
  ),
});

// Use in your table
<DataTable
  columns={[customSelectionColumn, customExpandingColumn, ...columns]}
  data={data}
  enableRowSelection
  enableExpanding
  // ... other props
/>

🔥 Advanced Examples

Server-Side Data Management

import { DataTable } from '@ackplus/react-tanstack-data-table';
import { useState, useCallback } from 'react';

function ServerSideTable() {
  const [loading, setLoading] = useState(false);

  const fetchData = useCallback(async (filters) => {
    setLoading(true);
    try {
      const response = await fetch('/api/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(filters),
      });
      const result = await response.json();
      return { data: result.users, total: result.total };
    } finally {
      setLoading(false);
    }
  }, []);

  return (
    <DataTable
      columns={columns}
      dataMode="server"
      loading={loading}
      onFetchData={fetchData}
      enablePagination
      enableSorting
      enableGlobalFilter
      paginationMode="server"
      sortingMode="server"
      filterMode="server"
    />
  );
}

Row Selection with Bulk Actions and Enhanced Slot System

import { CheckCircleIcon, RadioButtonUncheckedIcon } from '@mui/icons-material';

function SelectableTable() {
  const [selectedUsers, setSelectedUsers] = useState([]);

  const bulkActions = (selectionState) => {
    // Calculate selected count based on selection type
    const selectedCount = selectionState.type === 'include' 
      ? selectionState.ids.length 
      : data.length - selectionState.ids.length;

    // Get actual selected data
    const selectedRows = selectionState.type === 'include'
      ? data.filter(item => selectionState.ids.includes(item.id.toString()))
      : data.filter(item => !selectionState.ids.includes(item.id.toString()));

    return (
      <Stack direction="row" spacing={1}>
        <Button 
          variant="contained" 
          color="error"
          onClick={() => deleteUsers(selectedRows)}
        >
          Delete ({selectedCount})
        </Button>
        <Button 
          variant="outlined"
          onClick={() => exportUsers(selectedRows)}
        >
          Export Selected
        </Button>
      </Stack>
    );
  };

  return (
    <DataTable
      columns={columns}
      data={data}
      enableRowSelection
      enableMultiRowSelection
      enableBulkActions
      bulkActions={bulkActions}
      onSelectionChange={setSelectedUsers}
      slotProps={{
        selectionColumn: {
          width: 80,
          pinLeft: true,
          header: ({ table }) => (
            <Checkbox
              checked={table.getIsAllRowsSelected()}
              indeterminate={table.getIsSomeRowsSelected()}
              onChange={() => table.toggleAllRowsSelected()}
              sx={{ 
                color: 'primary.main',
                '&.Mui-checked': { color: 'primary.main' }
              }}
            />
          ),
          cell: ({ row, table }) => (
            <Checkbox
              checked={table.getIsRowSelected(row.id)}
              onChange={() => table.toggleRowSelected(row.id)}
              sx={{ 
                color: 'secondary.main',
                '&.Mui-checked': { color: 'secondary.main' }
              }}
            />
          ),
        },
      }}
    />
  );
}

Column Filters

const columns = [
  {
    accessorKey: 'status',
    header: 'Status',
    filterable: true,
    type: 'select',
    options: [
      { value: 'active', label: 'Active' },
      { value: 'inactive', label: 'Inactive' },
      { value: 'pending', label: 'Pending' },
    ],
  },
  {
    accessorKey: 'priority',
    header: 'Priority',
    filterable: true,
    type: 'number',
  },
  {
    accessorKey: 'created',
    header: 'Created Date',
    filterable: true,
    type: 'date',
  },
];

function FilterableTable() {
  return (
    <DataTable
      columns={columns}
      data={data}
      enableColumnFilter
      enableGlobalFilter
    />
  );
}

Expandable Rows with Enhanced Slot System

import { ExpandMoreIcon, ExpandLessIcon } from '@mui/icons-material';

function ExpandableTable() {
  const renderSubComponent = (row) => (
    <Box p={2}>
      <Typography variant="h6">User Details</Typography>
      <Grid container spacing={2}>
        <Grid item xs={6}>
          <Typography><strong>ID:</strong> {row.original.id}</Typography>
          <Typography><strong>Email:</strong> {row.original.email}</Typography>
        </Grid>
        <Grid item xs={6}>
          <Typography><strong>Role:</strong> {row.original.role}</Typography>
          <Typography><strong>Status:</strong> {row.original.status}</Typography>
        </Grid>
      </Grid>
    </Box>
  );

  return (
    <DataTable
      columns={columns}
      data={data}
      enableExpanding
      getRowCanExpand={(row) => row.original.details != null}
      renderSubComponent={renderSubComponent}
      slotProps={{
        expandColumn: {
          width: 60,
          pinLeft: true,
          header: 'Details',
          cell: ({ row }) => (
            <IconButton
              onClick={row.getToggleExpandedHandler()}
              size="small"
              sx={{ 
                color: 'primary.main',
                transition: 'transform 0.2s',
                transform: row.getIsExpanded() ? 'rotate(180deg)' : 'rotate(0deg)',
              }}
            >
              {row.getIsExpanded() ? <ExpandLessIcon /> : <ExpandMoreIcon />}
            </IconButton>
          ),
        },
      }}
    />
  );
}

Column Management

function ManageableColumnsTable() {
  const [columnOrder, setColumnOrder] = useState([]);
  const [columnPinning, setColumnPinning] = useState({ left: [], right: [] });

  return (
    <DataTable
      columns={columns}
      data={data}
      enableColumnVisibility
      enableColumnResizing
      enableColumnPinning
      draggable
      onColumnDragEnd={setColumnOrder}
      onColumnPinningChange={setColumnPinning}
      initialState={{
        columnOrder,
        columnPinning,
      }}
    />
  );
}

Export with Progress Tracking

function ExportableTable() {
  const [exportProgress, setExportProgress] = useState(null);

  const handleExportProgress = (progress) => {
    setExportProgress(progress);
  };

  const handleExportComplete = (result) => {
    setExportProgress(null);
  };

  return (
    <DataTable
      columns={columns}
      data={data}
      enableExport
      exportFilename="users-export"
      onExportProgress={handleExportProgress}
      onExportComplete={handleExportComplete}
      onExportError={(error) => console.error('Export failed:', error)}
    />
  );
}

🎛️ API Reference

DataTable Component

The main component that renders the data table with all features.

<DataTable<T>
  columns={DataTableColumn<T>[]}
  data={T[]}
  // ... other props
/>

Column Definition

Columns are defined using TanStack Table's column definition format with additional properties:

interface DataTableColumn<T> extends ColumnDef<T> {
  // Display properties
  align?: 'left' | 'center' | 'right';
  // Filtering
  filterable?: boolean;
  type?: 'boolean' | 'number' | 'date' | 'select' | 'text';
  options?: { label: string; value: string }[];
  
  // Export
  hideInExport?: boolean;
}

DataTable API

The DataTable exposes a comprehensive API through refs for programmatic control:

import { useRef } from 'react';
import { DataTable, DataTableApi } from '@ackplus/react-tanstack-data-table';

function MyComponent() {
  const tableRef = useRef<DataTableApi<User>>(null);

  const handleGetData = () => {
    const allData = tableRef.current?.data.getAllData();
  };

  return (
    <DataTable
      ref={tableRef}
      columns={columns}
      data={data}
    />
  );
}

Available API Methods

Column Management:

  • columnVisibility.showColumn(columnId) - Show specific column
  • columnVisibility.hideColumn(columnId) - Hide specific column
  • columnVisibility.toggleColumn(columnId) - Toggle column visibility
  • columnVisibility.showAllColumns() - Show all columns
  • columnVisibility.hideAllColumns() - Hide all columns
  • columnVisibility.resetColumnVisibility() - Reset to default visibility

Column Ordering:

  • columnOrdering.setColumnOrder(order) - Set column order
  • columnOrdering.moveColumn(columnId, toIndex) - Move column to position
  • columnOrdering.resetColumnOrder() - Reset to default order

Column Pinning:

  • columnPinning.pinColumnLeft(columnId) - Pin column to left
  • columnPinning.pinColumnRight(columnId) - Pin column to right
  • columnPinning.unpinColumn(columnId) - Unpin column
  • columnPinning.setPinning(pinning) - Set pinning state
  • columnPinning.resetColumnPinning() - Reset pinning

Column Resizing:

  • columnResizing.resizeColumn(columnId, width) - Resize column
  • columnResizing.autoSizeColumn(columnId) - Auto-size column
  • columnResizing.autoSizeAllColumns() - Auto-size all columns
  • columnResizing.resetColumnSizing() - Reset column sizing

Filtering:

  • filtering.setGlobalFilter(filter) - Set global filter
  • filtering.clearGlobalFilter() - Clear global filter
  • filtering.setColumnFilters(filters) - Set column filters
  • filtering.addColumnFilter(columnId, operator, value) - Add column filter
  • filtering.removeColumnFilter(filterId) - Remove column filter
  • filtering.clearAllFilters() - Clear all filters
  • filtering.resetFilters() - Reset all filters

Sorting:

  • sorting.setSorting(sortingState) - Set sorting state
  • sorting.sortColumn(columnId, direction) - Sort specific column
  • sorting.clearSorting() - Clear all sorting
  • sorting.resetSorting() - Reset sorting

Pagination:

  • pagination.goToPage(pageIndex) - Go to specific page
  • pagination.nextPage() - Go to next page
  • pagination.previousPage() - Go to previous page
  • pagination.setPageSize(pageSize) - Set page size
  • pagination.goToFirstPage() - Go to first page
  • pagination.goToLastPage() - Go to last page

Selection:

  • selection.selectRow(rowId) - Select specific row
  • selection.deselectRow(rowId) - Deselect specific row
  • selection.toggleRowSelection(rowId) - Toggle row selection
  • selection.selectAll() - Select all rows
  • selection.deselectAll() - Deselect all rows
  • selection.toggleSelectAll() - Toggle select all
  • selection.getSelectionState() - Get current selection state
  • selection.getSelectedRows() - Get selected rows
  • selection.getSelectedCount() - Get selected count
  • selection.isRowSelected(rowId) - Check if row is selected

Data Management:

  • data.refresh() - Refresh data
  • data.reload() - Reload data
  • data.getAllData() - Get all data
  • data.getRowData(rowId) - Get specific row data
  • data.getRowByIndex(index) - Get row by index
  • data.updateRow(rowId, updates) - Update specific row
  • data.updateRowByIndex(index, updates) - Update row by index
  • data.insertRow(newRow, index?) - Insert new row
  • data.deleteRow(rowId) - Delete specific row
  • data.deleteRowByIndex(index) - Delete row by index
  • data.deleteSelectedRows() - Delete selected rows
  • data.replaceAllData(newData) - Replace all data
  • data.updateMultipleRows(updates) - Update multiple rows
  • data.insertMultipleRows(newRows, startIndex?) - Insert multiple rows
  • data.deleteMultipleRows(rowIds) - Delete multiple rows
  • data.updateField(rowId, fieldName, value) - Update specific field
  • data.updateFieldByIndex(index, fieldName, value) - Update field by index
  • data.findRows(predicate) - Find rows by predicate
  • data.findRowIndex(predicate) - Find row index by predicate
  • data.getDataCount() - Get data count
  • data.getFilteredDataCount() - Get filtered data count

Layout Management:

  • layout.resetLayout() - Reset layout
  • layout.resetAll() - Reset everything
  • layout.saveLayout() - Save current layout
  • layout.restoreLayout(layout) - Restore saved layout

Export:

  • export.exportCSV(options?) - Export to CSV
  • export.exportExcel(options?) - Export to Excel
  • export.exportServerData(options) - Server-side export
  • export.isExporting() - Check if exporting
  • export.cancelExport() - Cancel export

Table State:

  • state.getTableState() - Get current table state
  • state.getCurrentFilters() - Get current filters
  • state.getCurrentSorting() - Get current sorting
  • state.getCurrentPagination() - Get current pagination
  • state.getCurrentSelection() - Get current selection

useDataTableApi Hook

Access the table's imperative API:

import { useRef } from 'react';
import { DataTable, DataTableApi } from '@ackplus/react-tanstack-data-table';

function MyComponent() {
  const tableRef = useRef<DataTableApi<User>>(null);

  const handleGetData = () => {
    const allData = tableRef.current?.data.getAllData();
  };

  return (
    <DataTable
      ref={tableRef}
      columns={columns}
      data={data}
    />
  );
}

🎨 Enhanced Customization with Slots System

The enhanced slot system provides powerful customization capabilities for DataTable components without limitations. This system allows you to override any component with full prop control and proper TypeScript support.

Key Features

  • Full Component Customization: Replace any component without limitations
  • Intelligent Prop Merging: Special handling for sx, style, and className props
  • Enhanced Type Safety: Better TypeScript inference and proper component prop typing
  • Performance Optimized: Efficient prop merging and component creation
  • Easy Migration: Works with existing code while providing enhanced capabilities

Basic Slot Customization

import { DataTable } from '@ackplus/react-tanstack-data-table';
import { Star as StarIcon } from '@mui/icons-material';

// Custom icon component
const CustomSearchIcon = (props) => (
    <StarIcon {...props} sx={{ color: 'warning.main', ...props.sx }} />
);

function MyTable() {
    return (
        <DataTable
            data={data}
            columns={columns}
            slots={{
                searchIcon: CustomSearchIcon,
            }}
            slotProps={{
                searchIcon: {
                    fontSize: 'large',
                    sx: {
                        animation: 'pulse 2s infinite',
                        '@keyframes pulse': {
                            '0%': { transform: 'scale(1)' },
                            '50%': { transform: 'scale(1.1)' },
                            '100%': { transform: 'scale(1)' },
                        },
                    },
                },
            }}
        />
    );
}

Advanced Component Replacement

import { styled, alpha } from '@mui/material/styles';

const CustomToolbar = styled(Box)(({ theme }) => ({
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: theme.spacing(2),
    backgroundColor: alpha(theme.palette.primary.main, 0.05),
    borderRadius: theme.shape.borderRadius,
}));

const CustomSearchInput = styled('input')(({ theme }) => ({
    padding: theme.spacing(1, 2),
    border: `1px solid ${theme.palette.divider}`,
    borderRadius: theme.shape.borderRadius,
    fontSize: theme.typography.body2.fontSize,
    '&:focus': {
        outline: 'none',
        borderColor: theme.palette.primary.main,
        boxShadow: `0 0 0 2px ${alpha(theme.palette.primary.main, 0.2)}`,
    },
}));

function AdvancedTable() {
    return (
        <DataTable
            data={data}
            columns={columns}
            slots={{
                toolbar: CustomToolbar,
                searchInput: ({ value, onChange, placeholder, ...props }) => (
                    <CustomSearchInput
                        type="text"
                        value={value}
                        onChange={(e) => onChange(e.target.value)}
                        placeholder={placeholder}
                        {...props}
                    />
                ),
            }}
            slotProps={{
                toolbar: {
                    sx: {
                        background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                        color: 'white',
                    },
                },
                searchInput: {
                    placeholder: 'Search anything...',
                    style: {
                        minWidth: '300px',
                    },
                },
            }}
        />
    );
}

Complete Customization Example

function FullyCustomizedTable() {
    const theme = useTheme();

    return (
        <DataTable
            data={data}
            columns={columns}
            slots={{
                // Custom toolbar with complete styling freedom
                toolbar: CustomToolbar,
                
                // Custom search input with full control
                searchInput: ({ value, onChange, placeholder, ...props }) => (
                    <CustomSearchInput
                        type="text"
                        value={value}
                        onChange={(e) => onChange(e.target.value)}
                        placeholder={placeholder || 'Search anything...'}
                        {...props}
                    />
                ),
                
                // Custom column visibility control
                columnVisibilityControl: (props) => {
                    const { table, color, ...buttonProps } = props;
                    return (
                        <CustomButton
                            variant="outlined"
                            startIcon={<VisibilityIcon />}
                            {...buttonProps}
                        >
                            Columns
                        </CustomButton>
                    );
                },
                
                // Custom export button
                exportButton: (props) => {
                    const { table, color, ...buttonProps } = props;
                    return (
                        <CustomButton
                            variant="contained"
                            startIcon={<ExportIcon />}
                            sx={{ 
                                background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
                                color: 'white',
                                ...buttonProps.sx
                            }}
                            {...buttonProps}
                        >
                            Export Data
                        </CustomButton>
                    );
                },
                
                // Custom table with enhanced styling
                table: ({ children, ...props }) => (
                    <Paper
                        elevation={3}
                        sx={{ 
                            borderRadius: 2,
                            overflow: 'hidden',
                            border: `2px solid ${theme.palette.primary.main}`,
                        }}
                    >
                        <table {...props} style={{ width: '100%' }}>
                            {children}
                        </table>
                    </Paper>
                ),
                
                // Custom row with hover effects
                row: ({ children, row, ...props }) => (
                    <tr 
                        {...props}
                        style={{
                            backgroundColor: row.index % 2 === 0 ? alpha(theme.palette.primary.main, 0.03) : 'transparent',
                            transition: 'background-color 0.2s ease',
                            cursor: 'pointer',
                            ...props.style,
                        }}
                        onMouseEnter={(e) => {
                            e.currentTarget.style.backgroundColor = alpha(theme.palette.primary.main, 0.1);
                        }}
                        onMouseLeave={(e) => {
                            e.currentTarget.style.backgroundColor = row.index % 2 === 0 ? alpha(theme.palette.primary.main, 0.03) : 'transparent';
                        }}
                    >
                        {children}
                    </tr>
                ),
            }}
            
            slotProps={{
                // Customize toolbar props
                toolbar: {
                    title: 'Custom Users Table',
                    subtitle: 'Manage your users with enhanced controls',
                    sx: {
                        background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.1)} 0%, ${alpha(theme.palette.secondary.main, 0.1)} 100%)`,
                        border: `1px solid ${alpha(theme.palette.primary.main, 0.2)}`,
                    },
                },
                
                // Customize search input
                searchInput: {
                    placeholder: 'Search users by name, email, or role...',
                    style: {
                        minWidth: '300px',
                        fontSize: '14px',
                    },
                },
                
                // Customize column visibility control
                columnVisibilityControl: {
                    title: 'Manage Columns',
                    menuSx: {
                        minWidth: 250,
                        maxHeight: 400,
                    },
                    titleSx: {
                        color: theme.palette.primary.main,
                        fontWeight: 'bold',
                    },
                    checkboxProps: {
                        color: 'primary',
                    },
                },
                
                // Customize table container
                tableContainer: {
                    sx: {
                        maxHeight: '600px',
                        '&::-webkit-scrollbar': {
                            width: '8px',
                        },
                        '&::-webkit-scrollbar-track': {
                            backgroundColor: alpha(theme.palette.grey[300], 0.5),
                            borderRadius: '4px',
                        },
                        '&::-webkit-scrollbar-thumb': {
                            backgroundColor: theme.palette.primary.main,
                            borderRadius: '4px',
                            '&:hover': {
                                backgroundColor: theme.palette.primary.dark,
                            },
                        },
                    },
                },
                
                // Customize pagination
                pagination: {
                    rowsPerPageOptions: [10, 25, 50, 100, 300, 500, 1000],
                    sx: {
                        '& .MuiTablePagination-toolbar': {
                            backgroundColor: alpha(theme.palette.primary.main, 0.05),
                            borderTop: `1px solid ${theme.palette.divider}`,
                        },
                        '& .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows': {
                            color: theme.palette.primary.main,
                            fontWeight: 'medium',
                        },
                    },
                },
            }}
        />
    );
}

Available Slots

Container Slots

  • root - Main container
  • tableContainer - Table container wrapper
  • table - Table element

Header Slots

  • toolbar - Main toolbar
  • header - Table header
  • headerRow - Header row
  • headerCell - Header cell

Body Slots

  • body - Table body
  • row - Table row
  • cell - Table cell

Control Slots

  • searchInput - Search input component
  • columnVisibilityControl - Column visibility control
  • columnCustomFilterControl - Column filter control
  • columnPinningControl - Column pinning control
  • exportButton - Export button
  • resetButton - Reset button
  • tableSizeControl - Table size control
  • bulkActionsToolbar - Bulk actions toolbar

Icon Slots

  • searchIcon - Search icon
  • filterIcon - Filter icon
  • exportIcon - Export icon
  • columnIcon - Column visibility icon
  • resetIcon - Reset icon
  • pinIcon - Pin column icon
  • unpinIcon - Unpin column icon
  • csvIcon - CSV export icon
  • excelIcon - Excel export icon
  • viewComfortableIcon - Comfortable view icon
  • viewCompactIcon - Compact view icon

Special Slots

  • loadingRow - Loading state row
  • emptyRow - Empty state row
  • footer - Table footer
  • pagination - Pagination component

Best Practices

1. Component Composition

// Good: Compose components properly
const CustomControl = ({ children, ...props }) => (
    <Box sx={{ display: 'flex', gap: 1 }} {...props}>
        {children}
    </Box>
);

// Usage
slots={{
    toolbar: ({ children, ...props }) => (
        <CustomControl {...props}>
            {children}
        </CustomControl>
    ),
}}

2. Prop Forwarding

// Good: Always forward props
const CustomIcon = (props) => (
    <StarIcon {...props} sx={{ color: 'primary.main', ...props.sx }} />
);

// Bad: Not forwarding props
const CustomIcon = () => <StarIcon color="primary" />;

3. TypeScript Support

// Good: Use proper typing
interface CustomButtonProps {
    onClick?: () => void;
    children: React.ReactNode;
    [key: string]: any; // Allow additional props
}

const CustomButton: React.FC<CustomButtonProps> = ({ children, ...props }) => (
    <Button {...props}>{children}</Button>
);

4. Performance Considerations

// Good: Memoize expensive components
const CustomToolbar = React.memo(({ children, ...props }) => (
    <Box {...props}>{children}</Box>
));

// Good: Use callbacks for event handlers
const handleClick = useCallback(() => {
    // Handle click
}, []);

Migration from Basic Slots

// Before
<DataTable
    slots={{
        searchIcon: MyIcon,
    }}
    slotProps={{
        searchIcon: { color: 'primary' },
    }}
/>

// After (Enhanced)
<DataTable
    slots={{
        searchIcon: MyIcon,
    }}
    slotProps={{
        searchIcon: {
            color: 'primary',
            sx: { fontSize: 20 }, // Now supports sx prop merging
        },
    }}
/>

Logging & Debugging

Use the built-in logger to trace pagination, server calls, and state transitions without sprinkling console.log statements throughout your app.

import { DataTable, configureDataTableLogging } from '@ackplus/react-tanstack-data-table';

configureDataTableLogging({
    enabled: true,
    level: 'debug',
    includeTimestamp: true,
});

<DataTable
    columns={columns}
    data={rows}
    logging={{
        enabled: true,
        level: 'info',
        prefix: 'OrdersTable',
    }}
/>
  • Call configureDataTableLogging once (for example in your app bootstrap) to set global defaults.
  • Use the logging prop to override settings per table or disable instrumentation for specific instances.
  • When logging is omitted, instances inherit the global configuration.

Troubleshooting

Common Issues

  1. Props not merging correctly

    • Ensure you're using the enhanced slot system
    • Check prop priority order (user > slot > default)
  2. TypeScript errors

    • Use [key: string]: any for flexible prop interfaces
    • Ensure proper prop forwarding with spread operator
    • Filter out incompatible props like table and color for Button components
  3. Styling conflicts

    • Check sx prop merging order
    • Use proper CSS specificity
  4. Performance issues

    • Memoize expensive components
    • Use callbacks for event handlers
    • Avoid inline function definitions

The enhanced slot system provides unprecedented flexibility for customizing DataTable components. With proper prop merging, full TypeScript support, and intelligent component composition, you can create highly customized tables without limitations.

🔧 Migration Guide

From v0.x to v1.x

Key changes in v1.0:

  • Updated to latest TanStack Table v8
  • Improved TypeScript support
  • Enhanced slot system
  • Better server-side integration

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

💖 Support the Project

If you find this package helpful and want to support its development, consider making a donation:

PayPal Razorpay

💳 PayPal💳 Razorpay

Your support helps us:

  • 🛠️ Maintain and improve the library
  • 🐛 Fix bugs and add new features
  • 📚 Create better documentation
  • 🚀 Keep the project active and up-to-date

📄 License

MIT © ACK Solutions

🆘 Support

If you find this package helpful, please consider giving it a ⭐ on GitHub!