@matthew.ngo/react-filter-pilot
Version:
Powerful filtering, pagination, and sorting for React with TanStack Query integration
3 lines • 7.54 kB
JavaScript
import {a}from'../chunk-KDVV4H2M.js';import {useMemo,useState,useRef,useEffect,useCallback}from'react';import {useQuery}from'@tanstack/react-query';import {getDefaultFilters,parseUrlParams,mergeFilters,buildSyncableUrlParams,transformFilterValue,isFilterActive}from'../utils';import {useDefaultUrlHandler}from'./useUrlHandler';import {useFetchControl}from'./useAdvancedFetchControl';import {normalizeQueryKey}from'../utils/normalize';/* @matthew.ngo/react-filter-pilot - MIT License */
function _e(H){const{filterConfigs:c,paginationConfig:i={},sortConfig:u={},fetchConfig:n,urlHandler:J,initialFiltersProvider:V,enablePresets:C=false}=H,Y=useDefaultUrlHandler(),D=useMemo(()=>J||Y,[J]),f=useMemo(()=>getDefaultFilters(c),[c]),v=useMemo(()=>({page:i.initialPage||1,pageSize:i.initialPageSize||10,totalPages:0,totalRecords:0,hasNextPage:false,hasPreviousPage:false}),[i.initialPage,i.initialPageSize]),Z=useMemo(()=>u.initialSortField?{field:u.initialSortField,direction:u.initialSortDirection||"asc"}:void 0,[u.initialSortField,u.initialSortDirection]),[S,z]=useState(f),[d,F]=useState(v),[p,E]=useState(Z),[W,M]=useState([]),[m,O]=useState(f),T=useRef({}),K=useRef(false),L=useMemo(()=>{const e=new Set;return c.forEach(t=>{if(t.syncWithUrl!==false){const r=t.urlKey||t.name;e.add(r);}}),i.syncWithUrl!==false&&(e.add("page"),e.add("pageSize")),u.syncWithUrl!==false&&(e.add("sortBy"),e.add("sortOrder")),e},[c,i.syncWithUrl,u.syncWithUrl]);useEffect(()=>{if(K.current)return;a(async()=>{const t=D.getParams(),r=parseUrlParams(t,c);let s=f;if(V)try{const g=await V();s=mergeFilters(g,f);}catch{}const h=mergeFilters(r,s);if(z(h),O(h),i.syncWithUrl!==false){const g=parseInt(t.get("page")||"1",10),y=parseInt(t.get("pageSize")||String(v.pageSize),10);F(G=>({...G,page:g,pageSize:y}));}if(u.syncWithUrl!==false){const g=t.get("sortBy"),y=t.get("sortOrder");g&&E({field:g,direction:y||"asc"});}K.current=true;},"initializeFromUrl")();},[]);const o=useCallback((e,t,r)=>{if(!K.current)return;const s=D.getParams(),h=e!==void 0?e:m,g=t?{...d,...t}:d,y=r!==void 0?r:p;L.forEach(_=>{s.delete(_);}),buildSyncableUrlParams(h,c).forEach((_,fe)=>{s.set(fe,_);}),i.syncWithUrl!==false&&(s.set("page",String(g.page)),s.set("pageSize",String(g.pageSize))),u.syncWithUrl!==false&&y&&(s.set("sortBy",y.field),s.set("sortOrder",y.direction)),D.setParams(s);},[c,i.syncWithUrl,u.syncWithUrl,D,d,p,m,L]),$=useCallback((e,t)=>{const r=c.find(s=>s.name===e);r?.debounceMs?(T.current[e]&&clearTimeout(T.current[e]),T.current[e]=setTimeout(()=>{O(s=>({...s,[e]:t})),i.resetOnFilterChange!==false&&(!i.resetPageOnFilterChange||i.resetPageOnFilterChange(e))&&F(s=>({...s,page:1}));},r.debounceMs)):(O(s=>({...s,[e]:t})),i.resetOnFilterChange!==false&&(!i.resetPageOnFilterChange||i.resetPageOnFilterChange(e))&&F(s=>({...s,page:1})));},[c,i.resetOnFilterChange,i.resetPageOnFilterChange]),k=useMemo(()=>{const e=normalizeQueryKey(n.queryKey),t=JSON.stringify(m),r=JSON.stringify({page:d.page,pageSize:d.pageSize}),s=JSON.stringify(p);return [...e,"filters",t,"pagination",r,"sort",s]},[n.queryKey,m,d.page,d.pageSize,p]),{shouldFetch:x,fetchReason:ee,controlledFetch:B}=useFetchControl(m,H.fetchControl),te=useCallback(async()=>{const e={filters:m,pagination:{page:d.page,pageSize:d.pageSize},sort:p},t={...e};return t.filters={},Object.entries(e.filters).forEach(([r,s])=>{const h=c.find(y=>y.name===r),g=transformFilterValue(s,h?.transformForApi);t.filters[r]=g;}),B(()=>n.fetchFn(t))},[m,d.page,d.pageSize,p,c,n.fetchFn,B]),a$1=useQuery({queryKey:k,queryFn:te,enabled:n.enabled!==false&&x&&K.current,staleTime:n.staleTime,gcTime:n.gcTime||n.cacheTime,refetchOnWindowFocus:n.refetchOnWindowFocus,refetchInterval:n.refetchInterval,refetchIntervalInBackground:n.refetchIntervalInBackground,select:n.select,placeholderData:n.placeholderData,initialData:n.initialData,initialDataUpdatedAt:n.initialDataUpdatedAt,retry:n.retry,retryDelay:n.retryDelay,networkMode:n.networkMode,meta:n.meta,queryKeyHashFn:n.queryKeyHashFn,structuralSharing:n.structuralSharing}),j=useRef();useEffect(()=>{a$1.isSuccess&&a$1.data&&j.current!==a$1.data.totalRecords&&(j.current=a$1.data.totalRecords,F(e=>({...e,totalRecords:a$1.data.totalRecords,totalPages:Math.ceil(a$1.data.totalRecords/e.pageSize),hasNextPage:e.page<Math.ceil(a$1.data.totalRecords/e.pageSize),hasPreviousPage:e.page>1})),n.onSuccess?.(a$1.data));},[a$1.isSuccess,a$1.data?.totalRecords,n.onSuccess]),useEffect(()=>{a$1.isError&&a$1.error&&n.onError?.(a$1.error);},[a$1.isError,a$1.error,n.onError]);const I=useCallback((e,t)=>{const r=c.find(h=>h.name===String(e)),s={...S,[e]:t};z(s),r?.syncWithUrl!==false&&(r?.debounceMs?(T.current[`url_${String(e)}`]&&clearTimeout(T.current[`url_${String(e)}`]),T.current[`url_${String(e)}`]=setTimeout(()=>{o(s);},r.debounceMs)):o(s)),$(String(e),t);},[o,$,c]),w=useCallback(e=>{const t={...S,...e};z(t),o(t),O(t),i.resetOnFilterChange!==false&&(!i.resetPageOnFilterChange||Object.keys(e).some(s=>i.resetPageOnFilterChange&&i.resetPageOnFilterChange(s)))&&F(s=>({...s,page:1}));},[S,o,i.resetOnFilterChange,i.resetPageOnFilterChange]),N=useCallback(()=>{z(f),O(f),o(f),F(e=>({...e,page:1}));},[f,o]),Q=useCallback(e=>{const t=f[e];I(e,t);},[f,I]),re=useCallback(e=>{F(t=>({...t,page:e})),o(void 0,{page:e});},[o]),se=useCallback(e=>{const t={pageSize:e,page:1};F(r=>({...r,...t})),o(void 0,t);},[o]),ne=useCallback(()=>{F(e=>{if(e.hasNextPage){const t=e.page+1;return o(void 0,{page:t}),{...e,page:t}}return e});},[o]),ie=useCallback(()=>{F(e=>{if(e.hasPreviousPage){const t=e.page-1;return o(void 0,{page:t}),{...e,page:t}}return e});},[o]),ae=useCallback((e,t="asc")=>{const r={field:e,direction:t};E(r),o(void 0,void 0,r);},[o]),oe=useCallback(e=>{E(t=>{let r;return !t||t.field!==e?r={field:e,direction:"asc"}:t.direction==="asc"?r={field:e,direction:"desc"}:r=void 0,o(void 0,void 0,r),r});},[o]),le=useCallback(()=>{E(void 0),o(void 0,void 0,void 0);},[o]),q=useCallback(()=>Object.entries(S).reduce((e,[t,r])=>{const s=c.find(h=>h.name===t);return isFilterActive(r,s?.defaultValue)?e+1:e},0),[S,c]),ce=useCallback(()=>q()>0,[q]),de=useCallback(()=>k,[k]),ge=useMemo(()=>{if(C)return {savePreset:a(e=>{const t={id:Date.now().toString(),name:e,filters:S,createdAt:new Date};M(r=>[...r,t]);try{const r=`filterPilot_presets_${n.queryKey||"default"}`;localStorage.setItem(r,JSON.stringify([...W,t]));}catch{}},"savePreset"),loadPreset:a(e=>{w(e.filters);},"loadPreset"),deletePreset:a(e=>{M(t=>t.filter(r=>r.id!==e));try{const t=`filterPilot_presets_${n.queryKey||"default"}`,r=W.filter(s=>s.id!==e);localStorage.setItem(t,JSON.stringify(r));}catch{}},"deletePreset"),getPresets:a(()=>W,"getPresets")}},[C,S,W,w,n.queryKey]);useEffect(()=>{if(C)try{const e=`filterPilot_presets_${n.queryKey||"default"}`,t=localStorage.getItem(e);t&&M(JSON.parse(t));}catch{}},[C,n.queryKey]),useEffect(()=>()=>{Object.values(T.current).forEach(clearTimeout);},[]);const ue=useMemo(()=>({setFilterValue:I,setFilters:w,resetFilters:N,resetFilter:Q}),[I,w,N,Q]);return {filters:S,...ue,pagination:d,setPage:re,setPageSize:se,nextPage:ne,previousPage:ie,sort:p,setSort:ae,toggleSort:oe,clearSort:le,data:a$1.data?.data,isLoading:a$1.isLoading,isError:a$1.isError,error:a$1.error||void 0,isFetching:a$1.isFetching,refetch:a$1.refetch,presets:ge,getActiveFiltersCount:q,hasActiveFilters:ce,getQueryKey:de,fetchControl:{isEnabled:x,reason:ee,retry:a$1.refetch}}}a(_e,"useFilterPilot");export{_e as useFilterPilot};//# sourceMappingURL=useFilterPilot.js.map
//# sourceMappingURL=useFilterPilot.js.map