From 0bae1edcebf32a55547b5b73009d227ca41105f0 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Sun, 17 May 2026 17:49:48 +0800 Subject: [PATCH] release: v1.0.1 with performance optimizations --- dist/datatable.js | 15 ++++++++++----- dist/datatable.min.js | 2 +- src/index.js | 15 ++++++++++----- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/dist/datatable.js b/dist/datatable.js index a0b59a2..e210ae5 100644 --- a/dist/datatable.js +++ b/dist/datatable.js @@ -17,7 +17,7 @@ Component.register("DataTable", (container) => { multiSelections: [], isSelecting: false }); - container.refresh = () => { + const refresh = () => { const scrollEl = container.querySelector(".dt-body"); if (!scrollEl) return; const res = vs.calc(scrollEl, state.list); @@ -28,17 +28,18 @@ Component.register("DataTable", (container) => { renderedList: res.renderedList }); }; + container.refresh = refresh; state.__watch("list", (list) => { if (list && list.length > 0 && !list[0].__watch) { - state.list = list.map((item) => item.__watch ? item : NewState(item)); + state.list = list.map((item) => NewState(item)); return; } state._listStartIndex = 0; const scrollEl = container.querySelector(".dt-body"); state.renderedList = vs.reset(list, scrollEl || { clientHeight: 800 }) || []; if (scrollEl) { - vs.init(list, container.refresh); - requestAnimationFrame(() => container.refresh()); + vs.init(list, refresh); + requestAnimationFrame(() => refresh()); } }); container.onItemUpdate = (rIdx, node) => vs.update(rIdx + state._listStartIndex, node); @@ -241,4 +242,8 @@ Component.register("DataTable", (container) => { ` )); -if (typeof document !== "undefined") RefreshState(document.documentElement); +if (typeof document !== "undefined") { + const initDataTable = () => RefreshState(document.documentElement); + if (document.readyState !== "loading") initDataTable(); + else document.addEventListener("DOMContentLoaded", initDataTable, true); +} diff --git a/dist/datatable.min.js b/dist/datatable.min.js index 5f38822..0b70780 100644 --- a/dist/datatable.min.js +++ b/dist/datatable.min.js @@ -1 +1 @@ -import{Component as t,NewState as e,Util as i,RefreshState as n}from"@web/state";import{VirtualScroll as s}from"@web/base";t.register("DataTable",t=>{const i=s(),n=t.state;Object.assign(n,{list:[],fields:[],renderedList:[],prevHeight:0,postHeight:0,_listStartIndex:0,selStartR:-1,selStartF:-1,selEndR:-1,selEndF:-1,multiSelections:[],isSelecting:!1}),t.refresh=()=>{const e=t.querySelector(".dt-body");if(!e)return;const s=i.calc(e,n.list);s&&Object.assign(n,{prevHeight:s.prevHeight,postHeight:s.postHeight,_listStartIndex:s.listStartIndex,renderedList:s.renderedList})},n.__watch("list",s=>{if(s&&s.length>0&&!s[0].__watch)return void(n.list=s.map(t=>t.__watch?t:e(t)));n._listStartIndex=0;const d=t.querySelector(".dt-body");n.renderedList=i.reset(s,d||{clientHeight:800})||[],d&&(i.init(s,t.refresh),requestAnimationFrame(()=>t.refresh()))}),t.onItemUpdate=(t,e)=>i.update(t+n._listStartIndex,e),t.getOffset=(t,e,i)=>{const n=t.slice(0,e).filter(t=>"left"===t.pinned),s=t.slice(e+1).filter(t=>"right"===t.pinned);return("left"===i?n:s).reduce((t,e)=>t+(e.width||150),0)},t.isCellSelected=(t,e)=>{const i=Math.min(n.selStartR,n.selEndR),s=Math.max(n.selStartR,n.selEndR),d=Math.min(n.selStartF,n.selEndF),r=Math.max(n.selStartF,n.selEndF);return t>=i&&t<=s&&e>=d&&e<=r||n.multiSelections.some(i=>t>=i.r1&&t<=i.r2&&e>=i.f1&&e<=i.f2)},t.clearAllActive=(t=!1)=>{n.list.forEach(t=>{null!==t._editingF&&(t._editingF=null),null!==t._activeF&&(t._activeF=null)}),t||(n.selStartR=-1,n.multiSelections=[])},t.startSelect=(e,i,s)=>{const d=t.isCellSelected(e,i);n.editingCell&&(n.editingCell=null),s.shiftKey&&-1!==n.selStartR?(n.selEndR=e,n.selEndF=i):(d||(s.ctrlKey||s.metaKey?-1!==n.selStartR&&n.multiSelections.push({r1:Math.min(n.selStartR,n.selEndR),r2:Math.max(n.selStartR,n.selEndR),f1:Math.min(n.selStartF,n.selEndF),f2:Math.max(n.selStartF,n.selEndF)}):t.clearAllActive(),n.selStartR=n.selEndR=e,n.selStartF=n.selEndF=i),n.isSelecting=!0,n.list[e]._activeF=i)},t.updateSelect=(t,e)=>n.isSelecting&&(n.selEndR=t,n.selEndF=e),t.endSelect=()=>n.isSelecting=!1,t.editCell=(e,i,s)=>{var d;const r=Math.min(n.selStartR,n.selEndR),l=Math.max(n.selStartR,n.selEndR),a=Math.min(n.selStartF,n.selEndF),o=Math.max(n.selStartF,n.selEndF),c=n.list.indexOf(e),h=-1!==n.selStartR&&c>=r&&c<=l&&s>=a&&s<=o?l-r+1:0;if(h>1&&(null==(d=globalThis.UI)?void 0:d.toast)&&UI.toast(`{#Bulk Editing {num} rows... || ${h}#}`),t.clearAllActive(!0),e._editingF=i.id,e._activeF=s,h>1){const t=e.__watch(i.id,s=>{for(let t=r;t<=l;t++)n.list[t]!==e&&(n.list[t][i.id]=s);t()})}};t.copy=async()=>{const t=Math.min(n.selStartR,n.selEndR),e=Math.max(n.selStartR,n.selEndR),i=Math.min(n.selStartF,n.selEndF),s=Math.max(n.selStartF,n.selEndF);if(-1===t)return;const d=n.list.slice(t,e+1).map(t=>n.fields.slice(i,s+1).map(e=>(t=>{const e=String(t??"");return e.includes("\t")||e.includes("\n")||e.includes('"')?'"'+e.replace(/"/g,'""')+'"':e})(t[e.id])).join("\t")).join("\n");await navigator.clipboard.writeText(d)},t.paste=async()=>{const t=(t=>{const e=[];let i=[],n="",s=!1;for(let d=0;d{const d=n.list[e+s];d&&t.forEach((t,e)=>{const s=n.fields[i+e];s&&("boolean"==typeof d[s.id]?d[s.id]="true"===t.toLowerCase():"number"==typeof d[s.id]?d[s.id]=Number(t):d[s.id]=t)})})},t.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&("c"===e.key&&(e.preventDefault(),t.copy()),"v"===e.key&&(e.preventDefault(),t.paste()))});const d=e=>!t.contains(e.target)&&t.clearAllActive();document.addEventListener("mousedown",d),window.addEventListener("mouseup",t.endSelect),t._onUnload=()=>{document.removeEventListener("mousedown",d),window.removeEventListener("mouseup",t.endSelect)}},i.makeDom("\n
\n\t
\n\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t
\n\t
this.refresh())\" style=\"overflow-anchor:none\">\n\t\t
0\" $style=\"'height:' + this.state.prevHeight + 'px;'\">
\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\t
0\" $style=\"'height:' + this.state.postHeight + 'px;'\">
\n\t
\n\t\n
\n")),"undefined"!=typeof document&&n(document.documentElement); +import{Component as t,NewState as e,Util as i,RefreshState as n}from"@web/state";import{VirtualScroll as s}from"@web/base";if(t.register("DataTable",t=>{const i=s(),n=t.state;Object.assign(n,{list:[],fields:[],renderedList:[],prevHeight:0,postHeight:0,_listStartIndex:0,selStartR:-1,selStartF:-1,selEndR:-1,selEndF:-1,multiSelections:[],isSelecting:!1});const d=()=>{const e=t.querySelector(".dt-body");if(!e)return;const s=i.calc(e,n.list);s&&Object.assign(n,{prevHeight:s.prevHeight,postHeight:s.postHeight,_listStartIndex:s.listStartIndex,renderedList:s.renderedList})};t.refresh=d,n.__watch("list",s=>{if(s&&s.length>0&&!s[0].__watch)return void(n.list=s.map(t=>e(t)));n._listStartIndex=0;const r=t.querySelector(".dt-body");n.renderedList=i.reset(s,r||{clientHeight:800})||[],r&&(i.init(s,d),requestAnimationFrame(()=>d()))}),t.onItemUpdate=(t,e)=>i.update(t+n._listStartIndex,e),t.getOffset=(t,e,i)=>{const n=t.slice(0,e).filter(t=>"left"===t.pinned),s=t.slice(e+1).filter(t=>"right"===t.pinned);return("left"===i?n:s).reduce((t,e)=>t+(e.width||150),0)},t.isCellSelected=(t,e)=>{const i=Math.min(n.selStartR,n.selEndR),s=Math.max(n.selStartR,n.selEndR),d=Math.min(n.selStartF,n.selEndF),r=Math.max(n.selStartF,n.selEndF);return t>=i&&t<=s&&e>=d&&e<=r||n.multiSelections.some(i=>t>=i.r1&&t<=i.r2&&e>=i.f1&&e<=i.f2)},t.clearAllActive=(t=!1)=>{n.list.forEach(t=>{null!==t._editingF&&(t._editingF=null),null!==t._activeF&&(t._activeF=null)}),t||(n.selStartR=-1,n.multiSelections=[])},t.startSelect=(e,i,s)=>{const d=t.isCellSelected(e,i);n.editingCell&&(n.editingCell=null),s.shiftKey&&-1!==n.selStartR?(n.selEndR=e,n.selEndF=i):(d||(s.ctrlKey||s.metaKey?-1!==n.selStartR&&n.multiSelections.push({r1:Math.min(n.selStartR,n.selEndR),r2:Math.max(n.selStartR,n.selEndR),f1:Math.min(n.selStartF,n.selEndF),f2:Math.max(n.selStartF,n.selEndF)}):t.clearAllActive(),n.selStartR=n.selEndR=e,n.selStartF=n.selEndF=i),n.isSelecting=!0,n.list[e]._activeF=i)},t.updateSelect=(t,e)=>n.isSelecting&&(n.selEndR=t,n.selEndF=e),t.endSelect=()=>n.isSelecting=!1,t.editCell=(e,i,s)=>{var d;const r=Math.min(n.selStartR,n.selEndR),l=Math.max(n.selStartR,n.selEndR),a=Math.min(n.selStartF,n.selEndF),o=Math.max(n.selStartF,n.selEndF),c=n.list.indexOf(e),h=-1!==n.selStartR&&c>=r&&c<=l&&s>=a&&s<=o?l-r+1:0;if(h>1&&(null==(d=globalThis.UI)?void 0:d.toast)&&UI.toast(`{#Bulk Editing {num} rows... || ${h}#}`),t.clearAllActive(!0),e._editingF=i.id,e._activeF=s,h>1){const t=e.__watch(i.id,s=>{for(let t=r;t<=l;t++)n.list[t]!==e&&(n.list[t][i.id]=s);t()})}};t.copy=async()=>{const t=Math.min(n.selStartR,n.selEndR),e=Math.max(n.selStartR,n.selEndR),i=Math.min(n.selStartF,n.selEndF),s=Math.max(n.selStartF,n.selEndF);if(-1===t)return;const d=n.list.slice(t,e+1).map(t=>n.fields.slice(i,s+1).map(e=>(t=>{const e=String(t??"");return e.includes("\t")||e.includes("\n")||e.includes('"')?'"'+e.replace(/"/g,'""')+'"':e})(t[e.id])).join("\t")).join("\n");await navigator.clipboard.writeText(d)},t.paste=async()=>{const t=(t=>{const e=[];let i=[],n="",s=!1;for(let d=0;d{const d=n.list[e+s];d&&t.forEach((t,e)=>{const s=n.fields[i+e];s&&("boolean"==typeof d[s.id]?d[s.id]="true"===t.toLowerCase():"number"==typeof d[s.id]?d[s.id]=Number(t):d[s.id]=t)})})},t.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&("c"===e.key&&(e.preventDefault(),t.copy()),"v"===e.key&&(e.preventDefault(),t.paste()))});const r=e=>!t.contains(e.target)&&t.clearAllActive();document.addEventListener("mousedown",r),window.addEventListener("mouseup",t.endSelect),t._onUnload=()=>{document.removeEventListener("mousedown",r),window.removeEventListener("mouseup",t.endSelect)}},i.makeDom("\n
\n\t
\n\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t
\n\t
this.refresh())\" style=\"overflow-anchor:none\">\n\t\t
0\" $style=\"'height:' + this.state.prevHeight + 'px;'\">
\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\t
0\" $style=\"'height:' + this.state.postHeight + 'px;'\">
\n\t
\n\t\n
\n")),"undefined"!=typeof document){const t=()=>n(document.documentElement);"loading"!==document.readyState?t():document.addEventListener("DOMContentLoaded",t,!0)} diff --git a/src/index.js b/src/index.js index 6fe577e..a72fbc2 100644 --- a/src/index.js +++ b/src/index.js @@ -13,7 +13,7 @@ Component.register('DataTable', container => { isSelecting: false }) - container.refresh = () => { + const refresh = () => { const scrollEl = container.querySelector('.dt-body') if (!scrollEl) return const res = vs.calc(scrollEl, state.list) @@ -22,18 +22,19 @@ Component.register('DataTable', container => { _listStartIndex: res.listStartIndex, renderedList: res.renderedList }) } + container.refresh = refresh state.__watch('list', list => { if (list && list.length > 0 && !list[0].__watch) { - state.list = list.map(item => item.__watch ? item : NewState(item)) + state.list = list.map(item => NewState(item)) return } state._listStartIndex = 0 const scrollEl = container.querySelector('.dt-body') state.renderedList = vs.reset(list, scrollEl || { clientHeight: 800 }) || [] if (scrollEl) { - vs.init(list, container.refresh) - requestAnimationFrame(() => container.refresh()) + vs.init(list, refresh) + requestAnimationFrame(() => refresh()) } }) @@ -232,4 +233,8 @@ Component.register('DataTable', container => { `)) -if (typeof document !== 'undefined') RefreshState(document.documentElement) +if (typeof document !== 'undefined') { + const initDataTable = () => RefreshState(document.documentElement) + if (document.readyState !== 'loading') initDataTable() + else document.addEventListener('DOMContentLoaded', initDataTable, true) +}