1 |
|
2 | import React, { PureComponent } from 'react';
|
3 | import PropTypes from 'prop-types';
|
4 | import styled from 'styled-components';
|
5 |
|
6 | const 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 |
|
173 | class 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 |
|
268 | Paginate.defaultProps = {
|
269 | count: 0,
|
270 | perPage: 5,
|
271 | func: {},
|
272 | };
|
273 |
|
274 | Paginate.propTypes = {
|
275 | count: PropTypes.number,
|
276 | perPage: PropTypes.number,
|
277 | func: PropTypes.func,
|
278 | };
|
279 |
|
280 | export default Paginate;
|