UNPKG

6.41 kBJavaScriptView Raw
1/* Paginate on pen https://codepen.io/rafacdb/pen/mwxwQa */
2import React, { PureComponent } from 'react';
3import PropTypes from 'prop-types';
4import styled from 'styled-components';
5
6const PaginateStyled = styled.ul`
7 display: flex;
8 flex-wrap: nowrap;
9 justify-content: center;
10 align-items: center;
11 list-style-type: none;
12
13 li a {
14 display: flex;
15 flex-wrap: nowrap;
16 justify-content: center;
17 align-items: center;
18 }
19
20 li {
21 background-color: ${props => props.theme.bahPaginateBackgroundColor};
22 display: none;
23 }
24
25 a {
26 font-weight: 300;
27 padding-top: 1px;
28 text-decoration: none;
29 border: 1px solid rgba(0, 0, 0, .25);
30 border-left-width: 0;
31 min-width: 44px;
32 min-height: 44px;
33 color: rgba(255, 255, 255, .85);
34 box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, .35);
35 }
36
37 li:not([class*="current"]) a:hover {
38 background-color: rgba(255, 255, 255, .2);
39 border-top-color: rgba(0, 0, 0, .35);
40 border-bottom-color: rgba(0, 0, 0, .5);
41 }
42
43 li:not([class*="current"]) a:focus,
44 li:not([class*="current"]) a:active {
45 box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, .25);
46 border-left-width: 1px;
47 }
48
49 li:first-of-type a {
50 border-left-width: 1px;
51 }
52
53 li:first-of-type span,
54 li:last-of-type span,
55 li:nth-of-type(2) span,
56 li:nth-last-of-type(2) span {
57 /* screen readers only */
58 position: absolute;
59 top: -9999px;
60 left: -9999px;
61 }
62
63 li:first-child a::before,
64 li:last-child a::after,
65 li:nth-of-type(2) a::before,
66 li:nth-last-of-type(2) a::after {
67 display: inline-block;
68 font-size: inherit;
69 text-rendering: auto;
70 -webkit-font-smoothing: antialiased;
71 -moz-osx-font-smoothing: grayscale;
72 transform: translate(0, 0);
73 }
74
75 li:first-child a::before,
76 li:last-child a::after {
77 content: "<<";
78 }
79
80 li:nth-of-type(2) a::before,
81 li:nth-last-of-type(2) a::after {
82 content: "<";
83 }
84
85 li:last-child a::after,
86 li:nth-last-of-type(2) a::after {
87 transform: rotate(180deg);
88 }
89
90 li:nth-last-child(-n + 2) {
91 display: inline-block;
92 }
93
94 li:nth-child(n + ${props => props.start}):nth-child(-n + ${props => props.end}) {
95 display: inline-block;
96 }
97 li:nth-child(-n + 2) {
98 display: inline-block;
99 }
100
101 li.current a {
102 color: rgba(255, 255, 255, 1);
103 background-color: rgba(255, 255, 255, .15);
104 box-shadow: inset 0px 2px 1px 0px rgba(0, 0, 0, .25);
105 cursor: default;
106 pointer-events: none;
107 }
108
109 @media only screen and (max-width: 64.063em) {
110 li:first-child,
111 li:last-child {
112 /* screen readers only */
113 position: absolute;
114 top: -9999px;
115 left: -9999px;
116 }
117 li:nth-of-type(2) a {
118 border-left-width: 1px;
119 }
120 }
121
122 @media only screen and (max-width: 40.063em) {
123 li {
124 /* screen readers only */
125 position: absolute;
126 top: -9999px;
127 left: -9999px;
128 }
129
130 li.current,
131 li:first-of-type,
132 li:last-of-type,
133 li:nth-of-type(2),
134 li:nth-last-of-type(2) {
135 position: initial;
136 top: initial;
137 left: initial;
138 }
139 li:nth-of-type(2) a {
140 border-left-width: 0;
141 }
142 }
143
144 @media only screen and (max-width: 30.063em) {
145 h1 {
146 font-size: 1.35em !important;
147 }
148 li:first-child,
149 li:last-child {
150 /* screen readers only */
151 position: absolute;
152 top: -9999px;
153 left: -9999px;
154 }
155 li:nth-of-type(2) a {
156 border-left-width: 1px;
157 }
158 }
159
160 @media only screen and (max-width: 15.063em) {
161 /* For watches? */
162 li {
163 width: 50%;
164 }
165 li.current {
166 order: 2;
167 width: 100%;
168 border-left-width: 1px;
169 }
170 }
171`;
172
173class Paginate extends PureComponent {
174 constructor(props) {
175 super(props);
176 this.state = { linkId: 0, linkActive: false, skip: 0, start: 3, end: 12 };
177
178 this.handleClick = link => () => {
179 let newSkip;
180 const { start, end, skip } = this.state;
181 const { perPage, count, func } = this.props;
182
183 if (link.id === 'Previous') {
184 newSkip = skip !== 0 ? skip - perPage : skip;
185 } else if (link.id === 'Next') {
186 newSkip = skip <= count && skip + perPage < count ? skip + perPage : skip;
187 } else if (link.id === 'First') {
188 newSkip = 0;
189 if (start - 3 < link.pages && start !== 3) {
190 this.setState({ start: start - 10, end: end - 10 });
191 }
192 } else if (link.id === 'Last') {
193 newSkip = link.skip;
194 if (end - 2 < link.pages) {
195 this.setState({ start: start + 10, end: end + 10 });
196 }
197 } else {
198 newSkip = link.skip;
199 }
200 func(perPage, newSkip);
201 this.setState({ linkId: link.id, linkActive: true, skip: newSkip });
202 };
203
204 this.buttonPages = link =>
205 (<li
206 key={`li-${link.id}`}
207 className={
208 this.state.linkId === link.id &&
209 this.state.linkActive &&
210 link.id !== 'First' &&
211 link.id !== 'Previous' &&
212 link.id !== 'Next' &&
213 link.id !== 'Last'
214 ? 'current'
215 : ''
216 }
217 >
218 <a href="#" onClick={this.handleClick(link)}>
219 <span>
220 {link.id}
221 </span>
222 </a>
223 </li>);
224
225 this.generatePageLinks = () => {
226 let pagesCount = this.props.count / this.props.perPage;
227 pagesCount = Math.ceil(pagesCount);
228
229 const links = [];
230 let skip = 0;
231
232 for (let i = 1; i <= pagesCount; i++) {
233 if (i === 1) {
234 links.push({ id: 'First', skip, pages: pagesCount });
235 links.push({
236 id: 'Previous',
237 skip,
238 pages: pagesCount,
239 });
240 }
241
242 links.push({ id: i, skip, pages: pagesCount });
243
244 if (i === pagesCount) {
245 links.push({ id: 'Next', skip, pages: pagesCount });
246 links.push({
247 id: 'Last',
248 skip,
249 pages: pagesCount,
250 });
251 }
252 skip += this.props.perPage;
253 }
254
255 return links.map(link => this.buttonPages(link));
256 };
257 }
258
259 render() {
260 return (
261 <PaginateStyled start={this.state.start} end={this.state.end}>
262 {this.generatePageLinks()}
263 </PaginateStyled>
264 );
265 }
266}
267
268Paginate.defaultProps = {
269 count: 0,
270 perPage: 5,
271 func: {},
272};
273
274Paginate.propTypes = {
275 count: PropTypes.number,
276 perPage: PropTypes.number,
277 func: PropTypes.func,
278};
279
280export default Paginate;