kempo 2.7.1 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/components/Table.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import Icon from"./Icon.js";import{toTitleCase}from"../utils/string.js";export default class Table extends Component{constructor(e=!1,t=!1,
|
|
1
|
+
import Component from"./Component.js";import Icon from"./Icon.js";import{toTitleCase}from"../utils/string.js";export default class Table extends Component{constructor(e=!1,t=!1,o={before:[],after:[],top:[],bottom:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[],top:[],bottom:[]}}),e&&this.setData(e,t,o)}async render(e){return!!await super.render(e)&&(this.renderControls(this.controls.top,"top"),this.renderFields(),this.renderRecords(),this.renderControls(this.controls.bottom,"bottom"),!0)}renderFields(){const e=this.controls?.before?.length?"<th></th>":"",t=this.controls?.after?.length?"<th></th>":"";this.shadowRoot.getElementById("fields").innerHTML=`${e}${this.fields.map((({label:e})=>`<th>${e}</th>`)).join("")}${t}`}renderRecords(){const e=this.shadowRoot.getElementById("records");e.innerHTML="",this.records.forEach((t=>{const o=document.createElement("tr");this.controls?.before?.length&&o.appendChild(this.renderRowControls(this.controls.before,t)),this.fields.forEach((({name:e})=>{const n=document.createElement("td");let r=t[e]||"";Array.isArray(r)&&(r=r.join(", ")),n.innerHTML=r,o.appendChild(n)})),this.controls?.after?.length&&o.appendChild(this.renderRowControls(this.controls.after,t)),e.appendChild(o)}))}renderRowControls(e=[],t){const o=document.createElement("td");return e.forEach((({html:e,icon:n,action:r,render:s})=>{if(e)o.appendChild(document.createRange().createContextualFragment(e));else if(s&&"function"==typeof s){const e=s(this,t);e instanceof HTMLElement?o.appendChild(e):"string"==typeof e&&o.appendChild(document.createRange().createContextualFragment(e))}else if(n){const e=document.createElement("button");e.appendChild(new Icon(n)),r&&e.addEventListener("click",(()=>r(this,t))),o.appendChild(e)}})),o}renderControls(e=[],t){const o=document.createElement("div");e.forEach((({html:e,icon:t,action:n,render:r})=>{if(e)o.appendChild(document.createRange().createContextualFragment(e));else if(r&&"function"==typeof r){const e=r(this);e instanceof HTMLElement?o.appendChild(e):"string"==typeof e&&o.appendChild(document.createRange().createContextualFragment(e))}else if(t){const e=document.createElement("button");e.appendChild(new Icon(t)),n&&e.addEventListener("click",(()=>n(this))),o.appendChild(e)}})),this.shadowRoot.getElementById(t).innerHTML="",this.shadowRoot.getElementById(t).appendChild(o)}setData(e,t=!1,o={before:[],after:[],top:[],bottom:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=o,this.renderControls(this.controls.top,"top"),this.renderFields(),this.renderRecords(),this.renderControls(this.controls.bottom,"bottom")}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <div id="top"></div>\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\n <div id="bottom"></div>\n </div>\n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n margin-bottom: var(--spacer);\n }\n `}static extractFieldsFromRecords(e,t=100){const o=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>o.add(e)))})),[...o].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<a href="#requirements">Requirements</a><br />
|
|
23
23
|
<a href="#properties">Properties</a><br />
|
|
24
24
|
<a href="#methods">Methods</a><br />
|
|
25
|
+
<a href="#controls">Row Controls</a><br />
|
|
25
26
|
</div>
|
|
26
27
|
</details>
|
|
27
28
|
|
|
@@ -107,6 +108,59 @@
|
|
|
107
108
|
]);
|
|
108
109
|
</script>
|
|
109
110
|
|
|
111
|
+
<h3 id="controls"><a href="#controls" class="no-link">Row Controls</a></h3>
|
|
112
|
+
<p>The table component can display controls before or after each row. Each control is defined by an icon name, a callback function, and optionally an HTML string or a render function. All controls are combined into a single <code><td></code> with each control being a button.</p>
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
<k-table id="contacts2"></k-table>
|
|
116
|
+
<script type="module">
|
|
117
|
+
document.getElementById('contacts2').setData([
|
|
118
|
+
{
|
|
119
|
+
name: "Dustin",
|
|
120
|
+
phoneNumber: "(111) 111-1111",
|
|
121
|
+
emailAddress: "dustin@mailserver.com",
|
|
122
|
+
gender: "Male"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "Kayla",
|
|
126
|
+
phoneNumber: "(222) 222-2222",
|
|
127
|
+
emailAddress: "kayla@mailserver.com",
|
|
128
|
+
gender: "Female"
|
|
129
|
+
}
|
|
130
|
+
], false, {
|
|
131
|
+
before: [
|
|
132
|
+
{
|
|
133
|
+
icon: 'edit',
|
|
134
|
+
action: (table, record) => console.log('Edit', table, record)
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
after: [
|
|
138
|
+
{
|
|
139
|
+
icon: 'delete',
|
|
140
|
+
action: (table, record) => console.log('Delete', table, record)
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
html: '<span>Custom HTML</span>'
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
render: (table, record) => `<a href="mailto:${record.emailAddress}">Email</a>`
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
top: [
|
|
150
|
+
{
|
|
151
|
+
icon: 'add',
|
|
152
|
+
action: (table) => console.log('Add', table)
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
bottom: [
|
|
156
|
+
{
|
|
157
|
+
icon: 'refresh',
|
|
158
|
+
action: (table) => console.log('Refresh', table)
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
});
|
|
162
|
+
</script>
|
|
163
|
+
|
|
110
164
|
<h3 id="constructor"><a href="#consttructor" class="no-link">Constructor</a></h3>
|
|
111
165
|
<h6>Extends <a href="./component.html">Component</a></h6>
|
|
112
166
|
<h5>
|
|
@@ -150,11 +204,10 @@
|
|
|
150
204
|
action: (record, table) => console.log('Delete', record, table)
|
|
151
205
|
},
|
|
152
206
|
{
|
|
153
|
-
html: '<span>Custom HTML</span>'
|
|
154
|
-
action: (record, table) => console.log('Custom Action', record, table)
|
|
207
|
+
html: '<span>Custom HTML</span>'
|
|
155
208
|
},
|
|
156
209
|
{
|
|
157
|
-
render: (record, table) =>
|
|
210
|
+
render: (record, table) => `<button onclick="console.log('Rendered Action', ${record}, ${table})">Rendered Button</button>`
|
|
158
211
|
}
|
|
159
212
|
]
|
|
160
213
|
}</code></pre>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import Icon from"./Icon.js";import{toTitleCase}from"../utils/string.js";export default class Table extends Component{constructor(e=!1,t=!1,
|
|
1
|
+
import Component from"./Component.js";import Icon from"./Icon.js";import{toTitleCase}from"../utils/string.js";export default class Table extends Component{constructor(e=!1,t=!1,o={before:[],after:[],top:[],bottom:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[],top:[],bottom:[]}}),e&&this.setData(e,t,o)}async render(e){return!!await super.render(e)&&(this.renderControls(this.controls.top,"top"),this.renderFields(),this.renderRecords(),this.renderControls(this.controls.bottom,"bottom"),!0)}renderFields(){const e=this.controls?.before?.length?"<th></th>":"",t=this.controls?.after?.length?"<th></th>":"";this.shadowRoot.getElementById("fields").innerHTML=`${e}${this.fields.map((({label:e})=>`<th>${e}</th>`)).join("")}${t}`}renderRecords(){const e=this.shadowRoot.getElementById("records");e.innerHTML="",this.records.forEach((t=>{const o=document.createElement("tr");this.controls?.before?.length&&o.appendChild(this.renderRowControls(this.controls.before,t)),this.fields.forEach((({name:e})=>{const n=document.createElement("td");let r=t[e]||"";Array.isArray(r)&&(r=r.join(", ")),n.innerHTML=r,o.appendChild(n)})),this.controls?.after?.length&&o.appendChild(this.renderRowControls(this.controls.after,t)),e.appendChild(o)}))}renderRowControls(e=[],t){const o=document.createElement("td");return e.forEach((({html:e,icon:n,action:r,render:s})=>{if(e)o.appendChild(document.createRange().createContextualFragment(e));else if(s&&"function"==typeof s){const e=s(this,t);e instanceof HTMLElement?o.appendChild(e):"string"==typeof e&&o.appendChild(document.createRange().createContextualFragment(e))}else if(n){const e=document.createElement("button");e.appendChild(new Icon(n)),r&&e.addEventListener("click",(()=>r(this,t))),o.appendChild(e)}})),o}renderControls(e=[],t){const o=document.createElement("div");e.forEach((({html:e,icon:t,action:n,render:r})=>{if(e)o.appendChild(document.createRange().createContextualFragment(e));else if(r&&"function"==typeof r){const e=r(this);e instanceof HTMLElement?o.appendChild(e):"string"==typeof e&&o.appendChild(document.createRange().createContextualFragment(e))}else if(t){const e=document.createElement("button");e.appendChild(new Icon(t)),n&&e.addEventListener("click",(()=>n(this))),o.appendChild(e)}})),this.shadowRoot.getElementById(t).innerHTML="",this.shadowRoot.getElementById(t).appendChild(o)}setData(e,t=!1,o={before:[],after:[],top:[],bottom:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=o,this.renderControls(this.controls.top,"top"),this.renderFields(),this.renderRecords(),this.renderControls(this.controls.bottom,"bottom")}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <div id="top"></div>\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\n <div id="bottom"></div>\n </div>\n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n margin-bottom: var(--spacer);\n }\n `}static extractFieldsFromRecords(e,t=100){const o=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>o.add(e)))})),[...o].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
|
package/package.json
CHANGED
package/src/components/Table.js
CHANGED
|
@@ -3,13 +3,13 @@ import Icon from './Icon.js'; // Import Icon component
|
|
|
3
3
|
import { toTitleCase } from '../utils/string.js';
|
|
4
4
|
|
|
5
5
|
export default class Table extends Component {
|
|
6
|
-
constructor(data = false, fields = false, controls = { before: [], after: [] }){
|
|
6
|
+
constructor(data = false, fields = false, controls = { before: [], after: [], top: [], bottom: [] }){
|
|
7
7
|
super();
|
|
8
8
|
|
|
9
9
|
this.registerProps({
|
|
10
10
|
fields: [],
|
|
11
11
|
records: [],
|
|
12
|
-
controls: { before: [], after: [] }
|
|
12
|
+
controls: { before: [], after: [], top: [], bottom: [] }
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
/* Init */
|
|
@@ -19,64 +19,112 @@ export default class Table extends Component {
|
|
|
19
19
|
}
|
|
20
20
|
async render(force){
|
|
21
21
|
if(await super.render(force)){
|
|
22
|
+
this.renderControls(this.controls.top, 'top');
|
|
22
23
|
this.renderFields();
|
|
23
24
|
this.renderRecords();
|
|
25
|
+
this.renderControls(this.controls.bottom, 'bottom');
|
|
24
26
|
return true;
|
|
25
27
|
}
|
|
26
28
|
return false;
|
|
27
29
|
}
|
|
28
30
|
renderFields(){
|
|
29
|
-
const beforeControls = this.controls
|
|
30
|
-
const afterControls = this.controls
|
|
31
|
+
const beforeControls = this.controls?.before?.length ? '<th></th>' : '';
|
|
32
|
+
const afterControls = this.controls?.after?.length ? '<th></th>' : '';
|
|
31
33
|
this.shadowRoot.getElementById('fields').innerHTML = `${beforeControls}${this.fields.map(({label})=>`<th>${label}</th>`).join('')}${afterControls}`;
|
|
32
34
|
}
|
|
33
35
|
renderRecords(){
|
|
34
|
-
this.shadowRoot.getElementById('records')
|
|
35
|
-
|
|
36
|
+
const $records = this.shadowRoot.getElementById('records');
|
|
37
|
+
$records.innerHTML = '';
|
|
38
|
+
this.records.forEach((record) => {
|
|
39
|
+
const $tr = document.createElement('tr');
|
|
40
|
+
if(this.controls?.before?.length){
|
|
41
|
+
$tr.appendChild(this.renderRowControls(this.controls.before, record));
|
|
42
|
+
}
|
|
43
|
+
this.fields.forEach(({name}) => {
|
|
44
|
+
const $td = document.createElement('td');
|
|
36
45
|
let value = record[name] || '';
|
|
37
46
|
if (Array.isArray(value)) {
|
|
38
47
|
value = value.join(', ');
|
|
39
48
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
$td.innerHTML = value;
|
|
50
|
+
$tr.appendChild($td);
|
|
51
|
+
});
|
|
52
|
+
if(this.controls?.after?.length){
|
|
53
|
+
$tr.appendChild(this.renderRowControls(this.controls.after, record));
|
|
54
|
+
}
|
|
55
|
+
$records.appendChild($tr);
|
|
56
|
+
});
|
|
43
57
|
}
|
|
44
58
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
59
|
+
renderRowControls(controls = [], record) {
|
|
60
|
+
const $td = document.createElement('td');
|
|
61
|
+
controls.forEach(({ html, icon, action, render }) => {
|
|
62
|
+
if(html){
|
|
63
|
+
$td.appendChild(document.createRange().createContextualFragment(html));
|
|
64
|
+
} else if(render && typeof(render) === 'function'){
|
|
65
|
+
const rendered = render(this, record);
|
|
66
|
+
if(rendered instanceof HTMLElement){
|
|
67
|
+
$td.appendChild(rendered);
|
|
68
|
+
} else if(typeof(rendered) === 'string'){
|
|
69
|
+
$td.appendChild(document.createRange().createContextualFragment(rendered));
|
|
70
|
+
}
|
|
71
|
+
} else if(icon){
|
|
72
|
+
const $button = document.createElement('button');
|
|
73
|
+
$button.appendChild(new Icon(icon));
|
|
74
|
+
if (action) {
|
|
75
|
+
$button.addEventListener('click', () => action(this, record));
|
|
76
|
+
}
|
|
77
|
+
$td.appendChild($button);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return $td;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
renderControls(controls = [], position) {
|
|
84
|
+
const $container = document.createElement('div');
|
|
85
|
+
controls.forEach(({ html, icon, action, render }) => {
|
|
48
86
|
if(html){
|
|
49
|
-
|
|
87
|
+
$container.appendChild(document.createRange().createContextualFragment(html));
|
|
50
88
|
} else if(render && typeof(render) === 'function'){
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
const rendered = render(this);
|
|
90
|
+
if(rendered instanceof HTMLElement){
|
|
91
|
+
$container.appendChild(rendered);
|
|
92
|
+
} else if(typeof(rendered) === 'string'){
|
|
93
|
+
$container.appendChild(document.createRange().createContextualFragment(rendered));
|
|
94
|
+
}
|
|
95
|
+
} else if(icon){
|
|
53
96
|
const $button = document.createElement('button');
|
|
54
97
|
$button.appendChild(new Icon(icon));
|
|
55
98
|
if (action) {
|
|
56
|
-
$button.addEventListener('click', () => action(
|
|
99
|
+
$button.addEventListener('click', () => action(this));
|
|
57
100
|
}
|
|
101
|
+
$container.appendChild($button);
|
|
58
102
|
}
|
|
59
|
-
|
|
60
|
-
|
|
103
|
+
});
|
|
104
|
+
this.shadowRoot.getElementById(position).innerHTML = '';
|
|
105
|
+
this.shadowRoot.getElementById(position).appendChild($container);
|
|
61
106
|
}
|
|
62
107
|
|
|
63
|
-
setData(records, fields = false, controls = { before: [], after: [] }){
|
|
108
|
+
setData(records, fields = false, controls = { before: [], after: [], top: [], bottom: [] }){
|
|
64
109
|
this.records = records;
|
|
65
110
|
this.fields = fields || Table.extractFieldsFromRecords(this.records);
|
|
66
111
|
this.controls = controls;
|
|
112
|
+
this.renderControls(this.controls.top, 'top');
|
|
67
113
|
this.renderFields();
|
|
68
114
|
this.renderRecords();
|
|
69
|
-
this.renderControls();
|
|
115
|
+
this.renderControls(this.controls.bottom, 'bottom');
|
|
70
116
|
}
|
|
71
117
|
|
|
72
118
|
get shadowTemplate(){
|
|
73
119
|
return /*html*/`
|
|
74
120
|
${super.shadowTemplate}
|
|
75
121
|
<div class="responsive-table">
|
|
122
|
+
<div id="top"></div>
|
|
76
123
|
<table>
|
|
77
124
|
<thead id="fields"></thead>
|
|
78
125
|
<tbody id="records"></tbody>
|
|
79
126
|
</table>
|
|
127
|
+
<div id="bottom"></div>
|
|
80
128
|
</div>
|
|
81
129
|
`;
|
|
82
130
|
}
|