@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.
🎯 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-tableRequired 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:
- Bordered theme options - Adds borders to all table elements
- Stripped theme options - Alternating row colors
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
mergeThemeOptionsto properly combine theme functions - it handlesstyleOverridesfunction 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:
- Tags Column Type - Display array of tags as chips
- Users Column Type - User objects with avatar and smart filtering
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
- Column Types define which smart filter operations are allowed via
allowedSmartFilters - Smart Filter Items implement the filtering logic and UI components
- 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
- Live Demo: Complete example app with all features demonstrated
- Column Types: Custom column implementations
- Smart Filters: Advanced filtering examples
- Theming: Theme customization guide
- Type Definitions: Extended table types
🛠 Built With
- TanStack Table v8 - Powerful table logic
- Material-UI v5/v6 - Beautiful, accessible components
- TanStack Query v5 - Server state management
- TypeScript - Type safety and great DX
📄 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! 🚀
