UNPKG

9.61 kBJSXView Raw
1import React from 'react';
2import PropTypes from 'prop-types';
3import { forbidExtraProps } from 'airbnb-prop-types';
4import { withStyles, withStylesPropTypes } from 'react-with-styles';
5
6import { DayPickerNavigationPhrases } from '../defaultPhrases';
7import getPhrasePropTypes from '../utils/getPhrasePropTypes';
8import noflip from '../utils/noflip';
9
10import LeftArrow from './LeftArrow';
11import RightArrow from './RightArrow';
12import ChevronUp from './ChevronUp';
13import ChevronDown from './ChevronDown';
14import ScrollableOrientationShape from '../shapes/ScrollableOrientationShape';
15
16import {
17 HORIZONTAL_ORIENTATION,
18 VERTICAL_SCROLLABLE,
19} from '../constants';
20
21const 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 // internationalization
33 phrases: PropTypes.shape(getPhrasePropTypes(DayPickerNavigationPhrases)),
34
35 isRTL: PropTypes.bool,
36});
37
38const defaultProps = {
39 disablePrev: false,
40 disableNext: false,
41 navPrev: null,
42 navNext: null,
43 orientation: HORIZONTAL_ORIENTATION,
44
45 onPrevMonthClick() {},
46 onNextMonthClick() {},
47
48 // internationalization
49 phrases: DayPickerNavigationPhrases,
50 isRTL: false,
51};
52
53function 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 // eslint-disable-line jsx-a11y/interactive-supports-focus
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 // eslint-disable-line jsx-a11y/interactive-supports-focus
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
213DayPickerNavigation.propTypes = propTypes;
214DayPickerNavigation.defaultProps = defaultProps;
215
216export 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);