JSPM

  • Created
  • Published
  • Downloads 4026
  • Score
    100M100P100Q123641F
  • License MIT

High-performance data grid web component

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-bootstrap.css
  • @toolbox-web/grid/themes/dg-theme-contrast.css
  • @toolbox-web/grid/themes/dg-theme-large.css
  • @toolbox-web/grid/themes/dg-theme-material.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

npm GitHub Sponsors

A high-performance, framework-agnostic data grid built with pure TypeScript and native Web Components. Zero runtime dependencies.

Installation

npm install @toolbox-web/grid

Quick 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:

  1. Individual props (fitMode, editOn) - highest
  2. columns prop
  3. Light DOM elements
  4. gridConfig property - 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:

  1. Override a specific plugin's style: --tbw-selection-bg
  2. 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.


Support This Project

This grid is built and maintained by a single developer in spare time. If it saves you time or money, consider sponsoring to keep development going:

GitHub Sponsors Patreon

What sponsorship enables:

  • 🚀 Faster feature development (see ROADMAP)
  • 🐛 Priority bug fixes and support
  • 📚 Better documentation and examples
  • 💼 Corporate sponsors get logo placement and priority support

License

MIT