arts-datatable
v0.1.0
Published
Reusable React data table with server-side query mode, backend-driven filters, exports, URL sync, fixed columns, and card view.
Maintainers
Readme
arts-datatable
Reusable data table for React projects with:
- server-side pagination
- server-side sorting
- backend-driven filters
- CSV export
- PDF export
- table / card view
- URL sync
- inline expandable rows
- fixed columns
- column resize
- column reorder
- table virtualization
Built with:
ReactMUI@tanstack/react-table
Install
npm install arts-datatableRequired peer dependencies:
npm install react react-dom @mui/material @mui/icons-material @mui/x-date-pickers @emotion/react @emotion/styled @tanstack/react-table dayjsFor PDF export the package already uses:
html2canvasjspdf
They are loaded lazily only when user clicks PDF.
Exports
import { ArtsDataTable, buildArtsTableSearchParams } from 'arts-datatable';
import type {
ArtsApiFilter,
ArtsApiFilterOption,
ArtsApiResponse,
ArtsColumnDef,
ArtsDataTableProps,
ArtsRowAction,
ArtsTableQuery,
ArtsTableSort,
ArtsToolbarAction
} from 'arts-datatable';Basic usage
import { ArtsDataTable } from 'arts-datatable';
<ArtsDataTable
title="My cases"
columns={columns}
request={requestCases}
/>Request mode
import { buildArtsTableSearchParams, type ArtsApiResponse, type ArtsTableQuery } from 'arts-datatable';
const requestCases = async (query: ArtsTableQuery): Promise<ArtsApiResponse<CaseItem, CaseAccess>> => {
const searchParams = buildArtsTableSearchParams(query);
const response = await fetch(`/api/cases?${searchParams.toString()}`);
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response.json();
};Response mode
<ArtsDataTable
columns={columns}
response={response}
loading={loading}
error={error}
/>Backend response shape
type ArtsApiResponse<TData, TAccess = unknown> = {
_payload: TData[];
_meta?: {
total?: number;
};
_access?: TAccess;
_filters?: ArtsApiFilter[];
code?: number;
message?: string;
};_filters is backend-driven. Supported filter types:
textdateselectmulti_selectdate_range
Example:
[
{
"type": "text",
"slug": "debtor",
"label": "Պարտապան"
},
{
"type": "multi_select",
"slug": "status",
"label": "Կարգավիճակ",
"options": [
{ "value": "sent", "label": "Ուղարկված" },
{ "value": "bankrupted", "label": "Սնանկ ճանաչված" }
]
},
{
"type": "date_range",
"slug": "inscription_date",
"label": "Մակագրման ամսաթիվ"
}
]Query shape
type ArtsTableQuery = {
page: number;
limit: number;
sort?: {
field: string;
direction: 'asc' | 'desc';
};
filters: Record<
string,
string | number | boolean | null | undefined | string[] | { from?: string; to?: string }
>;
};Generated URL examples:
?page=1&limit=50
?page=1&limit=50&sort=-inscribed_status_created_at
?page=1&limit=50&filters[debtor]=...
?page=1&limit=50&filters[status][]=sent&filters[status][]=bankrupted
?page=1&limit=50&filters[inscription_date][from]=2026-05-01&filters[inscription_date][to]=2026-05-31Columns
import type { ArtsColumnDef } from 'arts-datatable';
export const columns: ArtsColumnDef<RowItem>[] = [
{
key: 'code',
header: 'Code',
sort: true,
fixed: true
},
{
key: 'status',
header: 'Status',
sort: true,
cell: info => <StatusChip value={info.row.original.status} />,
exportValue: row => row.status
}
];Important column options:
key: field name from row objectheader: visible headercell: custom renderersort: enables server-side sortingsortField: backend field name if differentfixed:true | 'left' | 'right'display:falseor'exclude'exportValue: value for CSV/PDF export
Use exportValue only for computed/custom cells:
{
key: 'status',
cell: info => <StatusChip value={info.row.original.status} />,
exportValue: row => row.status
}For simple fields like code or uuid, exportValue is not needed.
Core props
<ArtsDataTable
title="My cases"
columns={columns}
request={requestCases}
emptyText="Տվյալներ չկան"
noDataText="Տվյալ չկա"
errorText="Տվյալները բեռնել չհաջողվեց"
/>Useful props:
enableCsvExportcsvFileNameenablePdfExportpdfFileNameenableUrlSyncurlSyncKeyenableRowSelectionenableColumnVisibilityenableColumnResizeenableColumnReorderenableVirtualizationvirtualRowHeightrenderExpandedContentrowActionstoolbarActions
CSV / PDF export
<ArtsDataTable
columns={columns}
request={requestCases}
enableCsvExport
csvFileName="court-cases"
enablePdfExport
pdfFileName="court-cases"
/>Export uses:
- currently loaded rows
- currently visible columns
exportValue, if column provides it
Action column is excluded automatically.
URL sync
<ArtsDataTable
columns={columns}
request={requestCases}
enableUrlSync
urlSyncKey="court-cases"
/>Synced values:
pagelimitsortfiltersview
Expandable rows
import type { Row } from '@tanstack/react-table';
const renderExpandedContent = (row: Row<CaseItem>) => (
<div>{row.original.uuid}</div>
);
<ArtsDataTable
columns={columns}
request={requestCases}
renderExpandedContent={renderExpandedContent}
/>If renderExpandedContent is missing, expand UI is not shown.
Fixed columns
{
key: 'code',
fixed: true
}
{
key: 'uuid',
fixed: 'right'
}__actions__ column is pinned to the right automatically.
Column resize
Resize works in table mode. By default it is enabled.
<ArtsDataTable
columns={columns}
request={requestCases}
enableColumnResize
/>User can:
- drag header edge
- double click resize handle to reset width
If you want to disable:
<ArtsDataTable enableColumnResize={false} />Column reorder
Reorder is available from the columns menu.
<ArtsDataTable
columns={columns}
request={requestCases}
enableColumnReorder
/>User can move each column left or right from the columns menu.
If you want to disable:
<ArtsDataTable enableColumnReorder={false} />Virtualization
Virtualization works in table mode and is useful for large pages.
<ArtsDataTable
columns={columns}
request={requestCases}
enableVirtualization
virtualRowHeight={56}
/>Notes:
- it virtualizes only table rows
- it uses fixed row height
- when expanded rows are opened, virtualization is disabled automatically for correct height rendering
Filters UI
Text filters are debounced by default:
<ArtsDataTable filterDebounceMs={400} />You can also switch filter mode:
<ArtsDataTable filterMode="submit" />select and multi_select are rendered with MUI Autocomplete.
Row actions
const getRowActions = row => [
{
label: 'View',
onClick: row => console.log(row.original)
}
];
<ArtsDataTable
columns={columns}
request={requestCases}
rowActions={getRowActions}
/>Toolbar actions
const getToolbarActions = access => [
{
label: 'Create',
onClick: () => {}
}
];
<ArtsDataTable
columns={columns}
request={requestCases}
toolbarActions={getToolbarActions}
/>Full example
import { ArtsDataTable } from 'arts-datatable';
import type { Row } from '@tanstack/react-table';
const renderExpandedContent = (row: Row<CaseItem>) => (
<div>{row.original.uuid}</div>
);
<ArtsDataTable
title="Իմ դատական գործերը"
columns={columns}
request={requestCases}
enableCsvExport
enablePdfExport
enableUrlSync
enableVirtualization
renderExpandedContent={renderExpandedContent}
rowActions={getRowActions}
toolbarActions={getToolbarActions}
/>