1 | import React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import { forbidExtraProps } from 'airbnb-prop-types';
|
4 | import { withStyles, withStylesPropTypes } from 'react-with-styles';
|
5 |
|
6 | import { DayPickerNavigationPhrases } from '../defaultPhrases';
|
7 | import getPhrasePropTypes from '../utils/getPhrasePropTypes';
|
8 | import noflip from '../utils/noflip';
|
9 |
|
10 | import LeftArrow from './LeftArrow';
|
11 | import RightArrow from './RightArrow';
|
12 | import ChevronUp from './ChevronUp';
|
13 | import ChevronDown from './ChevronDown';
|
14 | import ScrollableOrientationShape from '../shapes/ScrollableOrientationShape';
|
15 |
|
16 | import {
|
17 | HORIZONTAL_ORIENTATION,
|
18 | VERTICAL_SCROLLABLE,
|
19 | } from '../constants';
|
20 |
|
21 | const propTypes = forbidExtraProps({
|
22 | ...withStylesPropTypes,
|
23 | disablePrev: PropTypes.bool,
|
24 | disableNext: PropTypes.bool,
|
25 | navPrev: PropTypes.node,
|
26 | navNext: PropTypes.node,
|
27 | orientation: ScrollableOrientationShape,
|
28 |
|
29 | onPrevMonthClick: PropTypes.func,
|
30 | onNextMonthClick: PropTypes.func,
|
31 |
|
32 |
|
33 | phrases: PropTypes.shape(getPhrasePropTypes(DayPickerNavigationPhrases)),
|
34 |
|
35 | isRTL: PropTypes.bool,
|
36 | });
|
37 |
|
38 | const defaultProps = {
|
39 | disablePrev: false,
|
40 | disableNext: false,
|
41 | navPrev: null,
|
42 | navNext: null,
|
43 | orientation: HORIZONTAL_ORIENTATION,
|
44 |
|
45 | onPrevMonthClick() {},
|
46 | onNextMonthClick() {},
|
47 |
|
48 |
|
49 | phrases: DayPickerNavigationPhrases,
|
50 | isRTL: false,
|
51 | };
|
52 |
|
53 | function DayPickerNavigation({
|
54 | css,
|
55 | disablePrev,
|
56 | disableNext,
|
57 | navPrev,
|
58 | navNext,
|
59 | onPrevMonthClick,
|
60 | onNextMonthClick,
|
61 | orientation,
|
62 | phrases,
|
63 | isRTL,
|
64 | styles,
|
65 | }) {
|
66 | const isHorizontal = orientation === HORIZONTAL_ORIENTATION;
|
67 | const isVertical = orientation !== HORIZONTAL_ORIENTATION;
|
68 | const isVerticalScrollable = orientation === VERTICAL_SCROLLABLE;
|
69 |
|
70 | let navPrevIcon = navPrev;
|
71 | let navNextIcon = navNext;
|
72 | let isDefaultNavPrev = false;
|
73 | let isDefaultNavNext = false;
|
74 | let navPrevTabIndex = {};
|
75 | let navNextTabIndex = {};
|
76 | if (!navPrevIcon) {
|
77 | navPrevTabIndex = { tabIndex: '0' };
|
78 | isDefaultNavPrev = true;
|
79 | let Icon = isVertical ? ChevronUp : LeftArrow;
|
80 | if (isRTL && !isVertical) {
|
81 | Icon = RightArrow;
|
82 | }
|
83 | navPrevIcon = (
|
84 | <Icon
|
85 | {...css(
|
86 | isHorizontal && styles.DayPickerNavigation_svg__horizontal,
|
87 | isVertical && styles.DayPickerNavigation_svg__vertical,
|
88 | disablePrev && styles.DayPickerNavigation_svg__disabled,
|
89 | )}
|
90 | />
|
91 | );
|
92 | }
|
93 |
|
94 | if (!navNextIcon) {
|
95 | navNextTabIndex = { tabIndex: '0' };
|
96 | isDefaultNavNext = true;
|
97 | let Icon = isVertical ? ChevronDown : RightArrow;
|
98 | if (isRTL && !isVertical) {
|
99 | Icon = LeftArrow;
|
100 | }
|
101 | navNextIcon = (
|
102 | <Icon
|
103 | {...css(
|
104 | isHorizontal && styles.DayPickerNavigation_svg__horizontal,
|
105 | isVertical && styles.DayPickerNavigation_svg__vertical,
|
106 | disableNext && styles.DayPickerNavigation_svg__disabled,
|
107 | )}
|
108 | />
|
109 | );
|
110 | }
|
111 |
|
112 | const isDefaultNav = isVerticalScrollable
|
113 | ? isDefaultNavNext
|
114 | : (isDefaultNavNext || isDefaultNavPrev);
|
115 |
|
116 | return (
|
117 | <div
|
118 | {...css(
|
119 | styles.DayPickerNavigation,
|
120 | isHorizontal && styles.DayPickerNavigation__horizontal,
|
121 | ...(isVertical ? [
|
122 | styles.DayPickerNavigation__vertical,
|
123 | isDefaultNav && styles.DayPickerNavigation__verticalDefault,
|
124 | ] : []),
|
125 | ...(isVerticalScrollable ? [
|
126 | styles.DayPickerNavigation__verticalScrollable,
|
127 | isDefaultNav && styles.DayPickerNavigation__verticalScrollableDefault,
|
128 | ] : []),
|
129 | )}
|
130 | >
|
131 | {!isVerticalScrollable && (
|
132 | <div
|
133 | role="button"
|
134 | {...navPrevTabIndex}
|
135 | {...css(
|
136 | styles.DayPickerNavigation_button,
|
137 | isDefaultNavPrev && styles.DayPickerNavigation_button__default,
|
138 | disablePrev && styles.DayPickerNavigation_button__disabled,
|
139 | ...(isHorizontal ? [
|
140 | styles.DayPickerNavigation_button__horizontal,
|
141 | ...(isDefaultNavPrev ? [
|
142 | styles.DayPickerNavigation_button__horizontalDefault,
|
143 | !isRTL && styles.DayPickerNavigation_leftButton__horizontalDefault,
|
144 | isRTL && styles.DayPickerNavigation_rightButton__horizontalDefault,
|
145 | ] : []),
|
146 | ] : []),
|
147 | ...(isVertical ? [
|
148 | styles.DayPickerNavigation_button__vertical,
|
149 | ...(isDefaultNavPrev ? [
|
150 | styles.DayPickerNavigation_button__verticalDefault,
|
151 | styles.DayPickerNavigation_prevButton__verticalDefault,
|
152 | ] : []),
|
153 | ] : []),
|
154 | )}
|
155 | aria-disabled={disablePrev ? true : undefined}
|
156 | aria-label={phrases.jumpToPrevMonth}
|
157 | onClick={disablePrev ? undefined : onPrevMonthClick}
|
158 | onKeyUp={disablePrev ? undefined : (e) => {
|
159 | const { key } = e;
|
160 | if (key === 'Enter' || key === ' ') onPrevMonthClick(e);
|
161 | }}
|
162 | onMouseUp={disablePrev ? undefined : (e) => {
|
163 | e.currentTarget.blur();
|
164 | }}
|
165 | >
|
166 | {navPrevIcon}
|
167 | </div>
|
168 | )}
|
169 |
|
170 | <div
|
171 | role="button"
|
172 | {...navNextTabIndex}
|
173 | {...css(
|
174 | styles.DayPickerNavigation_button,
|
175 | isDefaultNavNext && styles.DayPickerNavigation_button__default,
|
176 | disableNext && styles.DayPickerNavigation_button__disabled,
|
177 | ...(isHorizontal ? [
|
178 | styles.DayPickerNavigation_button__horizontal,
|
179 | ...(isDefaultNavNext ? [
|
180 | styles.DayPickerNavigation_button__horizontalDefault,
|
181 | isRTL && styles.DayPickerNavigation_leftButton__horizontalDefault,
|
182 | !isRTL && styles.DayPickerNavigation_rightButton__horizontalDefault,
|
183 | ] : []),
|
184 | ] : []),
|
185 | ...(isVertical ? [
|
186 | styles.DayPickerNavigation_button__vertical,
|
187 | styles.DayPickerNavigation_nextButton__vertical,
|
188 | ...(isDefaultNavNext ? [
|
189 | styles.DayPickerNavigation_button__verticalDefault,
|
190 | styles.DayPickerNavigation_nextButton__verticalDefault,
|
191 | isVerticalScrollable
|
192 | && styles.DayPickerNavigation_nextButton__verticalScrollableDefault,
|
193 | ] : []),
|
194 | ] : []),
|
195 | )}
|
196 | aria-disabled={disableNext ? true : undefined}
|
197 | aria-label={phrases.jumpToNextMonth}
|
198 | onClick={disableNext ? undefined : onNextMonthClick}
|
199 | onKeyUp={disableNext ? undefined : (e) => {
|
200 | const { key } = e;
|
201 | if (key === 'Enter' || key === ' ') onNextMonthClick(e);
|
202 | }}
|
203 | onMouseUp={disableNext ? undefined : (e) => {
|
204 | e.currentTarget.blur();
|
205 | }}
|
206 | >
|
207 | {navNextIcon}
|
208 | </div>
|
209 | </div>
|
210 | );
|
211 | }
|
212 |
|
213 | DayPickerNavigation.propTypes = propTypes;
|
214 | DayPickerNavigation.defaultProps = defaultProps;
|
215 |
|
216 | export default withStyles(({ reactDates: { color, zIndex } }) => ({
|
217 | DayPickerNavigation: {
|
218 | position: 'relative',
|
219 | zIndex: zIndex + 2,
|
220 | },
|
221 |
|
222 | DayPickerNavigation__horizontal: {
|
223 | height: 0,
|
224 | },
|
225 |
|
226 | DayPickerNavigation__vertical: {},
|
227 | DayPickerNavigation__verticalScrollable: {},
|
228 |
|
229 | DayPickerNavigation__verticalDefault: {
|
230 | position: 'absolute',
|
231 | width: '100%',
|
232 | height: 52,
|
233 | bottom: 0,
|
234 | left: noflip(0),
|
235 | },
|
236 |
|
237 | DayPickerNavigation__verticalScrollableDefault: {
|
238 | position: 'relative',
|
239 | },
|
240 |
|
241 | DayPickerNavigation_button: {
|
242 | cursor: 'pointer',
|
243 | userSelect: 'none',
|
244 | border: 0,
|
245 | padding: 0,
|
246 | margin: 0,
|
247 | },
|
248 |
|
249 | DayPickerNavigation_button__default: {
|
250 | border: `1px solid ${color.core.borderLight}`,
|
251 | backgroundColor: color.background,
|
252 | color: color.placeholderText,
|
253 |
|
254 | ':focus': {
|
255 | border: `1px solid ${color.core.borderMedium}`,
|
256 | },
|
257 |
|
258 | ':hover': {
|
259 | border: `1px solid ${color.core.borderMedium}`,
|
260 | },
|
261 |
|
262 | ':active': {
|
263 | background: color.backgroundDark,
|
264 | },
|
265 | },
|
266 |
|
267 | DayPickerNavigation_button__disabled: {
|
268 | cursor: 'default',
|
269 | border: `1px solid ${color.disabled}`,
|
270 |
|
271 | ':focus': {
|
272 | border: `1px solid ${color.disabled}`,
|
273 | },
|
274 |
|
275 | ':hover': {
|
276 | border: `1px solid ${color.disabled}`,
|
277 | },
|
278 |
|
279 | ':active': {
|
280 | background: 'none',
|
281 | },
|
282 | },
|
283 |
|
284 | DayPickerNavigation_button__horizontal: {
|
285 | },
|
286 |
|
287 | DayPickerNavigation_button__horizontalDefault: {
|
288 | position: 'absolute',
|
289 | top: 18,
|
290 | lineHeight: 0.78,
|
291 | borderRadius: 3,
|
292 | padding: '6px 9px',
|
293 | },
|
294 |
|
295 | DayPickerNavigation_leftButton__horizontalDefault: {
|
296 | left: noflip(22),
|
297 | },
|
298 |
|
299 | DayPickerNavigation_rightButton__horizontalDefault: {
|
300 | right: noflip(22),
|
301 | },
|
302 |
|
303 | DayPickerNavigation_button__vertical: {
|
304 | },
|
305 |
|
306 | DayPickerNavigation_button__verticalDefault: {
|
307 | padding: 5,
|
308 | background: color.background,
|
309 | boxShadow: noflip('0 0 5px 2px rgba(0, 0, 0, 0.1)'),
|
310 | position: 'relative',
|
311 | display: 'inline-block',
|
312 | textAlign: 'center',
|
313 | height: '100%',
|
314 | width: '50%',
|
315 | },
|
316 |
|
317 | DayPickerNavigation_prevButton__verticalDefault: {
|
318 | },
|
319 |
|
320 | DayPickerNavigation_nextButton__verticalDefault: {
|
321 | borderLeft: noflip(0),
|
322 | },
|
323 |
|
324 | DayPickerNavigation_nextButton__verticalScrollableDefault: {
|
325 | width: '100%',
|
326 | },
|
327 |
|
328 | DayPickerNavigation_svg__horizontal: {
|
329 | height: 19,
|
330 | width: 19,
|
331 | fill: color.core.grayLight,
|
332 | display: 'block',
|
333 | },
|
334 |
|
335 | DayPickerNavigation_svg__vertical: {
|
336 | height: 42,
|
337 | width: 42,
|
338 | fill: color.text,
|
339 | },
|
340 |
|
341 | DayPickerNavigation_svg__disabled: {
|
342 | fill: color.disabled,
|
343 | },
|
344 | }), { pureComponent: typeof React.PureComponent !== 'undefined' })(DayPickerNavigation);
|