kempo 2.7.0 → 2.7.2

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.
@@ -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,r={before:[],after:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[]}}),e&&this.setData(e,t,r)}async render(e){return!!await super.render(e)&&(this.renderFields(),this.renderRecords(),!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(){this.shadowRoot.getElementById("records").innerHTML=this.records.map((e=>`<tr>${this.renderControls(this.controls.before,e)}${this.fields.map((({name:t})=>{let r=e[t]||"";return Array.isArray(r)&&(r=r.join(", ")),`<td>${r}</td>`})).join("")}${this.renderControls(this.controls.after,e)}</tr>`)).join("")}renderControls(e=[],t){return 0===e.length?"":`<td>${e.map((({html:e,icon:r,action:s})=>{if(e)return e;if(render&&"function"==typeof render)return render(t,this);{const e=document.createElement("button");e.appendChild(new Icon(r)),s&&e.addEventListener("click",(()=>s(t,this)))}return button.outerHTML})).join("")}</td>`}setData(e,t=!1,r={before:[],after:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=r,this.renderFields(),this.renderRecords(),this.renderControls()}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\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 r=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>r.add(e)))})),[...r].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
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,r={before:[],after:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[]}}),e&&this.setData(e,t,r)}async render(e){return!!await super.render(e)&&(this.renderFields(),this.renderRecords(),!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 r=document.createElement("tr");this.controls?.before?.length&&r.appendChild(this.renderControls(this.controls.before,t)),this.fields.forEach((({name:e})=>{const n=document.createElement("td");let s=t[e]||"";Array.isArray(s)&&(s=s.join(", ")),n.innerHTML=s,r.appendChild(n)})),this.controls?.after?.length&&r.appendChild(this.renderControls(this.controls.after,t)),e.appendChild(r)}))}renderControls(e=[],t){const r=document.createElement("td");return e.forEach((({html:e,icon:n,action:s,render:o})=>{if(e)r.appendChild(document.createRange().createContextualFragment(e));else if(o&&"function"==typeof o){const e=o(t,this);e instanceof HTMLElement?r.appendChild(e):"string"==typeof e&&r.appendChild(document.createRange().createContextualFragment(e))}else if(n){const e=document.createElement("button");e.appendChild(new Icon(n)),s&&e.addEventListener("click",(()=>s(t,this))),r.appendChild(e)}})),r}setData(e,t=!1,r={before:[],after:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=r,this.renderFields(),this.renderRecords()}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\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 r=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>r.add(e)))})),[...r].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,47 @@
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>&lt;td&gt;</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: (record, table) => console.log('Edit', record, table)
135
+ }
136
+ ],
137
+ after: [
138
+ {
139
+ icon: 'delete',
140
+ action: (record, table) => console.log('Delete', record, table)
141
+ },
142
+ {
143
+ html: '<span>Custom HTML</span>'
144
+ },
145
+ {
146
+ render: (record, table) => `<a href="mailto:${record.emailAddress}">Email</a>`
147
+ }
148
+ ]
149
+ });
150
+ </script>
151
+
110
152
  <h3 id="constructor"><a href="#consttructor" class="no-link">Constructor</a></h3>
111
153
  <h6>Extends <a href="./component.html">Component</a></h6>
112
154
  <h5>
@@ -150,11 +192,10 @@
150
192
  action: (record, table) => console.log('Delete', record, table)
151
193
  },
152
194
  {
153
- html: '<span>Custom HTML</span>',
154
- action: (record, table) => console.log('Custom Action', record, table)
195
+ html: '<span>Custom HTML</span>'
155
196
  },
156
197
  {
157
- render: (record, table) => `<button onclick="console.log('Rendered Action', ${record}, ${table})">Rendered Button</button>`
198
+ render: (record, table) => `&lt;button onclick="console.log('Rendered Action', ${record}, ${table})">Rendered Button&lt;/button>`
158
199
  }
159
200
  ]
160
201
  }</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,r={before:[],after:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[]}}),e&&this.setData(e,t,r)}async render(e){return!!await super.render(e)&&(this.renderFields(),this.renderRecords(),!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(){this.shadowRoot.getElementById("records").innerHTML=this.records.map((e=>`<tr>${this.renderControls(this.controls.before,e)}${this.fields.map((({name:t})=>{let r=e[t]||"";return Array.isArray(r)&&(r=r.join(", ")),`<td>${r}</td>`})).join("")}${this.renderControls(this.controls.after,e)}</tr>`)).join("")}renderControls(e=[],t){return 0===e.length?"":`<td>${e.map((({html:e,icon:r,action:s})=>{if(e)return e;if(render&&"function"==typeof render)return render(t,this);{const e=document.createElement("button");e.appendChild(new Icon(r)),s&&e.addEventListener("click",(()=>s(t,this)))}return button.outerHTML})).join("")}</td>`}setData(e,t=!1,r={before:[],after:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=r,this.renderFields(),this.renderRecords(),this.renderControls()}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\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 r=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>r.add(e)))})),[...r].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
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,r={before:[],after:[]}){super(),this.registerProps({fields:[],records:[],controls:{before:[],after:[]}}),e&&this.setData(e,t,r)}async render(e){return!!await super.render(e)&&(this.renderFields(),this.renderRecords(),!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 r=document.createElement("tr");this.controls?.before?.length&&r.appendChild(this.renderControls(this.controls.before,t)),this.fields.forEach((({name:e})=>{const n=document.createElement("td");let s=t[e]||"";Array.isArray(s)&&(s=s.join(", ")),n.innerHTML=s,r.appendChild(n)})),this.controls?.after?.length&&r.appendChild(this.renderControls(this.controls.after,t)),e.appendChild(r)}))}renderControls(e=[],t){const r=document.createElement("td");return e.forEach((({html:e,icon:n,action:s,render:o})=>{if(e)r.appendChild(document.createRange().createContextualFragment(e));else if(o&&"function"==typeof o){const e=o(t,this);e instanceof HTMLElement?r.appendChild(e):"string"==typeof e&&r.appendChild(document.createRange().createContextualFragment(e))}else if(n){const e=document.createElement("button");e.appendChild(new Icon(n)),s&&e.addEventListener("click",(()=>s(t,this))),r.appendChild(e)}})),r}setData(e,t=!1,r={before:[],after:[]}){this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),this.controls=r,this.renderFields(),this.renderRecords()}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <table>\n <thead id="fields"></thead>\n <tbody id="records"></tbody>\n </table>\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 r=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>r.add(e)))})),[...r].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo",
3
- "version": "2.7.0",
3
+ "version": "2.7.2",
4
4
  "type": "module",
5
5
  "description": "A web component library",
6
6
  "main": "dist/index.js",
@@ -26,38 +26,56 @@ export default class Table extends Component {
26
26
  return false;
27
27
  }
28
28
  renderFields(){
29
- const beforeControls = this.controls.before?.length ? '<th></th>' : '';
30
- const afterControls = this.controls.after?.length ? '<th></th>' : '';
29
+ const beforeControls = this.controls?.before?.length ? '<th></th>' : '';
30
+ const afterControls = this.controls?.after?.length ? '<th></th>' : '';
31
31
  this.shadowRoot.getElementById('fields').innerHTML = `${beforeControls}${this.fields.map(({label})=>`<th>${label}</th>`).join('')}${afterControls}`;
32
32
  }
33
33
  renderRecords(){
34
- this.shadowRoot.getElementById('records').innerHTML = this.records.map((record) => {
35
- return `<tr>${this.renderControls(this.controls.before, record)}${this.fields.map(({name}) => {
34
+ const $records = this.shadowRoot.getElementById('records');
35
+ $records.innerHTML = '';
36
+ this.records.forEach((record) => {
37
+ const $tr = document.createElement('tr');
38
+ if(this.controls?.before?.length){
39
+ $tr.appendChild(this.renderControls(this.controls.before, record));
40
+ }
41
+ this.fields.forEach(({name}) => {
42
+ const $td = document.createElement('td');
36
43
  let value = record[name] || '';
37
44
  if (Array.isArray(value)) {
38
45
  value = value.join(', ');
39
46
  }
40
- return `<td>${value}</td>`;
41
- }).join('')}${this.renderControls(this.controls.after, record)}</tr>`;
42
- }).join('');
47
+ $td.innerHTML = value;
48
+ $tr.appendChild($td);
49
+ });
50
+ if(this.controls?.after?.length){
51
+ $tr.appendChild(this.renderControls(this.controls.after, record));
52
+ }
53
+ $records.appendChild($tr);
54
+ });
43
55
  }
44
56
 
45
57
  renderControls(controls = [], record) {
46
- if (controls.length === 0) return '';
47
- return `<td>${controls.map(({ html, icon, action }) => {
58
+ const $td = document.createElement('td');
59
+ controls.forEach(({ html, icon, action, render }) => {
48
60
  if(html){
49
- return html;
61
+ $td.appendChild(document.createRange().createContextualFragment(html));
50
62
  } else if(render && typeof(render) === 'function'){
51
- return render(record, this);
52
- } else {
63
+ const rendered = render(record, this);
64
+ if(rendered instanceof HTMLElement){
65
+ $td.appendChild(rendered);
66
+ } else if(typeof(rendered) === 'string'){
67
+ $td.appendChild(document.createRange().createContextualFragment(rendered));
68
+ }
69
+ } else if(icon){
53
70
  const $button = document.createElement('button');
54
71
  $button.appendChild(new Icon(icon));
55
72
  if (action) {
56
73
  $button.addEventListener('click', () => action(record, this));
57
74
  }
75
+ $td.appendChild($button);
58
76
  }
59
- return button.outerHTML;
60
- }).join('')}</td>`;
77
+ });
78
+ return $td;
61
79
  }
62
80
 
63
81
  setData(records, fields = false, controls = { before: [], after: [] }){
@@ -66,7 +84,6 @@ export default class Table extends Component {
66
84
  this.controls = controls;
67
85
  this.renderFields();
68
86
  this.renderRecords();
69
- this.renderControls();
70
87
  }
71
88
 
72
89
  get shadowTemplate(){