@base-framework/organisms 1.1.5 → 1.1.6

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/organisms.js CHANGED
@@ -1,2 +1,2 @@
1
- import{Div as Z}from"@base-framework/atoms";import{Atom as tt}from"@base-framework/base";var f=class{constructor(t=0,s=20){this.lastCursor=null,this.currentOffset=t,this.limit=s,this.hasMoreData=!0,this.loading=!1,this.newestId=null,this.hasNewerData=!1,this.loadingNewer=!1}canLoadMore(){return this.hasMoreData}canLoadNewer(){return this.hasNewerData&&this.newestId!==null}update(t,s=null){t<this.limit&&(this.hasMoreData=!1),this.lastCursor=s,this.currentOffset+=t}updateNewest(t){this.newestId=t,this.hasNewerData=t!==null}reset(){this.lastCursor=null,this.currentOffset=0,this.hasMoreData=!0,this.loading=!1,this.newestId=null,this.hasNewerData=!1,this.loadingNewer=!1}};var E=100;function x(e){if(!e||e.length===0)return null;let t=e[0],s=e[e.length-1];return t?.id&&s?.id?t.id>s.id?t.id:s.id:t?.id?t.id:s?.id?s.id:null}function k(e){let t=e===globalThis?globalThis.pageYOffset:e.scrollTop,s=e===globalThis?globalThis.innerHeight:e.clientHeight,i=e===globalThis?globalThis.document.documentElement.scrollHeight:e.scrollHeight;return{scrollTop:t,clientHeight:s,scrollHeight:i}}function z(e,t=E){return e.scrollTop+e.clientHeight>=e.scrollHeight-t}function G(e,t=E){return e.scrollTop<=t}var V=(e,t)=>z(e)&&t.canLoadMore(),Q=(e,t)=>G(e)&&t.canLoadMore(),S=(e,t,s,i=null)=>{e&&e.length>0?(s.append(e),t.update(e.length,i)):(t.hasMoreData=!1,s.data.set("hasItems",!1))},X=(e,t,s,i=null,r=null)=>{if(e&&e.length>0){let n=0,a=0;if(r){let l=k(r);n=l.scrollHeight,a=l.scrollTop}if(s.prepend(e),t.update(e.length,i),e.length<t.limit&&(t.hasMoreData=!1,s.addTrailingDivider&&s.addTrailingDivider()),r){let o=k(r).scrollHeight-n;r===globalThis?globalThis.scrollTo(0,a+o):r.scrollTop=a+o}}else t.hasMoreData=!1,s.data.set("hasItems",!1),s.addTrailingDivider&&s.addTrailingDivider()};var g=e=>(t,s)=>{let i=r=>{let n=[],a=null;r&&(n=r.rows||r.items||[],a=r.lastCursor||null),s(n,a)};e.xhr.all("",i,t.currentOffset,t.limit,t.lastCursor)},F=e=>(t,s)=>{let i=r=>{let n=[],a=null;r&&(n=r.rows||r.items||[],a=x(n)),s(n,a)};e.xhr.all("",i,0,t.limit,null,t.newestId)};var w=(e,t,s)=>{t.reset(),e(t,(i,r)=>{s.reset(),S(i,t,s,r);let n=x(i);n!==null&&t.updateNewest(n)})};var O=(e,t,s,i="down",r="list")=>{let n=i==="up"?Q:V,a=i==="up";return(l,o,h)=>{let c=o[r],d=k(e);if(n(d,t)){if(t.loading)return;t.loading=!0,s(t,(u,p)=>{h&&h();let Y=t.currentOffset===0;if(a){if(X(u,t,c,p,e),Y){let R=x(u);R!==null&&t.updateNewest(R)}}else S(u,t,c,p);t.loading=!1})}}},$=(e,t,s)=>(i,r,n)=>{let a=k(e);if(V(a,t)){if(t.loading)return;t.loading=!0,s(t,(l,o)=>{n&&n(),S(l,t,r,o),t.loading=!1})}};var et=(e,t,s)=>()=>{w(e,t,s)},st=(e,t,s,i)=>{s[i].refresh=et(e,t,s[i])},K=tt((e,t)=>{let s=new f(e.offset,e.limit),i=e.scrollContainer||globalThis,r=e.scrollDirection||"down",n=e.loadMoreItems||g(e.data),a=e.loadNewerItems||F(e.data),l=O(i,s,n,r,e.listCache);return Z({class:e.containerClass??"",onCreated(o,h){st(n,s,h,e.listCache),l(null,h,()=>{let d=h[e.listCache];if(d.reset(),r==="up"){let u=d.data?.items||d.data?.rows||[];if(s.newestId===null){let p=x(u);p!==null&&s.updateNewest(p)}d.scrollToBottom()}});let c=h[e.listCache];c.fetchNew=(d=!1)=>{s.loadingNewer||(s.loadingNewer=!0,a(s,(u,p)=>{u&&u.length>0&&(r==="up"?c.append(u):c.prepend(u),p!==null&&s.updateNewest(p)),s.loadingNewer=!1,d&&r==="up"&&c.scrollToBottom()}))},c.scrollToBottom=()=>{c.onFlush(()=>{if(i===globalThis){let d=globalThis.document.documentElement.scrollHeight;globalThis.scrollTo(0,d);return}i.scrollTop=i.scrollHeight})}},addEvent:["scroll",i,l,{passive:!0}]},t)}),W=K;import{Atom as ut}from"@base-framework/base";import{Div as it}from"@base-framework/atoms";import{Atom as rt}from"@base-framework/base";var nt=(e,t,s)=>()=>{w(e,t,s)},at=(e,t,s,i)=>{s[i].refresh=nt(e,t,s[i])},lt=rt((e,t)=>{let s=new f(e.offset,e.limit),i=e.loadMoreItems||g(e.data);return it({class:e.containerClass??"",onCreated(r,n){at(i,s,n,e.listCache),n[e.listCache].refresh()}},t)}),q=lt;import{Div as N,On as ot}from"@base-framework/atoms";import{Component as ht,Data as ct,Jot as dt}from"@base-framework/base";import{Builder as H,Html as U}from"@base-framework/base";var m=class{static first(t){return this.get(t,0)}static last(t){let s=t.childNodes.length-1;return this.get(t,s)}static get(t,s){return t?.childNodes[s]??null}static next(t){return t?.nextSibling??null}static previous(t){return t?.previousSibling??null}static index(t){if(!t||!t.parentNode)return-1;let s=t.parentNode.children;return Array.from(s).indexOf(t)}static getPreviousIndex(t){let s=this.index(t);return s>0?s-1:0}static replace(t,s,i){if(!s)return;U.removeElementData(s);let r=H.build(t,null,i);s.replaceWith(r)}static remove(t){t&&U.removeChild(t)}static append(t,s,i){t&&H.build(t,s,i)}static prepend(t,s,i){if(!t)return;let r=H.build(t,null,i);s.insertBefore(r,s.firstChild)}};var T=(e,t,s)=>({index:e,item:t,status:s}),I=class e{static diff(t,s,i){let r=this.arrayToMap(t,i),n=[],a=[],l=s.length;for(let o=0;o<l;o++){let h=s[o],c=h[i];if(!r.has(c)){n.push(T(o,h,"added"));continue}let{item:d}=r.get(c);if(!this.deepEqual(d,h)){n.push(T(o,h,"updated"));continue}n.push(T(o,h,"unchanged")),r.delete(c)}return r.forEach(({item:o})=>{a.push(o)}),{changes:n,deletedItems:a}}static modify(t,s,i,r=!1){let n=[],a=e.arrayToMap(s,i),l=t.length;for(let o=0;o<l;o++){let h=t[o],c=h[i]??null;if(!a.has(h[c])){if(!r)continue;n.push(T(o,h,"added"));continue}h={...a.get(h[c]).item,...h},n.push(T(o,h,"updated"))}return n}static arrayToMap(t,s){let i=new Map,r=t.length;for(let n=0;n<r;n++){let a=t[n];i.set(a[s],{item:a,index:n})}return i}static deepEqual(t,s){if(t===s)return!0;if(typeof t!="object"||t===null||typeof s!="object"||s===null)return!1;let i=Object.keys(t),r=Object.keys(s);if(i.length!==r.length)return!1;let n=i.length;for(let a=0;a<n;a++){let l=i[a];if(!s.hasOwnProperty(l)||!this.deepEqual(t[l],s[l]))return!1}return!0}};var A=class{constructor({layout:t,itemProperty:s,customCompare:i,skipFirst:r=!1}){this.layout=t,this.itemProperty=s,this.customCompare=i,this.skipFirst=r,this.lastAppend=null,this.lastPrepend=null,this.lastDividerValue=null,this.prependBoundary=null}reset(){this.lastAppend=null,this.lastPrepend=null,this.lastDividerValue=null,this.prependBoundary=null}setPrependBoundary(t){if(t){let s=this.getValue(t);this.lastPrepend=s,this.prependBoundary=s}else this.prependBoundary=null}setFirstValues(t){let s=this.lastAppend;return s||(this.lastAppend=t,this.lastPrepend=t),!s}append(t,s){this.prependBoundary=null;let i=this.getValue(t),r=this.setFirstValues(i);if(r&&!this.skipFirst){this.addDivider(i,s);return}r||(this.compare(this.lastAppend,i)&&this.addDivider(i,s),this.lastAppend=i)}getValue(t){return t[this.itemProperty]??null}prepend(t,s){let i=this.getValue(t);if(this.setFirstValues(i)){this.addDivider(i,s);return}this.compare(this.lastPrepend,i)&&this.addDivider(i,s),this.lastPrepend=i}compare(t,s){return this.customCompare?this.customCompare(t,s):t!==s}addDivider(t,s){if(!this.layout||!s||this.lastDividerValue!==null&&this.compare(this.lastDividerValue,t)===!1)return;let i=this.layout(t);i&&typeof i=="object"&&(i["data-divider"]="true"),s.push(i),this.lastDividerValue=t}};var b=e=>Array.isArray(e)?e.map(t=>t&&typeof t=="object"?{...t}:t):e,y=dt({onCreated(){this.divider&&(this.rowDivider=new A({...this.divider})),this.elementCache=new Map},setData(){let e=this.items?b(this.items):[];return new ct({items:e,hasItems:null})},before(){this.setupHasItems()},setupHasItems(){if(this.defaultHasItemValue){this.data.set("hasItems",!0);return}let e=this.linkParentData(),t=e||null;if(e!==void 0)if(e===!0)t=!0;else{let s=this.items||[];t=Array.isArray(s)&&s.length>0}this.defaultHasItemValue=t},linkParentData(){let e=!1,t=this.parent?.data??this.parent?.context?.data??null;if(t&&this.linkParent!==!1)e=t.get("hasItems"),this.data.link(t,"hasItems");else if(this.isDynamic===!0)return;return e},checkHasAddedItems(){if(this.defaultHasItemValue===!0)return;(this.data.get("items")||[]).length>0&&this.persist===!0&&(this.defaultHasItemValue=!0)},destroy(){this.checkHasAddedItems(),this.data.hasItems=this.defaultHasItemValue},render(){let e=this.row.bind(this);return N({class:"flex flex-auto flex-col"},[ot("hasItems",t=>t===!1&&this.emptyState?this.emptyState():null),N({cache:"listContainer",class:`list ${this.class||""}`,onSet:["hasItems",{hidden:!1}],for:["items",e]})])},row(e,t,s,i){if(typeof this.rowItem!="function")return null;this.rowDivider&&i&&this.isDynamic!==!0&&this.rowDivider.append(e,i);let r=this.rowItem(e,t);if(r&&this.key&&e[this.key]!==void 0){let n=String(e[this.key]);if(r instanceof ht||!r.tag)return N({"data-row-key":n},[r]);r["data-row-key"]=n}return r},delete(e){let t=this.findIndexByKey(e);if(t!==-1){if(this.data.delete(`items[${t}]`),this.listContainer){let s=m.get(this.listContainer,t);s&&m.remove(s)}this.elementCache&&this.elementCache.delete(String(e)),this.updateHasItems()}},replace(e,t=!0){if(e.status==="unchanged")return;let s=e.item;if(e.status==="added"){if(t){this.append(s);return}this.prepend(s);return}let i=s[this.key],r=this.findIndexByKey(i);if(r===-1)return;this.data.set(`items[${r}]`,s);let n=this.findRowElementByKey(i),a=this.row(s,r);n&&a&&m.replace(a,n,this)},remove(e){if(!Array.isArray(e))return;let t=e.length;for(let s=0;s<t;s++){let i=e[s];this.delete(i[this.key])}this.updateHasItems()},isEmpty(){return this.data.get("items")?.length===0},setRows(e){let t=Array.isArray(e)?e:[];this.data.set("items",t),this.updateHasItems()},getRows(){return this.data.get("items")||[]},reset(){this.data.set("items",[]),this.data.set("hasItems",null),this.hasTrailingDivider=!1,this.elementCache&&this.elementCache.clear(),this.rowDivider&&this.rowDivider.reset()},append(e){if(!e)return;Array.isArray(e)||(e=[e]),e=b(e);let t=[],s=this.data.get("items")||[],i=s.length,r=e.length;for(let a=0;a<r;a++){let l=e[a];this.rowDivider&&this.rowDivider.append(l,t);let o=this.row(l,i+a);o&&t.push(o)}let n=s.concat(e);this.data.attributes.items=n,this.data.stage.items=n,this.updateHasItems(),t.length>0&&this.listContainer&&m.append(t,this.listContainer,this)},mingle(e,t=!1){if(!Array.isArray(e))return;e=b(e);let s=this.data.get("items")||[],i=I.diff(s,e,this.key);t&&i.deletedItems.length>0&&this.remove(i.deletedItems);let r=i.changes.length;for(let n=0;n<r;n++){let a=i.changes[n];this.replace(a)}this.updateHasItems()},merge(e,t=!0,s=!1){if(!Array.isArray(e))return;e=b(e);let i=this.data.get("items")||[],r=I.diff(i,e,this.key),n=r.changes.length;for(let a=0;a<n;a++){let l=r.changes[a];s&&(this.remove([l.item]),l.status="added"),this.replace(l,t)}this.updateHasItems()},modify(e,t=!1){if(!Array.isArray(e))return;let s=b(e),i=this.data.get("items")||[],r=I.modify(s,i,this.key,t),n=r.length;for(let a=0;a<n;a++){let l=r[a];this.replace(l)}this.updateHasItems()},prepend(e){if(!e)return;if(Array.isArray(e)||(e=[e]),e=b(e),this.rowDivider){let a=this.data.get("items")||[];a.length>0&&this.rowDivider.setPrependBoundary(a[0])}if(this.listContainer){let a=this.listContainer.firstChild;a&&a.getAttribute&&a.getAttribute("data-divider")==="true"&&this.listContainer.removeChild(a)}let t=[],s=e.reverse(),i=s.length;for(let a=0;a<i;a++){let l=s[a];this.rowDivider&&this.rowDivider.prepend(l,t);let o=this.row(l,0);o&&t.push(o)}let r=this.data.get("items")||[],n=s.concat(r);this.data.attributes.items=n,this.data.stage.items=n,this.updateHasItems(),t.length>0&&this.listContainer&&m.prepend(t,this.listContainer,this)},addTrailingDivider(){if(!this.rowDivider||this.hasTrailingDivider)return;let e=this.data.get("items")||[];if(e.length===0)return;let t=e[0],s=this.rowDivider.getValue(t),i=this.rowDivider.layout(s);i&&this.listContainer&&(typeof i=="object"&&(i["data-divider"]="true"),m.prepend([i],this.listContainer,this),this.hasTrailingDivider=!0)},updateHasItems(){let e=this.data.get("items")||[],t=Array.isArray(e)&&e.length>0;this.data.set("hasItems",t)},findIndexByKey(e){return(this.data.get("items")||[]).findIndex(s=>s&&s[this.key]===e)},findRowElementByKey(e){if(!this.listContainer)return null;let t=String(e);if(this.elementCache&&this.elementCache.has(t)){let r=this.elementCache.get(t);if(r&&this.listContainer.contains(r))return r;this.elementCache.delete(t)}let s=this.listContainer.children,i=s.length;for(let r=0;r<i;r++){let n=s[r];if(!(n.hasAttribute&&n.hasAttribute("data-divider"))&&n.hasAttribute&&n.getAttribute("data-row-key")===t)return this.elementCache&&this.elementCache.set(t,n),n}return null}});var ft=ut(e=>{let t=e.cache??"list";return q({listCache:t,loadMoreItems:e.loadMoreItems,offset:e.offset,limit:e.limit,containerClass:e.containerClass??"",data:e.data},[new y({cache:t,key:e.key,items:e.items||[],divider:e.divider,role:"list",class:e.class,rowItem:e.rowItem})])});import{Atom as mt}from"@base-framework/base";var pt=mt(e=>{let t=e.cache??"list";return W({listCache:t,scrollDirection:e.scrollDirection||"down",scrollContainer:e.scrollContainer,loadMoreItems:e.loadMoreItems,offset:e.offset,limit:e.limit,containerClass:e.containerClass??"flex flex-auto flex-col",data:e.data},[new y({cache:t,key:e.key,items:e.items||[],divider:e.divider,role:"list",class:e.class,emptyState:e.emptyState||null,rowItem:e.rowItem,linkParent:e.linkParent??!1,isDynamic:!0})])});import{Component as gt,router as wt}from"@base-framework/base";var _=(e,t)=>({attr:e,value:t}),yt=(e,t)=>new RegExp("^"+e+"($|#|/|\\.).*").test(t),B=class extends gt{beforeSetup(){this.selectedClass=this.activeClass||"active"}render(){let t=this.href,s=this.text,i=this.setupWatchers(t,s);return{tag:"a",class:this.class||this.className||null,onState:["selected",{[this.selectedClass]:!0}],href:this.getString(t),text:this.getString(s),nest:this.nest||this.children,dataSet:this.dataSet,watch:i}}getLinkPath(){return this?.panel?.pathname||null}getString(t){let s=typeof t;return s!=="object"&&s!=="undefined"?t:null}setupWatchers(t,s){let i=this.exact===!0,r=wt.data,n=[];return t&&typeof t=="object"&&n.push(_("href",t)),s&&typeof s=="object"&&n.push(_("text",s)),n.push({value:["[[path]]",r],callBack:(a,l)=>{let o=l.pathname+l.hash,h=i?a===o:yt(l.pathname,a);this.update(h)}}),n}setupStates(){return{selected:!1}}update(t){this.state.selected=t}};import{Tbody as Dt}from"@base-framework/atoms";import{Tbody as xt}from"@base-framework/atoms";import{Data as Tt}from"@base-framework/base";import{Div as Ct,Td as It,Tr as bt}from"@base-framework/atoms";var j=({columnCount:e=3,customCell:t,key:s})=>{let i=r=>{if(t&&typeof t=="function")return t(r);let n=["w-3/4","w-1/2","w-full","w-2/3","w-5/6"],a=n[r%n.length];return It({class:"px-6 py-4"},[Ct({class:`${a} h-4 bg-muted animate-pulse rounded-md`})])};return bt({class:"border-b",key:s},Array.from({length:e},(r,n)=>i(n)))};var C=class extends y{setData(){let t=this.items&&this.items.length>0;return this.skeleton&&!t?new Tt({items:this.generateSkeletonRows(),hasItems:!0,showSkeleton:!0}):super.setData()}generateSkeletonRows(){let t=this.skeleton,s=5,i=null;typeof t=="object"&&(s=t.number||5,i=t.row||null);let r=this.columnCount||3;return Array.from({length:s},(n,a)=>i&&typeof i=="function"?i(a,r):j({columnCount:r,key:`skeleton-${a}`}))}removeSkeleton(){this.data.get("showSkeleton")&&(this.data.set("showSkeleton",!1),this.data.set("items",this.items||[]))}setRows(t){this.removeSkeleton(),super.setRows(t)}append(t){this.removeSkeleton(),super.append(t)}prepend(t){this.removeSkeleton(),super.prepend(t)}row(t,s,i,r){return this.data&&this.data.get("showSkeleton")?t:super.row(t,s,i,r)}render(){let t=this.row.bind(this);return xt({onCreated:s=>{this.cacheEle(s,"listContainer")},class:`tbody ${this.class||""}`,for:["items",t]})}};var L=class extends C{declareProps(){this.tracker=null,this.fetchCallback=null}setupPageTracker(){return this.tracker=new f(this.offset,this.limit)}setupFetchCallback(){this.setupPageTracker(),this.fetchCallback=this.loadMoreItems||g(this.tableData)}refresh(){w(this.fetchCallback,this.tracker,this)}render(){let t=this.row.bind(this);return this.setupFetchCallback(),Dt({class:`tbody ${this.class||""}`,onCreated:(s,i)=>{this.cacheEle(s,"listContainer"),this.refresh()},for:["items",t]})}};import{Tbody as vt}from"@base-framework/atoms";var M=class extends C{declareProps(){this.tracker=null,this.scrollContainer=null,this.fetchCallback=null}setupPageTracker(){return this.tracker=new f(this.offset,this.limit)}setupScrollHandler(t){let s=this.setupPageTracker();return this.fetchCallback=this.loadMoreItems||g(this.tableData),$(t,s,this.fetchCallback)}refresh(){w(this.fetchCallback,this.tracker,this)}render(){let t=this.row.bind(this),s=this.scrollContainer||globalThis,i=this.setupScrollHandler(s);return vt({class:`tbody ${this.class||""}`,onCreated:(r,n)=>{this.cacheEle(r,"listContainer"),i(null,n,()=>{this.reset()})},addEvent:["scroll",s,i,{passive:!0}],for:["items",t]})}};import{Span as kt}from"@base-framework/atoms";import{Component as At,SimpleData as St}from"@base-framework/base";var D=class{constructor(t,s){this.timer=null,this.callBack=s,this.duration=t||1e3}createTimer(t){this.timer=globalThis.setTimeout(t,this.duration)}start(){this.stop();let t=this.returnCallBack.bind(this);this.createTimer(t)}stop(){globalThis.clearTimeout(this.timer)}returnCallBack(){let t=this.callBack;typeof t=="function"&&t.call()}};var v=class extends D{createTimer(t){this.timer=globalThis.setInterval(t,this.duration)}stop(){globalThis.clearInterval(this.timer)}};var J=new St({date:0}),Ht=6e4,Nt=new v(Ht,()=>{J.increment("date")});Nt.start();var P=class extends At{setData(){return J}render(){return kt({class:this.class,text:this.getTime(),onSet:["date",()=>this.getTime()]})}getTime(){let t=this.dateTime;return this.filter?this.filter(t):t}};export{K as BiDirectionalContainer,ft as DataList,L as DataTableBody,P as DynamicTime,v as IntervalTimer,y as List,B as NavLink,pt as ScrollableList,M as ScrollableTableBody,C as TableBody,D as Timer};
1
+ import{Div as Z}from"@base-framework/atoms";import{Atom as tt}from"@base-framework/base";var f=class{constructor(t=0,s=20){this.lastCursor=null,this.currentOffset=t,this.limit=s,this.hasMoreData=!0,this.loading=!1,this.newestId=null,this.hasNewerData=!1,this.loadingNewer=!1}canLoadMore(){return this.hasMoreData}canLoadNewer(){return this.hasNewerData&&this.newestId!==null}update(t,s=null){t<this.limit&&(this.hasMoreData=!1),this.lastCursor=s,this.currentOffset+=t}updateNewest(t){this.newestId=t,this.hasNewerData=t!==null}reset(){this.lastCursor=null,this.currentOffset=0,this.hasMoreData=!0,this.loading=!1,this.newestId=null,this.hasNewerData=!1,this.loadingNewer=!1}};var E=100;function x(e){if(!e||e.length===0)return null;let t=e[0],s=e[e.length-1];return t?.id&&s?.id?t.id>s.id?t.id:s.id:t?.id?t.id:s?.id?s.id:null}function v(e){let t=e===globalThis?globalThis.pageYOffset:e.scrollTop,s=e===globalThis?globalThis.innerHeight:e.clientHeight,i=e===globalThis?globalThis.document.documentElement.scrollHeight:e.scrollHeight;return{scrollTop:t,clientHeight:s,scrollHeight:i}}function z(e,t=E){return e.scrollTop+e.clientHeight>=e.scrollHeight-t}function G(e,t=E){return e.scrollTop<=t}var V=(e,t)=>z(e)&&t.canLoadMore(),Q=(e,t)=>G(e)&&t.canLoadMore(),S=(e,t,s,i=null)=>{e&&e.length>0?(s.append(e),t.update(e.length,i)):(t.hasMoreData=!1,s.data.set("hasItems",!1))},X=(e,t,s,i=null,r=null)=>{if(e&&e.length>0){let n=0,a=0;if(r){let l=v(r);n=l.scrollHeight,a=l.scrollTop}if(s.prepend(e),t.update(e.length,i),e.length<t.limit&&(t.hasMoreData=!1,s.addTrailingDivider&&s.addTrailingDivider()),r){let o=v(r).scrollHeight-n;r===globalThis?globalThis.scrollTo(0,a+o):r.scrollTop=a+o}}else t.hasMoreData=!1,s.data.set("hasItems",!1),s.addTrailingDivider&&s.addTrailingDivider()};var g=e=>(t,s)=>{let i=r=>{let n=[],a=null;r&&(n=r.rows||r.items||[],a=r.lastCursor||null),s(n,a)};e.xhr.all("",i,t.currentOffset,t.limit,t.lastCursor)},F=e=>(t,s)=>{let i=r=>{let n=[],a=null;r&&(n=r.rows||r.items||[],a=x(n)),s(n,a)};e.xhr.all("",i,0,t.limit,null,t.newestId)};var w=(e,t,s)=>{t.reset(),e(t,(i,r)=>{s.reset(),S(i,t,s,r);let n=x(i);n!==null&&t.updateNewest(n)})};var O=(e,t,s,i="down",r="list")=>{let n=i==="up"?Q:V,a=i==="up";return(l,o,h)=>{let c=o[r],d=v(e);if(n(d,t)){if(t.loading)return;t.loading=!0,s(t,(u,p)=>{h&&h();let Y=t.currentOffset===0;if(a){if(X(u,t,c,p,e),Y){let P=x(u);P!==null&&t.updateNewest(P)}}else S(u,t,c,p);t.loading=!1})}}},$=(e,t,s)=>(i,r,n)=>{let a=v(e);if(V(a,t)){if(t.loading)return;t.loading=!0,s(t,(l,o)=>{n&&n(),S(l,t,r,o),t.loading=!1})}};var et=(e,t,s)=>()=>{w(e,t,s)},st=(e,t,s,i)=>{s[i].refresh=et(e,t,s[i])},K=tt((e,t)=>{let s=new f(e.offset,e.limit),i=e.scrollContainer||globalThis,r=e.scrollDirection||"down",n=e.loadMoreItems||g(e.data),a=e.loadNewerItems||F(e.data),l=O(i,s,n,r,e.listCache);return Z({class:e.containerClass??"",onCreated(o,h){st(n,s,h,e.listCache),l(null,h,()=>{let d=h[e.listCache];if(d.reset(),r==="up"){let u=d.data?.items||d.data?.rows||[];if(s.newestId===null){let p=x(u);p!==null&&s.updateNewest(p)}d.scrollToBottom()}});let c=h[e.listCache];c.fetchNew=(d=!1)=>{s.loadingNewer||(s.loadingNewer=!0,a(s,(u,p)=>{u&&u.length>0&&(r==="up"?c.append(u):c.prepend(u),p!==null&&s.updateNewest(p)),s.loadingNewer=!1,d&&r==="up"&&c.scrollToBottom()}))},c.scrollToBottom=()=>{c.onFlush(()=>{if(i===globalThis){let d=globalThis.document.documentElement.scrollHeight;globalThis.scrollTo(0,d);return}i.scrollTop=i.scrollHeight})}},addEvent:["scroll",i,l,{passive:!0}]},t)}),W=K;import{Atom as ut}from"@base-framework/base";import{Div as it}from"@base-framework/atoms";import{Atom as rt}from"@base-framework/base";var nt=(e,t,s)=>()=>{w(e,t,s)},at=(e,t,s,i)=>{s[i].refresh=nt(e,t,s[i])},lt=rt((e,t)=>{let s=new f(e.offset,e.limit),i=e.loadMoreItems||g(e.data);return it({class:e.containerClass??"",onCreated(r,n){at(i,s,n,e.listCache),n[e.listCache].refresh()}},t)}),q=lt;import{Div as N,On as ot}from"@base-framework/atoms";import{Component as ht,Data as ct,Jot as dt}from"@base-framework/base";import{Builder as H,Html as U}from"@base-framework/base";var m=class{static first(t){return this.get(t,0)}static last(t){let s=t.childNodes.length-1;return this.get(t,s)}static get(t,s){return t?.childNodes[s]??null}static next(t){return t?.nextSibling??null}static previous(t){return t?.previousSibling??null}static index(t){if(!t||!t.parentNode)return-1;let s=t.parentNode.children;return Array.from(s).indexOf(t)}static getPreviousIndex(t){let s=this.index(t);return s>0?s-1:0}static replace(t,s,i){if(!s)return;U.removeElementData(s);let r=H.build(t,null,i);s.replaceWith(r)}static remove(t){t&&U.removeChild(t)}static append(t,s,i){t&&H.build(t,s,i)}static prepend(t,s,i){if(!t)return;let r=H.build(t,null,i);s.insertBefore(r,s.firstChild)}};var D=(e,t,s)=>({index:e,item:t,status:s}),I=class e{static diff(t,s,i){let r=this.arrayToMap(t,i),n=[],a=[],l=s.length;for(let o=0;o<l;o++){let h=s[o],c=h[i];if(!r.has(c)){n.push(D(o,h,"added"));continue}let{item:d}=r.get(c);if(!this.deepEqual(d,h)){n.push(D(o,h,"updated"));continue}n.push(D(o,h,"unchanged")),r.delete(c)}return r.forEach(({item:o})=>{a.push(o)}),{changes:n,deletedItems:a}}static modify(t,s,i,r=!1){let n=[],a=e.arrayToMap(s,i),l=t.length;for(let o=0;o<l;o++){let h=t[o],c=h[i]??null;if(!a.has(h[c])){if(!r)continue;n.push(D(o,h,"added"));continue}h={...a.get(h[c]).item,...h},n.push(D(o,h,"updated"))}return n}static arrayToMap(t,s){let i=new Map,r=t.length;for(let n=0;n<r;n++){let a=t[n];i.set(a[s],{item:a,index:n})}return i}static deepEqual(t,s){if(t===s)return!0;if(typeof t!="object"||t===null||typeof s!="object"||s===null)return!1;let i=Object.keys(t),r=Object.keys(s);if(i.length!==r.length)return!1;let n=i.length;for(let a=0;a<n;a++){let l=i[a];if(!s.hasOwnProperty(l)||!this.deepEqual(t[l],s[l]))return!1}return!0}};var A=class{constructor({layout:t,itemProperty:s,customCompare:i,skipFirst:r=!1}){this.layout=t,this.itemProperty=s,this.customCompare=i,this.skipFirst=r,this.lastAppend=null,this.lastPrepend=null,this.lastDividerValue=null,this.prependBoundary=null}reset(){this.lastAppend=null,this.lastPrepend=null,this.lastDividerValue=null,this.prependBoundary=null}setPrependBoundary(t){if(t){let s=this.getValue(t);this.lastPrepend=s,this.prependBoundary=s}else this.prependBoundary=null}setFirstValues(t){let s=this.lastAppend;return s||(this.lastAppend=t,this.lastPrepend=t),!s}append(t,s){this.prependBoundary=null;let i=this.getValue(t),r=this.setFirstValues(i);if(r&&!this.skipFirst){this.addDivider(i,s);return}r||(this.compare(this.lastAppend,i)&&this.addDivider(i,s),this.lastAppend=i)}getValue(t){return t[this.itemProperty]??null}prepend(t,s){let i=this.getValue(t);if(this.setFirstValues(i)){this.addDivider(i,s);return}this.compare(this.lastPrepend,i)&&this.addDivider(i,s),this.lastPrepend=i}compare(t,s){return this.customCompare?this.customCompare(t,s):t!==s}addDivider(t,s){if(!this.layout||!s||this.lastDividerValue!==null&&this.compare(this.lastDividerValue,t)===!1)return;let i=this.layout(t);i&&typeof i=="object"&&(i["data-divider"]="true"),s.push(i),this.lastDividerValue=t}};var b=e=>Array.isArray(e)?e.map(t=>t&&typeof t=="object"?{...t}:t):e,C=dt({onCreated(){this.divider&&(this.rowDivider=new A({...this.divider})),this.elementCache=new Map},setData(){let e=this.items?b(this.items):[];return new ct({items:e,hasItems:null})},before(){this.setupHasItems()},setupHasItems(){if(this.defaultHasItemValue){this.data.set("hasItems",!0);return}let e=this.linkParentData(),t=e||null;if(e!==void 0)if(e===!0)t=!0;else{let s=this.items||[];t=Array.isArray(s)&&s.length>0}this.defaultHasItemValue=t},linkParentData(){let e=!1,t=this.parent?.data??this.parent?.context?.data??null;if(t&&this.linkParent!==!1)e=t.get("hasItems"),this.data.link(t,"hasItems");else if(this.isDynamic===!0)return;return e},checkHasAddedItems(){if(this.defaultHasItemValue===!0)return;(this.data.get("items")||[]).length>0&&this.persist===!0&&(this.defaultHasItemValue=!0)},destroy(){this.checkHasAddedItems(),this.data.hasItems=this.defaultHasItemValue},render(){let e=this.row.bind(this);return N({class:"flex flex-auto flex-col"},[ot("hasItems",t=>t===!1&&this.emptyState?this.emptyState():null),N({cache:"listContainer",class:`list ${this.class||""}`,onSet:["hasItems",{hidden:!1}],for:["items",e]})])},row(e,t,s,i){if(typeof this.rowItem!="function")return null;this.rowDivider&&i&&this.isDynamic!==!0&&this.rowDivider.append(e,i);let r=this.rowItem(e,t);if(r&&this.key&&e[this.key]!==void 0){let n=String(e[this.key]);if(r instanceof ht||!r.tag)return N({"data-row-key":n},[r]);r["data-row-key"]=n}return r},delete(e){let t=this.findIndexByKey(e);if(t!==-1){if(this.data.delete(`items[${t}]`),this.listContainer){let s=m.get(this.listContainer,t);s&&m.remove(s)}this.elementCache&&this.elementCache.delete(String(e)),this.updateHasItems()}},replace(e,t=!0){if(e.status==="unchanged")return;let s=e.item;if(e.status==="added"){if(t){this.append(s);return}this.prepend(s);return}let i=s[this.key],r=this.findIndexByKey(i);if(r===-1)return;this.data.set(`items[${r}]`,s);let n=this.findRowElementByKey(i),a=this.row(s,r);n&&a&&m.replace(a,n,this)},remove(e){if(!Array.isArray(e))return;let t=e.length;for(let s=0;s<t;s++){let i=e[s];this.delete(i[this.key])}this.updateHasItems()},isEmpty(){return this.data.get("items")?.length===0},setRows(e){let t=Array.isArray(e)?e:[];this.data.set("items",t),this.updateHasItems()},getRows(){return this.data.get("items")||[]},reset(){this.data.set("items",[]),this.data.set("hasItems",null),this.hasTrailingDivider=!1,this.elementCache&&this.elementCache.clear(),this.rowDivider&&this.rowDivider.reset()},append(e){if(!e)return;Array.isArray(e)||(e=[e]),e=b(e);let t=[],s=this.data.get("items")||[],i=s.length,r=e.length;for(let a=0;a<r;a++){let l=e[a];this.rowDivider&&this.rowDivider.append(l,t);let o=this.row(l,i+a);o&&t.push(o)}let n=s.concat(e);s.length===0?this.data.set("items",n):(this.data.attributes.items=n,this.data.stage.items=n),this.updateHasItems(),t.length>0&&this.listContainer&&m.append(t,this.listContainer,this)},mingle(e,t=!1){if(!Array.isArray(e))return;e=b(e);let s=this.data.get("items")||[],i=I.diff(s,e,this.key);t&&i.deletedItems.length>0&&this.remove(i.deletedItems);let r=i.changes.length;for(let n=0;n<r;n++){let a=i.changes[n];this.replace(a)}this.updateHasItems()},merge(e,t=!0,s=!1){if(!Array.isArray(e))return;e=b(e);let i=this.data.get("items")||[],r=I.diff(i,e,this.key),n=r.changes.length;for(let a=0;a<n;a++){let l=r.changes[a];s&&(this.remove([l.item]),l.status="added"),this.replace(l,t)}this.updateHasItems()},modify(e,t=!1){if(!Array.isArray(e))return;let s=b(e),i=this.data.get("items")||[],r=I.modify(s,i,this.key,t),n=r.length;for(let a=0;a<n;a++){let l=r[a];this.replace(l)}this.updateHasItems()},prepend(e){if(!e)return;if(Array.isArray(e)||(e=[e]),e=b(e),this.rowDivider){let a=this.data.get("items")||[];a.length>0&&this.rowDivider.setPrependBoundary(a[0])}if(this.listContainer){let a=this.listContainer.firstChild;a&&a.getAttribute&&a.getAttribute("data-divider")==="true"&&this.listContainer.removeChild(a)}let t=[],s=e.reverse(),i=s.length;for(let a=0;a<i;a++){let l=s[a];this.rowDivider&&this.rowDivider.prepend(l,t);let o=this.row(l,0);o&&t.push(o)}let r=this.data.get("items")||[],n=s.concat(r);this.data.attributes.items=n,this.data.stage.items=n,this.updateHasItems(),t.length>0&&this.listContainer&&m.prepend(t,this.listContainer,this)},addTrailingDivider(){if(!this.rowDivider||this.hasTrailingDivider)return;let e=this.data.get("items")||[];if(e.length===0)return;let t=e[0],s=this.rowDivider.getValue(t),i=[];this.rowDivider.addDivider(s,i),i.length>0&&this.listContainer&&(m.prepend(i,this.listContainer,this),this.hasTrailingDivider=!0)},updateHasItems(){let e=this.data.get("items")||[],t=Array.isArray(e)&&e.length>0;this.data.set("hasItems",t)},findIndexByKey(e){return(this.data.get("items")||[]).findIndex(s=>s&&s[this.key]===e)},findRowElementByKey(e){if(!this.listContainer)return null;let t=String(e);if(this.elementCache&&this.elementCache.has(t)){let r=this.elementCache.get(t);if(r&&this.listContainer.contains(r))return r;this.elementCache.delete(t)}let s=this.listContainer.children,i=s.length;for(let r=0;r<i;r++){let n=s[r];if(!(n.hasAttribute&&n.hasAttribute("data-divider"))&&n.hasAttribute&&n.getAttribute("data-row-key")===t)return this.elementCache&&this.elementCache.set(t,n),n}return null}});var ft=ut(e=>{let t=e.cache??"list";return q({listCache:t,loadMoreItems:e.loadMoreItems,offset:e.offset,limit:e.limit,containerClass:e.containerClass??"",data:e.data},[new C({cache:t,key:e.key,items:e.items||[],divider:e.divider,role:"list",class:e.class,rowItem:e.rowItem})])});import{Atom as mt}from"@base-framework/base";var pt=mt(e=>{let t=e.cache??"list";return W({listCache:t,scrollDirection:e.scrollDirection||"down",scrollContainer:e.scrollContainer,loadMoreItems:e.loadMoreItems,offset:e.offset,limit:e.limit,containerClass:e.containerClass??"flex flex-auto flex-col",data:e.data},[new C({cache:t,key:e.key,items:e.items||[],divider:e.divider,role:"list",class:e.class,emptyState:e.emptyState||null,rowItem:e.rowItem,linkParent:e.linkParent??!1,isDynamic:!0})])});import{Component as gt,router as wt}from"@base-framework/base";var _=(e,t)=>({attr:e,value:t}),Ct=(e,t)=>new RegExp("^"+e+"($|#|/|\\.).*").test(t),B=class extends gt{beforeSetup(){this.selectedClass=this.activeClass||"active"}render(){let t=this.href,s=this.text,i=this.setupWatchers(t,s);return{tag:"a",class:this.class||this.className||null,onState:["selected",{[this.selectedClass]:!0}],href:this.getString(t),text:this.getString(s),nest:this.nest||this.children,dataSet:this.dataSet,watch:i}}getLinkPath(){return this?.panel?.pathname||null}getString(t){let s=typeof t;return s!=="object"&&s!=="undefined"?t:null}setupWatchers(t,s){let i=this.exact===!0,r=wt.data,n=[];return t&&typeof t=="object"&&n.push(_("href",t)),s&&typeof s=="object"&&n.push(_("text",s)),n.push({value:["[[path]]",r],callBack:(a,l)=>{let o=l.pathname+l.hash,h=i?a===o:Ct(l.pathname,a);this.update(h)}}),n}setupStates(){return{selected:!1}}update(t){this.state.selected=t}};import{Tbody as Tt}from"@base-framework/atoms";import{Tbody as xt}from"@base-framework/atoms";import{Data as Dt}from"@base-framework/base";import{Div as yt,Td as It,Tr as bt}from"@base-framework/atoms";var j=({columnCount:e=3,customCell:t,key:s})=>{let i=r=>{if(t&&typeof t=="function")return t(r);let n=["w-3/4","w-1/2","w-full","w-2/3","w-5/6"],a=n[r%n.length];return It({class:"px-6 py-4"},[yt({class:`${a} h-4 bg-muted animate-pulse rounded-md`})])};return bt({class:"border-b",key:s},Array.from({length:e},(r,n)=>i(n)))};var y=class extends C{setData(){let t=this.items&&this.items.length>0;return this.skeleton&&!t?new Dt({items:this.generateSkeletonRows(),hasItems:!0,showSkeleton:!0}):super.setData()}generateSkeletonRows(){let t=this.skeleton,s=5,i=null;typeof t=="object"&&(s=t.number||5,i=t.row||null);let r=this.columnCount||3;return Array.from({length:s},(n,a)=>i&&typeof i=="function"?i(a,r):j({columnCount:r,key:`skeleton-${a}`}))}removeSkeleton(){this.data.get("showSkeleton")&&(this.data.set("showSkeleton",!1),this.data.set("items",this.items||[]))}setRows(t){this.removeSkeleton(),super.setRows(t)}append(t){this.removeSkeleton(),super.append(t)}prepend(t){this.removeSkeleton(),super.prepend(t)}row(t,s,i,r){return this.data&&this.data.get("showSkeleton")?t:super.row(t,s,i,r)}render(){let t=this.row.bind(this);return xt({onCreated:s=>{this.cacheEle(s,"listContainer")},class:`tbody ${this.class||""}`,for:["items",t]})}};var M=class extends y{declareProps(){this.tracker=null,this.fetchCallback=null}setupPageTracker(){return this.tracker=new f(this.offset,this.limit)}setupFetchCallback(){this.setupPageTracker(),this.fetchCallback=this.loadMoreItems||g(this.tableData)}refresh(){w(this.fetchCallback,this.tracker,this)}render(){let t=this.row.bind(this);return this.setupFetchCallback(),Tt({class:`tbody ${this.class||""}`,onCreated:(s,i)=>{this.cacheEle(s,"listContainer"),this.refresh()},for:["items",t]})}};import{Tbody as kt}from"@base-framework/atoms";var L=class extends y{declareProps(){this.tracker=null,this.scrollContainer=null,this.fetchCallback=null}setupPageTracker(){return this.tracker=new f(this.offset,this.limit)}setupScrollHandler(t){let s=this.setupPageTracker();return this.fetchCallback=this.loadMoreItems||g(this.tableData),$(t,s,this.fetchCallback)}refresh(){w(this.fetchCallback,this.tracker,this)}render(){let t=this.row.bind(this),s=this.scrollContainer||globalThis,i=this.setupScrollHandler(s);return kt({class:`tbody ${this.class||""}`,onCreated:(r,n)=>{this.cacheEle(r,"listContainer"),i(null,n,()=>{this.reset()})},addEvent:["scroll",s,i,{passive:!0}],for:["items",t]})}};import{Span as vt}from"@base-framework/atoms";import{Component as At,SimpleData as St}from"@base-framework/base";var T=class{constructor(t,s){this.timer=null,this.callBack=s,this.duration=t||1e3}createTimer(t){this.timer=globalThis.setTimeout(t,this.duration)}start(){this.stop();let t=this.returnCallBack.bind(this);this.createTimer(t)}stop(){globalThis.clearTimeout(this.timer)}returnCallBack(){let t=this.callBack;typeof t=="function"&&t.call()}};var k=class extends T{createTimer(t){this.timer=globalThis.setInterval(t,this.duration)}stop(){globalThis.clearInterval(this.timer)}};var J=new St({date:0}),Ht=6e4,Nt=new k(Ht,()=>{J.increment("date")});Nt.start();var R=class extends At{setData(){return J}render(){return vt({class:this.class,text:this.getTime(),onSet:["date",()=>this.getTime()]})}getTime(){let t=this.dateTime;return this.filter?this.filter(t):t}};export{K as BiDirectionalContainer,ft as DataList,M as DataTableBody,R as DynamicTime,k as IntervalTimer,C as List,B as NavLink,pt as ScrollableList,L as ScrollableTableBody,y as TableBody,T as Timer};
2
2
  //# sourceMappingURL=organisms.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/lists/bi-directional-container.js", "../src/lists/pagination-tracker.js", "../src/lists/scroll-utils.js", "../src/lists/data-list.js", "../src/lists/data-container.js", "../src/lists/list.js", "../src/utils/child-helper.js", "../src/utils/data-helper.js", "../src/lists/row-divider.js", "../src/lists/scrollable-list.js", "../src/router/nav-link.js", "../src/tables/data-table-body.js", "../src/tables/table-body.js", "../src/tables/skeleton-table-row.js", "../src/tables/scrollable-table-body.js", "../src/time/dynamic-time.js", "../src/utils/timer/timer.js", "../src/utils/timer/interval-timer.js"],
4
- "sourcesContent": ["import { Div } from \"@base-framework/atoms\";\r\nimport { Atom } from \"@base-framework/base\";\r\nimport { PaginationTracker } from \"./pagination-tracker.js\";\r\nimport { createScrollHandler, fetchAndRefresh, getNewestId, setupFetchCallback, setupFetchNewerCallback } from \"./scroll-utils.js\";\r\n\r\n/**\r\n * This will reset the tracker and fetch new data.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {Function}\r\n */\r\nconst setupResetCallback = (fetchCallback, tracker, list) =>\r\n{\r\n\treturn () =>\r\n\t{\r\n\t\tfetchAndRefresh(fetchCallback, tracker, list);\r\n\t};\r\n};\r\n\r\n/**\r\n * This will add the refresh method to the list.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} parent\r\n * @param {string} listCache\r\n */\r\nconst addRefreshMethod = (fetchCallback, tracker, parent, listCache) =>\r\n{\r\n\tparent[listCache].refresh = setupResetCallback(fetchCallback, tracker, parent[listCache]);\r\n};\r\n\r\n/**\r\n * A BiDirectionalContainer component that supports both backward (older) and forward (newer)\r\n * data fetching using cursor and since pagination. Ideal for chat/message interfaces and activity feeds.\r\n *\r\n * Supports two scroll directions:\r\n * - **\"down\"** (default): Scrolling down loads older items (appends to bottom), fetchNew() prepends newer items to top\r\n * Use for: Activity feeds, news feeds, social media timelines\r\n * - **\"up\"**: Scrolling up loads older items (prepends to top), fetchNew() appends newer items to bottom\r\n * Use for: Chat/messaging interfaces where newest messages are at bottom\r\n *\r\n * Automatic scroll position management for 'up' direction:\r\n * - Initial load automatically scrolls to bottom (shows newest messages)\r\n * - Prepending older messages preserves scroll position (prevents jarring jumps)\r\n * - Exposes scrollToBottom() method for manual control\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch older items (backward pagination using cursor).\r\n * @property {function} [props.loadNewerItems] - A function to fetch newer items (forward pagination using since).\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.containerClass] - The class to add to the container.\r\n * @property {string} [props.scrollDirection='down'] - Scroll direction: 'down' (scroll down for older) or 'up' (scroll up for older).\r\n * @property {string} [props.listCache] - The list cache name to use.\r\n * @param {Array<any>} children - The child elements to render.\r\n * @returns {object}\r\n *\r\n * @example\r\n * // Activity feed (scroll down for older, new items at top)\r\n * const ActivityFeed = (userId, onSetup) => BiDirectionalContainer({\r\n * scrollDirection: 'down', // default\r\n * loadMoreItems: async (tracker, callback) => {\r\n * const response = await fetch(`/activities?cursor=${tracker.lastCursor}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.items, data.lastCursor);\r\n * },\r\n * loadNewerItems: async (tracker, callback) => {\r\n * const response = await fetch(`/activities?since=${tracker.newestId}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.items, data.items[0]?.id);\r\n * },\r\n * limit: 20\r\n * }, [\r\n * new List({\r\n * items: [],\r\n * rowItem: (activity) => ActivityRow(activity),\r\n * onCreated: (ele, parent) => {\r\n * if (onSetup) onSetup(parent.list);\r\n * }\r\n * })\r\n * ]);\r\n *\r\n * @example\r\n * // Chat conversation (scroll up for older, new messages at bottom)\r\n * const MessageList = (conversationId, onSetup) => BiDirectionalContainer({\r\n * scrollDirection: 'up',\r\n * loadMoreItems: async (tracker, callback) => {\r\n * const response = await fetch(`/messages?cursor=${tracker.lastCursor}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.messages, data.lastCursor);\r\n * },\r\n * loadNewerItems: async (tracker, callback) => {\r\n * const response = await fetch(`/messages?since=${tracker.newestId}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.messages, data.messages[0]?.id);\r\n * },\r\n * limit: 20\r\n * }, [\r\n * new List({\r\n * items: [],\r\n * rowItem: (msg) => MessageRow(msg),\r\n * onCreated: (ele, parent) => {\r\n * if (onSetup) onSetup(parent.list);\r\n * }\r\n * })\r\n * ]);\r\n *\r\n * // In parent layout (polling controlled externally):\r\n * let messageList = null;\r\n * const list = MessageList(123, (ref) => { messageList = ref; });\r\n * setInterval(() => messageList?.fetchNew(), 3000);\r\n *\r\n * @example\r\n * // Using with data object (backward only)\r\n * BiDirectionalContainer({\r\n * data: conversationData,\r\n * limit: 20\r\n * }, [\r\n * new List({ items: [], rowItem: (msg) => MessageRow(msg) })\r\n * ]);\r\n */\r\nexport const BiDirectionalContainer = Atom((props, children) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst tracker = new PaginationTracker(props.offset, props.limit);\r\n\t// @ts-ignore\r\n\tconst container = props.scrollContainer || globalThis;\r\n\t// @ts-ignore\r\n\tconst scrollDirection = props.scrollDirection || 'down';\r\n\t// @ts-ignore\r\n\tconst fetchCallback = props.loadMoreItems || setupFetchCallback(props.data);\r\n\t// @ts-ignore\r\n\tconst fetchNewerCallback = props.loadNewerItems || setupFetchNewerCallback(props.data);\r\n\r\n\t/**\r\n\t * This will handle the scroll event for loading older items.\r\n\t * Direction determines if we scroll up or down to load older items.\r\n\t *\r\n\t * @param {object|null} e\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\t// @ts-ignore\r\n\tconst handleScroll = createScrollHandler(container, tracker, fetchCallback, scrollDirection, props.listCache);\r\n\r\n\treturn Div(\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: props.containerClass ?? '',\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated(ele, parent)\r\n\t\t\t{\r\n\t\t\t\t/**\r\n\t\t\t\t * This will add the refresh method to the list.\r\n\t\t\t\t */\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\taddRefreshMethod(fetchCallback, tracker, parent, props.listCache);\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * This will request the first fetch.\r\n\t\t\t\t */\r\n\t\t\t\thandleScroll(null, parent, () =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tconst list = parent[props.listCache];\r\n\t\t\t\t\tlist.reset();\r\n\r\n\t\t\t\t\t// For 'up' direction (chat), ensure newestId is set from the loaded items\r\n\t\t\t\t\tif (scrollDirection === 'up')\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Get the newest ID by detecting sort order\r\n\t\t\t\t\t\tconst items = list.data?.items || list.data?.rows || [];\r\n\t\t\t\t\t\tif (tracker.newestId === null)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst newestId = getNewestId(items);\r\n\t\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tlist.scrollToBottom();\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tconst list = parent[props.listCache];\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Add method to manually fetch newer items (useful for polling).\r\n\t\t\t\t * This should be called via setInterval or other timer mechanism.\r\n\t\t\t\t * The placement of new items depends on scrollDirection:\r\n\t\t\t\t * - 'down': prepends to top (for feeds)\r\n\t\t\t\t * - 'up': appends to bottom (for chat)\r\n\t\t\t\t */\r\n\t\t\t\tlist.fetchNew = (shouldScroll = false) =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// Allow fetching if we're not already loading\r\n\t\t\t\t\t// Don't require hasNewerData to be true (it starts as false)\r\n\t\t\t\t\tif (!tracker.loadingNewer)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttracker.loadingNewer = true;\r\n\t\t\t\t\t\tfetchNewerCallback(tracker, (rows, newestId) =>\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (rows && rows.length > 0)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Direction determines where to add new items\r\n\t\t\t\t\t\t\t\tif (scrollDirection === 'up')\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Chat: new messages at bottom\r\n\t\t\t\t\t\t\t\t\t// Use append instead of updateRows to avoid affecting pagination tracker\r\n\t\t\t\t\t\t\t\t\tlist.append(rows);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Feed: new items at top\r\n\t\t\t\t\t\t\t\t\t// Use prepend instead of prependRows to avoid affecting pagination tracker\r\n\t\t\t\t\t\t\t\t\tlist.prepend(rows);\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t// Update newest ID tracker if available\r\n\t\t\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\ttracker.loadingNewer = false;\r\n\r\n\t\t\t\t\t\t\tif (shouldScroll && scrollDirection === 'up')\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlist.scrollToBottom();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Add method to scroll to bottom (useful for chat interfaces).\r\n\t\t\t\t * This can be called after fetching new messages to keep user at bottom.\r\n\t\t\t\t * Uses onFlush to wait for batched UI updates.\r\n\t\t\t\t */\r\n\t\t\t\tlist.scrollToBottom = () =>\r\n\t\t\t\t{\r\n\t\t\t\t\tlist.onFlush(() =>\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (container === globalThis)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst scrollHeight = globalThis.document.documentElement.scrollHeight;\r\n\t\t\t\t\t\t\tglobalThis.scrollTo(0, scrollHeight);\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\t\tcontainer.scrollTop = container.scrollHeight;\r\n\t\t\t\t\t});\r\n\t\t\t\t};\r\n\t\t\t},\r\n\r\n\t\t\t/**\r\n\t\t\t * This will add the scroll event to the container for loading older items.\r\n\t\t\t */\r\n\t\t\taddEvent: ['scroll', container, handleScroll, { passive: true }],\r\n\t\t},\r\n\t\tchildren\r\n\t);\r\n});\r\n\r\nexport default BiDirectionalContainer;\r\n", "/**\r\n * PaginationTracker stores and updates pagination state.\r\n * Supports bi-directional cursor pagination for both backward (older)\r\n * and forward (newer) data fetching.\r\n *\r\n * @class\r\n */\r\nexport class PaginationTracker\r\n{\r\n\t/**\r\n\t * Creates an instance of PaginationTracker.\r\n\t *\r\n\t * @param {number} [offset=0] - The initial offset.\r\n\t * @param {number} [limit=20] - The number of items to load per batch.\r\n\t */\r\n\tconstructor(offset = 0, limit = 20)\r\n\t{\r\n\t\t// Backward pagination (older/historical data)\r\n\t\tthis.lastCursor = null;\r\n\t\tthis.currentOffset = offset;\r\n\t\tthis.limit = limit;\r\n\t\tthis.hasMoreData = true;\r\n\t\tthis.loading = false;\r\n\r\n\t\t// Forward pagination (newer data)\r\n\t\tthis.newestId = null;\r\n\t\tthis.hasNewerData = false;\r\n\t\tthis.loadingNewer = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether more data can be loaded (backward/older).\r\n\t *\r\n\t * @returns {boolean}\r\n\t */\r\n\tcanLoadMore()\r\n\t{\r\n\t\treturn this.hasMoreData;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether newer data can be loaded (forward).\r\n\t *\r\n\t * @returns {boolean}\r\n\t */\r\n\tcanLoadNewer()\r\n\t{\r\n\t\treturn this.hasNewerData && this.newestId !== null;\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the tracker state based on the number of items loaded (backward).\r\n\t *\r\n\t * @param {number} numItems - The number of items loaded.\r\n\t * @param {string|null} lastCursor - The last cursor value.\r\n\t * @returns {void}\r\n\t */\r\n\tupdate(numItems, lastCursor = null)\r\n\t{\r\n\t\tif (numItems < this.limit)\r\n\t\t{\r\n\t\t\tthis.hasMoreData = false;\r\n\t\t}\r\n\r\n\t\tthis.lastCursor = lastCursor;\r\n\t\tthis.currentOffset += numItems;\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the newest ID for forward pagination.\r\n\t *\r\n\t * @param {string|number|null} newestId - The ID of the newest item.\r\n\t * @returns {void}\r\n\t */\r\n\tupdateNewest(newestId)\r\n\t{\r\n\t\tthis.newestId = newestId;\r\n\t\tthis.hasNewerData = newestId !== null;\r\n\t}\r\n\r\n\t/**\r\n\t * Resets the tracker state.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\tthis.lastCursor = null;\r\n\t\tthis.currentOffset = 0;\r\n\t\tthis.hasMoreData = true;\r\n\t\tthis.loading = false;\r\n\t\tthis.newestId = null;\r\n\t\tthis.hasNewerData = false;\r\n\t\tthis.loadingNewer = false;\r\n\t}\r\n}\r\n\r\nexport default PaginationTracker;", "import { PaginationTracker } from \"./pagination-tracker.js\";\r\n\r\n// Module-level constant for scroll threshold (in pixels)\r\nconst SCROLL_THRESHOLD = 100;\r\n\r\n/**\r\n * Extract the newest ID from an array of rows by detecting sort order.\r\n * Compares first and last item IDs to determine if data is in ASC or DESC order.\r\n *\r\n * @param {Array} rows - The array of row objects\r\n * @returns {number|string|null} The highest ID, or null if no valid ID found\r\n */\r\nexport function getNewestId(rows)\r\n{\r\n\tif (!rows || rows.length === 0)\r\n\t{\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst firstItem = rows[0];\r\n\tconst lastItem = rows[rows.length - 1];\r\n\r\n\t// Both items have IDs - compare to detect sort order\r\n\tif (firstItem?.id && lastItem?.id)\r\n\t{\r\n\t\t// If first ID > last ID, it's DESC order (newest first)\r\n\t\t// If first ID < last ID, it's ASC order (oldest first)\r\n\t\treturn firstItem.id > lastItem.id ? firstItem.id : lastItem.id;\r\n\t}\r\n\r\n\t// Only one item has an ID - return whichever exists\r\n\tif (firstItem?.id)\r\n\t{\r\n\t\treturn firstItem.id;\r\n\t}\r\n\r\n\tif (lastItem?.id)\r\n\t{\r\n\t\treturn lastItem.id;\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Get scroll metrics for a container.\r\n *\r\n * @param {HTMLElement|globalThis} container\r\n * @returns {object} Contains scrollTop, clientHeight, and scrollHeight.\r\n */\r\nexport function getScrollMetrics(container)\r\n{\r\n\t// @ts-ignore\r\n\tconst scrollTop = container === globalThis ? globalThis.pageYOffset : container.scrollTop;\r\n\t// @ts-ignore\r\n\tconst clientHeight = container === globalThis ? globalThis.innerHeight : container.clientHeight;\r\n\t// @ts-ignore\r\n\tconst scrollHeight = container === globalThis ? globalThis.document.documentElement.scrollHeight : container.scrollHeight;\r\n\treturn { scrollTop, clientHeight, scrollHeight };\r\n}\r\n\r\n/**\r\n * Check if the scroll position indicates we should load more items at the bottom.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {number} [threshold=SCROLL_THRESHOLD] - The threshold in pixels.\r\n * @returns {boolean}\r\n */\r\nexport function shouldLoadMore(metrics, threshold = SCROLL_THRESHOLD)\r\n{\r\n\treturn metrics.scrollTop + metrics.clientHeight >= metrics.scrollHeight - threshold;\r\n}\r\n\r\n/**\r\n * Check if the scroll position indicates we should load more items at the top.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {number} [threshold=SCROLL_THRESHOLD] - The threshold in pixels.\r\n * @returns {boolean}\r\n */\r\nexport function shouldLoadAtTop(metrics, threshold = SCROLL_THRESHOLD)\r\n{\r\n\treturn metrics.scrollTop <= threshold;\r\n}\r\n\r\n/**\r\n * Check if more items can be loaded at the bottom based on metrics and tracker state.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @returns {boolean}\r\n */\r\nexport const canLoad = (metrics, tracker) =>\r\n{\r\n\treturn shouldLoadMore(metrics) && tracker.canLoadMore();\r\n};\r\n\r\n/**\r\n * Check if more items can be loaded at the top based on metrics and tracker state.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @returns {boolean}\r\n */\r\nexport const canLoadAtTop = (metrics, tracker) =>\r\n{\r\n\treturn shouldLoadAtTop(metrics) && tracker.canLoadMore();\r\n};\r\n\r\n/**\r\n * Update the rows in the list by appending and update the tracker state.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|null} lastCursor - The last cursor value.\r\n * @returns {void}\r\n */\r\nexport const updateRows = (rows, tracker, list, lastCursor = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\tlist.append(rows);\r\n\t\ttracker.update(rows.length, lastCursor);\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttracker.hasMoreData = false;\r\n\t\tlist.data.set('hasItems', false);\r\n\t}\r\n};\r\n\r\n/**\r\n * Update the rows in the list by prepending older items and update the tracker state.\r\n * Used when scrolling up to load older items.\r\n * Preserves scroll position to prevent content jumping.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|null} lastCursor - The last cursor value.\r\n * @param {HTMLElement|globalThis|null} [container] - The scroll container.\r\n * @returns {void}\r\n */\r\nexport const updateRowsAtTop = (rows, tracker, list, lastCursor = null, container = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\t// Save scroll position before prepending\r\n\t\tlet scrollHeight = 0;\r\n\t\tlet scrollTop = 0;\r\n\r\n\t\tif (container)\r\n\t\t{\r\n\t\t\tconst metrics = getScrollMetrics(container);\r\n\t\t\tscrollHeight = metrics.scrollHeight;\r\n\t\t\tscrollTop = metrics.scrollTop;\r\n\t\t}\r\n\r\n\t\t// Prepend the rows\r\n\t\tlist.prepend(rows);\r\n\t\ttracker.update(rows.length, lastCursor);\r\n\r\n\t\t// Check if we received fewer rows than the limit, indicating no more data\r\n\t\tif (rows.length < tracker.limit)\r\n\t\t{\r\n\t\t\ttracker.hasMoreData = false;\r\n\r\n\t\t\t// Add a trailing divider to show the date of the oldest items\r\n\t\t\tif (list.addTrailingDivider)\r\n\t\t\t{\r\n\t\t\t\tlist.addTrailingDivider();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Restore scroll position to prevent jump\r\n\t\tif (container)\r\n\t\t{\r\n\t\t\t// Calculate the difference in height after prepending\r\n\t\t\tconst newMetrics = getScrollMetrics(container);\r\n\t\t\tconst heightDifference = newMetrics.scrollHeight - scrollHeight;\r\n\r\n\t\t\t// Adjust scroll position by the height difference\r\n\t\t\tif (container === globalThis)\r\n\t\t\t{\r\n\t\t\t\tglobalThis.scrollTo(0, scrollTop + heightDifference);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tcontainer.scrollTop = scrollTop + heightDifference;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttracker.hasMoreData = false;\r\n\t\tlist.data.set('hasItems', false);\r\n\r\n\t\t// Add a trailing divider to show the date of the oldest items\r\n\t\tif (list.addTrailingDivider)\r\n\t\t{\r\n\t\t\tlist.addTrailingDivider();\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/**\r\n * Update rows by prepending newer items to the list.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|number|null} newestId - The ID of the newest item.\r\n * @returns {void}\r\n */\r\nexport const prependRows = (rows, tracker, list, newestId = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\tlist.prepend(rows);\r\n\t\t// Update the newest ID to the first item's ID if available\r\n\t\tif (newestId !== null)\r\n\t\t{\r\n\t\t\ttracker.updateNewest(newestId);\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/**\r\n * Set up a fetch callback for loading data.\r\n *\r\n * @param {object} data\r\n * @returns {function}\r\n */\r\nexport const setupFetchCallback = (data) =>\r\n{\r\n\treturn (tracker, callback) =>\r\n\t{\r\n\t\t/**\r\n\t\t * This will handle the result of the fetch.\r\n\t\t *\r\n\t\t * @param {object|null} response\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst resultCallback = (response) =>\r\n\t\t{\r\n\t\t\tlet rows = [];\r\n\t\t\tlet lastCursor = null;\r\n\t\t\tif (response)\r\n\t\t\t{\r\n\t\t\t\trows = response.rows || response.items || [];\r\n\t\t\t\tlastCursor = response.lastCursor || null;\r\n\t\t\t}\r\n\t\t\tcallback(rows, lastCursor);\r\n\t\t};\r\n\r\n\t\tdata.xhr.all('', resultCallback, tracker.currentOffset, tracker.limit, tracker.lastCursor);\r\n\t};\r\n};\r\n\r\n/**\r\n * Set up a fetch callback for loading newer data (forward pagination).\r\n * Uses the 'since' parameter to fetch items newer than the current newest ID.\r\n *\r\n * @param {object} data\r\n * @returns {function}\r\n */\r\nexport const setupFetchNewerCallback = (data) =>\r\n{\r\n\treturn (tracker, callback) =>\r\n\t{\r\n\t\t/**\r\n\t\t * This will handle the result of the fetch.\r\n\t\t *\r\n\t\t * @param {object|null} response\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst resultCallback = (response) =>\r\n\t\t{\r\n\t\t\tlet rows = [];\r\n\t\t\tlet newestId = null;\r\n\t\t\tif (response)\r\n\t\t\t{\r\n\t\t\t\trows = response.rows || response.items || [];\r\n\t\t\t\tnewestId = getNewestId(rows);\r\n\t\t\t}\r\n\t\t\tcallback(rows, newestId);\r\n\t\t};\r\n\r\n\t\t// Pass since as a parameter to the all method\r\n\t\tdata.xhr.all('', resultCallback, 0, tracker.limit, null, tracker.newestId);\r\n\t};\r\n};\r\n\r\n/**\r\n * Fetch and update rows in the list.\r\n *\r\n * @param {function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndUpdate = (fetchCallback, tracker, list) =>\r\n{\r\n\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t{\r\n\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t});\r\n};\r\n\r\n/**\r\n * Fetch and refresh the list.\r\n *\r\n * @param {function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndRefresh = (fetchCallback, tracker, list) =>\r\n{\r\n\ttracker.reset();\r\n\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t{\r\n\t\tlist.reset();\r\n\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\r\n\t\t// Set the newest ID by detecting sort order\r\n\t\tconst newestId = getNewestId(rows);\r\n\t\tif (newestId !== null)\r\n\t\t{\r\n\t\t\ttracker.updateNewest(newestId);\r\n\t\t}\r\n\t});\r\n};\r\n\r\n/**\r\n * Fetch and prepend newer items to the list.\r\n * This is designed to be called manually (e.g., via timer/polling) rather than on scroll.\r\n *\r\n * @param {function} fetchNewerCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndPrepend = (fetchNewerCallback, tracker, list) =>\r\n{\r\n\tif (!tracker.canLoadNewer())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (tracker.loadingNewer)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ttracker.loadingNewer = true;\r\n\tfetchNewerCallback(tracker, (rows, newestId) =>\r\n\t{\r\n\t\tprependRows(rows, tracker, list, newestId);\r\n\t\ttracker.loadingNewer = false;\r\n\t});\r\n};\r\n\r\n/**\r\n * Create a scroll event handler for the container.\r\n *\r\n * This handler ensures that loading is triggered only when the user is close\r\n * to the bottom/top of the container and prevents multiple concurrent loads.\r\n *\r\n * @param {object} container - The scrollable container.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @param {function} fetchCallback - Function to fetch data.\r\n * @param {string} [direction='down'] - Scroll direction: 'down' for bottom loading, 'up' for top loading.\r\n * @param {string} [listCache='list'] - The list cache name.\r\n * @returns {function} A scroll event handler function.\r\n */\r\nexport const createScrollHandler = (container, tracker, fetchCallback, direction = 'down', listCache = 'list') =>\r\n{\r\n\tconst canLoadFunc = direction === 'up' ? canLoadAtTop : canLoad;\r\n\tconst isUpDirection = direction === 'up';\r\n\r\n\treturn (e, parent, callBack) =>\r\n\t{\r\n\t\tconst list = parent[listCache];\r\n\t\tconst metrics = getScrollMetrics(container);\r\n\t\tif (canLoadFunc(metrics, tracker))\r\n\t\t{\r\n\t\t\t// Prevent multiple concurrent loads\r\n\t\t\tif (tracker.loading)\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\ttracker.loading = true;\r\n\t\t\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t\t\t{\r\n\t\t\t\tif (callBack)\r\n\t\t\t\t{\r\n\t\t\t\t\tcallBack();\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Check if this is initial load BEFORE updating (which increments offset)\r\n\t\t\t\tconst isInitialLoad = tracker.currentOffset === 0;\r\n\r\n\t\t\t\t// Use appropriate update function based on direction\r\n\t\t\t\tif (isUpDirection)\r\n\t\t\t\t{\r\n\t\t\t\t\t// For 'up' direction, pass container to preserve scroll position\r\n\t\t\t\t\tupdateRowsAtTop(rows, tracker, list, lastCursor, container);\r\n\r\n\t\t\t\t\t// Set newestId from initial load by detecting sort order\r\n\t\t\t\t\tif (isInitialLoad)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst newestId = getNewestId(rows);\r\n\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttracker.loading = false;\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n};\r\n\r\n/**\r\n * Create a table scroll event handler for the container.\r\n *\r\n * This handler ensures that loading is triggered only when the user is close\r\n * to the bottom of the container and prevents multiple concurrent loads.\r\n *\r\n * @param {object} container - The scrollable container.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @param {function} fetchCallback - Function to fetch data.\r\n * @returns {function} A scroll event handler function.\r\n */\r\nexport const createTableScrollHandler = (container, tracker, fetchCallback) =>\r\n{\r\n\treturn (e, list, callBack) =>\r\n\t{\r\n\t\tconst metrics = getScrollMetrics(container);\r\n\t\tif (canLoad(metrics, tracker))\r\n\t\t{\r\n\t\t\t// Prevent multiple concurrent loads\r\n\t\t\tif (tracker.loading)\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\ttracker.loading = true;\r\n\t\t\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t\t\t{\r\n\t\t\t\tif (callBack)\r\n\t\t\t\t{\r\n\t\t\t\t\tcallBack();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t\t\t\ttracker.loading = false;\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n};\r\n", "import { Atom } from \"@base-framework/base\";\r\nimport DataContainer from \"./data-container.js\";\r\nimport { List } from \"./list.js\";\r\n\r\n/**\r\n * A ScrollableList component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {array} [props.items] - The initial items.\r\n * @property {object} [props.divider] - The row divider.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {string} [props.cache] - The cache name to use.\r\n * @returns {object}\r\n */\r\nexport const DataList = Atom((props) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst cache = props.cache ?? 'list';\r\n\treturn DataContainer(\r\n\t\t{\r\n\t\t\tlistCache: cache,\r\n\t\t\t// @ts-ignore\r\n\t\t\tloadMoreItems: props.loadMoreItems,\r\n\t\t\t// @ts-ignore\r\n\t\t\toffset: props.offset,\r\n\t\t\t// @ts-ignore\r\n\t\t\tlimit: props.limit,\r\n\t\t\t// @ts-ignore\r\n\t\t\tcontainerClass: props.containerClass ?? '',\r\n\t\t\t// @ts-ignore\r\n\t\t\tdata: props.data\r\n\t\t},\r\n\t\t[\r\n\t\t\tnew List({\r\n\t\t\t\tcache,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tkey: props.key,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\titems: props.items || [],\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tdivider: props.divider,\r\n\t\t\t\trole: 'list',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: props.class,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\trowItem: props.rowItem\r\n\t\t\t})\r\n\t\t]\r\n\t);\r\n});\r\n\r\nexport default DataList;", "import { Div } from \"@base-framework/atoms\";\r\nimport { Atom } from \"@base-framework/base\";\r\nimport { PaginationTracker } from \"./pagination-tracker.js\";\r\nimport { fetchAndRefresh, setupFetchCallback } from \"./scroll-utils.js\";\r\n\r\n/**\r\n * This will reset the tracker and fetch new data.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {Function}\r\n */\r\nconst setupResetCallback = (fetchCallback, tracker, list) =>\r\n{\r\n\treturn () =>\r\n\t{\r\n\t\tfetchAndRefresh(fetchCallback, tracker, list);\r\n\t};\r\n};\r\n\r\n/**\r\n * This will add the refresh method to the list.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} parent\r\n * @param {string} listCache\r\n */\r\nconst addRefreshMethod = (fetchCallback, tracker, parent, listCache) =>\r\n{\r\n\tparent[listCache].refresh = setupResetCallback(fetchCallback, tracker, parent[listCache]);\r\n};\r\n\r\n/**\r\n * A DataContainer component that updates using the provided data.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.containerClass] - The class to add to the list container.\r\n * @property {string} [props.listCache] - The list cache name to use.\r\n * @param {Array<any>} children - The child elements to render.\r\n * @returns {object}\r\n */\r\nexport const DataContainer = Atom((props, children) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst tracker = new PaginationTracker(props.offset, props.limit);\r\n\t// @ts-ignore\r\n\tconst fetchCallback = props.loadMoreItems || setupFetchCallback(props.data);\r\n\r\n\treturn Div(\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: props.containerClass ?? '',\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated(ele, parent)\r\n\t\t\t{\r\n\t\t\t\t/**\r\n\t\t\t\t * This will add the refresh method to the list.\r\n\t\t\t\t */\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\taddRefreshMethod(fetchCallback, tracker, parent, props.listCache);\r\n\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tparent[props.listCache].refresh();\r\n\t\t\t}\r\n\t\t},\r\n\t\tchildren\r\n\t);\r\n});\r\n\r\nexport default DataContainer;", "import { Div, On } from '@base-framework/atoms';\r\nimport { Component, Data, Jot } from '@base-framework/base';\r\nimport { ChildHelper } from '../utils/child-helper.js';\r\nimport { DataHelper } from '../utils/data-helper.js';\r\nimport { RowDivider } from './row-divider.js';\r\n\r\n/**\r\n * This will clone the data using shallow copy for better performance.\r\n * For array of objects, creates new array with shallow copies of each object.\r\n *\r\n * @param {*} data\r\n * @returns {*}\r\n */\r\nconst clone = (data) => {\r\n\tif (Array.isArray(data)) {\r\n\t\treturn data.map(item => {\r\n\t\t\tif (item && typeof item === 'object') {\r\n\t\t\t\treturn { ...item };\r\n\t\t\t}\r\n\t\t\treturn item;\r\n\t\t});\r\n\t}\r\n\treturn data;\r\n};\r\n\r\n/**\r\n * List\r\n *\r\n * This will create a list component.\r\n *\r\n * @param {object} props\r\n * @property {string} class - The class to add to the list\r\n * @property {string} key - The key to use to identify the items\r\n * @property {Array<object>} [items] - The items\r\n * @property {object} [emptyState] - The empty state component to show when no items\r\n * @property {object} [divider] - The divider configuration\r\n * @property {function} rowItem - Function to render each row item\r\n * @property {string} [cache] - The cache name to use\r\n * @property {boolean} [linkParent] - The parent data to link\r\n * @property {boolean} [isDynamic] - Whether the list is dynamic\r\n *\r\n * @returns {Component}\r\n */\r\nexport const List = Jot(\r\n{\r\n\t/**\r\n\t * This will check to set up the row divider.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tonCreated()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.divider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider = new RowDivider({ ...this.divider });\r\n\t\t}\r\n\r\n\t\t// Initialize element cache for O(1) lookups by key\r\n\t\t// @ts-ignore\r\n\t\tthis.elementCache = new Map();\r\n\t},\r\n\r\n\t/**\r\n\t * This will set the default data.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst items = (this.items) ? clone(this.items) : [];\r\n\r\n\t\treturn new Data({\r\n\t\t\titems,\r\n\t\t\thasItems: null\r\n\t\t});\r\n\t},\r\n\r\n\t/**\r\n\t * This will run before the component is set up.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tbefore()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.setupHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will set up the hasItems value.\r\n\t *\r\n\t * @protected\r\n\t * @returns {void}\r\n\t */\r\n\tsetupHasItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\t// If we have already set the default, skip it\r\n\t\tif (this.defaultHasItemValue)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('hasItems', true);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tlet parentValue = this.linkParentData();\r\n\r\n\t\tlet hasItems = parentValue || null;\r\n\t\tif (parentValue !== undefined)\r\n\t\t{\r\n\t\t\t/**\r\n\t\t\t * If parent already has items (hasItems === true), respect that value.\r\n\t\t\t * This prevents empty state flash when navigating back to a list\r\n\t\t\t * that was previously populated via data linking.\r\n\t\t\t */\r\n\t\t\tif (parentValue === true)\r\n\t\t\t{\r\n\t\t\t\thasItems = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tconst items = this.items || [];\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\thasItems = (Array.isArray(items) && items.length > 0);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.defaultHasItemValue = hasItems;\r\n\t},\r\n\r\n\t/**\r\n\t * This will link the parent data to the list.\r\n\t *\r\n\t * @protected\r\n\t * @returns {*}\r\n\t */\r\n\tlinkParentData()\r\n\t{\r\n\t\tlet parentValue = false;\r\n\t\t// @ts-ignore\r\n\t\tconst parentData = this.parent?.data ?? this.parent?.context?.data ?? null;\r\n\t\t// @ts-ignore\r\n\t\tif (parentData && this.linkParent !== false)\r\n\t\t{\r\n\t\t\tparentValue = parentData.get('hasItems');\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.link(parentData, 'hasItems');\r\n\t\t}\r\n\t\t// @ts-ignore\r\n\t\telse if (this.isDynamic === true)\r\n\t\t{\r\n\t\t\treturn undefined;\r\n\t\t}\r\n\t\treturn parentValue;\r\n\t},\r\n\r\n\t/**\r\n\t * This will check if we have added items that should persist.\r\n\t *\r\n\t * @protected\r\n\t * @returns {void}\r\n\t */\r\n\tcheckHasAddedItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.defaultHasItemValue === true)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\r\n\t\t// Determine if we have added items that should persist\r\n\t\t// @ts-ignore\r\n\t\tconst hasAddedItems = (items.length > 0 && this.persist === true);\r\n\t\tif (hasAddedItems)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.defaultHasItemValue = true;\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Called when the component is destroyed.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\tdestroy()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.checkHasAddedItems();\r\n\r\n\t\t// If we added items to a linked parent, reset hasItems to default\r\n\t\t// @ts-ignore\r\n\t\tthis.data.hasItems = this.defaultHasItemValue;\r\n\t},\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\r\n\t\treturn Div({ class: 'flex flex-auto flex-col' }, [\r\n\t\t\tOn('hasItems', (hasItems) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\treturn (hasItems === false && this.emptyState)? this.emptyState() : null;\r\n\t\t\t}),\r\n\t\t\tDiv({\r\n\t\t\t\tcache: 'listContainer',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: `list ${this.class || ''}`,\r\n\t\t\t\tonSet: ['hasItems', { hidden: false }],\r\n\t\t\t\tfor: ['items', rowCallBack]\r\n\t\t\t})\r\n\t\t]);\r\n\t},\r\n\r\n\t/**\r\n\t * This will create a row for each item.\r\n\t *\r\n\t * @param {*} item\r\n\t * @param {number} index\r\n\t * @param {*} scope\r\n\t * @param {*} children\r\n\t * @returns {object|null}\r\n\t */\r\n\trow(item, index, scope, children)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (typeof this.rowItem !== 'function')\r\n\t\t{\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\t// Only add dividers via the for: directive if we're not in dynamic mode.\r\n\t\t// Dynamic lists (prepend/append) manage dividers separately to prevent duplicates.\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider && children && this.isDynamic !== true)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider.append(item, children);\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst rowLayout = this.rowItem(item, index);\r\n\r\n\t\t// Add a data attribute with the item's key for reliable DOM element lookup\r\n\t\t// This is needed because dividers and prepending can shift DOM positions\r\n\t\t// @ts-ignore\r\n\t\tif (rowLayout && this.key && item[this.key] !== undefined)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst keyValue = String(item[this.key]);\r\n\r\n\t\t\t// If rowLayout is a Component instance or doesn't have a tag property,\r\n\t\t\t// wrap it in a div with the data-row-key attribute\r\n\t\t\tif (rowLayout instanceof Component || !rowLayout.tag)\r\n\t\t\t{\r\n\t\t\t\tconst wrapper = Div({\r\n\t\t\t\t\t'data-row-key': keyValue\r\n\t\t\t\t}, [rowLayout]);\r\n\t\t\t\t// Store in cache will happen after DOM render\r\n\t\t\t\treturn wrapper;\r\n\t\t\t}\r\n\r\n\t\t\t// Otherwise add the attribute directly to the layout object\r\n\t\t\t// @ts-ignore\r\n\t\t\trowLayout['data-row-key'] = keyValue;\r\n\t\t}\r\n\r\n\t\treturn rowLayout;\r\n\t},\r\n\r\n\t/**\r\n\t * This will delete an item from the list.\r\n\t *\r\n\t * @public\r\n\t * @param {*} keyValue\r\n\t * @returns {void}\r\n\t */\r\n\tdelete(keyValue)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst index = this.findIndexByKey(keyValue);\r\n\t\tif (index === -1)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.data.delete(`items[${index}]`);\r\n\t\t// @ts-ignore\r\n\t\tif (this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = ChildHelper.get(this.listContainer, index);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\tChildHelper.remove(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Remove from element cache\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache) {\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.delete(String(keyValue));\r\n\t\t}\r\n\r\n\t\t// Update hasItems after deletion\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will replace an item in the list.\r\n\t *\r\n\t * @protected\r\n\t * @param {object} row\r\n\t * @param {boolean} append\r\n\t * @returns {void}\r\n\t */\r\n\treplace(row, append = true)\r\n\t{\r\n\t\tif (row.status === 'unchanged')\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst item = row.item;\r\n\t\tif (row.status === 'added')\r\n\t\t{\r\n\t\t\tif (append)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.append(item);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.prepend(item);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst keyValue = item[this.key];\r\n\t\t// @ts-ignore\r\n\t\tconst index = this.findIndexByKey(keyValue);\r\n\t\tif (index === -1)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set(`items[${index}]`, item);\r\n\r\n\t\t// Find the actual DOM element by its key attribute\r\n\t\t// @ts-ignore\r\n\t\tconst oldRow = this.findRowElementByKey(keyValue);\r\n\t\t// @ts-ignore\r\n\t\tconst layout = this.row(item, index);\r\n\t\tif (oldRow && layout)\r\n\t\t{\r\n\t\t\tChildHelper.replace(layout, oldRow, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will remove items from the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array} items\r\n\t * @returns {void}\r\n\t */\r\n\tremove(items)\r\n\t{\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will get the deleted rows.\r\n\t\t */\r\n\t\tconst length = items.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = items[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.delete(item[this.key]);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after removal\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will check if the list is empty.\r\n\t *\r\n\t * @public\r\n\t * @returns {boolean}\r\n\t */\r\n\tisEmpty()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.data.get('items')?.length === 0;\r\n\t},\r\n\r\n\t/**\r\n\t * This will set the items in the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array} rows\r\n\t * @returns {void}\r\n\t */\r\n\tsetRows(rows)\r\n\t{\r\n\t\tconst safeRows = Array.isArray(rows) ? rows : [];\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('items', safeRows);\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will get the items in the list.\r\n\t *\r\n\t * @public\r\n\t * @returns {array}\r\n\t */\r\n\tgetRows()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.data.get('items') || [];\r\n\t},\r\n\r\n\t/**\r\n\t * This will reset the list.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('items', []);\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('hasItems', null);\r\n\t\t// @ts-ignore\r\n\t\tthis.hasTrailingDivider = false;\r\n\r\n\t\t// Clear element cache\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache) {\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.clear();\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider.reset();\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will append items to the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tappend(items)\r\n\t{\r\n\t\tif (!items)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\titems = [items];\r\n\t\t}\r\n\r\n\t\titems = clone(items);\r\n\r\n\t\t/**\r\n\t\t * This will get all the new rows to be batched later.\r\n\t\t */\r\n\t\tconst rows = [];\r\n\t\t// @ts-ignore\r\n\t\tconst existingItems = this.data.get('items') || [];\r\n\t\tconst startIndex = existingItems.length;\r\n\t\tconst length = items.length;\r\n\r\n\t\t// Build rows using traditional for loop for better performance\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = items[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (this.rowDivider)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.append(item, rows);\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will build the new rows that will be appended.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = this.row(item, startIndex + i);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\trows.push(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Batch update all items at once for better performance\r\n\t\t// @ts-ignore\r\n\t\tconst newItems = existingItems.concat(items);\r\n\r\n\t\t/**\r\n\t\t * This will silently add the new rows without re-rendering the entire\r\n\t\t * list. This will bypass the data object and directly add the items\r\n\t\t * to the stage.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tthis.data.attributes.items = newItems;\r\n\t\t// @ts-ignore\r\n\t\tthis.data.stage.items = newItems;\r\n\r\n\t\t// Update hasItems after appending\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\r\n\t\t// This will batch push all the rows.\r\n\t\t// @ts-ignore\r\n\t\tif (rows.length > 0 && this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.append(rows, this.listContainer, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will mingle the new items with the old items.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} newItems\r\n\t * @param {boolean} withDelete\r\n\t * @returns {void}\r\n\t */\r\n\tmingle(newItems, withDelete = false)\r\n\t{\r\n\t\tif (!Array.isArray(newItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tnewItems = clone(newItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\r\n\t\t/**\r\n\t\t * This will diff the old and new items to determine what has\r\n\t\t * been added, updated, or deleted.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.diff(oldItems, newItems, this.key);\r\n\r\n\t\t/**\r\n\t\t * We want to delete the items before adding and updating the\r\n\t\t * new items.\r\n\t\t */\r\n\t\tif (withDelete && changes.deletedItems.length > 0)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.remove(changes.deletedItems);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes.changes[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after mingling\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will mingle the new items with the old items.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} newItems\r\n\t * @param {boolean} append\r\n\t * @param {boolean} deleteIfFound\r\n\t * @returns {void}\r\n\t */\r\n\tmerge(newItems, append = true, deleteIfFound = false)\r\n\t{\r\n\t\tif (!Array.isArray(newItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tnewItems = clone(newItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\r\n\t\t/**\r\n\t\t * This will diff the old and new items to determine what has\r\n\t\t * been added, updated, or deleted.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.diff(oldItems, newItems, this.key);\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes.changes[i];\r\n\t\t\tif (deleteIfFound)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.remove([row.item]);\r\n\t\t\t\trow.status = 'added';\r\n\t\t\t}\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row, append);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after mingling\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will modify existing items in the list with updated data.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} updatedItems\r\n\t * @param {boolean} addMissing\r\n\t * @returns {void}\r\n\t */\r\n\tmodify(updatedItems, addMissing = false)\r\n\t{\r\n\t\tif (!Array.isArray(updatedItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst updatingItems = clone(updatedItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.modify(updatingItems, oldItems, this.key, addMissing);\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after modifying\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will prepend items to the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(items)\r\n\t{\r\n\t\tif (!items)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\titems = [items];\r\n\t\t}\r\n\r\n\t\titems = clone(items);\r\n\r\n\t\t// Set the prepend boundary to the first existing item's date\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst existingItems = this.data.get('items') || [];\r\n\t\t\tif (existingItems.length > 0)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.setPrependBoundary(existingItems[0]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Remove the first child of listContainer if it is a divider.\r\n\t\t// When prepending a new batch, the incoming rows will re-insert\r\n\t\t// the correct seam divider at the proper position. Without this,\r\n\t\t// the old seam divider ends up stranded in the middle of the\r\n\t\t// date group after new items are prepended above it.\r\n\t\t// @ts-ignore\r\n\t\tif (this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst firstChild = this.listContainer.firstChild;\r\n\t\t\tif (firstChild && firstChild.getAttribute && firstChild.getAttribute('data-divider') === 'true')\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.listContainer.removeChild(firstChild);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will get all the new rows to be batched later.\r\n\t\t */\r\n\t\tconst rows = [];\r\n\t\tconst reverseItems = items.reverse();\r\n\t\tconst reverseLength = reverseItems.length;\r\n\r\n\t\t// Build rows using traditional for loop for better performance\r\n\t\tfor (let i = 0; i < reverseLength; i++)\r\n\t\t{\r\n\t\t\tconst item = reverseItems[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (this.rowDivider)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.prepend(item, rows);\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will build the new rows that will be prepended.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = this.row(item, 0);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\trows.push(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// This will use the get method to get the items as a raw array.\r\n\t\t// @ts-ignore\r\n\t\tconst existingItems = this.data.get('items') || [];\r\n\t\tconst newItems = reverseItems.concat(existingItems);\r\n\r\n\t\t/**\r\n\t\t * This will silently add the new rows without re-rendering the entire\r\n\t\t * list. This will bypass the data object and directly add the items\r\n\t\t * to the stage.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tthis.data.attributes.items = newItems;\r\n\t\t// @ts-ignore\r\n\t\tthis.data.stage.items = newItems;\r\n\r\n\t\t// Update hasItems after prepending\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\r\n\t\t// @ts-ignore\r\n\t\tif (rows.length > 0 && this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.prepend(rows, this.listContainer, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will add a trailing divider after the last item in the list.\r\n\t * Useful for showing the date of the oldest items when reaching the end.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\taddTrailingDivider()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (!this.rowDivider)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Prevent adding multiple trailing dividers\r\n\t\t// @ts-ignore\r\n\t\tif (this.hasTrailingDivider)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\tif (items.length === 0)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Get the first (oldest) item - items are in DESC order (newest first)\r\n\t\t// so the oldest item is at index 0\r\n\t\tconst oldestItem = items[0];\r\n\t\t// @ts-ignore\r\n\t\tconst value = this.rowDivider.getValue(oldestItem);\r\n\r\n\t\t// Create the divider layout\r\n\t\t// @ts-ignore\r\n\t\tconst dividerLayout = this.rowDivider.layout(value);\r\n\t\t// @ts-ignore\r\n\t\tif (dividerLayout && this.listContainer)\r\n\t\t{\r\n\t\t\t// Mark dividers so they can be identified\r\n\t\t\tif (typeof dividerLayout === 'object')\r\n\t\t\t{\r\n\t\t\t\tdividerLayout['data-divider'] = 'true';\r\n\t\t\t}\r\n\r\n\t\t\t// Prepend the divider to the top of the list (before the oldest item)\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.prepend([dividerLayout], this.listContainer, this);\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.hasTrailingDivider = true;\r\n\t\t}\r\n\r\n\t},\r\n\r\n\t/**\r\n\t * Updates the hasItems flag based on current items length.\r\n\t *\r\n\t * @private\r\n\t * @returns {void}\r\n\t */\r\n\tupdateHasItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\tconst hasItems = Array.isArray(items) && items.length > 0;\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('hasItems', hasItems);\r\n\t},\r\n\r\n\t/**\r\n\t * Finds the index of an item in the data array by its key.\r\n\t *\r\n\t * @private\r\n\t * @param {*} keyValue\r\n\t * @returns {number} Index of the item, or -1 if not found\r\n\t */\r\n\tfindIndexByKey(keyValue)\r\n\t{\r\n\t\t//@ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\t//@ts-ignore\r\n\t\treturn items.findIndex((item) => item && item[this.key] === keyValue);\r\n\t},\r\n\r\n\t/**\r\n\t * Finds a row DOM element by its key value.\r\n\t * This is more reliable than finding by index, especially after prepending\r\n\t * or when dividers are present.\r\n\t * Now uses element cache for O(1) lookups.\r\n\t *\r\n\t * @private\r\n\t * @param {*} keyValue - The key value to find\r\n\t * @returns {HTMLElement|null} The DOM element, or null if not found\r\n\t */\r\n\tfindRowElementByKey(keyValue)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (!this.listContainer)\r\n\t\t{\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tconst keyString = String(keyValue);\r\n\r\n\t\t// Try cache first for O(1) lookup\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache && this.elementCache.has(keyString))\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst cached = this.elementCache.get(keyString);\r\n\t\t\t// Verify element is still in DOM\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (cached && this.listContainer.contains(cached))\r\n\t\t\t{\r\n\t\t\t\treturn cached;\r\n\t\t\t}\r\n\t\t\t// Remove stale cache entry\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.delete(keyString);\r\n\t\t}\r\n\r\n\t\t// Fallback to DOM search and update cache\r\n\t\t// @ts-ignore\r\n\t\tconst children = this.listContainer.children;\r\n\t\tconst childrenLength = children.length;\r\n\r\n\t\tfor (let i = 0; i < childrenLength; i++)\r\n\t\t{\r\n\t\t\tconst child = children[i];\r\n\t\t\t// Skip dividers\r\n\t\t\tif (child.hasAttribute && child.hasAttribute('data-divider'))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Check if this row has the matching key\r\n\t\t\tif (child.hasAttribute && child.getAttribute('data-row-key') === keyString)\r\n\t\t\t{\r\n\t\t\t\t// Update cache\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tif (this.elementCache)\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tthis.elementCache.set(keyString, child);\r\n\t\t\t\t}\r\n\t\t\t\treturn child;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn null;\r\n\t}\r\n});", "import { Builder, Html } from \"@base-framework/base\";\r\n\r\n/**\r\n * ChildHelper\r\n *\r\n * This class will help with getting children of a node.\r\n *\r\n * @class\r\n */\r\nexport class ChildHelper\r\n{\r\n\t/**\r\n\t * This will get the first child.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic first(parent)\r\n\t{\r\n\t\treturn this.get(parent, 0);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the last child.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic last(parent)\r\n\t{\r\n\t\tconst index = parent.childNodes.length - 1;\r\n\t\treturn this.get(parent, index);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the child at the specified index.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @param {number} index\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic get(parent, index)\r\n\t{\r\n\t\treturn parent?.childNodes[index] ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the parent of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic next(node)\r\n\t{\r\n\t\treturn node?.nextSibling ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the previous sibling.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic previous(node)\r\n\t{\r\n\t\treturn node?.previousSibling ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the index of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {number}\r\n\t */\r\n\tstatic index(node)\r\n\t{\r\n\t\tif (!node || !node.parentNode)\r\n\t\t{\r\n\t\t\treturn -1; // Return -1 if node or its parent doesn't exist\r\n\t\t}\r\n\r\n\t\tconst children = node.parentNode.children;\r\n\t\treturn Array.from(children).indexOf(node);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the previous index of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {number}\r\n\t */\r\n\tstatic getPreviousIndex(node)\r\n\t{\r\n\t\tconst index = this.index(node);\r\n\t\treturn (index > 0)? index - 1 : 0;\r\n\t}\r\n\r\n\t/**\r\n\t * This will replace a child layout.\r\n\t *\r\n\t * @param {object} layout\r\n\t * @param {object} oldChild\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic replace(layout, oldChild, parent)\r\n\t{\r\n\t\tif (!oldChild)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Remove the data from the old child before\r\n\t\t * replacing it with the new child.\r\n\t\t */\r\n\t\tHtml.removeElementData(oldChild);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst frag = Builder.build(layout, null, parent);\r\n\t\toldChild.replaceWith(frag);\r\n\t}\r\n\r\n\t/**\r\n\t * This will remove a child.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {void}\r\n\t */\r\n\tstatic remove(node)\r\n\t{\r\n\t\tif (node)\r\n\t\t{\r\n\t\t\tHtml.removeChild(node);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * This will append a child layout.\r\n\t *\r\n\t * @param {object} childrenLayout\r\n\t * @param {object} container\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic append(childrenLayout, container, parent)\r\n\t{\r\n\t\tif (!childrenLayout)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tBuilder.build(childrenLayout, container, parent);\r\n\t}\r\n\r\n\t/**\r\n\t * This will prepend a child layout.\r\n\t *\r\n\t * @param {object} childrenLayout\r\n\t * @param {object} container\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic prepend(childrenLayout, container, parent)\r\n\t{\r\n\t\tif (!childrenLayout)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst frag = Builder.build(childrenLayout, null, parent);\r\n\t\tcontainer.insertBefore(frag, container.firstChild);\r\n\t}\r\n}", "/**\r\n * This will create a new item.\r\n *\r\n * @param {number} index\r\n * @param {*} item\r\n * @param {string} status\r\n * @returns {object}\r\n */\r\nconst Item = (index, item, status) =>\r\n{\r\n\treturn {\r\n\t\tindex,\r\n\t\titem,\r\n\t\tstatus\r\n\t};\r\n};\r\n\r\n/**\r\n * DataHelper\r\n *\r\n * This will help with data manipulation.\r\n *\r\n * @class\r\n */\r\nexport class DataHelper\r\n{\r\n\t/**\r\n\t * Compares two arrays of objects and returns the differences based on a specified key.\r\n\t *\r\n\t * @param {Array<Object>} oldArray - The original array of objects.\r\n\t * @param {Array<Object>} newArray - The updated array of objects.\r\n\t * @param {string} key - The key used to compare objects in the arrays.\r\n\t * @returns {Object} An object containing arrays of added, updated, and deleted items.\r\n\t */\r\n\tstatic diff(oldArray, newArray, key)\r\n\t{\r\n\t\tconst oldItemsMap = this.arrayToMap(oldArray, key);\r\n\t\tconst changes = [];\r\n\t\tconst deletedItems = [];\r\n\r\n\t\t// Process new array to determine status of each item\r\n\t\tconst newLength = newArray.length;\r\n\t\tfor (let i = 0; i < newLength; i++)\r\n\t\t{\r\n\t\t\tconst newItem = newArray[i];\r\n\t\t\tconst keyValue = newItem[key];\r\n\t\t\tif (!oldItemsMap.has(keyValue))\r\n\t\t\t{\r\n\t\t\t\t// Item is added\r\n\t\t\t\tchanges.push(Item(i, newItem, 'added'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst { item: oldItem } = oldItemsMap.get(keyValue);\r\n\t\t\tif (!this.deepEqual(oldItem, newItem))\r\n\t\t\t{\r\n\t\t\t\t// Item is updated\r\n\t\t\t\tchanges.push(Item(i, newItem, 'updated'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Item is unchanged\r\n\t\t\tchanges.push(Item(i, newItem, 'unchanged'));\r\n\r\n\t\t\t// Remove from oldItemsMap to identify deletions later\r\n\t\t\toldItemsMap.delete(keyValue);\r\n\t\t}\r\n\r\n\t\t// Remaining items in oldItemsMap are deleted\r\n\t\toldItemsMap.forEach(({ item: oldItem }) =>\r\n\t\t{\r\n\t\t\tdeletedItems.push(oldItem);\r\n\t\t});\r\n\r\n\t\treturn {\r\n\t\t\tchanges,\r\n\t\t\tdeletedItems\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * Modifies an array of objects by updating existing items based on a specified key.\r\n\t *\r\n\t * @param {Array<Object>} newArray - The array containing updated items.\r\n\t * @param {Array<Object>} oldArray - The original array of items.\r\n\t * @param {string} key - The key used to identify items.\r\n\t * @param {boolean} [addMissing=false] - Whether to include items that are in newArray but not in oldArray.\r\n\t * @returns {Array<Object>} An array of items that were modified or added.\r\n\t */\r\n\tstatic modify(newArray, oldArray, key, addMissing = false)\r\n\t{\r\n\t\tconst changes = [];\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = DataHelper.arrayToMap(oldArray, key);\r\n\t\tconst length = newArray.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tlet item = newArray[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst id = item[key] ?? null;\r\n\t\t\tif (!oldItems.has(item[id]))\r\n\t\t\t{\r\n\t\t\t\tif (!addMissing)\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tchanges.push(Item(i, item, 'added'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will modify the existing item with new properties.\r\n\t\t\t */\r\n\t\t\tconst oldItem = oldItems.get(item[id]).item;\r\n\t\t\titem = { ...oldItem, ...item };\r\n\r\n\t\t\tchanges.push(Item(i, item, 'updated'));\r\n\t\t}\r\n\t\treturn changes;\r\n\t}\r\n\r\n\t/**\r\n\t * Converts an array of objects into a Map keyed by the specified property.\r\n\t * Each value in the Map is an object containing the item and its index in the array.\r\n\t *\r\n\t * @param {Array<Object>} array - The array to convert.\r\n\t * @param {string} key - The key used to map the objects.\r\n\t * @returns {Map} A Map with keys as specified property and values as objects.\r\n\t * @private\r\n\t */\r\n\tstatic arrayToMap(array, key)\r\n\t{\r\n\t\tconst map = new Map();\r\n\t\tconst length = array.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = array[i];\r\n\t\t\tmap.set(item[key], { item, index: i });\r\n\t\t}\r\n\t\treturn map;\r\n\t}\r\n\r\n\t/**\r\n\t * Performs a deep comparison between two objects.\r\n\t * Optimized with early exits for common cases.\r\n\t *\r\n\t * @param {Object} obj1 - The first object to compare.\r\n\t * @param {Object} obj2 - The second object to compare.\r\n\t * @returns {boolean} True if objects are equal, else false.\r\n\t * @private\r\n\t */\r\n\tstatic deepEqual(obj1, obj2)\r\n\t{\r\n\t\t// Fast path: identical references\r\n\t\tif (obj1 === obj2) return true;\r\n\r\n\t\t// Fast path: type check and null check\r\n\t\tif (\r\n\t\t\ttypeof obj1 !== 'object' ||\r\n\t\t\tobj1 === null ||\r\n\t\t\ttypeof obj2 !== 'object' ||\r\n\t\t\tobj2 === null\r\n\t\t)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst keys1 = Object.keys(obj1);\r\n\t\tconst keys2 = Object.keys(obj2);\r\n\r\n\t\t// Fast path: different number of properties\r\n\t\tif (keys1.length !== keys2.length)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Optimized loop for property comparison\r\n\t\tconst length = keys1.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst key = keys1[i];\r\n\r\n\t\t\t// Fast path: check if key exists in obj2\r\n\t\t\tif (!obj2.hasOwnProperty(key))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Recursive comparison\r\n\t\t\tif (!this.deepEqual(obj1[key], obj2[key]))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n}", "\r\n/**\r\n * RowDivider\r\n *\r\n * This will check to add divider rows to a list based on a divider.\r\n *\r\n * @class\r\n */\r\nexport class RowDivider\r\n{\r\n\t/**\r\n\t * This will create a row divider.\r\n\t *\r\n\t * @param {object} options\r\n\t * @param {function} options.layout\r\n\t * @param {string} options.itemProperty\r\n\t * @param {function} [options.customCompare]\r\n\t * @param {boolean} [options.skipFirst=false] - Skip adding divider for the first item\r\n\t */\r\n\tconstructor({ layout, itemProperty, customCompare, skipFirst = false })\r\n\t{\r\n\t\tthis.layout = layout;\r\n\t\tthis.itemProperty = itemProperty\r\n\t\tthis.customCompare = customCompare;\r\n\t\tthis.skipFirst = skipFirst;\r\n\r\n\t\tthis.lastAppend = null;\r\n\t\tthis.lastPrepend = null;\r\n\t\t// Track the last divider value that was actually added to prevent duplicates\r\n\t\tthis.lastDividerValue = null;\r\n\t\t// Track the boundary value when prepending to avoid duplicate dividers at the boundary\r\n\t\tthis.prependBoundary = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will reset the divider.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\tthis.lastAppend = null;\r\n\t\tthis.lastPrepend = null;\r\n\t\tthis.lastDividerValue = null;\r\n\t\tthis.prependBoundary = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set the prepend boundary to the first item's value.\r\n\t * This should be called before prepending a new batch of items.\r\n\t *\r\n\t * @param {object} firstItem\r\n\t * @returns {void}\r\n\t */\r\n\tsetPrependBoundary(firstItem)\r\n\t{\r\n\t\tif (firstItem)\r\n\t\t{\r\n\t\t\tconst value = this.getValue(firstItem);\r\n\t\t\t// Set lastPrepend so comparisons work correctly for items\r\n\t\t\t// that have the same date as the boundary\r\n\t\t\tthis.lastPrepend = value;\r\n\t\t\t// Store the boundary separately to track prepend context\r\n\t\t\tthis.prependBoundary = value;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Clear prepend boundary if no first item\r\n\t\t\tthis.prependBoundary = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * This will set the first values.\r\n\t *\r\n\t * @param {*} value\r\n\t * @returns {boolean}\r\n\t */\r\n\tsetFirstValues(value)\r\n\t{\r\n\t\tlet last = this.lastAppend;\r\n\t\tif (!last)\r\n\t\t{\r\n\t\t\tthis.lastAppend = value;\r\n\t\t\tthis.lastPrepend = value;\r\n\t\t}\r\n\t\treturn (!last);\r\n\t}\r\n\r\n\t/**\r\n\t * This will append a value.\r\n\t *\r\n\t * @param {object} item\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\tappend(item, children)\r\n\t{\r\n\t\t// Clear prepend boundary when appending (no longer prepending)\r\n\t\tthis.prependBoundary = null;\r\n\r\n\t\tconst value = this.getValue(item);\r\n\t\tconst first = this.setFirstValues(value);\r\n\r\n\t\t// Only add divider for first item if skipFirst is false\r\n\t\tif (first && !this.skipFirst)\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Skip adding divider on first item when skipFirst is true\r\n\t\tif (first)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this.compare(this.lastAppend, value))\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t}\r\n\r\n\t\t// Always update lastAppend to track the current date boundary\r\n\t\tthis.lastAppend = value;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the value of the item.\r\n\t *\r\n\t * @param {object} item\r\n\t * @returns {*}\r\n\t */\r\n\tgetValue(item)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn item[this.itemProperty] ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will prepend a value.\r\n\t *\r\n\t * @param {object} item\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(item, children)\r\n\t{\r\n\t\tconst value = this.getValue(item);\r\n\t\tconst first = this.setFirstValues(value);\r\n\r\n\t\t// Always add a divider for the first item when prepending.\r\n\t\t// skipFirst only applies to append (bottom-to-top lists).\r\n\t\tif (first)\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this.compare(this.lastPrepend, value))\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t}\r\n\r\n\t\t// Always update lastPrepend to track the current date boundary\r\n\t\tthis.lastPrepend = value;\r\n\t}\r\n\r\n\t/**\r\n\t * This will compare the values.\r\n\t *\r\n\t * @param {*} lastValue\r\n\t * @param {*} value\r\n\t * @returns {boolean}\r\n\t */\r\n\tcompare(lastValue, value)\r\n\t{\r\n\t\tif (this.customCompare)\r\n\t\t{\r\n\t\t\treturn this.customCompare(lastValue, value);\r\n\t\t}\r\n\r\n\t\treturn (lastValue !== value);\r\n\t}\r\n\r\n\t/**\r\n\t * This will add a divider layout.\r\n\t *\r\n\t * @param {*} value\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\taddDivider(value, children)\r\n\t{\r\n\t\tif (!this.layout || !children)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Avoid adding duplicate dividers for the same value as last divider\r\n\t\tif (this.lastDividerValue !== null && this.compare(this.lastDividerValue, value) === false)\r\n\t\t{\r\n\t\t\t// same value as last divider -> skip\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst layout = this.layout(value);\r\n\r\n\t\t// Mark dividers so they can be identified and skipped when finding row elements\r\n\t\tif (layout && typeof layout === 'object')\r\n\t\t{\r\n\t\t\tlayout['data-divider'] = 'true';\r\n\t\t}\r\n\r\n\t\tchildren.push(layout);\r\n\r\n\t\t// remember the last divider value we added\r\n\t\tthis.lastDividerValue = value;\r\n\t}\r\n}", "import { Atom } from \"@base-framework/base\";\r\nimport BiDirectionalContainer from \"./bi-directional-container.js\";\r\nimport { List } from \"./list.js\";\r\n\r\n/**\r\n * A ScrollableList component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {array} [props.items] - The initial items.\r\n * @property {object} [props.divider] - The row divider.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {object|null} [props.emptyState] - The empty state to show when there are no items.\r\n * @property {string} [props.cache] - The cache name to use.\r\n * @property {boolean} [props.linkParent] - Whether to link the parent data.\r\n * @returns {object}\r\n */\r\nexport const ScrollableList = Atom((props) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst cache = props.cache ?? 'list';\r\n\treturn BiDirectionalContainer(\r\n\t\t{\r\n\t\t\tlistCache: cache,\r\n\t\t\t// @ts-ignore\r\n\t\t\tscrollDirection: props.scrollDirection || 'down',\r\n\t\t\t// @ts-ignore\r\n\t\t\tscrollContainer: props.scrollContainer,\r\n\t\t\t// @ts-ignore\r\n\t\t\tloadMoreItems: props.loadMoreItems,\r\n\t\t\t// @ts-ignore\r\n\t\t\toffset: props.offset,\r\n\t\t\t// @ts-ignore\r\n\t\t\tlimit: props.limit,\r\n\t\t\t// @ts-ignore\r\n\t\t\tcontainerClass: props.containerClass ?? 'flex flex-auto flex-col',\r\n\t\t\t// @ts-ignore\r\n\t\t\tdata: props.data\r\n\t\t},\r\n\t\t[\r\n\t\t\tnew List({\r\n\t\t\t\tcache,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tkey: props.key,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\titems: props.items || [],\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tdivider: props.divider,\r\n\t\t\t\trole: 'list',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: props.class,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\temptyState: props.emptyState || null,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\trowItem: props.rowItem,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tlinkParent: props.linkParent ?? false,\r\n\t\t\t\tisDynamic: true\r\n\t\t\t})\r\n\t\t]\r\n\t);\r\n});\r\n\r\nexport default ScrollableList;", "import { Component, router } from '@base-framework/base';\r\n\r\n/**\r\n * Watcher\r\n *\r\n * This will create a watcher object.\r\n *\r\n * @param {string} attr\r\n * @param {string} value\r\n * @returns {object}\r\n */\r\nconst Watcher = (attr, value) => ({\r\n\tattr,\r\n\tvalue\r\n});\r\n\r\n/**\r\n * This will check if the path is active.\r\n *\r\n * @param {string} path\r\n * @param {string} url\r\n * @returns {boolean}\r\n */\r\nconst iSActive = (path, url) => new RegExp('^' + path + '($|#|/|\\\\.).*').test(url);\r\n\r\n/**\r\n * NavLink\r\n *\r\n * This will create a nav link that will add an active\r\n * class when the browser route path matches the link\r\n * href.\r\n *\r\n * @property {string} activeClass - The active class to add.\r\n * @property {string} class - The class\r\n * @property {string} exact - The exact match\r\n * @property {string|object} href - The href or watcher object\r\n * @property {string|object} text - The text or watcher object\r\n * @property {array|string} nest - The nested elements\r\n *\r\n * @class\r\n * @extends Component\r\n */\r\nexport class NavLink extends Component\r\n{\r\n /**\r\n * This will configure the link active class.\r\n *\r\n * @protected\r\n * @returns {void}\r\n */\r\n beforeSetup()\r\n {\r\n // @ts-ignore\r\n this.selectedClass = this.activeClass || 'active';\r\n }\r\n\r\n /**\r\n * This will render the component.\r\n *\r\n * @returns {object}\r\n */\r\n render()\r\n {\r\n // @ts-ignore\r\n const href = this.href,\r\n // @ts-ignore\r\n text = this.text,\r\n watchers = this.setupWatchers(href, text);\r\n\r\n return {\r\n tag: 'a',\r\n // @ts-ignore\r\n class: this.class || this.className || null,\r\n onState: ['selected', {\r\n [this.selectedClass]: true\r\n }],\r\n href: this.getString(href),\r\n text: this.getString(text),\r\n // @ts-ignore\r\n nest: this.nest || this.children,\r\n // @ts-ignore\r\n dataSet: this.dataSet,\r\n watch: watchers\r\n };\r\n }\r\n\r\n /**\r\n * This will get the link path.\r\n *\r\n * @returns {string|null}\r\n */\r\n getLinkPath()\r\n {\r\n // @ts-ignore\r\n return this?.panel?.pathname || null;\r\n }\r\n\r\n /**\r\n * This will get string.\r\n *\r\n * @param {string} string\r\n * @returns {(string|null)}\r\n */\r\n getString(string)\r\n {\r\n const type = typeof string;\r\n return (type !== 'object' && type !== 'undefined')? string : null;\r\n }\r\n\r\n /**\r\n * This will setup the watchers.\r\n *\r\n * @protected\r\n * @param {string} href\r\n * @param {string} text\r\n * @returns {array}\r\n */\r\n setupWatchers(href, text)\r\n {\r\n // @ts-ignore\r\n const exact = (this.exact === true),\r\n data = router.data;\r\n\r\n const watchers = [];\r\n\r\n if (href && typeof href === 'object')\r\n {\r\n watchers.push(Watcher('href', href));\r\n }\r\n\r\n if (text && typeof text === 'object')\r\n {\r\n watchers.push(Watcher('text', text));\r\n }\r\n\r\n watchers.push({\r\n value: ['[[path]]', data],\r\n callBack: (value, ele) =>\r\n {\r\n const path = ele.pathname + ele.hash;\r\n\t\t\t\tconst selected = exact? (value === path) : (iSActive(ele.pathname, value));\r\n this.update(selected);\r\n }\r\n });\r\n\r\n return watchers;\r\n }\r\n\r\n /**\r\n * This will setup the states.\r\n *\r\n * @protected\r\n * @returns {object}\r\n */\r\n setupStates()\r\n {\r\n return {\r\n selected: false\r\n };\r\n }\r\n\r\n /**\r\n * This will update the class on the element.\r\n *\r\n * @param {boolean} selected\r\n * @returns {void}\r\n */\r\n update(selected)\r\n {\r\n // @ts-ignore\r\n this.state.selected = selected;\r\n }\r\n}", "import { Tbody } from '@base-framework/atoms';\r\nimport { PaginationTracker } from '../lists/pagination-tracker.js';\r\nimport { fetchAndRefresh, setupFetchCallback } from '../lists/scroll-utils.js';\r\nimport { TableBody } from './table-body.js';\r\n\r\n/**\r\n * A DataTableBody component that handles data fetching and rendering for a table body.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {Array<object>} [props.items] - The initial items.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.tableData] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n *\r\n * @class DataTableBody\r\n * @extends TableBody\r\n */\r\nexport class DataTableBody extends TableBody\r\n{\r\n\t/**\r\n\t * This will declare the component props.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tdeclareProps()\r\n\t{\r\n\t\t/**\r\n\t\t * @member {PaginationTracker}\r\n\t\t */\r\n\t\tthis.tracker = null;\r\n\r\n\t\t/**\r\n\t\t * @member {function}\r\n\t\t */\r\n\t\tthis.fetchCallback = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the page tracker.\r\n\t *\r\n\t * @returns {PaginationTracker}\r\n\t */\r\n\tsetupPageTracker()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.tracker = new PaginationTracker(this.offset, this.limit);\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the fetch callback.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tsetupFetchCallback()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.setupPageTracker();\r\n\t\t// @ts-ignore\r\n\t\tthis.fetchCallback = this.loadMoreItems || setupFetchCallback(this.tableData);\r\n\t}\r\n\r\n\t/**\r\n\t * This will refresh the list.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\trefresh()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tfetchAndRefresh(this.fetchCallback, this.tracker, this);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\t\t// @ts-ignore\r\n\t\tthis.setupFetchCallback();\r\n\r\n\t\treturn Tbody({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated: (ele, parent) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\t\t\t\tthis.refresh();\r\n\t\t\t},\r\n\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};\r\n\r\nexport default DataTableBody;", "import { Tbody } from '@base-framework/atoms';\r\nimport { Data } from '@base-framework/base';\r\nimport { List } from '../lists/list.js';\r\nimport { SkeletonTableRow } from './skeleton-table-row.js';\r\n\r\n/**\r\n * TableBody\r\n *\r\n * This will create a table body component with skeleton support.\r\n *\r\n * @param {object} props\r\n * @property {string} class - The class to add to the list\r\n * @property {string} key - The key to use to identify the items\r\n * @property {Array<object>} [items] - The items\r\n * @property {boolean|object} [skeleton] - Skeleton configuration. Can be true for default or object with { number: 5, row: customRowFunction }\r\n * @property {number} [columnCount] - Number of columns for skeleton rows (auto-detected from headers if not provided)\r\n *\r\n * @class TableBody\r\n * @extends List\r\n */\r\n// @ts-ignore\r\nexport class TableBody extends List\r\n{\r\n\t/**\r\n\t * This will set the default data.\r\n\t *\r\n\t * @returns {Data}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst hasItems = this.items && this.items.length > 0;\r\n\t\t// @ts-ignore\r\n\t\tconst isSkeletonEnabled = this.skeleton && !hasItems;\r\n\t\tif (isSkeletonEnabled)\r\n\t\t{\r\n\t\t\t// Create new data with skeleton properties\r\n\t\t\treturn new Data({\r\n\t\t\t\titems: this.generateSkeletonRows(),\r\n\t\t\t\thasItems: true, // Show skeleton as if we have items\r\n\t\t\t\tshowSkeleton: true\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\treturn super.setData();\r\n\t}\r\n\r\n\t/**\r\n\t * Generates skeleton rows for the table.\r\n\t *\r\n\t * @returns {Array<object>}\r\n\t */\r\n\tgenerateSkeletonRows()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst skeletonConfig = this.skeleton;\r\n\r\n\t\t// Default skeleton configuration\r\n\t\tlet skeletonCount = 5;\r\n\t\tlet customRowFunction = null;\r\n\r\n\t\t// Handle skeleton configuration\r\n\t\tif (typeof skeletonConfig === 'object')\r\n\t\t{\r\n\t\t\tskeletonCount = skeletonConfig.number || 5;\r\n\t\t\tcustomRowFunction = skeletonConfig.row || null;\r\n\t\t}\r\n\r\n\t\t// Calculate column count from columnCount prop or default to 3\r\n\t\t// @ts-ignore\r\n\t\tconst columnCount = this.columnCount || 3;\r\n\r\n\t\t// Generate skeleton rows\r\n\t\treturn Array.from({ length: skeletonCount }, (_, index) =>\r\n\t\t{\r\n\t\t\tif (customRowFunction && typeof customRowFunction === 'function')\r\n\t\t\t{\r\n\t\t\t\treturn customRowFunction(index, columnCount);\r\n\t\t\t}\r\n\r\n\t\t\treturn SkeletonTableRow({\r\n\t\t\t\tcolumnCount,\r\n\t\t\t\tkey: `skeleton-${index}`\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Removes skeleton rows and shows real content.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tremoveSkeleton()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.data.get('showSkeleton'))\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('showSkeleton', false);\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('items', this.items || []);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Override setRows to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>} rows\r\n\t * @returns {void}\r\n\t */\r\n\tsetRows(rows)\r\n\t{\r\n\t\t// Remove skeleton when setting real rows\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.setRows(rows);\r\n\t}\r\n\r\n\t/**\r\n\t * Override append to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tappend(items)\r\n\t{\r\n\t\t// Remove skeleton when appending real items\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.append(items);\r\n\t}\r\n\r\n\t/**\r\n\t * Override prepend to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(items)\r\n\t{\r\n\t\t// Remove skeleton when prepending real items\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.prepend(items);\r\n\t}\r\n\r\n\t/**\r\n\t * This will create a row for each item.\r\n\t * Override to handle skeleton items differently from real data items.\r\n\t *\r\n\t * @param {*} item\r\n\t * @param {*} index\r\n\t * @param {*} scope\r\n\t * @param {*} children\r\n\t * @returns {object|null}\r\n\t */\r\n\trow(item, index, scope, children)\r\n\t{\r\n\t\t// If this is a skeleton item (already a component), return it directly\r\n\t\t// @ts-ignore\r\n\t\tif (this.data && this.data.get('showSkeleton'))\r\n\t\t{\r\n\t\t\treturn item;\r\n\t\t}\r\n\r\n\t\t// For real data items, use the normal row processing\r\n\t\t// @ts-ignore\r\n\t\treturn super.row(item, index, scope, children);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\r\n\t\treturn Tbody({\r\n\t\t\tonCreated: (ele) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\t\t\t},\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};", "import { Div, Td, Tr } from '@base-framework/atoms';\r\n\r\n/**\r\n * Creates a skeleton table row with animated placeholders.\r\n *\r\n * @param {object} props\r\n * @param {number} [props.columnCount=3] - Number of columns to create skeleton cells for\r\n * @param {function} [props.customCell] - Custom function to render skeleton cells\r\n * @param {string} [props.key] - Unique key for the row\r\n * @returns {object}\r\n */\r\nexport const SkeletonTableRow = ({ columnCount = 3, customCell, key }) =>\r\n{\r\n\tconst createSkeletonCell = (index) =>\r\n\t{\r\n\t\tif (customCell && typeof customCell === 'function')\r\n\t\t{\r\n\t\t\treturn customCell(index);\r\n\t\t}\r\n\r\n\t\t// Default skeleton cell with varying widths for more realistic appearance\r\n\t\tconst widths = ['w-3/4', 'w-1/2', 'w-full', 'w-2/3', 'w-5/6'];\r\n\t\tconst width = widths[index % widths.length];\r\n\r\n\t\treturn Td({ class: 'px-6 py-4' }, [\r\n\t\t\tDiv({\r\n\t\t\t\tclass: `${width} h-4 bg-muted animate-pulse rounded-md`\r\n\t\t\t})\r\n\t\t]);\r\n\t};\r\n\r\n\treturn Tr({\r\n\t\tclass: 'border-b',\r\n\t\tkey\r\n\t}, Array.from({ length: columnCount }, (_, index) => createSkeletonCell(index)));\r\n};\r\n\r\nexport default SkeletonTableRow;\r\n", "import { Tbody } from '@base-framework/atoms';\r\nimport { PaginationTracker } from '../lists/pagination-tracker.js';\r\nimport { createTableScrollHandler, fetchAndRefresh, setupFetchCallback } from '../lists/scroll-utils.js';\r\nimport { TableBody } from './table-body.js';\r\n\r\n/**\r\n * A ScrollableTableBody component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {Array<object>} [props.items] - The initial items.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.tableData] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {boolean|object} [props.skeleton] - Skeleton configuration. Can be true for default or object with { number: 5, row: customRowFunction }\r\n * @property {number} [props.columnCount] - Number of columns for skeleton rows\r\n *\r\n * @class ScrollableTableBody\r\n * @extends TableBody\r\n */\r\nexport class ScrollableTableBody extends TableBody\r\n{\r\n\t/**\r\n\t * This will declare the component props.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tdeclareProps()\r\n\t{\r\n\t\t/**\r\n\t\t * @member {PaginationTracker}\r\n\t\t */\r\n\t\tthis.tracker = null;\r\n\r\n\t\t/**\r\n\t\t * @member {HTMLElement}\r\n\t\t * @default globalThis\r\n\t\t */\r\n\t\tthis.scrollContainer = null;\r\n\r\n\t\t/**\r\n\t\t * @member {function}\r\n\t\t */\r\n\t\tthis.fetchCallback = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the page tracker.\r\n\t *\r\n\t * @returns {PaginationTracker}\r\n\t */\r\n\tsetupPageTracker()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.tracker = new PaginationTracker(this.offset, this.limit);\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the scroll handler.\r\n\t *\r\n\t * @param {HTMLElement} container\r\n\t * @returns {Function}\r\n\t */\r\n\tsetupScrollHandler(container)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst tracker = this.setupPageTracker();\r\n\t\t// @ts-ignore\r\n\t\tthis.fetchCallback = this.loadMoreItems || setupFetchCallback(this.tableData);\r\n\r\n\t\t/**\r\n\t\t * This will handle the scroll event.\r\n\t\t *\r\n\t\t * @param {object|null} e\r\n\t\t * @param {object} parent\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\treturn createTableScrollHandler(container, tracker, this.fetchCallback);\r\n\t}\r\n\r\n\t/**\r\n\t * This will refresh the list.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\trefresh()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tfetchAndRefresh(this.fetchCallback, this.tracker, this);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\t\t// @ts-ignore\r\n\t\tconst container = this.scrollContainer || globalThis;\r\n\r\n\t\t/**\r\n\t\t * This will handle the scroll event.\r\n\t\t *\r\n\t\t * @param {object|null} e\r\n\t\t * @param {object} parent\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst handleScroll = this.setupScrollHandler(container);\r\n\r\n\t\treturn Tbody({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated: (ele, parent) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\r\n\t\t\t\thandleScroll(null, parent, () =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tthis.reset();\r\n\t\t\t\t});\r\n\t\t\t},\r\n\r\n\t\t\t/**\r\n\t\t\t * This will add the scroll event to the container.\r\n\t\t\t */\r\n\t\t\taddEvent: ['scroll', container, handleScroll, { passive: true }],\r\n\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};\r\n\r\nexport default ScrollableTableBody;", "import { Span } from \"@base-framework/atoms\";\r\nimport { Component, SimpleData } from \"@base-framework/base\";\r\nimport { IntervalTimer } from \"../utils/timer/interval-timer.js\";\r\n\r\n/**\r\n * This will create a simple flat data object to use to bind\r\n * timer update. This will be used to update the time every\r\n * minute.\r\n *\r\n * This data will be bound to all the dynamic time elements.\r\n *\r\n * @constant\r\n * @type {SimpleData} data\r\n */\r\nconst data = new SimpleData({\r\n\tdate: 0\r\n});\r\n\r\n/**\r\n * @constant\r\n * @type {number} MINUTE_INTERVAL\r\n */\r\nconst MINUTE_INTERVAL = 60000;\r\n\r\n/**\r\n * This will update the the data value every minute.\r\n *\r\n * @constant\r\n * @type {IntervalTimer} timer\r\n */\r\nconst timer = new IntervalTimer(MINUTE_INTERVAL, () =>\r\n{\r\n\tdata.increment('date');\r\n});\r\n\r\n/**\r\n * This will start the timer to update any dynamic time\r\n * elements.\r\n */\r\ntimer.start();\r\n\r\n/**\r\n * DynamicTime\r\n *\r\n * This will create a dynamic time element that will update\r\n * the time every minute.\r\n *\r\n * @property {string} dateTime - The date time to display.\r\n * @property {function} [filter] - The filter to apply to the date time.\r\n *\r\n * @class\r\n * @augments Component\r\n */\r\nexport class DynamicTime extends Component\r\n{\r\n\t/**\r\n\t * This will set up the component data with the\r\n\t * data created above.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\treturn data;\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the component.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\treturn Span({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: this.class,\r\n\t\t\ttext: this.getTime(),\r\n\t\t\tonSet: ['date', () => this.getTime()]\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the date and check to filter the value.\r\n\t *\r\n\t * @returns {string}\r\n\t */\r\n\tgetTime()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst dateTime = this.dateTime;\r\n\t\t// @ts-ignore\r\n\t\treturn (this.filter) ? this.filter(dateTime) : dateTime;\r\n\t}\r\n}", "/**\r\n * Timer\r\n *\r\n * This will create a timer that will call a callback function.\r\n *\r\n * @property {number} duration - The duration of the timer.\r\n * @property {function} callBack - The callback function.\r\n *\r\n * @class\r\n */\r\nexport class Timer\r\n{\r\n\t/**\r\n\t * This will create a new timer.\r\n\t *\r\n\t * @param {number} duration\r\n\t * @param {function} callBack\r\n\t */\r\n\tconstructor(duration, callBack)\r\n\t{\r\n\t\t/**\r\n\t\t * @property {number|null} timer\r\n\t\t */\r\n\t\tthis.timer = null;\r\n\r\n\t\t/**\r\n\t\t * @property {function} callBack\r\n\t\t */\r\n\t\tthis.callBack = callBack;\r\n\r\n\t\t/**\r\n\t\t * @property {number} duration\r\n\t\t */\r\n\t\tthis.duration = duration || 1000;\r\n\t}\r\n\r\n\t/**\r\n\t * This will create a timer.\r\n\t *\r\n\t * @protected\r\n\t * @param {function} callBack\r\n\t * @returns {void}\r\n\t */\r\n\tcreateTimer(callBack)\r\n\t{\r\n\t\tthis.timer = globalThis.setTimeout(callBack, this.duration);\r\n\t}\r\n\r\n\t/**\r\n\t * This will start the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstart()\r\n\t{\r\n\t\t/**\r\n\t\t * This will stop the timer before starting a new one.\r\n\t\t */\r\n\t\tthis.stop();\r\n\r\n\t\tconst callBack = this.returnCallBack.bind(this);\r\n\t\tthis.createTimer(callBack);\r\n\t}\r\n\r\n\t/**\r\n\t * This will stop the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstop()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tglobalThis.clearTimeout(this.timer);\r\n\t}\r\n\r\n\t/**\r\n\t * This will call the callback function.\r\n\t *\r\n\t * @private\r\n\t * @returns {void}\r\n\t */\r\n\treturnCallBack()\r\n\t{\r\n\t\tconst callBack = this.callBack;\r\n\t\tif (typeof callBack === 'function')\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tcallBack.call();\r\n\t\t}\r\n\t}\r\n}", "import { Timer } from './timer.js';\r\n\r\n/**\r\n * IntervalTimer\r\n *\r\n * This will create a timer that will call a callback function.\r\n *\r\n * @class\r\n */\r\nexport class IntervalTimer extends Timer\r\n{\r\n\t/**\r\n\t * This will create a timer.\r\n\t *\r\n\t * @protected\r\n\t * @param {function} callBack\r\n\t * @returns {void}\r\n\t */\r\n\tcreateTimer(callBack)\r\n\t{\r\n\t\tthis.timer = globalThis.setInterval(callBack, this.duration);\r\n\t}\r\n\r\n\t/**\r\n\t * This will stop the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstop()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tglobalThis.clearInterval(this.timer);\r\n\t}\r\n}"],
5
- "mappings": "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",
6
- "names": ["Div", "Atom", "PaginationTracker", "offset", "limit", "numItems", "lastCursor", "newestId", "SCROLL_THRESHOLD", "getNewestId", "rows", "firstItem", "lastItem", "getScrollMetrics", "container", "scrollTop", "clientHeight", "scrollHeight", "shouldLoadMore", "metrics", "threshold", "shouldLoadAtTop", "canLoad", "tracker", "canLoadAtTop", "updateRows", "list", "lastCursor", "updateRowsAtTop", "heightDifference", "setupFetchCallback", "data", "tracker", "callback", "resultCallback", "response", "rows", "lastCursor", "setupFetchNewerCallback", "newestId", "getNewestId", "fetchAndRefresh", "fetchCallback", "tracker", "list", "rows", "lastCursor", "updateRows", "newestId", "getNewestId", "createScrollHandler", "container", "tracker", "fetchCallback", "direction", "listCache", "canLoadFunc", "canLoadAtTop", "canLoad", "isUpDirection", "e", "parent", "callBack", "list", "metrics", "getScrollMetrics", "rows", "lastCursor", "isInitialLoad", "updateRowsAtTop", "newestId", "getNewestId", "updateRows", "createTableScrollHandler", "setupResetCallback", "fetchCallback", "tracker", "list", "fetchAndRefresh", "addRefreshMethod", "parent", "listCache", "BiDirectionalContainer", "Atom", "props", "children", "PaginationTracker", "container", "scrollDirection", "setupFetchCallback", "fetchNewerCallback", "setupFetchNewerCallback", "handleScroll", "createScrollHandler", "Div", "ele", "items", "newestId", "getNewestId", "shouldScroll", "rows", "scrollHeight", "bi_directional_container_default", "Atom", "Div", "Atom", "setupResetCallback", "fetchCallback", "tracker", "list", "fetchAndRefresh", "addRefreshMethod", "parent", "listCache", "DataContainer", "Atom", "props", "children", "PaginationTracker", "setupFetchCallback", "Div", "ele", "data_container_default", "Div", "On", "Component", "Data", "Jot", "Builder", "Html", "ChildHelper", "parent", "index", "node", "children", "layout", "oldChild", "frag", "childrenLayout", "container", "Item", "index", "item", "status", "DataHelper", "_DataHelper", "oldArray", "newArray", "key", "oldItemsMap", "changes", "deletedItems", "newLength", "i", "newItem", "keyValue", "oldItem", "addMissing", "oldItems", "length", "id", "array", "map", "obj1", "obj2", "keys1", "keys2", "RowDivider", "layout", "itemProperty", "customCompare", "skipFirst", "firstItem", "value", "last", "item", "children", "first", "lastValue", "clone", "data", "item", "List", "Jot", "RowDivider", "items", "Data", "parentValue", "hasItems", "parentData", "rowCallBack", "Div", "On", "index", "scope", "children", "rowLayout", "keyValue", "Component", "rowElement", "ChildHelper", "row", "append", "oldRow", "layout", "length", "i", "rows", "safeRows", "existingItems", "startIndex", "newItems", "withDelete", "oldItems", "changes", "DataHelper", "changesLength", "deleteIfFound", "updatedItems", "addMissing", "updatingItems", "firstChild", "reverseItems", "reverseLength", "oldestItem", "value", "dividerLayout", "keyString", "cached", "childrenLength", "child", "DataList", "Atom", "props", "cache", "data_container_default", "List", "Atom", "ScrollableList", "Atom", "props", "cache", "bi_directional_container_default", "List", "Component", "router", "Watcher", "attr", "value", "iSActive", "path", "url", "NavLink", "href", "text", "watchers", "string", "type", "exact", "data", "ele", "selected", "Tbody", "Tbody", "Data", "Div", "Td", "Tr", "SkeletonTableRow", "columnCount", "customCell", "key", "createSkeletonCell", "index", "widths", "width", "_", "TableBody", "List", "hasItems", "Data", "skeletonConfig", "skeletonCount", "customRowFunction", "columnCount", "_", "index", "SkeletonTableRow", "rows", "items", "item", "scope", "children", "rowCallBack", "Tbody", "ele", "DataTableBody", "TableBody", "PaginationTracker", "setupFetchCallback", "fetchAndRefresh", "rowCallBack", "Tbody", "ele", "parent", "Tbody", "ScrollableTableBody", "TableBody", "PaginationTracker", "container", "tracker", "setupFetchCallback", "createTableScrollHandler", "fetchAndRefresh", "rowCallBack", "handleScroll", "Tbody", "ele", "parent", "Span", "Component", "SimpleData", "Timer", "duration", "callBack", "IntervalTimer", "Timer", "callBack", "data", "SimpleData", "MINUTE_INTERVAL", "timer", "IntervalTimer", "DynamicTime", "Component", "Span", "dateTime"]
4
+ "sourcesContent": ["import { Div } from \"@base-framework/atoms\";\r\nimport { Atom } from \"@base-framework/base\";\r\nimport { PaginationTracker } from \"./pagination-tracker.js\";\r\nimport { createScrollHandler, fetchAndRefresh, getNewestId, setupFetchCallback, setupFetchNewerCallback } from \"./scroll-utils.js\";\r\n\r\n/**\r\n * This will reset the tracker and fetch new data.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {Function}\r\n */\r\nconst setupResetCallback = (fetchCallback, tracker, list) =>\r\n{\r\n\treturn () =>\r\n\t{\r\n\t\tfetchAndRefresh(fetchCallback, tracker, list);\r\n\t};\r\n};\r\n\r\n/**\r\n * This will add the refresh method to the list.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} parent\r\n * @param {string} listCache\r\n */\r\nconst addRefreshMethod = (fetchCallback, tracker, parent, listCache) =>\r\n{\r\n\tparent[listCache].refresh = setupResetCallback(fetchCallback, tracker, parent[listCache]);\r\n};\r\n\r\n/**\r\n * A BiDirectionalContainer component that supports both backward (older) and forward (newer)\r\n * data fetching using cursor and since pagination. Ideal for chat/message interfaces and activity feeds.\r\n *\r\n * Supports two scroll directions:\r\n * - **\"down\"** (default): Scrolling down loads older items (appends to bottom), fetchNew() prepends newer items to top\r\n * Use for: Activity feeds, news feeds, social media timelines\r\n * - **\"up\"**: Scrolling up loads older items (prepends to top), fetchNew() appends newer items to bottom\r\n * Use for: Chat/messaging interfaces where newest messages are at bottom\r\n *\r\n * Automatic scroll position management for 'up' direction:\r\n * - Initial load automatically scrolls to bottom (shows newest messages)\r\n * - Prepending older messages preserves scroll position (prevents jarring jumps)\r\n * - Exposes scrollToBottom() method for manual control\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch older items (backward pagination using cursor).\r\n * @property {function} [props.loadNewerItems] - A function to fetch newer items (forward pagination using since).\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.containerClass] - The class to add to the container.\r\n * @property {string} [props.scrollDirection='down'] - Scroll direction: 'down' (scroll down for older) or 'up' (scroll up for older).\r\n * @property {string} [props.listCache] - The list cache name to use.\r\n * @param {Array<any>} children - The child elements to render.\r\n * @returns {object}\r\n *\r\n * @example\r\n * // Activity feed (scroll down for older, new items at top)\r\n * const ActivityFeed = (userId, onSetup) => BiDirectionalContainer({\r\n * scrollDirection: 'down', // default\r\n * loadMoreItems: async (tracker, callback) => {\r\n * const response = await fetch(`/activities?cursor=${tracker.lastCursor}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.items, data.lastCursor);\r\n * },\r\n * loadNewerItems: async (tracker, callback) => {\r\n * const response = await fetch(`/activities?since=${tracker.newestId}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.items, data.items[0]?.id);\r\n * },\r\n * limit: 20\r\n * }, [\r\n * new List({\r\n * items: [],\r\n * rowItem: (activity) => ActivityRow(activity),\r\n * onCreated: (ele, parent) => {\r\n * if (onSetup) onSetup(parent.list);\r\n * }\r\n * })\r\n * ]);\r\n *\r\n * @example\r\n * // Chat conversation (scroll up for older, new messages at bottom)\r\n * const MessageList = (conversationId, onSetup) => BiDirectionalContainer({\r\n * scrollDirection: 'up',\r\n * loadMoreItems: async (tracker, callback) => {\r\n * const response = await fetch(`/messages?cursor=${tracker.lastCursor}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.messages, data.lastCursor);\r\n * },\r\n * loadNewerItems: async (tracker, callback) => {\r\n * const response = await fetch(`/messages?since=${tracker.newestId}&limit=${tracker.limit}`);\r\n * const data = await response.json();\r\n * callback(data.messages, data.messages[0]?.id);\r\n * },\r\n * limit: 20\r\n * }, [\r\n * new List({\r\n * items: [],\r\n * rowItem: (msg) => MessageRow(msg),\r\n * onCreated: (ele, parent) => {\r\n * if (onSetup) onSetup(parent.list);\r\n * }\r\n * })\r\n * ]);\r\n *\r\n * // In parent layout (polling controlled externally):\r\n * let messageList = null;\r\n * const list = MessageList(123, (ref) => { messageList = ref; });\r\n * setInterval(() => messageList?.fetchNew(), 3000);\r\n *\r\n * @example\r\n * // Using with data object (backward only)\r\n * BiDirectionalContainer({\r\n * data: conversationData,\r\n * limit: 20\r\n * }, [\r\n * new List({ items: [], rowItem: (msg) => MessageRow(msg) })\r\n * ]);\r\n */\r\nexport const BiDirectionalContainer = Atom((props, children) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst tracker = new PaginationTracker(props.offset, props.limit);\r\n\t// @ts-ignore\r\n\tconst container = props.scrollContainer || globalThis;\r\n\t// @ts-ignore\r\n\tconst scrollDirection = props.scrollDirection || 'down';\r\n\t// @ts-ignore\r\n\tconst fetchCallback = props.loadMoreItems || setupFetchCallback(props.data);\r\n\t// @ts-ignore\r\n\tconst fetchNewerCallback = props.loadNewerItems || setupFetchNewerCallback(props.data);\r\n\r\n\t/**\r\n\t * This will handle the scroll event for loading older items.\r\n\t * Direction determines if we scroll up or down to load older items.\r\n\t *\r\n\t * @param {object|null} e\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\t// @ts-ignore\r\n\tconst handleScroll = createScrollHandler(container, tracker, fetchCallback, scrollDirection, props.listCache);\r\n\r\n\treturn Div(\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: props.containerClass ?? '',\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated(ele, parent)\r\n\t\t\t{\r\n\t\t\t\t/**\r\n\t\t\t\t * This will add the refresh method to the list.\r\n\t\t\t\t */\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\taddRefreshMethod(fetchCallback, tracker, parent, props.listCache);\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * This will request the first fetch.\r\n\t\t\t\t */\r\n\t\t\t\thandleScroll(null, parent, () =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tconst list = parent[props.listCache];\r\n\t\t\t\t\tlist.reset();\r\n\r\n\t\t\t\t\t// For 'up' direction (chat), ensure newestId is set from the loaded items\r\n\t\t\t\t\tif (scrollDirection === 'up')\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Get the newest ID by detecting sort order\r\n\t\t\t\t\t\tconst items = list.data?.items || list.data?.rows || [];\r\n\t\t\t\t\t\tif (tracker.newestId === null)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst newestId = getNewestId(items);\r\n\t\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tlist.scrollToBottom();\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tconst list = parent[props.listCache];\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Add method to manually fetch newer items (useful for polling).\r\n\t\t\t\t * This should be called via setInterval or other timer mechanism.\r\n\t\t\t\t * The placement of new items depends on scrollDirection:\r\n\t\t\t\t * - 'down': prepends to top (for feeds)\r\n\t\t\t\t * - 'up': appends to bottom (for chat)\r\n\t\t\t\t */\r\n\t\t\t\tlist.fetchNew = (shouldScroll = false) =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// Allow fetching if we're not already loading\r\n\t\t\t\t\t// Don't require hasNewerData to be true (it starts as false)\r\n\t\t\t\t\tif (!tracker.loadingNewer)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttracker.loadingNewer = true;\r\n\t\t\t\t\t\tfetchNewerCallback(tracker, (rows, newestId) =>\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (rows && rows.length > 0)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// Direction determines where to add new items\r\n\t\t\t\t\t\t\t\tif (scrollDirection === 'up')\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Chat: new messages at bottom\r\n\t\t\t\t\t\t\t\t\t// Use append instead of updateRows to avoid affecting pagination tracker\r\n\t\t\t\t\t\t\t\t\tlist.append(rows);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Feed: new items at top\r\n\t\t\t\t\t\t\t\t\t// Use prepend instead of prependRows to avoid affecting pagination tracker\r\n\t\t\t\t\t\t\t\t\tlist.prepend(rows);\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t// Update newest ID tracker if available\r\n\t\t\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\ttracker.loadingNewer = false;\r\n\r\n\t\t\t\t\t\t\tif (shouldScroll && scrollDirection === 'up')\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlist.scrollToBottom();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Add method to scroll to bottom (useful for chat interfaces).\r\n\t\t\t\t * This can be called after fetching new messages to keep user at bottom.\r\n\t\t\t\t * Uses onFlush to wait for batched UI updates.\r\n\t\t\t\t */\r\n\t\t\t\tlist.scrollToBottom = () =>\r\n\t\t\t\t{\r\n\t\t\t\t\tlist.onFlush(() =>\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (container === globalThis)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst scrollHeight = globalThis.document.documentElement.scrollHeight;\r\n\t\t\t\t\t\t\tglobalThis.scrollTo(0, scrollHeight);\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\t\tcontainer.scrollTop = container.scrollHeight;\r\n\t\t\t\t\t});\r\n\t\t\t\t};\r\n\t\t\t},\r\n\r\n\t\t\t/**\r\n\t\t\t * This will add the scroll event to the container for loading older items.\r\n\t\t\t */\r\n\t\t\taddEvent: ['scroll', container, handleScroll, { passive: true }],\r\n\t\t},\r\n\t\tchildren\r\n\t);\r\n});\r\n\r\nexport default BiDirectionalContainer;\r\n", "/**\r\n * PaginationTracker stores and updates pagination state.\r\n * Supports bi-directional cursor pagination for both backward (older)\r\n * and forward (newer) data fetching.\r\n *\r\n * @class\r\n */\r\nexport class PaginationTracker\r\n{\r\n\t/**\r\n\t * Creates an instance of PaginationTracker.\r\n\t *\r\n\t * @param {number} [offset=0] - The initial offset.\r\n\t * @param {number} [limit=20] - The number of items to load per batch.\r\n\t */\r\n\tconstructor(offset = 0, limit = 20)\r\n\t{\r\n\t\t// Backward pagination (older/historical data)\r\n\t\tthis.lastCursor = null;\r\n\t\tthis.currentOffset = offset;\r\n\t\tthis.limit = limit;\r\n\t\tthis.hasMoreData = true;\r\n\t\tthis.loading = false;\r\n\r\n\t\t// Forward pagination (newer data)\r\n\t\tthis.newestId = null;\r\n\t\tthis.hasNewerData = false;\r\n\t\tthis.loadingNewer = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether more data can be loaded (backward/older).\r\n\t *\r\n\t * @returns {boolean}\r\n\t */\r\n\tcanLoadMore()\r\n\t{\r\n\t\treturn this.hasMoreData;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether newer data can be loaded (forward).\r\n\t *\r\n\t * @returns {boolean}\r\n\t */\r\n\tcanLoadNewer()\r\n\t{\r\n\t\treturn this.hasNewerData && this.newestId !== null;\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the tracker state based on the number of items loaded (backward).\r\n\t *\r\n\t * @param {number} numItems - The number of items loaded.\r\n\t * @param {string|null} lastCursor - The last cursor value.\r\n\t * @returns {void}\r\n\t */\r\n\tupdate(numItems, lastCursor = null)\r\n\t{\r\n\t\tif (numItems < this.limit)\r\n\t\t{\r\n\t\t\tthis.hasMoreData = false;\r\n\t\t}\r\n\r\n\t\tthis.lastCursor = lastCursor;\r\n\t\tthis.currentOffset += numItems;\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the newest ID for forward pagination.\r\n\t *\r\n\t * @param {string|number|null} newestId - The ID of the newest item.\r\n\t * @returns {void}\r\n\t */\r\n\tupdateNewest(newestId)\r\n\t{\r\n\t\tthis.newestId = newestId;\r\n\t\tthis.hasNewerData = newestId !== null;\r\n\t}\r\n\r\n\t/**\r\n\t * Resets the tracker state.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\tthis.lastCursor = null;\r\n\t\tthis.currentOffset = 0;\r\n\t\tthis.hasMoreData = true;\r\n\t\tthis.loading = false;\r\n\t\tthis.newestId = null;\r\n\t\tthis.hasNewerData = false;\r\n\t\tthis.loadingNewer = false;\r\n\t}\r\n}\r\n\r\nexport default PaginationTracker;", "import { PaginationTracker } from \"./pagination-tracker.js\";\r\n\r\n// Module-level constant for scroll threshold (in pixels)\r\nconst SCROLL_THRESHOLD = 100;\r\n\r\n/**\r\n * Extract the newest ID from an array of rows by detecting sort order.\r\n * Compares first and last item IDs to determine if data is in ASC or DESC order.\r\n *\r\n * @param {Array} rows - The array of row objects\r\n * @returns {number|string|null} The highest ID, or null if no valid ID found\r\n */\r\nexport function getNewestId(rows)\r\n{\r\n\tif (!rows || rows.length === 0)\r\n\t{\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst firstItem = rows[0];\r\n\tconst lastItem = rows[rows.length - 1];\r\n\r\n\t// Both items have IDs - compare to detect sort order\r\n\tif (firstItem?.id && lastItem?.id)\r\n\t{\r\n\t\t// If first ID > last ID, it's DESC order (newest first)\r\n\t\t// If first ID < last ID, it's ASC order (oldest first)\r\n\t\treturn firstItem.id > lastItem.id ? firstItem.id : lastItem.id;\r\n\t}\r\n\r\n\t// Only one item has an ID - return whichever exists\r\n\tif (firstItem?.id)\r\n\t{\r\n\t\treturn firstItem.id;\r\n\t}\r\n\r\n\tif (lastItem?.id)\r\n\t{\r\n\t\treturn lastItem.id;\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Get scroll metrics for a container.\r\n *\r\n * @param {HTMLElement|globalThis} container\r\n * @returns {object} Contains scrollTop, clientHeight, and scrollHeight.\r\n */\r\nexport function getScrollMetrics(container)\r\n{\r\n\t// @ts-ignore\r\n\tconst scrollTop = container === globalThis ? globalThis.pageYOffset : container.scrollTop;\r\n\t// @ts-ignore\r\n\tconst clientHeight = container === globalThis ? globalThis.innerHeight : container.clientHeight;\r\n\t// @ts-ignore\r\n\tconst scrollHeight = container === globalThis ? globalThis.document.documentElement.scrollHeight : container.scrollHeight;\r\n\treturn { scrollTop, clientHeight, scrollHeight };\r\n}\r\n\r\n/**\r\n * Check if the scroll position indicates we should load more items at the bottom.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {number} [threshold=SCROLL_THRESHOLD] - The threshold in pixels.\r\n * @returns {boolean}\r\n */\r\nexport function shouldLoadMore(metrics, threshold = SCROLL_THRESHOLD)\r\n{\r\n\treturn metrics.scrollTop + metrics.clientHeight >= metrics.scrollHeight - threshold;\r\n}\r\n\r\n/**\r\n * Check if the scroll position indicates we should load more items at the top.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {number} [threshold=SCROLL_THRESHOLD] - The threshold in pixels.\r\n * @returns {boolean}\r\n */\r\nexport function shouldLoadAtTop(metrics, threshold = SCROLL_THRESHOLD)\r\n{\r\n\treturn metrics.scrollTop <= threshold;\r\n}\r\n\r\n/**\r\n * Check if more items can be loaded at the bottom based on metrics and tracker state.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @returns {boolean}\r\n */\r\nexport const canLoad = (metrics, tracker) =>\r\n{\r\n\treturn shouldLoadMore(metrics) && tracker.canLoadMore();\r\n};\r\n\r\n/**\r\n * Check if more items can be loaded at the top based on metrics and tracker state.\r\n *\r\n * @param {object} metrics - The scroll metrics.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @returns {boolean}\r\n */\r\nexport const canLoadAtTop = (metrics, tracker) =>\r\n{\r\n\treturn shouldLoadAtTop(metrics) && tracker.canLoadMore();\r\n};\r\n\r\n/**\r\n * Update the rows in the list by appending and update the tracker state.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|null} lastCursor - The last cursor value.\r\n * @returns {void}\r\n */\r\nexport const updateRows = (rows, tracker, list, lastCursor = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\tlist.append(rows);\r\n\t\ttracker.update(rows.length, lastCursor);\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttracker.hasMoreData = false;\r\n\t\tlist.data.set('hasItems', false);\r\n\t}\r\n};\r\n\r\n/**\r\n * Update the rows in the list by prepending older items and update the tracker state.\r\n * Used when scrolling up to load older items.\r\n * Preserves scroll position to prevent content jumping.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|null} lastCursor - The last cursor value.\r\n * @param {HTMLElement|globalThis|null} [container] - The scroll container.\r\n * @returns {void}\r\n */\r\nexport const updateRowsAtTop = (rows, tracker, list, lastCursor = null, container = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\t// Save scroll position before prepending\r\n\t\tlet scrollHeight = 0;\r\n\t\tlet scrollTop = 0;\r\n\r\n\t\tif (container)\r\n\t\t{\r\n\t\t\tconst metrics = getScrollMetrics(container);\r\n\t\t\tscrollHeight = metrics.scrollHeight;\r\n\t\t\tscrollTop = metrics.scrollTop;\r\n\t\t}\r\n\r\n\t\t// Prepend the rows\r\n\t\tlist.prepend(rows);\r\n\t\ttracker.update(rows.length, lastCursor);\r\n\r\n\t\t// Check if we received fewer rows than the limit, indicating no more data\r\n\t\tif (rows.length < tracker.limit)\r\n\t\t{\r\n\t\t\ttracker.hasMoreData = false;\r\n\r\n\t\t\t// Add a trailing divider to show the date of the oldest items\r\n\t\t\tif (list.addTrailingDivider)\r\n\t\t\t{\r\n\t\t\t\tlist.addTrailingDivider();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Restore scroll position to prevent jump\r\n\t\tif (container)\r\n\t\t{\r\n\t\t\t// Calculate the difference in height after prepending\r\n\t\t\tconst newMetrics = getScrollMetrics(container);\r\n\t\t\tconst heightDifference = newMetrics.scrollHeight - scrollHeight;\r\n\r\n\t\t\t// Adjust scroll position by the height difference\r\n\t\t\tif (container === globalThis)\r\n\t\t\t{\r\n\t\t\t\tglobalThis.scrollTo(0, scrollTop + heightDifference);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tcontainer.scrollTop = scrollTop + heightDifference;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttracker.hasMoreData = false;\r\n\t\tlist.data.set('hasItems', false);\r\n\r\n\t\t// Add a trailing divider to show the date of the oldest items\r\n\t\tif (list.addTrailingDivider)\r\n\t\t{\r\n\t\t\tlist.addTrailingDivider();\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/**\r\n * Update rows by prepending newer items to the list.\r\n *\r\n * @param {Array} rows\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @param {string|number|null} newestId - The ID of the newest item.\r\n * @returns {void}\r\n */\r\nexport const prependRows = (rows, tracker, list, newestId = null) =>\r\n{\r\n\tif (rows && rows.length > 0)\r\n\t{\r\n\t\tlist.prepend(rows);\r\n\t\t// Update the newest ID to the first item's ID if available\r\n\t\tif (newestId !== null)\r\n\t\t{\r\n\t\t\ttracker.updateNewest(newestId);\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/**\r\n * Set up a fetch callback for loading data.\r\n *\r\n * @param {object} data\r\n * @returns {function}\r\n */\r\nexport const setupFetchCallback = (data) =>\r\n{\r\n\treturn (tracker, callback) =>\r\n\t{\r\n\t\t/**\r\n\t\t * This will handle the result of the fetch.\r\n\t\t *\r\n\t\t * @param {object|null} response\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst resultCallback = (response) =>\r\n\t\t{\r\n\t\t\tlet rows = [];\r\n\t\t\tlet lastCursor = null;\r\n\t\t\tif (response)\r\n\t\t\t{\r\n\t\t\t\trows = response.rows || response.items || [];\r\n\t\t\t\tlastCursor = response.lastCursor || null;\r\n\t\t\t}\r\n\t\t\tcallback(rows, lastCursor);\r\n\t\t};\r\n\r\n\t\tdata.xhr.all('', resultCallback, tracker.currentOffset, tracker.limit, tracker.lastCursor);\r\n\t};\r\n};\r\n\r\n/**\r\n * Set up a fetch callback for loading newer data (forward pagination).\r\n * Uses the 'since' parameter to fetch items newer than the current newest ID.\r\n *\r\n * @param {object} data\r\n * @returns {function}\r\n */\r\nexport const setupFetchNewerCallback = (data) =>\r\n{\r\n\treturn (tracker, callback) =>\r\n\t{\r\n\t\t/**\r\n\t\t * This will handle the result of the fetch.\r\n\t\t *\r\n\t\t * @param {object|null} response\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst resultCallback = (response) =>\r\n\t\t{\r\n\t\t\tlet rows = [];\r\n\t\t\tlet newestId = null;\r\n\t\t\tif (response)\r\n\t\t\t{\r\n\t\t\t\trows = response.rows || response.items || [];\r\n\t\t\t\tnewestId = getNewestId(rows);\r\n\t\t\t}\r\n\t\t\tcallback(rows, newestId);\r\n\t\t};\r\n\r\n\t\t// Pass since as a parameter to the all method\r\n\t\tdata.xhr.all('', resultCallback, 0, tracker.limit, null, tracker.newestId);\r\n\t};\r\n};\r\n\r\n/**\r\n * Fetch and update rows in the list.\r\n *\r\n * @param {function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndUpdate = (fetchCallback, tracker, list) =>\r\n{\r\n\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t{\r\n\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t});\r\n};\r\n\r\n/**\r\n * Fetch and refresh the list.\r\n *\r\n * @param {function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndRefresh = (fetchCallback, tracker, list) =>\r\n{\r\n\ttracker.reset();\r\n\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t{\r\n\t\tlist.reset();\r\n\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\r\n\t\t// Set the newest ID by detecting sort order\r\n\t\tconst newestId = getNewestId(rows);\r\n\t\tif (newestId !== null)\r\n\t\t{\r\n\t\t\ttracker.updateNewest(newestId);\r\n\t\t}\r\n\t});\r\n};\r\n\r\n/**\r\n * Fetch and prepend newer items to the list.\r\n * This is designed to be called manually (e.g., via timer/polling) rather than on scroll.\r\n *\r\n * @param {function} fetchNewerCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {void}\r\n */\r\nexport const fetchAndPrepend = (fetchNewerCallback, tracker, list) =>\r\n{\r\n\tif (!tracker.canLoadNewer())\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (tracker.loadingNewer)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\ttracker.loadingNewer = true;\r\n\tfetchNewerCallback(tracker, (rows, newestId) =>\r\n\t{\r\n\t\tprependRows(rows, tracker, list, newestId);\r\n\t\ttracker.loadingNewer = false;\r\n\t});\r\n};\r\n\r\n/**\r\n * Create a scroll event handler for the container.\r\n *\r\n * This handler ensures that loading is triggered only when the user is close\r\n * to the bottom/top of the container and prevents multiple concurrent loads.\r\n *\r\n * @param {object} container - The scrollable container.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @param {function} fetchCallback - Function to fetch data.\r\n * @param {string} [direction='down'] - Scroll direction: 'down' for bottom loading, 'up' for top loading.\r\n * @param {string} [listCache='list'] - The list cache name.\r\n * @returns {function} A scroll event handler function.\r\n */\r\nexport const createScrollHandler = (container, tracker, fetchCallback, direction = 'down', listCache = 'list') =>\r\n{\r\n\tconst canLoadFunc = direction === 'up' ? canLoadAtTop : canLoad;\r\n\tconst isUpDirection = direction === 'up';\r\n\r\n\treturn (e, parent, callBack) =>\r\n\t{\r\n\t\tconst list = parent[listCache];\r\n\t\tconst metrics = getScrollMetrics(container);\r\n\t\tif (canLoadFunc(metrics, tracker))\r\n\t\t{\r\n\t\t\t// Prevent multiple concurrent loads\r\n\t\t\tif (tracker.loading)\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\ttracker.loading = true;\r\n\t\t\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t\t\t{\r\n\t\t\t\tif (callBack)\r\n\t\t\t\t{\r\n\t\t\t\t\tcallBack();\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Check if this is initial load BEFORE updating (which increments offset)\r\n\t\t\t\tconst isInitialLoad = tracker.currentOffset === 0;\r\n\r\n\t\t\t\t// Use appropriate update function based on direction\r\n\t\t\t\tif (isUpDirection)\r\n\t\t\t\t{\r\n\t\t\t\t\t// For 'up' direction, pass container to preserve scroll position\r\n\t\t\t\t\tupdateRowsAtTop(rows, tracker, list, lastCursor, container);\r\n\r\n\t\t\t\t\t// Set newestId from initial load by detecting sort order\r\n\t\t\t\t\tif (isInitialLoad)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst newestId = getNewestId(rows);\r\n\t\t\t\t\t\tif (newestId !== null)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttracker.updateNewest(newestId);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttracker.loading = false;\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n};\r\n\r\n/**\r\n * Create a table scroll event handler for the container.\r\n *\r\n * This handler ensures that loading is triggered only when the user is close\r\n * to the bottom of the container and prevents multiple concurrent loads.\r\n *\r\n * @param {object} container - The scrollable container.\r\n * @param {PaginationTracker} tracker - The pagination tracker.\r\n * @param {function} fetchCallback - Function to fetch data.\r\n * @returns {function} A scroll event handler function.\r\n */\r\nexport const createTableScrollHandler = (container, tracker, fetchCallback) =>\r\n{\r\n\treturn (e, list, callBack) =>\r\n\t{\r\n\t\tconst metrics = getScrollMetrics(container);\r\n\t\tif (canLoad(metrics, tracker))\r\n\t\t{\r\n\t\t\t// Prevent multiple concurrent loads\r\n\t\t\tif (tracker.loading)\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\ttracker.loading = true;\r\n\t\t\tfetchCallback(tracker, (rows, lastCursor) =>\r\n\t\t\t{\r\n\t\t\t\tif (callBack)\r\n\t\t\t\t{\r\n\t\t\t\t\tcallBack();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tupdateRows(rows, tracker, list, lastCursor);\r\n\t\t\t\ttracker.loading = false;\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n};\r\n", "import { Atom } from \"@base-framework/base\";\r\nimport DataContainer from \"./data-container.js\";\r\nimport { List } from \"./list.js\";\r\n\r\n/**\r\n * A ScrollableList component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {array} [props.items] - The initial items.\r\n * @property {object} [props.divider] - The row divider.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {string} [props.cache] - The cache name to use.\r\n * @returns {object}\r\n */\r\nexport const DataList = Atom((props) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst cache = props.cache ?? 'list';\r\n\treturn DataContainer(\r\n\t\t{\r\n\t\t\tlistCache: cache,\r\n\t\t\t// @ts-ignore\r\n\t\t\tloadMoreItems: props.loadMoreItems,\r\n\t\t\t// @ts-ignore\r\n\t\t\toffset: props.offset,\r\n\t\t\t// @ts-ignore\r\n\t\t\tlimit: props.limit,\r\n\t\t\t// @ts-ignore\r\n\t\t\tcontainerClass: props.containerClass ?? '',\r\n\t\t\t// @ts-ignore\r\n\t\t\tdata: props.data\r\n\t\t},\r\n\t\t[\r\n\t\t\tnew List({\r\n\t\t\t\tcache,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tkey: props.key,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\titems: props.items || [],\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tdivider: props.divider,\r\n\t\t\t\trole: 'list',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: props.class,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\trowItem: props.rowItem\r\n\t\t\t})\r\n\t\t]\r\n\t);\r\n});\r\n\r\nexport default DataList;", "import { Div } from \"@base-framework/atoms\";\r\nimport { Atom } from \"@base-framework/base\";\r\nimport { PaginationTracker } from \"./pagination-tracker.js\";\r\nimport { fetchAndRefresh, setupFetchCallback } from \"./scroll-utils.js\";\r\n\r\n/**\r\n * This will reset the tracker and fetch new data.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} list\r\n * @returns {Function}\r\n */\r\nconst setupResetCallback = (fetchCallback, tracker, list) =>\r\n{\r\n\treturn () =>\r\n\t{\r\n\t\tfetchAndRefresh(fetchCallback, tracker, list);\r\n\t};\r\n};\r\n\r\n/**\r\n * This will add the refresh method to the list.\r\n *\r\n * @param {Function} fetchCallback\r\n * @param {PaginationTracker} tracker\r\n * @param {object} parent\r\n * @param {string} listCache\r\n */\r\nconst addRefreshMethod = (fetchCallback, tracker, parent, listCache) =>\r\n{\r\n\tparent[listCache].refresh = setupResetCallback(fetchCallback, tracker, parent[listCache]);\r\n};\r\n\r\n/**\r\n * A DataContainer component that updates using the provided data.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.containerClass] - The class to add to the list container.\r\n * @property {string} [props.listCache] - The list cache name to use.\r\n * @param {Array<any>} children - The child elements to render.\r\n * @returns {object}\r\n */\r\nexport const DataContainer = Atom((props, children) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst tracker = new PaginationTracker(props.offset, props.limit);\r\n\t// @ts-ignore\r\n\tconst fetchCallback = props.loadMoreItems || setupFetchCallback(props.data);\r\n\r\n\treturn Div(\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: props.containerClass ?? '',\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated(ele, parent)\r\n\t\t\t{\r\n\t\t\t\t/**\r\n\t\t\t\t * This will add the refresh method to the list.\r\n\t\t\t\t */\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\taddRefreshMethod(fetchCallback, tracker, parent, props.listCache);\r\n\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tparent[props.listCache].refresh();\r\n\t\t\t}\r\n\t\t},\r\n\t\tchildren\r\n\t);\r\n});\r\n\r\nexport default DataContainer;", "import { Div, On } from '@base-framework/atoms';\r\nimport { Component, Data, Jot } from '@base-framework/base';\r\nimport { ChildHelper } from '../utils/child-helper.js';\r\nimport { DataHelper } from '../utils/data-helper.js';\r\nimport { RowDivider } from './row-divider.js';\r\n\r\n/**\r\n * This will clone the data using shallow copy for better performance.\r\n * For array of objects, creates new array with shallow copies of each object.\r\n *\r\n * @param {*} data\r\n * @returns {*}\r\n */\r\nconst clone = (data) => {\r\n\tif (Array.isArray(data)) {\r\n\t\treturn data.map(item => {\r\n\t\t\tif (item && typeof item === 'object') {\r\n\t\t\t\treturn { ...item };\r\n\t\t\t}\r\n\t\t\treturn item;\r\n\t\t});\r\n\t}\r\n\treturn data;\r\n};\r\n\r\n/**\r\n * List\r\n *\r\n * This will create a list component.\r\n *\r\n * @param {object} props\r\n * @property {string} class - The class to add to the list\r\n * @property {string} key - The key to use to identify the items\r\n * @property {Array<object>} [items] - The items\r\n * @property {object} [emptyState] - The empty state component to show when no items\r\n * @property {object} [divider] - The divider configuration\r\n * @property {function} rowItem - Function to render each row item\r\n * @property {string} [cache] - The cache name to use\r\n * @property {boolean} [linkParent] - The parent data to link\r\n * @property {boolean} [isDynamic] - Whether the list is dynamic\r\n *\r\n * @returns {Component}\r\n */\r\nexport const List = Jot(\r\n{\r\n\t/**\r\n\t * This will check to set up the row divider.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tonCreated()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.divider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider = new RowDivider({ ...this.divider });\r\n\t\t}\r\n\r\n\t\t// Initialize element cache for O(1) lookups by key\r\n\t\t// @ts-ignore\r\n\t\tthis.elementCache = new Map();\r\n\t},\r\n\r\n\t/**\r\n\t * This will set the default data.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst items = (this.items) ? clone(this.items) : [];\r\n\r\n\t\treturn new Data({\r\n\t\t\titems,\r\n\t\t\thasItems: null\r\n\t\t});\r\n\t},\r\n\r\n\t/**\r\n\t * This will run before the component is set up.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tbefore()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.setupHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will set up the hasItems value.\r\n\t *\r\n\t * @protected\r\n\t * @returns {void}\r\n\t */\r\n\tsetupHasItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\t// If we have already set the default, skip it\r\n\t\tif (this.defaultHasItemValue)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('hasItems', true);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tlet parentValue = this.linkParentData();\r\n\r\n\t\tlet hasItems = parentValue || null;\r\n\t\tif (parentValue !== undefined)\r\n\t\t{\r\n\t\t\t/**\r\n\t\t\t * If parent already has items (hasItems === true), respect that value.\r\n\t\t\t * This prevents empty state flash when navigating back to a list\r\n\t\t\t * that was previously populated via data linking.\r\n\t\t\t */\r\n\t\t\tif (parentValue === true)\r\n\t\t\t{\r\n\t\t\t\thasItems = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tconst items = this.items || [];\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\thasItems = (Array.isArray(items) && items.length > 0);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.defaultHasItemValue = hasItems;\r\n\t},\r\n\r\n\t/**\r\n\t * This will link the parent data to the list.\r\n\t *\r\n\t * @protected\r\n\t * @returns {*}\r\n\t */\r\n\tlinkParentData()\r\n\t{\r\n\t\tlet parentValue = false;\r\n\t\t// @ts-ignore\r\n\t\tconst parentData = this.parent?.data ?? this.parent?.context?.data ?? null;\r\n\t\t// @ts-ignore\r\n\t\tif (parentData && this.linkParent !== false)\r\n\t\t{\r\n\t\t\tparentValue = parentData.get('hasItems');\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.link(parentData, 'hasItems');\r\n\t\t}\r\n\t\t// @ts-ignore\r\n\t\telse if (this.isDynamic === true)\r\n\t\t{\r\n\t\t\treturn undefined;\r\n\t\t}\r\n\t\treturn parentValue;\r\n\t},\r\n\r\n\t/**\r\n\t * This will check if we have added items that should persist.\r\n\t *\r\n\t * @protected\r\n\t * @returns {void}\r\n\t */\r\n\tcheckHasAddedItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.defaultHasItemValue === true)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\r\n\t\t// Determine if we have added items that should persist\r\n\t\t// @ts-ignore\r\n\t\tconst hasAddedItems = (items.length > 0 && this.persist === true);\r\n\t\tif (hasAddedItems)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.defaultHasItemValue = true;\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Called when the component is destroyed.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\tdestroy()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.checkHasAddedItems();\r\n\r\n\t\t// If we added items to a linked parent, reset hasItems to default\r\n\t\t// @ts-ignore\r\n\t\tthis.data.hasItems = this.defaultHasItemValue;\r\n\t},\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\r\n\t\treturn Div({ class: 'flex flex-auto flex-col' }, [\r\n\t\t\tOn('hasItems', (hasItems) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\treturn (hasItems === false && this.emptyState)? this.emptyState() : null;\r\n\t\t\t}),\r\n\t\t\tDiv({\r\n\t\t\t\tcache: 'listContainer',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: `list ${this.class || ''}`,\r\n\t\t\t\tonSet: ['hasItems', { hidden: false }],\r\n\t\t\t\tfor: ['items', rowCallBack]\r\n\t\t\t})\r\n\t\t]);\r\n\t},\r\n\r\n\t/**\r\n\t * This will create a row for each item.\r\n\t *\r\n\t * @param {*} item\r\n\t * @param {number} index\r\n\t * @param {*} scope\r\n\t * @param {*} children\r\n\t * @returns {object|null}\r\n\t */\r\n\trow(item, index, scope, children)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (typeof this.rowItem !== 'function')\r\n\t\t{\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\t// Only add dividers via the for: directive if we're not in dynamic mode.\r\n\t\t// Dynamic lists (prepend/append) manage dividers separately to prevent duplicates.\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider && children && this.isDynamic !== true)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider.append(item, children);\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst rowLayout = this.rowItem(item, index);\r\n\r\n\t\t// Add a data attribute with the item's key for reliable DOM element lookup\r\n\t\t// This is needed because dividers and prepending can shift DOM positions\r\n\t\t// @ts-ignore\r\n\t\tif (rowLayout && this.key && item[this.key] !== undefined)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst keyValue = String(item[this.key]);\r\n\r\n\t\t\t// If rowLayout is a Component instance or doesn't have a tag property,\r\n\t\t\t// wrap it in a div with the data-row-key attribute\r\n\t\t\tif (rowLayout instanceof Component || !rowLayout.tag)\r\n\t\t\t{\r\n\t\t\t\tconst wrapper = Div({\r\n\t\t\t\t\t'data-row-key': keyValue\r\n\t\t\t\t}, [rowLayout]);\r\n\t\t\t\t// Store in cache will happen after DOM render\r\n\t\t\t\treturn wrapper;\r\n\t\t\t}\r\n\r\n\t\t\t// Otherwise add the attribute directly to the layout object\r\n\t\t\t// @ts-ignore\r\n\t\t\trowLayout['data-row-key'] = keyValue;\r\n\t\t}\r\n\r\n\t\treturn rowLayout;\r\n\t},\r\n\r\n\t/**\r\n\t * This will delete an item from the list.\r\n\t *\r\n\t * @public\r\n\t * @param {*} keyValue\r\n\t * @returns {void}\r\n\t */\r\n\tdelete(keyValue)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst index = this.findIndexByKey(keyValue);\r\n\t\tif (index === -1)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.data.delete(`items[${index}]`);\r\n\t\t// @ts-ignore\r\n\t\tif (this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = ChildHelper.get(this.listContainer, index);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\tChildHelper.remove(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Remove from element cache\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache) {\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.delete(String(keyValue));\r\n\t\t}\r\n\r\n\t\t// Update hasItems after deletion\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will replace an item in the list.\r\n\t *\r\n\t * @protected\r\n\t * @param {object} row\r\n\t * @param {boolean} append\r\n\t * @returns {void}\r\n\t */\r\n\treplace(row, append = true)\r\n\t{\r\n\t\tif (row.status === 'unchanged')\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst item = row.item;\r\n\t\tif (row.status === 'added')\r\n\t\t{\r\n\t\t\tif (append)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.append(item);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.prepend(item);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst keyValue = item[this.key];\r\n\t\t// @ts-ignore\r\n\t\tconst index = this.findIndexByKey(keyValue);\r\n\t\tif (index === -1)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set(`items[${index}]`, item);\r\n\r\n\t\t// Find the actual DOM element by its key attribute\r\n\t\t// @ts-ignore\r\n\t\tconst oldRow = this.findRowElementByKey(keyValue);\r\n\t\t// @ts-ignore\r\n\t\tconst layout = this.row(item, index);\r\n\t\tif (oldRow && layout)\r\n\t\t{\r\n\t\t\tChildHelper.replace(layout, oldRow, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will remove items from the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array} items\r\n\t * @returns {void}\r\n\t */\r\n\tremove(items)\r\n\t{\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will get the deleted rows.\r\n\t\t */\r\n\t\tconst length = items.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = items[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.delete(item[this.key]);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after removal\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will check if the list is empty.\r\n\t *\r\n\t * @public\r\n\t * @returns {boolean}\r\n\t */\r\n\tisEmpty()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.data.get('items')?.length === 0;\r\n\t},\r\n\r\n\t/**\r\n\t * This will set the items in the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array} rows\r\n\t * @returns {void}\r\n\t */\r\n\tsetRows(rows)\r\n\t{\r\n\t\tconst safeRows = Array.isArray(rows) ? rows : [];\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('items', safeRows);\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will get the items in the list.\r\n\t *\r\n\t * @public\r\n\t * @returns {array}\r\n\t */\r\n\tgetRows()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.data.get('items') || [];\r\n\t},\r\n\r\n\t/**\r\n\t * This will reset the list.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('items', []);\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('hasItems', null);\r\n\t\t// @ts-ignore\r\n\t\tthis.hasTrailingDivider = false;\r\n\r\n\t\t// Clear element cache\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache) {\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.clear();\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.rowDivider.reset();\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will append items to the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tappend(items)\r\n\t{\r\n\t\tif (!items)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\titems = [items];\r\n\t\t}\r\n\r\n\t\titems = clone(items);\r\n\r\n\t\t/**\r\n\t\t * This will get all the new rows to be batched later.\r\n\t\t */\r\n\t\tconst rows = [];\r\n\t\t// @ts-ignore\r\n\t\tconst existingItems = this.data.get('items') || [];\r\n\t\tconst startIndex = existingItems.length;\r\n\t\tconst length = items.length;\r\n\r\n\t\t// Build rows using traditional for loop for better performance\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = items[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (this.rowDivider)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.append(item, rows);\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will build the new rows that will be appended.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = this.row(item, startIndex + i);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\trows.push(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Batch update all items at once for better performance\r\n\t\t// @ts-ignore\r\n\t\tconst newItems = existingItems.concat(items);\r\n\r\n\t\tif (existingItems.length === 0)\r\n\t\t{\r\n\t\t\t/**\r\n\t\t\t * For the initial load the for: directive must be notified so it\r\n\t\t\t * registers the items and doesn't wipe the DOM on later reactive\r\n\t\t\t * updates.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('items', newItems);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/**\r\n\t\t\t * For incremental appends (e.g. mingle adding a new row) silently\r\n\t\t\t * patch the data store so the for: directive does not re-render\r\n\t\t\t * every existing row \u2014 only the new DOM nodes are inserted below.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.attributes.items = newItems;\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.stage.items = newItems;\r\n\t\t}\r\n\r\n\t\t// Update hasItems after appending\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\r\n\t\t// This will batch push all the rows.\r\n\t\t// @ts-ignore\r\n\t\tif (rows.length > 0 && this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.append(rows, this.listContainer, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will mingle the new items with the old items.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} newItems\r\n\t * @param {boolean} withDelete\r\n\t * @returns {void}\r\n\t */\r\n\tmingle(newItems, withDelete = false)\r\n\t{\r\n\t\tif (!Array.isArray(newItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tnewItems = clone(newItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\r\n\t\t/**\r\n\t\t * This will diff the old and new items to determine what has\r\n\t\t * been added, updated, or deleted.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.diff(oldItems, newItems, this.key);\r\n\r\n\t\t/**\r\n\t\t * We want to delete the items before adding and updating the\r\n\t\t * new items.\r\n\t\t */\r\n\t\tif (withDelete && changes.deletedItems.length > 0)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.remove(changes.deletedItems);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes.changes[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after mingling\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will mingle the new items with the old items.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} newItems\r\n\t * @param {boolean} append\r\n\t * @param {boolean} deleteIfFound\r\n\t * @returns {void}\r\n\t */\r\n\tmerge(newItems, append = true, deleteIfFound = false)\r\n\t{\r\n\t\tif (!Array.isArray(newItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tnewItems = clone(newItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\r\n\t\t/**\r\n\t\t * This will diff the old and new items to determine what has\r\n\t\t * been added, updated, or deleted.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.diff(oldItems, newItems, this.key);\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes.changes[i];\r\n\t\t\tif (deleteIfFound)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.remove([row.item]);\r\n\t\t\t\trow.status = 'added';\r\n\t\t\t}\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row, append);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after mingling\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will modify existing items in the list with updated data.\r\n\t *\r\n\t * @public\r\n\t * @param {Array<Object>} updatedItems\r\n\t * @param {boolean} addMissing\r\n\t * @returns {void}\r\n\t */\r\n\tmodify(updatedItems, addMissing = false)\r\n\t{\r\n\t\tif (!Array.isArray(updatedItems))\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst updatingItems = clone(updatedItems);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = this.data.get('items') || [];\r\n\t\t// @ts-ignore\r\n\t\tconst changes = DataHelper.modify(updatingItems, oldItems, this.key, addMissing);\r\n\r\n\t\t/**\r\n\t\t * This will add or update the new rows.\r\n\t\t */\r\n\t\tconst changesLength = changes.length;\r\n\t\tfor (let i = 0; i < changesLength; i++)\r\n\t\t{\r\n\t\t\tconst row = changes[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.replace(row);\r\n\t\t}\r\n\r\n\t\t// Update hasItems after modifying\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\t},\r\n\r\n\t/**\r\n\t * This will prepend items to the list.\r\n\t *\r\n\t * @public\r\n\t * @param {array|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(items)\r\n\t{\r\n\t\tif (!items)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!Array.isArray(items))\r\n\t\t{\r\n\t\t\titems = [items];\r\n\t\t}\r\n\r\n\t\titems = clone(items);\r\n\r\n\t\t// Set the prepend boundary to the first existing item's date\r\n\t\t// @ts-ignore\r\n\t\tif (this.rowDivider)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst existingItems = this.data.get('items') || [];\r\n\t\t\tif (existingItems.length > 0)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.setPrependBoundary(existingItems[0]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Remove the first child of listContainer if it is a divider.\r\n\t\t// When prepending a new batch, the incoming rows will re-insert\r\n\t\t// the correct seam divider at the proper position. Without this,\r\n\t\t// the old seam divider ends up stranded in the middle of the\r\n\t\t// date group after new items are prepended above it.\r\n\t\t// @ts-ignore\r\n\t\tif (this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst firstChild = this.listContainer.firstChild;\r\n\t\t\tif (firstChild && firstChild.getAttribute && firstChild.getAttribute('data-divider') === 'true')\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.listContainer.removeChild(firstChild);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * This will get all the new rows to be batched later.\r\n\t\t */\r\n\t\tconst rows = [];\r\n\t\tconst reverseItems = items.reverse();\r\n\t\tconst reverseLength = reverseItems.length;\r\n\r\n\t\t// Build rows using traditional for loop for better performance\r\n\t\tfor (let i = 0; i < reverseLength; i++)\r\n\t\t{\r\n\t\t\tconst item = reverseItems[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (this.rowDivider)\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.rowDivider.prepend(item, rows);\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will build the new rows that will be prepended.\r\n\t\t\t */\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst rowElement = this.row(item, 0);\r\n\t\t\tif (rowElement)\r\n\t\t\t{\r\n\t\t\t\trows.push(rowElement);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// This will use the get method to get the items as a raw array.\r\n\t\t// @ts-ignore\r\n\t\tconst existingItems = this.data.get('items') || [];\r\n\t\tconst newItems = reverseItems.concat(existingItems);\r\n\r\n\t\t/**\r\n\t\t * This will silently add the new rows without re-rendering the entire\r\n\t\t * list. This will bypass the data object and directly add the items\r\n\t\t * to the stage.\r\n\t\t */\r\n\t\t// @ts-ignore\r\n\t\tthis.data.attributes.items = newItems;\r\n\t\t// @ts-ignore\r\n\t\tthis.data.stage.items = newItems;\r\n\r\n\t\t// Update hasItems after prepending\r\n\t\t// @ts-ignore\r\n\t\tthis.updateHasItems();\r\n\r\n\t\t// @ts-ignore\r\n\t\tif (rows.length > 0 && this.listContainer)\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.prepend(rows, this.listContainer, this);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * This will add a trailing divider after the last item in the list.\r\n\t * Useful for showing the date of the oldest items when reaching the end.\r\n\t *\r\n\t * @public\r\n\t * @returns {void}\r\n\t */\r\n\taddTrailingDivider()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (!this.rowDivider)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Prevent adding multiple trailing dividers\r\n\t\t// @ts-ignore\r\n\t\tif (this.hasTrailingDivider)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\tif (items.length === 0)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Get the first (oldest) item - items are in DESC order (newest first)\r\n\t\t// so the oldest item is at index 0\r\n\t\tconst oldestItem = items[0];\r\n\t\t// @ts-ignore\r\n\t\tconst value = this.rowDivider.getValue(oldestItem);\r\n\r\n\t\t// Route through addDivider() so the lastDividerValue dedup guard suppresses\r\n\t\t// a duplicate when the prepend loop already inserted a divider for this date.\r\n\t\tconst trailingRows = [];\r\n\t\t// @ts-ignore\r\n\t\tthis.rowDivider.addDivider(value, trailingRows);\r\n\t\t// @ts-ignore\r\n\t\tif (trailingRows.length > 0 && this.listContainer)\r\n\t\t{\r\n\t\t\t// Prepend the divider to the top of the list (before the oldest item)\r\n\t\t\t// @ts-ignore\r\n\t\t\tChildHelper.prepend(trailingRows, this.listContainer, this);\r\n\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.hasTrailingDivider = true;\r\n\t\t}\r\n\r\n\t},\r\n\r\n\t/**\r\n\t * Updates the hasItems flag based on current items length.\r\n\t *\r\n\t * @private\r\n\t * @returns {void}\r\n\t */\r\n\tupdateHasItems()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\tconst hasItems = Array.isArray(items) && items.length > 0;\r\n\t\t// @ts-ignore\r\n\t\tthis.data.set('hasItems', hasItems);\r\n\t},\r\n\r\n\t/**\r\n\t * Finds the index of an item in the data array by its key.\r\n\t *\r\n\t * @private\r\n\t * @param {*} keyValue\r\n\t * @returns {number} Index of the item, or -1 if not found\r\n\t */\r\n\tfindIndexByKey(keyValue)\r\n\t{\r\n\t\t//@ts-ignore\r\n\t\tconst items = this.data.get('items') || [];\r\n\t\t//@ts-ignore\r\n\t\treturn items.findIndex((item) => item && item[this.key] === keyValue);\r\n\t},\r\n\r\n\t/**\r\n\t * Finds a row DOM element by its key value.\r\n\t * This is more reliable than finding by index, especially after prepending\r\n\t * or when dividers are present.\r\n\t * Now uses element cache for O(1) lookups.\r\n\t *\r\n\t * @private\r\n\t * @param {*} keyValue - The key value to find\r\n\t * @returns {HTMLElement|null} The DOM element, or null if not found\r\n\t */\r\n\tfindRowElementByKey(keyValue)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (!this.listContainer)\r\n\t\t{\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tconst keyString = String(keyValue);\r\n\r\n\t\t// Try cache first for O(1) lookup\r\n\t\t// @ts-ignore\r\n\t\tif (this.elementCache && this.elementCache.has(keyString))\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst cached = this.elementCache.get(keyString);\r\n\t\t\t// Verify element is still in DOM\r\n\t\t\t// @ts-ignore\r\n\t\t\tif (cached && this.listContainer.contains(cached))\r\n\t\t\t{\r\n\t\t\t\treturn cached;\r\n\t\t\t}\r\n\t\t\t// Remove stale cache entry\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.elementCache.delete(keyString);\r\n\t\t}\r\n\r\n\t\t// Fallback to DOM search and update cache\r\n\t\t// @ts-ignore\r\n\t\tconst children = this.listContainer.children;\r\n\t\tconst childrenLength = children.length;\r\n\r\n\t\tfor (let i = 0; i < childrenLength; i++)\r\n\t\t{\r\n\t\t\tconst child = children[i];\r\n\t\t\t// Skip dividers\r\n\t\t\tif (child.hasAttribute && child.hasAttribute('data-divider'))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Check if this row has the matching key\r\n\t\t\tif (child.hasAttribute && child.getAttribute('data-row-key') === keyString)\r\n\t\t\t{\r\n\t\t\t\t// Update cache\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tif (this.elementCache)\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tthis.elementCache.set(keyString, child);\r\n\t\t\t\t}\r\n\t\t\t\treturn child;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn null;\r\n\t}\r\n});", "import { Builder, Html } from \"@base-framework/base\";\r\n\r\n/**\r\n * ChildHelper\r\n *\r\n * This class will help with getting children of a node.\r\n *\r\n * @class\r\n */\r\nexport class ChildHelper\r\n{\r\n\t/**\r\n\t * This will get the first child.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic first(parent)\r\n\t{\r\n\t\treturn this.get(parent, 0);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the last child.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic last(parent)\r\n\t{\r\n\t\tconst index = parent.childNodes.length - 1;\r\n\t\treturn this.get(parent, index);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the child at the specified index.\r\n\t *\r\n\t * @param {object} parent\r\n\t * @param {number} index\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic get(parent, index)\r\n\t{\r\n\t\treturn parent?.childNodes[index] ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the parent of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic next(node)\r\n\t{\r\n\t\treturn node?.nextSibling ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the previous sibling.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {object|null}\r\n\t */\r\n\tstatic previous(node)\r\n\t{\r\n\t\treturn node?.previousSibling ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the index of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {number}\r\n\t */\r\n\tstatic index(node)\r\n\t{\r\n\t\tif (!node || !node.parentNode)\r\n\t\t{\r\n\t\t\treturn -1; // Return -1 if node or its parent doesn't exist\r\n\t\t}\r\n\r\n\t\tconst children = node.parentNode.children;\r\n\t\treturn Array.from(children).indexOf(node);\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the previous index of the node.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {number}\r\n\t */\r\n\tstatic getPreviousIndex(node)\r\n\t{\r\n\t\tconst index = this.index(node);\r\n\t\treturn (index > 0)? index - 1 : 0;\r\n\t}\r\n\r\n\t/**\r\n\t * This will replace a child layout.\r\n\t *\r\n\t * @param {object} layout\r\n\t * @param {object} oldChild\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic replace(layout, oldChild, parent)\r\n\t{\r\n\t\tif (!oldChild)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Remove the data from the old child before\r\n\t\t * replacing it with the new child.\r\n\t\t */\r\n\t\tHtml.removeElementData(oldChild);\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst frag = Builder.build(layout, null, parent);\r\n\t\toldChild.replaceWith(frag);\r\n\t}\r\n\r\n\t/**\r\n\t * This will remove a child.\r\n\t *\r\n\t * @param {object} node\r\n\t * @returns {void}\r\n\t */\r\n\tstatic remove(node)\r\n\t{\r\n\t\tif (node)\r\n\t\t{\r\n\t\t\tHtml.removeChild(node);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * This will append a child layout.\r\n\t *\r\n\t * @param {object} childrenLayout\r\n\t * @param {object} container\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic append(childrenLayout, container, parent)\r\n\t{\r\n\t\tif (!childrenLayout)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tBuilder.build(childrenLayout, container, parent);\r\n\t}\r\n\r\n\t/**\r\n\t * This will prepend a child layout.\r\n\t *\r\n\t * @param {object} childrenLayout\r\n\t * @param {object} container\r\n\t * @param {object} parent\r\n\t * @returns {void}\r\n\t */\r\n\tstatic prepend(childrenLayout, container, parent)\r\n\t{\r\n\t\tif (!childrenLayout)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst frag = Builder.build(childrenLayout, null, parent);\r\n\t\tcontainer.insertBefore(frag, container.firstChild);\r\n\t}\r\n}", "/**\r\n * This will create a new item.\r\n *\r\n * @param {number} index\r\n * @param {*} item\r\n * @param {string} status\r\n * @returns {object}\r\n */\r\nconst Item = (index, item, status) =>\r\n{\r\n\treturn {\r\n\t\tindex,\r\n\t\titem,\r\n\t\tstatus\r\n\t};\r\n};\r\n\r\n/**\r\n * DataHelper\r\n *\r\n * This will help with data manipulation.\r\n *\r\n * @class\r\n */\r\nexport class DataHelper\r\n{\r\n\t/**\r\n\t * Compares two arrays of objects and returns the differences based on a specified key.\r\n\t *\r\n\t * @param {Array<Object>} oldArray - The original array of objects.\r\n\t * @param {Array<Object>} newArray - The updated array of objects.\r\n\t * @param {string} key - The key used to compare objects in the arrays.\r\n\t * @returns {Object} An object containing arrays of added, updated, and deleted items.\r\n\t */\r\n\tstatic diff(oldArray, newArray, key)\r\n\t{\r\n\t\tconst oldItemsMap = this.arrayToMap(oldArray, key);\r\n\t\tconst changes = [];\r\n\t\tconst deletedItems = [];\r\n\r\n\t\t// Process new array to determine status of each item\r\n\t\tconst newLength = newArray.length;\r\n\t\tfor (let i = 0; i < newLength; i++)\r\n\t\t{\r\n\t\t\tconst newItem = newArray[i];\r\n\t\t\tconst keyValue = newItem[key];\r\n\t\t\tif (!oldItemsMap.has(keyValue))\r\n\t\t\t{\r\n\t\t\t\t// Item is added\r\n\t\t\t\tchanges.push(Item(i, newItem, 'added'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst { item: oldItem } = oldItemsMap.get(keyValue);\r\n\t\t\tif (!this.deepEqual(oldItem, newItem))\r\n\t\t\t{\r\n\t\t\t\t// Item is updated\r\n\t\t\t\tchanges.push(Item(i, newItem, 'updated'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Item is unchanged\r\n\t\t\tchanges.push(Item(i, newItem, 'unchanged'));\r\n\r\n\t\t\t// Remove from oldItemsMap to identify deletions later\r\n\t\t\toldItemsMap.delete(keyValue);\r\n\t\t}\r\n\r\n\t\t// Remaining items in oldItemsMap are deleted\r\n\t\toldItemsMap.forEach(({ item: oldItem }) =>\r\n\t\t{\r\n\t\t\tdeletedItems.push(oldItem);\r\n\t\t});\r\n\r\n\t\treturn {\r\n\t\t\tchanges,\r\n\t\t\tdeletedItems\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * Modifies an array of objects by updating existing items based on a specified key.\r\n\t *\r\n\t * @param {Array<Object>} newArray - The array containing updated items.\r\n\t * @param {Array<Object>} oldArray - The original array of items.\r\n\t * @param {string} key - The key used to identify items.\r\n\t * @param {boolean} [addMissing=false] - Whether to include items that are in newArray but not in oldArray.\r\n\t * @returns {Array<Object>} An array of items that were modified or added.\r\n\t */\r\n\tstatic modify(newArray, oldArray, key, addMissing = false)\r\n\t{\r\n\t\tconst changes = [];\r\n\r\n\t\t// @ts-ignore\r\n\t\tconst oldItems = DataHelper.arrayToMap(oldArray, key);\r\n\t\tconst length = newArray.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tlet item = newArray[i];\r\n\t\t\t// @ts-ignore\r\n\t\t\tconst id = item[key] ?? null;\r\n\t\t\tif (!oldItems.has(item[id]))\r\n\t\t\t{\r\n\t\t\t\tif (!addMissing)\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tchanges.push(Item(i, item, 'added'));\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t/**\r\n\t\t\t * This will modify the existing item with new properties.\r\n\t\t\t */\r\n\t\t\tconst oldItem = oldItems.get(item[id]).item;\r\n\t\t\titem = { ...oldItem, ...item };\r\n\r\n\t\t\tchanges.push(Item(i, item, 'updated'));\r\n\t\t}\r\n\t\treturn changes;\r\n\t}\r\n\r\n\t/**\r\n\t * Converts an array of objects into a Map keyed by the specified property.\r\n\t * Each value in the Map is an object containing the item and its index in the array.\r\n\t *\r\n\t * @param {Array<Object>} array - The array to convert.\r\n\t * @param {string} key - The key used to map the objects.\r\n\t * @returns {Map} A Map with keys as specified property and values as objects.\r\n\t * @private\r\n\t */\r\n\tstatic arrayToMap(array, key)\r\n\t{\r\n\t\tconst map = new Map();\r\n\t\tconst length = array.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst item = array[i];\r\n\t\t\tmap.set(item[key], { item, index: i });\r\n\t\t}\r\n\t\treturn map;\r\n\t}\r\n\r\n\t/**\r\n\t * Performs a deep comparison between two objects.\r\n\t * Optimized with early exits for common cases.\r\n\t *\r\n\t * @param {Object} obj1 - The first object to compare.\r\n\t * @param {Object} obj2 - The second object to compare.\r\n\t * @returns {boolean} True if objects are equal, else false.\r\n\t * @private\r\n\t */\r\n\tstatic deepEqual(obj1, obj2)\r\n\t{\r\n\t\t// Fast path: identical references\r\n\t\tif (obj1 === obj2) return true;\r\n\r\n\t\t// Fast path: type check and null check\r\n\t\tif (\r\n\t\t\ttypeof obj1 !== 'object' ||\r\n\t\t\tobj1 === null ||\r\n\t\t\ttypeof obj2 !== 'object' ||\r\n\t\t\tobj2 === null\r\n\t\t)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst keys1 = Object.keys(obj1);\r\n\t\tconst keys2 = Object.keys(obj2);\r\n\r\n\t\t// Fast path: different number of properties\r\n\t\tif (keys1.length !== keys2.length)\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Optimized loop for property comparison\r\n\t\tconst length = keys1.length;\r\n\t\tfor (let i = 0; i < length; i++)\r\n\t\t{\r\n\t\t\tconst key = keys1[i];\r\n\r\n\t\t\t// Fast path: check if key exists in obj2\r\n\t\t\tif (!obj2.hasOwnProperty(key))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Recursive comparison\r\n\t\t\tif (!this.deepEqual(obj1[key], obj2[key]))\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n}", "\r\n/**\r\n * RowDivider\r\n *\r\n * This will check to add divider rows to a list based on a divider.\r\n *\r\n * @class\r\n */\r\nexport class RowDivider\r\n{\r\n\t/**\r\n\t * This will create a row divider.\r\n\t *\r\n\t * @param {object} options\r\n\t * @param {function} options.layout\r\n\t * @param {string} options.itemProperty\r\n\t * @param {function} [options.customCompare]\r\n\t * @param {boolean} [options.skipFirst=false] - Skip adding divider for the first item\r\n\t */\r\n\tconstructor({ layout, itemProperty, customCompare, skipFirst = false })\r\n\t{\r\n\t\tthis.layout = layout;\r\n\t\tthis.itemProperty = itemProperty\r\n\t\tthis.customCompare = customCompare;\r\n\t\tthis.skipFirst = skipFirst;\r\n\r\n\t\tthis.lastAppend = null;\r\n\t\tthis.lastPrepend = null;\r\n\t\t// Track the last divider value that was actually added to prevent duplicates\r\n\t\tthis.lastDividerValue = null;\r\n\t\t// Track the boundary value when prepending to avoid duplicate dividers at the boundary\r\n\t\tthis.prependBoundary = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will reset the divider.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\treset()\r\n\t{\r\n\t\tthis.lastAppend = null;\r\n\t\tthis.lastPrepend = null;\r\n\t\tthis.lastDividerValue = null;\r\n\t\tthis.prependBoundary = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set the prepend boundary to the first item's value.\r\n\t * This should be called before prepending a new batch of items.\r\n\t *\r\n\t * @param {object} firstItem\r\n\t * @returns {void}\r\n\t */\r\n\tsetPrependBoundary(firstItem)\r\n\t{\r\n\t\tif (firstItem)\r\n\t\t{\r\n\t\t\tconst value = this.getValue(firstItem);\r\n\t\t\t// Set lastPrepend so comparisons work correctly for items\r\n\t\t\t// that have the same date as the boundary\r\n\t\t\tthis.lastPrepend = value;\r\n\t\t\t// Store the boundary separately to track prepend context\r\n\t\t\tthis.prependBoundary = value;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Clear prepend boundary if no first item\r\n\t\t\tthis.prependBoundary = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * This will set the first values.\r\n\t *\r\n\t * @param {*} value\r\n\t * @returns {boolean}\r\n\t */\r\n\tsetFirstValues(value)\r\n\t{\r\n\t\tlet last = this.lastAppend;\r\n\t\tif (!last)\r\n\t\t{\r\n\t\t\tthis.lastAppend = value;\r\n\t\t\tthis.lastPrepend = value;\r\n\t\t}\r\n\t\treturn (!last);\r\n\t}\r\n\r\n\t/**\r\n\t * This will append a value.\r\n\t *\r\n\t * @param {object} item\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\tappend(item, children)\r\n\t{\r\n\t\t// Clear prepend boundary when appending (no longer prepending)\r\n\t\tthis.prependBoundary = null;\r\n\r\n\t\tconst value = this.getValue(item);\r\n\t\tconst first = this.setFirstValues(value);\r\n\r\n\t\t// Only add divider for first item if skipFirst is false\r\n\t\tif (first && !this.skipFirst)\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Skip adding divider on first item when skipFirst is true\r\n\t\tif (first)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this.compare(this.lastAppend, value))\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t}\r\n\r\n\t\t// Always update lastAppend to track the current date boundary\r\n\t\tthis.lastAppend = value;\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the value of the item.\r\n\t *\r\n\t * @param {object} item\r\n\t * @returns {*}\r\n\t */\r\n\tgetValue(item)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn item[this.itemProperty] ?? null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will prepend a value.\r\n\t *\r\n\t * @param {object} item\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(item, children)\r\n\t{\r\n\t\tconst value = this.getValue(item);\r\n\t\tconst first = this.setFirstValues(value);\r\n\r\n\t\t// Always add a divider for the first item when prepending.\r\n\t\t// skipFirst only applies to append (bottom-to-top lists).\r\n\t\tif (first)\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this.compare(this.lastPrepend, value))\r\n\t\t{\r\n\t\t\tthis.addDivider(value, children);\r\n\t\t}\r\n\r\n\t\t// Always update lastPrepend to track the current date boundary\r\n\t\tthis.lastPrepend = value;\r\n\t}\r\n\r\n\t/**\r\n\t * This will compare the values.\r\n\t *\r\n\t * @param {*} lastValue\r\n\t * @param {*} value\r\n\t * @returns {boolean}\r\n\t */\r\n\tcompare(lastValue, value)\r\n\t{\r\n\t\tif (this.customCompare)\r\n\t\t{\r\n\t\t\treturn this.customCompare(lastValue, value);\r\n\t\t}\r\n\r\n\t\treturn (lastValue !== value);\r\n\t}\r\n\r\n\t/**\r\n\t * This will add a divider layout.\r\n\t *\r\n\t * @param {*} value\r\n\t * @param {Array<object>} children\r\n\t * @returns {void}\r\n\t */\r\n\taddDivider(value, children)\r\n\t{\r\n\t\tif (!this.layout || !children)\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Avoid adding duplicate dividers for the same value as last divider\r\n\t\tif (this.lastDividerValue !== null && this.compare(this.lastDividerValue, value) === false)\r\n\t\t{\r\n\t\t\t// same value as last divider -> skip\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst layout = this.layout(value);\r\n\r\n\t\t// Mark dividers so they can be identified and skipped when finding row elements\r\n\t\tif (layout && typeof layout === 'object')\r\n\t\t{\r\n\t\t\tlayout['data-divider'] = 'true';\r\n\t\t}\r\n\r\n\t\tchildren.push(layout);\r\n\r\n\t\t// remember the last divider value we added\r\n\t\tthis.lastDividerValue = value;\r\n\t}\r\n}", "import { Atom } from \"@base-framework/base\";\r\nimport BiDirectionalContainer from \"./bi-directional-container.js\";\r\nimport { List } from \"./list.js\";\r\n\r\n/**\r\n * A ScrollableList component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {array} [props.items] - The initial items.\r\n * @property {object} [props.divider] - The row divider.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.data] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {object|null} [props.emptyState] - The empty state to show when there are no items.\r\n * @property {string} [props.cache] - The cache name to use.\r\n * @property {boolean} [props.linkParent] - Whether to link the parent data.\r\n * @returns {object}\r\n */\r\nexport const ScrollableList = Atom((props) =>\r\n{\r\n\t// @ts-ignore\r\n\tconst cache = props.cache ?? 'list';\r\n\treturn BiDirectionalContainer(\r\n\t\t{\r\n\t\t\tlistCache: cache,\r\n\t\t\t// @ts-ignore\r\n\t\t\tscrollDirection: props.scrollDirection || 'down',\r\n\t\t\t// @ts-ignore\r\n\t\t\tscrollContainer: props.scrollContainer,\r\n\t\t\t// @ts-ignore\r\n\t\t\tloadMoreItems: props.loadMoreItems,\r\n\t\t\t// @ts-ignore\r\n\t\t\toffset: props.offset,\r\n\t\t\t// @ts-ignore\r\n\t\t\tlimit: props.limit,\r\n\t\t\t// @ts-ignore\r\n\t\t\tcontainerClass: props.containerClass ?? 'flex flex-auto flex-col',\r\n\t\t\t// @ts-ignore\r\n\t\t\tdata: props.data\r\n\t\t},\r\n\t\t[\r\n\t\t\tnew List({\r\n\t\t\t\tcache,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tkey: props.key,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\titems: props.items || [],\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tdivider: props.divider,\r\n\t\t\t\trole: 'list',\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tclass: props.class,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\temptyState: props.emptyState || null,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\trowItem: props.rowItem,\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tlinkParent: props.linkParent ?? false,\r\n\t\t\t\tisDynamic: true\r\n\t\t\t})\r\n\t\t]\r\n\t);\r\n});\r\n\r\nexport default ScrollableList;", "import { Component, router } from '@base-framework/base';\r\n\r\n/**\r\n * Watcher\r\n *\r\n * This will create a watcher object.\r\n *\r\n * @param {string} attr\r\n * @param {string} value\r\n * @returns {object}\r\n */\r\nconst Watcher = (attr, value) => ({\r\n\tattr,\r\n\tvalue\r\n});\r\n\r\n/**\r\n * This will check if the path is active.\r\n *\r\n * @param {string} path\r\n * @param {string} url\r\n * @returns {boolean}\r\n */\r\nconst iSActive = (path, url) => new RegExp('^' + path + '($|#|/|\\\\.).*').test(url);\r\n\r\n/**\r\n * NavLink\r\n *\r\n * This will create a nav link that will add an active\r\n * class when the browser route path matches the link\r\n * href.\r\n *\r\n * @property {string} activeClass - The active class to add.\r\n * @property {string} class - The class\r\n * @property {string} exact - The exact match\r\n * @property {string|object} href - The href or watcher object\r\n * @property {string|object} text - The text or watcher object\r\n * @property {array|string} nest - The nested elements\r\n *\r\n * @class\r\n * @extends Component\r\n */\r\nexport class NavLink extends Component\r\n{\r\n /**\r\n * This will configure the link active class.\r\n *\r\n * @protected\r\n * @returns {void}\r\n */\r\n beforeSetup()\r\n {\r\n // @ts-ignore\r\n this.selectedClass = this.activeClass || 'active';\r\n }\r\n\r\n /**\r\n * This will render the component.\r\n *\r\n * @returns {object}\r\n */\r\n render()\r\n {\r\n // @ts-ignore\r\n const href = this.href,\r\n // @ts-ignore\r\n text = this.text,\r\n watchers = this.setupWatchers(href, text);\r\n\r\n return {\r\n tag: 'a',\r\n // @ts-ignore\r\n class: this.class || this.className || null,\r\n onState: ['selected', {\r\n [this.selectedClass]: true\r\n }],\r\n href: this.getString(href),\r\n text: this.getString(text),\r\n // @ts-ignore\r\n nest: this.nest || this.children,\r\n // @ts-ignore\r\n dataSet: this.dataSet,\r\n watch: watchers\r\n };\r\n }\r\n\r\n /**\r\n * This will get the link path.\r\n *\r\n * @returns {string|null}\r\n */\r\n getLinkPath()\r\n {\r\n // @ts-ignore\r\n return this?.panel?.pathname || null;\r\n }\r\n\r\n /**\r\n * This will get string.\r\n *\r\n * @param {string} string\r\n * @returns {(string|null)}\r\n */\r\n getString(string)\r\n {\r\n const type = typeof string;\r\n return (type !== 'object' && type !== 'undefined')? string : null;\r\n }\r\n\r\n /**\r\n * This will setup the watchers.\r\n *\r\n * @protected\r\n * @param {string} href\r\n * @param {string} text\r\n * @returns {array}\r\n */\r\n setupWatchers(href, text)\r\n {\r\n // @ts-ignore\r\n const exact = (this.exact === true),\r\n data = router.data;\r\n\r\n const watchers = [];\r\n\r\n if (href && typeof href === 'object')\r\n {\r\n watchers.push(Watcher('href', href));\r\n }\r\n\r\n if (text && typeof text === 'object')\r\n {\r\n watchers.push(Watcher('text', text));\r\n }\r\n\r\n watchers.push({\r\n value: ['[[path]]', data],\r\n callBack: (value, ele) =>\r\n {\r\n const path = ele.pathname + ele.hash;\r\n\t\t\t\tconst selected = exact? (value === path) : (iSActive(ele.pathname, value));\r\n this.update(selected);\r\n }\r\n });\r\n\r\n return watchers;\r\n }\r\n\r\n /**\r\n * This will setup the states.\r\n *\r\n * @protected\r\n * @returns {object}\r\n */\r\n setupStates()\r\n {\r\n return {\r\n selected: false\r\n };\r\n }\r\n\r\n /**\r\n * This will update the class on the element.\r\n *\r\n * @param {boolean} selected\r\n * @returns {void}\r\n */\r\n update(selected)\r\n {\r\n // @ts-ignore\r\n this.state.selected = selected;\r\n }\r\n}", "import { Tbody } from '@base-framework/atoms';\r\nimport { PaginationTracker } from '../lists/pagination-tracker.js';\r\nimport { fetchAndRefresh, setupFetchCallback } from '../lists/scroll-utils.js';\r\nimport { TableBody } from './table-body.js';\r\n\r\n/**\r\n * A DataTableBody component that handles data fetching and rendering for a table body.\r\n *\r\n * @param {object} props\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {Array<object>} [props.items] - The initial items.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.tableData] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n *\r\n * @class DataTableBody\r\n * @extends TableBody\r\n */\r\nexport class DataTableBody extends TableBody\r\n{\r\n\t/**\r\n\t * This will declare the component props.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tdeclareProps()\r\n\t{\r\n\t\t/**\r\n\t\t * @member {PaginationTracker}\r\n\t\t */\r\n\t\tthis.tracker = null;\r\n\r\n\t\t/**\r\n\t\t * @member {function}\r\n\t\t */\r\n\t\tthis.fetchCallback = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the page tracker.\r\n\t *\r\n\t * @returns {PaginationTracker}\r\n\t */\r\n\tsetupPageTracker()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.tracker = new PaginationTracker(this.offset, this.limit);\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the fetch callback.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tsetupFetchCallback()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tthis.setupPageTracker();\r\n\t\t// @ts-ignore\r\n\t\tthis.fetchCallback = this.loadMoreItems || setupFetchCallback(this.tableData);\r\n\t}\r\n\r\n\t/**\r\n\t * This will refresh the list.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\trefresh()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tfetchAndRefresh(this.fetchCallback, this.tracker, this);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\t\t// @ts-ignore\r\n\t\tthis.setupFetchCallback();\r\n\r\n\t\treturn Tbody({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated: (ele, parent) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\t\t\t\tthis.refresh();\r\n\t\t\t},\r\n\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};\r\n\r\nexport default DataTableBody;", "import { Tbody } from '@base-framework/atoms';\r\nimport { Data } from '@base-framework/base';\r\nimport { List } from '../lists/list.js';\r\nimport { SkeletonTableRow } from './skeleton-table-row.js';\r\n\r\n/**\r\n * TableBody\r\n *\r\n * This will create a table body component with skeleton support.\r\n *\r\n * @param {object} props\r\n * @property {string} class - The class to add to the list\r\n * @property {string} key - The key to use to identify the items\r\n * @property {Array<object>} [items] - The items\r\n * @property {boolean|object} [skeleton] - Skeleton configuration. Can be true for default or object with { number: 5, row: customRowFunction }\r\n * @property {number} [columnCount] - Number of columns for skeleton rows (auto-detected from headers if not provided)\r\n *\r\n * @class TableBody\r\n * @extends List\r\n */\r\n// @ts-ignore\r\nexport class TableBody extends List\r\n{\r\n\t/**\r\n\t * This will set the default data.\r\n\t *\r\n\t * @returns {Data}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst hasItems = this.items && this.items.length > 0;\r\n\t\t// @ts-ignore\r\n\t\tconst isSkeletonEnabled = this.skeleton && !hasItems;\r\n\t\tif (isSkeletonEnabled)\r\n\t\t{\r\n\t\t\t// Create new data with skeleton properties\r\n\t\t\treturn new Data({\r\n\t\t\t\titems: this.generateSkeletonRows(),\r\n\t\t\t\thasItems: true, // Show skeleton as if we have items\r\n\t\t\t\tshowSkeleton: true\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t// @ts-ignore\r\n\t\treturn super.setData();\r\n\t}\r\n\r\n\t/**\r\n\t * Generates skeleton rows for the table.\r\n\t *\r\n\t * @returns {Array<object>}\r\n\t */\r\n\tgenerateSkeletonRows()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst skeletonConfig = this.skeleton;\r\n\r\n\t\t// Default skeleton configuration\r\n\t\tlet skeletonCount = 5;\r\n\t\tlet customRowFunction = null;\r\n\r\n\t\t// Handle skeleton configuration\r\n\t\tif (typeof skeletonConfig === 'object')\r\n\t\t{\r\n\t\t\tskeletonCount = skeletonConfig.number || 5;\r\n\t\t\tcustomRowFunction = skeletonConfig.row || null;\r\n\t\t}\r\n\r\n\t\t// Calculate column count from columnCount prop or default to 3\r\n\t\t// @ts-ignore\r\n\t\tconst columnCount = this.columnCount || 3;\r\n\r\n\t\t// Generate skeleton rows\r\n\t\treturn Array.from({ length: skeletonCount }, (_, index) =>\r\n\t\t{\r\n\t\t\tif (customRowFunction && typeof customRowFunction === 'function')\r\n\t\t\t{\r\n\t\t\t\treturn customRowFunction(index, columnCount);\r\n\t\t\t}\r\n\r\n\t\t\treturn SkeletonTableRow({\r\n\t\t\t\tcolumnCount,\r\n\t\t\t\tkey: `skeleton-${index}`\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Removes skeleton rows and shows real content.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tremoveSkeleton()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tif (this.data.get('showSkeleton'))\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('showSkeleton', false);\r\n\t\t\t// @ts-ignore\r\n\t\t\tthis.data.set('items', this.items || []);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Override setRows to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>} rows\r\n\t * @returns {void}\r\n\t */\r\n\tsetRows(rows)\r\n\t{\r\n\t\t// Remove skeleton when setting real rows\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.setRows(rows);\r\n\t}\r\n\r\n\t/**\r\n\t * Override append to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tappend(items)\r\n\t{\r\n\t\t// Remove skeleton when appending real items\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.append(items);\r\n\t}\r\n\r\n\t/**\r\n\t * Override prepend to remove skeleton when real data arrives\r\n\t *\r\n\t * @param {Array<object>|object} items\r\n\t * @returns {void}\r\n\t */\r\n\tprepend(items)\r\n\t{\r\n\t\t// Remove skeleton when prepending real items\r\n\t\tthis.removeSkeleton();\r\n\t\t// @ts-ignore\r\n\t\tsuper.prepend(items);\r\n\t}\r\n\r\n\t/**\r\n\t * This will create a row for each item.\r\n\t * Override to handle skeleton items differently from real data items.\r\n\t *\r\n\t * @param {*} item\r\n\t * @param {*} index\r\n\t * @param {*} scope\r\n\t * @param {*} children\r\n\t * @returns {object|null}\r\n\t */\r\n\trow(item, index, scope, children)\r\n\t{\r\n\t\t// If this is a skeleton item (already a component), return it directly\r\n\t\t// @ts-ignore\r\n\t\tif (this.data && this.data.get('showSkeleton'))\r\n\t\t{\r\n\t\t\treturn item;\r\n\t\t}\r\n\r\n\t\t// For real data items, use the normal row processing\r\n\t\t// @ts-ignore\r\n\t\treturn super.row(item, index, scope, children);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\r\n\t\treturn Tbody({\r\n\t\t\tonCreated: (ele) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\t\t\t},\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};", "import { Div, Td, Tr } from '@base-framework/atoms';\r\n\r\n/**\r\n * Creates a skeleton table row with animated placeholders.\r\n *\r\n * @param {object} props\r\n * @param {number} [props.columnCount=3] - Number of columns to create skeleton cells for\r\n * @param {function} [props.customCell] - Custom function to render skeleton cells\r\n * @param {string} [props.key] - Unique key for the row\r\n * @returns {object}\r\n */\r\nexport const SkeletonTableRow = ({ columnCount = 3, customCell, key }) =>\r\n{\r\n\tconst createSkeletonCell = (index) =>\r\n\t{\r\n\t\tif (customCell && typeof customCell === 'function')\r\n\t\t{\r\n\t\t\treturn customCell(index);\r\n\t\t}\r\n\r\n\t\t// Default skeleton cell with varying widths for more realistic appearance\r\n\t\tconst widths = ['w-3/4', 'w-1/2', 'w-full', 'w-2/3', 'w-5/6'];\r\n\t\tconst width = widths[index % widths.length];\r\n\r\n\t\treturn Td({ class: 'px-6 py-4' }, [\r\n\t\t\tDiv({\r\n\t\t\t\tclass: `${width} h-4 bg-muted animate-pulse rounded-md`\r\n\t\t\t})\r\n\t\t]);\r\n\t};\r\n\r\n\treturn Tr({\r\n\t\tclass: 'border-b',\r\n\t\tkey\r\n\t}, Array.from({ length: columnCount }, (_, index) => createSkeletonCell(index)));\r\n};\r\n\r\nexport default SkeletonTableRow;\r\n", "import { Tbody } from '@base-framework/atoms';\r\nimport { PaginationTracker } from '../lists/pagination-tracker.js';\r\nimport { createTableScrollHandler, fetchAndRefresh, setupFetchCallback } from '../lists/scroll-utils.js';\r\nimport { TableBody } from './table-body.js';\r\n\r\n/**\r\n * A ScrollableTableBody component that updates when its container is scrolled.\r\n *\r\n * @param {object} props\r\n * @property {HTMLElement} [props.scrollContainer] - The container element for scroll events. Defaults to globalThis.\r\n * @property {function} [props.loadMoreItems] - A function to fetch/generate additional items.\r\n * @property {number} [props.offset] - The initial offset. Defaults to 0.\r\n * @property {number} [props.limit] - Number of items to load per batch. Defaults to 20.\r\n * @property {string} [props.class] - The class to add to the list.\r\n * @property {string} [props.key] - The key to use to identify the items.\r\n * @property {Array<object>} [props.items] - The initial items.\r\n * @property {function} [props.rowItem] - The row item.\r\n * @property {object} [props.tableData] - The data object containing the xhr method.\r\n * @property {string} [props.containerClass] - The class to add to the scroll container.\r\n * @property {boolean|object} [props.skeleton] - Skeleton configuration. Can be true for default or object with { number: 5, row: customRowFunction }\r\n * @property {number} [props.columnCount] - Number of columns for skeleton rows\r\n *\r\n * @class ScrollableTableBody\r\n * @extends TableBody\r\n */\r\nexport class ScrollableTableBody extends TableBody\r\n{\r\n\t/**\r\n\t * This will declare the component props.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tdeclareProps()\r\n\t{\r\n\t\t/**\r\n\t\t * @member {PaginationTracker}\r\n\t\t */\r\n\t\tthis.tracker = null;\r\n\r\n\t\t/**\r\n\t\t * @member {HTMLElement}\r\n\t\t * @default globalThis\r\n\t\t */\r\n\t\tthis.scrollContainer = null;\r\n\r\n\t\t/**\r\n\t\t * @member {function}\r\n\t\t */\r\n\t\tthis.fetchCallback = null;\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the page tracker.\r\n\t *\r\n\t * @returns {PaginationTracker}\r\n\t */\r\n\tsetupPageTracker()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\treturn this.tracker = new PaginationTracker(this.offset, this.limit);\r\n\t}\r\n\r\n\t/**\r\n\t * This will set up the scroll handler.\r\n\t *\r\n\t * @param {HTMLElement} container\r\n\t * @returns {Function}\r\n\t */\r\n\tsetupScrollHandler(container)\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst tracker = this.setupPageTracker();\r\n\t\t// @ts-ignore\r\n\t\tthis.fetchCallback = this.loadMoreItems || setupFetchCallback(this.tableData);\r\n\r\n\t\t/**\r\n\t\t * This will handle the scroll event.\r\n\t\t *\r\n\t\t * @param {object|null} e\r\n\t\t * @param {object} parent\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\treturn createTableScrollHandler(container, tracker, this.fetchCallback);\r\n\t}\r\n\r\n\t/**\r\n\t * This will refresh the list.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\trefresh()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tfetchAndRefresh(this.fetchCallback, this.tracker, this);\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the list.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst rowCallBack = this.row.bind(this);\r\n\t\t// @ts-ignore\r\n\t\tconst container = this.scrollContainer || globalThis;\r\n\r\n\t\t/**\r\n\t\t * This will handle the scroll event.\r\n\t\t *\r\n\t\t * @param {object|null} e\r\n\t\t * @param {object} parent\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tconst handleScroll = this.setupScrollHandler(container);\r\n\r\n\t\treturn Tbody({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: `tbody ${this.class || ''}`,\r\n\r\n\t\t\t/**\r\n\t\t\t * This will request to update the list when the atom is created.\r\n\t\t\t *\r\n\t\t\t * @param {object} ele\r\n\t\t\t * @param {object} parent\r\n\t\t\t * @returns {void}\r\n\t\t\t */\r\n\t\t\tonCreated: (ele, parent) =>\r\n\t\t\t{\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tthis.cacheEle(ele, 'listContainer');\r\n\r\n\t\t\t\thandleScroll(null, parent, () =>\r\n\t\t\t\t{\r\n\t\t\t\t\t// @ts-ignore\r\n\t\t\t\t\tthis.reset();\r\n\t\t\t\t});\r\n\t\t\t},\r\n\r\n\t\t\t/**\r\n\t\t\t * This will add the scroll event to the container.\r\n\t\t\t */\r\n\t\t\taddEvent: ['scroll', container, handleScroll, { passive: true }],\r\n\r\n\t\t\tfor: ['items', rowCallBack]\r\n\t\t});\r\n\t}\r\n};\r\n\r\nexport default ScrollableTableBody;", "import { Span } from \"@base-framework/atoms\";\r\nimport { Component, SimpleData } from \"@base-framework/base\";\r\nimport { IntervalTimer } from \"../utils/timer/interval-timer.js\";\r\n\r\n/**\r\n * This will create a simple flat data object to use to bind\r\n * timer update. This will be used to update the time every\r\n * minute.\r\n *\r\n * This data will be bound to all the dynamic time elements.\r\n *\r\n * @constant\r\n * @type {SimpleData} data\r\n */\r\nconst data = new SimpleData({\r\n\tdate: 0\r\n});\r\n\r\n/**\r\n * @constant\r\n * @type {number} MINUTE_INTERVAL\r\n */\r\nconst MINUTE_INTERVAL = 60000;\r\n\r\n/**\r\n * This will update the the data value every minute.\r\n *\r\n * @constant\r\n * @type {IntervalTimer} timer\r\n */\r\nconst timer = new IntervalTimer(MINUTE_INTERVAL, () =>\r\n{\r\n\tdata.increment('date');\r\n});\r\n\r\n/**\r\n * This will start the timer to update any dynamic time\r\n * elements.\r\n */\r\ntimer.start();\r\n\r\n/**\r\n * DynamicTime\r\n *\r\n * This will create a dynamic time element that will update\r\n * the time every minute.\r\n *\r\n * @property {string} dateTime - The date time to display.\r\n * @property {function} [filter] - The filter to apply to the date time.\r\n *\r\n * @class\r\n * @augments Component\r\n */\r\nexport class DynamicTime extends Component\r\n{\r\n\t/**\r\n\t * This will set up the component data with the\r\n\t * data created above.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\tsetData()\r\n\t{\r\n\t\treturn data;\r\n\t}\r\n\r\n\t/**\r\n\t * This will render the component.\r\n\t *\r\n\t * @returns {object}\r\n\t */\r\n\trender()\r\n\t{\r\n\t\treturn Span({\r\n\t\t\t// @ts-ignore\r\n\t\t\tclass: this.class,\r\n\t\t\ttext: this.getTime(),\r\n\t\t\tonSet: ['date', () => this.getTime()]\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * This will get the date and check to filter the value.\r\n\t *\r\n\t * @returns {string}\r\n\t */\r\n\tgetTime()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tconst dateTime = this.dateTime;\r\n\t\t// @ts-ignore\r\n\t\treturn (this.filter) ? this.filter(dateTime) : dateTime;\r\n\t}\r\n}", "/**\r\n * Timer\r\n *\r\n * This will create a timer that will call a callback function.\r\n *\r\n * @property {number} duration - The duration of the timer.\r\n * @property {function} callBack - The callback function.\r\n *\r\n * @class\r\n */\r\nexport class Timer\r\n{\r\n\t/**\r\n\t * This will create a new timer.\r\n\t *\r\n\t * @param {number} duration\r\n\t * @param {function} callBack\r\n\t */\r\n\tconstructor(duration, callBack)\r\n\t{\r\n\t\t/**\r\n\t\t * @property {number|null} timer\r\n\t\t */\r\n\t\tthis.timer = null;\r\n\r\n\t\t/**\r\n\t\t * @property {function} callBack\r\n\t\t */\r\n\t\tthis.callBack = callBack;\r\n\r\n\t\t/**\r\n\t\t * @property {number} duration\r\n\t\t */\r\n\t\tthis.duration = duration || 1000;\r\n\t}\r\n\r\n\t/**\r\n\t * This will create a timer.\r\n\t *\r\n\t * @protected\r\n\t * @param {function} callBack\r\n\t * @returns {void}\r\n\t */\r\n\tcreateTimer(callBack)\r\n\t{\r\n\t\tthis.timer = globalThis.setTimeout(callBack, this.duration);\r\n\t}\r\n\r\n\t/**\r\n\t * This will start the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstart()\r\n\t{\r\n\t\t/**\r\n\t\t * This will stop the timer before starting a new one.\r\n\t\t */\r\n\t\tthis.stop();\r\n\r\n\t\tconst callBack = this.returnCallBack.bind(this);\r\n\t\tthis.createTimer(callBack);\r\n\t}\r\n\r\n\t/**\r\n\t * This will stop the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstop()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tglobalThis.clearTimeout(this.timer);\r\n\t}\r\n\r\n\t/**\r\n\t * This will call the callback function.\r\n\t *\r\n\t * @private\r\n\t * @returns {void}\r\n\t */\r\n\treturnCallBack()\r\n\t{\r\n\t\tconst callBack = this.callBack;\r\n\t\tif (typeof callBack === 'function')\r\n\t\t{\r\n\t\t\t// @ts-ignore\r\n\t\t\tcallBack.call();\r\n\t\t}\r\n\t}\r\n}", "import { Timer } from './timer.js';\r\n\r\n/**\r\n * IntervalTimer\r\n *\r\n * This will create a timer that will call a callback function.\r\n *\r\n * @class\r\n */\r\nexport class IntervalTimer extends Timer\r\n{\r\n\t/**\r\n\t * This will create a timer.\r\n\t *\r\n\t * @protected\r\n\t * @param {function} callBack\r\n\t * @returns {void}\r\n\t */\r\n\tcreateTimer(callBack)\r\n\t{\r\n\t\tthis.timer = globalThis.setInterval(callBack, this.duration);\r\n\t}\r\n\r\n\t/**\r\n\t * This will stop the timer.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tstop()\r\n\t{\r\n\t\t// @ts-ignore\r\n\t\tglobalThis.clearInterval(this.timer);\r\n\t}\r\n}"],
5
+ "mappings": "AAAA,OAAS,OAAAA,MAAW,wBACpB,OAAS,QAAAC,OAAY,uBCMd,IAAMC,EAAN,KACP,CAOC,YAAYC,EAAS,EAAGC,EAAQ,GAChC,CAEC,KAAK,WAAa,KAClB,KAAK,cAAgBD,EACrB,KAAK,MAAQC,EACb,KAAK,YAAc,GACnB,KAAK,QAAU,GAGf,KAAK,SAAW,KAChB,KAAK,aAAe,GACpB,KAAK,aAAe,EACrB,CAOA,aACA,CACC,OAAO,KAAK,WACb,CAOA,cACA,CACC,OAAO,KAAK,cAAgB,KAAK,WAAa,IAC/C,CASA,OAAOC,EAAUC,EAAa,KAC9B,CACKD,EAAW,KAAK,QAEnB,KAAK,YAAc,IAGpB,KAAK,WAAaC,EAClB,KAAK,eAAiBD,CACvB,CAQA,aAAaE,EACb,CACC,KAAK,SAAWA,EAChB,KAAK,aAAeA,IAAa,IAClC,CAOA,OACA,CACC,KAAK,WAAa,KAClB,KAAK,cAAgB,EACrB,KAAK,YAAc,GACnB,KAAK,QAAU,GACf,KAAK,SAAW,KAChB,KAAK,aAAe,GACpB,KAAK,aAAe,EACrB,CACD,EC5FA,IAAMC,EAAmB,IASlB,SAASC,EAAYC,EAC5B,CACC,GAAI,CAACA,GAAQA,EAAK,SAAW,EAE5B,OAAO,KAGR,IAAMC,EAAYD,EAAK,CAAC,EAClBE,EAAWF,EAAKA,EAAK,OAAS,CAAC,EAGrC,OAAIC,GAAW,IAAMC,GAAU,GAIvBD,EAAU,GAAKC,EAAS,GAAKD,EAAU,GAAKC,EAAS,GAIzDD,GAAW,GAEPA,EAAU,GAGdC,GAAU,GAENA,EAAS,GAGV,IACR,CAQO,SAASC,EAAiBC,EACjC,CAEC,IAAMC,EAAYD,IAAc,WAAa,WAAW,YAAcA,EAAU,UAE1EE,EAAeF,IAAc,WAAa,WAAW,YAAcA,EAAU,aAE7EG,EAAeH,IAAc,WAAa,WAAW,SAAS,gBAAgB,aAAeA,EAAU,aAC7G,MAAO,CAAE,UAAAC,EAAW,aAAAC,EAAc,aAAAC,CAAa,CAChD,CASO,SAASC,EAAeC,EAASC,EAAYZ,EACpD,CACC,OAAOW,EAAQ,UAAYA,EAAQ,cAAgBA,EAAQ,aAAeC,CAC3E,CASO,SAASC,EAAgBF,EAASC,EAAYZ,EACrD,CACC,OAAOW,EAAQ,WAAaC,CAC7B,CASO,IAAME,EAAU,CAACH,EAASI,IAEzBL,EAAeC,CAAO,GAAKI,EAAQ,YAAY,EAU1CC,EAAe,CAACL,EAASI,IAE9BF,EAAgBF,CAAO,GAAKI,EAAQ,YAAY,EAY3CE,EAAa,CAACf,EAAMa,EAASG,EAAMC,EAAa,OAC7D,CACKjB,GAAQA,EAAK,OAAS,GAEzBgB,EAAK,OAAOhB,CAAI,EAChBa,EAAQ,OAAOb,EAAK,OAAQiB,CAAU,IAItCJ,EAAQ,YAAc,GACtBG,EAAK,KAAK,IAAI,WAAY,EAAK,EAEjC,EAcaE,EAAkB,CAAClB,EAAMa,EAASG,EAAMC,EAAa,KAAMb,EAAY,OACpF,CACC,GAAIJ,GAAQA,EAAK,OAAS,EAC1B,CAEC,IAAIO,EAAe,EACfF,EAAY,EAEhB,GAAID,EACJ,CACC,IAAMK,EAAUN,EAAiBC,CAAS,EAC1CG,EAAeE,EAAQ,aACvBJ,EAAYI,EAAQ,SACrB,CAmBA,GAhBAO,EAAK,QAAQhB,CAAI,EACjBa,EAAQ,OAAOb,EAAK,OAAQiB,CAAU,EAGlCjB,EAAK,OAASa,EAAQ,QAEzBA,EAAQ,YAAc,GAGlBG,EAAK,oBAERA,EAAK,mBAAmB,GAKtBZ,EACJ,CAGC,IAAMe,EADahB,EAAiBC,CAAS,EACT,aAAeG,EAG/CH,IAAc,WAEjB,WAAW,SAAS,EAAGC,EAAYc,CAAgB,EAKnDf,EAAU,UAAYC,EAAYc,CAEpC,CACD,MAGCN,EAAQ,YAAc,GACtBG,EAAK,KAAK,IAAI,WAAY,EAAK,EAG3BA,EAAK,oBAERA,EAAK,mBAAmB,CAG3B,EA8BO,IAAMI,EAAsBC,GAE3B,CAACC,EAASC,IACjB,CAOC,IAAMC,EAAkBC,GACxB,CACC,IAAIC,EAAO,CAAC,EACRC,EAAa,KACbF,IAEHC,EAAOD,EAAS,MAAQA,EAAS,OAAS,CAAC,EAC3CE,EAAaF,EAAS,YAAc,MAErCF,EAASG,EAAMC,CAAU,CAC1B,EAEAN,EAAK,IAAI,IAAI,GAAIG,EAAgBF,EAAQ,cAAeA,EAAQ,MAAOA,EAAQ,UAAU,CAC1F,EAUYM,EAA2BP,GAEhC,CAACC,EAASC,IACjB,CAOC,IAAMC,EAAkBC,GACxB,CACC,IAAIC,EAAO,CAAC,EACRG,EAAW,KACXJ,IAEHC,EAAOD,EAAS,MAAQA,EAAS,OAAS,CAAC,EAC3CI,EAAWC,EAAYJ,CAAI,GAE5BH,EAASG,EAAMG,CAAQ,CACxB,EAGAR,EAAK,IAAI,IAAI,GAAIG,EAAgB,EAAGF,EAAQ,MAAO,KAAMA,EAAQ,QAAQ,CAC1E,EA2BM,IAAMS,EAAkB,CAACC,EAAeC,EAASC,IACxD,CACCD,EAAQ,MAAM,EACdD,EAAcC,EAAS,CAACE,EAAMC,IAC9B,CACCF,EAAK,MAAM,EACXG,EAAWF,EAAMF,EAASC,EAAME,CAAU,EAG1C,IAAME,EAAWC,EAAYJ,CAAI,EAC7BG,IAAa,MAEhBL,EAAQ,aAAaK,CAAQ,CAE/B,CAAC,CACF,EA4CO,IAAME,EAAsB,CAACC,EAAWC,EAASC,EAAeC,EAAY,OAAQC,EAAY,SACvG,CACC,IAAMC,EAAcF,IAAc,KAAOG,EAAeC,EAClDC,EAAgBL,IAAc,KAEpC,MAAO,CAACM,EAAGC,EAAQC,IACnB,CACC,IAAMC,EAAOF,EAAON,CAAS,EACvBS,EAAUC,EAAiBd,CAAS,EAC1C,GAAIK,EAAYQ,EAASZ,CAAO,EAChC,CAEC,GAAIA,EAAQ,QAEX,OAGDA,EAAQ,QAAU,GAClBC,EAAcD,EAAS,CAACc,EAAMC,IAC9B,CACKL,GAEHA,EAAS,EAIV,IAAMM,EAAgBhB,EAAQ,gBAAkB,EAGhD,GAAIO,GAMH,GAHAU,EAAgBH,EAAMd,EAASW,EAAMI,EAAYhB,CAAS,EAGtDiB,EACJ,CACC,IAAME,EAAWC,EAAYL,CAAI,EAC7BI,IAAa,MAEhBlB,EAAQ,aAAakB,CAAQ,CAE/B,OAIAE,EAAWN,EAAMd,EAASW,EAAMI,CAAU,EAG3Cf,EAAQ,QAAU,EACnB,CAAC,CACF,CACD,CACD,EAaaqB,EAA2B,CAACtB,EAAWC,EAASC,IAErD,CAACO,EAAGG,EAAMD,IACjB,CACC,IAAME,EAAUC,EAAiBd,CAAS,EAC1C,GAAIO,EAAQM,EAASZ,CAAO,EAC5B,CAEC,GAAIA,EAAQ,QAEX,OAGDA,EAAQ,QAAU,GAClBC,EAAcD,EAAS,CAACc,EAAMC,IAC9B,CACKL,GAEHA,EAAS,EAGVU,EAAWN,EAAMd,EAASW,EAAMI,CAAU,EAC1Cf,EAAQ,QAAU,EACnB,CAAC,CACF,CACD,EFxcD,IAAMsB,GAAqB,CAACC,EAAeC,EAASC,IAE5C,IACP,CACCC,EAAgBH,EAAeC,EAASC,CAAI,CAC7C,EAWKE,GAAmB,CAACJ,EAAeC,EAASI,EAAQC,IAC1D,CACCD,EAAOC,CAAS,EAAE,QAAUP,GAAmBC,EAAeC,EAASI,EAAOC,CAAS,CAAC,CACzF,EA8FaC,EAAyBC,GAAK,CAACC,EAAOC,IACnD,CAEC,IAAMT,EAAU,IAAIU,EAAkBF,EAAM,OAAQA,EAAM,KAAK,EAEzDG,EAAYH,EAAM,iBAAmB,WAErCI,EAAkBJ,EAAM,iBAAmB,OAE3CT,EAAgBS,EAAM,eAAiBK,EAAmBL,EAAM,IAAI,EAEpEM,EAAqBN,EAAM,gBAAkBO,EAAwBP,EAAM,IAAI,EAW/EQ,EAAeC,EAAoBN,EAAWX,EAASD,EAAea,EAAiBJ,EAAM,SAAS,EAE5G,OAAOU,EACN,CAEC,MAAOV,EAAM,gBAAkB,GAS/B,UAAUW,EAAKf,EACf,CAKCD,GAAiBJ,EAAeC,EAASI,EAAQI,EAAM,SAAS,EAKhEQ,EAAa,KAAMZ,EAAQ,IAC3B,CAEC,IAAMH,EAAOG,EAAOI,EAAM,SAAS,EAInC,GAHAP,EAAK,MAAM,EAGPW,IAAoB,KACxB,CAEC,IAAMQ,EAAQnB,EAAK,MAAM,OAASA,EAAK,MAAM,MAAQ,CAAC,EACtD,GAAID,EAAQ,WAAa,KACzB,CACC,IAAMqB,EAAWC,EAAYF,CAAK,EAC9BC,IAAa,MAEhBrB,EAAQ,aAAaqB,CAAQ,CAE/B,CAEApB,EAAK,eAAe,CACrB,CACD,CAAC,EAGD,IAAMA,EAAOG,EAAOI,EAAM,SAAS,EASnCP,EAAK,SAAW,CAACsB,EAAe,KAChC,CAGMvB,EAAQ,eAEZA,EAAQ,aAAe,GACvBc,EAAmBd,EAAS,CAACwB,EAAMH,IACnC,CACKG,GAAQA,EAAK,OAAS,IAGrBZ,IAAoB,KAIvBX,EAAK,OAAOuB,CAAI,EAMhBvB,EAAK,QAAQuB,CAAI,EAIdH,IAAa,MAEhBrB,EAAQ,aAAaqB,CAAQ,GAG/BrB,EAAQ,aAAe,GAEnBuB,GAAgBX,IAAoB,MAEvCX,EAAK,eAAe,CAEtB,CAAC,EAEH,EAOAA,EAAK,eAAiB,IACtB,CACCA,EAAK,QAAQ,IACb,CACC,GAAIU,IAAc,WAClB,CACC,IAAMc,EAAe,WAAW,SAAS,gBAAgB,aACzD,WAAW,SAAS,EAAGA,CAAY,EACnC,MACD,CAGAd,EAAU,UAAYA,EAAU,YACjC,CAAC,CACF,CACD,EAKA,SAAU,CAAC,SAAUA,EAAWK,EAAc,CAAE,QAAS,EAAK,CAAC,CAChE,EACAP,CACD,CACD,CAAC,EAEMiB,EAAQpB,EGvRf,OAAS,QAAAqB,OAAY,uBCArB,OAAS,OAAAC,OAAW,wBACpB,OAAS,QAAAC,OAAY,uBAYrB,IAAMC,GAAqB,CAACC,EAAeC,EAASC,IAE5C,IACP,CACCC,EAAgBH,EAAeC,EAASC,CAAI,CAC7C,EAWKE,GAAmB,CAACJ,EAAeC,EAASI,EAAQC,IAC1D,CACCD,EAAOC,CAAS,EAAE,QAAUP,GAAmBC,EAAeC,EAASI,EAAOC,CAAS,CAAC,CACzF,EAeaC,GAAgBC,GAAK,CAACC,EAAOC,IAC1C,CAEC,IAAMT,EAAU,IAAIU,EAAkBF,EAAM,OAAQA,EAAM,KAAK,EAEzDT,EAAgBS,EAAM,eAAiBG,EAAmBH,EAAM,IAAI,EAE1E,OAAOI,GACN,CAEC,MAAOJ,EAAM,gBAAkB,GAS/B,UAAUK,EAAKT,EACf,CAKCD,GAAiBJ,EAAeC,EAASI,EAAQI,EAAM,SAAS,EAGhEJ,EAAOI,EAAM,SAAS,EAAE,QAAQ,CACjC,CACD,EACAC,CACD,CACD,CAAC,EAEMK,EAAQR,GClFf,OAAS,OAAAS,EAAK,MAAAC,OAAU,wBACxB,OAAS,aAAAC,GAAW,QAAAC,GAAM,OAAAC,OAAW,uBCDrC,OAAS,WAAAC,EAAS,QAAAC,MAAY,uBASvB,IAAMC,EAAN,KACP,CAOC,OAAO,MAAMC,EACb,CACC,OAAO,KAAK,IAAIA,EAAQ,CAAC,CAC1B,CAQA,OAAO,KAAKA,EACZ,CACC,IAAMC,EAAQD,EAAO,WAAW,OAAS,EACzC,OAAO,KAAK,IAAIA,EAAQC,CAAK,CAC9B,CASA,OAAO,IAAID,EAAQC,EACnB,CACC,OAAOD,GAAQ,WAAWC,CAAK,GAAK,IACrC,CAQA,OAAO,KAAKC,EACZ,CACC,OAAOA,GAAM,aAAe,IAC7B,CAQA,OAAO,SAASA,EAChB,CACC,OAAOA,GAAM,iBAAmB,IACjC,CAQA,OAAO,MAAMA,EACb,CACC,GAAI,CAACA,GAAQ,CAACA,EAAK,WAElB,MAAO,GAGR,IAAMC,EAAWD,EAAK,WAAW,SACjC,OAAO,MAAM,KAAKC,CAAQ,EAAE,QAAQD,CAAI,CACzC,CAQA,OAAO,iBAAiBA,EACxB,CACC,IAAMD,EAAQ,KAAK,MAAMC,CAAI,EAC7B,OAAQD,EAAQ,EAAIA,EAAQ,EAAI,CACjC,CAUA,OAAO,QAAQG,EAAQC,EAAUL,EACjC,CACC,GAAI,CAACK,EAEJ,OAODP,EAAK,kBAAkBO,CAAQ,EAG/B,IAAMC,EAAOT,EAAQ,MAAMO,EAAQ,KAAMJ,CAAM,EAC/CK,EAAS,YAAYC,CAAI,CAC1B,CAQA,OAAO,OAAOJ,EACd,CACKA,GAEHJ,EAAK,YAAYI,CAAI,CAEvB,CAUA,OAAO,OAAOK,EAAgBC,EAAWR,EACzC,CACMO,GAKLV,EAAQ,MAAMU,EAAgBC,EAAWR,CAAM,CAChD,CAUA,OAAO,QAAQO,EAAgBC,EAAWR,EAC1C,CACC,GAAI,CAACO,EAEJ,OAID,IAAMD,EAAOT,EAAQ,MAAMU,EAAgB,KAAMP,CAAM,EACvDQ,EAAU,aAAaF,EAAME,EAAU,UAAU,CAClD,CACD,ECtKA,IAAMC,EAAO,CAACC,EAAOC,EAAMC,KAEnB,CACN,MAAAF,EACA,KAAAC,EACA,OAAAC,CACD,GAUYC,EAAN,MAAMC,CACb,CASC,OAAO,KAAKC,EAAUC,EAAUC,EAChC,CACC,IAAMC,EAAc,KAAK,WAAWH,EAAUE,CAAG,EAC3CE,EAAU,CAAC,EACXC,EAAe,CAAC,EAGhBC,EAAYL,EAAS,OAC3B,QAASM,EAAI,EAAGA,EAAID,EAAWC,IAC/B,CACC,IAAMC,EAAUP,EAASM,CAAC,EACpBE,EAAWD,EAAQN,CAAG,EAC5B,GAAI,CAACC,EAAY,IAAIM,CAAQ,EAC7B,CAECL,EAAQ,KAAKV,EAAKa,EAAGC,EAAS,OAAO,CAAC,EACtC,QACD,CAEA,GAAM,CAAE,KAAME,CAAQ,EAAIP,EAAY,IAAIM,CAAQ,EAClD,GAAI,CAAC,KAAK,UAAUC,EAASF,CAAO,EACpC,CAECJ,EAAQ,KAAKV,EAAKa,EAAGC,EAAS,SAAS,CAAC,EACxC,QACD,CAGAJ,EAAQ,KAAKV,EAAKa,EAAGC,EAAS,WAAW,CAAC,EAG1CL,EAAY,OAAOM,CAAQ,CAC5B,CAGA,OAAAN,EAAY,QAAQ,CAAC,CAAE,KAAMO,CAAQ,IACrC,CACCL,EAAa,KAAKK,CAAO,CAC1B,CAAC,EAEM,CACN,QAAAN,EACA,aAAAC,CACD,CACD,CAWA,OAAO,OAAOJ,EAAUD,EAAUE,EAAKS,EAAa,GACpD,CACC,IAAMP,EAAU,CAAC,EAGXQ,EAAWb,EAAW,WAAWC,EAAUE,CAAG,EAC9CW,EAASZ,EAAS,OACxB,QAASM,EAAI,EAAGA,EAAIM,EAAQN,IAC5B,CACC,IAAIX,EAAOK,EAASM,CAAC,EAEfO,EAAKlB,EAAKM,CAAG,GAAK,KACxB,GAAI,CAACU,EAAS,IAAIhB,EAAKkB,CAAE,CAAC,EAC1B,CACC,GAAI,CAACH,EAEJ,SAGDP,EAAQ,KAAKV,EAAKa,EAAGX,EAAM,OAAO,CAAC,EACnC,QACD,CAMAA,EAAO,CAAE,GADOgB,EAAS,IAAIhB,EAAKkB,CAAE,CAAC,EAAE,KAClB,GAAGlB,CAAK,EAE7BQ,EAAQ,KAAKV,EAAKa,EAAGX,EAAM,SAAS,CAAC,CACtC,CACA,OAAOQ,CACR,CAWA,OAAO,WAAWW,EAAOb,EACzB,CACC,IAAMc,EAAM,IAAI,IACVH,EAASE,EAAM,OACrB,QAASR,EAAI,EAAGA,EAAIM,EAAQN,IAC5B,CACC,IAAMX,EAAOmB,EAAMR,CAAC,EACpBS,EAAI,IAAIpB,EAAKM,CAAG,EAAG,CAAE,KAAAN,EAAM,MAAOW,CAAE,CAAC,CACtC,CACA,OAAOS,CACR,CAWA,OAAO,UAAUC,EAAMC,EACvB,CAEC,GAAID,IAASC,EAAM,MAAO,GAG1B,GACC,OAAOD,GAAS,UAChBA,IAAS,MACT,OAAOC,GAAS,UAChBA,IAAS,KAGT,MAAO,GAGR,IAAMC,EAAQ,OAAO,KAAKF,CAAI,EACxBG,EAAQ,OAAO,KAAKF,CAAI,EAG9B,GAAIC,EAAM,SAAWC,EAAM,OAE1B,MAAO,GAIR,IAAMP,EAASM,EAAM,OACrB,QAASZ,EAAI,EAAGA,EAAIM,EAAQN,IAC5B,CACC,IAAML,EAAMiB,EAAMZ,CAAC,EASnB,GANI,CAACW,EAAK,eAAehB,CAAG,GAMxB,CAAC,KAAK,UAAUe,EAAKf,CAAG,EAAGgB,EAAKhB,CAAG,CAAC,EAEvC,MAAO,EAET,CAEA,MAAO,EACR,CACD,EC/LO,IAAMmB,EAAN,KACP,CAUC,YAAY,CAAE,OAAAC,EAAQ,aAAAC,EAAc,cAAAC,EAAe,UAAAC,EAAY,EAAM,EACrE,CACC,KAAK,OAASH,EACd,KAAK,aAAeC,EACpB,KAAK,cAAgBC,EACrB,KAAK,UAAYC,EAEjB,KAAK,WAAa,KAClB,KAAK,YAAc,KAEnB,KAAK,iBAAmB,KAExB,KAAK,gBAAkB,IACxB,CAOA,OACA,CACC,KAAK,WAAa,KAClB,KAAK,YAAc,KACnB,KAAK,iBAAmB,KACxB,KAAK,gBAAkB,IACxB,CASA,mBAAmBC,EACnB,CACC,GAAIA,EACJ,CACC,IAAMC,EAAQ,KAAK,SAASD,CAAS,EAGrC,KAAK,YAAcC,EAEnB,KAAK,gBAAkBA,CACxB,MAIC,KAAK,gBAAkB,IAEzB,CAQA,eAAeA,EACf,CACC,IAAIC,EAAO,KAAK,WAChB,OAAKA,IAEJ,KAAK,WAAaD,EAClB,KAAK,YAAcA,GAEZ,CAACC,CACV,CASA,OAAOC,EAAMC,EACb,CAEC,KAAK,gBAAkB,KAEvB,IAAMH,EAAQ,KAAK,SAASE,CAAI,EAC1BE,EAAQ,KAAK,eAAeJ,CAAK,EAGvC,GAAII,GAAS,CAAC,KAAK,UACnB,CACC,KAAK,WAAWJ,EAAOG,CAAQ,EAC/B,MACD,CAGIC,IAKA,KAAK,QAAQ,KAAK,WAAYJ,CAAK,GAEtC,KAAK,WAAWA,EAAOG,CAAQ,EAIhC,KAAK,WAAaH,EACnB,CAQA,SAASE,EACT,CAEC,OAAOA,EAAK,KAAK,YAAY,GAAK,IACnC,CASA,QAAQA,EAAMC,EACd,CACC,IAAMH,EAAQ,KAAK,SAASE,CAAI,EAKhC,GAJc,KAAK,eAAeF,CAAK,EAKvC,CACC,KAAK,WAAWA,EAAOG,CAAQ,EAC/B,MACD,CAEI,KAAK,QAAQ,KAAK,YAAaH,CAAK,GAEvC,KAAK,WAAWA,EAAOG,CAAQ,EAIhC,KAAK,YAAcH,CACpB,CASA,QAAQK,EAAWL,EACnB,CACC,OAAI,KAAK,cAED,KAAK,cAAcK,EAAWL,CAAK,EAGnCK,IAAcL,CACvB,CASA,WAAWA,EAAOG,EAClB,CAOC,GANI,CAAC,KAAK,QAAU,CAACA,GAMjB,KAAK,mBAAqB,MAAQ,KAAK,QAAQ,KAAK,iBAAkBH,CAAK,IAAM,GAGpF,OAGD,IAAML,EAAS,KAAK,OAAOK,CAAK,EAG5BL,GAAU,OAAOA,GAAW,WAE/BA,EAAO,cAAc,EAAI,QAG1BQ,EAAS,KAAKR,CAAM,EAGpB,KAAK,iBAAmBK,CACzB,CACD,EH7MA,IAAMM,EAASC,GACV,MAAM,QAAQA,CAAI,EACdA,EAAK,IAAIC,GACXA,GAAQ,OAAOA,GAAS,SACpB,CAAE,GAAGA,CAAK,EAEXA,CACP,EAEKD,EAqBKE,EAAOC,GACpB,CAMC,WACA,CAEK,KAAK,UAGR,KAAK,WAAa,IAAIC,EAAW,CAAE,GAAG,KAAK,OAAQ,CAAC,GAKrD,KAAK,aAAe,IAAI,GACzB,EAOA,SACA,CAEC,IAAMC,EAAS,KAAK,MAASN,EAAM,KAAK,KAAK,EAAI,CAAC,EAElD,OAAO,IAAIO,GAAK,CACf,MAAAD,EACA,SAAU,IACX,CAAC,CACF,EAOA,QACA,CAEC,KAAK,cAAc,CACpB,EAQA,eACA,CAGC,GAAI,KAAK,oBACT,CAEC,KAAK,KAAK,IAAI,WAAY,EAAI,EAC9B,MACD,CAGA,IAAIE,EAAc,KAAK,eAAe,EAElCC,EAAWD,GAAe,KAC9B,GAAIA,IAAgB,OAOnB,GAAIA,IAAgB,GAEnBC,EAAW,OAGZ,CAEC,IAAMH,EAAQ,KAAK,OAAS,CAAC,EAE7BG,EAAY,MAAM,QAAQH,CAAK,GAAKA,EAAM,OAAS,CACpD,CAID,KAAK,oBAAsBG,CAC5B,EAQA,gBACA,CACC,IAAID,EAAc,GAEZE,EAAa,KAAK,QAAQ,MAAQ,KAAK,QAAQ,SAAS,MAAQ,KAEtE,GAAIA,GAAc,KAAK,aAAe,GAErCF,EAAcE,EAAW,IAAI,UAAU,EAEvC,KAAK,KAAK,KAAKA,EAAY,UAAU,UAG7B,KAAK,YAAc,GAE3B,OAED,OAAOF,CACR,EAQA,oBACA,CAEC,GAAI,KAAK,sBAAwB,GAEhC,QAIa,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,GAIZ,OAAS,GAAK,KAAK,UAAY,KAI3D,KAAK,oBAAsB,GAE7B,EAQA,SACA,CAEC,KAAK,mBAAmB,EAIxB,KAAK,KAAK,SAAW,KAAK,mBAC3B,EAOA,QACA,CAEC,IAAMG,EAAc,KAAK,IAAI,KAAK,IAAI,EAEtC,OAAOC,EAAI,CAAE,MAAO,yBAA0B,EAAG,CAChDC,GAAG,WAAaJ,GAGPA,IAAa,IAAS,KAAK,WAAa,KAAK,WAAW,EAAI,IACpE,EACDG,EAAI,CACH,MAAO,gBAEP,MAAO,QAAQ,KAAK,OAAS,EAAE,GAC/B,MAAO,CAAC,WAAY,CAAE,OAAQ,EAAM,CAAC,EACrC,IAAK,CAAC,QAASD,CAAW,CAC3B,CAAC,CACF,CAAC,CACF,EAWA,IAAIT,EAAMY,EAAOC,EAAOC,EACxB,CAEC,GAAI,OAAO,KAAK,SAAY,WAE3B,OAAO,KAMJ,KAAK,YAAcA,GAAY,KAAK,YAAc,IAGrD,KAAK,WAAW,OAAOd,EAAMc,CAAQ,EAItC,IAAMC,EAAY,KAAK,QAAQf,EAAMY,CAAK,EAK1C,GAAIG,GAAa,KAAK,KAAOf,EAAK,KAAK,GAAG,IAAM,OAChD,CAEC,IAAMgB,EAAW,OAAOhB,EAAK,KAAK,GAAG,CAAC,EAItC,GAAIe,aAAqBE,IAAa,CAACF,EAAU,IAMhD,OAJgBL,EAAI,CACnB,eAAgBM,CACjB,EAAG,CAACD,CAAS,CAAC,EAOfA,EAAU,cAAc,EAAIC,CAC7B,CAEA,OAAOD,CACR,EASA,OAAOC,EACP,CAEC,IAAMJ,EAAQ,KAAK,eAAeI,CAAQ,EAC1C,GAAIJ,IAAU,GAQd,IAFA,KAAK,KAAK,OAAO,SAASA,CAAK,GAAG,EAE9B,KAAK,cACT,CAEC,IAAMM,EAAaC,EAAY,IAAI,KAAK,cAAeP,CAAK,EACxDM,GAEHC,EAAY,OAAOD,CAAU,CAE/B,CAII,KAAK,cAER,KAAK,aAAa,OAAO,OAAOF,CAAQ,CAAC,EAK1C,KAAK,eAAe,EACrB,EAUA,QAAQI,EAAKC,EAAS,GACtB,CACC,GAAID,EAAI,SAAW,YAElB,OAID,IAAMpB,EAAOoB,EAAI,KACjB,GAAIA,EAAI,SAAW,QACnB,CACC,GAAIC,EACJ,CAEC,KAAK,OAAOrB,CAAI,EAChB,MACD,CAGA,KAAK,QAAQA,CAAI,EACjB,MACD,CAGA,IAAMgB,EAAWhB,EAAK,KAAK,GAAG,EAExBY,EAAQ,KAAK,eAAeI,CAAQ,EAC1C,GAAIJ,IAAU,GAEb,OAID,KAAK,KAAK,IAAI,SAASA,CAAK,IAAKZ,CAAI,EAIrC,IAAMsB,EAAS,KAAK,oBAAoBN,CAAQ,EAE1CO,EAAS,KAAK,IAAIvB,EAAMY,CAAK,EAC/BU,GAAUC,GAEbJ,EAAY,QAAQI,EAAQD,EAAQ,IAAI,CAE1C,EASA,OAAOlB,EACP,CACC,GAAI,CAAC,MAAM,QAAQA,CAAK,EAEvB,OAMD,IAAMoB,EAASpB,EAAM,OACrB,QAASqB,EAAI,EAAGA,EAAID,EAAQC,IAC5B,CACC,IAAMzB,EAAOI,EAAMqB,CAAC,EAEpB,KAAK,OAAOzB,EAAK,KAAK,GAAG,CAAC,CAC3B,CAIA,KAAK,eAAe,CACrB,EAQA,SACA,CAEC,OAAO,KAAK,KAAK,IAAI,OAAO,GAAG,SAAW,CAC3C,EASA,QAAQ0B,EACR,CACC,IAAMC,EAAW,MAAM,QAAQD,CAAI,EAAIA,EAAO,CAAC,EAE/C,KAAK,KAAK,IAAI,QAASC,CAAQ,EAE/B,KAAK,eAAe,CACrB,EAQA,SACA,CAEC,OAAO,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,CACnC,EAQA,OACA,CAEC,KAAK,KAAK,IAAI,QAAS,CAAC,CAAC,EAEzB,KAAK,KAAK,IAAI,WAAY,IAAI,EAE9B,KAAK,mBAAqB,GAItB,KAAK,cAER,KAAK,aAAa,MAAM,EAIrB,KAAK,YAGR,KAAK,WAAW,MAAM,CAExB,EASA,OAAOvB,EACP,CACC,GAAI,CAACA,EAEJ,OAGI,MAAM,QAAQA,CAAK,IAEvBA,EAAQ,CAACA,CAAK,GAGfA,EAAQN,EAAMM,CAAK,EAKnB,IAAMsB,EAAO,CAAC,EAERE,EAAgB,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAC3CC,EAAaD,EAAc,OAC3BJ,EAASpB,EAAM,OAGrB,QAASqB,EAAI,EAAGA,EAAID,EAAQC,IAC5B,CACC,IAAMzB,EAAOI,EAAMqB,CAAC,EAEhB,KAAK,YAGR,KAAK,WAAW,OAAOzB,EAAM0B,CAAI,EAOlC,IAAMR,EAAa,KAAK,IAAIlB,EAAM6B,EAAaJ,CAAC,EAC5CP,GAEHQ,EAAK,KAAKR,CAAU,CAEtB,CAIA,IAAMY,EAAWF,EAAc,OAAOxB,CAAK,EAEvCwB,EAAc,SAAW,EAQ5B,KAAK,KAAK,IAAI,QAASE,CAAQ,GAU/B,KAAK,KAAK,WAAW,MAAQA,EAE7B,KAAK,KAAK,MAAM,MAAQA,GAKzB,KAAK,eAAe,EAIhBJ,EAAK,OAAS,GAAK,KAAK,eAG3BP,EAAY,OAAOO,EAAM,KAAK,cAAe,IAAI,CAEnD,EAUA,OAAOI,EAAUC,EAAa,GAC9B,CACC,GAAI,CAAC,MAAM,QAAQD,CAAQ,EAE1B,OAGDA,EAAWhC,EAAMgC,CAAQ,EAGzB,IAAME,EAAW,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAOtCC,EAAUC,EAAW,KAAKF,EAAUF,EAAU,KAAK,GAAG,EAMxDC,GAAcE,EAAQ,aAAa,OAAS,GAG/C,KAAK,OAAOA,EAAQ,YAAY,EAMjC,IAAME,EAAgBF,EAAQ,QAAQ,OACtC,QAASR,EAAI,EAAGA,EAAIU,EAAeV,IACnC,CACC,IAAML,EAAMa,EAAQ,QAAQR,CAAC,EAE7B,KAAK,QAAQL,CAAG,CACjB,CAIA,KAAK,eAAe,CACrB,EAWA,MAAMU,EAAUT,EAAS,GAAMe,EAAgB,GAC/C,CACC,GAAI,CAAC,MAAM,QAAQN,CAAQ,EAE1B,OAGDA,EAAWhC,EAAMgC,CAAQ,EAGzB,IAAME,EAAW,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAOtCC,EAAUC,EAAW,KAAKF,EAAUF,EAAU,KAAK,GAAG,EAKtDK,EAAgBF,EAAQ,QAAQ,OACtC,QAASR,EAAI,EAAGA,EAAIU,EAAeV,IACnC,CACC,IAAML,EAAMa,EAAQ,QAAQR,CAAC,EACzBW,IAGH,KAAK,OAAO,CAAChB,EAAI,IAAI,CAAC,EACtBA,EAAI,OAAS,SAId,KAAK,QAAQA,EAAKC,CAAM,CACzB,CAIA,KAAK,eAAe,CACrB,EAUA,OAAOgB,EAAcC,EAAa,GAClC,CACC,GAAI,CAAC,MAAM,QAAQD,CAAY,EAE9B,OAID,IAAME,EAAgBzC,EAAMuC,CAAY,EAGlCL,EAAW,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAEtCC,EAAUC,EAAW,OAAOK,EAAeP,EAAU,KAAK,IAAKM,CAAU,EAKzEH,EAAgBF,EAAQ,OAC9B,QAASR,EAAI,EAAGA,EAAIU,EAAeV,IACnC,CACC,IAAML,EAAMa,EAAQR,CAAC,EAErB,KAAK,QAAQL,CAAG,CACjB,CAIA,KAAK,eAAe,CACrB,EASA,QAAQhB,EACR,CACC,GAAI,CAACA,EAEJ,OAYD,GATK,MAAM,QAAQA,CAAK,IAEvBA,EAAQ,CAACA,CAAK,GAGfA,EAAQN,EAAMM,CAAK,EAIf,KAAK,WACT,CAEC,IAAMwB,EAAgB,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAC7CA,EAAc,OAAS,GAG1B,KAAK,WAAW,mBAAmBA,EAAc,CAAC,CAAC,CAErD,CAQA,GAAI,KAAK,cACT,CAEC,IAAMY,EAAa,KAAK,cAAc,WAClCA,GAAcA,EAAW,cAAgBA,EAAW,aAAa,cAAc,IAAM,QAGxF,KAAK,cAAc,YAAYA,CAAU,CAE3C,CAKA,IAAMd,EAAO,CAAC,EACRe,EAAerC,EAAM,QAAQ,EAC7BsC,EAAgBD,EAAa,OAGnC,QAAShB,EAAI,EAAGA,EAAIiB,EAAejB,IACnC,CACC,IAAMzB,EAAOyC,EAAahB,CAAC,EAEvB,KAAK,YAGR,KAAK,WAAW,QAAQzB,EAAM0B,CAAI,EAOnC,IAAMR,EAAa,KAAK,IAAIlB,EAAM,CAAC,EAC/BkB,GAEHQ,EAAK,KAAKR,CAAU,CAEtB,CAIA,IAAMU,EAAgB,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EAC3CE,EAAWW,EAAa,OAAOb,CAAa,EAQlD,KAAK,KAAK,WAAW,MAAQE,EAE7B,KAAK,KAAK,MAAM,MAAQA,EAIxB,KAAK,eAAe,EAGhBJ,EAAK,OAAS,GAAK,KAAK,eAG3BP,EAAY,QAAQO,EAAM,KAAK,cAAe,IAAI,CAEpD,EASA,oBACA,CASC,GAPI,CAAC,KAAK,YAON,KAAK,mBAER,OAID,IAAMtB,EAAQ,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EACzC,GAAIA,EAAM,SAAW,EAEpB,OAKD,IAAMuC,EAAavC,EAAM,CAAC,EAEpBwC,EAAQ,KAAK,WAAW,SAASD,CAAU,EAI3CE,EAAe,CAAC,EAEtB,KAAK,WAAW,WAAWD,EAAOC,CAAY,EAE1CA,EAAa,OAAS,GAAK,KAAK,gBAInC1B,EAAY,QAAQ0B,EAAc,KAAK,cAAe,IAAI,EAG1D,KAAK,mBAAqB,GAG5B,EAQA,gBACA,CAEC,IAAMzC,EAAQ,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EACnCG,EAAW,MAAM,QAAQH,CAAK,GAAKA,EAAM,OAAS,EAExD,KAAK,KAAK,IAAI,WAAYG,CAAQ,CACnC,EASA,eAAeS,EACf,CAIC,OAFc,KAAK,KAAK,IAAI,OAAO,GAAK,CAAC,GAE5B,UAAWhB,GAASA,GAAQA,EAAK,KAAK,GAAG,IAAMgB,CAAQ,CACrE,EAYA,oBAAoBA,EACpB,CAEC,GAAI,CAAC,KAAK,cAET,OAAO,KAGR,IAAM8B,EAAY,OAAO9B,CAAQ,EAIjC,GAAI,KAAK,cAAgB,KAAK,aAAa,IAAI8B,CAAS,EACxD,CAEC,IAAMC,EAAS,KAAK,aAAa,IAAID,CAAS,EAG9C,GAAIC,GAAU,KAAK,cAAc,SAASA,CAAM,EAE/C,OAAOA,EAIR,KAAK,aAAa,OAAOD,CAAS,CACnC,CAIA,IAAMhC,EAAW,KAAK,cAAc,SAC9BkC,EAAiBlC,EAAS,OAEhC,QAASW,EAAI,EAAGA,EAAIuB,EAAgBvB,IACpC,CACC,IAAMwB,EAAQnC,EAASW,CAAC,EAExB,GAAI,EAAAwB,EAAM,cAAgBA,EAAM,aAAa,cAAc,IAMvDA,EAAM,cAAgBA,EAAM,aAAa,cAAc,IAAMH,EAIhE,OAAI,KAAK,cAGR,KAAK,aAAa,IAAIA,EAAWG,CAAK,EAEhCA,CAET,CAEA,OAAO,IACR,CACD,CAAC,EFz7BM,IAAMC,GAAWC,GAAMC,GAC9B,CAEC,IAAMC,EAAQD,EAAM,OAAS,OAC7B,OAAOE,EACN,CACC,UAAWD,EAEX,cAAeD,EAAM,cAErB,OAAQA,EAAM,OAEd,MAAOA,EAAM,MAEb,eAAgBA,EAAM,gBAAkB,GAExC,KAAMA,EAAM,IACb,EACA,CACC,IAAIG,EAAK,CACR,MAAAF,EAEA,IAAKD,EAAM,IAEX,MAAOA,EAAM,OAAS,CAAC,EAEvB,QAASA,EAAM,QACf,KAAM,OAEN,MAAOA,EAAM,MAEb,QAASA,EAAM,OAChB,CAAC,CACF,CACD,CACD,CAAC,EMxDD,OAAS,QAAAI,OAAY,uBAwBd,IAAMC,GAAiBC,GAAMC,GACpC,CAEC,IAAMC,EAAQD,EAAM,OAAS,OAC7B,OAAOE,EACN,CACC,UAAWD,EAEX,gBAAiBD,EAAM,iBAAmB,OAE1C,gBAAiBA,EAAM,gBAEvB,cAAeA,EAAM,cAErB,OAAQA,EAAM,OAEd,MAAOA,EAAM,MAEb,eAAgBA,EAAM,gBAAkB,0BAExC,KAAMA,EAAM,IACb,EACA,CACC,IAAIG,EAAK,CACR,MAAAF,EAEA,IAAKD,EAAM,IAEX,MAAOA,EAAM,OAAS,CAAC,EAEvB,QAASA,EAAM,QACf,KAAM,OAEN,MAAOA,EAAM,MAEb,WAAYA,EAAM,YAAc,KAEhC,QAASA,EAAM,QAEf,WAAYA,EAAM,YAAc,GAChC,UAAW,EACZ,CAAC,CACF,CACD,CACD,CAAC,ECpED,OAAS,aAAAI,GAAW,UAAAC,OAAc,uBAWlC,IAAMC,EAAU,CAACC,EAAMC,KAAW,CACjC,KAAAD,EACA,MAAAC,CACD,GASMC,GAAW,CAACC,EAAMC,IAAQ,IAAI,OAAO,IAAMD,EAAO,eAAe,EAAE,KAAKC,CAAG,EAmBpEC,EAAN,cAAsBR,EAC7B,CAOI,aACA,CAEI,KAAK,cAAgB,KAAK,aAAe,QAC7C,CAOA,QACA,CAEI,IAAMS,EAAO,KAAK,KAElBC,EAAO,KAAK,KACZC,EAAW,KAAK,cAAcF,EAAMC,CAAI,EAExC,MAAO,CACH,IAAK,IAEL,MAAO,KAAK,OAAS,KAAK,WAAa,KACvC,QAAS,CAAC,WAAY,CAClB,CAAC,KAAK,aAAa,EAAG,EAC1B,CAAC,EACD,KAAM,KAAK,UAAUD,CAAI,EACzB,KAAM,KAAK,UAAUC,CAAI,EAEzB,KAAM,KAAK,MAAQ,KAAK,SAExB,QAAS,KAAK,QACd,MAAOC,CACX,CACJ,CAOA,aACA,CAEI,OAAO,MAAM,OAAO,UAAY,IACpC,CAQA,UAAUC,EACV,CACI,IAAMC,EAAO,OAAOD,EACpB,OAAQC,IAAS,UAAYA,IAAS,YAAcD,EAAS,IACjE,CAUA,cAAcH,EAAMC,EACpB,CAEI,IAAMI,EAAS,KAAK,QAAU,GAC9BC,EAAOd,GAAO,KAERU,EAAW,CAAC,EAElB,OAAIF,GAAQ,OAAOA,GAAS,UAExBE,EAAS,KAAKT,EAAQ,OAAQO,CAAI,CAAC,EAGnCC,GAAQ,OAAOA,GAAS,UAExBC,EAAS,KAAKT,EAAQ,OAAQQ,CAAI,CAAC,EAGvCC,EAAS,KAAK,CACV,MAAO,CAAC,WAAYI,CAAI,EACxB,SAAU,CAACX,EAAOY,IAClB,CACI,IAAMV,EAAOU,EAAI,SAAWA,EAAI,KACtCC,EAAWH,EAAQV,IAAUE,EAASD,GAASW,EAAI,SAAUZ,CAAK,EAC5D,KAAK,OAAOa,CAAQ,CACxB,CACJ,CAAC,EAEMN,CACX,CAQA,aACA,CACI,MAAO,CACH,SAAU,EACd,CACJ,CAQA,OAAOM,EACP,CAEI,KAAK,MAAM,SAAWA,CAC1B,CACJ,EC5KA,OAAS,SAAAC,OAAa,wBCAtB,OAAS,SAAAC,OAAa,wBACtB,OAAS,QAAAC,OAAY,uBCDrB,OAAS,OAAAC,GAAK,MAAAC,GAAI,MAAAC,OAAU,wBAWrB,IAAMC,EAAmB,CAAC,CAAE,YAAAC,EAAc,EAAG,WAAAC,EAAY,IAAAC,CAAI,IACpE,CACC,IAAMC,EAAsBC,GAC5B,CACC,GAAIH,GAAc,OAAOA,GAAe,WAEvC,OAAOA,EAAWG,CAAK,EAIxB,IAAMC,EAAS,CAAC,QAAS,QAAS,SAAU,QAAS,OAAO,EACtDC,EAAQD,EAAOD,EAAQC,EAAO,MAAM,EAE1C,OAAOR,GAAG,CAAE,MAAO,WAAY,EAAG,CACjCD,GAAI,CACH,MAAO,GAAGU,CAAK,wCAChB,CAAC,CACF,CAAC,CACF,EAEA,OAAOR,GAAG,CACT,MAAO,WACP,IAAAI,CACD,EAAG,MAAM,KAAK,CAAE,OAAQF,CAAY,EAAG,CAACO,EAAGH,IAAUD,EAAmBC,CAAK,CAAC,CAAC,CAChF,EDdO,IAAMI,EAAN,cAAwBC,CAC/B,CAMC,SACA,CAEC,IAAMC,EAAW,KAAK,OAAS,KAAK,MAAM,OAAS,EAGnD,OAD0B,KAAK,UAAY,CAACA,EAIpC,IAAIC,GAAK,CACf,MAAO,KAAK,qBAAqB,EACjC,SAAU,GACV,aAAc,EACf,CAAC,EAIK,MAAM,QAAQ,CACtB,CAOA,sBACA,CAEC,IAAMC,EAAiB,KAAK,SAGxBC,EAAgB,EAChBC,EAAoB,KAGpB,OAAOF,GAAmB,WAE7BC,EAAgBD,EAAe,QAAU,EACzCE,EAAoBF,EAAe,KAAO,MAK3C,IAAMG,EAAc,KAAK,aAAe,EAGxC,OAAO,MAAM,KAAK,CAAE,OAAQF,CAAc,EAAG,CAACG,EAAGC,IAE5CH,GAAqB,OAAOA,GAAsB,WAE9CA,EAAkBG,EAAOF,CAAW,EAGrCG,EAAiB,CACvB,YAAAH,EACA,IAAK,YAAYE,CAAK,EACvB,CAAC,CACD,CACF,CAOA,gBACA,CAEK,KAAK,KAAK,IAAI,cAAc,IAG/B,KAAK,KAAK,IAAI,eAAgB,EAAK,EAEnC,KAAK,KAAK,IAAI,QAAS,KAAK,OAAS,CAAC,CAAC,EAEzC,CAQA,QAAQE,EACR,CAEC,KAAK,eAAe,EAEpB,MAAM,QAAQA,CAAI,CACnB,CAQA,OAAOC,EACP,CAEC,KAAK,eAAe,EAEpB,MAAM,OAAOA,CAAK,CACnB,CAQA,QAAQA,EACR,CAEC,KAAK,eAAe,EAEpB,MAAM,QAAQA,CAAK,CACpB,CAYA,IAAIC,EAAMJ,EAAOK,EAAOC,EACxB,CAGC,OAAI,KAAK,MAAQ,KAAK,KAAK,IAAI,cAAc,EAErCF,EAKD,MAAM,IAAIA,EAAMJ,EAAOK,EAAOC,CAAQ,CAC9C,CAOA,QACA,CAEC,IAAMC,EAAc,KAAK,IAAI,KAAK,IAAI,EAEtC,OAAOC,GAAM,CACZ,UAAYC,GACZ,CAEC,KAAK,SAASA,EAAK,eAAe,CACnC,EAEA,MAAO,SAAS,KAAK,OAAS,EAAE,GAChC,IAAK,CAAC,QAASF,CAAW,CAC3B,CAAC,CACF,CACD,ED1KO,IAAMG,EAAN,cAA4BC,CACnC,CAMC,cACA,CAIC,KAAK,QAAU,KAKf,KAAK,cAAgB,IACtB,CAOA,kBACA,CAEC,OAAO,KAAK,QAAU,IAAIC,EAAkB,KAAK,OAAQ,KAAK,KAAK,CACpE,CAOA,oBACA,CAEC,KAAK,iBAAiB,EAEtB,KAAK,cAAgB,KAAK,eAAiBC,EAAmB,KAAK,SAAS,CAC7E,CAOA,SACA,CAECC,EAAgB,KAAK,cAAe,KAAK,QAAS,IAAI,CACvD,CAOA,QACA,CAEC,IAAMC,EAAc,KAAK,IAAI,KAAK,IAAI,EAEtC,YAAK,mBAAmB,EAEjBC,GAAM,CAEZ,MAAO,SAAS,KAAK,OAAS,EAAE,GAShC,UAAW,CAACC,EAAKC,IACjB,CAEC,KAAK,SAASD,EAAK,eAAe,EAClC,KAAK,QAAQ,CACd,EAEA,IAAK,CAAC,QAASF,CAAW,CAC3B,CAAC,CACF,CACD,EG9GA,OAAS,SAAAI,OAAa,wBAyBf,IAAMC,EAAN,cAAkCC,CACzC,CAMC,cACA,CAIC,KAAK,QAAU,KAMf,KAAK,gBAAkB,KAKvB,KAAK,cAAgB,IACtB,CAOA,kBACA,CAEC,OAAO,KAAK,QAAU,IAAIC,EAAkB,KAAK,OAAQ,KAAK,KAAK,CACpE,CAQA,mBAAmBC,EACnB,CAEC,IAAMC,EAAU,KAAK,iBAAiB,EAEtC,YAAK,cAAgB,KAAK,eAAiBC,EAAmB,KAAK,SAAS,EASrEC,EAAyBH,EAAWC,EAAS,KAAK,aAAa,CACvE,CAOA,SACA,CAECG,EAAgB,KAAK,cAAe,KAAK,QAAS,IAAI,CACvD,CAOA,QACA,CAEC,IAAMC,EAAc,KAAK,IAAI,KAAK,IAAI,EAEhCL,EAAY,KAAK,iBAAmB,WASpCM,EAAe,KAAK,mBAAmBN,CAAS,EAEtD,OAAOO,GAAM,CAEZ,MAAO,SAAS,KAAK,OAAS,EAAE,GAShC,UAAW,CAACC,EAAKC,IACjB,CAEC,KAAK,SAASD,EAAK,eAAe,EAElCF,EAAa,KAAMG,EAAQ,IAC3B,CAEC,KAAK,MAAM,CACZ,CAAC,CACF,EAKA,SAAU,CAAC,SAAUT,EAAWM,EAAc,CAAE,QAAS,EAAK,CAAC,EAE/D,IAAK,CAAC,QAASD,CAAW,CAC3B,CAAC,CACF,CACD,ECpJA,OAAS,QAAAK,OAAY,wBACrB,OAAS,aAAAC,GAAW,cAAAC,OAAkB,uBCS/B,IAAMC,EAAN,KACP,CAOC,YAAYC,EAAUC,EACtB,CAIC,KAAK,MAAQ,KAKb,KAAK,SAAWA,EAKhB,KAAK,SAAWD,GAAY,GAC7B,CASA,YAAYC,EACZ,CACC,KAAK,MAAQ,WAAW,WAAWA,EAAU,KAAK,QAAQ,CAC3D,CAOA,OACA,CAIC,KAAK,KAAK,EAEV,IAAMA,EAAW,KAAK,eAAe,KAAK,IAAI,EAC9C,KAAK,YAAYA,CAAQ,CAC1B,CAOA,MACA,CAEC,WAAW,aAAa,KAAK,KAAK,CACnC,CAQA,gBACA,CACC,IAAMA,EAAW,KAAK,SAClB,OAAOA,GAAa,YAGvBA,EAAS,KAAK,CAEhB,CACD,ECjFO,IAAMC,EAAN,cAA4BC,CACnC,CAQC,YAAYC,EACZ,CACC,KAAK,MAAQ,WAAW,YAAYA,EAAU,KAAK,QAAQ,CAC5D,CAOA,MACA,CAEC,WAAW,cAAc,KAAK,KAAK,CACpC,CACD,EFnBA,IAAMC,EAAO,IAAIC,GAAW,CAC3B,KAAM,CACP,CAAC,EAMKC,GAAkB,IAQlBC,GAAQ,IAAIC,EAAcF,GAAiB,IACjD,CACCF,EAAK,UAAU,MAAM,CACtB,CAAC,EAMDG,GAAM,MAAM,EAcL,IAAME,EAAN,cAA0BC,EACjC,CAOC,SACA,CACC,OAAON,CACR,CAOA,QACA,CACC,OAAOO,GAAK,CAEX,MAAO,KAAK,MACZ,KAAM,KAAK,QAAQ,EACnB,MAAO,CAAC,OAAQ,IAAM,KAAK,QAAQ,CAAC,CACrC,CAAC,CACF,CAOA,SACA,CAEC,IAAMC,EAAW,KAAK,SAEtB,OAAQ,KAAK,OAAU,KAAK,OAAOA,CAAQ,EAAIA,CAChD,CACD",
6
+ "names": ["Div", "Atom", "PaginationTracker", "offset", "limit", "numItems", "lastCursor", "newestId", "SCROLL_THRESHOLD", "getNewestId", "rows", "firstItem", "lastItem", "getScrollMetrics", "container", "scrollTop", "clientHeight", "scrollHeight", "shouldLoadMore", "metrics", "threshold", "shouldLoadAtTop", "canLoad", "tracker", "canLoadAtTop", "updateRows", "list", "lastCursor", "updateRowsAtTop", "heightDifference", "setupFetchCallback", "data", "tracker", "callback", "resultCallback", "response", "rows", "lastCursor", "setupFetchNewerCallback", "newestId", "getNewestId", "fetchAndRefresh", "fetchCallback", "tracker", "list", "rows", "lastCursor", "updateRows", "newestId", "getNewestId", "createScrollHandler", "container", "tracker", "fetchCallback", "direction", "listCache", "canLoadFunc", "canLoadAtTop", "canLoad", "isUpDirection", "e", "parent", "callBack", "list", "metrics", "getScrollMetrics", "rows", "lastCursor", "isInitialLoad", "updateRowsAtTop", "newestId", "getNewestId", "updateRows", "createTableScrollHandler", "setupResetCallback", "fetchCallback", "tracker", "list", "fetchAndRefresh", "addRefreshMethod", "parent", "listCache", "BiDirectionalContainer", "Atom", "props", "children", "PaginationTracker", "container", "scrollDirection", "setupFetchCallback", "fetchNewerCallback", "setupFetchNewerCallback", "handleScroll", "createScrollHandler", "Div", "ele", "items", "newestId", "getNewestId", "shouldScroll", "rows", "scrollHeight", "bi_directional_container_default", "Atom", "Div", "Atom", "setupResetCallback", "fetchCallback", "tracker", "list", "fetchAndRefresh", "addRefreshMethod", "parent", "listCache", "DataContainer", "Atom", "props", "children", "PaginationTracker", "setupFetchCallback", "Div", "ele", "data_container_default", "Div", "On", "Component", "Data", "Jot", "Builder", "Html", "ChildHelper", "parent", "index", "node", "children", "layout", "oldChild", "frag", "childrenLayout", "container", "Item", "index", "item", "status", "DataHelper", "_DataHelper", "oldArray", "newArray", "key", "oldItemsMap", "changes", "deletedItems", "newLength", "i", "newItem", "keyValue", "oldItem", "addMissing", "oldItems", "length", "id", "array", "map", "obj1", "obj2", "keys1", "keys2", "RowDivider", "layout", "itemProperty", "customCompare", "skipFirst", "firstItem", "value", "last", "item", "children", "first", "lastValue", "clone", "data", "item", "List", "Jot", "RowDivider", "items", "Data", "parentValue", "hasItems", "parentData", "rowCallBack", "Div", "On", "index", "scope", "children", "rowLayout", "keyValue", "Component", "rowElement", "ChildHelper", "row", "append", "oldRow", "layout", "length", "i", "rows", "safeRows", "existingItems", "startIndex", "newItems", "withDelete", "oldItems", "changes", "DataHelper", "changesLength", "deleteIfFound", "updatedItems", "addMissing", "updatingItems", "firstChild", "reverseItems", "reverseLength", "oldestItem", "value", "trailingRows", "keyString", "cached", "childrenLength", "child", "DataList", "Atom", "props", "cache", "data_container_default", "List", "Atom", "ScrollableList", "Atom", "props", "cache", "bi_directional_container_default", "List", "Component", "router", "Watcher", "attr", "value", "iSActive", "path", "url", "NavLink", "href", "text", "watchers", "string", "type", "exact", "data", "ele", "selected", "Tbody", "Tbody", "Data", "Div", "Td", "Tr", "SkeletonTableRow", "columnCount", "customCell", "key", "createSkeletonCell", "index", "widths", "width", "_", "TableBody", "List", "hasItems", "Data", "skeletonConfig", "skeletonCount", "customRowFunction", "columnCount", "_", "index", "SkeletonTableRow", "rows", "items", "item", "scope", "children", "rowCallBack", "Tbody", "ele", "DataTableBody", "TableBody", "PaginationTracker", "setupFetchCallback", "fetchAndRefresh", "rowCallBack", "Tbody", "ele", "parent", "Tbody", "ScrollableTableBody", "TableBody", "PaginationTracker", "container", "tracker", "setupFetchCallback", "createTableScrollHandler", "fetchAndRefresh", "rowCallBack", "handleScroll", "Tbody", "ele", "parent", "Span", "Component", "SimpleData", "Timer", "duration", "callBack", "IntervalTimer", "Timer", "callBack", "data", "SimpleData", "MINUTE_INTERVAL", "timer", "IntervalTimer", "DynamicTime", "Component", "Span", "dateTime"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base-framework/organisms",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "This will add default organisms to the base framework.",
5
5
  "main": "./dist/organisms.js",
6
6
  "scripts": {