@7span/react-list 0.0.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- (function(v,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],s):(v=typeof globalThis<"u"?globalThis:v||self,s(v.ReactList={},v.jsxRuntime,v.react))})(this,function(v,s,n){"use strict";const B=n.createContext(null),j=({children:a,config:l})=>{const{requestHandler:o,stateManager:t={}}=l,[r,i]=n.useState({data:[],response:null,error:null,count:0,selection:[],pagination:{page:1,perPage:25},loader:{isLoading:!1,initialLoading:!0},sort:{sortBy:null,sortOrder:"desc"},search:"",filters:{},attrs:[],isEmpty:!0,isInitializing:!0});if(!o)throw new Error("ListProvider: requestHandler is required.");const f=n.useMemo(()=>({requestHandler:o,stateManager:t,listState:r,setListState:i}),[o,t,r]);return s.jsx(B.Provider,{value:f,children:a})},w=()=>{const a=n.useContext(B);if(!a)throw new Error("useListContext must be used within a ListProvider");return a},I=n.memo(({children:a,renderAttribute:l})=>{const{listState:o}=w(),{attrs:t,attrSettings:r,updateAttr:i}=o,f=n.useCallback(d=>m=>{i(d,"visible",m.target.checked)},[i]),p=n.useMemo(()=>({attrs:t,attrSettings:r,updateAttr:i}),[t,r,i]);return a?a(p):s.jsx("div",{className:"react-list-attributes",children:t.map((d,m)=>{var u;return l?l({key:`attr-${m}`,attr:d,updateAttr:i,attrSettings:r}):s.jsxs("label",{children:[s.jsx("span",{children:d.label}),s.jsx("input",{type:"checkbox",checked:((u=r==null?void 0:r[d.name])==null?void 0:u.visible)??!1,onChange:f(d.name)})]},`attr-${m}`)})})}),q=n.memo(({children:a})=>{const{listState:l}=w(),{data:o,loader:t,error:r}=l,{isLoading:i,initialLoading:f}=t;return(o==null?void 0:o.length)>0||f||i||r?null:s.jsx("div",{className:"react-list-empty",children:a||s.jsx("div",{children:s.jsx("p",{children:"No data found!"})})})}),A=n.memo(({children:a})=>{const{listState:l}=w(),{error:o,loader:t}=l,{isLoading:r}=t;return!o||r?null:s.jsx("div",{className:"react-list-error",children:typeof a=="function"?a({error:o}):a||s.jsxs("div",{children:[s.jsx("h3",{children:"Error occurred"}),s.jsxs("pre",{children:[o.name,": ",o.message]})]})})}),_=n.memo(({children:a})=>{const{listState:l}=w(),{data:o,count:t,pagination:r,setPage:i,loader:f,error:p}=l,{page:d,perPage:m}=r,{initialLoading:u,isLoading:L}=f,{pages:M,pagesCount:y}=n.useMemo(()=>{const C=Math.ceil(t/m);return{pages:Array.from({length:C},(k,P)=>P+1),pagesCount:C}},[t,m]),N=n.useCallback(C=>{i(Number(C.target.value))},[i]),b=n.useMemo(()=>({setPage:i,page:d,pages:M,pagesCount:y}),[i,d,M,y]);return u||!o||o.length===0||p?null:s.jsx("div",{className:"react-list-go-to",children:a?a(b):s.jsx("select",{value:d,onChange:N,children:M.map(C=>s.jsxs("option",{value:C,children:["Page ",C]},`page-${C}`))})})}),$=n.memo(({children:a})=>{const{listState:l}=w(),{loader:o}=l,{initialLoading:t}=o;return n.useMemo(()=>({loading:t}),[t]),t?s.jsx("div",{className:"react-list-initial-loader",children:a||s.jsx("p",{children:"Initial Loading..."})}):null}),D=n.memo(({children:a,renderItem:l})=>{const{listState:o}=w(),{data:t=[],loader:r,error:i,setSort:f,sort:p}=o,{initialLoading:d}=r,m=n.useMemo(()=>({items:t,setSort:f,sort:p}),[t,p,f]);return d||!t||t.length===0||i?null:l?s.jsx("div",{className:"react-list-items",children:t.map((u,L)=>s.jsx("div",{children:l({item:u,index:L})},u.id||L))}):typeof a=="function"?s.jsx("div",{className:"react-list-items",children:a(m)}):s.jsx("div",{className:"react-list-items",children:t.map((u,L)=>s.jsx("pre",{children:JSON.stringify(u,null,2)},u.id||L))})}),H=({initialItems:a=[],children:l,endpoint:o,page:t=1,perPage:r=25,sortBy:i="",sortOrder:f="desc",count:p=0,search:d="",filters:m={},attrs:u,version:L=1,paginationMode:M="pagination",meta:y={}})=>{const{requestHandler:N,setListState:b}=w(),C=M==="loadMore",[e,k]=n.useState({page:t,perPage:r,sortBy:i,sortOrder:f,search:d,filters:m,attrSettings:{},items:a,selection:[],error:null,response:null,count:p,isLoading:!1,initializingState:!a.length}),P=n.useCallback(async(g={},c=null)=>{e.initializingState||k(h=>({...h,error:null,isLoading:!0}));try{const h=c||e,S=await N({endpoint:o,version:L,meta:y,page:h.page,perPage:h.perPage,search:h.search,sortBy:h.sortBy,sortOrder:h.sortOrder,filters:h.filters,...g});k(z=>({...z,response:S,selection:[],items:C&&h.page>1?[...z.items,...S.items]:S.items,count:S.count,initializingState:!1,isLoading:!1}))}catch(h){throw k(S=>({...S,error:h,items:[],count:0,initializingState:!1,isLoading:!1})),h}},[o,L,C,y,N,e]),O=n.useMemo(()=>({setPage:(g,c)=>{let h=g;g===0&&(h="");const S={...e,page:h};k(S),h&&P(c,S)},setPerPage:g=>{const c={...e,perPage:g,page:1};k(c),P({},c)},setSearch:g=>{if(g!==e.search){const c={...e,search:g,page:1};k(c),P({},c)}},setSort:({by:g,order:c})=>{const h={...e,sortBy:g,sortOrder:c,page:1};k(h),P({},h)},loadMore:()=>{const g={...e,page:e.page+1};k(g),P({},g)},refresh:(g={isRefresh:!0})=>{if(C){const c={...e,page:1,items:[]};k(c),P(g,c)}else P(g)},setFilters:g=>{const c={...e,filters:g,page:1};k(c),P({},c)},updateItemById:(g,c)=>{const h=e.items.map(S=>S.id===c?{...S,...g}:S);k(S=>({...S,items:h}))},setSelection:g=>k(c=>({...c,selection:g}))}),[P,C,e]),E=n.useMemo(()=>({data:e.items,response:e.response,error:e.error,count:e.count,selection:e.selection,pagination:{page:e.page,perPage:e.perPage,hasMore:e.items.length<e.count},loader:{isLoading:e.isLoading,initialLoading:e.initializingState},sort:{sortBy:e.sortBy,sortOrder:e.sortOrder},search:e.search,filters:e.filters,attrs:u||Object.keys(e.items[0]||{}),isEmpty:e.items.length===0,...O}),[e.items,e.response,e.error,e.count,e.selection,e.page,e.perPage,e.isLoading,e.initializingState,e.sortBy,e.sortOrder,e.search,e.filters,O,u]);return n.useEffect(()=>{e.initializingState&&(a.length||O.setPage(e.page))},[]),n.useEffect(()=>{b(E)},[b,e.items,e.count,e.error,e.isLoading,e.selection,e.page,e.perPage,e.sortBy,e.sortOrder]),typeof l=="function"?l(E):l},x=n.memo(({children:a})=>{const{listState:l}=w(),{data:o,count:t,pagination:r,setPage:i,loader:f,error:p}=l,{page:d,perPage:m}=r,{isLoading:u}=f,L=n.useMemo(()=>d*m<t,[d,m,t]),M=n.useCallback(()=>{L&&!u&&i(d+1)},[L,u,i,d]),y=n.useMemo(()=>({isLoading:u,loadMore:M,hasMoreItems:L}),[u,M,L]);return!o||o.length===0||p?null:a(y)}),G=n.memo(({children:a,position:l="overlay"})=>{const{listState:o}=w(),{loader:t}=o,{isLoading:r,initializingState:i}=t;return n.useMemo(()=>({isLoading:r}),[r]),!i&&!r?null:s.jsx("div",{children:a||s.jsx("div",{children:s.jsx("p",{children:"Loading..."})})})}),W=n.memo(({children:a,pageLinks:l=5,renderFirst:o,renderPrev:t,renderPages:r,renderPage:i,renderNext:f,renderLast:p})=>{const{listState:d}=w(),{data:m,count:u,pagination:L,setPage:M,loader:y,error:N}=d,{page:b,perPage:C}=L,{initialLoading:e,isLoading:k}=y,P=n.useMemo(()=>{const c=Math.ceil(u/C),h=Math.floor(l/2),S=b*C<u;return{pagesCount:c,halfWay:h,hasNext:S,hasPrev:b!==1}},[u,C,b,l]),O=n.useMemo(()=>{const{pagesCount:c,halfWay:h}=P,S=Array.from({length:Math.min(l,c)});return b<=h?S.map((z,T)=>T+1):c-b<h?S.map((z,T)=>c-T).reverse():S.map((z,T)=>b-h+T)},[b,l,P]),E=n.useMemo(()=>({prev:()=>M(b-1),next:()=>M(b+1),first:()=>M(1),last:()=>M(P.pagesCount),setPage:c=>M(c)}),[M,b,P.pagesCount]),g=n.useMemo(()=>({page:b,perPage:C,count:u,...P,pagesToDisplay:O,...E}),[b,C,u,P,O,E]);return e||!m||m.length===0||N?null:a?a(g):s.jsxs("div",{className:"react-list-pagination",children:[o?o(g):s.jsx("button",{type:"button",disabled:!P.hasPrev,onClick:E.first,children:"First"}),t?t(g):s.jsx("button",{type:"button",disabled:!P.hasPrev,onClick:E.prev,children:"Prev"}),r?r(g):s.jsx("div",{children:O.map(c=>{const h=c===b,S={...g,page:c,isActive:h};return i?i(S):s.jsx("div",{children:h?s.jsx("span",{children:c}):s.jsx("button",{type:"button",onClick:()=>E.setPage(c),children:c})},`page-${c}`)})}),f?f(g):s.jsx("button",{type:"button",disabled:!P.hasNext,onClick:E.next,children:"Next"}),p?p(g):s.jsx("button",{type:"button",disabled:!P.hasNext,onClick:E.last,children:"Last"})]})}),F=n.memo(({children:a,options:l=[10,25,50,100]})=>{const{listState:o}=w(),{data:t,pagination:r,setPerPage:i,loader:f,error:p}=o,{perPage:d}=r,{initialLoading:m}=f,u=n.useMemo(()=>l.map(y=>typeof y!="object"?{value:y,label:y}:y),[l]),L=n.useCallback(y=>{i(Number(y.target.value))},[i]),M=n.useMemo(()=>({perPage:d,setPerPage:i,options:u}),[d,i,u]);return m||!t||t.length===0||p?null:s.jsx("div",{className:"react-list-per-page",children:a?a(M):s.jsx("select",{value:d,onChange:L,children:u.map(y=>s.jsxs("option",{value:y.value,children:[y.label," items per page"]},`option-${y.value}`))})})}),J=n.memo(({children:a})=>{const{listState:l}=w(),{loader:o,refresh:t}=l,{isLoading:r,initialLoading:i}=o,f=n.useCallback(()=>{t({isRefresh:!0})},[t]),p=n.useMemo(()=>({isLoading:r,refresh:f}),[r,f]);return i?null:a?a(p):s.jsx("div",{className:"react-list-refresh",children:s.jsx("button",{onClick:f,disabled:r,children:r?"Loading...":"Refresh"})})}),K=n.memo(({children:a,debounceTime:l=500})=>{const{listState:o}=w(),{search:t,setSearch:r}=o,[i,f]=n.useState(t??""),p=n.useRef(null);n.useEffect(()=>{t!==i&&f(t??"")},[t]);const d=u=>{f(u),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{r(u)},l)};n.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const m={search:i,setSearch:d};return s.jsx("div",{className:"react-list-search",children:a?a(m):s.jsx("input",{type:"text",value:i,onChange:u=>d(u.target.value),placeholder:"Search..."})})}),Q=n.memo(({children:a})=>{const{listState:l}=w(),{data:o,count:t,pagination:r,loader:i,error:f}=l,{page:p,perPage:d}=r,{initialLoading:m,isLoading:u}=i,L=n.useMemo(()=>{const y=p*d-d+1,N=Math.min(p*d,t),b=(o==null?void 0:o.length)||0;return{from:y,to:N,visibleCount:b}},[p,d,t,o]),M=n.useMemo(()=>({...L,count:t}),[L,t]);return m||!o||o.length===0||f?null:s.jsx("div",{className:"react-list-summary",children:a?a(M):s.jsxs("span",{children:["Showing ",s.jsx("span",{children:L.visibleCount})," items (",s.jsxs("span",{children:[L.from," - ",L.to]}),") out of ",s.jsx("span",{children:t})]})})});v.ReactListAttributes=I,v.ReactListEmpty=q,v.ReactListError=A,v.ReactListGoTo=_,v.ReactListInitialLoader=$,v.ReactListItems=D,v.ReactListLoadMore=x,v.ReactListLoader=G,v.ReactListPagination=W,v.ReactListPerPage=F,v.ReactListProvider=j,v.ReactListRefresh=J,v.ReactListSearch=K,v.ReactListSummary=Q,v.default=H,Object.defineProperties(v,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(C,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],a):(C=typeof globalThis<"u"?globalThis:C||self,a(C.ReactList={},C.jsxRuntime,C.react))})(this,function(C,a,r){"use strict";const H=r.createContext(null),K=({children:t,config:o})=>{const{requestHandler:l,stateManager:n={}}=o,[i,u]=r.useState({data:[],response:null,error:null,count:0,selection:[],pagination:{page:1,perPage:25},loader:{isLoading:!1,initialLoading:!0},sort:{sortBy:null,sortOrder:"desc"},search:"",filters:{},attrs:[],isEmpty:!0,isInitializing:!0});if(!l)throw new Error("ListProvider: requestHandler is required.");const f=r.useMemo(()=>({requestHandler:l,stateManager:n,listState:i,setListState:u}),[l,n,i]);return a.jsx(H.Provider,{value:f,children:t})},S=()=>{const t=r.useContext(H);if(!t)throw new Error("useListContext must be used within a ListProvider");return t},Q=r.memo(({children:t,renderAttribute:o})=>{const{listState:l}=S(),{attrs:n,attrSettings:i,updateAttr:u}=l,f=r.useCallback(d=>m=>{u(d,"visible",m.target.checked)},[u]),L=r.useMemo(()=>({attrs:n,attrSettings:i,updateAttr:u}),[n,i,u]);return t?t(L):a.jsx("div",{className:"react-list-attributes",children:n.map((d,m)=>{var h;return o?o({key:`attr-${m}`,attr:d,updateAttr:u,attrSettings:i}):a.jsxs("label",{children:[a.jsx("span",{children:d.label}),a.jsx("input",{type:"checkbox",checked:((h=i==null?void 0:i[d.name])==null?void 0:h.visible)??!1,onChange:f(d.name)})]},`attr-${m}`)})})}),U=r.memo(({children:t})=>{const{listState:o}=S(),{data:l,loader:n,error:i}=o,{isLoading:u,initialLoading:f}=n;return(l==null?void 0:l.length)>0||f||u||i?null:a.jsx("div",{className:"react-list-empty",children:t||a.jsx("div",{children:a.jsx("p",{children:"No data found!"})})})}),V=r.memo(({children:t})=>{const{listState:o}=S(),{error:l,loader:n}=o,{isLoading:i}=n;return!l||i?null:a.jsx("div",{className:"react-list-error",children:typeof t=="function"?t({error:l}):t||a.jsxs("div",{children:[a.jsx("h3",{children:"Error occurred"}),a.jsxs("pre",{children:[l.name,": ",l.message]})]})})}),X=r.memo(({children:t})=>{const{listState:o}=S(),{data:l,count:n,pagination:i,setPage:u,loader:f,error:L}=o,{page:d,perPage:m}=i,{initialLoading:h,isLoading:y}=f,{pages:v,pagesCount:P}=r.useMemo(()=>{const M=Math.ceil(n/m);return{pages:Array.from({length:M},(_,p)=>p+1),pagesCount:M}},[n,m]),T=r.useCallback(M=>{u(Number(M.target.value))},[u]),b=r.useMemo(()=>({setPage:u,page:d,pages:v,pagesCount:P}),[u,d,v,P]);return h||!l||l.length===0||L?null:a.jsx("div",{className:"react-list-go-to",children:t?t(b):a.jsx("select",{value:d,onChange:T,children:v.map(M=>a.jsxs("option",{value:M,children:["Page ",M]},`page-${M}`))})})}),Y=r.memo(({children:t})=>{const{listState:o}=S(),{loader:l}=o,{initialLoading:n}=l;return r.useMemo(()=>({loading:n}),[n]),n?a.jsx("div",{className:"react-list-initial-loader",children:t||a.jsx("p",{children:"Initial Loading..."})}):null}),Z=r.memo(({children:t,renderItem:o})=>{const{listState:l}=S(),{data:n=[],loader:i,error:u,setSort:f,sort:L}=l,{initialLoading:d,isLoading:m}=i,h=r.useMemo(()=>({items:n,isLoading:m,setSort:f,sort:L}),[n,L,f,m]);return d||!n||n.length===0||u?null:o?a.jsx("div",{className:"react-list-items",children:n.map((y,v)=>a.jsx("div",{children:o({item:y,index:v})},y.id||v))}):typeof t=="function"?a.jsx("div",{className:"react-list-items",children:t(h)}):a.jsx("div",{className:"react-list-items",children:n.map((y,v)=>a.jsx("pre",{children:JSON.stringify(y,null,2)},y.id||v))})}),$=(t,o)=>{if(t===o)return!0;if(t==null||o==null||typeof t!="object"||typeof o!="object")return t===o;if(Array.isArray(t)&&Array.isArray(o)){if(t.length!==o.length)return!1;for(let i=0;i<t.length;i++)if(!$(t[i],o[i]))return!1;return!0}if(Array.isArray(t)||Array.isArray(o))return!1;const l=Object.keys(t).filter(i=>t[i]!==void 0),n=Object.keys(o).filter(i=>o[i]!==void 0);if(l.length!==n.length)return!1;for(let i of l)if(!n.includes(i)||!$(t[i],o[i]))return!1;return!0},F=(t,o)=>!o||Object.keys(o).length===0?t&&Object.keys(t).length>0:!t||Object.keys(t).length===0?!1:!$(t,o),R=({initialItems:t=[],children:o,endpoint:l,page:n=1,perPage:i=25,sortBy:u="",sortOrder:f="desc",count:L=0,search:d="",filters:m={},attrs:h,version:y=1,paginationMode:v="pagination",meta:P={},onResponse:T,afterPageChange:b,afterLoadMore:M})=>{const{requestHandler:x,setListState:_,stateManager:p}=S(),q=r.useRef(!1),A=v==="loadMore",w=r.useCallback(e=>({endpoint:l,version:y,meta:P,search:(e==null?void 0:e.search)||d,page:(e==null?void 0:e.page)||n,perPage:(e==null?void 0:e.perPage)||i,sortBy:(e==null?void 0:e.sortBy)||u,sortOrder:(e==null?void 0:e.sortOrder)||f,filters:(e==null?void 0:e.filters)||m,attrSettings:(e==null?void 0:e.attrSettings)||{},isRefresh:!1}),[l,y,P,d,n,i,u,f,m]),k=r.useCallback(()=>{var e;try{const g=w(),c=(e=p==null?void 0:p.get)==null?void 0:e.call(p,g);return{page:c==null?void 0:c.page,perPage:c==null?void 0:c.perPage,sortBy:c==null?void 0:c.sortBy,sortOrder:c==null?void 0:c.sortOrder,search:c==null?void 0:c.search,attrSettings:c==null?void 0:c.attrSettings,filters:c==null?void 0:c.filters}}catch(g){return console.error(g),{}}},[w,p]),B=r.useCallback(()=>{const e=k();let g=n;return A?g=1:e.page!=null&&(g=e.page),{page:g,perPage:e.perPage!=null?e.perPage:i,sortBy:e.sortBy!=null?e.sortBy:u,sortOrder:e.sortOrder!=null?e.sortOrder:f,search:e.search!=null?e.search:d,filters:e.filters!=null?e.filters:m,attrSettings:e.attrSettings||{},items:t,selection:[],error:null,response:null,count:0,isLoading:!1,initializingState:!t.length,confirmedPage:null}},[k,d,n,i,u,f,d,m,A]),[s,O]=r.useState(B),I=r.useCallback(e=>{var g;if(p){const c=w(e);(g=p==null?void 0:p.set)==null||g.call(p,c)}},[p,w]),N=r.useCallback(async(e={},g=null)=>{s.initializingState||O(c=>({...c,error:null,isLoading:!0}));try{const c=g||s,E=(g==null?void 0:g.items)??s.items,z=await x({endpoint:l,version:y,meta:P,page:c.page,perPage:c.perPage,search:c.search,sortBy:c.sortBy,sortOrder:c.sortOrder,filters:c.filters,...e});T&&T(z);let W;A?(W=c.page===1?z.items:[...E,...z.items],M&&M(z)):(W=z.items,b&&b(z));const J={...c,response:z,selection:[],items:A&&c.page>1?[...E,...z.items]:z.items,count:z.count,initializingState:!1,isLoading:!1};I(J),O(J)}catch(c){throw O(E=>({...E,error:c,items:[],count:0,initializingState:!1,isLoading:!1})),c}},[l,y,A,P,x,s]),D=r.useMemo(()=>({setPage:(e,g)=>{let c=e;e===0&&(c="");const E={...s,page:c};O(E),c&&N(g,E)},setPerPage:e=>{const g={...s,perPage:e,page:1};O(g),N({},g)},setSearch:e=>{if(e!==s.search){const g={...s,search:e,page:1};O(g),N({},g)}},setSort:({by:e,order:g})=>{const c={...s,sortBy:e,sortOrder:g,page:1};O(c),N({},c)},loadMore:()=>{const e={...s,page:s.page+1};O(e),N({},e)},clearFilters:()=>{const e={...s,filters:m,page:1};O(e),N({},e)},refresh:(e={isRefresh:!0})=>{if(A){const g={...s,page:1,items:[]};O(g),N(e,g)}else N(e)},setFilters:e=>{const g={...s,filters:e,page:1};O(g),N({},g)},updateItemById:(e,g)=>{const c=s.items.map(E=>E.id===g?{...E,...e}:E);O(E=>({...E,items:c}))},setSelection:e=>O(g=>({...g,selection:e}))}),[N,A,s]),G=r.useMemo(()=>({data:s.items,response:s.response,error:s.error,count:s.count,selection:s.selection,pagination:{page:s.page,perPage:s.perPage,hasMore:s.items.length<s.count},loader:{isLoading:s.isLoading,initialLoading:s.initializingState},sort:{sortBy:s.sortBy,sortOrder:s.sortOrder},hasActiveFilters:F(s.filters,m),search:s.search,filters:s.filters,attrs:h||Object.keys(s.items[0]||{}),isEmpty:s.items.length===0,...D}),[s.items,s.response,s.error,s.count,s.selection,s.page,s.perPage,s.isLoading,s.initializingState,s.sortBy,s.sortOrder,s.search,s.filters,D,h]);return r.useEffect(()=>{if(s.initializingState&&!q.current){if(q.current=!0,p!=null&&p.init){const e=w(s);p.init(e)}t.length||D.setPage(s.page)}},[]),r.useEffect(()=>{_(G)},[_,s.items,s.count,s.error,s.isLoading,s.selection,s.page,s.perPage,s.sortBy,s.sortOrder]),typeof o=="function"?o(G):o},j=r.memo(({children:t})=>{const{listState:o}=S(),{data:l,count:n,pagination:i,setPage:u,loader:f,error:L}=o,{page:d,perPage:m}=i,{isLoading:h}=f,y=r.useMemo(()=>d*m<n,[d,m,n]),v=r.useCallback(()=>{y&&!h&&u(d+1)},[y,h,u,d]),P=r.useMemo(()=>({isLoading:h,loadMore:v,hasMoreItems:y}),[h,v,y]);return!l||l.length===0||L?null:t(P)}),ee=r.memo(({children:t,position:o="overlay"})=>{const{listState:l}=S(),{loader:n}=l,{isLoading:i,initializingState:u}=n;return r.useMemo(()=>({isLoading:i}),[i]),!u&&!i?null:a.jsx("div",{children:t||a.jsx("div",{children:a.jsx("p",{children:"Loading..."})})})}),se=r.memo(({children:t,pageLinks:o=5,renderFirst:l,renderPrev:n,renderPages:i,renderPage:u,renderNext:f,renderLast:L})=>{const{listState:d}=S(),{data:m,count:h,pagination:y,setPage:v,loader:P,error:T}=d,{page:b,perPage:M}=y,{initialLoading:x,isLoading:_}=P,p=r.useMemo(()=>{const k=Math.ceil(h/M),B=Math.floor(o/2),s=b*M<h;return{pagesCount:k,halfWay:B,hasNext:s,hasPrev:b!==1}},[h,M,b,o]),q=r.useMemo(()=>{const{pagesCount:k,halfWay:B}=p,s=Array.from({length:Math.min(o,k)});return b<=B?s.map((O,I)=>I+1):k-b<B?s.map((O,I)=>k-I).reverse():s.map((O,I)=>b-B+I)},[b,o,p]),A=r.useMemo(()=>({prev:()=>v(b-1),next:()=>v(b+1),first:()=>v(1),last:()=>v(p.pagesCount),setPage:k=>v(k)}),[v,b,p.pagesCount]),w=r.useMemo(()=>({page:b,perPage:M,count:h,...p,pagesToDisplay:q,...A}),[b,M,h,p,q,A]);return x||!m||m.length===0||T?null:t?t(w):a.jsxs("div",{className:"react-list-pagination",children:[l?l(w):a.jsx("button",{type:"button",disabled:!p.hasPrev,onClick:A.first,children:"First"}),n?n(w):a.jsx("button",{type:"button",disabled:!p.hasPrev,onClick:A.prev,children:"Prev"}),i?i(w):a.jsx("div",{children:q.map(k=>{const B=k===b,s={...w,page:k,isActive:B};return u?u(s):a.jsx("div",{children:B?a.jsx("span",{children:k}):a.jsx("button",{type:"button",onClick:()=>A.setPage(k),children:k})},`page-${k}`)})}),f?f(w):a.jsx("button",{type:"button",disabled:!p.hasNext,onClick:A.next,children:"Next"}),L?L(w):a.jsx("button",{type:"button",disabled:!p.hasNext,onClick:A.last,children:"Last"})]})}),te=r.memo(({children:t,options:o=[10,25,50,100]})=>{const{listState:l}=S(),{data:n,pagination:i,setPerPage:u,loader:f,error:L}=l,{perPage:d}=i,{initialLoading:m}=f,h=r.useMemo(()=>o.map(P=>typeof P!="object"?{value:P,label:P}:P),[o]),y=r.useCallback(P=>{u(Number(P.target.value))},[u]),v=r.useMemo(()=>({perPage:d,setPerPage:u,options:h}),[d,u,h]);return m||!n||n.length===0||L?null:a.jsx("div",{className:"react-list-per-page",children:t?t(v):a.jsx("select",{value:d,onChange:y,children:h.map(P=>a.jsxs("option",{value:P.value,children:[P.label," items per page"]},`option-${P.value}`))})})}),ne=r.memo(({children:t})=>{const{listState:o}=S(),{loader:l,refresh:n}=o,{isLoading:i,initialLoading:u}=l,f=r.useCallback(()=>{n({isRefresh:!0})},[n]),L=r.useMemo(()=>({isLoading:i,refresh:f}),[i,f]);return u?null:t?t(L):a.jsx("div",{className:"react-list-refresh",children:a.jsx("button",{onClick:f,disabled:i,children:i?"Loading...":"Refresh"})})}),ie=r.memo(({children:t,debounceTime:o=500})=>{const{listState:l}=S(),{search:n,setSearch:i}=l,[u,f]=r.useState(n??""),L=r.useRef(null);r.useEffect(()=>{n!==u&&f(n??"")},[n]);const d=h=>{f(h),L.current&&clearTimeout(L.current),L.current=setTimeout(()=>{i(h)},o)};r.useEffect(()=>()=>{L.current&&clearTimeout(L.current)},[]);const m={search:u,setSearch:d};return a.jsx("div",{className:"react-list-search",children:t?t(m):a.jsx("input",{type:"text",value:u,onChange:h=>d(h.target.value),placeholder:"Search..."})})}),re=r.memo(({children:t})=>{const{listState:o}=S(),{data:l,count:n,pagination:i,loader:u,error:f}=o,{page:L,perPage:d}=i,{initialLoading:m,isLoading:h}=u,y=r.useMemo(()=>{const P=L*d-d+1,T=Math.min(L*d,n),b=(l==null?void 0:l.length)||0;return{from:P,to:T,visibleCount:b}},[L,d,n,l]),v=r.useMemo(()=>({...y,count:n}),[y,n]);return m||!l||l.length===0||f?null:a.jsx("div",{className:"react-list-summary",children:t?t(v):a.jsxs("span",{children:["Showing ",a.jsx("span",{children:y.visibleCount})," items (",a.jsxs("span",{children:[y.from," - ",y.to]}),") out of ",a.jsx("span",{children:n})]})})});C.ReactListAttributes=Q,C.ReactListEmpty=U,C.ReactListError=V,C.ReactListGoTo=X,C.ReactListInitialLoader=Y,C.ReactListItems=Z,C.ReactListLoadMore=j,C.ReactListLoader=ee,C.ReactListPagination=se,C.ReactListPerPage=te,C.ReactListProvider=K,C.ReactListRefresh=ne,C.ReactListSearch=ie,C.ReactListSummary=re,C.default=R,Object.defineProperties(C,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7span/react-list",
3
- "version": "0.0.5",
3
+ "version": "1.0.0",
4
4
  "description": "A simple and reusable list component for React",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,10 +10,18 @@
10
10
  "preview": "vite preview",
11
11
  "prepublishOnly": "npm run build"
12
12
  },
13
- "main": "dist/react-list.js",
13
+ "main": "src/index.js",
14
+ "exports": {
15
+ ".": "./src/index.js"
16
+ },
14
17
  "files": [
15
- "dist"
18
+ "dist",
19
+ "src"
16
20
  ],
21
+ "peerDependencies": {
22
+ "react": "^18.2.0 || ^19.0.0",
23
+ "react-dom": "^18.2.0 || ^19.0.0"
24
+ },
17
25
  "publishConfig": {
18
26
  "access": "public"
19
27
  },
@@ -0,0 +1,53 @@
1
+ import { memo, useCallback, useMemo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListAttributes = memo(({ children, renderAttribute }) => {
5
+ const { listState } = useListContext();
6
+ const { attrs, attrSettings, updateAttr } = listState;
7
+
8
+ const handleAttrChange = useCallback(
9
+ (attrName) => (e) => {
10
+ updateAttr(attrName, "visible", e.target.checked);
11
+ },
12
+ [updateAttr]
13
+ );
14
+
15
+ const scope = useMemo(
16
+ () => ({
17
+ attrs,
18
+ attrSettings,
19
+ updateAttr,
20
+ }),
21
+ [attrs, attrSettings, updateAttr]
22
+ );
23
+
24
+ if (children) {
25
+ return children(scope);
26
+ }
27
+
28
+ return (
29
+ <div className="react-list-attributes">
30
+ {attrs.map((attr, index) => {
31
+ if (renderAttribute) {
32
+ return renderAttribute({
33
+ key: `attr-${index}`,
34
+ attr,
35
+ updateAttr,
36
+ attrSettings,
37
+ });
38
+ }
39
+
40
+ return (
41
+ <label key={`attr-${index}`}>
42
+ <span>{attr.label}</span>
43
+ <input
44
+ type="checkbox"
45
+ checked={attrSettings?.[attr.name]?.visible ?? false}
46
+ onChange={handleAttrChange(attr.name)}
47
+ />
48
+ </label>
49
+ );
50
+ })}
51
+ </div>
52
+ );
53
+ });
@@ -0,0 +1,22 @@
1
+ import { memo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListEmpty = memo(({ children }) => {
5
+ const { listState } = useListContext();
6
+ const { data: items, loader, error } = listState;
7
+ const { isLoading, initialLoading } = loader;
8
+
9
+ if (items?.length > 0 || initialLoading || isLoading || error) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <div className="react-list-empty">
15
+ {children || (
16
+ <div>
17
+ <p>No data found!</p>
18
+ </div>
19
+ )}
20
+ </div>
21
+ );
22
+ });
@@ -0,0 +1,27 @@
1
+ import { memo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListError = memo(({ children }) => {
5
+ const { listState } = useListContext();
6
+ const { error, loader } = listState;
7
+ const { isLoading } = loader;
8
+
9
+ if (!error || isLoading) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <div className="react-list-error">
15
+ {typeof children === "function"
16
+ ? children({ error })
17
+ : children || (
18
+ <div>
19
+ <h3>Error occurred</h3>
20
+ <pre>
21
+ {error.name}: {error.message}
22
+ </pre>
23
+ </div>
24
+ )}
25
+ </div>
26
+ );
27
+ });
@@ -0,0 +1,58 @@
1
+ import { memo, useCallback, useMemo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListGoTo = memo(({ children }) => {
5
+ const { listState } = useListContext();
6
+ const { data, count, pagination, setPage, loader, error } = listState;
7
+ const { page, perPage } = pagination;
8
+ const { initialLoading, isLoading } = loader;
9
+
10
+ const { pages, pagesCount } = useMemo(() => {
11
+ const pagesCount = Math.ceil(count / perPage);
12
+ const pages = Array.from({ length: pagesCount }, (_, i) => i + 1);
13
+ return { pages, pagesCount };
14
+ }, [count, perPage]);
15
+
16
+ const handlePageChange = useCallback(
17
+ (e) => {
18
+ setPage(Number(e.target.value));
19
+ },
20
+ [setPage]
21
+ );
22
+
23
+ const scope = useMemo(
24
+ () => ({
25
+ setPage,
26
+ page,
27
+ pages,
28
+ pagesCount,
29
+ }),
30
+ [setPage, page, pages, pagesCount]
31
+ );
32
+
33
+ if (initialLoading) return null;
34
+
35
+ if (!data || data.length === 0) {
36
+ return null;
37
+ }
38
+
39
+ if (error) {
40
+ return null;
41
+ }
42
+
43
+ return (
44
+ <div className="react-list-go-to">
45
+ {children ? (
46
+ children(scope)
47
+ ) : (
48
+ <select value={page} onChange={handlePageChange}>
49
+ {pages.map((pageNum) => (
50
+ <option key={`page-${pageNum}`} value={pageNum}>
51
+ Page {pageNum}
52
+ </option>
53
+ ))}
54
+ </select>
55
+ )}
56
+ </div>
57
+ );
58
+ });
@@ -0,0 +1,25 @@
1
+ import { memo, useMemo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListInitialLoader = memo(({ children }) => {
5
+ const { listState } = useListContext();
6
+ const { loader } = listState;
7
+ const { initialLoading } = loader;
8
+
9
+ const scope = useMemo(
10
+ () => ({
11
+ loading: initialLoading,
12
+ }),
13
+ [initialLoading]
14
+ );
15
+
16
+ if (!initialLoading) {
17
+ return null;
18
+ }
19
+
20
+ return (
21
+ <div className="react-list-initial-loader">
22
+ {children || <p>Initial Loading...</p>}
23
+ </div>
24
+ );
25
+ });
@@ -0,0 +1,50 @@
1
+ import { memo, useMemo } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+
4
+ export const ReactListItems = memo(({ children, renderItem }) => {
5
+ const { listState } = useListContext();
6
+ const { data: items = [], loader, error, setSort, sort } = listState;
7
+ const { initialLoading, isLoading } = loader;
8
+
9
+ const scope = useMemo(
10
+ () => ({
11
+ items,
12
+ isLoading,
13
+ setSort,
14
+ sort,
15
+ }),
16
+ [items, sort, setSort, isLoading]
17
+ );
18
+
19
+ if (initialLoading) return null;
20
+
21
+ if (!items || items.length === 0) {
22
+ return null;
23
+ }
24
+
25
+ if (error) {
26
+ return null;
27
+ }
28
+
29
+ if (renderItem) {
30
+ return (
31
+ <div className="react-list-items">
32
+ {items.map((item, index) => (
33
+ <div key={item.id || index}>{renderItem({ item, index })}</div>
34
+ ))}
35
+ </div>
36
+ );
37
+ }
38
+
39
+ if (typeof children === "function") {
40
+ return <div className="react-list-items">{children(scope)}</div>;
41
+ }
42
+
43
+ return (
44
+ <div className="react-list-items">
45
+ {items.map((item, index) => (
46
+ <pre key={item.id || index}>{JSON.stringify(item, null, 2)}</pre>
47
+ ))}
48
+ </div>
49
+ );
50
+ });
@@ -0,0 +1,361 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { useListContext } from "../context/list-provider";
3
+ import { hasActiveFilters } from "./utils";
4
+
5
+ /**
6
+ * ReactList component for handling data fetching, pagination, and state management
7
+ */
8
+ const ReactList = ({
9
+ initialItems = [],
10
+ children,
11
+ endpoint,
12
+ page = 1,
13
+ perPage = 25,
14
+ sortBy = "",
15
+ sortOrder = "desc",
16
+ count = 0,
17
+ search = "",
18
+ filters = {},
19
+ attrs,
20
+ version = 1,
21
+ paginationMode = "pagination",
22
+ meta = {},
23
+ onResponse,
24
+ afterPageChange,
25
+ afterLoadMore,
26
+ }) => {
27
+ const { requestHandler, setListState, stateManager } = useListContext();
28
+
29
+ const initRef = useRef(false);
30
+
31
+ const isLoadMore = paginationMode === "loadMore";
32
+
33
+ const getContext = useCallback(
34
+ (currentState) => {
35
+ return {
36
+ endpoint,
37
+ version,
38
+ meta,
39
+ search: currentState?.search || search,
40
+ page: currentState?.page || page,
41
+ perPage: currentState?.perPage || perPage,
42
+ sortBy: currentState?.sortBy || sortBy,
43
+ sortOrder: currentState?.sortOrder || sortOrder,
44
+ filters: currentState?.filters || filters,
45
+ attrSettings: currentState?.attrSettings || {},
46
+ isRefresh: false,
47
+ };
48
+ },
49
+ [endpoint, version, meta, search, page, perPage, sortBy, sortOrder, filters]
50
+ );
51
+
52
+ const getSavedState = useCallback(() => {
53
+ try {
54
+ const context = getContext();
55
+ const oldState = stateManager?.get?.(context);
56
+
57
+ return {
58
+ page: oldState?.page,
59
+ perPage: oldState?.perPage,
60
+ sortBy: oldState?.sortBy,
61
+ sortOrder: oldState?.sortOrder,
62
+ search: oldState?.search,
63
+ attrSettings: oldState?.attrSettings,
64
+ filters: oldState?.filters,
65
+ };
66
+ } catch (err) {
67
+ console.error(err);
68
+ return {};
69
+ }
70
+ }, [getContext, stateManager]);
71
+
72
+ const initializeState = useCallback(() => {
73
+ const savedState = getSavedState();
74
+
75
+ let initialPage = page;
76
+ if (isLoadMore) {
77
+ initialPage = 1;
78
+ } else if (savedState.page != null) {
79
+ initialPage = savedState.page;
80
+ }
81
+
82
+ return {
83
+ page: initialPage,
84
+ perPage: savedState.perPage != null ? savedState.perPage : perPage,
85
+ sortBy: savedState.sortBy != null ? savedState.sortBy : sortBy,
86
+ sortOrder:
87
+ savedState.sortOrder != null ? savedState.sortOrder : sortOrder,
88
+ search: savedState.search != null ? savedState.search : search,
89
+ filters: savedState.filters != null ? savedState.filters : filters,
90
+ attrSettings: savedState.attrSettings || {},
91
+ items: initialItems,
92
+ selection: [],
93
+ error: null,
94
+ response: null,
95
+ count: 0,
96
+ isLoading: false,
97
+ initializingState: !initialItems.length,
98
+ confirmedPage: null,
99
+ };
100
+ }, [
101
+ getSavedState,
102
+ search,
103
+ page,
104
+ perPage,
105
+ sortBy,
106
+ sortOrder,
107
+ search,
108
+ filters,
109
+ isLoadMore,
110
+ ]);
111
+
112
+ // Initialize state with default values
113
+ const [state, setState] = useState(initializeState);
114
+
115
+ const updateStateManager = useCallback(
116
+ (stateToSave) => {
117
+ if (stateManager) {
118
+ const context = getContext(stateToSave);
119
+ stateManager?.set?.(context);
120
+ }
121
+ },
122
+ [stateManager, getContext]
123
+ );
124
+
125
+ /**
126
+ * Fetch data from the API
127
+ * @param {Object} addContext - Additional context to pass to the request handler
128
+ * @param {Object} newState - New state to use for the request
129
+ */
130
+ const fetchData = useCallback(
131
+ async (addContext = {}, newState = null) => {
132
+ // Only set loading state if not initializing
133
+ if (!state.initializingState) {
134
+ setState((prev) => ({ ...prev, error: null, isLoading: true }));
135
+ }
136
+
137
+ try {
138
+ const currentState = newState || state;
139
+ const previousItems = newState?.items ?? state.items;
140
+ const res = await requestHandler({
141
+ endpoint,
142
+ version,
143
+ meta,
144
+ page: currentState.page,
145
+ perPage: currentState.perPage,
146
+ search: currentState.search,
147
+ sortBy: currentState.sortBy,
148
+ sortOrder: currentState.sortOrder,
149
+ filters: currentState.filters,
150
+ ...addContext,
151
+ });
152
+
153
+ if (onResponse) onResponse(res);
154
+
155
+ let newItems;
156
+
157
+ if (isLoadMore) {
158
+ newItems =
159
+ currentState.page === 1
160
+ ? res.items
161
+ : [...previousItems, ...res.items];
162
+ if (afterLoadMore) afterLoadMore(res);
163
+ } else {
164
+ newItems = res.items;
165
+ if (afterPageChange) afterPageChange(res);
166
+ }
167
+
168
+ const updatedState = {
169
+ ...currentState,
170
+ response: res,
171
+ selection: [],
172
+ // Append items for loadMore, replace for pagination
173
+ items:
174
+ isLoadMore && currentState.page > 1
175
+ ? [...previousItems, ...res.items]
176
+ : res.items,
177
+ count: res.count,
178
+ initializingState: false,
179
+ isLoading: false,
180
+ };
181
+
182
+ updateStateManager(updatedState);
183
+
184
+ setState(updatedState);
185
+ } catch (err) {
186
+ setState((prev) => ({
187
+ ...prev,
188
+ error: err,
189
+ items: [],
190
+ count: 0,
191
+ initializingState: false,
192
+ isLoading: false,
193
+ }));
194
+ throw err;
195
+ }
196
+ },
197
+ [endpoint, version, isLoadMore, meta, requestHandler, state]
198
+ );
199
+
200
+ /**
201
+ * Handlers for various actions (pagination, sorting, filtering, etc.)
202
+ */
203
+ const handlers = useMemo(
204
+ () => ({
205
+ setPage: (value, addContext) => {
206
+ let newPage = value;
207
+ if (value === 0) {
208
+ newPage = "";
209
+ }
210
+ const newState = { ...state, page: newPage };
211
+ setState(newState);
212
+ if (newPage) fetchData(addContext, newState);
213
+ },
214
+
215
+ setPerPage: (value) => {
216
+ const newState = { ...state, perPage: value, page: 1 };
217
+ setState(newState);
218
+ fetchData({}, newState);
219
+ },
220
+
221
+ setSearch: (value) => {
222
+ // Only update if value changed to prevent unnecessary requests
223
+ if (value !== state.search) {
224
+ const newState = { ...state, search: value, page: 1 };
225
+ setState(newState);
226
+ fetchData({}, newState);
227
+ }
228
+ },
229
+
230
+ setSort: ({ by, order }) => {
231
+ const newState = { ...state, sortBy: by, sortOrder: order, page: 1 };
232
+ setState(newState);
233
+ fetchData({}, newState);
234
+ },
235
+
236
+ loadMore: () => {
237
+ const newState = { ...state, page: state.page + 1 };
238
+ setState(newState);
239
+ fetchData({}, newState);
240
+ },
241
+
242
+ clearFilters: () => {
243
+ const newState = { ...state, filters: filters, page: 1 };
244
+ setState(newState);
245
+ fetchData({}, newState);
246
+ },
247
+
248
+ refresh: (addContext = { isRefresh: true }) => {
249
+ if (isLoadMore) {
250
+ // For loadMore, reset to page 1
251
+ const newState = { ...state, page: 1, items: [] };
252
+ setState(newState);
253
+ fetchData(addContext, newState);
254
+ } else {
255
+ // For pagination, keep current page
256
+ fetchData(addContext);
257
+ }
258
+ },
259
+
260
+ setFilters: (filters) => {
261
+ const newState = { ...state, filters, page: 1 };
262
+ setState(newState);
263
+ fetchData({}, newState);
264
+ },
265
+ updateItemById: (item, id) => {
266
+ const newItems = state.items.map((i) => {
267
+ if (i.id === id) {
268
+ return { ...i, ...item };
269
+ }
270
+ return i;
271
+ });
272
+ setState((prev) => ({ ...prev, items: newItems }));
273
+ },
274
+ setSelection: (selection) => setState((prev) => ({ ...prev, selection })),
275
+ }),
276
+ [fetchData, isLoadMore, state]
277
+ );
278
+
279
+ /**
280
+ * Memoized state for context to prevent unnecessary re-renders
281
+ */
282
+ const memoizedState = useMemo(
283
+ () => ({
284
+ data: state.items,
285
+ response: state.response,
286
+ error: state.error,
287
+ count: state.count,
288
+ selection: state.selection,
289
+ pagination: {
290
+ page: state.page,
291
+ perPage: state.perPage,
292
+ hasMore: state.items.length < state.count,
293
+ },
294
+ loader: {
295
+ isLoading: state.isLoading,
296
+ initialLoading: state.initializingState,
297
+ },
298
+ sort: { sortBy: state.sortBy, sortOrder: state.sortOrder },
299
+ hasActiveFilters: hasActiveFilters(state.filters, filters),
300
+ search: state.search,
301
+ filters: state.filters,
302
+ attrs: attrs || Object.keys(state.items[0] || {}),
303
+ isEmpty: state.items.length === 0,
304
+ ...handlers,
305
+ }),
306
+ [
307
+ state.items,
308
+ state.response,
309
+ state.error,
310
+ state.count,
311
+ state.selection,
312
+ state.page,
313
+ state.perPage,
314
+ state.isLoading,
315
+ state.initializingState,
316
+ state.sortBy,
317
+ state.sortOrder,
318
+ state.search,
319
+ state.filters,
320
+ handlers,
321
+ attrs,
322
+ ]
323
+ );
324
+
325
+ useEffect(() => {
326
+ if (!state.initializingState) {
327
+ return;
328
+ }
329
+ if (!initRef.current) {
330
+ initRef.current = true;
331
+
332
+ // Initialize state manager
333
+ if (stateManager?.init) {
334
+ const context = getContext(state);
335
+ stateManager.init(context);
336
+ }
337
+
338
+ if (!initialItems.length) handlers.setPage(state.page);
339
+ }
340
+ }, []);
341
+
342
+ // Update list state in context
343
+ useEffect(() => {
344
+ setListState(memoizedState);
345
+ }, [
346
+ setListState,
347
+ state.items,
348
+ state.count,
349
+ state.error,
350
+ state.isLoading,
351
+ state.selection,
352
+ state.page,
353
+ state.perPage,
354
+ state.sortBy,
355
+ state.sortOrder,
356
+ ]);
357
+
358
+ return typeof children === "function" ? children(memoizedState) : children;
359
+ };
360
+
361
+ export default ReactList;