Package Exports
- @toolbox-web/grid
- @toolbox-web/grid/all
- @toolbox-web/grid/plugins/clipboard
- @toolbox-web/grid/plugins/column-virtualization
- @toolbox-web/grid/plugins/context-menu
- @toolbox-web/grid/plugins/export
- @toolbox-web/grid/plugins/filtering
- @toolbox-web/grid/plugins/grouping-columns
- @toolbox-web/grid/plugins/grouping-rows
- @toolbox-web/grid/plugins/master-detail
- @toolbox-web/grid/plugins/multi-sort
- @toolbox-web/grid/plugins/pinned-columns
- @toolbox-web/grid/plugins/pinned-rows
- @toolbox-web/grid/plugins/pivot
- @toolbox-web/grid/plugins/reorder
- @toolbox-web/grid/plugins/selection
- @toolbox-web/grid/plugins/server-side
- @toolbox-web/grid/plugins/tree
- @toolbox-web/grid/plugins/undo-redo
- @toolbox-web/grid/plugins/visibility
- @toolbox-web/grid/themes/dg-theme-contrast.css
- @toolbox-web/grid/themes/dg-theme-large.css
- @toolbox-web/grid/themes/dg-theme-standard.css
- @toolbox-web/grid/themes/dg-theme-vibrant.css
- @toolbox-web/grid/umd/grid.all.umd.js
- @toolbox-web/grid/umd/grid.all.umd.js.map
- @toolbox-web/grid/umd/grid.umd.js
- @toolbox-web/grid/umd/grid.umd.js.map
- @toolbox-web/grid/umd/plugins/clipboard.umd.js
- @toolbox-web/grid/umd/plugins/clipboard.umd.js.map
- @toolbox-web/grid/umd/plugins/column-virtualization.umd.js
- @toolbox-web/grid/umd/plugins/column-virtualization.umd.js.map
- @toolbox-web/grid/umd/plugins/context-menu.umd.js
- @toolbox-web/grid/umd/plugins/context-menu.umd.js.map
- @toolbox-web/grid/umd/plugins/export.umd.js
- @toolbox-web/grid/umd/plugins/export.umd.js.map
- @toolbox-web/grid/umd/plugins/filtering.umd.js
- @toolbox-web/grid/umd/plugins/filtering.umd.js.map
- @toolbox-web/grid/umd/plugins/grouping-columns.umd.js
- @toolbox-web/grid/umd/plugins/grouping-columns.umd.js.map
- @toolbox-web/grid/umd/plugins/grouping-rows.umd.js
- @toolbox-web/grid/umd/plugins/grouping-rows.umd.js.map
- @toolbox-web/grid/umd/plugins/master-detail.umd.js
- @toolbox-web/grid/umd/plugins/master-detail.umd.js.map
- @toolbox-web/grid/umd/plugins/multi-sort.umd.js
- @toolbox-web/grid/umd/plugins/multi-sort.umd.js.map
- @toolbox-web/grid/umd/plugins/pinned-columns.umd.js
- @toolbox-web/grid/umd/plugins/pinned-columns.umd.js.map
- @toolbox-web/grid/umd/plugins/pinned-rows.umd.js
- @toolbox-web/grid/umd/plugins/pinned-rows.umd.js.map
- @toolbox-web/grid/umd/plugins/pivot.umd.js
- @toolbox-web/grid/umd/plugins/pivot.umd.js.map
- @toolbox-web/grid/umd/plugins/reorder.umd.js
- @toolbox-web/grid/umd/plugins/reorder.umd.js.map
- @toolbox-web/grid/umd/plugins/selection.umd.js
- @toolbox-web/grid/umd/plugins/selection.umd.js.map
- @toolbox-web/grid/umd/plugins/server-side.umd.js
- @toolbox-web/grid/umd/plugins/server-side.umd.js.map
- @toolbox-web/grid/umd/plugins/tree.umd.js
- @toolbox-web/grid/umd/plugins/tree.umd.js.map
- @toolbox-web/grid/umd/plugins/undo-redo.umd.js
- @toolbox-web/grid/umd/plugins/undo-redo.umd.js.map
- @toolbox-web/grid/umd/plugins/visibility.umd.js
- @toolbox-web/grid/umd/plugins/visibility.umd.js.map
Readme
@toolbox-web/grid
A high-performance, framework-agnostic data grid built with pure TypeScript and native Web Components. Zero runtime dependencies.
Installation
npm install @toolbox-web/gridQuick Start
import '@toolbox-web/grid';
const grid = document.createElement('tbw-grid');
grid.columns = [
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
];
grid.rows = data;
document.body.appendChild(grid);[!TIP] For complete examples, see the Storybook documentation.
Configuration
The grid supports multiple configuration methods, all converging into a single source of truth (effectiveConfig).
Configuration Methods
1. Via gridConfig (recommended for complex setups):
grid.gridConfig = {
columns: [{ field: 'name' }, { field: 'age', type: 'number' }],
fitMode: 'stretch',
editOn: 'dblclick',
plugins: [new SelectionPlugin({ mode: 'row' })],
shell: { header: { title: 'My Data Grid' } },
};2. Via individual properties (convenience for simple cases):
grid.columns = [{ field: 'name' }, { field: 'age' }];
grid.fitMode = 'stretch';
grid.editOn = 'dblclick';3. Via Light DOM (declarative HTML):
<tbw-grid>
<tbw-grid-column field="name" header="Name" sortable></tbw-grid-column>
<tbw-grid-column field="age" header="Age" type="number"></tbw-grid-column>
<tbw-grid-header title="My Data Grid">
<tbw-grid-header-content>
<span>Custom content</span>
</tbw-grid-header-content>
</tbw-grid-header>
</tbw-grid>Precedence
When the same property is set via multiple methods, higher precedence wins:
- Individual props (
fitMode,editOn) - highest columnsprop- Light DOM elements
gridConfigproperty - lowest
Features
Core Capabilities
| Feature | Description |
|---|---|
| Virtualization | Row and column virtualization for datasets with 100k+ rows |
| Keyboard Navigation | Full keyboard support including arrow keys, Tab, Enter, Home/End, PageUp/PageDown |
| Accessibility | ARIA attributes and screen reader support |
| Theming | CSS custom properties with 4 built-in themes |
| Column Inference | Automatic column type detection from data |
Editing
| Feature | Description |
|---|---|
| Inline Editing | Cell and row editing modes with configurable triggers |
| Undo/Redo | Edit history with Ctrl+Z / Ctrl+Y |
| Clipboard | Copy/paste with configurable delimiters |
| Change Tracking | Track modified rows with commit/reset lifecycle |
Data Operations
| Feature | Description |
|---|---|
| Sorting | Single and multi-column sorting |
| Filtering | Text, number, date, set, and boolean filters |
| Aggregations | Built-in aggregators (sum, avg, count, min, max) plus custom functions |
| Row Grouping | Hierarchical grouping with nested aggregations |
| Tree Data | Nested data structures with expand/collapse |
| Pivot Tables | Data transformation with row/column groups |
| Server-Side Data | Lazy loading with block caching |
Column Features
| Feature | Description |
|---|---|
| Pinning | Sticky columns on left or right edges |
| Resizing | Drag-to-resize with auto-sizing |
| Reordering | Drag-and-drop repositioning |
| Visibility | Show/hide columns programmatically or via UI |
| Header Groups | Multi-level column headers |
Selection & Export
| Feature | Description |
|---|---|
| Selection Modes | Cell, row, or range selection |
| Context Menus | Configurable right-click menus |
| Master/Detail | Expandable detail rows |
| Export | CSV, Excel (XML), and JSON formats |
API Reference
Element
<tbw-grid></tbw-grid>Properties
| Property | Type | Description |
|---|---|---|
rows |
T[] |
Data array |
columns |
ColumnConfig[] |
Column definitions (→ gridConfig.columns) |
gridConfig |
GridConfig |
Full configuration object (single source of truth) |
fitMode |
'stretch' | 'fixed' |
Column sizing behavior (→ gridConfig.fitMode) |
editOn |
'click' | 'dblclick' |
Edit trigger (→ gridConfig.editOn) |
Methods
| Method | Returns | Description |
|---|---|---|
ready() |
Promise<void> |
Resolves when fully initialized |
forceLayout() |
Promise<void> |
Force re-layout |
getConfig() |
Promise<GridConfig> |
Get effective configuration |
resetChangedRows(silent?) |
Promise<void> |
Clear change tracking |
beginBulkEdit(rowIndex) |
Promise<void> |
Start row editing |
commitActiveRowEdit() |
Promise<void> |
Commit current edit |
setColumnVisible(field, visible) |
boolean |
Set column visibility |
getAllColumns() |
ColumnInfo[] |
Get all columns with visibility status |
Events
| Event | Detail | Description |
|---|---|---|
cell-commit |
CellCommitDetail |
Cell value committed |
row-commit |
RowCommitDetail |
Row edit committed |
sort-change |
SortChangeDetail |
Sort state changed |
column-resize |
ColumnResizeDetail |
Column resized |
column-visibility |
ColumnVisibilityDetail |
Column visibility changed |
activate-cell |
ActivateCellDetail |
Cell activated |
Import event names from the DGEvents constant:
import { DGEvents } from '@toolbox-web/grid';
grid.addEventListener(DGEvents.CELL_COMMIT, handler);Column Configuration
interface ColumnConfig {
field: string; // Required: property key in row data
header?: string; // Display label (defaults to field name)
type?: 'string' | 'number' | 'date' | 'boolean' | 'select';
width?: number | string; // Pixels, '1fr', or percentage
sortable?: boolean; // Enable sorting (default: true)
resizable?: boolean; // Enable resize (default: true)
editable?: boolean; // Enable editing
hidden?: boolean; // Initially hidden
lockVisible?: boolean; // Prevent hiding
format?: (value: any, row: T) => string;
}Plugin-Provided Column Properties
Some column properties are added via TypeScript module augmentation when you import a plugin:
| Property | Plugin | Description |
|---|---|---|
sticky |
pinnedColumns |
Pin column left or right |
group |
groupingColumns |
Column header group |
filterable |
filtering |
Enable column filter |
filterType |
filtering |
Filter type |
reorderable |
reorder |
Enable column reordering |
See Storybook for complete configuration examples.
Grid Configuration
interface GridConfig {
columns?: ColumnConfig[];
fitMode?: 'stretch' | 'fixed';
editOn?: 'click' | 'dblclick';
plugins?: BaseGridPlugin[]; // Array of plugin class instances
icons?: GridIcons; // Centralized icon configuration
shell?: ShellConfig; // Optional header bar and tool panels
}Icons Configuration
The grid provides a centralized icon system via gridConfig.icons. All plugins (tree, grouping, sorting, context menus, etc.) automatically use these icons, ensuring visual consistency across the entire grid.
import { DEFAULT_GRID_ICONS } from '@toolbox-web/grid';
grid.gridConfig = {
icons: {
expand: '▶', // Collapsed tree/group/detail icon
collapse: '▼', // Expanded tree/group/detail icon
sortAsc: '▲', // Sort ascending indicator
sortDesc: '▼', // Sort descending indicator
sortNone: '⇅', // Unsorted column indicator
submenuArrow: '▶', // Context menu submenu arrow
dragHandle: '⋮⋮', // Column reorder drag handle
},
};Icons can be strings (text or HTML) or HTMLElement instances. Plugins use grid-level icons by default but can override with their own config when needed.
Plugin Configuration Example
Plugins are class instances that you import and instantiate with their configuration:
import { GroupingRowsPlugin } from '@toolbox-web/grid/plugins/grouping-rows';
import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
grid.gridConfig = {
plugins: [
new GroupingRowsPlugin({
groupOn: (row) => row.category,
fullWidth: false,
aggregators: { total: 'sum' },
}),
new SelectionPlugin({
mode: 'row',
multiple: true,
}),
],
};Theming
Apply a built-in theme:
@import '@toolbox-web/grid/themes/dg-theme-standard.css';Available themes: standard, contrast, vibrant, large
Custom Theming
Override CSS custom properties on tbw-grid or a parent element:
tbw-grid {
--tbw-color-bg: #ffffff;
--tbw-color-fg: #1a1a1a;
--tbw-color-border: #e5e5e5;
--tbw-color-header-bg: #f5f5f5;
--tbw-row-height: 32px;
}For a complete list of available CSS variables, see grid.css.
Core CSS Variables
| Variable | Description |
|---|---|
--tbw-color-bg |
Grid background |
--tbw-color-fg |
Text color |
--tbw-color-fg-muted |
Secondary text color |
--tbw-color-accent |
Accent/primary color |
--tbw-color-border |
Border color |
--tbw-color-header-bg |
Header background |
--tbw-color-header-fg |
Header text color |
--tbw-color-selection |
Selected cell/row background |
--tbw-color-row-hover |
Row hover background |
--tbw-row-height |
Data row height |
--tbw-header-height |
Header row height |
--tbw-font-family |
Font family |
--tbw-font-size |
Base font size |
--tbw-border-radius |
Corner radius |
--tbw-focus-outline |
Focus ring style |
Plugin CSS Variables
Plugins define their own CSS variables following a layered fallback pattern:
var(--tbw-{plugin}-{property}, var(--tbw-{global-property}))This allows you to:
- Override a specific plugin's style:
--tbw-selection-bg - Or let it inherit from the global variable:
--tbw-color-selection
Example: Customizing the selection plugin
tbw-grid {
/* Override just the selection plugin's background */
--tbw-selection-bg: #e0f2fe;
/* Or change the global selection color (affects all plugins) */
--tbw-color-selection: #e0f2fe;
}Common plugin variables:
| Plugin | Variables |
|---|---|
selection |
--tbw-selection-bg, --tbw-selection-border |
filtering |
--tbw-filtering-panel-bg, --tbw-filtering-input-border |
contextMenu |
--tbw-context-menu-bg, --tbw-context-menu-hover |
pinnedRows |
--tbw-pinned-rows-bg, --tbw-pinned-rows-border |
tree |
--tbw-tree-indent, --tbw-tree-toggle-color |
Check each plugin's styles property for the full list of customizable variables.
Plugins
The grid uses a plugin architecture for optional features. Each plugin has its own documentation:
| Plugin | Description | Documentation |
|---|---|---|
| Selection | Cell, row, and range selection | README |
| Multi-Sort | Multi-column sorting | README |
| Filtering | Column filters | README |
| Row Grouping | Row grouping with aggregation | README |
| Column Grouping | Column header groups | README |
| Tree | Tree/hierarchical data | README |
| Pivot | Pivot table transformation | README |
| Master-Detail | Expandable detail rows | README |
| Pinned Columns | Sticky columns | README |
| Reorder | Column drag reordering | README |
| Visibility | Column visibility UI | README |
| Clipboard | Copy/paste | README |
| Context Menu | Right-click menus | README |
| Export | CSV/Excel/JSON export | README |
| Undo/Redo | Edit history | README |
| Server-Side | Lazy data loading | README |
| Pinned Rows | Footer aggregations | README |
| Column Virtualization | Horizontal virtualization | README |
Creating Custom Plugins
Plugins extend the BaseGridPlugin class:
import { BaseGridPlugin } from '@toolbox-web/grid';
interface MyPluginConfig {
myOption?: boolean;
}
export class MyPlugin extends BaseGridPlugin<MyPluginConfig> {
readonly name = 'myPlugin';
readonly version = '1.0.0';
// CSS injected into shadow DOM
readonly styles = `
.my-element { color: red; }
`;
// Default config (override in constructor)
protected get defaultConfig(): Partial<MyPluginConfig> {
return { myOption: true };
}
// Called when plugin is attached to grid
attach(grid: GridElement): void {
super.attach(grid);
// Setup event listeners, etc.
}
// Called when plugin is detached
detach(): void {
// Cleanup
}
// Hook: Called after grid renders
afterRender(): void {
// DOM manipulation
}
}Accessing Plugin Instances
Use grid.getPlugin() to get a plugin instance for inter-plugin communication or API access:
import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
const selection = grid.getPlugin(SelectionPlugin);
if (selection) {
selection.selectAll();
}TypeScript
All types are exported from the package:
import type { GridConfig, ColumnConfig, CellCommitDetail, BaseGridPlugin } from '@toolbox-web/grid';Plugin Type Exports
Each plugin exports its class and configuration types from its own entry point:
import { SelectionPlugin, SelectionConfig } from '@toolbox-web/grid/plugins/selection';
import { FilteringPlugin, FilterConfig, FilterModel } from '@toolbox-web/grid/plugins/filtering';
import { TreePlugin, TreeConfig, TreeState } from '@toolbox-web/grid/plugins/tree';All-in-One Bundle
For convenience, you can import everything from the all-in-one bundle:
import {
SelectionPlugin,
FilteringPlugin,
TreePlugin,
// ... all other plugins
} from '@toolbox-web/grid/all';Note: This includes all plugins in your bundle. For smaller bundles, import plugins individually.
Browser Support
Modern browsers with Web Components support (Chrome, Firefox, Safari, Edge).
Development
bun nx build grid # Build
bun nx test grid # Test
bun nx test grid --coverage # Test with coverage
bun nx storybook storybook-app # Storybook (port 4400)For architecture details, rendering pipeline, and plugin development, see ARCHITECTURE.md.
License
MIT