%# Data table: sortable headers, row-select, typed cells, badges, kebab row actions. Mirrors the html-css-foundation markup; zero-JS (sort = links, select highlight = CSS). Config: caption?, selectable?, actions? sr-only caption; toggle the check / kebab columns columns: { label, sortable?, sort?: "asc"|"desc", href?, className? }[] rows: { name?, cells: Cell[], actions?: Action[] }[] Cell ∈ string | { text, className? } | { user:{name,initials} } | { rowHeader:{text,href?} } | { badge:{tone,label} } | { html, className? } user + rowHeader cells render as
| <% } -%> <% columns.forEach((col) => { -%> <% if (col.sortable) { -%> | aria-sort="ascending"<% } else if (col.sort === "desc") { %> aria-sort="descending"<% } %><% if (col.className) { %> class="<%= col.className %>"<% } %>><%= col.label %> | <% } else { -%>class="<%= col.className %>"<% } %>><%= col.label %> | <% } -%> <% }) -%> <% if (withActions) { -%>Actions | <% } -%>|||||
|---|---|---|---|---|---|---|---|---|
| "> | <% } -%> <% (row.cells || []).forEach((cell) => { -%> <% if (typeof cell === "string") { -%><%= cell %> | <% } else if (cell.user) { -%><%= cell.user.name %> | <% } else if (cell.rowHeader) { -%><% if (cell.rowHeader.href) { %><%= cell.rowHeader.text %><% } else { %><%= cell.rowHeader.text %><% } %> | <% } else if (cell.badge) { -%><%= cell.badge.label %> | <% } else if (cell.html != null) { -%>class="<%= cell.className %>"<% } %>><%- cell.html %> | <% } else { -%>class="<%= cell.className %>"<% } %>><%= cell.text %> | <% } -%> <% }) -%> <% if (withActions) { -%> <% if ((row.actions || []).length) { -%><% } else { -%> | <% } -%> <% } -%> |