lunaDOM Docs
lunaDOM Docs

lunaDOM is a collection of lightweight, accessible shadowdom based web components built with JavaScript.

v0.0.25

The <luna-data-grid> component provides a full-featured data table with sorting, filtering, row selection, and pagination.

Paths

/lunadom/components/data-grid/data-grid.js REQUIRED

Basic Grid

With Filter

Selectable Rows

No rows selected

Customization

Attributes
page-size - Rows per page (default: 10, set 0 to disable)
filter - Initial filter query string
selectable - Enable row checkboxes and selection
striped - Alternating row backgrounds
no-border - Remove outer border and radius
loading - Shows skeleton loading state
empty-label - Text when no results (default: "No results")

Properties
columns - Array of column definitions (JS only)
rows - Array of data objects (JS only)
selected - Set of selected row indices (read-only)

CSS Variables
--luna-grid-bg - Card background
--luna-grid-border - Border color
--luna-grid-header-bg - Header background
--luna-grid-row-hover - Row hover background
--luna-grid-row-selected - Selected row background
--luna-grid-accent - Sort arrow/checkbox accent

Events
luna-sort - sort column or direction changes.
{ key: string, direction: 'asc'|'desc' }

luna-filter - filter query changes.
{ query: string, count: number }

luna-select - row selection changes.
{ selected: number[], rows: object[] }

luna-page - active page changes.
{ page: number, pageSize: number, total: number }

luna-row-click - row is clicked (not on an interactive child).
{ index: number, row: object }

Example Code

<!-- Basic grid --> <luna-data-grid id="grid"></luna-data-grid> <script> const grid = document.getElementById('grid'); // Define columns grid.columns = [ { key: 'name', label: 'Name', sortable: true, filterable: true }, { key: 'email', label: 'Email', sortable: true, filterable: true }, { key: 'role', label: 'Role', sortable: true, width: '120px' } ]; // Set data grid.rows = [ { name: 'Alice', email: 'alice@example.com', role: 'Admin' }, { name: 'Bob', email: 'bob@example.com', role: 'User' } ]; </script> <!-- With filter --> <luna-input id="filter" placeholder="Search..."></luna-input> <luna-data-grid id="grid" striped></luna-data-grid> <script> const grid = document.getElementById('grid'); const filter = document.getElementById('filter'); grid.columns = [ { key: 'name', label: 'Name', sortable: true, filterable: true }, { key: 'salary', label: 'Salary', sortable: true, align: 'right', render: (val) => `$${val.toLocaleString()}` } ]; grid.rows = [ { name: 'John', salary: 95000 }, { name: 'Jane', salary: 105000 } ]; // Connect filter input grid.connectFilter(filter); </script> <!-- Selectable rows --> <luna-data-grid id="grid" selectable></luna-data-grid> <script> const grid = document.getElementById('grid'); grid.columns = [...]; grid.rows = [...]; // Listen to selection changes grid.addEventListener('luna-select', (e) => { console.log('Selected rows:', e.detail.selected); console.log('Selected data:', e.detail.rows); }); </script> <!-- Custom page size --> <luna-data-grid page-size="20"></luna-data-grid> <!-- Disable pagination --> <luna-data-grid page-size="0"></luna-data-grid> <!-- Loading state --> <luna-data-grid loading></luna-data-grid> <!-- Custom column definition --> <script> grid.columns = [ { key: 'name', // Data property key (required) label: 'Full Name', // Header text sortable: true, // Enable sorting filterable: true, // Include in filter width: '200px', // CSS width align: 'left', // left, center, right render: (value, row, index) => { // Custom HTML rendering return `<strong>${value}</strong>`; } } ]; </script> <!-- Event listeners --> <script> grid.addEventListener('luna-sort', (e) => { console.log('Sorted by:', e.detail.key, e.detail.direction); }); grid.addEventListener('luna-filter', (e) => { console.log('Filter query:', e.detail.query); console.log('Matching rows:', e.detail.count); }); grid.addEventListener('luna-page', (e) => { console.log('Page:', e.detail.page); }); grid.addEventListener('luna-row-click', (e) => { console.log('Clicked row:', e.detail.index, e.detail.row); }); </script>