@chainsys/sab-react-grid
v1.0.1
Published
Enterprise TanStack Table component for React: virtualized rows, sorting, filtering, grouping, column resize, Excel/CSV export, and layout modes.
Downloads
160
Readme
@chainsys/sab-react-grid
A professional, enterprise-grade data grid for React applications. Built on TanStack Table and TanStack React Virtual, it delivers high-performance tables with sorting, filtering, grouping, column visibility, virtualization, and Excel/CSV export—with a consistent API and minimal configuration.
Package: @chainsys/sab-react-grid
Version: 1.0.1
License: MIT
Features
| Feature | Description |
|--------|-------------|
| TanStack Table | Full control over sorting, filtering, grouping, pagination, column visibility, order, and sizing |
| Row virtualization | Renders only visible rows via @tanstack/react-virtual for smooth scrolling with large datasets |
| Layout modes | fit-default, fit-window, or fit-content (content-based column widths) |
| Column filters | Text, number, date, datetime, time (Flatpickr), multiselect, checkbox, boolean, dropdown, and radio with operand support (contains, equals, greater than, etc.) |
| Filter placeholders | Search icon (🔎︎) for text/number and dropdown filters; calendar icon for date/datetime/time filters (with SVG placeholder when empty) |
| Export | Excel (.xlsx) via ExcelJS and CSV via plain Blob from the toolbar Data Export menu |
| Grouping | Drag columns into the grouping zone; expand/collapse groups |
| Column reorder | Drag-and-drop column reordering in the header |
| Column visibility | Show/hide columns from the Columns menu |
| Sticky headers | Header and filter rows stay fixed while the body scrolls |
| Actions column | Row actions (Add, View, Edit, Delete, List, or custom) with configurable icon, label, and navigation URL from meta.actions |
| Performance | Memoized header, filter, row, and cell components |
Installation
npm install @chainsys/sab-react-grid @tanstack/react-table @tanstack/react-virtual react react-domPeer dependencies
Install in your application if not already present:
react(^18.0.0 or ^19.0.0)react-dom(^18.0.0 or ^19.0.0)@tanstack/react-table(^8.0.0)@tanstack/react-virtual(^3.0.0)
Dependencies (installed automatically)
date-fns– date formattingexceljs– Excel (.xlsx) export (larger files; NPM vulnerabilities mitigated via package overrides)flatpickr,react-flatpickr– date/datetime/time filters
CSV export uses no extra libraries (plain string/Blob).
Project structure and main files
| Path | Purpose |
|------|---------|
| src/index.ts | Package entry; re-exports component, formatters, export helpers, and types |
| src/SabReactTable.tsx | Main grid component: table UI, toolbar, filter row, virtualization, grouping, export menu |
| src/utils/tableFormatters.tsx | DataFormatter, ActionFormatter, date formatting, TableAction / ACTION_ICON_KEYS / ActionIcons |
| src/utils/exportUtils.ts | exportTableToExcel (ExcelJS), exportTableToCSV (plain Blob) |
| src/utils/tableColumnResizeUtils.ts | resizeColumnsByCellContent, getWidthInPixel, getWidthInPixelTitle for fit-to-content layout |
| dist/ | Built output (ESM + CJS + types); files in package.json ships only dist |
Build: npm run build (runs clean then build:esm and build:cjs).
Clean: npm run clean removes dist before build to avoid stale artifacts.
Quick start
import { SabReactTable } from '@chainsys/sab-react-grid'
import type { ColumnDef } from '@tanstack/react-table'
interface Person {
id: number
name: string
email: string
role: string
}
const columns: ColumnDef<Person, unknown>[] = [
{ id: 'id', accessorKey: 'id', header: 'ID' },
{ id: 'name', accessorKey: 'name', header: 'Name' },
{ id: 'email', accessorKey: 'email', header: 'Email' },
{ id: 'role', accessorKey: 'role', header: 'Role', meta: { dataType: 'text' } },
]
const data: Person[] = [
{ id: 1, name: 'Alice', email: '[email protected]', role: 'Admin' },
{ id: 2, name: 'Bob', email: '[email protected]', role: 'User' },
]
export function MyTable() {
return (
<SabReactTable<Person>
data={data}
columns={columns}
title="Users"
defaultPageSize={50}
pageSizeOptions={[10, 20, 50, 100]}
initialLayoutMode="fit-content"
onSortedDataChange={(rows) => console.log('Filtered/sorted rows', rows)}
onRowClick={(row) => console.log('Clicked', row)}
/>
)
}Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | TData[] | required | Row data |
| columns | ColumnDef<TData, any>[] | required | TanStack Table column definitions |
| title | string | 'Table_List' | Table title in the toolbar |
| onSortedDataChange | (rows: TData[]) => void | — | Called with filtered/sorted rows (pre-pagination) |
| defaultPageSize | number | 50 | Initial page size |
| pageSizeOptions | number[] | [10, 20, 50, 100, 500, 1000] | Page size dropdown options |
| groupingLabels | Record<string, string> | {} | Display labels for grouping columns |
| onRowClick | (row: TData) => void | — | Row click handler |
| onActionClick | (actionId, row, action) => void | — | Handler for action buttons; use action.navigate or action.id to route |
| initialLayoutMode | 'fit-default' \| 'fit-window' \| 'fit-content' | 'fit-content' | Initial layout mode |
Column meta
Use the meta property on column definitions to control formatting and filtering:
| Meta key | Type | Description |
|----------|------|-------------|
| dataType | 'text' \| 'number' \| 'decimal' \| 'currency' \| 'email' \| 'boolean' \| 'date' \| 'datetime' \| 'time' \| 'percentage' \| 'icon-boolean' | Cell formatting and alignment |
| formatOptions | { decimals?, currencySymbol?, dateFormat?, datetimeFormat?, timeFormat? } | Number, currency, and date formatting |
| filterType | 'text' \| 'select' \| 'multiselect' \| 'checkbox' \| 'boolean' \| 'date' \| 'number' \| 'dropdown' \| 'radio' | Filter UI type |
| filterOptions | { label: string; value: any }[] | Options for select, multiselect, dropdown, and radio filters |
| actions | TableAction[] | Row action buttons (Add, View, Edit, Delete, List, or custom) |
Filter placeholders
- Text, number, and dropdown/select filters: search placeholder (🔎︎).
- Date, datetime, and time filters: calendar icon (SVG) when empty, plus optional text placeholder; Flatpickr for picking date/time.
Actions (from config / JSON)
Actions are fully driven by column meta.actions. Each action can specify:
| Field | Type | Description |
|-------|------|-------------|
| id | string | Unique key passed to onActionClick |
| label | string | Button label (optional for icon-only buttons) |
| icon | 'View' \| 'Edit' \| 'Delete' \| 'Add' \| 'List' or lowercase in JSON, or ReactNode | Built-in icon or custom node |
| navigate | string \| (row) => string | URL or function; use in onActionClick for routing (e.g. router.push(...)) |
| onClick | (row) => void | Per-action handler (if not using table onActionClick) |
| show | (row) => boolean | Hide button for specific rows |
| className | string | Extra CSS class for the button |
Built-in icon keys: View, Edit, Delete, Add, List (exported as ACTION_ICON_KEYS). In JSON you can use lowercase ("view", "add", etc.).
Example:
meta: {
actions: [
{ id: 'add', label: 'Add', icon: 'Add', navigate: '/create' },
{ id: 'view', label: 'View', icon: 'View', navigate: (row) => `/item/${row.id}` },
{ id: 'edit', label: 'Edit', icon: 'Edit', navigate: (row) => `/edit/${row.id}` },
{ id: 'list', label: 'List', icon: 'List', navigate: '/list' },
],
}Example: filters and formatting
const columns: ColumnDef<Person, unknown>[] = [
{ id: 'id', accessorKey: 'id', header: 'ID', meta: { dataType: 'number' } },
{ id: 'name', accessorKey: 'name', header: 'Name', meta: { dataType: 'text' } },
{ id: 'email', accessorKey: 'email', header: 'Email', meta: { dataType: 'email' } },
{
id: 'role',
accessorKey: 'role',
header: 'Role',
meta: {
dataType: 'text',
filterType: 'select',
filterOptions: [
{ label: 'Admin', value: 'Admin' },
{ label: 'User', value: 'User' },
],
},
},
]Export
- Excel:
exportTableToExcel(data, filename?, tableTitle?)– uses ExcelJS; suitable for larger files. NPM audit issues from transitive deps are addressed viaoverridesin package.json (minimatch). - CSV:
exportTableToCSV(data, filename?)– plain string/Blob; no ExcelJS.
Both are available from the toolbar Data Export menu and as standalone imports.
Exports
| Export | Description |
|--------|-------------|
| SabReactTable | Main grid component |
| SabReactTableProps, LayoutMode, OnActionClickHandler | Component and layout types |
| DataFormatter, ActionFormatter | Default cell and action formatters |
| formatDateValue, renderDateCell, isIsoDateLike | Date formatting helpers |
| ActionIcons, ACTION_ICON_KEYS, TableAction, ActionConfig, ActionIconKey | Action types and built-in icons |
| exportTableToExcel, exportTableToCSV | Standalone export helpers |
| resizeColumnsByCellContent, getWidthInPixel, getWidthInPixelTitle | Column resize utilities |
| ColumnResizeDef, ResizeColumnsByCellContentParams | Resize utility types |
| DateFormatOptions | Date format options type |
| ColumnDef | Re-exported from @tanstack/react-table |
License
MIT
