kempo 2.8.0 → 2.9.1
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 +1 -1
- package/dist/components/tableControls/DeleteSelected.js +1 -0
- package/dist/components/tableControls/PageSelect.js +1 -0
- package/dist/components/tableControls/PageSize.js +1 -0
- package/dist/components/tableControls/SelectCount.js +1 -0
- package/dist/index.js +1 -1
- package/docs/components/table.html +39 -0
- package/docs/kempo/components/Table.js +1 -1
- package/docs/kempo/components/tableControls/DeleteSelected.js +1 -0
- package/docs/kempo/components/tableControls/PageSelect.js +1 -0
- package/docs/kempo/components/tableControls/PageSize.js +1 -0
- package/docs/kempo/components/tableControls/SelectCount.js +1 -0
- package/docs/kempo/index.js +1 -1
- package/docs/table.html +0 -0
- package/package.json +1 -1
- package/scripts/build.js +43 -24
- package/src/components/Table.js +107 -134
- package/src/components/tableControls/DeleteSelected.js +58 -0
- package/src/components/tableControls/PageSelect.js +68 -0
- package/src/components/tableControls/PageSize.js +56 -0
- package/src/components/tableControls/SelectCount.js +47 -0
- package/dist/components/Stack.js +0 -1
- package/docs/kempo/components/Stack.js +0 -1
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";import{onEvent,dispatchEvent}from"../utils/element.js";export default class Table extends Component{static controls={prevPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq"),t.appendChild(new Icon("chevron-left")),onEvent(t,"click",(()=>e.prevPage())),onEvent(e,"pageChange",(()=>{t.disabled=1===e.getCurrentPage()})),t}},nextPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq"),t.appendChild(new Icon("chevron-right")),onEvent(t,"click",(()=>e.nextPage())),onEvent(e,"pageChange",(()=>{t.disabled=e.getCurrentPage()===e.getTotalPages()})),t}},pageSelect:{render:e=>new PageSelect(e)},pageSize:{render:e=>new PageSize(e)},spacer:{html:'<div class="flex"></div>'}};constructor({records:e=[],fields:t=[],controls:n={before:[],after:[],top:[],bottom:[]},pageSize:s=100,pageSizeOptions:r=[10,25,50,100,500],currentPage:
|
|
1
|
+
import Component from"./Component.js";import Icon from"./Icon.js";import SelectCount from"./tableControls/SelectCount.js";import PageSelect from"./tableControls/PageSelect.js";import PageSize from"./tableControls/PageSize.js";import DeleteSelected from"./tableControls/DeleteSelected.js";import{toTitleCase}from"../utils/string.js";import{onEvent,dispatchEvent}from"../utils/element.js";export default class Table extends Component{static controls={prevPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq","no-btn"),t.appendChild(new Icon("chevron-left")),onEvent(t,"click",(()=>e.prevPage())),onEvent(e,"pageChange",(()=>{t.disabled=1===e.getCurrentPage()})),t}},nextPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq","no-btn"),t.appendChild(new Icon("chevron-right")),onEvent(t,"click",(()=>e.nextPage())),onEvent(e,"pageChange",(()=>{t.disabled=e.getCurrentPage()===e.getTotalPages()})),t}},pageSelect:{render:e=>new PageSelect(e)},pageSize:{render:e=>new PageSize(e)},selectCount:{render:e=>new SelectCount(e)},deleteSelected:{render:e=>new DeleteSelected(e)},spacer:{html:'<div class="flex"></div>'}};constructor({records:e=[],fields:t=[],controls:n={before:[],after:[],top:[],bottom:[]},pageSize:s=100,pageSizeOptions:r=[10,25,50,100,500],currentPage:i=1,enableSelection:o=!1}={}){super(),this.registerProps({fields:t,records:e,controls:n,pageSize:s,pageSizeOptions:r,currentPage:i,enableSelection:o,selectedIndexes:[]})}async render(e){return!!await super.render(e)&&(this.setData({records:this.records,fields:this.fields,controls:this.controls,pageSize:this.pageSize,pageSizeOptions:this.pageSizeOptions,currentPage:this.currentPage}),!0)}renderFields(){if(!this.rendered)return;const e=this.controls?.before?.length?"<th></th>":"",t=this.controls?.after?.length?"<th></th>":"",n=this.enableSelection?'<th class="selection"><input type="checkbox" id="select-all"></th>':"";if(this.shadowRoot.getElementById("fields").innerHTML=`${n}${e}${this.fields.map((({label:e})=>`<th>${e}</th>`)).join("")}${t}`,this.enableSelection){const e=this.shadowRoot.getElementById("select-all");e.addEventListener("change",(()=>{e.checked?this.selectAllOnPage():this.deselectAllOnPage()})),onEvent(this,"selectionChange pageChange",(()=>{this.allOnPageSelected()?e.checked=!0:e.checked=!1}))}}renderRecords(){if(!this.rendered)return;const e=this.shadowRoot.getElementById("records");e.innerHTML="";const t=(this.currentPage-1)*this.pageSize,n=t+this.pageSize;this.records.slice(t,n).forEach(((s,r)=>{const i=document.createElement("tr");if(this.enableSelection){const e=document.createElement("td");e.classList.add("selection");const n=document.createElement("input");n.type="checkbox",n.checked=this.selectedIndexes.includes(t+r),n.addEventListener("change",(()=>{n.checked?this.selectedIndexes.push(t+r):this.selectedIndexes=this.selectedIndexes.filter((e=>e!==t+r)),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})})),e.appendChild(n),i.appendChild(e)}this.controls?.before?.length&&i.appendChild(this.renderRowControls(this.controls.before,s,t+r)),this.fields.forEach((({name:e,formatter:r,calculator:o})=>{const d=document.createElement("td");if(null===s)d.innerHTML="Loading...",dispatchEvent(this,"fetchRecords",{start:t,end:n});else{let t;o?t=o(s,this):(t=s[e]||"",Array.isArray(t)?t=r?t.map(r).join(", "):t.join(", "):r&&(t=r(t))),d.innerHTML=t}i.appendChild(d)})),this.controls?.after?.length&&i.appendChild(this.renderRowControls(this.controls.after,s,t+r)),e.appendChild(i)}))}renderRowControls(e=[],t,n){if(!this.rendered)return;const s=document.createElement("td");return e.forEach((({html:e,icon:r,action:i,render:o})=>{if(e)s.appendChild(document.createRange().createContextualFragment(e));else if(o&&"function"==typeof o){const e=o(this,t,n);e instanceof HTMLElement?s.appendChild(e):"string"==typeof e&&s.appendChild(document.createRange().createContextualFragment(e))}else if(r){const e=document.createElement("button");e.classList.add("pq","no-btn"),e.appendChild(new Icon(r)),i&&onEvent(e,"click",(()=>i(this,t,n))),s.appendChild(e)}})),s}renderControls(e=[],t){if(!this.rendered)return;const n=this.shadowRoot.getElementById(t);n.innerHTML="",e.forEach((({html:e,icon:t,action:s,render:r})=>{if(e)n.appendChild(document.createRange().createContextualFragment(e));else if(r&&"function"==typeof r){const e=r(this);e instanceof HTMLElement?n.appendChild(e):"string"==typeof e&&n.appendChild(document.createRange().createContextualFragment(e))}else if(t){const e=document.createElement("button");e.classList.add("pq","no-btn"),e.appendChild(new Icon(t)),s&&onEvent(e,"click",(()=>s(this))),n.appendChild(e)}}))}getCurrentPage(){return this.currentPage}getTotalPages(){return Math.ceil(this.records.length/this.pageSize)}setPage(e){e<1||e>this.getTotalPages()||(this.currentPage=e,this.renderRecords(),dispatchEvent(this,"pageChange"))}nextPage(){this.currentPage<this.getTotalPages()&&this.setPage(this.currentPage+1)}prevPage(){this.currentPage>1&&this.setPage(this.currentPage-1)}setPageSize(e){this.pageSize=e,this.currentPage=1,this.renderRecords(),dispatchEvent(this,"pageSizeChange")}setData({records:e=!1,fields:t=!1,controls:n=!1,pageSize:s=!1,pageSizeOptions:r=!1,currentPage:i=!1,enableSelection:o=!1}={}){let d=!1,c=!1;e&&(this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),d=!0),s&&(this.pageSize=s,d=!0),r&&(this.pageSizeOptions=r),n&&(this.controls=n,c=!0),i&&(this.currentPage=i,d=!0),void 0!==o&&(this.enableSelection=o,d=!0),d&&(this.renderFields(),this.renderRecords()),c&&(this.renderControls(this.controls.top,"top"),this.renderControls(this.controls.bottom,"bottom"))}setRecords(e){this.records=e,this.currentPage=1,this.renderRecords(),dispatchEvent(this,"recordsSet",{records:e})}setupFetchRecords(e,t){const n=this.records.length;n<e&&(this.records.length=e,this.records.fill(null,n)),onEvent(this,"fetchRecords",(async e=>{const{start:n,end:s}=e.detail,r=await t(n,s-n);this.records.splice(n,r.length,...r),this.renderRecords()}))}addRecord(e){this.records.push(e),this.renderRecords(),dispatchEvent(this,"recordAdded",{record:e})}updateRecord(e,t){this.records[e]=t;const n=(this.currentPage-1)*this.pageSize,s=n+this.pageSize;e>=n&&e<s&&this.renderRecords()}deleteRecord(e){e>=0&&e<this.records.length&&(this.selectedIndexes=this.selectedIndexes.filter((t=>t!==e)),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes}),this.records.splice(e,1),this.renderRecords(),dispatchEvent(this,"recordDeleted",{index:e}))}getSelectedRecords(){return this.selectedIndexes.map((e=>this.records[e]))}selectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let n=e;n<t;n++)this.selectedIndexes.includes(n)||this.selectedIndexes.push(n);this.renderRecords(),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})}deselectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);this.selectedIndexes=this.selectedIndexes.filter((n=>n<e||n>=t)),this.renderRecords(),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})}allOnPageSelected(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let n=e;n<t;n++)if(!this.selectedIndexes.includes(n))return!1;return!0}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <div id="top"></div>\n <table class="b0">\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 border: 1px solid var(--c_border);\n border-radius: var(--radius);\n }\n #top, #bottom {\n display: flex;\n }\n th {\n border-top: none;\n }\n tr:last-child td:first-child {\n border-bottom-left-radius: 0;\n }\n tr:last-child td:last-child {\n border-bottom-right-radius: 0;\n }\n tr:last-child td {\n border-bottom: none;\n }\n th:first-child, td:first-child {\n border-left: none;\n }\n th:last-child, td:last-child {\n border-right: none;\n }\n #top:not(:empty) {\n border-bottom: 1px solid var(--c_border);\n }\n #bottom:not(:empty) {\n border-top: 1px solid var(--c_border);\n }\n th.selection, td.selection {\n width: 50px;\n }\n th.selection input,\n td.selection input {\n margin: 0;\n width: 1.35rem;\n height: 1.35rem;\n }\n `}static extractFieldsFromRecords(e,t=100){const n=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>n.add(e)))})),[...n].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class DeleteSelected extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){if(await super.render()){this.updateButtonState();const e=this.shadowRoot.getElementById("deleteSelectedButton");return onEvent(e,"click",(()=>this.deleteSelected())),onEvent(this.table,"selectionChange",(()=>this.updateButtonState())),!0}return!1}deleteSelected(){const e=this.table.selectedIndexes;e.sort(((e,t)=>t-e)),e.forEach((e=>this.table.deleteRecord(e))),this.table.selectedIndexes=[],this.table.renderRecords(),this.updateButtonState()}updateButtonState(){this.shadowRoot.getElementById("deleteSelectedButton").disabled=0===this.table.selectedIndexes.length}get shadowTemplate(){return'\n <button id="deleteSelectedButton" class="pq no-btn">\n <k-icon name="delete"></k-icon>\n </button>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n button {\n display: flex;\n align-items: center;\n }\n "}}window.customElements.define("k-table-delete-selected",DeleteSelected);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class PageSelect extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){return!!await super.render()&&(this.updateOptions(),!0)}updateOptions(){const e=this.shadowRoot.getElementById("pageSelect");e.innerHTML="";for(let t=1;t<=this.table.getTotalPages();t++){const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)}e.value=this.table.getCurrentPage();this.shadowRoot.getElementById("totalPages").textContent=this.table.getTotalPages(),onEvent(e,"change",(()=>{this.table.setPage(parseInt(e.value))})),onEvent(this.table,"pageSizeChange",(()=>{this.updateOptions()})),onEvent(this.table,"pageChange",(()=>{e.value=this.table.getCurrentPage()}))}get shadowTemplate(){return'\n <select id="pageSelect" class="mxq"></select>\n <label> out of <span id="totalPages"></span></label>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n #pageSelect, label {\n display: inline;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-page-select",PageSelect);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class PageSize extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){if(await super.render()){const e=this.shadowRoot.getElementById("pageSizeSelect");return this.table.pageSizeOptions.forEach((t=>{const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)})),e.value=this.table.pageSize,onEvent(e,"change",(()=>{this.table.setPageSize(parseInt(e.value))})),onEvent(this.table,"pageSizeChange",(()=>{e.value=this.table.pageSize})),!0}return!1}get shadowTemplate(){return'\n <label for="pageSizeSelect">Page Size: </label>\n <select id="pageSizeSelect" class="mxq"></select>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-page-size",PageSize);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class SelectCount extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){return!!await super.render()&&(this.updateCount(),onEvent(this.table,"selectionChange",(()=>{this.updateCount()})),!0)}updateCount(){this.shadowRoot.getElementById("selectCount").textContent=this.table.getSelectedRecords().length}get shadowTemplate(){return'\n Selected: <span id="selectCount"></span>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n align-self: center;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-select-count",SelectCount);
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import Accordion from"./components/Accordion.js";import Card from"./components/Card.js";import Component from"./components/Component.js";import ContentSlider from"./components/ContentSlider.js";import Dialog from"./components/Dialog.js";import DirectoryViewer from"./components/DirectoryViewer.js";import FocusCapture from"./components/FocusCapture.js";import Icon from"./components/Icon.js";import Import from"./components/Import.js";import LazyComponent from"./components/LazyComponent.js";import ReactiveComponent from"./components/ReactiveComponent.js";import ReactiveLazyComponent from"./components/ReactiveLazyComponent.js";import Resize from"./components/Resize.js";import Search from"./components/Search.js";import ShowMore from"./components/ShowMore.js";import SideMenu from"./components/SideMenu.js";import Split from"./components/Split.js";import Stacks from"./components/Stacks.js";import Table from"./components/Table.js";import Tabs from"./components/Tabs.js";import Tags from"./components/Tags.js";import ThemeSwitcher from"./components/ThemeSwitcher.js";import Timestamp from"./components/Timestamp.js";import Toggle from"./components/Toggle.js";import cli from"./utils/cli.js";import cookie from"./utils/cookie.js";import debounce from"./utils/debounce.js";import drag from"./utils/drag.js";import element from"./utils/element.js";import files from"./utils/files.js";import formatTimestamp from"./utils/formatTimestamp.js";import fuzzyMatch from"./utils/fuzzyMatch.js";import getPreferredTheme from"./utils/getPreferredTheme.js";import loadCss from"./utils/loadCss.js";import loadScript from"./utils/loadScript.js";import object from"./utils/object.js";import raf from"./utils/raf.js";import string from"./utils/string.js";import toFunction from"./utils/toFunction.js";import type from"./utils/type.js";import waitFrames from"./utils/waitFrames.js";import watchDirectoryHandle from"./utils/watchDirectoryHandle.js";export default{Accordion:Accordion,Card:Card,Component:Component,ContentSlider:ContentSlider,Dialog:Dialog,DirectoryViewer:DirectoryViewer,FocusCapture:FocusCapture,Icon:Icon,Import:Import,LazyComponent:LazyComponent,ReactiveComponent:ReactiveComponent,ReactiveLazyComponent:ReactiveLazyComponent,Resize:Resize,Search:Search,ShowMore:ShowMore,SideMenu:SideMenu,Split:Split,Stacks:Stacks,Table:Table,Tabs:Tabs,Tags:Tags,ThemeSwitcher:ThemeSwitcher,Timestamp:Timestamp,Toggle:Toggle,cli:cli,cookie:cookie,debounce:debounce,drag:drag,element:element,files:files,formatTimestamp:formatTimestamp,fuzzyMatch:fuzzyMatch,getPreferredTheme:getPreferredTheme,loadCss:loadCss,loadScript:loadScript,object:object,raf:raf,string:string,toFunction:toFunction,type:type,waitFrames:waitFrames,watchDirectoryHandle:watchDirectoryHandle};
|
|
1
|
+
import Accordion from"./components/Accordion.js";import Card from"./components/Card.js";import Component from"./components/Component.js";import ContentSlider from"./components/ContentSlider.js";import Dialog from"./components/Dialog.js";import DirectoryViewer from"./components/DirectoryViewer.js";import FocusCapture from"./components/FocusCapture.js";import Icon from"./components/Icon.js";import Import from"./components/Import.js";import LazyComponent from"./components/LazyComponent.js";import ReactiveComponent from"./components/ReactiveComponent.js";import ReactiveLazyComponent from"./components/ReactiveLazyComponent.js";import Resize from"./components/Resize.js";import Search from"./components/Search.js";import ShowMore from"./components/ShowMore.js";import SideMenu from"./components/SideMenu.js";import Split from"./components/Split.js";import Stacks from"./components/Stacks.js";import Table from"./components/Table.js";import DeleteSelected from"./components/tableControlsDeleteSelected.js";import PageSelect from"./components/tableControlsPageSelect.js";import PageSize from"./components/tableControlsPageSize.js";import SelectCount from"./components/tableControlsSelectCount.js";import Tabs from"./components/Tabs.js";import Tags from"./components/Tags.js";import ThemeSwitcher from"./components/ThemeSwitcher.js";import Timestamp from"./components/Timestamp.js";import Toggle from"./components/Toggle.js";import cli from"./utils/cli.js";import cookie from"./utils/cookie.js";import debounce from"./utils/debounce.js";import drag from"./utils/drag.js";import element from"./utils/element.js";import files from"./utils/files.js";import formatTimestamp from"./utils/formatTimestamp.js";import fuzzyMatch from"./utils/fuzzyMatch.js";import getPreferredTheme from"./utils/getPreferredTheme.js";import loadCss from"./utils/loadCss.js";import loadScript from"./utils/loadScript.js";import object from"./utils/object.js";import raf from"./utils/raf.js";import string from"./utils/string.js";import toFunction from"./utils/toFunction.js";import type from"./utils/type.js";import waitFrames from"./utils/waitFrames.js";import watchDirectoryHandle from"./utils/watchDirectoryHandle.js";export default{Accordion:Accordion,Card:Card,Component:Component,ContentSlider:ContentSlider,Dialog:Dialog,DirectoryViewer:DirectoryViewer,FocusCapture:FocusCapture,Icon:Icon,Import:Import,LazyComponent:LazyComponent,ReactiveComponent:ReactiveComponent,ReactiveLazyComponent:ReactiveLazyComponent,Resize:Resize,Search:Search,ShowMore:ShowMore,SideMenu:SideMenu,Split:Split,Stacks:Stacks,Table:Table,DeleteSelected:DeleteSelected,PageSelect:PageSelect,PageSize:PageSize,SelectCount:SelectCount,Tabs:Tabs,Tags:Tags,ThemeSwitcher:ThemeSwitcher,Timestamp:Timestamp,Toggle:Toggle,cli:cli,cookie:cookie,debounce:debounce,drag:drag,element:element,files:files,formatTimestamp:formatTimestamp,fuzzyMatch:fuzzyMatch,getPreferredTheme:getPreferredTheme,loadCss:loadCss,loadScript:loadScript,object:object,raf:raf,string:string,toFunction:toFunction,type:type,waitFrames:waitFrames,watchDirectoryHandle:watchDirectoryHandle};
|
|
@@ -255,6 +255,29 @@
|
|
|
255
255
|
});
|
|
256
256
|
</script>
|
|
257
257
|
|
|
258
|
+
<h3 id="recordSelection"><a href="#recordSelection" class="no-link">Record Selection</a></h3>
|
|
259
|
+
<p>The table component supports record selection. You can enable record selection by setting the <code>enableSelection</code> property to <code>true</code>.</p>
|
|
260
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-table</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"recordSelectionExample"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-table</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Table <span class="hljs-keyword">from</span> <span class="hljs-string">'../kempo/components/Table.js'</span>;<br /><br /> <span class="hljs-keyword">const</span> $recordSelectionExample = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'recordSelectionExample'</span>);<br /> $recordSelectionExample.setData({<br /> <span class="hljs-attr">records</span>: contacts,<br /> <span class="hljs-attr">enableSelection</span>: <span class="hljs-literal">true</span>,<br /> <span class="hljs-attr">controls</span>: {<br /> <span class="hljs-attr">bottom</span>: [<br /> Table.controls.prevPage,<br /> Table.controls.nextPage,<br /> Table.controls.spacer,<br /> Table.controls.selectCount,<br /> Table.controls.deleteSelected<br /> ]<br /> },<br /> <span class="hljs-attr">pageSize</span>: <span class="hljs-number">10</span><br /> });<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
261
|
+
<k-table id="recordSelectionExample"></k-table>
|
|
262
|
+
<script type="module">
|
|
263
|
+
import Table from '../kempo/components/Table.js';
|
|
264
|
+
|
|
265
|
+
const $recordSelectionExample = document.getElementById('recordSelectionExample');
|
|
266
|
+
$recordSelectionExample.setData({
|
|
267
|
+
records: contacts,
|
|
268
|
+
enableSelection: true,
|
|
269
|
+
controls: {
|
|
270
|
+
bottom: [
|
|
271
|
+
Table.controls.prevPage,
|
|
272
|
+
Table.controls.nextPage,
|
|
273
|
+
Table.controls.spacer,
|
|
274
|
+
Table.controls.selectCount,
|
|
275
|
+
Table.controls.deleteSelected
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
pageSize: 10
|
|
279
|
+
});
|
|
280
|
+
</script>
|
|
258
281
|
|
|
259
282
|
<h2>JavaScript Reference</h2>
|
|
260
283
|
<h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
|
|
@@ -332,6 +355,22 @@
|
|
|
332
355
|
<h5><code>goToPage(<i>number</i> pageNumber)<i>: undefined</i></code></h5>
|
|
333
356
|
<p>Navigates to the specified page number.</p>
|
|
334
357
|
|
|
358
|
+
<h5><code>getSelectedRecords()<i>: Array</i></code></h5>
|
|
359
|
+
<p>Returns an array of the currently selected records.</p>
|
|
360
|
+
|
|
361
|
+
<h5><code>deleteSelectedRecords()<i>: undefined</i></code></h5>
|
|
362
|
+
<p>Deletes all currently selected records from the table.</p>
|
|
363
|
+
|
|
364
|
+
<h5><code>selectAllOnPage()<i>: undefined</i></code></h5>
|
|
365
|
+
<p>Selects all the records on the current page.</p>
|
|
366
|
+
|
|
367
|
+
<h5><code>deselectAllOnPage()<i>: undefined</i></code></h5>
|
|
368
|
+
<p>Deselects all the records on the current page.</p>
|
|
369
|
+
|
|
370
|
+
<h5><code>allOnPageSelected()<i>: undefined</i></code></h5>
|
|
371
|
+
<p>Returns <code>true</code> if all the records on the current page are selected, and <code>false</code> if they are not.</p>
|
|
372
|
+
|
|
373
|
+
|
|
335
374
|
</main>
|
|
336
375
|
<div style="height: 33.333vh"></div>
|
|
337
376
|
<script type="module" src="../kempo/components/Import.js"></script>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import Icon from"./Icon.js";import{toTitleCase}from"../utils/string.js";import{onEvent,dispatchEvent}from"../utils/element.js";export default class Table extends Component{static controls={prevPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq"),t.appendChild(new Icon("chevron-left")),onEvent(t,"click",(()=>e.prevPage())),onEvent(e,"pageChange",(()=>{t.disabled=1===e.getCurrentPage()})),t}},nextPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq"),t.appendChild(new Icon("chevron-right")),onEvent(t,"click",(()=>e.nextPage())),onEvent(e,"pageChange",(()=>{t.disabled=e.getCurrentPage()===e.getTotalPages()})),t}},pageSelect:{render:e=>new PageSelect(e)},pageSize:{render:e=>new PageSize(e)},spacer:{html:'<div class="flex"></div>'}};constructor({records:e=[],fields:t=[],controls:n={before:[],after:[],top:[],bottom:[]},pageSize:s=100,pageSizeOptions:r=[10,25,50,100,500],currentPage:
|
|
1
|
+
import Component from"./Component.js";import Icon from"./Icon.js";import SelectCount from"./tableControls/SelectCount.js";import PageSelect from"./tableControls/PageSelect.js";import PageSize from"./tableControls/PageSize.js";import DeleteSelected from"./tableControls/DeleteSelected.js";import{toTitleCase}from"../utils/string.js";import{onEvent,dispatchEvent}from"../utils/element.js";export default class Table extends Component{static controls={prevPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq","no-btn"),t.appendChild(new Icon("chevron-left")),onEvent(t,"click",(()=>e.prevPage())),onEvent(e,"pageChange",(()=>{t.disabled=1===e.getCurrentPage()})),t}},nextPage:{render:e=>{const t=document.createElement("button");return t.classList.add("pq","no-btn"),t.appendChild(new Icon("chevron-right")),onEvent(t,"click",(()=>e.nextPage())),onEvent(e,"pageChange",(()=>{t.disabled=e.getCurrentPage()===e.getTotalPages()})),t}},pageSelect:{render:e=>new PageSelect(e)},pageSize:{render:e=>new PageSize(e)},selectCount:{render:e=>new SelectCount(e)},deleteSelected:{render:e=>new DeleteSelected(e)},spacer:{html:'<div class="flex"></div>'}};constructor({records:e=[],fields:t=[],controls:n={before:[],after:[],top:[],bottom:[]},pageSize:s=100,pageSizeOptions:r=[10,25,50,100,500],currentPage:i=1,enableSelection:o=!1}={}){super(),this.registerProps({fields:t,records:e,controls:n,pageSize:s,pageSizeOptions:r,currentPage:i,enableSelection:o,selectedIndexes:[]})}async render(e){return!!await super.render(e)&&(this.setData({records:this.records,fields:this.fields,controls:this.controls,pageSize:this.pageSize,pageSizeOptions:this.pageSizeOptions,currentPage:this.currentPage}),!0)}renderFields(){if(!this.rendered)return;const e=this.controls?.before?.length?"<th></th>":"",t=this.controls?.after?.length?"<th></th>":"",n=this.enableSelection?'<th class="selection"><input type="checkbox" id="select-all"></th>':"";if(this.shadowRoot.getElementById("fields").innerHTML=`${n}${e}${this.fields.map((({label:e})=>`<th>${e}</th>`)).join("")}${t}`,this.enableSelection){const e=this.shadowRoot.getElementById("select-all");e.addEventListener("change",(()=>{e.checked?this.selectAllOnPage():this.deselectAllOnPage()})),onEvent(this,"selectionChange pageChange",(()=>{this.allOnPageSelected()?e.checked=!0:e.checked=!1}))}}renderRecords(){if(!this.rendered)return;const e=this.shadowRoot.getElementById("records");e.innerHTML="";const t=(this.currentPage-1)*this.pageSize,n=t+this.pageSize;this.records.slice(t,n).forEach(((s,r)=>{const i=document.createElement("tr");if(this.enableSelection){const e=document.createElement("td");e.classList.add("selection");const n=document.createElement("input");n.type="checkbox",n.checked=this.selectedIndexes.includes(t+r),n.addEventListener("change",(()=>{n.checked?this.selectedIndexes.push(t+r):this.selectedIndexes=this.selectedIndexes.filter((e=>e!==t+r)),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})})),e.appendChild(n),i.appendChild(e)}this.controls?.before?.length&&i.appendChild(this.renderRowControls(this.controls.before,s,t+r)),this.fields.forEach((({name:e,formatter:r,calculator:o})=>{const d=document.createElement("td");if(null===s)d.innerHTML="Loading...",dispatchEvent(this,"fetchRecords",{start:t,end:n});else{let t;o?t=o(s,this):(t=s[e]||"",Array.isArray(t)?t=r?t.map(r).join(", "):t.join(", "):r&&(t=r(t))),d.innerHTML=t}i.appendChild(d)})),this.controls?.after?.length&&i.appendChild(this.renderRowControls(this.controls.after,s,t+r)),e.appendChild(i)}))}renderRowControls(e=[],t,n){if(!this.rendered)return;const s=document.createElement("td");return e.forEach((({html:e,icon:r,action:i,render:o})=>{if(e)s.appendChild(document.createRange().createContextualFragment(e));else if(o&&"function"==typeof o){const e=o(this,t,n);e instanceof HTMLElement?s.appendChild(e):"string"==typeof e&&s.appendChild(document.createRange().createContextualFragment(e))}else if(r){const e=document.createElement("button");e.classList.add("pq","no-btn"),e.appendChild(new Icon(r)),i&&onEvent(e,"click",(()=>i(this,t,n))),s.appendChild(e)}})),s}renderControls(e=[],t){if(!this.rendered)return;const n=this.shadowRoot.getElementById(t);n.innerHTML="",e.forEach((({html:e,icon:t,action:s,render:r})=>{if(e)n.appendChild(document.createRange().createContextualFragment(e));else if(r&&"function"==typeof r){const e=r(this);e instanceof HTMLElement?n.appendChild(e):"string"==typeof e&&n.appendChild(document.createRange().createContextualFragment(e))}else if(t){const e=document.createElement("button");e.classList.add("pq","no-btn"),e.appendChild(new Icon(t)),s&&onEvent(e,"click",(()=>s(this))),n.appendChild(e)}}))}getCurrentPage(){return this.currentPage}getTotalPages(){return Math.ceil(this.records.length/this.pageSize)}setPage(e){e<1||e>this.getTotalPages()||(this.currentPage=e,this.renderRecords(),dispatchEvent(this,"pageChange"))}nextPage(){this.currentPage<this.getTotalPages()&&this.setPage(this.currentPage+1)}prevPage(){this.currentPage>1&&this.setPage(this.currentPage-1)}setPageSize(e){this.pageSize=e,this.currentPage=1,this.renderRecords(),dispatchEvent(this,"pageSizeChange")}setData({records:e=!1,fields:t=!1,controls:n=!1,pageSize:s=!1,pageSizeOptions:r=!1,currentPage:i=!1,enableSelection:o=!1}={}){let d=!1,c=!1;e&&(this.records=e,this.fields=t||Table.extractFieldsFromRecords(this.records),d=!0),s&&(this.pageSize=s,d=!0),r&&(this.pageSizeOptions=r),n&&(this.controls=n,c=!0),i&&(this.currentPage=i,d=!0),void 0!==o&&(this.enableSelection=o,d=!0),d&&(this.renderFields(),this.renderRecords()),c&&(this.renderControls(this.controls.top,"top"),this.renderControls(this.controls.bottom,"bottom"))}setRecords(e){this.records=e,this.currentPage=1,this.renderRecords(),dispatchEvent(this,"recordsSet",{records:e})}setupFetchRecords(e,t){const n=this.records.length;n<e&&(this.records.length=e,this.records.fill(null,n)),onEvent(this,"fetchRecords",(async e=>{const{start:n,end:s}=e.detail,r=await t(n,s-n);this.records.splice(n,r.length,...r),this.renderRecords()}))}addRecord(e){this.records.push(e),this.renderRecords(),dispatchEvent(this,"recordAdded",{record:e})}updateRecord(e,t){this.records[e]=t;const n=(this.currentPage-1)*this.pageSize,s=n+this.pageSize;e>=n&&e<s&&this.renderRecords()}deleteRecord(e){e>=0&&e<this.records.length&&(this.selectedIndexes=this.selectedIndexes.filter((t=>t!==e)),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes}),this.records.splice(e,1),this.renderRecords(),dispatchEvent(this,"recordDeleted",{index:e}))}getSelectedRecords(){return this.selectedIndexes.map((e=>this.records[e]))}selectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let n=e;n<t;n++)this.selectedIndexes.includes(n)||this.selectedIndexes.push(n);this.renderRecords(),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})}deselectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);this.selectedIndexes=this.selectedIndexes.filter((n=>n<e||n>=t)),this.renderRecords(),dispatchEvent(this,"selectionChange",{selectedIndexes:this.selectedIndexes})}allOnPageSelected(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let n=e;n<t;n++)if(!this.selectedIndexes.includes(n))return!1;return!0}get shadowTemplate(){return`\n ${super.shadowTemplate}\n <div class="responsive-table">\n <div id="top"></div>\n <table class="b0">\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 border: 1px solid var(--c_border);\n border-radius: var(--radius);\n }\n #top, #bottom {\n display: flex;\n }\n th {\n border-top: none;\n }\n tr:last-child td:first-child {\n border-bottom-left-radius: 0;\n }\n tr:last-child td:last-child {\n border-bottom-right-radius: 0;\n }\n tr:last-child td {\n border-bottom: none;\n }\n th:first-child, td:first-child {\n border-left: none;\n }\n th:last-child, td:last-child {\n border-right: none;\n }\n #top:not(:empty) {\n border-bottom: 1px solid var(--c_border);\n }\n #bottom:not(:empty) {\n border-top: 1px solid var(--c_border);\n }\n th.selection, td.selection {\n width: 50px;\n }\n th.selection input,\n td.selection input {\n margin: 0;\n width: 1.35rem;\n height: 1.35rem;\n }\n `}static extractFieldsFromRecords(e,t=100){const n=new Set;return e.slice(0,t).forEach((e=>{Object.keys(e).forEach((e=>n.add(e)))})),[...n].map((e=>({name:e,label:toTitleCase(e)})))}}window.customElements.define("k-table",Table);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class DeleteSelected extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){if(await super.render()){this.updateButtonState();const e=this.shadowRoot.getElementById("deleteSelectedButton");return onEvent(e,"click",(()=>this.deleteSelected())),onEvent(this.table,"selectionChange",(()=>this.updateButtonState())),!0}return!1}deleteSelected(){const e=this.table.selectedIndexes;e.sort(((e,t)=>t-e)),e.forEach((e=>this.table.deleteRecord(e))),this.table.selectedIndexes=[],this.table.renderRecords(),this.updateButtonState()}updateButtonState(){this.shadowRoot.getElementById("deleteSelectedButton").disabled=0===this.table.selectedIndexes.length}get shadowTemplate(){return'\n <button id="deleteSelectedButton" class="pq no-btn">\n <k-icon name="delete"></k-icon>\n </button>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n button {\n display: flex;\n align-items: center;\n }\n "}}window.customElements.define("k-table-delete-selected",DeleteSelected);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class PageSelect extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){return!!await super.render()&&(this.updateOptions(),!0)}updateOptions(){const e=this.shadowRoot.getElementById("pageSelect");e.innerHTML="";for(let t=1;t<=this.table.getTotalPages();t++){const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)}e.value=this.table.getCurrentPage();this.shadowRoot.getElementById("totalPages").textContent=this.table.getTotalPages(),onEvent(e,"change",(()=>{this.table.setPage(parseInt(e.value))})),onEvent(this.table,"pageSizeChange",(()=>{this.updateOptions()})),onEvent(this.table,"pageChange",(()=>{e.value=this.table.getCurrentPage()}))}get shadowTemplate(){return'\n <select id="pageSelect" class="mxq"></select>\n <label> out of <span id="totalPages"></span></label>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n #pageSelect, label {\n display: inline;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-page-select",PageSelect);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class PageSize extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){if(await super.render()){const e=this.shadowRoot.getElementById("pageSizeSelect");return this.table.pageSizeOptions.forEach((t=>{const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)})),e.value=this.table.pageSize,onEvent(e,"change",(()=>{this.table.setPageSize(parseInt(e.value))})),onEvent(this.table,"pageSizeChange",(()=>{e.value=this.table.pageSize})),!0}return!1}get shadowTemplate(){return'\n <label for="pageSizeSelect">Page Size: </label>\n <select id="pageSizeSelect" class="mxq"></select>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-page-size",PageSize);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"../Component.js";import{onEvent}from"../../utils/element.js";export default class SelectCount extends Component{constructor(e){super(),this.table=e,this.classList.add("mxq")}async render(){return!!await super.render()&&(this.updateCount(),onEvent(this.table,"selectionChange",(()=>{this.updateCount()})),!0)}updateCount(){this.shadowRoot.getElementById("selectCount").textContent=this.table.getSelectedRecords().length}get shadowTemplate(){return'\n Selected: <span id="selectCount"></span>\n '}get shadowStyles(){return"\n :host {\n display: inline-flex;\n width: max-content;\n align-items: baseline;\n align-self: center;\n }\n label {\n white-space: nowrap;\n }\n "}}window.customElements.define("k-table-select-count",SelectCount);
|
package/docs/kempo/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import Accordion from"./components/Accordion.js";import Card from"./components/Card.js";import Component from"./components/Component.js";import ContentSlider from"./components/ContentSlider.js";import Dialog from"./components/Dialog.js";import DirectoryViewer from"./components/DirectoryViewer.js";import FocusCapture from"./components/FocusCapture.js";import Icon from"./components/Icon.js";import Import from"./components/Import.js";import LazyComponent from"./components/LazyComponent.js";import ReactiveComponent from"./components/ReactiveComponent.js";import ReactiveLazyComponent from"./components/ReactiveLazyComponent.js";import Resize from"./components/Resize.js";import Search from"./components/Search.js";import ShowMore from"./components/ShowMore.js";import SideMenu from"./components/SideMenu.js";import Split from"./components/Split.js";import Stacks from"./components/Stacks.js";import Table from"./components/Table.js";import Tabs from"./components/Tabs.js";import Tags from"./components/Tags.js";import ThemeSwitcher from"./components/ThemeSwitcher.js";import Timestamp from"./components/Timestamp.js";import Toggle from"./components/Toggle.js";import cli from"./utils/cli.js";import cookie from"./utils/cookie.js";import debounce from"./utils/debounce.js";import drag from"./utils/drag.js";import element from"./utils/element.js";import files from"./utils/files.js";import formatTimestamp from"./utils/formatTimestamp.js";import fuzzyMatch from"./utils/fuzzyMatch.js";import getPreferredTheme from"./utils/getPreferredTheme.js";import loadCss from"./utils/loadCss.js";import loadScript from"./utils/loadScript.js";import object from"./utils/object.js";import raf from"./utils/raf.js";import string from"./utils/string.js";import toFunction from"./utils/toFunction.js";import type from"./utils/type.js";import waitFrames from"./utils/waitFrames.js";import watchDirectoryHandle from"./utils/watchDirectoryHandle.js";export default{Accordion:Accordion,Card:Card,Component:Component,ContentSlider:ContentSlider,Dialog:Dialog,DirectoryViewer:DirectoryViewer,FocusCapture:FocusCapture,Icon:Icon,Import:Import,LazyComponent:LazyComponent,ReactiveComponent:ReactiveComponent,ReactiveLazyComponent:ReactiveLazyComponent,Resize:Resize,Search:Search,ShowMore:ShowMore,SideMenu:SideMenu,Split:Split,Stacks:Stacks,Table:Table,Tabs:Tabs,Tags:Tags,ThemeSwitcher:ThemeSwitcher,Timestamp:Timestamp,Toggle:Toggle,cli:cli,cookie:cookie,debounce:debounce,drag:drag,element:element,files:files,formatTimestamp:formatTimestamp,fuzzyMatch:fuzzyMatch,getPreferredTheme:getPreferredTheme,loadCss:loadCss,loadScript:loadScript,object:object,raf:raf,string:string,toFunction:toFunction,type:type,waitFrames:waitFrames,watchDirectoryHandle:watchDirectoryHandle};
|
|
1
|
+
import Accordion from"./components/Accordion.js";import Card from"./components/Card.js";import Component from"./components/Component.js";import ContentSlider from"./components/ContentSlider.js";import Dialog from"./components/Dialog.js";import DirectoryViewer from"./components/DirectoryViewer.js";import FocusCapture from"./components/FocusCapture.js";import Icon from"./components/Icon.js";import Import from"./components/Import.js";import LazyComponent from"./components/LazyComponent.js";import ReactiveComponent from"./components/ReactiveComponent.js";import ReactiveLazyComponent from"./components/ReactiveLazyComponent.js";import Resize from"./components/Resize.js";import Search from"./components/Search.js";import ShowMore from"./components/ShowMore.js";import SideMenu from"./components/SideMenu.js";import Split from"./components/Split.js";import Stacks from"./components/Stacks.js";import Table from"./components/Table.js";import DeleteSelected from"./components/tableControlsDeleteSelected.js";import PageSelect from"./components/tableControlsPageSelect.js";import PageSize from"./components/tableControlsPageSize.js";import SelectCount from"./components/tableControlsSelectCount.js";import Tabs from"./components/Tabs.js";import Tags from"./components/Tags.js";import ThemeSwitcher from"./components/ThemeSwitcher.js";import Timestamp from"./components/Timestamp.js";import Toggle from"./components/Toggle.js";import cli from"./utils/cli.js";import cookie from"./utils/cookie.js";import debounce from"./utils/debounce.js";import drag from"./utils/drag.js";import element from"./utils/element.js";import files from"./utils/files.js";import formatTimestamp from"./utils/formatTimestamp.js";import fuzzyMatch from"./utils/fuzzyMatch.js";import getPreferredTheme from"./utils/getPreferredTheme.js";import loadCss from"./utils/loadCss.js";import loadScript from"./utils/loadScript.js";import object from"./utils/object.js";import raf from"./utils/raf.js";import string from"./utils/string.js";import toFunction from"./utils/toFunction.js";import type from"./utils/type.js";import waitFrames from"./utils/waitFrames.js";import watchDirectoryHandle from"./utils/watchDirectoryHandle.js";export default{Accordion:Accordion,Card:Card,Component:Component,ContentSlider:ContentSlider,Dialog:Dialog,DirectoryViewer:DirectoryViewer,FocusCapture:FocusCapture,Icon:Icon,Import:Import,LazyComponent:LazyComponent,ReactiveComponent:ReactiveComponent,ReactiveLazyComponent:ReactiveLazyComponent,Resize:Resize,Search:Search,ShowMore:ShowMore,SideMenu:SideMenu,Split:Split,Stacks:Stacks,Table:Table,DeleteSelected:DeleteSelected,PageSelect:PageSelect,PageSize:PageSize,SelectCount:SelectCount,Tabs:Tabs,Tags:Tags,ThemeSwitcher:ThemeSwitcher,Timestamp:Timestamp,Toggle:Toggle,cli:cli,cookie:cookie,debounce:debounce,drag:drag,element:element,files:files,formatTimestamp:formatTimestamp,fuzzyMatch:fuzzyMatch,getPreferredTheme:getPreferredTheme,loadCss:loadCss,loadScript:loadScript,object:object,raf:raf,string:string,toFunction:toFunction,type:type,waitFrames:waitFrames,watchDirectoryHandle:watchDirectoryHandle};
|
package/docs/table.html
ADDED
|
File without changes
|
package/package.json
CHANGED
package/scripts/build.js
CHANGED
|
@@ -8,14 +8,31 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
9
|
|
|
10
10
|
console.log('Loading utils');
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
const components = [];
|
|
13
|
+
async function buildComponents(dir) {
|
|
14
|
+
const files = await fs.readdir(dir);
|
|
15
|
+
for (const file of files) {
|
|
16
|
+
const fullPath = path.join(dir, file);
|
|
17
|
+
const stat = await fs.lstat(fullPath);
|
|
18
|
+
if (stat.isDirectory()) {
|
|
19
|
+
await buildComponents(fullPath);
|
|
20
|
+
} else if (file.endsWith('.js')) {
|
|
21
|
+
components.push(fullPath);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const componentsDir = path.join(__dirname, '..', 'src', 'components');
|
|
27
|
+
await buildComponents(componentsDir);
|
|
28
|
+
|
|
12
29
|
let complete = 0;
|
|
13
30
|
|
|
14
31
|
console.log('Loading Component Source Code');
|
|
15
32
|
process.stdout.write(`0/${components.length} = 0%`);
|
|
16
33
|
const componentCode = {};
|
|
17
|
-
await Promise.all(components.map(
|
|
18
|
-
componentCode[component] = await fs.readFile(
|
|
34
|
+
await Promise.all(components.map(async component => {
|
|
35
|
+
componentCode[component] = await fs.readFile(component, 'utf-8');
|
|
19
36
|
process.stdout.write("\r");
|
|
20
37
|
complete++;
|
|
21
38
|
process.stdout.write(`${complete}/${components.length} = ${Math.round((complete/components.length)*100)}%`);
|
|
@@ -25,9 +42,9 @@ process.stdout.write("\n");
|
|
|
25
42
|
complete = 0;
|
|
26
43
|
console.log('Minifying Component Source Code');
|
|
27
44
|
process.stdout.write(`0/${components.length} = 0%`);
|
|
28
|
-
const
|
|
29
|
-
await Promise.all(components.map(
|
|
30
|
-
|
|
45
|
+
const minifiedComponents = {};
|
|
46
|
+
await Promise.all(components.map(async componentFile => {
|
|
47
|
+
minifiedComponents[componentFile] = (await minify(componentCode[componentFile])).code;
|
|
31
48
|
process.stdout.write("\r");
|
|
32
49
|
complete++;
|
|
33
50
|
process.stdout.write(`${complete}/${components.length} = ${Math.round((complete/components.length)*100)}%`);
|
|
@@ -37,9 +54,11 @@ process.stdout.write("\n");
|
|
|
37
54
|
complete = 0;
|
|
38
55
|
console.log('Saving Minified Components to dist/');
|
|
39
56
|
process.stdout.write(`0/${components.length} = 0%`);
|
|
40
|
-
await
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
await Promise.all(components.map(async component => {
|
|
58
|
+
const relativePath = path.relative(componentsDir, component);
|
|
59
|
+
const destPath = path.join('./dist/components', relativePath);
|
|
60
|
+
await fse.ensureDir(path.dirname(destPath));
|
|
61
|
+
await fs.writeFile(destPath, minifiedComponents[component], 'utf-8');
|
|
43
62
|
process.stdout.write("\r");
|
|
44
63
|
complete++;
|
|
45
64
|
process.stdout.write(`${complete}/${components.length} = ${Math.round((complete/components.length)*100)}%`);
|
|
@@ -47,17 +66,17 @@ await Promise.all(components.map( async component => {
|
|
|
47
66
|
process.stdout.write("\n");
|
|
48
67
|
|
|
49
68
|
console.log('Loading Utils');
|
|
50
|
-
const utils = (await fs.readdir('./src/utils/')).map(f=>f.substring(0,f.length-3));
|
|
69
|
+
const utils = (await fs.readdir('./src/utils/')).map(f => f.substring(0, f.length - 3));
|
|
51
70
|
complete = 0;
|
|
52
71
|
|
|
53
72
|
console.log('Loading Utils Source Code');
|
|
54
73
|
process.stdout.write(`0/${utils.length} = 0%`);
|
|
55
74
|
const utilCode = {};
|
|
56
|
-
await Promise.all(utils.map(
|
|
75
|
+
await Promise.all(utils.map(async util => {
|
|
57
76
|
utilCode[util] = await fs.readFile(`./src/utils/${util}.js`, 'utf-8');
|
|
58
77
|
process.stdout.write("\r");
|
|
59
78
|
complete++;
|
|
60
|
-
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length)*100)}%`);
|
|
79
|
+
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length) * 100)}%`);
|
|
61
80
|
}));
|
|
62
81
|
process.stdout.write("\n");
|
|
63
82
|
|
|
@@ -65,11 +84,11 @@ complete = 0;
|
|
|
65
84
|
console.log('Minifying Utils Source Code');
|
|
66
85
|
process.stdout.write(`0/${utils.length} = 0%`);
|
|
67
86
|
const minifiedUtils = {};
|
|
68
|
-
await Promise.all(utils.map(
|
|
69
|
-
minifiedUtils[utilFile] = (await minify(utilCode[utilFile])).code
|
|
87
|
+
await Promise.all(utils.map(async utilFile => {
|
|
88
|
+
minifiedUtils[utilFile] = (await minify(utilCode[utilFile])).code;
|
|
70
89
|
process.stdout.write("\r");
|
|
71
90
|
complete++;
|
|
72
|
-
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length)*100)}%`);
|
|
91
|
+
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length) * 100)}%`);
|
|
73
92
|
}));
|
|
74
93
|
process.stdout.write("\n");
|
|
75
94
|
|
|
@@ -77,21 +96,21 @@ complete = 0;
|
|
|
77
96
|
console.log('Saving Minified Utils to dist/');
|
|
78
97
|
process.stdout.write(`0/${utils.length} = 0%`);
|
|
79
98
|
await fse.ensureDir('./dist/utils');
|
|
80
|
-
await Promise.all(utils.map(
|
|
99
|
+
await Promise.all(utils.map(async util => {
|
|
81
100
|
await fs.writeFile(`./dist/utils/${util}.js`, minifiedUtils[util], 'utf-8');
|
|
82
101
|
process.stdout.write("\r");
|
|
83
102
|
complete++;
|
|
84
|
-
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length)*100)}%`);
|
|
103
|
+
process.stdout.write(`${complete}/${utils.length} = ${Math.round((complete/utils.length) * 100)}%`);
|
|
85
104
|
}));
|
|
86
105
|
process.stdout.write("\n");
|
|
87
106
|
|
|
88
|
-
console.log('
|
|
107
|
+
console.log('Generating export file');
|
|
89
108
|
const main = `
|
|
90
|
-
${components.map(
|
|
91
|
-
${utils.map(
|
|
109
|
+
${components.map(component => `import ${path.basename(component, '.js')} from './components/${path.relative(componentsDir, component)}';`).join('')}
|
|
110
|
+
${utils.map(util => `import ${util} from './utils/${util}.js';`).join('')}
|
|
92
111
|
export default {
|
|
93
|
-
${components.map(
|
|
94
|
-
${utils.map(
|
|
112
|
+
${components.map(component => `${path.basename(component, '.js')}`).join(',')},
|
|
113
|
+
${utils.map(util => `${util}`).join(',')}
|
|
95
114
|
};
|
|
96
115
|
`;
|
|
97
116
|
const minifiedMain = (await minify(main)).code;
|
|
@@ -108,9 +127,9 @@ await fs.writeFile('./dist/kempo-vars.css', minifiedKempoVarsCSS, 'utf-8');
|
|
|
108
127
|
console.log('Loading kempo-styles.css');
|
|
109
128
|
const kempoStylesCSS = await fs.readFile('./src/kempo-styles.css', 'utf-8');
|
|
110
129
|
console.log('Minifying kempo-styles.css');
|
|
111
|
-
const
|
|
130
|
+
const minifiedKempoStylesCSS = kempoStylesCSS.replace(/\s*\{\s*/g, '{').replace(/\s*\}\s*/g, '}').replace(/\n/g, '').replace(/\r/g, '').replace(/\s+/g, ' ').replace(/\s*\:\s*/g, ':').replace(/\s*\;\s*/g, ';').replace(/;\}/g, '}');
|
|
112
131
|
console.log('Saving kempo-styles.css');
|
|
113
|
-
await fs.writeFile('./dist/kempo-styles.css',
|
|
132
|
+
await fs.writeFile('./dist/kempo-styles.css', minifiedKempoStylesCSS, 'utf-8');
|
|
114
133
|
|
|
115
134
|
console.log('Loading kempo-hljs.css');
|
|
116
135
|
const kempoHljsCSS = await fs.readFile('./src/kempo-hljs.css', 'utf-8');
|
package/src/components/Table.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import Component from './Component.js';
|
|
2
2
|
import Icon from './Icon.js';
|
|
3
|
+
import SelectCount from './tableControls/SelectCount.js';
|
|
4
|
+
import PageSelect from './tableControls/PageSelect.js';
|
|
5
|
+
import PageSize from './tableControls/PageSize.js';
|
|
6
|
+
import DeleteSelected from './tableControls/DeleteSelected.js';
|
|
3
7
|
import { toTitleCase } from '../utils/string.js';
|
|
4
8
|
import { onEvent, dispatchEvent } from '../utils/element.js';
|
|
5
9
|
|
|
@@ -8,7 +12,7 @@ export default class Table extends Component {
|
|
|
8
12
|
prevPage: {
|
|
9
13
|
render: (table) => {
|
|
10
14
|
const $button = document.createElement('button');
|
|
11
|
-
$button.classList.add('pq');
|
|
15
|
+
$button.classList.add('pq', 'no-btn');
|
|
12
16
|
$button.appendChild(new Icon('chevron-left'));
|
|
13
17
|
onEvent($button, 'click', () => table.prevPage());
|
|
14
18
|
|
|
@@ -23,7 +27,7 @@ export default class Table extends Component {
|
|
|
23
27
|
nextPage: {
|
|
24
28
|
render: (table) => {
|
|
25
29
|
const $button = document.createElement('button');
|
|
26
|
-
$button.classList.add('pq');
|
|
30
|
+
$button.classList.add('pq', 'no-btn');
|
|
27
31
|
$button.appendChild(new Icon('chevron-right'));
|
|
28
32
|
onEvent($button, 'click', () => table.nextPage());
|
|
29
33
|
|
|
@@ -41,6 +45,12 @@ export default class Table extends Component {
|
|
|
41
45
|
pageSize: {
|
|
42
46
|
render: (table) => new PageSize(table)
|
|
43
47
|
},
|
|
48
|
+
selectCount: {
|
|
49
|
+
render: (table) => new SelectCount(table)
|
|
50
|
+
},
|
|
51
|
+
deleteSelected: {
|
|
52
|
+
render: (table) => new DeleteSelected(table)
|
|
53
|
+
},
|
|
44
54
|
spacer: {
|
|
45
55
|
html: '<div class="flex"></div>'
|
|
46
56
|
}
|
|
@@ -53,6 +63,7 @@ export default class Table extends Component {
|
|
|
53
63
|
pageSize = 100,
|
|
54
64
|
pageSizeOptions = [10, 25, 50, 100, 500],
|
|
55
65
|
currentPage = 1,
|
|
66
|
+
enableSelection = false,
|
|
56
67
|
} = {}) {
|
|
57
68
|
super();
|
|
58
69
|
|
|
@@ -63,6 +74,8 @@ export default class Table extends Component {
|
|
|
63
74
|
pageSize,
|
|
64
75
|
pageSizeOptions,
|
|
65
76
|
currentPage,
|
|
77
|
+
enableSelection,
|
|
78
|
+
selectedIndexes: [], // Renamed property
|
|
66
79
|
});
|
|
67
80
|
|
|
68
81
|
/* Init */
|
|
@@ -86,7 +99,26 @@ export default class Table extends Component {
|
|
|
86
99
|
if(!this.rendered) return;
|
|
87
100
|
const beforeControls = this.controls?.before?.length ? '<th></th>' : '';
|
|
88
101
|
const afterControls = this.controls?.after?.length ? '<th></th>' : '';
|
|
89
|
-
this.
|
|
102
|
+
const selectionControl = this.enableSelection ? '<th class="selection"><input type="checkbox" id="select-all"></th>' : '';
|
|
103
|
+
this.shadowRoot.getElementById('fields').innerHTML = `${selectionControl}${beforeControls}${this.fields.map(({label})=>`<th>${label}</th>`).join('')}${afterControls}`;
|
|
104
|
+
|
|
105
|
+
if (this.enableSelection) {
|
|
106
|
+
const selectAllCheckbox = this.shadowRoot.getElementById('select-all');
|
|
107
|
+
selectAllCheckbox.addEventListener('change', () => {
|
|
108
|
+
if (selectAllCheckbox.checked) {
|
|
109
|
+
this.selectAllOnPage();
|
|
110
|
+
} else {
|
|
111
|
+
this.deselectAllOnPage();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
onEvent(this, 'selectionChange pageChange', () => {
|
|
115
|
+
if(this.allOnPageSelected()){
|
|
116
|
+
selectAllCheckbox.checked = true;
|
|
117
|
+
} else {
|
|
118
|
+
selectAllCheckbox.checked = false;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
90
122
|
}
|
|
91
123
|
renderRecords(){
|
|
92
124
|
if(!this.rendered) return;
|
|
@@ -97,6 +129,23 @@ export default class Table extends Component {
|
|
|
97
129
|
const paginatedRecords = this.records.slice(start, end);
|
|
98
130
|
paginatedRecords.forEach((record, index) => {
|
|
99
131
|
const $tr = document.createElement('tr');
|
|
132
|
+
if (this.enableSelection) {
|
|
133
|
+
const $td = document.createElement('td');
|
|
134
|
+
$td.classList.add('selection');
|
|
135
|
+
const $checkbox = document.createElement('input');
|
|
136
|
+
$checkbox.type = 'checkbox';
|
|
137
|
+
$checkbox.checked = this.selectedIndexes.includes(start + index);
|
|
138
|
+
$checkbox.addEventListener('change', () => {
|
|
139
|
+
if ($checkbox.checked) {
|
|
140
|
+
this.selectedIndexes.push(start + index);
|
|
141
|
+
} else {
|
|
142
|
+
this.selectedIndexes = this.selectedIndexes.filter(i => i !== start + index);
|
|
143
|
+
}
|
|
144
|
+
dispatchEvent(this, 'selectionChange', { selectedIndexes: this.selectedIndexes });
|
|
145
|
+
});
|
|
146
|
+
$td.appendChild($checkbox);
|
|
147
|
+
$tr.appendChild($td);
|
|
148
|
+
}
|
|
100
149
|
if(this.controls?.before?.length){
|
|
101
150
|
$tr.appendChild(this.renderRowControls(this.controls.before, record, start + index));
|
|
102
151
|
}
|
|
@@ -149,7 +198,7 @@ export default class Table extends Component {
|
|
|
149
198
|
}
|
|
150
199
|
} else if(icon){
|
|
151
200
|
const $button = document.createElement('button');
|
|
152
|
-
$button.classList.add('pq');
|
|
201
|
+
$button.classList.add('pq', 'no-btn');
|
|
153
202
|
$button.appendChild(new Icon(icon));
|
|
154
203
|
if (action) {
|
|
155
204
|
onEvent($button, 'click', () => action(this, record, index));
|
|
@@ -176,7 +225,7 @@ export default class Table extends Component {
|
|
|
176
225
|
}
|
|
177
226
|
} else if(icon){
|
|
178
227
|
const $button = document.createElement('button');
|
|
179
|
-
$button.classList.add('pq');
|
|
228
|
+
$button.classList.add('pq', 'no-btn');
|
|
180
229
|
$button.appendChild(new Icon(icon));
|
|
181
230
|
if (action) {
|
|
182
231
|
onEvent($button, 'click', () => action(this));
|
|
@@ -228,7 +277,8 @@ export default class Table extends Component {
|
|
|
228
277
|
controls = false,
|
|
229
278
|
pageSize = false,
|
|
230
279
|
pageSizeOptions = false,
|
|
231
|
-
currentPage = false
|
|
280
|
+
currentPage = false,
|
|
281
|
+
enableSelection = false // Add enableSelection property
|
|
232
282
|
} = {}) {
|
|
233
283
|
let rerender = false;
|
|
234
284
|
let rerenderControls = false;
|
|
@@ -252,6 +302,10 @@ export default class Table extends Component {
|
|
|
252
302
|
this.currentPage = currentPage;
|
|
253
303
|
rerender = true;
|
|
254
304
|
}
|
|
305
|
+
if(enableSelection !== undefined){
|
|
306
|
+
this.enableSelection = enableSelection;
|
|
307
|
+
rerender = true;
|
|
308
|
+
}
|
|
255
309
|
if(rerender){
|
|
256
310
|
this.renderFields();
|
|
257
311
|
this.renderRecords();
|
|
@@ -301,12 +355,50 @@ export default class Table extends Component {
|
|
|
301
355
|
|
|
302
356
|
deleteRecord(index) {
|
|
303
357
|
if (index >= 0 && index < this.records.length) {
|
|
358
|
+
// Deselect the record before deleting
|
|
359
|
+
this.selectedIndexes = this.selectedIndexes.filter(i => i !== index);
|
|
360
|
+
dispatchEvent(this, 'selectionChange', { selectedIndexes: this.selectedIndexes });
|
|
304
361
|
this.records.splice(index, 1);
|
|
305
362
|
this.renderRecords();
|
|
306
363
|
dispatchEvent(this, 'recordDeleted', { index });
|
|
307
364
|
}
|
|
308
365
|
}
|
|
309
366
|
|
|
367
|
+
getSelectedRecords() {
|
|
368
|
+
return this.selectedIndexes.map(index => this.records[index]);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
selectAllOnPage() {
|
|
372
|
+
const start = (this.currentPage - 1) * this.pageSize;
|
|
373
|
+
const end = Math.min(start + this.pageSize, this.records.length);
|
|
374
|
+
for (let i = start; i < end; i++) {
|
|
375
|
+
if (!this.selectedIndexes.includes(i)) {
|
|
376
|
+
this.selectedIndexes.push(i);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
this.renderRecords();
|
|
380
|
+
dispatchEvent(this, 'selectionChange', { selectedIndexes: this.selectedIndexes });
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
deselectAllOnPage() {
|
|
384
|
+
const start = (this.currentPage - 1) * this.pageSize;
|
|
385
|
+
const end = Math.min(start + this.pageSize, this.records.length);
|
|
386
|
+
this.selectedIndexes = this.selectedIndexes.filter(index => index < start || index >= end);
|
|
387
|
+
this.renderRecords();
|
|
388
|
+
dispatchEvent(this, 'selectionChange', { selectedIndexes: this.selectedIndexes });
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
allOnPageSelected() {
|
|
392
|
+
const start = (this.currentPage - 1) * this.pageSize;
|
|
393
|
+
const end = Math.min(start + this.pageSize, this.records.length);
|
|
394
|
+
for (let i = start; i < end; i++) {
|
|
395
|
+
if (!this.selectedIndexes.includes(i)) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
|
|
310
402
|
get shadowTemplate(){
|
|
311
403
|
return /*html*/`
|
|
312
404
|
${super.shadowTemplate}
|
|
@@ -356,6 +448,15 @@ export default class Table extends Component {
|
|
|
356
448
|
#bottom:not(:empty) {
|
|
357
449
|
border-top: 1px solid var(--c_border);
|
|
358
450
|
}
|
|
451
|
+
th.selection, td.selection {
|
|
452
|
+
width: 50px;
|
|
453
|
+
}
|
|
454
|
+
th.selection input,
|
|
455
|
+
td.selection input {
|
|
456
|
+
margin: 0;
|
|
457
|
+
width: 1.35rem;
|
|
458
|
+
height: 1.35rem;
|
|
459
|
+
}
|
|
359
460
|
`;
|
|
360
461
|
}
|
|
361
462
|
|
|
@@ -368,131 +469,3 @@ export default class Table extends Component {
|
|
|
368
469
|
}
|
|
369
470
|
}
|
|
370
471
|
window.customElements.define('k-table', Table);
|
|
371
|
-
|
|
372
|
-
class PageSelect extends Component {
|
|
373
|
-
constructor(table) {
|
|
374
|
-
super();
|
|
375
|
-
this.table = table;
|
|
376
|
-
this.classList.add('mxq');
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
connectedCallback() {
|
|
380
|
-
this.render();
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
async render() {
|
|
384
|
-
if(await super.render()){
|
|
385
|
-
this.updateOptions();
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
updateOptions() {
|
|
392
|
-
const $select = this.shadowRoot.getElementById('pageSelect');
|
|
393
|
-
$select.innerHTML = '';
|
|
394
|
-
for (let i = 1; i <= this.table.getTotalPages(); i++) {
|
|
395
|
-
const $option = document.createElement('option');
|
|
396
|
-
$option.value = i;
|
|
397
|
-
$option.textContent = i;
|
|
398
|
-
$select.appendChild($option);
|
|
399
|
-
}
|
|
400
|
-
$select.value = this.table.getCurrentPage();
|
|
401
|
-
const $totalPages = this.shadowRoot.getElementById('totalPages');
|
|
402
|
-
$totalPages.textContent = this.table.getTotalPages();
|
|
403
|
-
|
|
404
|
-
onEvent($select, 'change', () => {
|
|
405
|
-
this.table.setPage(parseInt($select.value));
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
onEvent(this.table, 'pageSizeChange', () => {
|
|
409
|
-
this.updateOptions();
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
onEvent(this.table, 'pageChange', () => {
|
|
413
|
-
$select.value = this.table.getCurrentPage();
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
get shadowTemplate() {
|
|
418
|
-
return /*html*/`
|
|
419
|
-
<select id="pageSelect" class="mxq"></select>
|
|
420
|
-
<label> out of <span id="totalPages"></span></label>
|
|
421
|
-
`;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
get shadowStyles() {
|
|
425
|
-
return /*css*/`
|
|
426
|
-
:host {
|
|
427
|
-
display: inline-flex;
|
|
428
|
-
width: max-content;
|
|
429
|
-
align-items: baseline;
|
|
430
|
-
}
|
|
431
|
-
#pageSelect, label {
|
|
432
|
-
display: inline;
|
|
433
|
-
}
|
|
434
|
-
label {
|
|
435
|
-
white-space: nowrap;
|
|
436
|
-
}
|
|
437
|
-
`;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
window.customElements.define('k-table-page-select', PageSelect);
|
|
441
|
-
|
|
442
|
-
class PageSize extends Component {
|
|
443
|
-
constructor(table) {
|
|
444
|
-
super();
|
|
445
|
-
this.table = table;
|
|
446
|
-
this.classList.add('mxq');
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
connectedCallback() {
|
|
450
|
-
this.render();
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
async render() {
|
|
454
|
-
if(await super.render()){
|
|
455
|
-
const $select = this.shadowRoot.getElementById('pageSizeSelect');
|
|
456
|
-
const options = this.table.pageSizeOptions;
|
|
457
|
-
options.forEach(size => {
|
|
458
|
-
const $option = document.createElement('option');
|
|
459
|
-
$option.value = size;
|
|
460
|
-
$option.textContent = size;
|
|
461
|
-
$select.appendChild($option);
|
|
462
|
-
});
|
|
463
|
-
$select.value = this.table.pageSize;
|
|
464
|
-
|
|
465
|
-
onEvent($select, 'change', () => {
|
|
466
|
-
this.table.setPageSize(parseInt($select.value));
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
onEvent(this.table, 'pageSizeChange', () => {
|
|
470
|
-
$select.value = this.table.pageSize;
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
return true;
|
|
474
|
-
}
|
|
475
|
-
return false;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
get shadowTemplate() {
|
|
479
|
-
return /*html*/`
|
|
480
|
-
<label for="pageSizeSelect">Page Size: </label>
|
|
481
|
-
<select id="pageSizeSelect" class="mxq"></select>
|
|
482
|
-
`;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
get shadowStyles() {
|
|
486
|
-
return /*css*/`
|
|
487
|
-
:host {
|
|
488
|
-
display: inline-flex;
|
|
489
|
-
width: max-content;
|
|
490
|
-
align-items: baseline;
|
|
491
|
-
}
|
|
492
|
-
label {
|
|
493
|
-
white-space: nowrap;
|
|
494
|
-
}
|
|
495
|
-
`;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
window.customElements.define('k-table-page-size', PageSize);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Component from '../Component.js';
|
|
2
|
+
import { onEvent } from '../../utils/element.js';
|
|
3
|
+
|
|
4
|
+
export default class DeleteSelected extends Component {
|
|
5
|
+
constructor(table) {
|
|
6
|
+
super();
|
|
7
|
+
this.table = table;
|
|
8
|
+
this.classList.add('mxq');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async render() {
|
|
12
|
+
if (await super.render()) {
|
|
13
|
+
this.updateButtonState();
|
|
14
|
+
const $button = this.shadowRoot.getElementById('deleteSelectedButton');
|
|
15
|
+
onEvent($button, 'click', () => this.deleteSelected());
|
|
16
|
+
onEvent(this.table, 'selectionChange', () => this.updateButtonState());
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
deleteSelected() {
|
|
23
|
+
const selectedIndexes = this.table.selectedIndexes;
|
|
24
|
+
selectedIndexes.sort((a, b) => b - a); // Sort in descending order
|
|
25
|
+
selectedIndexes.forEach(index => this.table.deleteRecord(index));
|
|
26
|
+
this.table.selectedIndexes = [];
|
|
27
|
+
this.table.renderRecords();
|
|
28
|
+
this.updateButtonState();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
updateButtonState() {
|
|
32
|
+
const $button = this.shadowRoot.getElementById('deleteSelectedButton');
|
|
33
|
+
$button.disabled = this.table.selectedIndexes.length === 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get shadowTemplate() {
|
|
37
|
+
return /*html*/`
|
|
38
|
+
<button id="deleteSelectedButton" class="pq no-btn">
|
|
39
|
+
<k-icon name="delete"></k-icon>
|
|
40
|
+
</button>
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get shadowStyles() {
|
|
45
|
+
return /*css*/`
|
|
46
|
+
:host {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
width: max-content;
|
|
49
|
+
align-items: baseline;
|
|
50
|
+
}
|
|
51
|
+
button {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
window.customElements.define('k-table-delete-selected', DeleteSelected);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Component from '../Component.js';
|
|
2
|
+
import { onEvent } from '../../utils/element.js';
|
|
3
|
+
|
|
4
|
+
export default class PageSelect extends Component {
|
|
5
|
+
constructor(table) {
|
|
6
|
+
super();
|
|
7
|
+
this.table = table;
|
|
8
|
+
this.classList.add('mxq');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async render() {
|
|
12
|
+
if(await super.render()){
|
|
13
|
+
this.updateOptions();
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
updateOptions() {
|
|
20
|
+
const $select = this.shadowRoot.getElementById('pageSelect');
|
|
21
|
+
$select.innerHTML = '';
|
|
22
|
+
for (let i = 1; i <= this.table.getTotalPages(); i++) {
|
|
23
|
+
const $option = document.createElement('option');
|
|
24
|
+
$option.value = i;
|
|
25
|
+
$option.textContent = i;
|
|
26
|
+
$select.appendChild($option);
|
|
27
|
+
}
|
|
28
|
+
$select.value = this.table.getCurrentPage();
|
|
29
|
+
const $totalPages = this.shadowRoot.getElementById('totalPages');
|
|
30
|
+
$totalPages.textContent = this.table.getTotalPages();
|
|
31
|
+
|
|
32
|
+
onEvent($select, 'change', () => {
|
|
33
|
+
this.table.setPage(parseInt($select.value));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
onEvent(this.table, 'pageSizeChange', () => {
|
|
37
|
+
this.updateOptions();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
onEvent(this.table, 'pageChange', () => {
|
|
41
|
+
$select.value = this.table.getCurrentPage();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get shadowTemplate() {
|
|
46
|
+
return /*html*/`
|
|
47
|
+
<select id="pageSelect" class="mxq"></select>
|
|
48
|
+
<label> out of <span id="totalPages"></span></label>
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get shadowStyles() {
|
|
53
|
+
return /*css*/`
|
|
54
|
+
:host {
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
width: max-content;
|
|
57
|
+
align-items: baseline;
|
|
58
|
+
}
|
|
59
|
+
#pageSelect, label {
|
|
60
|
+
display: inline;
|
|
61
|
+
}
|
|
62
|
+
label {
|
|
63
|
+
white-space: nowrap;
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
window.customElements.define('k-table-page-select', PageSelect);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import Component from '../Component.js';
|
|
2
|
+
import { onEvent } from '../../utils/element.js';
|
|
3
|
+
|
|
4
|
+
export default class PageSize extends Component {
|
|
5
|
+
constructor(table) {
|
|
6
|
+
super();
|
|
7
|
+
this.table = table;
|
|
8
|
+
this.classList.add('mxq');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async render() {
|
|
12
|
+
if(await super.render()){
|
|
13
|
+
const $select = this.shadowRoot.getElementById('pageSizeSelect');
|
|
14
|
+
const options = this.table.pageSizeOptions;
|
|
15
|
+
options.forEach(size => {
|
|
16
|
+
const $option = document.createElement('option');
|
|
17
|
+
$option.value = size;
|
|
18
|
+
$option.textContent = size;
|
|
19
|
+
$select.appendChild($option);
|
|
20
|
+
});
|
|
21
|
+
$select.value = this.table.pageSize;
|
|
22
|
+
|
|
23
|
+
onEvent($select, 'change', () => {
|
|
24
|
+
this.table.setPageSize(parseInt($select.value));
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
onEvent(this.table, 'pageSizeChange', () => {
|
|
28
|
+
$select.value = this.table.pageSize;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get shadowTemplate() {
|
|
37
|
+
return /*html*/`
|
|
38
|
+
<label for="pageSizeSelect">Page Size: </label>
|
|
39
|
+
<select id="pageSizeSelect" class="mxq"></select>
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get shadowStyles() {
|
|
44
|
+
return /*css*/`
|
|
45
|
+
:host {
|
|
46
|
+
display: inline-flex;
|
|
47
|
+
width: max-content;
|
|
48
|
+
align-items: baseline;
|
|
49
|
+
}
|
|
50
|
+
label {
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
window.customElements.define('k-table-page-size', PageSize);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Component from '../Component.js';
|
|
2
|
+
import { onEvent } from '../../utils/element.js';
|
|
3
|
+
|
|
4
|
+
export default class SelectCount extends Component {
|
|
5
|
+
constructor(table) {
|
|
6
|
+
super();
|
|
7
|
+
this.table = table;
|
|
8
|
+
this.classList.add('mxq');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async render() {
|
|
12
|
+
if (await super.render()) {
|
|
13
|
+
this.updateCount();
|
|
14
|
+
onEvent(this.table, 'selectionChange', () => {
|
|
15
|
+
this.updateCount();
|
|
16
|
+
});
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
updateCount() {
|
|
23
|
+
const $count = this.shadowRoot.getElementById('selectCount');
|
|
24
|
+
$count.textContent = this.table.getSelectedRecords().length;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get shadowTemplate() {
|
|
28
|
+
return /*html*/`
|
|
29
|
+
Selected: <span id="selectCount"></span>
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get shadowStyles() {
|
|
34
|
+
return /*css*/`
|
|
35
|
+
:host {
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
width: max-content;
|
|
38
|
+
align-items: baseline;
|
|
39
|
+
align-self: center;
|
|
40
|
+
}
|
|
41
|
+
label {
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
window.customElements.define('k-table-select-count', SelectCount);
|
package/dist/components/Stack.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import Component from"./components/Component.js";export default class Stack extends Component{constructor(){super()}}window.customElements.define("k-stack",Stack);export class StackPanel extends Component{get shadowStyles(){return"\n :host {\n display: block;\n }\n "}}window.customElements.define("k-stack-panel",StackPanel);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import Component from"./components/Component.js";export default class Stack extends Component{constructor(){super()}}window.customElements.define("k-stack",Stack);export class StackPanel extends Component{get shadowStyles(){return"\n :host {\n display: block;\n }\n "}}window.customElements.define("k-stack-panel",StackPanel);
|