Package Exports
- @toolbox-web/grid-react
- @toolbox-web/grid-react/package.json
Readme
@toolbox-web/grid-react
React adapter library for @toolbox-web/grid - a high-performance, framework-agnostic data grid web component.
Installation
npm install @toolbox-web/grid @toolbox-web/grid-reactBasic Usage
import { DataGrid, GridColumn } from '@toolbox-web/grid-react';
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
function EmployeeGrid() {
const [employees, setEmployees] = useState<Employee[]>([
{ id: 1, name: 'Alice', department: 'Engineering', salary: 95000 },
{ id: 2, name: 'Bob', department: 'Marketing', salary: 75000 },
{ id: 3, name: 'Charlie', department: 'Sales', salary: 85000 },
]);
return (
<DataGrid
rows={employees}
columns={[
{ field: 'id', header: 'ID', width: 60 },
{ field: 'name', header: 'Name', sortable: true },
{ field: 'department', header: 'Department', sortable: true },
{ field: 'salary', header: 'Salary', type: 'number' },
]}
onRowsChange={setEmployees}
/>
);
}Custom Cell Renderers
There are two ways to define custom renderers: inline in the configuration, or via GridColumn components.
Inline Configuration (Recommended)
Define renderers directly in your ReactGridConfig:
import { DataGrid, type ReactGridConfig } from '@toolbox-web/grid-react';
const config: ReactGridConfig<Employee> = {
columns: [
{ field: 'name', header: 'Name' },
{
field: 'status',
header: 'Status',
// Custom React renderer - same property name as vanilla!
renderer: (ctx) => (
<span className={`badge badge-${ctx.value.toLowerCase()}`}>
{ctx.value}
</span>
),
},
],
};
function EmployeeGrid() {
return <DataGrid rows={employees} gridConfig={config} />;
}Using GridColumn Components
Use the GridColumn component with a render prop:
import { DataGrid, GridColumn } from '@toolbox-web/grid-react';
function StatusBadge({ status }: { status: string }) {
return <span className={`badge badge-${status.toLowerCase()}`}>{status}</span>;
}
function EmployeeGrid() {
return (
<DataGrid rows={employees}>
<GridColumn field="name" header="Name" />
<GridColumn field="status">{(ctx) => <StatusBadge status={ctx.value} />}</GridColumn>
</DataGrid>
);
}Custom Cell Editors
Define editors inline in your configuration or via GridColumn:
Inline Configuration
const config: ReactGridConfig<Employee> = {
columns: [
{
field: 'status',
header: 'Status',
editable: true,
renderer: (ctx) => <StatusBadge status={ctx.value} />,
editor: (ctx) => (
<select
defaultValue={ctx.value}
autoFocus
onChange={(e) => ctx.commit(e.target.value)}
onKeyDown={(e) => e.key === 'Escape' && ctx.cancel()}
>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
),
},
],
};Using GridColumn
<DataGrid rows={employees}>
<GridColumn
field="name"
editable
editor={(ctx) => (
<input
autoFocus
defaultValue={ctx.value}
onBlur={(e) => ctx.commit(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') ctx.commit(e.currentTarget.value);
if (e.key === 'Escape') ctx.cancel();
}}
/>
)}
/>
</DataGrid>Master-Detail with GridDetailPanel
Create expandable row details using the GridDetailPanel component:
import { DataGrid, GridDetailPanel } from '@toolbox-web/grid-react';
import { MasterDetailPlugin } from '@toolbox-web/grid/all';
function EmployeeGrid() {
const config: ReactGridConfig<Employee> = {
columns: [...],
plugins: [new MasterDetailPlugin()],
};
return (
<DataGrid rows={employees} gridConfig={config}>
<GridDetailPanel showExpandColumn animation="slide">
{({ row, rowIndex }) => (
<div className="detail-panel">
<h4>{row.name}'s Details</h4>
<p>Email: {row.email}</p>
<EmployeeHistory employeeId={row.id} />
</div>
)}
</GridDetailPanel>
</DataGrid>
);
}GridDetailPanel Props:
| Prop | Type | Default | Description |
|---|---|---|---|
children |
(ctx: DetailPanelContext) => ReactNode |
Required | Render function for panel content |
showExpandColumn |
boolean |
true |
Show expand/collapse chevron column |
animation |
'slide' | 'fade' | false |
'slide' |
Animation style for expand/collapse |
Custom Tool Panels with GridToolPanel
Add custom sidebar panels to the grid shell:
import { DataGrid, GridToolPanel, GridToolButtons } from '@toolbox-web/grid-react';
import { ShellPlugin } from '@toolbox-web/grid/all';
function EmployeeGrid() {
const config: ReactGridConfig<Employee> = {
columns: [...],
plugins: [new ShellPlugin()],
};
return (
<DataGrid rows={employees} gridConfig={config}>
{/* Toolbar buttons */}
<GridToolButtons>
<button onClick={handleExport}>Export CSV</button>
<button onClick={handlePrint}>Print</button>
</GridToolButtons>
{/* Custom sidebar panel */}
<GridToolPanel id="quick-filters" title="Quick Filters" icon="🔍" order={10}>
{({ grid }) => (
<div className="filter-panel">
<label>
Department:
<select onChange={(e) => applyFilter(grid, 'department', e.target.value)}>
<option value="">All</option>
<option value="Engineering">Engineering</option>
<option value="Marketing">Marketing</option>
</select>
</label>
</div>
)}
</GridToolPanel>
</DataGrid>
);
}GridToolPanel Props:
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
Required | Unique panel identifier |
title |
string |
Required | Panel title in accordion header |
children |
(ctx: ToolPanelContext) => ReactNode |
Required | Render function for panel content |
icon |
string |
- | Icon for the accordion header |
tooltip |
string |
- | Tooltip text for header |
order |
number |
100 |
Panel sort order (lower = higher) |
Using Refs
Access the grid instance for programmatic control:
import { DataGrid, DataGridRef } from '@toolbox-web/grid-react';
import { useRef } from 'react';
function MyComponent() {
const gridRef = useRef<DataGridRef>(null);
const handleExport = async () => {
const config = await gridRef.current?.getConfig();
console.log('Columns:', config?.columns);
};
return (
<>
<button onClick={handleExport}>Export</button>
<DataGrid ref={gridRef} rows={employees} />
</>
);
}useGrid Hook
For more complex scenarios, use the useGrid hook:
import { DataGrid, useGrid } from '@toolbox-web/grid-react';
function MyComponent() {
const { ref, isReady, forceLayout } = useGrid<Employee>();
return (
<>
<button onClick={() => forceLayout()}>Refresh Layout</button>
<DataGrid ref={ref} rows={employees} />
</>
);
}Event Handling
Via Props
<DataGrid
rows={employees}
onCellEdit={(e) => console.log('Edited:', e.detail)}
onRowClick={(e) => console.log('Clicked:', e.detail.row)}
onSortChange={(e) => console.log('Sort:', e.detail)}
/>Via useGridEvent Hook
import { DataGrid, useGridEvent, DataGridRef } from '@toolbox-web/grid-react';
function MyComponent() {
const gridRef = useRef<DataGridRef>(null);
useGridEvent(gridRef, 'selection-change', (event) => {
console.log('Selected:', event.detail.selectedRows);
});
return <DataGrid ref={gridRef} rows={employees} />;
}Plugins
Use plugins from @toolbox-web/grid/all:
import { DataGrid } from '@toolbox-web/grid-react';
import { SelectionPlugin, FilteringPlugin } from '@toolbox-web/grid/all';
function MyComponent() {
return (
<DataGrid
rows={employees}
gridConfig={{
columns: [...],
plugins: [
new SelectionPlugin({ mode: 'row' }),
new FilteringPlugin({ debounceMs: 200 }),
],
}}
/>
);
}Custom Styles
Inject custom CSS into the grid's shadow DOM:
<DataGrid
rows={employees}
customStyles={`
.my-custom-cell {
background: #f0f0f0;
padding: 8px;
}
`}
/>API Reference
DataGrid Props
| Prop | Type | Description |
|---|---|---|
rows |
TRow[] |
Row data to display |
columns |
ColumnConfig[] |
Column definitions |
gridConfig |
GridConfig |
Full configuration object |
fitMode |
'stretch' | 'fit-columns' | 'auto-fit' |
Column sizing mode |
editOn |
'click' | 'dblclick' | 'none' |
Edit trigger |
customStyles |
string |
CSS to inject into shadow DOM |
onRowsChange |
(rows: TRow[]) => void |
Rows changed callback |
onCellEdit |
(event: CustomEvent) => void |
Cell edited callback |
onRowClick |
(event: CustomEvent) => void |
Row clicked callback |
GridColumn Props
| Prop | Type | Description |
|---|---|---|
field |
string |
Field key in row object |
header |
string |
Column header text |
type |
'string' | 'number' | 'date' | 'boolean' |
Data type |
editable |
boolean |
Enable editing |
sortable |
boolean |
Enable sorting |
resizable |
boolean |
Enable column resizing |
width |
string | number |
Column width |
children |
(ctx: CellRenderContext) => ReactNode |
Custom renderer |
editor |
(ctx: ColumnEditorContext) => ReactNode |
Custom editor |
DataGridRef Methods
| Method | Description |
|---|---|
getConfig() |
Get effective configuration |
ready() |
Wait for grid ready |
forceLayout() |
Force layout recalculation |
toggleGroup(key) |
Toggle group expansion |
registerStyles(id, css) |
Register custom styles |
unregisterStyles(id) |
Remove custom styles |
Requirements
- React 18.0.0 or higher
- @toolbox-web/grid 0.2.0 or higher
License
MIT