Skip to content

Commit c62974b

Browse files
committed
Initial commit
0 parents  commit c62974b

4 files changed

Lines changed: 174 additions & 0 deletions

File tree

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Basic
2+
.DS_Store
3+
4+
# IDE
5+
/.idea
6+
/.vscode

__test__/pagination.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { calculatePagination } from '../index'
2+
3+
it('should return no pagination if not enough items are given', () => {
4+
const page = 1
5+
const size = 5
6+
const total = 2
7+
const pagination = calculatePagination(page, size, total)
8+
9+
expect(pagination).toBeNull()
10+
})
11+
it('should return only a few pages', () => {
12+
const page = 2
13+
const size = 5
14+
const total = 15
15+
const pagination = calculatePagination(page, size, total)
16+
17+
expect(pagination?.pages).toHaveLength(3)
18+
19+
expect(pagination.pages[0].number).toBe(1)
20+
expect(pagination.pages[0].isCurrentPage).toBeFalsy()
21+
expect(pagination.pages[1].number).toBe(2)
22+
expect(pagination.pages[1].isCurrentPage).toBeTruthy()
23+
expect(pagination.pages[2].number).toBe(3)
24+
expect(pagination.pages[2].isCurrentPage).toBeFalsy()
25+
})
26+
it('should return the maximum number of pages', () => {
27+
const page = 5
28+
const size = 5
29+
const total = 50
30+
const maxPages = 5
31+
const pagination = calculatePagination(page, size, total, maxPages)
32+
33+
expect(pagination?.pages).toHaveLength(5)
34+
35+
expect(pagination.pages[0].number).toBe(3)
36+
expect(pagination.pages[0].isCurrentPage).toBeFalsy()
37+
expect(pagination.pages[1].number).toBe(4)
38+
expect(pagination.pages[1].isCurrentPage).toBeFalsy()
39+
expect(pagination.pages[2].number).toBe(5)
40+
expect(pagination.pages[2].isCurrentPage).toBeTruthy()
41+
expect(pagination.pages[3].number).toBe(6)
42+
expect(pagination.pages[3].isCurrentPage).toBeFalsy()
43+
expect(pagination.pages[4].number).toBe(7)
44+
expect(pagination.pages[4].isCurrentPage).toBeFalsy()
45+
})
46+
it('should disable the previous link', () => {
47+
const page = 1
48+
const size = 5
49+
const total = 10
50+
const pagination = calculatePagination(page, size, total)
51+
52+
expect(pagination.previous.number).toBe(1)
53+
expect(pagination.previous.isDisabled).toBeTruthy()
54+
55+
expect(pagination.next.number).toBe(2)
56+
expect(pagination.next.isDisabled).toBeFalsy()
57+
58+
expect(pagination?.pages[0].isCurrentPage).toBeTruthy()
59+
expect(pagination?.pages[1].isCurrentPage).toBeFalsy()
60+
})
61+
it('should disable the next link', () => {
62+
const page = 2
63+
const size = 5
64+
const total = 10
65+
const pagination = calculatePagination(page, size, total)
66+
67+
expect(pagination.previous.number).toBe(1)
68+
expect(pagination.previous.isDisabled).toBeFalsy()
69+
70+
expect(pagination.next.number).toBe(2)
71+
expect(pagination.next.isDisabled).toBeTruthy()
72+
73+
expect(pagination?.pages[0].isCurrentPage).toBeFalsy()
74+
expect(pagination?.pages[1].isCurrentPage).toBeTruthy()
75+
})

index.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const calculateVisiblePages = (
2+
page: number,
3+
total: number,
4+
maxPages: number
5+
): number[] => {
6+
const range = Math.floor(maxPages / 2)
7+
let lowerBound = 1
8+
let lowerBoundRest = 0
9+
let upperBound = total
10+
let upperBoundRest = 0
11+
12+
if (page - range >= 1) {
13+
lowerBound = page - range
14+
} else {
15+
lowerBoundRest = (page - range - 1) * -1
16+
}
17+
18+
if (page + range <= total) {
19+
upperBound = page + range
20+
} else {
21+
upperBoundRest = (total - range - page) * -1
22+
}
23+
24+
if (upperBoundRest > 0) {
25+
lowerBound =
26+
lowerBound - upperBoundRest > 0 ? lowerBound - upperBoundRest : 1
27+
}
28+
29+
if (lowerBoundRest > 0) {
30+
upperBound =
31+
upperBound + lowerBoundRest < total ? upperBound + lowerBoundRest : total
32+
}
33+
34+
const pages = []
35+
36+
for (let i = lowerBound; i <= upperBound; i++) {
37+
pages.push(i)
38+
}
39+
40+
return pages
41+
}
42+
43+
const calculatePagination = (
44+
page: number,
45+
size: number,
46+
total: number,
47+
maxPages: number = 5
48+
): {
49+
previous: {
50+
number: number
51+
isDisabled: boolean
52+
}
53+
next: {
54+
number: number
55+
isDisabled: boolean
56+
}
57+
pages: {
58+
number: number
59+
isCurrentPage: boolean
60+
}[]
61+
} | null => {
62+
if (total <= size) {
63+
return null
64+
}
65+
66+
const lastPage = Math.ceil(total / size)
67+
const isCurrentTheFirstPage = page === 1
68+
const isCurrentTheLastPage = page === lastPage
69+
70+
return {
71+
previous: {
72+
number: isCurrentTheFirstPage ? 1 : page - 1,
73+
isDisabled: isCurrentTheFirstPage,
74+
},
75+
next: {
76+
number: isCurrentTheLastPage ? lastPage : page + 1,
77+
isDisabled: isCurrentTheLastPage,
78+
},
79+
pages: calculateVisiblePages(page, lastPage, maxPages).map(
80+
(visiblePage) => {
81+
return {
82+
number: visiblePage,
83+
isCurrentPage: visiblePage === page,
84+
}
85+
}
86+
),
87+
}
88+
}
89+
90+
export { calculatePagination }

readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Pagination
2+
==========
3+

0 commit comments

Comments
 (0)