@bw-ui/datatable
December 1, 2025 ยท View on GitHub
Production-ready data table with plugin architecture - Zero dependencies, vanilla JavaScript.
Live Demo โข Documentation โข Plugins
โจ Features
- ๐ชถ Lightweight - ~32KB minified, zero dependencies
- ๐ Plugin Architecture - Extend with official or custom plugins
- โ๏ธ Inline Editing - Double-click to edit cells
- ๐ Search & Filter - Global search across all columns
- โ๏ธ Sorting - Multi-column sorting support
- ๐ Pagination - Built-in pagination controls
- โ Selection - Single/multi row selection with checkboxes
- ๐ฑ Responsive - Mobile-friendly design
- โฟ Accessible - Keyboard navigation, ARIA labels
- ๐จ Themeable - CSS custom properties for styling
๐ฆ Installation
npm install @bw-ui/datatable
๐ Quick Start
ES Modules
import { BWDataTable } from '@bw-ui/datatable';
import '@bw-ui/datatable/dist/bw-datatable.min.css';
const table = new BWDataTable('#my-table', {
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'Editor' },
{ id: 3, name: 'Bob Wilson', email: 'bob@example.com', role: 'Viewer' },
],
});
CDN
<link
rel="stylesheet"
href="https://unpkg.com/@bw-ui/datatable/dist/bw-datatable.min.css"
/>
<script src="https://unpkg.com/@bw-ui/datatable/dist/bw-datatable.min.js"></script>
<div id="my-table"></div>
<script>
const table = new BWDataTable('#my-table', {
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
],
});
</script>
โ๏ธ Options
new BWDataTable('#table', {
// Data
data: [], // Array of row objects
columns: null, // Column definitions (auto-detect if null)
rowId: 'id', // Field to use as row ID
// Features
editable: false, // Enable inline editing
editableColumns: [], // Which columns are editable
selectable: false, // Enable row selection
selectionMode: 'multi', // 'single' | 'multi' | 'none'
sortable: true, // Enable column sorting
paginated: true, // Enable pagination
pageSize: 20, // Rows per page
searchable: true, // Enable global search
// UI
showHeader: true, // Show table header
showFooter: true, // Show pagination footer
loadingText: 'Loading...', // Loading overlay text
emptyText: 'No data', // Empty state text
// Callbacks
onEditEnd: null, // (rowId, columnId, value, oldValue) => {}
onSelect: null, // (selectedIds) => {}
onSort: null, // (column, direction) => {}
onFilter: null, // (filters) => {}
onPageChange: null, // (page) => {}
});
Column Definition
{
columns: [
{
id: 'name', // Unique column ID
header: 'Full Name', // Header text
field: 'name', // Data field (supports dot notation: 'user.name')
type: 'string', // 'string' | 'number' | 'boolean' | 'date'
width: '200px', // Column width
sortable: true, // Enable sorting for this column
editable: true, // Enable editing for this column
hidden: false, // Hide column
render: (value, row) => `<strong>${value}</strong>`, // Custom renderer
},
// ... more columns
],
}
๐ Examples
Editable Table
const table = new BWDataTable('#table', {
data: myData,
editable: true,
editableColumns: ['name', 'email', 'role'],
onEditEnd: (rowId, columnId, value, oldValue) => {
console.log(`Cell [${rowId}][${columnId}]: ${oldValue} โ ${value}`);
// Save to server...
},
});
Selectable Table
const table = new BWDataTable('#table', {
data: myData,
selectable: true,
selectionMode: 'multi',
onSelect: (selectedIds) => {
console.log('Selected:', selectedIds);
},
});
// Get selected rows
const selected = table.getSelected();
Custom Column Rendering
const table = new BWDataTable('#table', {
data: myData,
columns: [
{ id: 'name', header: 'Name' },
{ id: 'email', header: 'Email' },
{
id: 'status',
header: 'Status',
render: (value) =>
value
? '<span class="badge green">Active</span>'
: '<span class="badge red">Inactive</span>',
},
{
id: 'salary',
header: 'Salary',
type: 'number',
render: (value) => `$${value.toLocaleString()}`,
},
],
});
Search & Filter
const table = new BWDataTable('#table', {
data: myData,
searchable: true,
});
// Programmatic filtering
table.filter('global', 'john'); // Search all columns
table.filter('role', 'Admin'); // Filter specific column
Sorting
const table = new BWDataTable('#table', {
data: myData,
sortable: true,
onSort: (column, direction) => {
console.log(`Sorted by ${column} ${direction}`);
},
});
// Programmatic sorting
table.sort('name', 'asc');
table.sort('salary', 'desc');
๐ Plugins
Extend functionality with official plugins:
| Package | Description | Size |
|---|---|---|
| @bw-ui/datatable-history | Undo/Redo (Ctrl+Z) | ~3KB |
| @bw-ui/datatable-export | Export JSON, CSV | ~2KB |
| @bw-ui/datatable-url-state | URL sync | ~2KB |
| @bw-ui/datatable-clipboard | Copy/Paste Excel | ~3KB |
Using Plugins
import { BWDataTable } from '@bw-ui/datatable';
import { HistoryPlugin } from '@bw-ui/datatable-history';
import { ExportPlugin } from '@bw-ui/datatable-export';
const table = new BWDataTable('#table', { data: myData })
.use(HistoryPlugin)
.use(ExportPlugin);
// Now you have undo/redo and export
table.undo();
table.exportCSV();
๐ API Methods
Data
table.getData(); // Get current rows (filtered/sorted)
table.getOriginalData(); // Get original data
table.setData(newData); // Replace all data
table.addRow(row); // Add single row
table.removeRow(rowId); // Remove row by ID
table.updateRow(rowId, data); // Update row data
Selection
table.getSelected(); // Get selected row objects
table.getSelectedIds(); // Get selected row IDs
table.selectAll(); // Select all visible rows
table.clearSelection(); // Clear selection
Sorting & Filtering
table.sort(column, 'asc'); // Sort by column
table.filter('global', term); // Global search
table.filter(column, value); // Column filter
table.clearFilters(); // Clear all filters
Pagination
table.goToPage(2); // Go to page (0-indexed)
table.setPageSize(50); // Change page size
Editing
table.startEdit(rowId, colId); // Start editing cell
table.setCellValue(rowId, colId, value); // Set cell value
Columns
table.getVisibleColumns(); // Get visible columns
table.hideColumn(colId); // Hide column
table.showColumn(colId); // Show column
Rendering
table.render(); // Re-render table
table.setLoading(true); // Show loading overlay
table.destroy(); // Cleanup and remove
๐จ Theming
Customize with CSS custom properties:
:root {
/* Colors */
--bw-dt-bg: #ffffff;
--bw-dt-text: #1a1a1a;
--bw-dt-border: #e5e5e5;
--bw-dt-header-bg: #f8f9fa;
--bw-dt-row-hover: #f5f5f5;
--bw-dt-row-selected: #e3f2fd;
--bw-dt-primary: #2563eb;
/* Spacing */
--bw-dt-cell-padding: 12px 16px;
--bw-dt-border-radius: 8px;
/* Typography */
--bw-dt-font-family: system-ui, sans-serif;
--bw-dt-font-size: 14px;
}
Dark Mode
[data-theme='dark'] {
--bw-dt-bg: #1a1a1a;
--bw-dt-text: #e5e5e5;
--bw-dt-border: #333333;
--bw-dt-header-bg: #252525;
--bw-dt-row-hover: #2a2a2a;
--bw-dt-row-selected: #1e3a5f;
}
โจ๏ธ Keyboard Navigation
| Key | Action |
|---|---|
โ โ โ โ | Navigate cells |
Enter | Start editing focused cell |
Escape | Cancel editing |
Tab | Move to next cell |
Space | Toggle row selection |
Home / End | Jump to first/last cell in row |
Ctrl+Home / Ctrl+End | Jump to first/last row |
๐ What's Included
dist/
โโโ bw-datatable.min.js # IIFE build (for <script>)
โโโ bw-datatable.esm.min.js # ESM build (for import)
โโโ bw-datatable.min.css # Styles
๐ Browser Support
- Chrome 80+
- Firefox 75+
- Safari 13+
- Edge 80+
๐ License
MIT ยฉ BW UI
๐ Issues
Found a bug? Report it here