@trimble-oss/moduswebcomponents
Version:
Modus Web Components is a modern, accessible UI library built with Stencil JS that provides reusable web components following Trimble's Modus design system. This updated version focuses on improved flexibility, enhanced theming options, comprehensive cust
1,000 lines (999 loc) • 45.1 kB
JavaScript
/* eslint-disable @typescript-eslint/no-base-to-string */
import { h, Host, } from "@stencil/core";
import { convertTablePropsToClasses } from "./modus-wc-table.tailwind";
import { inheritAriaAttributes } from "../utils";
import { createModusTable, transformColumns, } from "./modus-wc-table.core";
export class ModusWcTable {
constructor() {
this.inheritedAttributes = {};
this.table = null;
this.tanStackColumns = [];
/** Enable cell editing. Either a boolean (all rows) or a predicate per row. */
this.editable = false;
/** Custom CSS class to apply to the inner div. */
this.customClass = '';
/** The density of the table, used to save space or increase readability. */
this.density = 'comfortable';
/** Enable hover effect on table rows. */
this.hover = true;
/** The current page number in pagination (1-based index). */
this.currentPage = 1;
/** Enable pagination for the table. */
this.paginated = false;
/** Available options for the number of rows per page. */
this.pageSizeOptions = [5, 10, 15];
/** Show/hide the page size selector in pagination. */
this.showPageSizeSelector = true;
/** Enable sorting functionality for sortable columns. */
this.sortable = true;
/** Row selection mode: 'none' for no selection, 'single' for single row, 'multi' for multiple rows. */
this.selectable = 'none';
/** Zebra striped tables differentiate rows by styling them in an alternating fashion. */
this.zebra = false;
/** Currently editing cell coordinates */
this.activeEditor = null;
/** Internal state for column sorting. */
this.sorting = [];
/** Internal state for pagination. */
this.internalPagination = {
pageIndex: 0,
pageSize: 5,
};
/** Internal state for row selection. */
this.internalRowSelection = {};
// Handle sorting changes from TanStack
this.handleSortingChange = (updater) => {
// Get the new sorting state
const newSorting = typeof updater === 'function' ? updater(this.sorting) : updater;
// Update the component state - this should trigger a re-render
this.sorting = [...newSorting]; // Create a new array to ensure Stencil detects the change
if (this.table) {
// Tell TanStack the new sorting so it can recompute row model
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { state: Object.assign(Object.assign({}, prev.state), { sorting: newSorting }) })));
// Trigger row-model recomputation
void this.table.getSortedRowModel().rows;
}
// Emit event
this.sortChange.emit(newSorting);
// Update the component state to ensure UI updates
this.sorting = [...newSorting];
};
// Handle pagination changes from TanStack
this.handlePaginationChange = (updater) => {
// Get the new pagination state
const newPagination = typeof updater === 'function'
? updater(this.internalPagination)
: updater;
// Update the component state
this.internalPagination = newPagination;
// Force a row model recalculation for immediate display
if (this.table) {
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { state: Object.assign(Object.assign({}, prev.state), { pagination: newPagination }) })));
}
// Emit event
this.paginationChange.emit({
currentPage: newPagination.pageIndex + 1,
pageSize: newPagination.pageSize,
});
this.internalPagination = newPagination;
};
// NEW: handle row-selection changes coming from TanStack
this.handleRowSelectionChange = (updater) => {
const newSelection = typeof updater === 'function'
? updater(this.internalRowSelection)
: updater;
// If uncontrolled, update internal state (do NOT call setRowSelection again – would recurse)
if (!this.selectedRowIds) {
this.internalRowSelection = Object.assign({}, newSelection);
}
const selectedRowIds = Object.keys(newSelection).filter((id) => newSelection[id]);
const selectedRows = [];
if (this.table) {
selectedRowIds.forEach((id) => {
const row = this.table.getRow(id);
if (row)
selectedRows.push(row.original);
});
}
if (this.table) {
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { state: Object.assign(Object.assign({}, prev.state), { rowSelection: newSelection }) })));
}
this.rowSelectionChange.emit({ selectedRows, selectedRowIds });
};
this.handleRowClick = (rowObj, index) => {
if (this.selectable !== 'none' && this.table) {
this.toggleRowSelection(rowObj);
}
this.rowClick.emit({ row: rowObj.original, index });
};
this.handleHeaderClick = (columnId) => {
const column = this.columns.find((col) => col.id === columnId);
if (!(column === null || column === void 0 ? void 0 : column.sortable) || !this.sortable || !this.table)
return;
// Get the current sorting state from the component
const currentColumnSort = this.sorting.find((sort) => sort.id === columnId);
// Determine the new sorting state
let newSorting = [];
if (!currentColumnSort) {
// Not sorted yet, sort ascending
newSorting = [{ id: columnId, desc: false }];
}
else if (!currentColumnSort.desc) {
// Currently ascending, change to descending
newSorting = [{ id: columnId, desc: true }];
}
// If already descending, clear sorting (empty array)
try {
// Update TanStack table with the new sorting state
this.table.setSorting(newSorting);
// Recalculate row model to apply sorting immediately
void this.table.getSortedRowModel().rows;
// Update the component state to ensure UI updates
this.sorting = [...newSorting];
// Emit the event
this.sortChange.emit(newSorting);
}
catch (error) {
console.error('Error applying sorting:', error);
}
};
}
handleCurrentPageChange(newValue) {
if (!this.table)
return;
if (this.internalPagination.pageIndex !== newValue - 1) {
this.internalPagination = Object.assign(Object.assign({}, this.internalPagination), { pageIndex: newValue - 1 });
// This will trigger onPaginationChange callback
this.table.setPagination(this.internalPagination);
}
}
handleDataChange(newData) {
if (this.table) {
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { data: [...newData] })));
}
else if (newData && this.columns) {
// If table doesn't exist yet but we have both data and columns, initialize
this.initializeTable();
}
}
handleColumnsChange(newColumns) {
if (this.table) {
this.tanStackColumns = transformColumns(newColumns, this.sortable);
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { columns: this.tanStackColumns })));
}
else if (newColumns && this.data) {
// If table doesn't exist yet but we have both columns and data, initialize
this.initializeTable();
}
}
handleSortableChange(newSortable) {
if (this.table) {
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { enableSorting: newSortable, columns: transformColumns(this.columns, newSortable), state: Object.assign(Object.assign({}, prev.state), { sorting: [] }) })));
}
}
handlePaginatedChange(newPaginated) {
if (this.table) {
this.table.setOptions((prev) => (Object.assign(Object.assign({}, prev), { manualPagination: !newPaginated })));
}
}
handleSelectedRowIdsChange(newIds) {
if (!this.table)
return;
if (Array.isArray(newIds)) {
const selection = {};
newIds.forEach((id) => (selection[id] = true));
this.internalRowSelection = selection;
this.table.setRowSelection(selection);
}
}
componentWillLoad() {
var _a, _b;
if (!this.columns) {
console.error('ModusWcTable: columns is required.');
}
if (!this.data) {
console.error('ModusWcTable: data is required.');
}
this.internalPagination = {
pageIndex: this.currentPage - 1,
pageSize: this.pageSizeOptions[0],
};
// Initialize row selection from selectedRowIds prop
const rowSelection = Object.fromEntries((_b = (_a = this.selectedRowIds) === null || _a === void 0 ? void 0 : _a.map((id) => [id, true])) !== null && _b !== void 0 ? _b : []);
if (rowSelection && Object.keys(rowSelection).length > 0) {
this.internalRowSelection = rowSelection;
}
this.inheritedAttributes = inheritAriaAttributes(this.el);
this.initializeTable();
}
disconnectedCallback() {
// Clean up global listener on component disconnect
if (this.globalClickHandler) {
document.removeEventListener('click', this.globalClickHandler, true);
this.globalClickHandler = undefined;
}
// Clear active editor reference
this.activeEditorElement = undefined;
}
initializeTable() {
if (!this.columns || !this.data)
return;
// First, make a copy of the data to avoid any reference issues
const dataForTable = [...this.data];
// Transform columns (selection column rendered manually in DOM)
this.tanStackColumns = transformColumns(this.columns, this.sortable);
// Create the table with callbacks to handle state changes
this.table = createModusTable({
data: dataForTable, // Use the copied data
columns: this.tanStackColumns,
rowSelection: this.internalRowSelection,
enableRowSelection: this.selectable !== 'none',
pagination: this.internalPagination,
enableSorting: this.sortable,
manualPagination: !this.paginated,
manualSorting: false, // Let TanStack handle sorting internally
onSortingChange: this.handleSortingChange,
onPaginationChange: this.handlePaginationChange,
onRowSelectionChange: this.handleRowSelectionChange,
getRowId: (orig, idx) => orig && orig['id'] !== undefined && orig['id'] !== null
? String(orig['id'])
: String(idx),
});
// If we already have a sorting state, apply it immediately
if (this.sorting.length > 0 && this.table) {
this.table.setSorting([...this.sorting]);
}
}
getClasses() {
const classList = ['modus-wc-table'];
const propClasses = convertTablePropsToClasses({
density: this.density,
zebra: this.zebra,
hover: this.hover,
});
if (propClasses)
classList.push(propClasses);
if (this.customClass)
classList.push(this.customClass);
return classList.join(' ');
}
toggleRowSelection(rowObj) {
var _a, _b;
const idStr = String(rowObj.id);
const isSelected = !!this.internalRowSelection[idStr];
if (this.selectable === 'single') {
/* istanbul ignore next */
(_a = this.table) === null || _a === void 0 ? void 0 : _a.setRowSelection({
[idStr]: !isSelected,
});
}
else {
// Multi-select: toggle via TanStack then mirror into reactive state so
// row highlight updates synchronously.
(_b = rowObj.toggleSelected) === null || _b === void 0 ? void 0 : _b.call(rowObj);
}
}
getTotalPages() {
if (!this.data || !this.data.length)
return 1;
return this.internalPagination.pageSize <= 0
? 1
: Math.ceil(this.data.length / this.internalPagination.pageSize);
}
handlePageChange(newPage) {
const totalPages = this.getTotalPages();
if (newPage < 1 || newPage > totalPages || !this.table)
return;
const newPageIndex = newPage - 1;
// Setting pagination will trigger the onPaginationChange callback
this.table.setPagination(Object.assign(Object.assign({}, this.internalPagination), { pageIndex: newPageIndex }));
}
handlePageSizeOptionChange(event) {
if (!this.table)
return;
const select = event.detail
.srcElement;
const newPageSize = parseInt(select.value, 10);
// Setting pagination will trigger the onPaginationChange callback
this.table.setPagination({
pageSize: newPageSize,
pageIndex: 0,
});
}
renderCell(column, row) {
var _a;
const value = row[column.accessor];
if (column.cellRenderer) {
return column.cellRenderer(value, row);
}
return (_a = value === null || value === void 0 ? void 0 : value.toString()) !== null && _a !== void 0 ? _a : '';
}
getPaginationSize() {
switch (this.density) {
case 'compact':
return 'sm';
case 'relaxed':
return 'lg';
default:
return 'md';
}
}
renderPageSizeSelector() {
var _a;
if (!this.showPageSizeSelector)
return null;
const paginationSize = this.getPaginationSize();
const options = (_a = this.pageSizeOptions) === null || _a === void 0 ? void 0 : _a.map((size) => ({
value: size.toString(),
label: size.toString(),
}));
return (h("div", { class: "page-size-selector" }, h("span", null, "Show"), h("modus-wc-select", { "aria-label": "Select page size", bordered: true, size: paginationSize, onInputChange: (e) => this.handlePageSizeOptionChange(e), options: options })));
}
renderPaginationInfo() {
if (!this.data || !this.data.length)
return null;
const startItem = Math.min(this.internalPagination.pageIndex * this.internalPagination.pageSize + 1, this.data.length);
const endItem = Math.min((this.internalPagination.pageIndex + 1) *
this.internalPagination.pageSize, this.data.length);
return (h("div", { class: "pagination-info" }, "Showing ", startItem, " to ", endItem, " of ", this.data.length, " entries"));
}
/* ---------- Editing helpers ---------- */
isRowEditable(row) {
if (typeof this.editable === 'function')
return this.editable(row);
return Boolean(this.editable);
}
/**
* Validate that the row index and column ID are valid
* @param rowIndex The row index to validate
* @param colId The column ID to validate
* @returns true if both row index and column ID are valid
*/
validateRowAndColumn(rowIndex, colId) {
var _a, _b;
// Check valid row index
if (rowIndex < 0 || rowIndex >= (((_a = this.data) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
return false;
}
// Check valid column ID
const columnExists = ((_b = this.columns) === null || _b === void 0 ? void 0 : _b.some((col) => col.id === colId)) || false;
return columnExists;
}
enterEdit(rowIndex, colId) {
// Validate row and column first
if (!this.validateRowAndColumn(rowIndex, colId)) {
return;
}
const row = this.data[rowIndex];
if (!this.isRowEditable(row))
return;
this.activeEditor = { rowIndex, colId };
this.cellEditStart.emit({ rowIndex, colId });
}
commitEdit(rowIndex, colId, newValue) {
var _a;
// Validate row and column first
if (!this.validateRowAndColumn(rowIndex, colId)) {
return;
}
// Update data array immutably
const newData = [...this.data];
const updatedRow = Object.assign(Object.assign({}, newData[rowIndex]), { [colId]: newValue });
newData[rowIndex] = updatedRow;
this.data = newData;
// Push into TanStack so internal model stays in sync
(_a = this.table) === null || _a === void 0 ? void 0 : _a.setOptions((prev) => (Object.assign(Object.assign({}, prev), { data: newData })));
this.cellEditCommit.emit({ rowIndex, colId, newValue, updatedRow });
// Simply clear editor state – Stencil will re-render cell normally
this.activeEditor = null;
}
setupEditorCell(el, cellNode, column, row, handleCommit) {
el.innerHTML = '';
const isNode = typeof cellNode !== 'string' && 'tagName' in cellNode;
if (isNode) {
el.appendChild(cellNode);
if (column.editorTemplate && column.editorSetup) {
column.editorSetup(cellNode, row, handleCommit);
}
// Store reference to active editor element
this.activeEditorElement = el;
// Create and keep global click handler active
if (!this.globalClickHandler) {
this.globalClickHandler = (event) => {
// Only process clicks when we have an active editor
if (!this.activeEditor || !this.activeEditorElement) {
return;
}
const target = event.target;
const outsideTable = !this.el.contains(target);
// Check if click is outside table
if (outsideTable) {
this.activeEditor = null;
this.activeEditorElement = undefined;
}
};
// Register once and keep it active
document.addEventListener('click', this.globalClickHandler, true);
}
}
else {
el.textContent = String(cellNode);
}
}
render() {
var _a, _b, _c;
// Derive rows straight from TanStack's row model so that any sorting/pagination
// is reflected automatically
const rows = this.table
? this.paginated
? this.table.getPaginationRowModel().rows
: this.table.getRowModel().rows
: [];
const displayData = rows.map((r) => r.original);
const totalPages = this.getTotalPages();
return (h(Host, { key: '1cf7f9c0b22b23d76fe433dc69b7c12e3c36263c' }, h("div", { key: '896c63170c7ef798d3b2d5cf9978cceadb40529a', class: "table-container" }, h("div", Object.assign({ key: 'd551fb0d5e4ca7de9d01381e4ff80606b2dc4580', class: "modus-wc-overflow-x-auto" }, this.inheritedAttributes), h("table", { key: '504170d756594e6dc8da783d5414a96310382ce3', class: this.getClasses() }, this.caption && (h("caption", { key: '43703be78071edfa608ae23c8b71724486eb82c3', class: "modus-wc-sr-only" }, this.caption)), h("thead", { key: '733bce82284aba8b72df8131e01279649995ccf7' }, h("tr", { key: 'aeaa9d8214f7022d324ac16c5aaa88666fc6c0a8' }, this.selectable !== 'none' && (h("th", { key: '2178d4040efaef874635add286fa1a9219c648e8', class: "selection-column", style: { width: '48px' } }, this.selectable === 'multi' && this.table && (h("modus-wc-checkbox", { key: '8ae882271283a269561e369bab88586230dcd707', "aria-label": "Select all rows", size: "sm", value: this.table.getIsAllRowsSelected(), indeterminate: this.table.getIsSomeRowsSelected() &&
!this.table.getIsAllRowsSelected(), onInputChange: () => {
var _a;
/* istanbul ignore next */
return (_a = this.table) === null || _a === void 0 ? void 0 : _a.toggleAllRowsSelected();
} })))), (_a = this.columns) === null || _a === void 0 ? void 0 :
_a.map((column) => {
var _a;
const tanCol = (_a = this.table) === null || _a === void 0 ? void 0 : _a.getColumn(column.id);
const sortStatus = tanCol === null || tanCol === void 0 ? void 0 : tanCol.getIsSorted(); // 'asc' | 'desc' | false
const isAsc = sortStatus === 'asc';
const isDesc = sortStatus === 'desc';
return (h("th", { class: {
[column.className || '']: !!column.className,
sortable: Boolean(column.sortable && this.sortable),
sorted: !!sortStatus,
asc: !!isAsc,
desc: !!isDesc,
}, style: { width: column.width }, onClick: () => this.handleHeaderClick(column.id), role: column.sortable && this.sortable
? 'button'
: undefined, tabIndex: column.sortable && this.sortable ? 0 : undefined, "aria-sort": isAsc
? 'ascending'
: isDesc
? 'descending'
: undefined }, column.header, column.sortable && this.sortable && (h("span", { class: "sort-icon", "aria-hidden": "true" }, isAsc ? (h("modus-wc-icon", { name: "sort_alpha_down", size: "xs" })) : isDesc ? (h("modus-wc-icon", { name: "sort_alpha_up", size: "xs" })) : (h("modus-wc-icon", { name: "sort_alpha_down", size: "xs", style: { opacity: '0.5' } }))))));
}))), h("tbody", { key: '92c266aeeecb4e742f2e600d61c249f83f63bad0' }, displayData.length > 0 ? (rows.map((rowObj, index) => {
var _a, _b, _c, _d, _e;
const row = rowObj.original;
return (h("tr", { key: (_a = rowObj.id) !== null && _a !== void 0 ? _a : `row-${index}`, class: {
selected: !!this.internalRowSelection[String(rowObj.id)] ||
((_b = rowObj.getIsSelected) === null || _b === void 0 ? void 0 : _b.call(rowObj)),
}, onClick: () => this.handleRowClick(rowObj, index) }, this.selectable !== 'none' && (h("td", { class: "selection-column", style: { width: '48px' } }, h("modus-wc-checkbox", { "aria-label": "Select row", size: "sm", value: (_d = (_c = rowObj.getIsSelected) === null || _c === void 0 ? void 0 : _c.call(rowObj)) !== null && _d !== void 0 ? _d : false }))), /* istanbul ignore next */ (_e = this.columns) === null || _e === void 0 ? void 0 :
_e.map((column) => {
var _a, _b, _c;
const editing = ((_a = this.activeEditor) === null || _a === void 0 ? void 0 : _a.rowIndex) === index &&
this.activeEditor.colId === column.id;
const cellDisplay = this.renderCell(column, row);
/* istanbul ignore next */
const handleCommit = (newVal) => this.commitEdit(index, column.id, newVal);
let cellNode;
if (editing) {
if (column.editorTemplate) {
const htmlStr = column.editorTemplate.replace(/\$\{value\}/g,
/* istanbul ignore next */
String((_b = row[column.accessor]) !== null && _b !== void 0 ? _b : ''));
const wrapper = document.createElement('div');
wrapper.innerHTML = htmlStr;
cellNode =
wrapper.firstElementChild;
// allow users to wire events / data
(_c = column.editorSetup) === null || _c === void 0 ? void 0 : _c.call(column, cellNode, row, handleCommit);
}
else if (column.customEditorRenderer) {
cellNode = column.customEditorRenderer(row[column.accessor], handleCommit, row);
}
else {
cellNode = cellDisplay;
}
}
else {
cellNode = cellDisplay;
}
return (h("td", { class: {
[column.className || '']: !!column.className,
editing,
}, "data-col": column.id, onDblClick: (e) => {
var _a, _b, _c;
// Don't enter edit mode if already editing this cell
if (((_a = this.activeEditor) === null || _a === void 0 ? void 0 : _a.rowIndex) === index &&
((_b = this.activeEditor) === null || _b === void 0 ? void 0 : _b.colId) === column.id) {
return;
}
// Don't enter edit mode if clicking inside an active editor
if ((_c = this.activeEditorElement) === null || _c === void 0 ? void 0 : _c.contains(e.target)) {
return;
}
this.enterEdit(index, column.id);
}, ref: (el) => {
if (!el)
return;
this.setupEditorCell(el, cellNode, column, row, handleCommit);
} }));
})));
})) : (h("tr", null, h("td", { colSpan: (((_b = this.columns) === null || _b === void 0 ? void 0 : _b.length) || 1) +
(this.selectable !== 'none' ? 1 : 0), class: "no-data-message" }, "No data available")))))), this.paginated && ((_c = this.data) === null || _c === void 0 ? void 0 : _c.length) > 0 && (h("div", { key: 'aaa5bfe16cb2433f3adec73e2740625aa7afa678', class: "pagination-container" }, this.renderPageSizeSelector(), this.renderPaginationInfo(), h("div", { key: '2f12609eebdc7e3bcd5ea9f24fe99eae6d51ab0f', class: "pagination-controls" }, h("modus-wc-pagination", { key: '5d4782ec737bc3ec3547f0f40280c91e03bc1614', count: totalPages, page: this.internalPagination.pageIndex + 1, size: this.getPaginationSize(), onPageChange: (e) => this.handlePageChange(Number(e.detail.newPage)) })))))));
}
static get is() { return "modus-wc-table"; }
static get originalStyleUrls() {
return {
"$": ["modus-wc-table.scss"]
};
}
static get styleUrls() {
return {
"$": ["modus-wc-table.css"]
};
}
static get properties() {
return {
"editable": {
"type": "boolean",
"attribute": "editable",
"mutable": false,
"complexType": {
"original": "boolean | ((row: Record<string, unknown>) => boolean)",
"resolved": "((row: Record<string, unknown>) => boolean) | boolean | undefined",
"references": {
"Record": {
"location": "global",
"id": "global::Record"
}
}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Enable cell editing. Either a boolean (all rows) or a predicate per row."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"columns": {
"type": "unknown",
"attribute": "columns",
"mutable": false,
"complexType": {
"original": "ITableColumn[]",
"resolved": "ITableColumn[]",
"references": {
"ITableColumn": {
"location": "local",
"path": "/home/runner/work/modus-wc-2.0/modus-wc-2.0/src/components/modus-wc-table/modus-wc-table.tsx",
"id": "src/components/modus-wc-table/modus-wc-table.tsx::ITableColumn"
}
}
},
"required": true,
"optional": false,
"docs": {
"tags": [],
"text": "An array of column definitions."
},
"getter": false,
"setter": false
},
"customClass": {
"type": "string",
"attribute": "custom-class",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Custom CSS class to apply to the inner div."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "''"
},
"data": {
"type": "unknown",
"attribute": "data",
"mutable": false,
"complexType": {
"original": "Record<string, unknown>[]",
"resolved": "Record<string, unknown>[]",
"references": {
"Record": {
"location": "global",
"id": "global::Record"
}
}
},
"required": true,
"optional": false,
"docs": {
"tags": [],
"text": "An array of data objects."
},
"getter": false,
"setter": false
},
"density": {
"type": "string",
"attribute": "density",
"mutable": false,
"complexType": {
"original": "Density",
"resolved": "\"comfortable\" | \"compact\" | \"relaxed\" | undefined",
"references": {
"Density": {
"location": "import",
"path": "../types",
"id": "src/components/types.ts::Density"
}
}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "The density of the table, used to save space or increase readability."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "'comfortable'"
},
"hover": {
"type": "boolean",
"attribute": "hover",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Enable hover effect on table rows."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "true"
},
"currentPage": {
"type": "number",
"attribute": "current-page",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "The current page number in pagination (1-based index)."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "1"
},
"paginated": {
"type": "boolean",
"attribute": "paginated",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Enable pagination for the table."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"pageSizeOptions": {
"type": "unknown",
"attribute": "page-size-options",
"mutable": false,
"complexType": {
"original": "number[]",
"resolved": "number[]",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Available options for the number of rows per page."
},
"getter": false,
"setter": false,
"defaultValue": "[5, 10, 15]"
},
"showPageSizeSelector": {
"type": "boolean",
"attribute": "show-page-size-selector",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Show/hide the page size selector in pagination."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "true"
},
"sortable": {
"type": "boolean",
"attribute": "sortable",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Enable sorting functionality for sortable columns."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "true"
},
"selectable": {
"type": "string",
"attribute": "selectable",
"mutable": false,
"complexType": {
"original": "'none' | 'single' | 'multi'",
"resolved": "\"multi\" | \"none\" | \"single\" | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Row selection mode: 'none' for no selection, 'single' for single row, 'multi' for multiple rows."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "'none'"
},
"selectedRowIds": {
"type": "unknown",
"attribute": "selected-row-ids",
"mutable": false,
"complexType": {
"original": "string[]",
"resolved": "string[] | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Array of selected row IDs. Used for controlled selection state."
},
"getter": false,
"setter": false
},
"zebra": {
"type": "boolean",
"attribute": "zebra",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Zebra striped tables differentiate rows by styling them in an alternating fashion."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"caption": {
"type": "string",
"attribute": "caption",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Accessibility caption for the table (visually hidden but available to screen readers)."
},
"getter": false,
"setter": false,
"reflect": false
}
};
}
static get states() {
return {
"activeEditor": {},
"sorting": {},
"internalPagination": {},
"internalRowSelection": {}
};
}
static get events() {
return [{
"method": "cellEditStart",
"name": "cellEditStart",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when cell editing starts."
},
"complexType": {
"original": "{\n rowIndex: number;\n colId: string;\n }",
"resolved": "{ rowIndex: number; colId: string; }",
"references": {}
}
}, {
"method": "cellEditCommit",
"name": "cellEditCommit",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when cell editing is committed with the new value."
},
"complexType": {
"original": "{\n rowIndex: number;\n colId: string;\n newValue: unknown;\n updatedRow: Record<string, unknown>;\n }",
"resolved": "{ rowIndex: number; colId: string; newValue: unknown; updatedRow: Record<string, unknown>; }",
"references": {
"Record": {
"location": "global",
"id": "global::Record"
}
}
}
}, {
"method": "rowClick",
"name": "rowClick",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when a row is clicked."
},
"complexType": {
"original": "{\n row: Record<string, unknown>;\n index: number;\n }",
"resolved": "{ row: Record<string, unknown>; index: number; }",
"references": {
"Record": {
"location": "global",
"id": "global::Record"
}
}
}
}, {
"method": "sortChange",
"name": "sortChange",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when sorting changes with the new sorting state."
},
"complexType": {
"original": "SortingState",
"resolved": "ColumnSort[]",
"references": {
"SortingState": {
"location": "import",
"path": "@tanstack/table-core",
"id": "node_modules::SortingState"
}
}
}
}, {
"method": "paginationChange",
"name": "paginationChange",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when pagination changes with the new pagination state."
},
"complexType": {
"original": "IPaginationChangeEventDetail",
"resolved": "IPaginationChangeEventDetail",
"references": {
"IPaginationChangeEventDetail": {
"location": "local",
"path": "/home/runner/work/modus-wc-2.0/modus-wc-2.0/src/components/modus-wc-table/modus-wc-table.tsx",
"id": "src/components/modus-wc-table/modus-wc-table.tsx::IPaginationChangeEventDetail"
}
}
}
}, {
"method": "rowSelectionChange",
"name": "rowSelectionChange",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emits when row selection changes with the selected rows and their IDs."
},
"complexType": {
"original": "{\n selectedRows: Record<string, unknown>[];\n selectedRowIds: string[];\n }",
"resolved": "{ selectedRows: Record<string, unknown>[]; selectedRowIds: string[]; }",
"references": {
"Record": {
"location": "global",
"id": "global::Record"
}
}
}
}];
}
static get elementRef() { return "el"; }
static get watchers() {
return [{
"propName": "currentPage",
"methodName": "handleCurrentPageChange"
}, {
"propName": "data",
"methodName": "handleDataChange"
}, {
"propName": "columns",
"methodName": "handleColumnsChange"
}, {
"propName": "sortable",
"methodName": "handleSortableChange"
}, {
"propName": "paginated",
"methodName": "handlePaginatedChange"
}, {
"propName": "selectedRowIds",
"methodName": "handleSelectedRowIdsChange"
}];
}
}