Skip to content

Commit 097d359

Browse files
committed
fix: CPagination: component rewrite according to Vue functionality
1 parent 99586ab commit 097d359

File tree

1 file changed

+182
-111
lines changed

1 file changed

+182
-111
lines changed

src/CPagination.js

+182-111
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,219 @@
1-
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import classNames from 'classnames';
4-
import {tagPropType, mapToCssModules} from './Shared/helper.js';
5-
import CPaginationItem from './CPaginationItem';
6-
import CPaginationLink from './CPaginationLink';
7-
8-
export const Context = React.createContext({});
1+
import React, { useEffect } from 'react'
2+
import PropTypes from 'prop-types'
3+
import classNames from 'classnames'
4+
import { mapToCssModules } from './Shared/helper.js'
5+
import CLink from './CLink'
96

107
//component - CoreUI / CPagination
11-
12-
const CPagination = props=>{
8+
const CPagination = props => {
139

1410
const {
15-
tag: Tag,
16-
children,
1711
className,
1812
cssModule,
19-
custom,
2013
//
2114
innerRef,
22-
listClassName,
23-
pageFrom,
24-
pageTo,
25-
pageMin,
26-
pageMax,
15+
addListClass,
2716
activePage,
2817
size,
29-
firstButtonHtml,
30-
previousButtonHtml,
31-
nextButtonHtml,
32-
lastButtonHtml,
33-
hideDots,
34-
//hideArrows,
35-
//hideDoubleArrows,
36-
listTag: ListTag,
37-
'aria-label': label,
38-
listProps,
39-
onClick,
18+
firstButton,
19+
previousButton,
20+
nextButton,
21+
lastButton,
22+
dots,
23+
arrows,
24+
doubleArrows,
25+
limit,
26+
pages,
27+
align,
28+
onActivePageChange,
4029
...attributes
4130
} = props;
4231

43-
44-
const paginationClick = (e, type, n)=>{
45-
onClick && onClick(e, type, n);
46-
}
32+
useEffect(() => {
33+
pages < activePage && onActivePageChange(pages, true)
34+
}, [pages])
4735

4836
//render
49-
50-
const classes = mapToCssModules(classNames(
51-
className
52-
), cssModule);
53-
5437
const listClasses = mapToCssModules(classNames(
55-
listClassName,
5638
'pagination',
57-
{
58-
[`pagination-${size}`]: !!size,
39+
size && 'pagination-' + size,
40+
'justify-content-' + align,
41+
addListClass
42+
), cssModule)
43+
44+
const backArrowsClasses = mapToCssModules(classNames(
45+
'page-item',
46+
activePage === 1 && 'disabled'
47+
), cssModule)
48+
49+
const nextArrowsClasses = mapToCssModules(classNames(
50+
'page-item',
51+
activePage === pages && 'disabled'
52+
), cssModule)
53+
54+
const showDots = (() => {
55+
return dots && limit > 4 && limit < pages
56+
})()
57+
const maxPrevItems = (() => {
58+
return Math.floor((limit - 1) / 2)
59+
})()
60+
const maxNextItems = (() => {
61+
return Math.ceil((limit - 1) / 2)
62+
})()
63+
const beforeDots = (() => {
64+
return showDots && activePage > maxPrevItems + 1
65+
})()
66+
const afterDots = (() => {
67+
return showDots && activePage < pages - maxNextItems
68+
})()
69+
const computedLimit = (() => {
70+
return limit - afterDots - beforeDots
71+
})()
72+
const range = (() => {
73+
return activePage + maxNextItems
74+
})()
75+
const lastItem = (() => {
76+
return range >= pages ? pages : range - afterDots
77+
})()
78+
const itemsAmount = (() => {
79+
return pages < computedLimit ? pages : computedLimit
80+
})()
81+
const items = (() => {
82+
if (activePage - maxPrevItems <= 1) {
83+
return Array.from({
84+
length: itemsAmount
85+
}, (v, i) => i + 1)
86+
} else {
87+
return Array.from({
88+
length: itemsAmount
89+
}, (v, i) => {
90+
return lastItem - i
91+
}).reverse()
5992
}
60-
), cssModule);
61-
62-
let autoChildren;
93+
})()
6394

64-
if (!custom){
65-
let list=[];
66-
let pageAutoFrom = pageFrom;
67-
let pageAutoTo = pageTo;
68-
if (!pageFrom || !pageTo){
69-
pageAutoFrom = activePage-3;
70-
pageAutoFrom < pageMin ? (pageAutoFrom = pageMin) : null;
71-
pageAutoTo = activePage+3;
72-
pageAutoTo > pageMax ? (pageAutoTo = pageMax) : null;
95+
const setPage = (number) => {
96+
if (number !== activePage) {
97+
onActivePageChange(number)
7398
}
74-
for (let i=pageAutoFrom;i<=pageAutoTo;i++)
75-
list.push(<CPaginationItem key={i} active={activePage==i?true:false}><CPaginationLink type="number" n={i}>{i}</CPaginationLink></CPaginationItem>);
76-
const pagesBefore = pageAutoFrom>pageMin;
77-
const pagesAfter = pageAutoTo<pageMax;
78-
autoChildren = (
79-
<React.Fragment>
80-
{pagesBefore&&firstButtonHtml?<CPaginationItem><CPaginationLink type="first">{firstButtonHtml}</CPaginationLink></CPaginationItem>:''}
81-
{pagesBefore&&previousButtonHtml?<CPaginationItem><CPaginationLink type="previous">{previousButtonHtml}</CPaginationLink></CPaginationItem>:''}
82-
{!hideDots&&pagesBefore?<CPaginationItem><CPaginationLink type="less">...</CPaginationLink></CPaginationItem>:''}
83-
{list}
84-
{!hideDots&&pagesAfter?<CPaginationItem><CPaginationLink type="more">...</CPaginationLink></CPaginationItem>:''}
85-
{pagesAfter&&nextButtonHtml?<CPaginationItem><CPaginationLink type="next">{nextButtonHtml}</CPaginationLink></CPaginationItem>:''}
86-
{pagesAfter&&lastButtonHtml?<CPaginationItem><CPaginationLink type="last">{lastButtonHtml}</CPaginationLink></CPaginationItem>:''}
87-
</React.Fragment>
88-
)
8999
}
90100

91101
return (
92-
<Context.Provider value={{
93-
paginationClick
94-
}}>
95-
<Tag {...attributes} className={classes} aria-label={label} ref={innerRef}>
96-
<ListTag className={listClasses} {...listProps}>
97-
{autoChildren||children}
98-
</ListTag>
99-
</Tag>
100-
</Context.Provider>
101-
);
102+
<nav
103+
className={className}
104+
aria-label="pagination"
105+
{...attributes}
106+
ref={innerRef}
107+
>
108+
<ul className={listClasses}>
109+
{ doubleArrows &&
110+
<li className={backArrowsClasses}>
111+
<CLink
112+
className="page-link"
113+
onClick={ () => setPage(1)}
114+
aria-label="Go to first page"
115+
aria-disabled={activePage === 1}
116+
>
117+
{ firstButton }
118+
</CLink>
119+
</li>
120+
}
121+
{ arrows &&
122+
<li className={backArrowsClasses}>
123+
<CLink
124+
className="page-link"
125+
onClick={ () => setPage(activePage - 1)}
126+
aria-label="Go to previous page"
127+
aria-disabled={activePage === 1}
128+
>
129+
{ previousButton }
130+
</CLink>
131+
</li>
132+
}
133+
{ beforeDots &&
134+
<li role="separator" className="page-item disabled">
135+
<span className="page-link"></span>
136+
</li>
137+
}
138+
{ items.map(i => {
139+
return (
140+
<li className={`${activePage===i ? 'active' : ''} page-item`} key={i}>
141+
<CLink
142+
className="page-link"
143+
onClick={(e) => setPage(i, e)}
144+
aria-label={activePage === i ? `Current page ${i}` : `Go to page ${i}`}
145+
>{i}</CLink>
146+
</li>)
147+
})
148+
}
149+
{ afterDots &&
150+
<li role="separator" className="page-item disabled">
151+
<span className="page-link"></span>
152+
</li>
153+
}
154+
{ arrows &&
155+
<li className={nextArrowsClasses}>
156+
<CLink
157+
className="page-link"
158+
onClick={ () => setPage(activePage + 1)}
159+
aria-label="Go to next page"
160+
aria-disabled={activePage === pages}
161+
>
162+
{ nextButton }
163+
</CLink>
164+
</li>
165+
}
166+
{ doubleArrows &&
167+
<li className={nextArrowsClasses}>
168+
<CLink
169+
className="page-link"
170+
onClick={ () => setPage(pages)}
171+
aria-label="Go to last page"
172+
aria-disabled={activePage === pages}
173+
>
174+
{ lastButton }
175+
</CLink>
176+
</li>
177+
}
178+
</ul>
179+
</nav>
180+
)
102181

103182
}
104183

105184
CPagination.propTypes = {
106-
tag: tagPropType,
107-
children: PropTypes.node,
108185
className: PropTypes.string,
109186
cssModule: PropTypes.object,
110-
custom: PropTypes.bool,
111187
//
112188
innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func, PropTypes.string]),
113-
pageMin: PropTypes.number,
114-
pageMax: PropTypes.number,
115-
pageFrom: PropTypes.number,
116-
pageTo: PropTypes.number,
117189
activePage: PropTypes.number,
118-
hideDots: PropTypes.bool,
119-
hideArrows: PropTypes.bool,
120-
hideDoubleArrows: PropTypes.bool,
121-
firstButtonHtml: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
122-
previousButtonHtml: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
123-
nextButtonHtml: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
124-
lastButtonHtml: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
125-
size: PropTypes.string,
126-
listTag: tagPropType,
127-
'aria-label': PropTypes.string,
128-
listClassName: PropTypes.string,
129-
listProps: PropTypes.object,
130-
onClick: PropTypes.func
190+
dots: PropTypes.bool,
191+
arrows: PropTypes.bool,
192+
doubleArrows: PropTypes.bool,
193+
firstButton: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
194+
previousButton: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
195+
nextButton: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
196+
lastButton: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
197+
size: PropTypes.oneOf(['', 'sm', 'lg']),
198+
align: PropTypes.oneOf(['start', 'center', 'end']),
199+
addListClass: PropTypes.string,
200+
limit: PropTypes.number,
201+
pages: PropTypes.number,
202+
onActivePageChange: PropTypes.func.isRequired
131203
};
132204

133205
CPagination.defaultProps = {
134-
custom: true,
135-
tag: 'nav',
136-
listTag: 'ul',
137-
'aria-label': 'pagination',
138-
pageMin: 1,
139-
pageMax: 5,
140-
activePage: 2,
141-
hideDots: true,
142-
firstButtonHtml: <React.Fragment>&laquo;</React.Fragment>,
143-
previousButtonHtml: <React.Fragment>&lsaquo;</React.Fragment>,
144-
nextButtonHtml: <React.Fragment>&rsaquo;</React.Fragment>,
145-
lastButtonHtml: <React.Fragment>&raquo;</React.Fragment>,
206+
activePage: 1,
207+
dots: true,
208+
arrows: true,
209+
doubleArrows: true,
210+
limit: 5,
211+
firstButton: <>&laquo;</>,
212+
previousButton: <>&lsaquo;</>,
213+
nextButton: <>&rsaquo;</>,
214+
lastButton: <>&raquo;</>,
215+
align: 'start',
216+
pages: 10
146217
};
147218

148-
export default CPagination;
219+
export default CPagination

0 commit comments

Comments
 (0)