1 | import React from 'react';
|
2 | import moment from 'moment';
|
3 | import { withStyles, withStylesPropTypes } from 'react-with-styles';
|
4 | import { Portal } from 'react-portal';
|
5 | import { forbidExtraProps } from 'airbnb-prop-types';
|
6 | import { addEventListener } from 'consolidated-events';
|
7 | import isTouchDevice from 'is-touch-device';
|
8 | import OutsideClickHandler from 'react-outside-click-handler';
|
9 |
|
10 | import DateRangePickerShape from '../shapes/DateRangePickerShape';
|
11 | import { DateRangePickerPhrases } from '../defaultPhrases';
|
12 |
|
13 | import getResponsiveContainerStyles from '../utils/getResponsiveContainerStyles';
|
14 | import getDetachedContainerStyles from '../utils/getDetachedContainerStyles';
|
15 | import getInputHeight from '../utils/getInputHeight';
|
16 | import isInclusivelyAfterDay from '../utils/isInclusivelyAfterDay';
|
17 | import disableScroll from '../utils/disableScroll';
|
18 | import noflip from '../utils/noflip';
|
19 |
|
20 | import DateRangePickerInputController from './DateRangePickerInputController';
|
21 | import DayPickerRangeController from './DayPickerRangeController';
|
22 | import CloseButton from './CloseButton';
|
23 |
|
24 | import {
|
25 | START_DATE,
|
26 | END_DATE,
|
27 | HORIZONTAL_ORIENTATION,
|
28 | VERTICAL_ORIENTATION,
|
29 | ANCHOR_LEFT,
|
30 | ANCHOR_RIGHT,
|
31 | OPEN_DOWN,
|
32 | OPEN_UP,
|
33 | DAY_SIZE,
|
34 | ICON_BEFORE_POSITION,
|
35 | INFO_POSITION_BOTTOM,
|
36 | FANG_HEIGHT_PX,
|
37 | DEFAULT_VERTICAL_SPACING,
|
38 | } from '../constants';
|
39 |
|
40 | const propTypes = forbidExtraProps({
|
41 | ...withStylesPropTypes,
|
42 | ...DateRangePickerShape,
|
43 | });
|
44 |
|
45 | const defaultProps = {
|
46 |
|
47 | startDate: null,
|
48 | endDate: null,
|
49 | focusedInput: null,
|
50 |
|
51 |
|
52 | startDatePlaceholderText: 'Start Date',
|
53 | endDatePlaceholderText: 'End Date',
|
54 | startDateAriaLabel: undefined,
|
55 | endDateAriaLabel: undefined,
|
56 | startDateOffset: undefined,
|
57 | endDateOffset: undefined,
|
58 | disabled: false,
|
59 | required: false,
|
60 | readOnly: false,
|
61 | screenReaderInputMessage: '',
|
62 | showClearDates: false,
|
63 | showDefaultInputIcon: false,
|
64 | inputIconPosition: ICON_BEFORE_POSITION,
|
65 | customInputIcon: null,
|
66 | customArrowIcon: null,
|
67 | customCloseIcon: null,
|
68 | noBorder: false,
|
69 | block: false,
|
70 | small: false,
|
71 | regular: false,
|
72 | keepFocusOnInput: false,
|
73 |
|
74 |
|
75 | renderMonthText: null,
|
76 | renderWeekHeaderElement: null,
|
77 | orientation: HORIZONTAL_ORIENTATION,
|
78 | anchorDirection: ANCHOR_LEFT,
|
79 | openDirection: OPEN_DOWN,
|
80 | horizontalMargin: 0,
|
81 | withPortal: false,
|
82 | withFullScreenPortal: false,
|
83 | appendToBody: false,
|
84 | disableScroll: false,
|
85 | initialVisibleMonth: null,
|
86 | numberOfMonths: 2,
|
87 | keepOpenOnDateSelect: false,
|
88 | reopenPickerOnClearDates: false,
|
89 | renderCalendarInfo: null,
|
90 | calendarInfoPosition: INFO_POSITION_BOTTOM,
|
91 | hideKeyboardShortcutsPanel: false,
|
92 | daySize: DAY_SIZE,
|
93 | isRTL: false,
|
94 | firstDayOfWeek: null,
|
95 | verticalHeight: null,
|
96 | transitionDuration: undefined,
|
97 | verticalSpacing: DEFAULT_VERTICAL_SPACING,
|
98 | horizontalMonthPadding: undefined,
|
99 |
|
100 |
|
101 | navPrev: null,
|
102 | navNext: null,
|
103 |
|
104 | onPrevMonthClick() {},
|
105 | onNextMonthClick() {},
|
106 |
|
107 | onClose() {},
|
108 |
|
109 |
|
110 | renderCalendarDay: undefined,
|
111 | renderDayContents: null,
|
112 | renderMonthElement: null,
|
113 | minimumNights: 1,
|
114 | enableOutsideDays: false,
|
115 | isDayBlocked: () => false,
|
116 | isOutsideRange: (day) => !isInclusivelyAfterDay(day, moment()),
|
117 | isDayHighlighted: () => false,
|
118 |
|
119 |
|
120 | displayFormat: () => moment.localeData().longDateFormat('L'),
|
121 | monthFormat: 'MMMM YYYY',
|
122 | weekDayFormat: 'dd',
|
123 | phrases: DateRangePickerPhrases,
|
124 | dayAriaLabelFormat: undefined,
|
125 | };
|
126 |
|
127 | class DateRangePicker extends React.PureComponent {
|
128 | constructor(props) {
|
129 | super(props);
|
130 | this.state = {
|
131 | dayPickerContainerStyles: {},
|
132 | isDateRangePickerInputFocused: false,
|
133 | isDayPickerFocused: false,
|
134 | showKeyboardShortcuts: false,
|
135 | };
|
136 |
|
137 | this.isTouchDevice = false;
|
138 |
|
139 | this.onOutsideClick = this.onOutsideClick.bind(this);
|
140 | this.onDateRangePickerInputFocus = this.onDateRangePickerInputFocus.bind(this);
|
141 | this.onDayPickerFocus = this.onDayPickerFocus.bind(this);
|
142 | this.onDayPickerFocusOut = this.onDayPickerFocusOut.bind(this);
|
143 | this.onDayPickerBlur = this.onDayPickerBlur.bind(this);
|
144 | this.showKeyboardShortcutsPanel = this.showKeyboardShortcutsPanel.bind(this);
|
145 |
|
146 | this.responsivizePickerPosition = this.responsivizePickerPosition.bind(this);
|
147 | this.disableScroll = this.disableScroll.bind(this);
|
148 |
|
149 | this.setDayPickerContainerRef = this.setDayPickerContainerRef.bind(this);
|
150 | this.setContainerRef = this.setContainerRef.bind(this);
|
151 | }
|
152 |
|
153 | componentDidMount() {
|
154 | this.removeEventListener = addEventListener(
|
155 | window,
|
156 | 'resize',
|
157 | this.responsivizePickerPosition,
|
158 | { passive: true },
|
159 | );
|
160 | this.responsivizePickerPosition();
|
161 | this.disableScroll();
|
162 |
|
163 | const { focusedInput } = this.props;
|
164 | if (focusedInput) {
|
165 | this.setState({
|
166 | isDateRangePickerInputFocused: true,
|
167 | });
|
168 | }
|
169 |
|
170 | this.isTouchDevice = isTouchDevice();
|
171 | }
|
172 |
|
173 | componentDidUpdate(prevProps) {
|
174 | const { focusedInput } = this.props;
|
175 | if (!prevProps.focusedInput && focusedInput && this.isOpened()) {
|
176 |
|
177 | this.responsivizePickerPosition();
|
178 | this.disableScroll();
|
179 | } else if (prevProps.focusedInput && !focusedInput && !this.isOpened()) {
|
180 |
|
181 | if (this.enableScroll) this.enableScroll();
|
182 | }
|
183 | }
|
184 |
|
185 | componentWillUnmount() {
|
186 | this.removeDayPickerEventListeners();
|
187 | if (this.removeEventListener) this.removeEventListener();
|
188 | if (this.enableScroll) this.enableScroll();
|
189 | }
|
190 |
|
191 | onOutsideClick(event) {
|
192 | const {
|
193 | onFocusChange,
|
194 | onClose,
|
195 | startDate,
|
196 | endDate,
|
197 | appendToBody,
|
198 | } = this.props;
|
199 |
|
200 | if (!this.isOpened()) return;
|
201 | if (appendToBody && this.dayPickerContainer.contains(event.target)) return;
|
202 |
|
203 | this.setState({
|
204 | isDateRangePickerInputFocused: false,
|
205 | isDayPickerFocused: false,
|
206 | showKeyboardShortcuts: false,
|
207 | });
|
208 |
|
209 | onFocusChange(null);
|
210 | onClose({ startDate, endDate });
|
211 | }
|
212 |
|
213 | onDateRangePickerInputFocus(focusedInput) {
|
214 | const {
|
215 | onFocusChange,
|
216 | readOnly,
|
217 | withPortal,
|
218 | withFullScreenPortal,
|
219 | keepFocusOnInput,
|
220 | } = this.props;
|
221 |
|
222 | if (focusedInput) {
|
223 | const withAnyPortal = withPortal || withFullScreenPortal;
|
224 | const moveFocusToDayPicker = withAnyPortal
|
225 | || (readOnly && !keepFocusOnInput)
|
226 | || (this.isTouchDevice && !keepFocusOnInput);
|
227 |
|
228 | if (moveFocusToDayPicker) {
|
229 | this.onDayPickerFocus();
|
230 | } else {
|
231 | this.onDayPickerBlur();
|
232 | }
|
233 | }
|
234 |
|
235 | onFocusChange(focusedInput);
|
236 | }
|
237 |
|
238 | onDayPickerFocus() {
|
239 | const { focusedInput, onFocusChange } = this.props;
|
240 | if (!focusedInput) onFocusChange(START_DATE);
|
241 |
|
242 | this.setState({
|
243 | isDateRangePickerInputFocused: false,
|
244 | isDayPickerFocused: true,
|
245 | showKeyboardShortcuts: false,
|
246 | });
|
247 | }
|
248 |
|
249 | onDayPickerFocusOut(event) {
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 | const relatedTarget = event.relatedTarget === document.body
|
257 | ? event.target
|
258 | : (event.relatedTarget || event.target);
|
259 | if (this.dayPickerContainer.contains(relatedTarget)) return;
|
260 | this.onOutsideClick(event);
|
261 | }
|
262 |
|
263 | onDayPickerBlur() {
|
264 | this.setState({
|
265 | isDateRangePickerInputFocused: true,
|
266 | isDayPickerFocused: false,
|
267 | showKeyboardShortcuts: false,
|
268 | });
|
269 | }
|
270 |
|
271 | setDayPickerContainerRef(ref) {
|
272 | if (ref === this.dayPickerContainer) return;
|
273 | if (this.dayPickerContainer) this.removeDayPickerEventListeners();
|
274 |
|
275 | this.dayPickerContainer = ref;
|
276 | if (!ref) return;
|
277 |
|
278 | this.addDayPickerEventListeners();
|
279 | }
|
280 |
|
281 | setContainerRef(ref) {
|
282 | this.container = ref;
|
283 | }
|
284 |
|
285 | addDayPickerEventListeners() {
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 | this.removeDayPickerFocusOut = addEventListener(
|
293 | this.dayPickerContainer,
|
294 | 'focusout',
|
295 | this.onDayPickerFocusOut,
|
296 | );
|
297 | }
|
298 |
|
299 | removeDayPickerEventListeners() {
|
300 | if (this.removeDayPickerFocusOut) this.removeDayPickerFocusOut();
|
301 | }
|
302 |
|
303 | isOpened() {
|
304 | const { focusedInput } = this.props;
|
305 | return focusedInput === START_DATE || focusedInput === END_DATE;
|
306 | }
|
307 |
|
308 | disableScroll() {
|
309 | const { appendToBody, disableScroll: propDisableScroll } = this.props;
|
310 | if (!appendToBody && !propDisableScroll) return;
|
311 | if (!this.isOpened()) return;
|
312 |
|
313 |
|
314 |
|
315 |
|
316 | this.enableScroll = disableScroll(this.container);
|
317 | }
|
318 |
|
319 | responsivizePickerPosition() {
|
320 |
|
321 |
|
322 | const { dayPickerContainerStyles } = this.state;
|
323 |
|
324 | if (Object.keys(dayPickerContainerStyles).length > 0) {
|
325 | this.setState({ dayPickerContainerStyles: {} });
|
326 | }
|
327 |
|
328 | if (!this.isOpened()) {
|
329 | return;
|
330 | }
|
331 |
|
332 | const {
|
333 | openDirection,
|
334 | anchorDirection,
|
335 | horizontalMargin,
|
336 | withPortal,
|
337 | withFullScreenPortal,
|
338 | appendToBody,
|
339 | } = this.props;
|
340 |
|
341 | const isAnchoredLeft = anchorDirection === ANCHOR_LEFT;
|
342 | if (!withPortal && !withFullScreenPortal) {
|
343 | const containerRect = this.dayPickerContainer.getBoundingClientRect();
|
344 | const currentOffset = dayPickerContainerStyles[anchorDirection] || 0;
|
345 | const containerEdge = isAnchoredLeft
|
346 | ? containerRect[ANCHOR_RIGHT]
|
347 | : containerRect[ANCHOR_LEFT];
|
348 |
|
349 | this.setState({
|
350 | dayPickerContainerStyles: {
|
351 | ...getResponsiveContainerStyles(
|
352 | anchorDirection,
|
353 | currentOffset,
|
354 | containerEdge,
|
355 | horizontalMargin,
|
356 | ),
|
357 | ...(appendToBody && getDetachedContainerStyles(
|
358 | openDirection,
|
359 | anchorDirection,
|
360 | this.container,
|
361 | )),
|
362 | },
|
363 | });
|
364 | }
|
365 | }
|
366 |
|
367 | showKeyboardShortcutsPanel() {
|
368 | this.setState({
|
369 | isDateRangePickerInputFocused: false,
|
370 | isDayPickerFocused: true,
|
371 | showKeyboardShortcuts: true,
|
372 | });
|
373 | }
|
374 |
|
375 | maybeRenderDayPickerWithPortal() {
|
376 | const { withPortal, withFullScreenPortal, appendToBody } = this.props;
|
377 |
|
378 | if (!this.isOpened()) {
|
379 | return null;
|
380 | }
|
381 |
|
382 | if (withPortal || withFullScreenPortal || appendToBody) {
|
383 | return (
|
384 | <Portal>
|
385 | {this.renderDayPicker()}
|
386 | </Portal>
|
387 | );
|
388 | }
|
389 |
|
390 | return this.renderDayPicker();
|
391 | }
|
392 |
|
393 | renderDayPicker() {
|
394 | const {
|
395 | anchorDirection,
|
396 | css,
|
397 | openDirection,
|
398 | isDayBlocked,
|
399 | isDayHighlighted,
|
400 | isOutsideRange,
|
401 | numberOfMonths,
|
402 | orientation,
|
403 | monthFormat,
|
404 | renderMonthText,
|
405 | renderWeekHeaderElement,
|
406 | navPrev,
|
407 | navNext,
|
408 | onPrevMonthClick,
|
409 | onNextMonthClick,
|
410 | onDatesChange,
|
411 | onFocusChange,
|
412 | withPortal,
|
413 | withFullScreenPortal,
|
414 | daySize,
|
415 | enableOutsideDays,
|
416 | focusedInput,
|
417 | startDate,
|
418 | startDateOffset,
|
419 | endDate,
|
420 | endDateOffset,
|
421 | minimumNights,
|
422 | keepOpenOnDateSelect,
|
423 | renderCalendarDay,
|
424 | renderDayContents,
|
425 | renderCalendarInfo,
|
426 | renderMonthElement,
|
427 | calendarInfoPosition,
|
428 | firstDayOfWeek,
|
429 | initialVisibleMonth,
|
430 | hideKeyboardShortcutsPanel,
|
431 | customCloseIcon,
|
432 | onClose,
|
433 | phrases,
|
434 | dayAriaLabelFormat,
|
435 | isRTL,
|
436 | weekDayFormat,
|
437 | styles,
|
438 | verticalHeight,
|
439 | transitionDuration,
|
440 | verticalSpacing,
|
441 | horizontalMonthPadding,
|
442 | small,
|
443 | disabled,
|
444 | theme: { reactDates },
|
445 | } = this.props;
|
446 |
|
447 | const { dayPickerContainerStyles, isDayPickerFocused, showKeyboardShortcuts } = this.state;
|
448 |
|
449 | const onOutsideClick = (!withFullScreenPortal && withPortal)
|
450 | ? this.onOutsideClick
|
451 | : undefined;
|
452 | const initialVisibleMonthThunk = initialVisibleMonth || (
|
453 | () => (startDate || endDate || moment())
|
454 | );
|
455 |
|
456 | const closeIcon = customCloseIcon || (
|
457 | <CloseButton {...css(styles.DateRangePicker_closeButton_svg)} />
|
458 | );
|
459 |
|
460 | const inputHeight = getInputHeight(reactDates, small);
|
461 |
|
462 | const withAnyPortal = withPortal || withFullScreenPortal;
|
463 |
|
464 | return (
|
465 | <div
|
466 | ref={this.setDayPickerContainerRef}
|
467 | {...css(
|
468 | styles.DateRangePicker_picker,
|
469 | anchorDirection === ANCHOR_LEFT && styles.DateRangePicker_picker__directionLeft,
|
470 | anchorDirection === ANCHOR_RIGHT && styles.DateRangePicker_picker__directionRight,
|
471 | orientation === HORIZONTAL_ORIENTATION && styles.DateRangePicker_picker__horizontal,
|
472 | orientation === VERTICAL_ORIENTATION && styles.DateRangePicker_picker__vertical,
|
473 | !withAnyPortal && openDirection === OPEN_DOWN && {
|
474 | top: inputHeight + verticalSpacing,
|
475 | },
|
476 | !withAnyPortal && openDirection === OPEN_UP && {
|
477 | bottom: inputHeight + verticalSpacing,
|
478 | },
|
479 | withAnyPortal && styles.DateRangePicker_picker__portal,
|
480 | withFullScreenPortal && styles.DateRangePicker_picker__fullScreenPortal,
|
481 | isRTL && styles.DateRangePicker_picker__rtl,
|
482 | dayPickerContainerStyles,
|
483 | )}
|
484 | onClick={onOutsideClick}
|
485 | >
|
486 | <DayPickerRangeController
|
487 | orientation={orientation}
|
488 | enableOutsideDays={enableOutsideDays}
|
489 | numberOfMonths={numberOfMonths}
|
490 | onPrevMonthClick={onPrevMonthClick}
|
491 | onNextMonthClick={onNextMonthClick}
|
492 | onDatesChange={onDatesChange}
|
493 | onFocusChange={onFocusChange}
|
494 | onClose={onClose}
|
495 | focusedInput={focusedInput}
|
496 | startDate={startDate}
|
497 | startDateOffset={startDateOffset}
|
498 | endDate={endDate}
|
499 | endDateOffset={endDateOffset}
|
500 | monthFormat={monthFormat}
|
501 | renderMonthText={renderMonthText}
|
502 | renderWeekHeaderElement={renderWeekHeaderElement}
|
503 | withPortal={withAnyPortal}
|
504 | daySize={daySize}
|
505 | initialVisibleMonth={initialVisibleMonthThunk}
|
506 | hideKeyboardShortcutsPanel={hideKeyboardShortcutsPanel}
|
507 | navPrev={navPrev}
|
508 | navNext={navNext}
|
509 | minimumNights={minimumNights}
|
510 | isOutsideRange={isOutsideRange}
|
511 | isDayHighlighted={isDayHighlighted}
|
512 | isDayBlocked={isDayBlocked}
|
513 | keepOpenOnDateSelect={keepOpenOnDateSelect}
|
514 | renderCalendarDay={renderCalendarDay}
|
515 | renderDayContents={renderDayContents}
|
516 | renderCalendarInfo={renderCalendarInfo}
|
517 | renderMonthElement={renderMonthElement}
|
518 | calendarInfoPosition={calendarInfoPosition}
|
519 | isFocused={isDayPickerFocused}
|
520 | showKeyboardShortcuts={showKeyboardShortcuts}
|
521 | onBlur={this.onDayPickerBlur}
|
522 | phrases={phrases}
|
523 | dayAriaLabelFormat={dayAriaLabelFormat}
|
524 | isRTL={isRTL}
|
525 | firstDayOfWeek={firstDayOfWeek}
|
526 | weekDayFormat={weekDayFormat}
|
527 | verticalHeight={verticalHeight}
|
528 | transitionDuration={transitionDuration}
|
529 | disabled={disabled}
|
530 | horizontalMonthPadding={horizontalMonthPadding}
|
531 | />
|
532 |
|
533 | {withFullScreenPortal && (
|
534 | <button
|
535 | {...css(styles.DateRangePicker_closeButton)}
|
536 | type="button"
|
537 | onClick={this.onOutsideClick}
|
538 | aria-label={phrases.closeDatePicker}
|
539 | >
|
540 | {closeIcon}
|
541 | </button>
|
542 | )}
|
543 | </div>
|
544 | );
|
545 | }
|
546 |
|
547 | render() {
|
548 | const {
|
549 | css,
|
550 | startDate,
|
551 | startDateId,
|
552 | startDatePlaceholderText,
|
553 | startDateAriaLabel,
|
554 | endDate,
|
555 | endDateId,
|
556 | endDatePlaceholderText,
|
557 | endDateAriaLabel,
|
558 | focusedInput,
|
559 | screenReaderInputMessage,
|
560 | showClearDates,
|
561 | showDefaultInputIcon,
|
562 | inputIconPosition,
|
563 | customInputIcon,
|
564 | customArrowIcon,
|
565 | customCloseIcon,
|
566 | disabled,
|
567 | required,
|
568 | readOnly,
|
569 | openDirection,
|
570 | phrases,
|
571 | isOutsideRange,
|
572 | minimumNights,
|
573 | withPortal,
|
574 | withFullScreenPortal,
|
575 | displayFormat,
|
576 | reopenPickerOnClearDates,
|
577 | keepOpenOnDateSelect,
|
578 | onDatesChange,
|
579 | onClose,
|
580 | isRTL,
|
581 | noBorder,
|
582 | block,
|
583 | verticalSpacing,
|
584 | small,
|
585 | regular,
|
586 | styles,
|
587 | } = this.props;
|
588 |
|
589 | const { isDateRangePickerInputFocused } = this.state;
|
590 |
|
591 | const enableOutsideClick = (!withPortal && !withFullScreenPortal);
|
592 |
|
593 | const hideFang = verticalSpacing < FANG_HEIGHT_PX;
|
594 |
|
595 | const input = (
|
596 | <DateRangePickerInputController
|
597 | startDate={startDate}
|
598 | startDateId={startDateId}
|
599 | startDatePlaceholderText={startDatePlaceholderText}
|
600 | isStartDateFocused={focusedInput === START_DATE}
|
601 | startDateAriaLabel={startDateAriaLabel}
|
602 | endDate={endDate}
|
603 | endDateId={endDateId}
|
604 | endDatePlaceholderText={endDatePlaceholderText}
|
605 | isEndDateFocused={focusedInput === END_DATE}
|
606 | endDateAriaLabel={endDateAriaLabel}
|
607 | displayFormat={displayFormat}
|
608 | showClearDates={showClearDates}
|
609 | showCaret={!withPortal && !withFullScreenPortal && !hideFang}
|
610 | showDefaultInputIcon={showDefaultInputIcon}
|
611 | inputIconPosition={inputIconPosition}
|
612 | customInputIcon={customInputIcon}
|
613 | customArrowIcon={customArrowIcon}
|
614 | customCloseIcon={customCloseIcon}
|
615 | disabled={disabled}
|
616 | required={required}
|
617 | readOnly={readOnly}
|
618 | openDirection={openDirection}
|
619 | reopenPickerOnClearDates={reopenPickerOnClearDates}
|
620 | keepOpenOnDateSelect={keepOpenOnDateSelect}
|
621 | isOutsideRange={isOutsideRange}
|
622 | minimumNights={minimumNights}
|
623 | withFullScreenPortal={withFullScreenPortal}
|
624 | onDatesChange={onDatesChange}
|
625 | onFocusChange={this.onDateRangePickerInputFocus}
|
626 | onKeyDownArrowDown={this.onDayPickerFocus}
|
627 | onKeyDownQuestionMark={this.showKeyboardShortcutsPanel}
|
628 | onClose={onClose}
|
629 | phrases={phrases}
|
630 | screenReaderMessage={screenReaderInputMessage}
|
631 | isFocused={isDateRangePickerInputFocused}
|
632 | isRTL={isRTL}
|
633 | noBorder={noBorder}
|
634 | block={block}
|
635 | small={small}
|
636 | regular={regular}
|
637 | verticalSpacing={verticalSpacing}
|
638 | >
|
639 | {this.maybeRenderDayPickerWithPortal()}
|
640 | </DateRangePickerInputController>
|
641 | );
|
642 |
|
643 | return (
|
644 | <div
|
645 | ref={this.setContainerRef}
|
646 | {...css(
|
647 | styles.DateRangePicker,
|
648 | block && styles.DateRangePicker__block,
|
649 | )}
|
650 | >
|
651 | {enableOutsideClick && (
|
652 | <OutsideClickHandler onOutsideClick={this.onOutsideClick}>
|
653 | {input}
|
654 | </OutsideClickHandler>
|
655 | )}
|
656 | {enableOutsideClick || input}
|
657 | </div>
|
658 | );
|
659 | }
|
660 | }
|
661 |
|
662 | DateRangePicker.propTypes = propTypes;
|
663 | DateRangePicker.defaultProps = defaultProps;
|
664 |
|
665 | export { DateRangePicker as PureDateRangePicker };
|
666 | export default withStyles(({ reactDates: { color, zIndex } }) => ({
|
667 | DateRangePicker: {
|
668 | position: 'relative',
|
669 | display: 'inline-block',
|
670 | },
|
671 |
|
672 | DateRangePicker__block: {
|
673 | display: 'block',
|
674 | },
|
675 |
|
676 | DateRangePicker_picker: {
|
677 | zIndex: zIndex + 1,
|
678 | backgroundColor: color.background,
|
679 | position: 'absolute',
|
680 | },
|
681 |
|
682 | DateRangePicker_picker__rtl: {
|
683 | direction: noflip('rtl'),
|
684 | },
|
685 |
|
686 | DateRangePicker_picker__directionLeft: {
|
687 | left: noflip(0),
|
688 | },
|
689 |
|
690 | DateRangePicker_picker__directionRight: {
|
691 | right: noflip(0),
|
692 | },
|
693 |
|
694 | DateRangePicker_picker__portal: {
|
695 | backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
696 | position: 'fixed',
|
697 | top: 0,
|
698 | left: noflip(0),
|
699 | height: '100%',
|
700 | width: '100%',
|
701 | },
|
702 |
|
703 | DateRangePicker_picker__fullScreenPortal: {
|
704 | backgroundColor: color.background,
|
705 | },
|
706 |
|
707 | DateRangePicker_closeButton: {
|
708 | background: 'none',
|
709 | border: 0,
|
710 | color: 'inherit',
|
711 | font: 'inherit',
|
712 | lineHeight: 'normal',
|
713 | overflow: 'visible',
|
714 | cursor: 'pointer',
|
715 |
|
716 | position: 'absolute',
|
717 | top: 0,
|
718 | right: noflip(0),
|
719 | padding: 15,
|
720 | zIndex: zIndex + 2,
|
721 |
|
722 | ':hover': {
|
723 | color: `darken(${color.core.grayLighter}, 10%)`,
|
724 | textDecoration: 'none',
|
725 | },
|
726 |
|
727 | ':focus': {
|
728 | color: `darken(${color.core.grayLighter}, 10%)`,
|
729 | textDecoration: 'none',
|
730 | },
|
731 | },
|
732 |
|
733 | DateRangePicker_closeButton_svg: {
|
734 | height: 15,
|
735 | width: 15,
|
736 | fill: color.core.grayLighter,
|
737 | },
|
738 | }), { pureComponent: typeof React.PureComponent !== 'undefined' })(DateRangePicker);
|