UNPKG

react-daterange-picker-onedesert

Version:
644 lines (551 loc) 21.5 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _createReactClass = require('create-react-class'); var _createReactClass2 = _interopRequireDefault(_createReactClass); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _moment = require('moment'); var _moment2 = _interopRequireDefault(_moment); require('moment-range'); var _immutable = require('immutable'); var _immutable2 = _interopRequireDefault(_immutable); var _calendar = require('calendar'); var _calendar2 = _interopRequireDefault(_calendar); var _BemMixin = require('./utils/BemMixin'); var _BemMixin2 = _interopRequireDefault(_BemMixin); var _CustomPropTypes = require('./utils/CustomPropTypes'); var _CustomPropTypes2 = _interopRequireDefault(_CustomPropTypes); var _Legend = require('./Legend'); var _Legend2 = _interopRequireDefault(_Legend); var _CalendarMonth = require('./calendar/CalendarMonth'); var _CalendarMonth2 = _interopRequireDefault(_CalendarMonth); var _CalendarDate = require('./calendar/CalendarDate'); var _CalendarDate2 = _interopRequireDefault(_CalendarDate); var _PaginationArrow = require('./PaginationArrow'); var _PaginationArrow2 = _interopRequireDefault(_PaginationArrow); var _isMomentRange = require('./utils/isMomentRange'); var _isMomentRange2 = _interopRequireDefault(_isMomentRange); var _hasUpdatedValue = require('./utils/hasUpdatedValue'); var _hasUpdatedValue2 = _interopRequireDefault(_hasUpdatedValue); var _getYearMonth = require('./utils/getYearMonth'); var _reactAddonsPureRenderMixin = require('react-addons-pure-render-mixin'); var _reactAddonsPureRenderMixin2 = _interopRequireDefault(_reactAddonsPureRenderMixin); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var absoluteMinimum = (0, _moment2.default)(new Date(-8640000000000000 / 2)).startOf('day'); var absoluteMaximum = (0, _moment2.default)(new Date(8640000000000000 / 2)).startOf('day'); function noop() {} var DateRangePicker = (0, _createReactClass2.default)({ mixins: [_BemMixin2.default, _reactAddonsPureRenderMixin2.default], propTypes: { bemBlock: _propTypes2.default.string, bemNamespace: _propTypes2.default.string, className: _propTypes2.default.string, dateStates: _propTypes2.default.array, // an array of date ranges and their states defaultState: _propTypes2.default.string, disableNavigation: _propTypes2.default.bool, firstOfWeek: _propTypes2.default.oneOf([0, 1, 2, 3, 4, 5, 6]), helpMessage: _propTypes2.default.string, initialDate: _propTypes2.default.instanceOf(Date), initialFromValue: _propTypes2.default.bool, initialMonth: _propTypes2.default.number, // Overrides values derived from initialDate/initialRange initialRange: _propTypes2.default.object, initialYear: _propTypes2.default.number, // Overrides values derived from initialDate/initialRange locale: _propTypes2.default.string, selectEnd: _propTypes2.default.bool, maximumDate: _propTypes2.default.instanceOf(Date), minimumDate: _propTypes2.default.instanceOf(Date), numberOfCalendars: _propTypes2.default.number, onHighlightDate: _propTypes2.default.func, // triggered when a date is highlighted (hovered) onHighlightRange: _propTypes2.default.func, // triggered when a range is highlighted (hovered) onSelect: _propTypes2.default.func, // triggered when a date or range is selectec onSelectStart: _propTypes2.default.func, // triggered when the first date in a range is selected onChange: _propTypes2.default.func, // triggered when a year or month is changed paginationArrowComponent: _propTypes2.default.func, selectedLabel: _propTypes2.default.string, selectionType: _propTypes2.default.oneOf(['single', 'range']), singleDateRange: _propTypes2.default.bool, showLegend: _propTypes2.default.bool, stateDefinitions: _propTypes2.default.object, value: _CustomPropTypes2.default.momentOrMomentRange }, getDefaultProps: function getDefaultProps() { var date = new Date(); var initialDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); return { bemNamespace: null, bemBlock: 'DateRangePicker', className: '', numberOfCalendars: 1, firstOfWeek: 0, disableNavigation: false, nextLabel: '', previousLabel: '', initialDate: initialDate, initialFromValue: true, locale: (0, _moment2.default)().locale(), selectionType: 'range', singleDateRange: false, stateDefinitions: { '__default': { color: null, selectable: true, label: null } }, selectedLabel: "Your selected dates", selectEnd: false, defaultState: '__default', dateStates: [], showLegend: false, onSelect: noop, paginationArrowComponent: _PaginationArrow2.default }; }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { var nextDateStates = this.getDateStates(nextProps); var nextEnabledRange = this.getEnabledRange(nextProps); var updatedState = { selectEnd: nextProps.selectEnd, selectedStartDate: null, hideSelection: false, dateStates: this.state.dateStates && _immutable2.default.is(this.state.dateStates, nextDateStates) ? this.state.dateStates : nextDateStates, enabledRange: this.state.enabledRange && this.state.enabledRange.isSame(nextEnabledRange) ? this.state.enabledRange : nextEnabledRange }; if ((0, _hasUpdatedValue2.default)(this.props, nextProps)) { var isNewValueVisible = this.isStartOrEndVisible(nextProps); if (!isNewValueVisible) { var yearMonth = (0, _getYearMonth.getYearMonthProps)(nextProps); updatedState.year = yearMonth.year; updatedState.month = yearMonth.month; } } this.setState(updatedState); }, componentWillUpdate: function componentWillUpdate(nextProps, nextState) { if (nextState.month !== this.state.month || nextState.year !== this.state.year) { if (typeof this.props.onChange === "function") { this.props.onChange({ year: nextState.year, month: nextState.month }); } } }, getInitialState: function getInitialState() { var now = new Date(); var _props = this.props, initialYear = _props.initialYear, initialMonth = _props.initialMonth, initialFromValue = _props.initialFromValue, selectEnd = _props.selectEnd, value = _props.value; var year = now.getFullYear(); var month = now.getMonth(); if (initialYear && initialMonth) { year = initialYear; month = initialMonth; } if (initialFromValue && value) { var yearMonth = (0, _getYearMonth.getYearMonthProps)(this.props); month = yearMonth.month; year = yearMonth.year; } return { year: year, month: month, selectedStartDate: null, highlightedDate: null, highlightRange: null, selectEnd: selectEnd, hideSelection: false, enabledRange: this.getEnabledRange(this.props), dateStates: this.getDateStates(this.props) }; }, getEnabledRange: function getEnabledRange(props) { var min = props.minimumDate ? (0, _moment2.default)(props.minimumDate).startOf('day') : absoluteMinimum; var max = props.maximumDate ? (0, _moment2.default)(props.maximumDate).startOf('day') : absoluteMaximum; return _moment2.default.range(min, max); }, getDateStates: function getDateStates(props) { var dateStates = props.dateStates, defaultState = props.defaultState, stateDefinitions = props.stateDefinitions; var actualStates = []; var minDate = absoluteMinimum; var maxDate = absoluteMaximum; var dateCursor = (0, _moment2.default)(minDate).startOf('day'); var defs = _immutable2.default.fromJS(stateDefinitions); dateStates.forEach(function (s) { var r = s.range; var start = r.start.startOf('day'); var end = r.end.startOf('day'); if (!dateCursor.isSame(start, 'day')) { actualStates.push({ state: defaultState, range: _moment2.default.range(dateCursor, start) }); } actualStates.push(s); dateCursor = end; }); actualStates.push({ state: defaultState, range: _moment2.default.range(dateCursor, maxDate) }); // sanitize date states return _immutable2.default.List(actualStates).map(function (s) { var def = defs.get(s.state); return _immutable2.default.Map({ range: s.range, state: s.state, selectable: def.get('selectable', true), color: def.get('color') }); }); }, isDateDisabled: function isDateDisabled(date) { return !this.state.enabledRange.contains(date); }, isDateSelectable: function isDateSelectable(date) { return this.dateRangesForDate(date).some(function (r) { return r.get('selectable'); }); }, nonSelectableStateRanges: function nonSelectableStateRanges() { return this.state.dateStates.filter(function (d) { return !d.get('selectable'); }); }, dateRangesForDate: function dateRangesForDate(date) { return this.state.dateStates.filter(function (d) { return d.get('range').contains(date); }); }, sanitizeRange: function sanitizeRange(range, forwards) { /* Truncates the provided range at the first intersection * with a non-selectable state. Using forwards to determine * which direction to work */ var blockedRanges = this.nonSelectableStateRanges().map(function (r) { return r.get('range'); }); var intersect = void 0; if (forwards) { intersect = blockedRanges.find(function (r) { return range.intersect(r); }); if (intersect) { return _moment2.default.range(range.start, intersect.start); } } else { intersect = blockedRanges.findLast(function (r) { return range.intersect(r); }); if (intersect) { return _moment2.default.range(intersect.end, range.end); } } if (range.start.isBefore(this.state.enabledRange.start)) { return _moment2.default.range(this.state.enabledRange.start, range.end); } if (range.end.isAfter(this.state.enabledRange.end)) { return _moment2.default.range(range.start, this.state.enabledRange.end); } return range; }, highlightRange: function highlightRange(range) { this.setState({ highlightedRange: range, highlightedDate: null }); if (typeof this.props.onHighlightRange === 'function') { this.props.onHighlightRange(range, this.statesForRange(range)); } }, onUnHighlightDate: function onUnHighlightDate() { this.setState({ highlightedDate: null }); }, onSelectDate: function onSelectDate(date) { var _props2 = this.props, selectionType = _props2.selectionType, value = _props2.value; var _state = this.state, selectEnd = _state.selectEnd, selectedStartDate = _state.selectedStartDate; if (selectionType === 'range') { if (selectEnd && value && value.start && value.start.diff(date) < 0) { this.highlightRange(_moment2.default.range(value.start, date)); this.completeRangeSelection(); } else if (selectedStartDate) { this.completeRangeSelection(); } else if (!this.isDateDisabled(date) && this.isDateSelectable(date)) { this.startRangeSelection(date); if (this.props.singleDateRange) { this.highlightRange(_moment2.default.range(date, date)); } } } else { if (!this.isDateDisabled(date) && this.isDateSelectable(date)) { this.completeSelection(); } } }, onHighlightDate: function onHighlightDate(date) { var _props3 = this.props, selectionType = _props3.selectionType, value = _props3.value; var _state2 = this.state, selectedStartDate = _state2.selectedStartDate, selectEnd = _state2.selectEnd; var datePair = void 0; var range = void 0; var forwards = void 0; if (selectionType === 'range') { if (selectEnd && value && value.start && value.start.diff(date) < 0) { datePair = _immutable2.default.List.of(value.start, date).sortBy(function (d) { return d.unix(); }); range = _moment2.default.range(datePair.get(0), datePair.get(1)); forwards = range.start.unix() === value.start.unix(); range = this.sanitizeRange(range, forwards); this.highlightRange(range); } else if (selectedStartDate) { datePair = _immutable2.default.List.of(selectedStartDate, date).sortBy(function (d) { return d.unix(); }); range = _moment2.default.range(datePair.get(0), datePair.get(1)); forwards = range.start.unix() === selectedStartDate.unix(); range = this.sanitizeRange(range, forwards); this.highlightRange(range); } else if (!this.isDateDisabled(date) && this.isDateSelectable(date)) { this.highlightDate(date); } } else { if (!this.isDateDisabled(date) && this.isDateSelectable(date)) { this.highlightDate(date); } } }, startRangeSelection: function startRangeSelection(date) { this.setState({ hideSelection: true, selectedStartDate: date }); if (typeof this.props.onSelectStart === 'function') { this.props.onSelectStart((0, _moment2.default)(date)); } }, statesForDate: function statesForDate(date) { return this.state.dateStates.filter(function (d) { return date.within(d.get('range')); }).map(function (d) { return d.get('state'); }); }, statesForRange: function statesForRange(range) { if (range.start.isSame(range.end, 'day')) { return this.statesForDate(range.start); } return this.state.dateStates.filter(function (d) { return d.get('range').intersect(range); }).map(function (d) { return d.get('state'); }); }, completeSelection: function completeSelection() { var highlightedDate = this.state.highlightedDate; if (highlightedDate) { this.setState({ hideSelection: false, highlightedDate: null }); this.props.onSelect(highlightedDate, this.statesForDate(highlightedDate)); } }, completeRangeSelection: function completeRangeSelection() { var range = this.state.highlightedRange; if (range && (!range.start.isSame(range.end, 'day') || this.props.singleDateRange)) { this.setState({ selectedStartDate: null, highlightedRange: null, highlightedDate: null, hideSelection: false }); this.props.onSelect(range, this.statesForRange(range)); } }, highlightDate: function highlightDate(date) { this.setState({ highlightedDate: date }); if (typeof this.props.onHighlightDate === 'function') { this.props.onHighlightDate(date, this.statesForDate(date)); } }, getMonthDate: function getMonthDate() { return (0, _moment2.default)(new Date(this.state.year, this.state.month, 1)); }, isStartOrEndVisible: function isStartOrEndVisible(props) { var _this = this; var value = props.value, selectionType = props.selectionType, numberOfCalendars = props.numberOfCalendars; var isVisible = function isVisible(date) { var yearMonth = (0, _getYearMonth.getYearMonth)(date); var isSameYear = yearMonth.year === _this.state.year; var isMonthVisible = yearMonth.month === _this.state.month || numberOfCalendars === 2 && yearMonth.month - 1 === _this.state.month; return isSameYear && isMonthVisible; }; if (selectionType === 'single') { return isVisible(value); } return isVisible(value.start) || isVisible(value.end); }, canMoveBack: function canMoveBack() { if (this.getMonthDate().subtract(1, 'days').isBefore(this.state.enabledRange.start)) { return false; } return true; }, moveBack: function moveBack() { var monthDate = void 0; if (this.canMoveBack()) { monthDate = this.getMonthDate(); monthDate.subtract(1, 'months'); this.setState((0, _getYearMonth.getYearMonth)(monthDate)); } }, canMoveForward: function canMoveForward() { if (this.getMonthDate().add(this.props.numberOfCalendars, 'months').isAfter(this.state.enabledRange.end)) { return false; } return true; }, moveForward: function moveForward() { var monthDate = void 0; if (this.canMoveForward()) { monthDate = this.getMonthDate(); monthDate.add(1, 'months'); this.setState((0, _getYearMonth.getYearMonth)(monthDate)); } }, changeYear: function changeYear(year) { var _state3 = this.state, enabledRange = _state3.enabledRange, month = _state3.month; if ((0, _moment2.default)({ years: year, months: month, date: 1 }).unix() < enabledRange.start.unix()) { month = enabledRange.start.month(); } if ((0, _moment2.default)({ years: year, months: month + 1, date: 1 }).unix() > enabledRange.end.unix()) { month = enabledRange.end.month(); } this.setState({ year: year, month: month }); }, changeMonth: function changeMonth(date) { this.setState({ month: date }); }, renderCalendar: function renderCalendar(index) { var _props4 = this.props, bemBlock = _props4.bemBlock, bemNamespace = _props4.bemNamespace, firstOfWeek = _props4.firstOfWeek, numberOfCalendars = _props4.numberOfCalendars, selectionType = _props4.selectionType, value = _props4.value; var _state4 = this.state, dateStates = _state4.dateStates, enabledRange = _state4.enabledRange, hideSelection = _state4.hideSelection, highlightedDate = _state4.highlightedDate, highlightedRange = _state4.highlightedRange; var monthDate = this.getMonthDate(); var year = monthDate.year(); var month = monthDate.month(); var key = index + '-' + year + '-' + month; var props = void 0; monthDate.add(index, 'months'); var cal = new _calendar2.default.Calendar(firstOfWeek); var monthDates = _immutable2.default.fromJS(cal.monthDates(monthDate.year(), monthDate.month())); var monthStart = monthDates.first().first(); var monthEnd = monthDates.last().last(); var monthRange = _moment2.default.range(monthStart, monthEnd); if (_moment2.default.isMoment(value)) { if (!monthRange.contains(value)) { value = null; } } else if ((0, _isMomentRange2.default)(value)) { if (!monthRange.overlaps(value)) { value = null; } } if (!_moment2.default.isMoment(highlightedDate) || !monthRange.contains(highlightedDate)) { highlightedDate = null; } if (!(0, _isMomentRange2.default)(highlightedRange) || !monthRange.overlaps(highlightedRange)) { highlightedRange = null; } props = { bemBlock: bemBlock, bemNamespace: bemNamespace, dateStates: dateStates, enabledRange: enabledRange, firstOfWeek: firstOfWeek, hideSelection: hideSelection, highlightedDate: highlightedDate, highlightedRange: highlightedRange, index: index, key: key, selectionType: selectionType, value: value, maxIndex: numberOfCalendars - 1, firstOfMonth: monthDate, onMonthChange: this.changeMonth, onYearChange: this.changeYear, onSelectDate: this.onSelectDate, onHighlightDate: this.onHighlightDate, onUnHighlightDate: this.onUnHighlightDate, dateRangesForDate: this.dateRangesForDate, dateComponent: _CalendarDate2.default, locale: this.props.locale }; return _react2.default.createElement(_CalendarMonth2.default, props); }, render: function render() { var _props5 = this.props, PaginationArrowComponent = _props5.paginationArrowComponent, className = _props5.className, numberOfCalendars = _props5.numberOfCalendars, stateDefinitions = _props5.stateDefinitions, selectedLabel = _props5.selectedLabel, showLegend = _props5.showLegend, helpMessage = _props5.helpMessage; var calendars = _immutable2.default.Range(0, numberOfCalendars).map(this.renderCalendar); className = this.cx({ element: null }) + ' ' + className; return _react2.default.createElement( 'div', { className: className.trim() }, _react2.default.createElement(PaginationArrowComponent, { direction: 'previous', onTrigger: this.moveBack, disabled: !this.canMoveBack() }), calendars.toJS(), _react2.default.createElement(PaginationArrowComponent, { direction: 'next', onTrigger: this.moveForward, disabled: !this.canMoveForward() }), helpMessage ? _react2.default.createElement( 'span', { className: this.cx({ element: 'HelpMessage' }) }, helpMessage ) : null, showLegend ? _react2.default.createElement(_Legend2.default, { stateDefinitions: stateDefinitions, selectedLabel: selectedLabel }) : null ); } }); exports.default = DateRangePicker;