Initial implementation.
This commit is contained in:
parent
f16e0cd8b5
commit
8b7facdc64
68
column-resizer.js
Normal file
68
column-resizer.js
Normal file
@ -0,0 +1,68 @@
|
||||
export default class ColumResizer {
|
||||
constructor(wrap, handleSelector) {
|
||||
this._handleSelector = handleSelector;
|
||||
this._mouseDown = this._mouseDown.bind(this);
|
||||
this._dragging = this._dragging.bind(this);
|
||||
this._draggingEnd = this._draggingEnd.bind(this);
|
||||
this._trackingStarted = false;
|
||||
|
||||
// Amount of pixels the handle must be moved before its registered as a tracking gesture.
|
||||
this.threshold = 5;
|
||||
|
||||
wrap.addEventListener('mousedown', this._mouseDown);
|
||||
}
|
||||
|
||||
_mouseDown(e) {
|
||||
const handle = e.composedPath().find(node => node.matches && node.matches(this._handleSelector));
|
||||
if (!handle) return;
|
||||
|
||||
this._cHandle = handle;
|
||||
this._startX = e.pageX;
|
||||
this._watchDrag();
|
||||
}
|
||||
|
||||
_watchDrag() {
|
||||
window.addEventListener('mousemove', this._dragging);
|
||||
window.addEventListener('mouseup', this._draggingEnd);
|
||||
}
|
||||
|
||||
_stopWatchDrag() {
|
||||
window.removeEventListener('mousemove', this._dragging);
|
||||
window.removeEventListener('mouseup', this._draggingEnd);
|
||||
}
|
||||
|
||||
_dragging(e) {
|
||||
this._dx = e.pageX - this._startX;
|
||||
|
||||
if (this._trackingStarted === false && Math.abs(this._dx) >= this.threshold) {
|
||||
this._trackingStarted = true;
|
||||
this._clearSelection();
|
||||
this._cHandle.dispatchEvent(new CustomEvent('track', { detail: { state: 'start', dx: this._dx }, bubbles: true, composed: true }));
|
||||
}
|
||||
|
||||
if (this._trackingStarted === true) {
|
||||
this._cHandle.dispatchEvent(new CustomEvent('track', { detail: { state: 'track', dx: this._dx }, bubbles: true, composed: true }));
|
||||
}
|
||||
}
|
||||
|
||||
_draggingEnd(e) {
|
||||
this._dx = e.pageX - this._startX;
|
||||
this._trackingStarted = false;
|
||||
this._cHandle.dispatchEvent(new CustomEvent('track', { detail: { state: 'end', dx: this._dx }, bubbles: true, composed: true }));
|
||||
this._stopWatchDrag();
|
||||
this._cHandle = null;
|
||||
this._startX = 0;
|
||||
this._clearSelection();
|
||||
}
|
||||
|
||||
_clearSelection() {
|
||||
const sel = window.getSelection ? window.getSelection() : document.selection;
|
||||
if (sel) {
|
||||
if (sel.removeAllRanges) {
|
||||
sel.removeAllRanges();
|
||||
} else if (sel.empty) {
|
||||
sel.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
235
package-lock.json
generated
Normal file
235
package-lock.json
generated
Normal file
@ -0,0 +1,235 @@
|
||||
{
|
||||
"name": "@tp/tp-table",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@tp/tp-table",
|
||||
"version": "1.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@lit-labs/virtualizer": "^0.7.0",
|
||||
"@tp/helpers": "^1.1.3",
|
||||
"@tp/tp-checkbox": "^1.0.4",
|
||||
"@tp/tp-icon": "^1.0.1",
|
||||
"@tp/tp-scroll-threshold": "^1.0.0",
|
||||
"lit": "^2.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit-labs/virtualizer": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@lit-labs%2fvirtualizer/-/virtualizer-0.7.0.tgz",
|
||||
"integrity": "sha512-4h/TGmabGoo81EysUR9AV+fBeYHHvcgs0knmZDUQ5QRP49PM8k5mNnMfPBL7fxYErZrl0cUiNewg101q5zOitg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"event-target-shim": "^5.0.1",
|
||||
"lit": "^2.0.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://verdaccio.codeblob.work/@lit%2freactive-element/-/reactive-element-1.3.2.tgz",
|
||||
"integrity": "sha512-A2e18XzPMrIh35nhIdE4uoqRzoIpEU5vZYuQN4S3Ee1zkGdYC27DP12pewbw/RLgPHzaE4kx/YqxMzebOpm0dA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@tp/helpers": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2fhelpers/-/helpers-1.1.3.tgz",
|
||||
"integrity": "sha512-WDj3meXgCjF9/4eyPQMk2YEderVDUD3IVJrjds0i4seABVI5yyaMWVNtxxH+w8O9eIDgwxiuyQqaI7bdyNaCoA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@tp/tp-checkbox": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-checkbox/-/tp-checkbox-1.0.4.tgz",
|
||||
"integrity": "sha512-6pa7rS8sTi4b2EKgSIfeqgjMRXixt9PnehaPN6mOPW83BBivXuF1rtMwzjc38xNiqesyis0uhcJApTCyh3hA+A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tp/helpers": "^1.1.3",
|
||||
"@tp/tp-icon": "^1.0.1",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tp/tp-icon": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-icon/-/tp-icon-1.0.1.tgz",
|
||||
"integrity": "sha512-rBbQoXZ5t35F7yIbPAEGAlDscZhxLZ5/o229kyiBBrXvCrc+aVOsetSwF1jPeBSmb57h2PfinIvQhtMARwWHoA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tp/tp-tooltip": "^1.0.0",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tp/tp-scroll-threshold": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-scroll-threshold/-/tp-scroll-threshold-1.0.0.tgz",
|
||||
"integrity": "sha512-8azYxjw9P1y5j9FLt6MVjzIBpG8vV8B6es0k2zeHf1CJJ7I/o+nRI+LOlfMoeU491bMZpgBdJHZqeNHLO5RyWw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tp/tp-tooltip": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-tooltip/-/tp-tooltip-1.0.0.tgz",
|
||||
"integrity": "sha512-UtrIK5KWcEiC+HnHOVbgg90j4RjHn3e9ehOBYPZsm6zO+tT7pQJJYFOtJqBW+DDV7jVfH3AvGKCxtzNiJXYvDw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tp/helpers": "^1.0.0",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://verdaccio.codeblob.work/@types%2ftrusted-types/-/trusted-types-2.0.2.tgz",
|
||||
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/lit": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit/-/lit-2.2.6.tgz",
|
||||
"integrity": "sha512-K2vkeGABfSJSfkhqHy86ujchJs3NR9nW1bEEiV+bXDkbiQ60Tv5GUausYN2mXigZn8lC1qXuc46ArQRKYmumZw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.3.0",
|
||||
"lit-element": "^3.2.0",
|
||||
"lit-html": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-element": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit-element/-/lit-element-3.2.0.tgz",
|
||||
"integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.3.0",
|
||||
"lit-html": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-html": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit-html/-/lit-html-2.2.6.tgz",
|
||||
"integrity": "sha512-xOKsPmq/RAKJ6dUeOxhmOYFjcjf0Q7aSdfBJgdJkOfCUnkmmJPxNrlZpRBeVe1Gg50oYWMlgm6ccAE/SpJgSdw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"license": "0BSD"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@lit-labs/virtualizer": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@lit-labs%2fvirtualizer/-/virtualizer-0.7.0.tgz",
|
||||
"integrity": "sha512-4h/TGmabGoo81EysUR9AV+fBeYHHvcgs0knmZDUQ5QRP49PM8k5mNnMfPBL7fxYErZrl0cUiNewg101q5zOitg==",
|
||||
"requires": {
|
||||
"event-target-shim": "^5.0.1",
|
||||
"lit": "^2.0.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@lit/reactive-element": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://verdaccio.codeblob.work/@lit%2freactive-element/-/reactive-element-1.3.2.tgz",
|
||||
"integrity": "sha512-A2e18XzPMrIh35nhIdE4uoqRzoIpEU5vZYuQN4S3Ee1zkGdYC27DP12pewbw/RLgPHzaE4kx/YqxMzebOpm0dA=="
|
||||
},
|
||||
"@tp/helpers": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2fhelpers/-/helpers-1.1.3.tgz",
|
||||
"integrity": "sha512-WDj3meXgCjF9/4eyPQMk2YEderVDUD3IVJrjds0i4seABVI5yyaMWVNtxxH+w8O9eIDgwxiuyQqaI7bdyNaCoA=="
|
||||
},
|
||||
"@tp/tp-checkbox": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-checkbox/-/tp-checkbox-1.0.4.tgz",
|
||||
"integrity": "sha512-6pa7rS8sTi4b2EKgSIfeqgjMRXixt9PnehaPN6mOPW83BBivXuF1rtMwzjc38xNiqesyis0uhcJApTCyh3hA+A==",
|
||||
"requires": {
|
||||
"@tp/helpers": "^1.1.3",
|
||||
"@tp/tp-icon": "^1.0.1",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@tp/tp-icon": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-icon/-/tp-icon-1.0.1.tgz",
|
||||
"integrity": "sha512-rBbQoXZ5t35F7yIbPAEGAlDscZhxLZ5/o229kyiBBrXvCrc+aVOsetSwF1jPeBSmb57h2PfinIvQhtMARwWHoA==",
|
||||
"requires": {
|
||||
"@tp/tp-tooltip": "^1.0.0",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@tp/tp-scroll-threshold": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-scroll-threshold/-/tp-scroll-threshold-1.0.0.tgz",
|
||||
"integrity": "sha512-8azYxjw9P1y5j9FLt6MVjzIBpG8vV8B6es0k2zeHf1CJJ7I/o+nRI+LOlfMoeU491bMZpgBdJHZqeNHLO5RyWw==",
|
||||
"requires": {
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@tp/tp-tooltip": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/@tp%2ftp-tooltip/-/tp-tooltip-1.0.0.tgz",
|
||||
"integrity": "sha512-UtrIK5KWcEiC+HnHOVbgg90j4RjHn3e9ehOBYPZsm6zO+tT7pQJJYFOtJqBW+DDV7jVfH3AvGKCxtzNiJXYvDw==",
|
||||
"requires": {
|
||||
"@tp/helpers": "^1.0.0",
|
||||
"lit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@types/trusted-types": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://verdaccio.codeblob.work/@types%2ftrusted-types/-/trusted-types-2.0.2.tgz",
|
||||
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
|
||||
},
|
||||
"event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||
},
|
||||
"lit": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit/-/lit-2.2.6.tgz",
|
||||
"integrity": "sha512-K2vkeGABfSJSfkhqHy86ujchJs3NR9nW1bEEiV+bXDkbiQ60Tv5GUausYN2mXigZn8lC1qXuc46ArQRKYmumZw==",
|
||||
"requires": {
|
||||
"@lit/reactive-element": "^1.3.0",
|
||||
"lit-element": "^3.2.0",
|
||||
"lit-html": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"lit-element": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit-element/-/lit-element-3.2.0.tgz",
|
||||
"integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==",
|
||||
"requires": {
|
||||
"@lit/reactive-element": "^1.3.0",
|
||||
"lit-html": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"lit-html": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://verdaccio.codeblob.work/lit-html/-/lit-html-2.2.6.tgz",
|
||||
"integrity": "sha512-xOKsPmq/RAKJ6dUeOxhmOYFjcjf0Q7aSdfBJgdJkOfCUnkmmJPxNrlZpRBeVe1Gg50oYWMlgm6ccAE/SpJgSdw==",
|
||||
"requires": {
|
||||
"@types/trusted-types": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://verdaccio.codeblob.work/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
}
|
||||
}
|
15
package.json
15
package.json
@ -1,18 +1,23 @@
|
||||
{
|
||||
"name": "@tp/tp-element",
|
||||
"version": "0.0.1",
|
||||
"name": "@tp/tp-table",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "tp-element.js",
|
||||
"main": "tp-table.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.codeblob.work/tp-elements/tp-element.git"
|
||||
"url": "https://gitea.codeblob.work/tp-elements/tp-table.git"
|
||||
},
|
||||
"author": "trading_peter",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lit": "^2.2.0"
|
||||
"@lit-labs/virtualizer": "^0.7.0",
|
||||
"@tp/helpers": "^1.1.3",
|
||||
"@tp/tp-checkbox": "^1.0.4",
|
||||
"@tp/tp-icon": "^1.0.1",
|
||||
"@tp/tp-scroll-threshold": "^1.0.0",
|
||||
"lit": "^2.2.6"
|
||||
}
|
||||
}
|
||||
|
226
pagination.js
Normal file
226
pagination.js
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
@license
|
||||
Copyright (c) 2022 trading_peter
|
||||
This program is available under Apache License Version 2.0
|
||||
*/
|
||||
|
||||
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||
import { Helper } from '@era-core/era-mixins/era-helper-mixin.js';
|
||||
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
||||
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
|
||||
|
||||
/**
|
||||
* # ListLoader
|
||||
*
|
||||
* Methods to load list contents page by page.
|
||||
*
|
||||
* @polymerBehavior ListLoader
|
||||
*/
|
||||
export const Pagination = dedupingMixin(function(superClass) {
|
||||
return class extends Helper(superClass) {
|
||||
static get properties() {
|
||||
return {
|
||||
_entries: { type: Array },
|
||||
_entriesSet: { type: Object },
|
||||
_page: { type: Number },
|
||||
_filter: { type: String },
|
||||
_filterPage: { type: Number },
|
||||
_limit: { type: Number }
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._entries = [];
|
||||
this._entriesSet = new Set();
|
||||
this._page = 1;
|
||||
this._filterPage = 1;
|
||||
this._limit = 350;
|
||||
}
|
||||
|
||||
_fetch(query, cb) {
|
||||
// Override
|
||||
}
|
||||
|
||||
_isInFlight() {
|
||||
// Override
|
||||
}
|
||||
|
||||
get _hasFilter() {
|
||||
return typeof this._filter === 'string' && this._filter.length > 0;
|
||||
}
|
||||
|
||||
_reloadList() {
|
||||
this._resetList();
|
||||
this.__currentPage = 0;
|
||||
this._lastPage = false;
|
||||
this._listStateChanged();
|
||||
}
|
||||
|
||||
_listStateChanged() {
|
||||
if (this._hasFilter) {
|
||||
this._fetchFiltered();
|
||||
} else {
|
||||
this._fetchPage();
|
||||
}
|
||||
}
|
||||
|
||||
_scrollThresholdTriggered(e) {
|
||||
if (this.active && this._listOverflows()) {
|
||||
this.__list = e.composedPath()[0].scrollTarget;
|
||||
this.__listScrollOffset = this.__list.scrollTop;
|
||||
|
||||
if (this._hasFilter) {
|
||||
this._filterPage++;
|
||||
this._fetchFiltered();
|
||||
} else {
|
||||
this._page++;
|
||||
this._fetchPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_resetList() {
|
||||
if (typeof this.setProperties === 'function') {
|
||||
this.setProperties({ _page: 1, _filterPage: 1, _entries: [] });
|
||||
} else {
|
||||
this._page = 1;
|
||||
this._filterPage = 1;
|
||||
this._entries = [];
|
||||
}
|
||||
}
|
||||
|
||||
_shouldFetch() {
|
||||
if (this._page === undefined || this._limit === undefined) return false;
|
||||
const pageChanged = this._page !== this.__currentPage;
|
||||
|
||||
let optionsChanged = false;
|
||||
optionsChanged = JSON.stringify(this._statusFilter) !== JSON.stringify(this.__currentStatusFilter) || optionsChanged;
|
||||
optionsChanged = JSON.stringify(this._sorting) !== JSON.stringify(this.__currentSorting) || optionsChanged;
|
||||
|
||||
this.__currentStatusFilter = this._statusFilter;
|
||||
this.__currentSorting = this._sorting;
|
||||
|
||||
if (optionsChanged === true) {
|
||||
this._resetList();
|
||||
}
|
||||
|
||||
if ((pageChanged === false || this._lastPage || this._isInFlight()) && optionsChanged === false) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_fetchPage() {
|
||||
this._filterDebouncer = Debouncer.debounce(
|
||||
this._filterDebouncer,
|
||||
timeOut.after(20),
|
||||
() => {
|
||||
if (this._shouldFetch() === false) return;
|
||||
|
||||
this._fetch({ page: this._page, limit: this._limit, options: { statusFilter: this._statusFilter, sorting: this._sorting } }, (docs, pages) => {
|
||||
if (this._page === 1) {
|
||||
this._entriesSet = new Set();
|
||||
}
|
||||
|
||||
docs = docs.filter(doc => this._entriesSet.has(doc._id) === false);
|
||||
docs.forEach(doc => this._entriesSet.add(doc._id));
|
||||
|
||||
if (this._page === 1) {
|
||||
this._entries = docs;
|
||||
} else {
|
||||
this._entries = this._entries.concat(docs);
|
||||
}
|
||||
|
||||
// Restore scrolling position in the list.
|
||||
if (this.__list !== undefined) {
|
||||
this.__list.scrollTop = this.__listScrollOffset || 0;
|
||||
}
|
||||
|
||||
this.__currentPage = this._page;
|
||||
|
||||
// Check if we reached the last page.
|
||||
this._lastPage = pages <= this._page;
|
||||
|
||||
// Clear scroll threshold so the next page can be loaded.
|
||||
this.clearTriggers();
|
||||
|
||||
this.__fillList();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_fetchFiltered() {
|
||||
this._filterDebouncer = Debouncer.debounce(
|
||||
this._filterDebouncer,
|
||||
timeOut.after(300),
|
||||
() => {
|
||||
if (!this._hasFilter) {
|
||||
this._lastPage = false;
|
||||
this.__currentPage = false;
|
||||
this._lastFilter = null;
|
||||
this._page = 1;
|
||||
this._filterPage = 1;
|
||||
this.__listScrollOffset = 0;
|
||||
this._fetchPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._shouldFetch() === false && this._lastPage === true && this._filter === this._lastFilter) return;
|
||||
|
||||
if (this._filter !== this._lastFilter) {
|
||||
this._filterPage = 1;
|
||||
}
|
||||
|
||||
this._lastFilter = this._filter;
|
||||
|
||||
this._fetch({ filter: this._filter, page: this._filterPage, limit: this._limit, options: {
|
||||
statusFilter: this._statusFilter,
|
||||
sorting: this._sorting
|
||||
} }, (result, resp) => {
|
||||
if (resp && resp.statusCode === 200) {
|
||||
if (this._filterPage === 1) {
|
||||
this._entries = result.entries.map(entry => entry.doc);
|
||||
} else {
|
||||
this._entries = this._entries.concat(result.entries.map(entry => entry.doc));
|
||||
}
|
||||
|
||||
// Restore scrolling position in the list.
|
||||
if (this.__list !== undefined) {
|
||||
this.__list.scrollTop = this.__listScrollOffset || 0;
|
||||
}
|
||||
|
||||
// Check if we reached the last page.
|
||||
this._lastPage = result.pages <= this._filterPage || result.pages === 0;
|
||||
|
||||
// Clear scroll threshold so the next page can be loaded.
|
||||
this.clearTriggers();
|
||||
|
||||
this.__fillList();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Load pages until the list fills the screen.
|
||||
// We check the list height after next render to see if the list already fills the screen.
|
||||
// If not, load the next page.
|
||||
// This needs to be triggered async so that the current `_fetchPage` request
|
||||
// is finished and no longer considered "in flight".
|
||||
__fillList() {
|
||||
if (!this._lastPage && !this.listOverflows()) {
|
||||
setTimeout(() => {
|
||||
if (this._hasFilter) {
|
||||
this._filterPage++;
|
||||
this._fetchFiltered();
|
||||
} else {
|
||||
this._page++;
|
||||
this._fetchPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
135
tp-table-item.js
Normal file
135
tp-table-item.js
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
@license
|
||||
Copyright (c) 2021 EDV Wasmeier
|
||||
*/
|
||||
|
||||
import '@tp/tp-checkbox/tp-checkbox.js';
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { DomQuery } from '@tp/helpers/dom-query.js';
|
||||
|
||||
/**
|
||||
# ef-base-table-item
|
||||
|
||||
## Example
|
||||
```html
|
||||
<ef-base-table-item></ef-base-table-item>
|
||||
```
|
||||
|
||||
*/
|
||||
|
||||
const mixins = [
|
||||
DomQuery
|
||||
];
|
||||
|
||||
/* @litElement */
|
||||
const BaseElement = mixins.reduce((baseClass, mixin) => {
|
||||
return mixin(baseClass);
|
||||
}, LitElement);
|
||||
|
||||
class TpTableItem extends BaseElement {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
display: grid;
|
||||
grid-template-columns: 0.5fr 3fr 0.5fr 0.5fr 0.5fr; /* Overridden by javascript */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[part="cell"] {
|
||||
align-self: stretch;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding: 10px 20px;
|
||||
border-right: solid 1px #c1c1c1;
|
||||
}
|
||||
|
||||
.wrap > div.chk {
|
||||
border-right: none;
|
||||
}
|
||||
`
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const { columns, item } = this;
|
||||
|
||||
return html`
|
||||
<div id="grid" class="wrap" part="row">
|
||||
${this.selectable ? html`
|
||||
<div class="chk">
|
||||
<tp-checkbox id="selectionChk" @click=${this._updateSelectionState}></tp-checkbox>
|
||||
</div>
|
||||
` : null}
|
||||
${Array.isArray(columns) ? columns.map(column => {
|
||||
if (column.visible !== true && column.required !== true) return;
|
||||
return this.renderColumn(column, item) || null;
|
||||
}) : null
|
||||
}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
index: { type: Array },
|
||||
item: { type: Object },
|
||||
columns: { type: Array },
|
||||
selectable: { type: Boolean },
|
||||
};
|
||||
}
|
||||
|
||||
renderColumn(column, item) {
|
||||
return html`<div part="cell">${item[column.name]}</div>`;
|
||||
}
|
||||
|
||||
async updated(changes) {
|
||||
if (changes.has('item') && this.selectable) {
|
||||
this.$.selectionChk.checked = Boolean(this.item.__selected__);
|
||||
}
|
||||
|
||||
if (changes.has('columns') && Array.isArray(this.columns)) {
|
||||
let colWidths = this.columns.filter(col => col.required || col.visible).map(col => col.width).join(' ');
|
||||
|
||||
if (this.selectable) {
|
||||
colWidths = '40px ' + colWidths;
|
||||
}
|
||||
|
||||
this.$grid.style.gridTemplateColumns = colWidths;
|
||||
}
|
||||
|
||||
if (changes.has('index')) {
|
||||
if (this.index % 2 === 0) {
|
||||
this.part.add('odd');
|
||||
} else {
|
||||
this.part.remove('odd');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get $grid() {
|
||||
if (this.__$grid) {
|
||||
return this.__$grid;
|
||||
}
|
||||
this.__$grid = this.shadowRoot.getElementById('grid');
|
||||
return this.__$grid;
|
||||
}
|
||||
|
||||
_updateSelectionState(e) {
|
||||
const target = e.target;
|
||||
|
||||
setTimeout(() => {
|
||||
this.dispatchEvent(new CustomEvent('selection-changed', { detail: { item: this.item, selected: target.checked }, bubbles: true, composed: true }));
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('tp-table-item', TpTableItem);
|
||||
|
||||
export default TpTableItem
|
439
tp-table.js
Normal file
439
tp-table.js
Normal file
@ -0,0 +1,439 @@
|
||||
/**
|
||||
@license
|
||||
Copyright (c) 2022 trading_peter
|
||||
This program is available under Apache License Version 2.0
|
||||
*/
|
||||
|
||||
import '@tp/tp-scroll-threshold/tp-scroll-threshold.js';
|
||||
import '@lit-labs/virtualizer';
|
||||
import '@tp/tp-icon/tp-icon.js';
|
||||
import '@tp/tp-checkbox/tp-checkbox.js';
|
||||
import './tp-table-item.js';
|
||||
import { DomQuery } from '@tp/helpers/dom-query.js';
|
||||
import { closest } from '@tp/helpers/closest.js';
|
||||
import ColumResizer from './column-resizer.js';
|
||||
import { LitElement, html, css, svg } from 'lit';
|
||||
|
||||
export class TpTable extends DomQuery(LitElement) {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#tableHeader {
|
||||
display: grid;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#virtualList,
|
||||
.empty-message {
|
||||
position: absolute !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#virtualList {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.empty-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a.sort-link,
|
||||
a.no-sort-link {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
border-right: solid 1px #c1c1c1;
|
||||
padding: 10px 20px 10px 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a.sort-link:hover,
|
||||
a.no-sort-link:hover {
|
||||
border-right: solid 1px #c1c1c1;
|
||||
}
|
||||
|
||||
a.sort-link tp-icon {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
--tp-icon-width: 18px;
|
||||
--tp-icon-height: 18px;
|
||||
}
|
||||
|
||||
div.col-label {
|
||||
flex: 1;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.width-handle {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
right: -2px;
|
||||
cursor: col-resize;
|
||||
width: 6px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.width-handle > div {
|
||||
margin: auto;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#tableHeader:not(.col-dragging) a.sort-link .width-handle:hover > div {
|
||||
background: var(--pc-blue);
|
||||
}
|
||||
|
||||
a.sort-link .width-handle.dragging {
|
||||
position: fixed;
|
||||
height: 300px;
|
||||
z-index: 100;
|
||||
border-style: none;
|
||||
width: 3px;
|
||||
background: linear-gradient(180deg, rgba(59, 164, 240, 1), rgba(59, 164, 240, 0));
|
||||
}
|
||||
|
||||
.select-col {
|
||||
padding: 0px 20px 10px;
|
||||
}
|
||||
|
||||
lit-virtualizer {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
lit-virtualizer::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
lit-virtualizer::-webkit-scrollbar-track {
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
|
||||
lit-virtualizer::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb);
|
||||
outline: none;
|
||||
border-radius: var(--scrollbar-thumb-border-radius, 4px);
|
||||
}
|
||||
|
||||
[item]:not(.odd) {
|
||||
background: var(--table-bg-1);
|
||||
}
|
||||
|
||||
[item].odd {
|
||||
background: var(--table-bg-2);
|
||||
}
|
||||
|
||||
[item]:hover {
|
||||
background: var(--table-row-hl);
|
||||
--list-columns-h-borders: var(--list-columns-h-borders-hover);
|
||||
}
|
||||
`
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const columns = this.columns || [];
|
||||
const items = this.items || [];
|
||||
|
||||
return html`
|
||||
<div class="wrap">
|
||||
<div id="tableHeader" part="header" class="list-headline" @track=${this._colResizeTracked}>
|
||||
${this.selectable ? html`
|
||||
<div class="select-col"><tp-checkbox @checked-changed=${e => this._checkedChanged(e)}></tp-checkbox></div>
|
||||
` : null}
|
||||
${columns.map(column => this.renderColumnHeader(column))}
|
||||
</div>
|
||||
<div class="list">
|
||||
${this._emptyMessage}
|
||||
<lit-virtualizer id="virtualList" part="list" @scroll=${this._onScroll} scroller .items=${items} .renderItem=${(item, idx) => this.renderItem(item, idx, columns)}></lit-virtualizer>
|
||||
</div>
|
||||
|
||||
<tp-scroll-threshold id="threshold" lowerThreshold="40"></tp-scroll-threshold>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
renderColumnHeader(column) {
|
||||
if (column.visible !== true && column.required !== true) return null;
|
||||
|
||||
const { name, width, label, sortable } = column;
|
||||
const sorting = this.sorting || {};
|
||||
const isSortedBy = sorting.column === name;
|
||||
const sortDirection = isSortedBy ? sorting.direction : 'desc';
|
||||
const canSort = sortable !== false;
|
||||
|
||||
return html`
|
||||
<a part="column-label" class="${canSort ? 'sort-link' : 'no-sort-link'}" @click=${() => canSort ? this._sort(column, sortDirection) : null} .type=${name} .width=${width}>
|
||||
${canSort ? html`
|
||||
<tp-icon part="sort-icon" .icon=${sortDirection === 'asc' ? TpTable.downIcon : TpTable.upIcon} ?hidden=${!isSortedBy}></tp-icon>
|
||||
` : null}
|
||||
<div class="col-label">${label}</div>
|
||||
<div class="width-handle" part="width-handle"><div part="width-handle-bar"></div></div>
|
||||
${this.renderColumnHeaderAddons(column)}
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
renderColumnHeaderAddons(column) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static get downIcon() {
|
||||
return svg`<path fill="var(--tp-table-icon-color)" d="M7,10L12,15L17,10H7Z">`;
|
||||
}
|
||||
|
||||
static get upIcon() {
|
||||
return svg`<path fill="var(--tp-table-icon-color)" d="M7,15L12,10L17,15H7Z">`;
|
||||
}
|
||||
|
||||
renderItem(item, idx, columns) {
|
||||
return html`
|
||||
<tp-table-item
|
||||
exportparts="cell,odd,row"
|
||||
item
|
||||
.index=${idx}
|
||||
.item=${item}
|
||||
.selectable=${this.selectable}
|
||||
.columns=${columns}
|
||||
@selection-changed=${(e) => this._selectionChanged(e)}>
|
||||
</tp-table-item>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
sorting: { type: Object },
|
||||
selectable: { type: Boolean },
|
||||
columns: { type: Array },
|
||||
_selItems: { type: Array },
|
||||
_visibleColumns: { type: Array },
|
||||
items: { type: Array },
|
||||
_advFilters: { type: Array },
|
||||
_advFilterActive: { type: Boolean },
|
||||
_advFilterFields: { type: Object },
|
||||
_filter: { type: String },
|
||||
_totalCount: { type: Number },
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._selItems = [];
|
||||
}
|
||||
|
||||
updated(changes) {
|
||||
if (changes.has('columns')) {
|
||||
this._updateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
get _emptyMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get sortingPath() {
|
||||
return `${this.dataKey}.sorting`;
|
||||
}
|
||||
|
||||
get statusFilterPath() {
|
||||
return `${this.dataKey}.filtering.statusFilter`;
|
||||
}
|
||||
|
||||
set filter(val) {
|
||||
this._advFilterActive = false;
|
||||
this._filter = this._clone(val);
|
||||
this.reloadPagedList();
|
||||
}
|
||||
|
||||
set statusFilter(val) {
|
||||
this._statusFilter = this._clone(val);
|
||||
this.reloadPagedList();
|
||||
}
|
||||
|
||||
set advancedFilter(val) {
|
||||
this._advFilterActive = val ? true : false;
|
||||
this._advFilters = this._clone(val);
|
||||
this.reloadPagedList();
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.shadowRoot.querySelector('tp-scroll-threshold').target = this.shadowRoot.querySelector('lit-virtualizer');
|
||||
new ColumResizer(this.$.tableHeader, '.width-handle');
|
||||
}
|
||||
|
||||
_onScroll(e) {
|
||||
this.$.tableHeader.style.paddingRight = (this.$.virtualList.offsetWidth - this.$.virtualList.clientWidth) + 'px';
|
||||
this.$.tableHeader.scrollLeft = this.$.virtualList.scrollLeft;
|
||||
}
|
||||
|
||||
shouldUpdate(changes) {
|
||||
if (changes.has('items')) {
|
||||
this._updateSelEntries();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_sort(column, direction) {
|
||||
if (this._draggedColumn) return;
|
||||
|
||||
this.sorting = { column: column.name, direction: direction === 'asc' ? 'desc' : 'asc' };
|
||||
this.dispatchEvent(new CustomEvent('sorting-changed', { detail: this.sorting, bubbles: true, composed: true }));
|
||||
}
|
||||
|
||||
_updateColumns() {
|
||||
this.$.tableHeader.style.gridTemplateColumns = this._updateColumnWidths(this.selectable ? [ '40px' ] : []).join(' ');
|
||||
}
|
||||
|
||||
_updateColumnWidths(prepend) {
|
||||
return [ ...(prepend || []), ...this.columns.filter(col => col.required || col.visible).map(col => col.width) ];
|
||||
}
|
||||
|
||||
_colResizeTracked(e) {
|
||||
const handle = closest(e.target, '.width-handle');
|
||||
const data = e.detail;
|
||||
|
||||
if (data.state === 'start') {
|
||||
this._draggedColumn = true;
|
||||
const rect = handle.getBoundingClientRect();
|
||||
document.body.style.userSelect = 'none';
|
||||
handle.style.top = `${rect.top}px`;
|
||||
handle.style.left = `${rect.left}px`;
|
||||
handle.style.transform = `translateX(${data.dx}px)`;
|
||||
handle.classList.add('dragging');
|
||||
this.$.tableHeader.classList.add('col-dragging');
|
||||
} else if (data.state === 'end') {
|
||||
document.body.style.userSelect = '';
|
||||
handle.classList.remove('dragging');
|
||||
handle.style.transform = '';
|
||||
handle.style.top = '';
|
||||
handle.style.left = '';
|
||||
this.$.tableHeader.classList.remove('col-dragging');
|
||||
|
||||
const colLink = closest(handle, 'a');
|
||||
const { type, width } = colLink;
|
||||
const newWidth = (parseInt(width, 10) + data.dx) + 'px';
|
||||
const colDef = this.columns.find(col => col.name === type);
|
||||
colDef.width = newWidth;
|
||||
this.columns = [...this.columns];
|
||||
|
||||
setTimeout(() => {
|
||||
this._draggedColumn = false;
|
||||
this.dispatchEvent(new CustomEvent('column-width-changed', { detail: this.columns, bubbles: true, composed: true }));
|
||||
});
|
||||
} else if (data.state === 'track') {
|
||||
handle.style.transform = `translateX(${data.dx}px)`;
|
||||
}
|
||||
}
|
||||
|
||||
clearTriggers() {
|
||||
if (this.$.threshold) {
|
||||
this.$.threshold.clearTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
_listOverflows() {
|
||||
return this.$.virtualList.scrollHeight > this.$.virtualList.offsetHeight;
|
||||
}
|
||||
|
||||
_checkedChanged(e) {
|
||||
if (Array.isArray(this.items) === false) return;
|
||||
|
||||
if (e.detail.value) {
|
||||
this._selectAll();
|
||||
} else {
|
||||
this._selectNone();
|
||||
}
|
||||
|
||||
this.items = [...this.times];
|
||||
}
|
||||
|
||||
_selectAll() {
|
||||
this.items.forEach((entry, idx) => {
|
||||
this.items[idx].__selected__ = true;
|
||||
});
|
||||
|
||||
this._selectionChanged();
|
||||
}
|
||||
|
||||
_selectNone() {
|
||||
this._items.forEach((entry, idx) => {
|
||||
this._items[idx].__selected__ = false;
|
||||
});
|
||||
|
||||
this._selectionChanged();
|
||||
}
|
||||
|
||||
_selectionChanged(e) {
|
||||
if (this.__restoringSelection) return;
|
||||
|
||||
if (e !== undefined) {
|
||||
const item = this._items.find(item => item._id === e.detail.item._id);
|
||||
item.__selected__ = e.detail.selected;
|
||||
}
|
||||
|
||||
this._selItems = this._items.filter(entry => entry.__selected__ === true);
|
||||
this.dispatchEvent(new CustomEvent('item-selection-changed', { detail: this._selItems, bubbles: true, composed: true }));
|
||||
}
|
||||
|
||||
_updateSelEntries() {
|
||||
this._hiddenSelection = 0;
|
||||
|
||||
if (!this._items) {
|
||||
this._selItems = [];
|
||||
} else {
|
||||
this._selItems.forEach(sel => {
|
||||
const idx = this._items.findIndex(entry => entry._id === sel._id);
|
||||
if (idx > -1) {
|
||||
// Suppress rebuild of the selected invoices list.
|
||||
// When we restore the selection on a filtered list of invoices we would loose the selection of hidden onces
|
||||
// when _selectionChanged is triggered. So we set a flag that the observer is skipped.
|
||||
this.__restoringSelection = true;
|
||||
this._items[idx].__selected__ = true;
|
||||
this.__restoringSelection = false;
|
||||
} else {
|
||||
this._hiddenSelection++;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('tp-table', TpTable);
|
@ -6,7 +6,7 @@ This program is available under Apache License Version 2.0
|
||||
|
||||
import { LitElement, html, css } from 'lit';
|
||||
|
||||
class TpElement extends LitElement {
|
||||
class TpTextFilter extends LitElement {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
@ -21,7 +21,8 @@ class TpElement extends LitElement {
|
||||
const { } = this;
|
||||
|
||||
return html`
|
||||
|
||||
<h1>Test</h1>
|
||||
<p>No</p>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -32,4 +33,4 @@ class TpElement extends LitElement {
|
||||
|
||||
}
|
||||
|
||||
window.customElements.define('tp-element', TpElement);
|
||||
window.customElements.define('tp-text-filter', TpTextFilter);
|
Loading…
Reference in New Issue
Block a user