} from '../../helpers/l10n';
import './DayPicker.css';
import EscKeydownHandler from './EscKeydownHandler';
+import FocusOutHandler from './FocusOutHandler';
import Select from './Select';
import './styles.css';
interface Props {
+ alignRight?: boolean;
className?: string;
currentMonth?: Date;
highlightFrom?: Date;
render() {
const {
+ alignRight,
highlightFrom,
highlightTo,
minDate,
const yearOptions = years.map((year) => ({ label: String(year), value: year }));
return (
- <OutsideClickHandler onClickOutside={this.closeCalendar}>
- <EscKeydownHandler onKeydown={this.closeCalendar}>
- <span className={classNames('date-input-control', className)}>
- <InputWrapper
- className={classNames('date-input-control-input', inputClassName, {
- 'is-filled': value !== undefined,
- })}
- id={id}
- innerRef={(node: HTMLInputElement | null) => (this.input = node)}
- name={name}
- onFocus={this.openCalendar}
- placeholder={placeholder}
- readOnly={true}
- type="text"
- value={value}
- />
- <CalendarIcon className="date-input-control-icon" fill="" />
- {value !== undefined && (
- <ClearButton
- aria-label={translate('reset_verb')}
- className="button-tiny date-input-control-reset"
- iconProps={{ size: 12 }}
- onClick={this.handleResetClick}
+ <FocusOutHandler onFocusOut={this.closeCalendar}>
+ <OutsideClickHandler onClickOutside={this.closeCalendar}>
+ <EscKeydownHandler onKeydown={this.closeCalendar}>
+ <span className={classNames('date-input-control', className)}>
+ <InputWrapper
+ className={classNames('date-input-control-input', inputClassName, {
+ 'is-filled': value !== undefined,
+ })}
+ id={id}
+ innerRef={(node: HTMLInputElement | null) => (this.input = node)}
+ name={name}
+ onFocus={this.openCalendar}
+ placeholder={placeholder}
+ readOnly={true}
+ type="text"
+ value={value}
/>
- )}
- {open && (
- <div className="date-input-calendar">
- <nav className="date-input-calendar-nav">
- <ButtonIcon className="button-small" onClick={this.handlePreviousMonthClick}>
- <ChevronLeftIcon />
- </ButtonIcon>
- <div className="date-input-calender-month">
- <Select
- aria-label={translate('select_month')}
- className="date-input-calender-month-select"
- onChange={this.handleCurrentMonthChange}
- options={monthOptions}
- value={monthOptions.find((month) => month.value === currentMonth.getMonth())}
- />
- <Select
- aria-label={translate('select_year')}
- className="date-input-calender-month-select spacer-left"
- onChange={this.handleCurrentYearChange}
- options={yearOptions}
- value={yearOptions.find((year) => year.value === currentMonth.getFullYear())}
- />
- </div>
- <ButtonIcon className="button-small" onClick={this.handleNextMonthClick}>
- <ChevronRightIcon />
- </ButtonIcon>
- </nav>
- <DayPicker
- captionElement={<NullComponent />}
- disabledDays={{ after, before: minDate }}
- firstDayOfWeek={1}
- modifiers={modifiers}
- month={currentMonth}
- navbarElement={<NullComponent />}
- onDayClick={this.handleDayClick}
- onDayMouseEnter={this.handleDayMouseEnter}
- selectedDays={selectedDays}
- weekdaysLong={weekdaysLong}
- weekdaysShort={weekdaysShort}
+ <CalendarIcon className="date-input-control-icon" fill="" />
+ {value !== undefined && (
+ <ClearButton
+ aria-label={translate('reset_verb')}
+ className="button-tiny date-input-control-reset"
+ iconProps={{ size: 12 }}
+ onClick={this.handleResetClick}
/>
- </div>
- )}
- </span>
- </EscKeydownHandler>
- </OutsideClickHandler>
+ )}
+ {open && (
+ <div className={classNames('date-input-calendar', { 'align-right': alignRight })}>
+ <nav className="date-input-calendar-nav">
+ <ButtonIcon className="button-small" onClick={this.handlePreviousMonthClick}>
+ <ChevronLeftIcon />
+ </ButtonIcon>
+ <div className="date-input-calender-month">
+ <Select
+ aria-label={translate('select_month')}
+ className="date-input-calender-month-select"
+ onChange={this.handleCurrentMonthChange}
+ options={monthOptions}
+ value={monthOptions.find(
+ (month) => month.value === currentMonth.getMonth()
+ )}
+ />
+ <Select
+ aria-label={translate('select_year')}
+ className="date-input-calender-month-select spacer-left"
+ onChange={this.handleCurrentYearChange}
+ options={yearOptions}
+ value={yearOptions.find(
+ (year) => year.value === currentMonth.getFullYear()
+ )}
+ />
+ </div>
+ <ButtonIcon className="button-small" onClick={this.handleNextMonthClick}>
+ <ChevronRightIcon />
+ </ButtonIcon>
+ </nav>
+ <DayPicker
+ captionElement={<NullComponent />}
+ disabledDays={{ after, before: minDate }}
+ firstDayOfWeek={1}
+ modifiers={modifiers}
+ month={currentMonth}
+ navbarElement={<NullComponent />}
+ onDayClick={this.handleDayClick}
+ onDayMouseEnter={this.handleDayMouseEnter}
+ selectedDays={selectedDays}
+ weekdaysLong={weekdaysLong}
+ weekdaysShort={weekdaysShort}
+ />
+ </div>
+ )}
+ </span>
+ </EscKeydownHandler>
+ </OutsideClickHandler>
+ </FocusOutHandler>
);
}
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render 1`] = `
-<OutsideClickHandler
- onClickOutside={[Function]}
+<FocusOutHandler
+ onFocusOut={[Function]}
>
- <EscKeydownHandler
- onKeydown={[Function]}
+ <OutsideClickHandler
+ onClickOutside={[Function]}
>
- <span
- className="date-input-control"
+ <EscKeydownHandler
+ onKeydown={[Function]}
>
- <injectIntl(Component)
- className="date-input-control-input"
- innerRef={[Function]}
- onFocus={[Function]}
- placeholder="placeholder"
- readOnly={true}
- type="text"
- />
- <CalendarIcon
- className="date-input-control-icon"
- fill=""
- />
- </span>
- </EscKeydownHandler>
-</OutsideClickHandler>
+ <span
+ className="date-input-control"
+ >
+ <injectIntl(Component)
+ className="date-input-control-input"
+ innerRef={[Function]}
+ onFocus={[Function]}
+ placeholder="placeholder"
+ readOnly={true}
+ type="text"
+ />
+ <CalendarIcon
+ className="date-input-control-icon"
+ fill=""
+ />
+ </span>
+ </EscKeydownHandler>
+ </OutsideClickHandler>
+</FocusOutHandler>
`;
exports[`should render 2`] = `
-<OutsideClickHandler
- onClickOutside={[Function]}
+<FocusOutHandler
+ onFocusOut={[Function]}
>
- <EscKeydownHandler
- onKeydown={[Function]}
+ <OutsideClickHandler
+ onClickOutside={[Function]}
>
- <span
- className="date-input-control"
+ <EscKeydownHandler
+ onKeydown={[Function]}
>
- <injectIntl(Component)
- className="date-input-control-input is-filled"
- innerRef={[Function]}
- onFocus={[Function]}
- placeholder="placeholder"
- readOnly={true}
- type="text"
- value={2018-01-17T00:00:00.000Z}
- />
- <CalendarIcon
- className="date-input-control-icon"
- fill=""
- />
- <ClearButton
- aria-label="reset_verb"
- className="button-tiny date-input-control-reset"
- iconProps={
- Object {
- "size": 12,
+ <span
+ className="date-input-control"
+ >
+ <injectIntl(Component)
+ className="date-input-control-input is-filled"
+ innerRef={[Function]}
+ onFocus={[Function]}
+ placeholder="placeholder"
+ readOnly={true}
+ type="text"
+ value={2018-01-17T00:00:00.000Z}
+ />
+ <CalendarIcon
+ className="date-input-control-icon"
+ fill=""
+ />
+ <ClearButton
+ aria-label="reset_verb"
+ className="button-tiny date-input-control-reset"
+ iconProps={
+ Object {
+ "size": 12,
+ }
}
- }
- onClick={[Function]}
- />
- </span>
- </EscKeydownHandler>
-</OutsideClickHandler>
+ onClick={[Function]}
+ />
+ </span>
+ </EscKeydownHandler>
+ </OutsideClickHandler>
+</FocusOutHandler>
`;
exports[`should render 3`] = `
-<OutsideClickHandler
- onClickOutside={[Function]}
+<FocusOutHandler
+ onFocusOut={[Function]}
>
- <EscKeydownHandler
- onKeydown={[Function]}
+ <OutsideClickHandler
+ onClickOutside={[Function]}
>
- <span
- className="date-input-control"
+ <EscKeydownHandler
+ onKeydown={[Function]}
>
- <injectIntl(Component)
- className="date-input-control-input is-filled"
- innerRef={[Function]}
- onFocus={[Function]}
- placeholder="placeholder"
- readOnly={true}
- type="text"
- value={2018-01-17T00:00:00.000Z}
- />
- <CalendarIcon
- className="date-input-control-icon"
- fill=""
- />
- <ClearButton
- aria-label="reset_verb"
- className="button-tiny date-input-control-reset"
- iconProps={
- Object {
- "size": 12,
- }
- }
- onClick={[Function]}
- />
- <div
- className="date-input-calendar"
+ <span
+ className="date-input-control"
>
- <nav
- className="date-input-calendar-nav"
+ <injectIntl(Component)
+ className="date-input-control-input is-filled"
+ innerRef={[Function]}
+ onFocus={[Function]}
+ placeholder="placeholder"
+ readOnly={true}
+ type="text"
+ value={2018-01-17T00:00:00.000Z}
+ />
+ <CalendarIcon
+ className="date-input-control-icon"
+ fill=""
+ />
+ <ClearButton
+ aria-label="reset_verb"
+ className="button-tiny date-input-control-reset"
+ iconProps={
+ Object {
+ "size": 12,
+ }
+ }
+ onClick={[Function]}
+ />
+ <div
+ className="date-input-calendar"
>
- <ButtonIcon
- className="button-small"
- onClick={[Function]}
- >
- <ChevronLeftIcon />
- </ButtonIcon>
- <div
- className="date-input-calender-month"
+ <nav
+ className="date-input-calendar-nav"
>
- <Select
- aria-label="select_month"
- className="date-input-calender-month-select"
- onChange={[Function]}
- options={
- Array [
+ <ButtonIcon
+ className="button-small"
+ onClick={[Function]}
+ >
+ <ChevronLeftIcon />
+ </ButtonIcon>
+ <div
+ className="date-input-calender-month"
+ >
+ <Select
+ aria-label="select_month"
+ className="date-input-calender-month-select"
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "Jan",
+ "value": 0,
+ },
+ Object {
+ "label": "Feb",
+ "value": 1,
+ },
+ Object {
+ "label": "Mar",
+ "value": 2,
+ },
+ Object {
+ "label": "Apr",
+ "value": 3,
+ },
+ Object {
+ "label": "May",
+ "value": 4,
+ },
+ Object {
+ "label": "Jun",
+ "value": 5,
+ },
+ Object {
+ "label": "Jul",
+ "value": 6,
+ },
+ Object {
+ "label": "Aug",
+ "value": 7,
+ },
+ Object {
+ "label": "Sep",
+ "value": 8,
+ },
+ Object {
+ "label": "Oct",
+ "value": 9,
+ },
+ Object {
+ "label": "Nov",
+ "value": 10,
+ },
+ Object {
+ "label": "Dec",
+ "value": 11,
+ },
+ ]
+ }
+ value={
Object {
"label": "Jan",
"value": 0,
- },
- Object {
- "label": "Feb",
- "value": 1,
- },
- Object {
- "label": "Mar",
- "value": 2,
- },
- Object {
- "label": "Apr",
- "value": 3,
- },
- Object {
- "label": "May",
- "value": 4,
- },
- Object {
- "label": "Jun",
- "value": 5,
- },
- Object {
- "label": "Jul",
- "value": 6,
- },
- Object {
- "label": "Aug",
- "value": 7,
- },
- Object {
- "label": "Sep",
- "value": 8,
- },
- Object {
- "label": "Oct",
- "value": 9,
- },
- Object {
- "label": "Nov",
- "value": 10,
- },
- Object {
- "label": "Dec",
- "value": 11,
- },
- ]
- }
- value={
- Object {
- "label": "Jan",
- "value": 0,
+ }
}
- }
- />
- <Select
- aria-label="select_year"
- className="date-input-calender-month-select spacer-left"
- onChange={[Function]}
- options={
- Array [
- Object {
- "label": "2008",
- "value": 2008,
- },
- Object {
- "label": "2009",
- "value": 2009,
- },
- Object {
- "label": "2010",
- "value": 2010,
- },
- Object {
- "label": "2011",
- "value": 2011,
- },
- Object {
- "label": "2012",
- "value": 2012,
- },
- Object {
- "label": "2013",
- "value": 2013,
- },
- Object {
- "label": "2014",
- "value": 2014,
- },
- Object {
- "label": "2015",
- "value": 2015,
- },
- Object {
- "label": "2016",
- "value": 2016,
- },
- Object {
- "label": "2017",
- "value": 2017,
- },
+ />
+ <Select
+ aria-label="select_year"
+ className="date-input-calender-month-select spacer-left"
+ onChange={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "2008",
+ "value": 2008,
+ },
+ Object {
+ "label": "2009",
+ "value": 2009,
+ },
+ Object {
+ "label": "2010",
+ "value": 2010,
+ },
+ Object {
+ "label": "2011",
+ "value": 2011,
+ },
+ Object {
+ "label": "2012",
+ "value": 2012,
+ },
+ Object {
+ "label": "2013",
+ "value": 2013,
+ },
+ Object {
+ "label": "2014",
+ "value": 2014,
+ },
+ Object {
+ "label": "2015",
+ "value": 2015,
+ },
+ Object {
+ "label": "2016",
+ "value": 2016,
+ },
+ Object {
+ "label": "2017",
+ "value": 2017,
+ },
+ Object {
+ "label": "2018",
+ "value": 2018,
+ },
+ ]
+ }
+ value={
Object {
"label": "2018",
"value": 2018,
- },
- ]
- }
- value={
- Object {
- "label": "2018",
- "value": 2018,
+ }
}
+ />
+ </div>
+ <ButtonIcon
+ className="button-small"
+ onClick={[Function]}
+ >
+ <ChevronRightIcon />
+ </ButtonIcon>
+ </nav>
+ <DayPicker
+ canChangeMonth={true}
+ captionElement={<NullComponent />}
+ classNames={
+ Object {
+ "body": "DayPicker-Body",
+ "caption": "DayPicker-Caption",
+ "container": "DayPicker",
+ "day": "DayPicker-Day",
+ "disabled": "disabled",
+ "footer": "DayPicker-Footer",
+ "interactionDisabled": "DayPicker--interactionDisabled",
+ "month": "DayPicker-Month",
+ "months": "DayPicker-Months",
+ "navBar": "DayPicker-NavBar",
+ "navButtonInteractionDisabled": "DayPicker-NavButton--interactionDisabled",
+ "navButtonNext": "DayPicker-NavButton DayPicker-NavButton--next",
+ "navButtonPrev": "DayPicker-NavButton DayPicker-NavButton--prev",
+ "outside": "outside",
+ "selected": "selected",
+ "today": "today",
+ "todayButton": "DayPicker-TodayButton",
+ "week": "DayPicker-Week",
+ "weekNumber": "DayPicker-WeekNumber",
+ "weekday": "DayPicker-Weekday",
+ "weekdays": "DayPicker-Weekdays",
+ "weekdaysRow": "DayPicker-WeekdaysRow",
+ "wrapper": "DayPicker-wrapper",
}
- />
- </div>
- <ButtonIcon
- className="button-small"
- onClick={[Function]}
- >
- <ChevronRightIcon />
- </ButtonIcon>
- </nav>
- <DayPicker
- canChangeMonth={true}
- captionElement={<NullComponent />}
- classNames={
- Object {
- "body": "DayPicker-Body",
- "caption": "DayPicker-Caption",
- "container": "DayPicker",
- "day": "DayPicker-Day",
- "disabled": "disabled",
- "footer": "DayPicker-Footer",
- "interactionDisabled": "DayPicker--interactionDisabled",
- "month": "DayPicker-Month",
- "months": "DayPicker-Months",
- "navBar": "DayPicker-NavBar",
- "navButtonInteractionDisabled": "DayPicker-NavButton--interactionDisabled",
- "navButtonNext": "DayPicker-NavButton DayPicker-NavButton--next",
- "navButtonPrev": "DayPicker-NavButton DayPicker-NavButton--prev",
- "outside": "outside",
- "selected": "selected",
- "today": "today",
- "todayButton": "DayPicker-TodayButton",
- "week": "DayPicker-Week",
- "weekNumber": "DayPicker-WeekNumber",
- "weekday": "DayPicker-Weekday",
- "weekdays": "DayPicker-Weekdays",
- "weekdaysRow": "DayPicker-WeekdaysRow",
- "wrapper": "DayPicker-wrapper",
}
- }
- disabledDays={
- Object {
- "after": 2018-02-05T00:00:00.000Z,
- "before": 2018-01-17T00:00:00.000Z,
+ disabledDays={
+ Object {
+ "after": 2018-02-05T00:00:00.000Z,
+ "before": 2018-01-17T00:00:00.000Z,
+ }
}
- }
- enableOutsideDaysClick={true}
- firstDayOfWeek={1}
- fixedWeeks={false}
- labels={
- Object {
- "nextMonth": "Next Month",
- "previousMonth": "Previous Month",
+ enableOutsideDaysClick={true}
+ firstDayOfWeek={1}
+ fixedWeeks={false}
+ labels={
+ Object {
+ "nextMonth": "Next Month",
+ "previousMonth": "Previous Month",
+ }
}
- }
- locale="en"
- localeUtils={
- Object {
- "default": Object {
+ locale="en"
+ localeUtils={
+ Object {
+ "default": Object {
+ "formatDay": [Function],
+ "formatMonthTitle": [Function],
+ "formatWeekdayLong": [Function],
+ "formatWeekdayShort": [Function],
+ "getFirstDayOfWeek": [Function],
+ "getMonths": [Function],
+ },
"formatDay": [Function],
"formatMonthTitle": [Function],
"formatWeekdayLong": [Function],
"formatWeekdayShort": [Function],
"getFirstDayOfWeek": [Function],
"getMonths": [Function],
- },
- "formatDay": [Function],
- "formatMonthTitle": [Function],
- "formatWeekdayLong": [Function],
- "formatWeekdayShort": [Function],
- "getFirstDayOfWeek": [Function],
- "getMonths": [Function],
+ }
}
- }
- month={2018-01-17T00:00:00.000Z}
- navbarElement={<NullComponent />}
- numberOfMonths={1}
- onDayClick={[Function]}
- onDayMouseEnter={[Function]}
- pagedNavigation={false}
- renderDay={[Function]}
- renderWeek={[Function]}
- reverseMonths={false}
- selectedDays={
- Array [
- 2018-01-17T00:00:00.000Z,
- ]
- }
- showOutsideDays={false}
- showWeekDays={true}
- showWeekNumbers={false}
- tabIndex={0}
- weekdayElement={<Weekday />}
- weekdaysLong={
- Array [
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday",
- ]
- }
- weekdaysShort={
- Array [
- "Sun",
- "Mon",
- "Tue",
- "Wed",
- "Thu",
- "Fri",
- "Sat",
- ]
- }
- />
- </div>
- </span>
- </EscKeydownHandler>
-</OutsideClickHandler>
+ month={2018-01-17T00:00:00.000Z}
+ navbarElement={<NullComponent />}
+ numberOfMonths={1}
+ onDayClick={[Function]}
+ onDayMouseEnter={[Function]}
+ pagedNavigation={false}
+ renderDay={[Function]}
+ renderWeek={[Function]}
+ reverseMonths={false}
+ selectedDays={
+ Array [
+ 2018-01-17T00:00:00.000Z,
+ ]
+ }
+ showOutsideDays={false}
+ showWeekDays={true}
+ showWeekNumbers={false}
+ tabIndex={0}
+ weekdayElement={<Weekday />}
+ weekdaysLong={
+ Array [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ ]
+ }
+ weekdaysShort={
+ Array [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ ]
+ }
+ />
+ </div>
+ </span>
+ </EscKeydownHandler>
+ </OutsideClickHandler>
+</FocusOutHandler>
`;
exports[`should select a day 1`] = `
-<OutsideClickHandler
- onClickOutside={[Function]}
+<FocusOutHandler
+ onFocusOut={[Function]}
>
- <EscKeydownHandler
- onKeydown={[Function]}
+ <OutsideClickHandler
+ onClickOutside={[Function]}
>
- <span
- className="date-input-control"
+ <EscKeydownHandler
+ onKeydown={[Function]}
>
- <injectIntl(Component)
- className="date-input-control-input"
- innerRef={[Function]}
- onFocus={[Function]}
- placeholder="placeholder"
- readOnly={true}
- type="text"
- />
- <CalendarIcon
- className="date-input-control-icon"
- fill=""
- />
- </span>
- </EscKeydownHandler>
-</OutsideClickHandler>
+ <span
+ className="date-input-control"
+ >
+ <injectIntl(Component)
+ className="date-input-control-input"
+ innerRef={[Function]}
+ onFocus={[Function]}
+ placeholder="placeholder"
+ readOnly={true}
+ type="text"
+ />
+ <CalendarIcon
+ className="date-input-control-icon"
+ fill=""
+ />
+ </span>
+ </EscKeydownHandler>
+ </OutsideClickHandler>
+</FocusOutHandler>
`;