| 
									
										
										
										
											2024-11-28 12:26:02 +08:00
										 |  |  | import React, { useCallback } from 'react' | 
					
						
							|  |  |  | import type { IPaginationProps, IUsePagination } from './type' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const usePagination = ({ | 
					
						
							|  |  |  |   currentPage, | 
					
						
							|  |  |  |   setCurrentPage, | 
					
						
							|  |  |  |   truncableText = '...', | 
					
						
							|  |  |  |   truncableClassName = '', | 
					
						
							|  |  |  |   totalPages, | 
					
						
							|  |  |  |   edgePageCount, | 
					
						
							|  |  |  |   middlePagesSiblingCount, | 
					
						
							|  |  |  | }: IPaginationProps): IUsePagination => { | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |   const pages = new Array(totalPages) | 
					
						
							| 
									
										
										
										
											2024-11-28 12:26:02 +08:00
										 |  |  |     .fill(0) | 
					
						
							|  |  |  |     .map((_, i) => i + 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const hasPreviousPage = currentPage > 1 | 
					
						
							|  |  |  |   const hasNextPage = currentPage < totalPages | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isReachedToFirst = currentPage <= middlePagesSiblingCount | 
					
						
							|  |  |  |   const isReachedToLast = currentPage + middlePagesSiblingCount >= totalPages | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const middlePages = React.useMemo(() => { | 
					
						
							|  |  |  |     const middlePageCount = middlePagesSiblingCount * 2 + 1 | 
					
						
							|  |  |  |     if (isReachedToFirst) | 
					
						
							|  |  |  |       return pages.slice(0, middlePageCount) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isReachedToLast) | 
					
						
							|  |  |  |       return pages.slice(-middlePageCount) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pages.slice( | 
					
						
							|  |  |  |       currentPage - middlePagesSiblingCount, | 
					
						
							|  |  |  |       currentPage + middlePagesSiblingCount + 1, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |   }, [currentPage, isReachedToFirst, isReachedToLast, middlePagesSiblingCount, pages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const getAllPreviousPages = useCallback(() => { | 
					
						
							|  |  |  |     return pages.slice(0, middlePages[0] - 1) | 
					
						
							|  |  |  |   }, [middlePages, pages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const previousPages = React.useMemo(() => { | 
					
						
							|  |  |  |     if (isReachedToFirst || getAllPreviousPages().length < 1) | 
					
						
							|  |  |  |       return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pages | 
					
						
							|  |  |  |       .slice(0, edgePageCount) | 
					
						
							|  |  |  |       .filter(p => !middlePages.includes(p)) | 
					
						
							|  |  |  |   }, [edgePageCount, getAllPreviousPages, isReachedToFirst, middlePages, pages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const getAllNextPages = React.useMemo(() => { | 
					
						
							|  |  |  |     return pages.slice( | 
					
						
							|  |  |  |       middlePages[middlePages.length - 1], | 
					
						
							|  |  |  |       pages[pages.length], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |   }, [pages, middlePages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const nextPages = React.useMemo(() => { | 
					
						
							|  |  |  |     if (isReachedToLast) | 
					
						
							|  |  |  |       return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (getAllNextPages.length < 1) | 
					
						
							|  |  |  |       return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pages | 
					
						
							|  |  |  |       .slice(pages.length - edgePageCount, pages.length) | 
					
						
							|  |  |  |       .filter(p => !middlePages.includes(p)) | 
					
						
							|  |  |  |   }, [edgePageCount, getAllNextPages.length, isReachedToLast, middlePages, pages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isPreviousTruncable = React.useMemo(() => { | 
					
						
							|  |  |  |     // Is truncable if first value of middlePage is larger than last value of previousPages
 | 
					
						
							|  |  |  |     return middlePages[0] > previousPages[previousPages.length - 1] + 1 | 
					
						
							|  |  |  |   }, [previousPages, middlePages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isNextTruncable = React.useMemo(() => { | 
					
						
							|  |  |  |     // Is truncable if last value of middlePage is larger than first value of previousPages
 | 
					
						
							|  |  |  |     return middlePages[middlePages.length - 1] + 1 < nextPages[0] | 
					
						
							|  |  |  |   }, [nextPages, middlePages]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     currentPage, | 
					
						
							|  |  |  |     setCurrentPage, | 
					
						
							|  |  |  |     truncableText, | 
					
						
							|  |  |  |     truncableClassName, | 
					
						
							|  |  |  |     pages, | 
					
						
							|  |  |  |     hasPreviousPage, | 
					
						
							|  |  |  |     hasNextPage, | 
					
						
							|  |  |  |     previousPages, | 
					
						
							|  |  |  |     isPreviousTruncable, | 
					
						
							|  |  |  |     middlePages, | 
					
						
							|  |  |  |     isNextTruncable, | 
					
						
							|  |  |  |     nextPages, | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default usePagination |