smartgrid-react-ui
v0.1.3
Published
React data grid with filtering, sorting, pagination, theming, and card view
Maintainers
Readme
smartgrid-react-ui
smartgrid-react-ui is a React data-grid library with:
useGrid(headless hook)Grid(ready-to-use UI component)
This README is aligned with the DemoPage flow and shows exactly what to change per feature.
Install
npm i smartgrid-react-uiDemo Flow (same as DemoPage)
- Final Product Grid (all features together)
- Basic Grid
- Enable Sorting
- Enable Filters (enum + date)
- Enable Selection + Delete Selected
- Date Filters operators/presets
- Formatted Cells
- Custom Row Action Buttons
In each snippet below, changed lines are marked with // CHANGED.
Shared Types and Base Columns
import { Grid, useGrid, type ColumnDef, type RowRecord } from "smartgrid-react-ui";
interface LeadRow extends RowRecord {
id: number;
name: string;
company: string;
email: string;
phone: string;
status: string;
value: number;
city: string;
createdAt: string;
}
const leadColumns: ColumnDef<LeadRow>[] = [
{ field: "id", headerName: "ID", type: "number", sortable: true, filterable: true, width: 70 },
{ field: "name", headerName: "Name", type: "string", sortable: true, filterable: true },
{ field: "company", headerName: "Company", type: "string", sortable: true, filterable: true },
{ field: "email", headerName: "Email", type: "string", sortable: true, filterable: true },
{ field: "phone", headerName: "Phone", type: "string", sortable: true, filterable: true, searchable: false },
{
field: "status",
headerName: "Status",
type: "string",
sortable: true,
filterable: true,
searchable: false,
enumValues: ["New", "Contacted", "Qualified", "Won", "Lost"], // CHANGED: enum dropdown values
},
{ field: "value", headerName: "Value", type: "number", sortable: true, filterable: true },
{ field: "city", headerName: "City", type: "string", sortable: true, filterable: true, searchable: false },
{
field: "createdAt",
headerName: "Created At",
type: "date", // CHANGED: date type enables date filter operators
sortable: true,
filterable: true,
searchable: false,
},
];1) Basic Grid
const grid = useGrid<LeadRow>({
columns: leadColumns,
data: rows,
enableSelection: false, // CHANGED: base demo state
showSelectionCheckboxes: false, // CHANGED: base demo state
enableSorting: false, // CHANGED: base demo state
enableFilters: false, // CHANGED: base demo state
paginationMode: "server",
totalRowCount: total,
getRowId: (row) => String(row.id),
});
<Grid grid={grid} className="h-full" showActionColumn={false} />;2) Enable Sorting
const sortableColumns: ColumnDef<LeadRow>[] = [
{ field: "id", headerName: "ID", type: "number", sortable: true }, // CHANGED
{ field: "name", headerName: "Name", type: "string", sortable: true }, // CHANGED
{ field: "value", headerName: "Value", type: "number", sortable: true }, // CHANGED
{ field: "createdAt", headerName: "Created At", type: "date", sortable: true }, // CHANGED
];
const grid = useGrid<LeadRow>({
columns: sortableColumns,
data: rows,
enableSelection: false,
showSelectionCheckboxes: false,
enableSorting: true, // CHANGED: sorting ON
enableFilters: false,
paginationMode: "server",
totalRowCount: total,
});3) Enable Filters (enum + date)
const filterableColumns: ColumnDef<LeadRow>[] = [
{ field: "name", headerName: "Name", type: "string", filterable: true }, // CHANGED
{
field: "status",
headerName: "Status",
type: "string",
filterable: true, // CHANGED
searchable: false, // CHANGED
enumValues: ["New", "Contacted", "Qualified", "Won", "Lost"], // CHANGED
},
{ field: "createdAt", headerName: "Created At", type: "date", filterable: true }, // CHANGED
];
const grid = useGrid<LeadRow>({
columns: filterableColumns,
data: rows,
enableSelection: false,
showSelectionCheckboxes: false,
enableSorting: true,
enableFilters: true, // CHANGED: filters ON
paginationMode: "server",
totalRowCount: total,
});4) Enable Selection + Delete Selected (custom behavior)
const grid = useGrid<LeadRow>({
columns: leadColumns,
data: rows,
enableSelection: true, // CHANGED
showSelectionCheckboxes: true, // CHANGED
enableSorting: true,
enableFilters: true,
paginationMode: "server",
totalRowCount: total,
getRowId: (row) => String(row.id),
});
<Grid
grid={grid}
onDeleteSelectedRows={(selectedRows) => { // CHANGED: your custom delete logic
const ids = new Set(selectedRows.map((r) => r.id));
setRows((prev) => prev.filter((r) => !ids.has(r.id))); // frontend delete example
setTotal((prev) => Math.max(0, prev - ids.size));
}}
/>;If you want API delete instead:
onDeleteSelectedRows={async (selectedRows) => {
await fetch("/api/leads/bulk-delete", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ids: selectedRows.map((r) => r.id) }),
});
await refetchLeads();
}}5) Date Filters (before / after / between / preset)
const dateColumns: ColumnDef<LeadRow>[] = [
{
field: "createdAt",
headerName: "Created At",
type: "date", // CHANGED
sortable: true,
filterable: true, // CHANGED
searchable: false,
},
];
const grid = useGrid<LeadRow>({
columns: dateColumns,
data: rows,
enableFilters: true, // CHANGED
});Available date filter operations:
beforeafterbetweenpreset:last7Days,last30Days,thisWeek,lastWeek,thisMonth,lastMonth
6) Formatted Cell (status badges)
const formattedColumns: ColumnDef<LeadRow>[] = leadColumns.map((col) =>
col.field === "status"
? {
...col,
renderCell: ({ value }) => { // CHANGED
const status = String(value ?? "");
// CHANGED: map value -> badge colors
return <StatusBadge status={status} />;
},
}
: col
);7) Custom Row Actions (View / Edit / Delete)
const actionColumns: ColumnDef<LeadRow>[] = [
...leadColumns,
{
field: "actions", // CHANGED: added action column
headerName: "Actions",
type: "string",
sortable: false, // CHANGED
filterable: false, // CHANGED
searchable: false, // CHANGED
renderCell: ({ row }) => ( // CHANGED: your own action handlers
<div style={{ display: "flex", gap: 6 }}>
<button onClick={() => handleView(row)}>View</button>
<button onClick={() => handleEdit(row)}>Edit</button>
<button onClick={() => handleDelete(row)}>Delete</button>
</div>
),
},
];Final Product Grid (all features together)
const grid = useGrid<LeadRow>({
columns: finalColumns, // CHANGED
data: rows,
enableSelection: true, // CHANGED
showSelectionCheckboxes: true, // CHANGED
enableSorting: true, // CHANGED
enableFilters: true, // CHANGED
paginationMode: "server", // CHANGED
totalRowCount: total, // CHANGED
getRowId: (row) => String(row.id),
});Server Pagination Pattern (Leads API)
useEffect(() => {
async function load() {
const sort = grid.sortModel[0];
const payload = await fetchLeads({
page: grid.pagination.pageIndex + 1, // CHANGED: map 0-based UI -> 1-based API
limit: grid.pagination.pageSize, // CHANGED
sortBy: sort?.field,
order: sort?.direction ?? "asc",
});
setRows(payload.data ?? []);
setTotal(payload.total ?? 0);
}
load();
}, [grid.pagination.pageIndex, grid.pagination.pageSize, grid.sortModel]);Important Props (quick reference)
enableSelectionshowSelectionCheckboxesenableSortingenableFilterspaginationMode(client|server)totalRowCount(required for server mode)onDeleteSelectedRows(custom bulk delete)
Development
npm install
npm run dev
npm run build