UNPKG

material-date-range-picker

Version:

React components, that implements material design pickers for material-ui v1

598 lines (496 loc) 19.6 kB
import _taggedTemplateLiteralLoose from '@babel/runtime/helpers/esm/taggedTemplateLiteralLoose'; import styled from 'styled-components'; import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; import { withTheme } from '@material-ui/core/styles'; import { fade } from '@material-ui/core/styles/colorManipulator'; import React, { Fragment, PureComponent } from 'react'; import { isSameMonth, isWithinRange, isSameDay, isToday, getYear, addYears, format, isThisYear, isSameYear, getMonth, addMonths, isThisMonth, isAfter, isBefore } from 'date-fns'; import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose'; import Button from '@material-ui/core/Button'; import IconButton from '@material-ui/core/IconButton'; import NavigateNext from '@material-ui/icons/NavigateNext'; import NavigateBefore from '@material-ui/icons/NavigateBefore'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import ArrowDropUp from '@material-ui/icons/ArrowDropUp'; import ClearAll from '@material-ui/icons/ClearAll'; import Card from '@material-ui/core/Card'; import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose'; import _extends from '@babel/runtime/helpers/esm/extends'; import PropTypes from 'prop-types'; import Downshift from 'downshift'; import TextField from '@material-ui/core/TextField'; import Kalendaryo from 'kalendaryo'; function _templateObject6() { var data = _taggedTemplateLiteralLoose(["\n && {\n * {\n color: ", ";\n }\n }\n"]); _templateObject6 = function _templateObject6() { return data; }; return data; } function _templateObject5() { var data = _taggedTemplateLiteralLoose(["\n border-radius: ", ";\n border-color: ", ";\n box-sizing: border-box;\n cursor: pointer;\n background: ", ";\n && {\n * {\n color: ", ";\n }\n }\n"]); _templateObject5 = function _templateObject5() { return data; }; return data; } function _templateObject4() { var data = _taggedTemplateLiteralLoose(["\n width: calc(\n 100% * ", " -\n ", "px\n );\n padding-top: calc((100% / 7) - 2px);\n margin: 2px 0;\n position: relative;\n border: 1px solid transparent;\n"]); _templateObject4 = function _templateObject4() { return data; }; return data; } function _templateObject3() { var data = _taggedTemplateLiteralLoose(["\n && {\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n"]); _templateObject3 = function _templateObject3() { return data; }; return data; } function _templateObject2() { var data = _taggedTemplateLiteralLoose(["\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n"]); _templateObject2 = function _templateObject2() { return data; }; return data; } function _templateObject() { var data = _taggedTemplateLiteralLoose(["\n && {\n margin: 0 -8px 8px;\n }\n"]); _templateObject = function _templateObject() { return data; }; return data; } function fromTheme(theme, key, def) { if (!theme || !theme.dateRangePicker) return def; var value = theme.dateRangePicker[key]; return typeof value !== 'undefined' ? value : def; } var HeaderDivider = styled(Divider)(_templateObject()); var Row = styled.div(_templateObject2()); var Text = styled(Typography)(_templateObject3()); var Cell = styled.div(_templateObject4(), function (_ref) { var _ref$widthPercentage = _ref.widthPercentage, widthPercentage = _ref$widthPercentage === void 0 ? 1 / 7 : _ref$widthPercentage; return widthPercentage; }, function (_ref2) { var horizontalSpacing = _ref2.horizontalSpacing; return horizontalSpacing ? 3 : 0; }); function getBorderRadius(_ref3) { var isInRange = _ref3.isInRange, isRangeStart = _ref3.isRangeStart, isRangeEnd = _ref3.isRangeEnd; if (isRangeStart) return '999px 0 0 999px'; if (isRangeEnd) return '0 999px 999px 0'; if (isInRange) return 0; return '999px'; } function getBackground(_ref4) { var isInRange = _ref4.isInRange, isSelected = _ref4.isSelected, theme = _ref4.theme, isHighlighted = _ref4.isHighlighted; if (isSelected) return fromTheme(theme, 'selected', theme.palette.primary.main); if (isHighlighted) return fromTheme(theme, 'highlighted', '#ebebeb'); if (isInRange) return fromTheme(theme, 'inRange', theme.palette.primary.light); return '#fff'; } function getColor(props) { var isLessImportant = props.isLessImportant, isSelected = props.isSelected, theme = props.theme; var color = theme.palette.getContrastText(getBackground(props)); if (isSelected || !isLessImportant) return color; return fromTheme(theme, 'lessImportant', fade(color, 0.54)); } var SelectableCell = withTheme()(styled(Cell)(_templateObject5(), getBorderRadius, function (_ref5) { var theme = _ref5.theme, isCurrent = _ref5.isCurrent; return isCurrent ? fromTheme(theme, 'current', '#9e9e9e') : 'transparent'; }, getBackground, getColor)); var Header = withTheme()(styled(Cell)(_templateObject6(), function (_ref6) { var theme = _ref6.theme; return fromTheme(theme, 'header', '#9e9e9e'); })); var dateIsInRange = function dateIsInRange(date, fromDate, toDate) { return fromDate && toDate && isWithinRange(date, fromDate, toDate); }; var isSelected = function isSelected(date, compareDate) { return compareDate && isSameDay(date, compareDate); }; function DaySelect(props) { var fromDate = props.fromDate, toDate = props.toDate, getWeeksInMonth = props.getWeeksInMonth, getDayLabelsInWeek = props.getDayLabelsInWeek, date = props.date, getItemProps = props.getItemProps, getMenuProps = props.getMenuProps, highlightedIndex = props.highlightedIndex, setHighlightedIndex = props.setHighlightedIndex; var weeksInMonth = getWeeksInMonth(); var isInOtherMonth = function isInOtherMonth(dateValue) { return !isSameMonth(date, dateValue); }; return React.createElement(Fragment, null, React.createElement(Row, null, getDayLabelsInWeek('dd').map(function (day) { return React.createElement(Header, { key: day }, React.createElement(Text, null, day)); })), React.createElement(HeaderDivider, null), React.createElement(Row, getMenuProps({ onMouseLeave: function onMouseLeave() { return setHighlightedIndex(null); } }), weeksInMonth.map(function (week, i) { return week.map(function (day, j, _ref) { var length = _ref.length; var isFromDate = isSelected(day.dateValue, fromDate); var isToDate = isSelected(day.dateValue, toDate); var index = i * length + j; return React.createElement(SelectableCell, getItemProps({ key: day.label, item: day.dateValue, index: index, isHighlighted: highlightedIndex === index, isLessImportant: isInOtherMonth(day.dateValue), isInRange: dateIsInRange(day.dateValue, fromDate, toDate), isRangeStart: isFromDate && toDate, isRangeEnd: isToDate && fromDate, isSelected: isFromDate || isToDate, isCurrent: isToday(day.dateValue) }), React.createElement(Text, null, day.label)); }); }))); } function _templateObject$1() { var data = _taggedTemplateLiteralLoose(["\n && {\n margin-top: 8px;\n }\n"]); _templateObject$1 = function _templateObject() { return data; }; return data; } var Divider$1 = styled(HeaderDivider)(_templateObject$1()); function getSurroundingYears(date, amount, dateFormat) { if (amount === void 0) { amount = 8; } if (dateFormat === void 0) { dateFormat = 'YYYY'; } var result = []; var selectedYearIndex = getYear(date) % amount; for (var year = 0; year < amount; year++) { var dateValue = addYears(date, year - selectedYearIndex); result.push({ dateValue: dateValue, label: format(dateValue, dateFormat) }); } return result; } function YearSelect(props) { var setDate = props.setDate, date = props.date; return React.createElement(Fragment, null, React.createElement(Divider$1, null), React.createElement(Row, null, getSurroundingYears(date).map(function (year) { return React.createElement(SelectableCell, { key: year.label, widthPercentage: 1 / 4, horizontalSpacing: true, onClick: function onClick() { return setDate(year.dateValue); }, isSelected: isSameYear(year.dateValue, date), isCurrent: isThisYear(year.dateValue) }, React.createElement(Text, null, year.label)); }))); } function getMonthsInYear(date, dateFormat) { if (dateFormat === void 0) { dateFormat = 'MMM'; } var result = []; var selectedMonth = getMonth(date); for (var month = 0; month < 12; month++) { var dateValue = addMonths(date, month - selectedMonth); result.push({ dateValue: dateValue, label: format(dateValue, dateFormat) }); } return result; } function MonthSelect(props) { var setDate = props.setDate, date = props.date; return React.createElement(Fragment, null, React.createElement(Header, { widthPercentage: 1 }, React.createElement(Text, null, "Month & Year")), React.createElement(HeaderDivider, null), React.createElement(Row, null, getMonthsInYear(date).map(function (month) { return React.createElement(SelectableCell, { key: month.label, widthPercentage: 1 / 4, horizontalSpacing: true, onClick: function onClick() { return setDate(month.dateValue); }, isSelected: isSameMonth(month.dateValue, date), isCurrent: isThisMonth(month.dateValue) }, React.createElement(Text, null, month.label)); })), React.createElement(YearSelect, props)); } function _templateObject4$1() { var data = _taggedTemplateLiteralLoose(["\n && {\n font-weight: 600;\n font-size: 14px;\n }\n"]); _templateObject4$1 = function _templateObject4() { return data; }; return data; } function _templateObject3$1() { var data = _taggedTemplateLiteralLoose(["\n flex: 1;\n"]); _templateObject3$1 = function _templateObject3() { return data; }; return data; } function _templateObject2$1() { var data = _taggedTemplateLiteralLoose(["\n && {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n"]); _templateObject2$1 = function _templateObject2() { return data; }; return data; } function _templateObject$2() { var data = _taggedTemplateLiteralLoose(["\n && {\n margin-top: 10px;\n width: 100%;\n min-width: 212px;\n position: absolute;\n z-index: 1;\n flex-direction: row;\n padding: 8px;\n }\n"]); _templateObject$2 = function _templateObject() { return data; }; return data; } var Wrapper = styled(Card)(_templateObject$2()); var MonthButton = styled(IconButton)(_templateObject2$1()); var Spacer = styled.div(_templateObject3$1()); var MothText = styled(Button)(_templateObject4$1()); var Calendar = /*#__PURE__*/ function (_PureComponent) { _inheritsLoose(Calendar, _PureComponent); function Calendar() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _PureComponent.call.apply(_PureComponent, [this].concat(args)) || this; _this.state = { monthSelectOpen: false }; _this.handleMonthTextClick = function () { return _this.setState(function (_ref) { var monthSelectOpen = _ref.monthSelectOpen; return { monthSelectOpen: !monthSelectOpen }; }); }; _this.preventInputLosingFocus = function (e) { return e.preventDefault(); }; return _this; } var _proto = Calendar.prototype; _proto.render = function render() { var _this$props = this.props, getFormattedDate = _this$props.getFormattedDate, setDateNextMonth = _this$props.setDateNextMonth, setDatePrevMonth = _this$props.setDatePrevMonth, clearDateRange = _this$props.clearDateRange; var monthSelectOpen = this.state.monthSelectOpen; return React.createElement(Wrapper, { raised: true, onMouseDown: this.preventInputLosingFocus }, React.createElement(Row, null, React.createElement(MothText, { size: "small", onClick: this.handleMonthTextClick }, getFormattedDate('MMM YYYY'), monthSelectOpen ? React.createElement(ArrowDropUp, null) : React.createElement(ArrowDropDown, null)), React.createElement(Spacer, null), React.createElement(Cell, null, React.createElement(MonthButton, { onClick: clearDateRange, "aria-label": "Clear selection" }, React.createElement(ClearAll, null))), React.createElement(Cell, null, React.createElement(MonthButton, { onClick: setDatePrevMonth, "aria-label": "Previous month" }, React.createElement(NavigateBefore, null))), React.createElement(Cell, null, React.createElement(MonthButton, { onClick: setDateNextMonth, "aria-label": "Next month" }, React.createElement(NavigateNext, null)))), monthSelectOpen ? React.createElement(MonthSelect, this.props) : React.createElement(DaySelect, this.props)); }; return Calendar; }(PureComponent); function _templateObject$3() { var data = _taggedTemplateLiteralLoose(["\n position: relative;\n * {\n box-sizing: border-box;\n }\n"]); _templateObject$3 = function _templateObject() { return data; }; return data; } var Wrapper$1 = styled.div(_templateObject$3()); var itemToString = function itemToString(dateFormat) { return function (_temp) { var _ref = _temp === void 0 ? {} : _temp, fromDate = _ref.fromDate, toDate = _ref.toDate; return "" + (fromDate ? "From: " + format(fromDate, dateFormat) + (toDate ? ' ' : '') : '') + (toDate ? "To: " + format(toDate, dateFormat) : ''); }; }; function stateReducer(state, changes) { // this prevents the menu from being closed when the user // selects an item with a keyboard or mouse switch (changes.type) { case Downshift.stateChangeTypes.keyDownEnter: case Downshift.stateChangeTypes.clickItem: return _extends({}, changes, { isOpen: state.isOpen, highlightedIndex: state.highlightedIndex }); default: return changes; } } var renderCalendar = function renderCalendar(props) { return React.createElement(Calendar, props); }; var DateRangePicker = /*#__PURE__*/ function (_PureComponent) { _inheritsLoose(DateRangePicker, _PureComponent); function DateRangePicker() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _PureComponent.call.apply(_PureComponent, [this].concat(args)) || this; _this.setDateRange = function (selectedDate, stateAndHelpers) { var _this$props = _this.props, fromDate = _this$props.fromDate, toDate = _this$props.toDate; if (!fromDate && toDate && isAfter(selectedDate, toDate)) { _this.props.onChange({ fromDate: toDate, toDate: selectedDate }); return; } // Reset the state if the selected date is equal if (toDate && isSameDay(selectedDate, toDate)) { _this.props.onChange({ toDate: null }); return; } if (fromDate && isSameDay(selectedDate, fromDate)) { _this.props.onChange({ fromDate: null }); return; } // Set the starting date to the selected date // if the starting date is empty if (!fromDate) { _this.props.onChange({ fromDate: selectedDate }); return; } // Set the ending date to the selected date if the start date // is given and the selected date is after the start date if (fromDate && isAfter(selectedDate, fromDate)) { _this.props.onChange({ toDate: selectedDate }); } // Set the starting date to the selected date if the // starting date is given and the selected date is // before the ending date else if (toDate && fromDate && isBefore(selectedDate, fromDate)) { _this.props.onChange({ fromDate: selectedDate }); } // Set the starting date to the selected date // and the ending date to the last starting date // if the starting date is given and the selected date is before this starting date else if (fromDate && isBefore(selectedDate, fromDate)) { _this.props.onChange({ fromDate: selectedDate, toDate: fromDate }); } // Both dates are selected if we get here if (_this.props.closeDialogOnSelection) { stateAndHelpers.closeMenu(); } }; _this.clearDateRange = function () { return _this.props.onChange({ fromDate: null, toDate: null }); }; return _this; } var _proto = DateRangePicker.prototype; _proto.render = function render() { var _this2 = this; var _this$props2 = this.props, fromDate = _this$props2.fromDate, toDate = _this$props2.toDate, dateFormat = _this$props2.dateFormat; return React.createElement(Downshift, _extends({ stateReducer: stateReducer, selectedItem: { fromDate: fromDate, toDate: toDate }, itemToString: itemToString(dateFormat), onSelect: this.setDateRange }, this.props), function (_ref2) { var getInputProps = _ref2.getInputProps, getLabelProps = _ref2.getLabelProps, selectedItem = _ref2.selectedItem, downshiftProps = _objectWithoutPropertiesLoose(_ref2, ["getInputProps", "getLabelProps", "selectedItem"]); return React.createElement("div", { className: _this2.props.className }, React.createElement(TextField, { id: "date-range", label: "Date range", InputLabelProps: getLabelProps({ shrink: downshiftProps.isOpen || !!fromDate || !!toDate }), placeholder: "From:", fullWidth: true, InputProps: getInputProps({ readOnly: true, onClick: downshiftProps.openMenu, onFocus: downshiftProps.openMenu }) }), downshiftProps.isOpen ? React.createElement(Wrapper$1, null, React.createElement(Kalendaryo, _extends({}, downshiftProps, { startCurrentDateAt: selectedItem.fromDate || selectedItem.toDate, fromDate: selectedItem.fromDate, toDate: selectedItem.toDate, clearDateRange: _this2.clearDateRange, startWeekAt: 1, defaultFormat: dateFormat, render: renderCalendar }))) : null); }); }; return DateRangePicker; }(PureComponent); process.env.NODE_ENV !== "production" ? DateRangePicker.propTypes = { fromDate: PropTypes.instanceOf(Date), toDate: PropTypes.instanceOf(Date), onChange: PropTypes.func.isRequired, className: PropTypes.string, dateFormat: PropTypes.string, closeDialogOnSelection: PropTypes.bool } : void 0; DateRangePicker.defaultProps = { fromDate: null, toDate: null, className: '', dateFormat: 'YYYY-MM-DD' }; export { DateRangePicker, Calendar }; //# sourceMappingURL=material-ui-pickers.esm.js.map