v0.0.13: Refactored the render-loop to solve hard-to-track bugs and added more (elaborate) unit-tests to make sure it all works

This commit is contained in:
2020-04-15 16:33:32 +02:00
parent b95e5506d2
commit 0da07549e7
28 changed files with 1113 additions and 235 deletions

View File

@@ -27,6 +27,9 @@
<li>
<a href="./table/">Tables (arrow functions)</a>
</li>
<li>
<a href="./table-2/">Tables 2 (Key-prop)</a>
</li>
</ul>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cerxes - CustomElements - SVG</title>
</head>
<body>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>

132
examples/table-2/index.jsx Normal file
View File

@@ -0,0 +1,132 @@
import {render, CustomElement, defineElement, Host, prop, state} from "../../packages/csx";
import style from "./index.scss";
import {TableComponent} from "./table-component";
@defineElement("table-tester")
class TableTester extends CustomElement{
/**
*
* @type {({[headerRender]: (function(): string), render: (function(User): *), [size]: number})[]}
*/
#columnDefinitions = [
{
headerRender: () => "Id",
render: (u) => u.userId,
size: 110
},
{
headerRender: () => "Email",
render: (u) => u.identity?.email,
},
{
headerRender: () => "FirstName",
render: (u) => u.identity?.firstName,
size: 160
},
{
headerRender: () => "LastName",
render: (u) => u.identity?.lastName,
size: 160
},
{
headerRender: () => "Up",
render: (u) => {
let d = new Date();
return (<button onClick={(ev) => this.moveUp(ev, u, d)}>Up</button>)
},
size: 110
},
{
headerRender: () => "Down",
render: (u) => {
let d = new Date();
return (<button onClick={(ev) => this.moveDown(ev, u, d)}>Down</button>)
},
size: 110
},
];
@state()
users = [];
rowKey = (user)=>user.userId;
cellRef = (user, colIdx, el)=>user.cells[colIdx]=el;
render(){
return <TableComponent
columns={this.#columnDefinitions}
data={this.users}
rowKey={this.rowKey}
cellRef={this.cellRef}
/>
}
connectedCallback() {
super.connectedCallback();
setTimeout(()=>this.load(), 0);
}
interval;
disconnectedCallback() {
super.disconnectedCallback();
if(this.interval) {
clearInterval(this.interval);
}
}
load(){
let users = [];
let rndFirstNames = ['Loes', 'Johnny', 'Maria', 'Jezus', 'Philippe', 'Filip', 'Annie'];
let rndLastNames = ['Peeters', 'Wachters', 'Jannsens', 'De Schaetzen', 'Becks', 'Konings', 'De Clerk'];
for(let i = 0; i < 10; ++i){
let first = rndFirstNames[Math.floor(rndFirstNames.length*Math.random())];
let last = rndLastNames[Math.floor(rndLastNames.length*Math.random())];
users.push({
userId: (Math.random()*99999).toString(36).slice(-6).toUpperCase(),
identity: {
firstName: first,
lastName: last,
email: `${first}.${last}@example.com`.toLocaleLowerCase()
},
cells: []
})
}
this.users = users;
}
lastClear = new Date();
moveUp = (ev, u, d)=>{
let data = this.users.slice();
let indexOf = this.users.indexOf(u);
if(indexOf>0) {
let [before, after] = data.splice(indexOf - 1, 2);
data.splice(indexOf - 1, 0, after, before);
console.log(data.map((u,index)=>this.rowKey(u,index)))
this.users = data;
}
console.log(this.users);
}
moveDown = (ev, u, d)=>{
let data = this.users.slice();
let indexOf = this.users.indexOf(u);
if(indexOf<(this.users.length-1)) {
let [before, after] = data.splice(indexOf, 2);
data.splice(indexOf, 0, after, before);
console.log(data.map((u,index)=>this.rowKey(u,index)));
this.users = data;
}
console.log(this.users);
}
}
document.body.appendChild(render(<style>{style}</style>));
document.body.appendChild(render(<TableTester/>));

View File

@@ -0,0 +1,19 @@
html{
width: 100%;
height: 100%;
}
body{
display: flex;
flex-direction: column;
overflow: auto;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.center-me{
align-self: center;
}

View File

@@ -0,0 +1,72 @@
import {CustomElement, defineElement, Host, prop, state} from "../../packages/csx";
import TableComponentStyle from "./table-component.scss";
let tableId = 0;
@defineElement("tripto-table")
export class TableComponent extends CustomElement {
#columnDefinitions;
@prop()
set columns(value) {
this.#columnDefinitions = value;
}
@state() data;
@prop()
set data(value) {
this.data = value;
this.rows = new Map();
}
@prop()
rowKey = (value,index)=>index;
@prop()
cellRef = ()=>null;
rows = new Map();
#tableId = tableId++;
render() {
console.log(`Table render at for ${this.data?.length??0} rows: ${Date.now()}`);
return (
<Host>
<style>{TableComponentStyle}</style>
<style>
{this.#columnDefinitions?.map((col, idx) => (
`#table_${this.#tableId} .cell.cell_${idx} {` +
` flex: ${(col.size ? (`0 0 ${col.size}px`) : `1`)};` +
`}`
))}
</style>
<section className="table" id={`table_${this.#tableId}`}>
<header>
<div className="row">
{this.#columnDefinitions.map((col, idx) => (
<div className={`cell cell_${idx}`}>
{col.headerRender()}
</div>
))}
</div>
</header>
<main>
{this.data?.map((dataRow,index) => (
<div className="row"
key={this.rowKey(dataRow, index)}
ref={(el)=>this.rows.set(this.rowKey(dataRow,index), el)}>
{this.#columnDefinitions.map((col, idx) => (
<div className={`cell cell_${idx}`} key={idx} ref={(el)=>this.cellRef(dataRow,idx,el)}>
{col.render(dataRow)}
</div>
))}
</div>
))}
</main>
</section>
</Host>
);
}
}

View File

@@ -0,0 +1,32 @@
.table {
--box-color: #a0a0a0;
--primary-color: #5f74ff;
--table-background: #e4e4f0;
--box-border: 1px solid #7d7d7d;
border: var(--box-border);
display: block;
header {
color: var(--primary-color);
}
header > .row,
main > .row {
background: var(--table-background);
display: flex;
width: 100%;
line-height: 3em;
border-bottom: var(--box-border);
.cell {
padding: 0 15px;
}
}
main > .row {
&:last-child {
border-bottom: 0;
}
}
}