JSPM

  • Created
  • Published
  • Downloads 3942
  • Score
    100M100P100Q123580F
  • License MIT

Zero-dependency, framework-agnostic data grid web component with virtualization, sorting, filtering, editing, and 20+ plugins. Works in vanilla JS, React, Vue, Angular, and any framework.

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/editing
  • @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/print
  • @toolbox-web/grid/plugins/reorder
  • @toolbox-web/grid/plugins/responsive
  • @toolbox-web/grid/plugins/row-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/editing.umd.js
  • @toolbox-web/grid/umd/plugins/editing.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/print.umd.js
  • @toolbox-web/grid/umd/plugins/print.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/responsive.umd.js
  • @toolbox-web/grid/umd/plugins/responsive.umd.js.map
  • @toolbox-web/grid/umd/plugins/row-reorder.umd.js
  • @toolbox-web/grid/umd/plugins/row-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 License: MIT 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';
import { createGrid } from '@toolbox-web/grid';

const grid = createGrid<Employee>({
  columns: [
    { field: 'name', header: 'Name' },
    { field: 'email', header: 'Email' },
  ],
});
grid.rows = data;
document.body.appendChild(grid);

Factory Functions

Use createGrid<T>() for typed grid creation (avoids manual casting):

import { createGrid, queryGrid } from '@toolbox-web/grid';

// Create a new typed grid
const grid = createGrid<Employee>({
  columns: [{ field: 'name' }],
  plugins: [new SelectionPlugin()],
});

// Query an existing grid with proper typing
const existing = queryGrid<Employee>('#my-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',
  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';

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) - highest
  2. columns prop
  3. Light DOM elements
  4. gridConfig property - lowest

Features

Core Capabilities
VirtualizationRow and column virtualization for datasets with 100k+ rows
Keyboard NavigationFull keyboard support including arrow keys, Tab, Enter, Home/End, PageUp/PageDown
AccessibilityARIA attributes and screen reader support
ThemingCSS custom properties with 6 built-in themes
Column InferenceAutomatic column type detection from data
Editing
Inline EditingCell and row editing modes with configurable triggers
Undo/RedoEdit history with Ctrl+Z / Ctrl+Y
ClipboardCopy/paste with configurable delimiters
Change TrackingTrack modified rows with commit/reset lifecycle
Data Operations
SortingSingle and multi-column sorting
FilteringText, number, date, set, and boolean filters
AggregationsBuilt-in aggregators (sum, avg, count, min, max) plus custom functions
Row GroupingHierarchical grouping with nested aggregations
Tree DataNested data structures with expand/collapse
Pivot TablesData transformation with row/column groups
Server-Side DataLazy loading with block caching
Column Features
PinningSticky columns on left or right edges
ResizingDrag-to-resize with auto-sizing
ReorderingDrag-and-drop repositioning
VisibilityShow/hide columns programmatically or via UI
Header GroupsMulti-level column headers
Selection & Export
Selection ModesCell, row, or range selection
Context MenusConfigurable right-click menus
Master/DetailExpandable detail rows
ExportCSV, Excel (XML), and JSON formats

API Reference

Element

<tbw-grid></tbw-grid>

HTML Attributes

The grid supports configuration via HTML attributes with JSON-serialized values:

Attribute Type Description
rows JSON Data array (JSON-serialized)
columns JSON Column definitions (JSON-serialized)
grid-config JSON Full configuration object (JSON-serialized)
fit-mode string Column sizing: 'stretch' or 'fixed'

Example with HTML attributes:

<tbw-grid
  rows='[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]'
  columns='[{"field":"id","header":"ID"},{"field":"name","header":"Name"}]'
  fit-mode="stretch"
>
</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)
loading boolean | LoadingContext Grid-level loading state
columnState GridColumnState[] Get/set column widths, order, visibility, sort
changedRows T[] (readonly) Rows with pending edits (requires EditingPlugin)
sortState Map<string, SortState> (readonly) Current sort state per column
focusedCell { rowIndex, colIndex, field } | null (readonly) Currently focused cell position

Methods

Data Methods

Method Returns Description
ready() Promise<void> Resolves when fully initialized
forceLayout() Promise<void> Force re-layout
getConfig() Promise<GridConfig> Get effective configuration
getRowId(row) string Get unique identifier for a row
getRow(id) T | undefined Get row by its ID
updateRow(id, changes, source?) void Update a single row by ID
updateRows(updates, source?) void Batch update multiple rows

Editing Methods (require EditingPlugin)

Method Returns Description
beginBulkEdit(rowIndex) void Start row editing
commitActiveRowEdit() void Commit current row edit
cancelActiveRowEdit() void Cancel current row edit
resetChangedRows(silent?) void Clear change tracking

Focus & Navigation Methods

Method Returns Description
focusCell(rowIndex, column) void Focus a cell by index or field name
scrollToRow(rowIndex, options?) void Scroll row into view
scrollToRowById(rowId, options?) void Scroll to row by ID

Column Methods

Method Returns Description
setColumnVisible(field, visible) boolean Set column visibility
toggleColumnVisibility(field) void Toggle column visible/hidden
isColumnVisible(field) boolean Check if column is visible
showAllColumns() void Show all hidden columns
setColumnOrder(order) void Reorder columns by field array
getColumnOrder() string[] Get current column order
getAllColumns() ColumnInfo[] Get all columns with visibility status
getColumnState() GridColumnState[] Get column state (for persistence)
resetColumnState() void Reset to initial column configuration

Shell Methods

Method Returns Description
openToolPanel() void Open the tool panel sidebar
closeToolPanel() void Close the tool panel sidebar
toggleToolPanel() void Toggle tool panel open/closed
toggleToolPanelSection(sectionId) void Toggle a tool panel accordion section
isToolPanelOpen boolean (getter) Whether tool panel is open
expandedToolPanelSections string[] (getter) IDs of expanded accordion sections
getToolPanels() ToolPanelDefinition[] Get registered tool panels
registerToolPanel(panel) void Register a custom tool panel
unregisterToolPanel(panelId) void Remove a registered tool panel
registerHeaderContent(content) void Add custom header content
unregisterHeaderContent(contentId) void Remove custom header content
registerToolbarContent(content) void Add custom toolbar button
unregisterToolbarContent(contentId) void Remove custom toolbar button

Style Methods

Method Returns Description
registerStyles(id, css) void Register custom CSS (adoptedStyleSheets)
unregisterStyles(id) void Remove custom CSS by ID
getRegisteredStyles() Map<string, CSSStyleSheet> Get all registered styles

Loading Methods

Method Returns Description
setRowLoading(rowId, loading) void Show/hide row loading indicator
setCellLoading(rowId, field, loading) void Show/hide cell loading indicator
isRowLoading(rowId) boolean Check if row is loading
isCellLoading(rowId, field) boolean Check if cell is loading
clearAllLoading() void Clear all loading states

Row Mutation Methods

Method Returns Description
insertRow(index, row, animate?) Promise<void> Insert a row at a visible position (auto-animates)
removeRow(index, animate?) Promise<T | undefined> Remove a row at a visible position (auto-animates)

Animation Methods

Method Returns Description
animateRow(index, type) Promise<boolean> Animate a single row (change/insert/remove)
animateRows(indices, type) Promise<number> Animate multiple rows at once
animateRowById(id, type) Promise<boolean> Animate row by ID (resolves true if found)

Plugin Methods

Method Returns Description
getPluginByName(name) Plugin | undefined Get plugin instance by name — preferred (type-safe, no import needed)
getPlugin(PluginClass) P | undefined Get plugin instance by class (requires import)

Events

Core Events

Event Detail Description
cell-click CellClickDetail Cell clicked
row-click RowClickDetail Row clicked
cell-activate CellActivateDetail Cell activated via keyboard or click (cancelable)
cell-change CellChangeDetail Row updated via Row Update API
sort-change SortChangeDetail Sort state changed
column-resize ColumnResizeDetail Column resized
column-state-change GridColumnState Column state changed
group-toggle GroupToggleDetail Row group expanded/collapsed
mount-external-view ExternalMountViewDetail External view mount request
mount-external-editor ExternalMountEditorDetail External editor mount request

Editing Events (require EditingPlugin)

Event Detail Description
cell-commit CellCommitDetail Cell value committed (cancelable)
row-commit RowCommitDetail Row edit committed (cancelable)
edit-open EditOpenDetail Row entered edit mode
edit-close EditCloseDetail Row left edit mode
changed-rows-reset ChangedRowsResetDetail Change tracking cleared
dirty-change DirtyChangeDetail Row dirty state changed

Deprecated Events

Event Detail Description
activate-cell ActivateCellDetail ⚠️ Deprecated. Use cell-activate instead

Import event names from the DGEvents constant:

import { DGEvents } from '@toolbox-web/grid';
grid.addEventListener(DGEvents.CELL_COMMIT, handler);

Insert & Remove Rows

Add or remove rows at a specific visible position without re-running the sort/filter pipeline:

// Insert with animation (default)
grid.insertRow(3, newEmployee);

// Insert without animation
grid.insertRow(3, newEmployee, false);

// Remove with fade-out animation and await completion
await grid.removeRow(5);

// Remove without animation
const removed = await grid.removeRow(5, false);

Both methods update the source data automatically. The next full grid.rows = freshData assignment re-sorts/re-filters normally. Do not use them for bulk data refreshes — assign grid.rows directly instead.

Row Animation API

All animation methods return Promises that resolve when the animation completes:

// Flash highlight for updated row
await grid.animateRow(5, 'change');

// Animate by row ID
await grid.animateRowById('emp-123', 'change');

// Animate multiple rows
await grid.animateRows([0, 1, 2], 'change');

Note: insertRow and removeRow handle animation automatically — you only need animateRow directly for highlighting existing rows (e.g., after an external data update).

Animation Types: 'change' | 'insert' | 'remove'

Animation Configuration

Configure animation behavior globally:

grid.gridConfig = {
  animation: {
    mode: 'on', // 'on' | 'off' | 'reduced-motion'
    style: 'smooth', // Animation easing (alias for `easing`)
    duration: 200, // Default duration in ms
  },
};

The grid respects prefers-reduced-motion media query automatically when mode is 'reduced-motion'.


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';
  plugins?: BaseGridPlugin[]; // Array of plugin class instances
  icons?: GridIcons; // Centralized icon configuration
  shell?: ShellConfig; // Optional header bar and tool panels
  getRowId?: (row: T) => string; // Custom row ID resolver
  typeDefaults?: Record<string, TypeDefault<T>>; // Type-level renderers/editors
}

Row Identification

The grid uses row IDs for the Row Update API. By default, it looks for id or _id properties on row objects. Rows without an identifiable ID are not accessible via the Row Update API. For custom ID fields, provide a getRowId function:

grid.gridConfig = {
  columns: [...],
  getRowId: (row) => row.employeeNumber, // Use custom field as ID
};

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.

Type-Level Defaults

Define renderers and editors at the type level that apply to all columns with matching type:

grid.gridConfig = {
  typeDefaults: {
    country: {
      renderer: (ctx) => {
        const span = document.createElement('span');
        span.textContent = `🌍 ${ctx.value}`;
        return span;
      },
      editor: (ctx) => {
        const select = document.createElement('select');
        ['USA', 'UK', 'Germany'].forEach((c) => {
          const opt = document.createElement('option');
          opt.value = c;
          opt.textContent = c;
          select.appendChild(opt);
        });
        select.value = ctx.value;
        select.onchange = () => ctx.commit(select.value);
        return select;
      },
    },
    currency: {
      editorParams: { min: 0, step: 0.01 },
    },
  },
  columns: [
    { field: 'country', type: 'country', editable: true }, // Uses country renderer/editor
    { field: 'salary', type: 'currency', editable: true }, // Uses currency editorParams
  ],
};

Resolution Priority: Column-level → gridConfig.typeDefaults → Framework adapter → Built-in

Framework adapters (@toolbox-web/grid-react, @toolbox-web/grid-angular) provide app-level type registries for React/Angular components.

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, bootstrap, material

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
Editing Inline cell editing README
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
Pinned Rows Footer aggregations README
Reorder Column drag reordering README
Row Reorder Row drag reordering README
Visibility Column visibility UI README
Responsive Card layout for mobile README
Clipboard Copy/paste README
Context Menu Right-click menus README
Export CSV/Excel/JSON export README
Print Print-optimized layout README
Undo/Redo Edit history README
Server-Side Lazy data loading README
Column Virtualization Horizontal virtualization README

Creating Custom Plugins

Plugins extend the BaseGridPlugin class:

import { BaseGridPlugin } from '@toolbox-web/grid';
import styles from './my-plugin.css?inline';

interface MyPluginConfig {
  myOption?: boolean;
}

export class MyPlugin extends BaseGridPlugin<MyPluginConfig> {
  readonly name = 'myPlugin';
  override readonly styles = styles; // CSS imported via Vite

  // Default config (override in constructor)
  protected override get defaultConfig(): Partial<MyPluginConfig> {
    return { myOption: true };
  }

  // Called when plugin is attached to grid
  override attach(grid: GridElement): void {
    super.attach(grid);
    // Setup event listeners using this.disconnectSignal for auto-cleanup
  }

  // Called when plugin is detached
  override detach(): void {
    // Cleanup (listeners with disconnectSignal auto-cleanup)
  }

  // Hook: Called after grid renders
  override afterRender(): void {
    // Access DOM via this.gridElement
  }
}

Inter-Plugin Communication

Plugins can communicate with each other using two systems:

  1. Event Bus - For async notifications between plugins
  2. Query System - For sync state retrieval

Event Bus

Emit and subscribe to plugin events (distinct from DOM events):

import { BaseGridPlugin, type PluginManifest } from '@toolbox-web/grid';

export class MyPlugin extends BaseGridPlugin<MyConfig> {
  // Declare events this plugin emits
  static override readonly manifest: PluginManifest = {
    events: [{ type: 'my-event', description: 'Emitted when something happens' }],
  };

  override attach(grid: GridElementRef): void {
    super.attach(grid);
    // Subscribe to events from other plugins
    this.on('filter-change', (detail) => {
      console.log('Filter changed:', detail);
    });
  }

  private doSomething(): void {
    // Emit to other plugins (not DOM events)
    this.emitPluginEvent('my-event', { data: 'value' });
  }
}

Query System

Respond to queries from other plugins:

import { BaseGridPlugin, type PluginManifest, type PluginQuery } from '@toolbox-web/grid';

export class MyPlugin extends BaseGridPlugin<MyConfig> {
  // Declare queries this plugin handles
  static override readonly manifest: PluginManifest = {
    queries: [{ type: 'canMoveColumn', description: 'Check if column can be moved' }],
  };

  override handleQuery(query: PluginQuery): unknown {
    if (query.type === 'canMoveColumn') {
      const column = query.context as ColumnConfig;
      if (this.isLocked(column)) return false;
      return undefined; // Let other plugins decide
    }
    return undefined;
  }
}

Querying other plugins:

// Simplified API
const responses = grid.query<boolean>('canMoveColumn', column);
const canMove = !responses.includes(false);

// Or full query object
const responses = grid.queryPlugins<boolean>({
  type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,
  context: column,
});

Built-in query types:

Query Type Context Response Description
CAN_MOVE_COLUMN ColumnConfig boolean Can the column be reordered?
GET_CONTEXT_MENU_ITEMS ContextMenuParams ContextMenuItem[] Get menu items for context menu

Plugins can also define custom query types for their own inter-plugin communication.

Accessing Plugin Instances

Use grid.getPluginByName() to get a plugin instance for inter-plugin communication or API access:

const selection = grid.getPluginByName('selection');
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 run build
bun run test
bun run coverage
bun run start

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