diff --git a/readme.md b/readme.md index 1d62e16..0aac788 100644 --- a/readme.md +++ b/readme.md @@ -24,7 +24,9 @@ Second, you can call the calculate function by passing the following information - `page`: The current page - `size`: The amount of items shown per page - `total`: The amount of total items in the list/collection -- `maxPages`: The maximum amount of pages that should be shown (default: 5) +- `config`: A configuration object containing the following possible configuration values: + - `firstPage`: The first page of the pagination (default: 1) + - `maxPages`: The maximum amount of pages that should be shown (default: 5) In return, you receive an object with all relevant information: diff --git a/src/__test__/pagination-with-first-page-0.test.ts b/src/__test__/pagination-with-first-page-0.test.ts new file mode 100644 index 0000000..f450b50 --- /dev/null +++ b/src/__test__/pagination-with-first-page-0.test.ts @@ -0,0 +1,84 @@ +import { calculatePagination } from '../index' + +it('should return no pagination if not enough items are given', () => { + const page = 0 + const size = 5 + const total = 2 + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) + + expect(pagination).toBeNull() +}) +it('should return only a few pages', () => { + const page = 1 + const size = 5 + const total = 15 + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) + + expect(pagination).not.toBeNull() + expect(pagination?.pages).toHaveLength(3) + + expect(pagination?.pages[0].number).toBe(0) + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].number).toBe(1) + expect(pagination?.pages[1].isCurrent).toBeTruthy() + expect(pagination?.pages[2].number).toBe(2) + expect(pagination?.pages[2].isCurrent).toBeFalsy() +}) +it('should return the maximum number of pages', () => { + const page = 4 + const size = 5 + const total = 50 + const maxPages = 5 + const pagination = calculatePagination(page, size, total, { + firstPage: 0, + maxPages: maxPages, + }) + + expect(pagination).not.toBeNull() + expect(pagination?.pages).toHaveLength(5) + + expect(pagination?.pages[0].number).toBe(2) + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].number).toBe(3) + expect(pagination?.pages[1].isCurrent).toBeFalsy() + expect(pagination?.pages[2].number).toBe(4) + expect(pagination?.pages[2].isCurrent).toBeTruthy() + expect(pagination?.pages[3].number).toBe(5) + expect(pagination?.pages[3].isCurrent).toBeFalsy() + expect(pagination?.pages[4].number).toBe(6) + expect(pagination?.pages[4].isCurrent).toBeFalsy() +}) +it('should disable the previous link', () => { + const page = 0 + const size = 5 + const total = 10 + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) + + expect(pagination).not.toBeNull() + + expect(pagination?.previous.number).toBe(0) + expect(pagination?.previous.isDisabled).toBeTruthy() + + expect(pagination?.next.number).toBe(1) + expect(pagination?.next.isDisabled).toBeFalsy() + + expect(pagination?.pages[0].isCurrent).toBeTruthy() + expect(pagination?.pages[1].isCurrent).toBeFalsy() +}) +it('should disable the next link', () => { + const page = 1 + const size = 5 + const total = 10 + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) + + expect(pagination).not.toBeNull() + + expect(pagination?.previous.number).toBe(0) + expect(pagination?.previous.isDisabled).toBeFalsy() + + expect(pagination?.next.number).toBe(1) + expect(pagination?.next.isDisabled).toBeTruthy() + + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].isCurrent).toBeTruthy() +}) diff --git a/src/__test__/pagination.test.ts b/src/__test__/pagination-with-first-page-1.test.ts similarity index 96% rename from src/__test__/pagination.test.ts rename to src/__test__/pagination-with-first-page-1.test.ts index c66e582..33f3879 100644 --- a/src/__test__/pagination.test.ts +++ b/src/__test__/pagination-with-first-page-1.test.ts @@ -29,7 +29,9 @@ it('should return the maximum number of pages', () => { const size = 5 const total = 50 const maxPages = 5 - const pagination = calculatePagination(page, size, total, maxPages) + const pagination = calculatePagination(page, size, total, { + maxPages: maxPages, + }) expect(pagination).not.toBeNull() expect(pagination?.pages).toHaveLength(5) diff --git a/src/index.ts b/src/index.ts index 1a5d0d8..b5f3436 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,13 @@ const calculateVisiblePages = ( page: number, - total: number, + firstPage: number, + lastPage: number, maxPages: number ): number[] => { const range = Math.floor(maxPages / 2) - let lowerBound = 1 + let lowerBound = firstPage let lowerBoundRest = 0 - let upperBound = total + let upperBound = lastPage let upperBoundRest = 0 if (page - range >= 1) { @@ -15,20 +16,22 @@ const calculateVisiblePages = ( lowerBoundRest = (page - range - 1) * -1 } - if (page + range <= total) { + if (page + range <= lastPage) { upperBound = page + range } else { - upperBoundRest = (total - range - page) * -1 + upperBoundRest = (lastPage - range - page) * -1 } if (upperBoundRest > 0) { lowerBound = - lowerBound - upperBoundRest > 0 ? lowerBound - upperBoundRest : 1 + lowerBound - upperBoundRest > 0 ? lowerBound - upperBoundRest : firstPage } if (lowerBoundRest > 0) { upperBound = - upperBound + lowerBoundRest < total ? upperBound + lowerBoundRest : total + upperBound + lowerBoundRest < lastPage + ? upperBound + lowerBoundRest + : lastPage } const pages = [] @@ -44,7 +47,10 @@ const calculatePagination = ( page: number, size: number, total: number, - maxPages = 5 + config?: { + firstPage?: number + maxPages?: number + } ): { previous: { number: number @@ -63,20 +69,23 @@ const calculatePagination = ( return null } - const lastPage = Math.ceil(total / size) - const isCurrentTheFirstPage = page === 1 + const firstPage = config?.firstPage ?? 1 + const maxPages = config?.maxPages ?? 5 + + const lastPage = Math.ceil(total / size) + (firstPage - 1) + const isCurrentTheFirstPage = page === firstPage const isCurrentTheLastPage = page === lastPage return { previous: { - number: isCurrentTheFirstPage ? 1 : page - 1, + number: isCurrentTheFirstPage ? firstPage : page - 1, isDisabled: isCurrentTheFirstPage, }, next: { number: isCurrentTheLastPage ? lastPage : page + 1, isDisabled: isCurrentTheLastPage, }, - pages: calculateVisiblePages(page, lastPage, maxPages).map( + pages: calculateVisiblePages(page, firstPage, lastPage, maxPages).map( (visiblePage) => { return { number: visiblePage,