ui-lit
Version:
UI Elements on LIT
333 lines (332 loc) • 12.8 kB
JavaScript
import { __decorate } from "tslib";
import { classMap } from 'lit/directives/class-map';
import { LitElement, html, nothing, svg } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat';
import '../pagination';
import './table-header';
import { scrollbar } from '../styles/scrollbar';
import { ResizeObserverController } from '../controllers/ResizeObserverController';
import { tableStyles } from './styles';
const nodataSVG = svg `
<svg class = "nodata-svg" width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<path d="M46.0625 44.7083L4.97917 3.60416L2.3125 6.24999L6.25 10.2083V39.5833C6.25 40.6884 6.68899 41.7482 7.47039 42.5296C8.25179 43.311 9.3116 43.75 10.4167 43.75H39.7917L43.4167 47.3542L46.0625 44.7083ZM10.4167 39.5833V14.3542L35.6458 39.5833H10.4167ZM17.0833 10.4167L12.9167 6.24999H39.5833C40.6884 6.24999 41.7482 6.68898 42.5296 7.47038C43.311 8.25178 43.75 9.31159 43.75 10.4167V37.0833L39.5833 32.9167V10.4167H17.0833Z"/>
</svg>`;
let LitTable = class LitTable extends LitElement {
constructor() {
super(...arguments);
this.RO = new ResizeObserverController(this);
this._columns = [];
this._headerHeight = 50;
this._rowHeight = 30;
this.dataSource = [];
this.pagination = false;
this.paginationToHeight = false;
this.pageLength = 5;
this.sort = '';
this.sortDirection = 'ascend';
this.page = 0;
this._data = [];
this._rect = null;
this._stopResize = false;
this._filters = new Map();
this._onResize = (rect) => {
this._rect = rect;
this.recalcPageLength();
this.dispatchEvent(new CustomEvent('tableResize', {
detail: rect
}));
Promise.resolve().then(() => {
this.recalcPageLength();
});
};
}
static get properties() {
return {
columns: { type: Array },
rowHeight: { type: Number },
headerHeight: { type: Number },
};
}
set columns(value) {
const oldValue = this._columns;
this._columns = value;
if (oldValue.length !== value.length) {
this.style.setProperty('--lit-cells', this.columns.length.toString());
}
this._updateSort();
this.requestUpdate('columns', oldValue);
}
get columns() {
return this._columns;
}
set headerHeight(value) {
const oldValue = this._headerHeight;
this._headerHeight = value;
if (oldValue !== value) {
this.style.setProperty('--header-height', this._headerHeight + "px");
}
this.requestUpdate('headerHeight', value);
}
get headerHeight() { return this._headerHeight; }
set rowHeight(value) {
const oldValue = this._rowHeight;
this._rowHeight = value;
if (oldValue !== value) {
this.style.setProperty('--row-height', this._rowHeight + "px");
}
this.requestUpdate('rowHeight', value);
}
get rowHeight() { return this._rowHeight; }
setPage(page) {
var _a, _b;
(_b = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('lit-pagination')) === null || _b === void 0 ? void 0 : _b.setPage(page);
}
get rect() {
return this._rect;
}
recalcPageLength() {
if (!this.paginationToHeight || !this.pagination || !this._rect || this._stopResize)
return;
const availableHeight = this._rect.height - this.headerHeight;
this.pageLength = Math.floor(availableHeight / this.rowHeight);
}
sortFunction(a, b, direction) {
if (a[this.sort] > b[this.sort]) {
return direction === 'descend' ? -1 : 1;
}
if (a[this.sort] < b[this.sort]) {
return direction === 'descend' ? 1 : -1;
}
return 0;
}
_updateSort() {
var _a;
if (this.sort)
return;
const data = this.columns.filter(it => it.defaultSort)[0];
if (data && (data === null || data === void 0 ? void 0 : data.key) !== this.sort) {
this.sort = data.key;
this.sortDirection = ((_a = data.sortDirections) === null || _a === void 0 ? void 0 : _a[0]) || 'ascend';
}
}
hasFilters() {
return !!this._filters.size;
}
getFilteredData() {
if (!this.hasFilters()) {
return [...this.dataSource];
}
const cols = {};
for (const [key, filters] of this._filters) {
filters === null || filters === void 0 ? void 0 : filters.forEach(f => {
if (f.checked) {
if (!cols[key])
cols[key] = [];
cols[key].push(f);
}
});
}
return this.dataSource.filter(it => {
const keys = Object.keys(cols);
for (const key of keys) {
const data = cols[key].filter(f => f.value || f.checked);
if (!data.length) {
continue;
}
let colFilter = false;
for (const f of cols[key]) {
if (f.onFilter) {
if (f.onFilter(f.value, it, this._filters)) {
colFilter = true;
}
}
else if (Array.isArray(f.value)) {
if (f.value.includes(it[key]) || f.value.includes(it[key].toString())) {
colFilter = true;
}
}
else if (it[key] === f.value) {
colFilter = true;
}
if (colFilter) {
break;
}
}
;
if (!colFilter) {
return false;
}
}
;
return true;
});
}
willUpdate() {
const dataSource = this.getFilteredData();
if (this.sort) {
const data = this.columns.filter(it => it.key === this.sort)[0];
if (data) {
const sorter = (a, b) => {
if (typeof data.sorter === 'function') {
return data.sorter(a, b, this.sortDirection);
}
return this.sortFunction(a, b, this.sortDirection);
};
dataSource.sort(sorter);
}
}
this._data = dataSource;
}
getColumnFilters(key) {
const filters = this._filters.get(key);
const CFilters = this.columns.filter(c => c.key === key)[0].filters;
return (filters === null || filters === void 0 ? void 0 : filters.map((f, i) => ({ ...f, text: CFilters[i].text }))) || CFilters;
}
setFilter(key, id, filter) {
const filters = this.getColumnFilters(key);
if (filters && id < filters.length) {
filters[id] = filter;
}
this._filters.set(key, filters || [filter]);
this.requestUpdate();
}
_headerTemplate() {
return this.columns.map((col, i) => {
return html `<th>
<lit-table-header
.filters = "${this.getColumnFilters(col.key)}"
= "${this._changeFilter}"
= "${this._resetFilter}"
style = "min-width: ${col.width ? col.width + "px" : "auto"}"
.align = "${col.align || "left"}"
.sort = "${this.sort}"
.sortDirection = "${this.sortDirection}"
.item = "${col}"></lit-table-header>
</th>`;
});
}
_rowsTemplate() {
return repeat(this.pagination
? this._data.slice(this.page * this.pageLength, (this.page + 1) * this.pageLength)
: this._data, it => it.key, it => {
var _a;
return html `
<tr = "${this._onRowClick}"
class = "${((_a = this.rowSelect) === null || _a === void 0 ? void 0 : _a.call(this, it)) ? 'selected' : ''}"
data-key = "${it.key}">
${this.columns.map((col, i) => {
var _a;
const classes = {
ellipses: !!col.ellipses,
['status-' + (((_a = col.getStatus) === null || _a === void 0 ? void 0 : _a.call(col, it)) || 'none')]: true,
'half-hidden': col.halfHidden ? col.halfHidden(it) : false
};
return html `<td .align = "${col.align || "left"}"
style = "width: ${col.percent ? col.percent + '%' : 'auto'}"
class = "${classMap(classes)}">
<div
style = "min-width: ${col.width ? col.width + "px" : "auto"}"
class = "col-wrapper ${!!col.ellipses ? 'ellipses' : ''}">
${col.valueFn ? col.valueFn(it) : it[col.key]}
</div>
</td>`;
})}
</tr>`;
});
}
render() {
return html `
<main class = "ff-scrollbar" ${this.RO.observe(this._onResize)}>
<table class = " ${!this._data.length ? 'nodata' : ''}"
= "${this._onSortChanged}">
<thead>
<tr>
${this._headerTemplate()}
</tr>
</thead>
<tbody>
${!this._data.length
? html `<tr><td colspan = "200" style = "text-align: center;">
${nodataSVG}
</td></tr>`
: this._rowsTemplate()}
</tbody>
</table>
</main>
<footer>
${this.pagination
? html `<lit-pagination
= "${this._onFocus}"
= "${this._onBlur}"
= "${this._onPageChanged}"
.length = "${this._data.length}"
.pageLength = "${this.pageLength}"
.page = "${this.page}"
></lit-pagination>`
: nothing}
<slot></slot>
</footer>`;
}
_onRowClick(e) {
var _a;
const key = (_a = e.target.closest('tr')) === null || _a === void 0 ? void 0 : _a.dataset.key;
this.dispatchEvent(new CustomEvent("rowClick", {
detail: key,
bubbles: true,
composed: true
}));
}
_onFocus() {
this._stopResize = true;
}
_onBlur() {
this._stopResize = false;
}
_changeFilter(e) {
const item = e.detail;
this._filters.set(item.key, item.filters);
this.requestUpdate();
}
_resetFilter(e) {
this._filters.delete(e.detail);
this.requestUpdate();
}
_onSortChanged(e) {
this.sort = e.detail.sort;
this.sortDirection = e.detail.direction;
this.requestUpdate();
}
_onPageChanged(e) {
this.page = e.detail;
}
};
LitTable.styles = [tableStyles, scrollbar];
__decorate([
property({ type: Object })
], LitTable.prototype, "rowSelect", void 0);
__decorate([
property({ type: Array })
], LitTable.prototype, "dataSource", void 0);
__decorate([
property({ type: Boolean, reflect: true })
], LitTable.prototype, "pagination", void 0);
__decorate([
property({ type: Boolean })
], LitTable.prototype, "paginationToHeight", void 0);
__decorate([
property({ type: Number })
], LitTable.prototype, "pageLength", void 0);
__decorate([
state()
], LitTable.prototype, "sort", void 0);
__decorate([
state()
], LitTable.prototype, "sortDirection", void 0);
__decorate([
state()
], LitTable.prototype, "page", void 0);
LitTable = __decorate([
customElement("lit-table")
], LitTable);
export { LitTable };