UNPKG

3.67 kBJavaScriptView Raw
1"use strict";
2'use client';
3
4var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8exports.default = usePagination;
9var _useControlled = _interopRequireDefault(require("@mui/utils/useControlled"));
10function usePagination(props = {}) {
11 // keep default values in sync with @default tags in Pagination.propTypes
12 const {
13 boundaryCount = 1,
14 componentName = 'usePagination',
15 count = 1,
16 defaultPage = 1,
17 disabled = false,
18 hideNextButton = false,
19 hidePrevButton = false,
20 onChange: handleChange,
21 page: pageProp,
22 showFirstButton = false,
23 showLastButton = false,
24 siblingCount = 1,
25 ...other
26 } = props;
27 const [page, setPageState] = (0, _useControlled.default)({
28 controlled: pageProp,
29 default: defaultPage,
30 name: componentName,
31 state: 'page'
32 });
33 const handleClick = (event, value) => {
34 if (!pageProp) {
35 setPageState(value);
36 }
37 if (handleChange) {
38 handleChange(event, value);
39 }
40 };
41
42 // https://dev.to/namirsab/comment/2050
43 const range = (start, end) => {
44 const length = end - start + 1;
45 return Array.from({
46 length
47 }, (_, i) => start + i);
48 };
49 const startPages = range(1, Math.min(boundaryCount, count));
50 const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count);
51 const siblingsStart = Math.max(Math.min(
52 // Natural start
53 page - siblingCount,
54 // Lower boundary when page is high
55 count - boundaryCount - siblingCount * 2 - 1),
56 // Greater than startPages
57 boundaryCount + 2);
58 const siblingsEnd = Math.min(Math.max(
59 // Natural end
60 page + siblingCount,
61 // Upper boundary when page is low
62 boundaryCount + siblingCount * 2 + 2),
63 // Less than endPages
64 count - boundaryCount - 1);
65
66 // Basic list of items to render
67 // for example itemList = ['first', 'previous', 1, 'ellipsis', 4, 5, 6, 'ellipsis', 10, 'next', 'last']
68 const itemList = [...(showFirstButton ? ['first'] : []), ...(hidePrevButton ? [] : ['previous']), ...startPages,
69 // Start ellipsis
70 // eslint-disable-next-line no-nested-ternary
71 ...(siblingsStart > boundaryCount + 2 ? ['start-ellipsis'] : boundaryCount + 1 < count - boundaryCount ? [boundaryCount + 1] : []),
72 // Sibling pages
73 ...range(siblingsStart, siblingsEnd),
74 // End ellipsis
75 // eslint-disable-next-line no-nested-ternary
76 ...(siblingsEnd < count - boundaryCount - 1 ? ['end-ellipsis'] : count - boundaryCount > boundaryCount ? [count - boundaryCount] : []), ...endPages, ...(hideNextButton ? [] : ['next']), ...(showLastButton ? ['last'] : [])];
77
78 // Map the button type to its page number
79 const buttonPage = type => {
80 switch (type) {
81 case 'first':
82 return 1;
83 case 'previous':
84 return page - 1;
85 case 'next':
86 return page + 1;
87 case 'last':
88 return count;
89 default:
90 return null;
91 }
92 };
93
94 // Convert the basic item list to PaginationItem props objects
95 const items = itemList.map(item => {
96 return typeof item === 'number' ? {
97 onClick: event => {
98 handleClick(event, item);
99 },
100 type: 'page',
101 page: item,
102 selected: item === page,
103 disabled,
104 'aria-current': item === page ? 'true' : undefined
105 } : {
106 onClick: event => {
107 handleClick(event, buttonPage(item));
108 },
109 type: item,
110 page: buttonPage(item),
111 selected: false,
112 disabled: disabled || !item.includes('ellipsis') && (item === 'next' || item === 'last' ? page >= count : page <= 1)
113 };
114 });
115 return {
116 items,
117 ...other
118 };
119}
\No newline at end of file