@e-group/material-lab
Version:
EGroup Team Lab - Incubator for EGroup Team experimental React components.
370 lines (310 loc) • 10.4 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
import React, { useEffect, useRef, useState } from 'react';
import { isSameDay, addYears, isAfter, isBefore, format } from 'date-fns';
import { ClickAwayListener, Fade, Popper, TextField, Paper, Hidden, IconButton, createStyles, withStyles } from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import { getValidDate } from './utils';
import RangeMenu from './RangeMenu';
import Menu from './Menu';
const styles = theme => createStyles({
root: {
[theme.breakpoints.down('xs')]: {
minWidth: '100vw',
minHeight: '100vh',
overflow: 'auto',
transform: 'none !important'
}
},
paper: {
display: 'flex',
[theme.breakpoints.down('xs')]: {
width: '100%',
minHeight: '100vh'
}
},
close: {
position: 'absolute',
right: 5,
top: 5
}
});
/**
* DateRange picker behavior is inspire by ant design.
* https://ant.design/components/date-picker/
*/
const DateRangePicker = props => {
const classes = props.classes,
initialStartDate = props.initialStartDate,
initialEndDate = props.initialEndDate,
minDateProp = props.minDate,
maxDateProp = props.maxDate,
onChange = props.onChange,
onDayClickProp = props.onDayClick,
onCloseClick = props.onCloseClick,
showTime = props.showTime;
const startEl = useRef(null);
const endEl = useRef(null);
const _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
open = _useState2[0],
setOpen = _useState2[1];
const _useState3 = useState(initialStartDate),
_useState4 = _slicedToArray(_useState3, 2),
startDate = _useState4[0],
setStartDate = _useState4[1];
const _useState5 = useState(initialEndDate),
_useState6 = _slicedToArray(_useState5, 2),
endDate = _useState6[0],
setEndDate = _useState6[1];
const _useState7 = useState(''),
_useState8 = _slicedToArray(_useState7, 2),
startTime = _useState8[0],
setStartTime = _useState8[1];
const _useState9 = useState(''),
_useState10 = _slicedToArray(_useState9, 2),
endTime = _useState10[0],
setEndTime = _useState10[1];
const _useState11 = useState(),
_useState12 = _slicedToArray(_useState11, 2),
hoverDay = _useState12[0],
setHoverDay = _useState12[1];
const _useState13 = useState(),
_useState14 = _slicedToArray(_useState13, 2),
focused = _useState14[0],
setFocused = _useState14[1];
const _useState15 = useState({
start: false,
end: false
}),
_useState16 = _slicedToArray(_useState15, 2),
touched = _useState16[0],
setTouched = _useState16[1];
const minDate = getValidDate(minDateProp, addYears(new Date(), -10));
const maxDate = getValidDate(maxDateProp, addYears(new Date(), 10));
useEffect(() => {
const getValidDateTime = (date, time = '00:00') => {
if (!date) return undefined;
return getValidDate("".concat(format(date, 'yyyy-MM-dd'), " ").concat(time), new Date());
};
if (onChange) {
onChange([getValidDateTime(startDate, startTime), getValidDateTime(endDate, endTime)], focused);
} // eslint-disable-next-line react-hooks/exhaustive-deps
}, [endDate, endTime, focused, startDate, startTime]);
const getStartDateTimeValue = () => {
if (!startDate) return '';
if (showTime) {
return "".concat(format(startDate, 'yyyy-MM-dd'), " ").concat(startTime || '00:00');
}
return format(startDate, 'yyyy-MM-dd');
};
const getEndDateTimeValue = () => {
if (!endDate) return '';
if (showTime) {
return "".concat(format(endDate, 'yyyy-MM-dd'), " ").concat(endTime || '00:00');
}
return format(endDate, 'yyyy-MM-dd');
};
const handlePopupOpen = () => {
setOpen(true);
};
const handlePopupClose = () => {
if (onCloseClick) {
onCloseClick();
}
setOpen(false);
setTouched({
start: false,
end: false
});
};
const focusStartDate = () => {
setFocused('start');
const current = startEl.current;
if (current) {
current.focus();
}
};
const focusEndDate = () => {
setFocused('end');
const current = endEl.current;
if (current) {
current.focus();
}
};
const handleStartClick = () => {
focusStartDate();
handlePopupOpen();
};
const handleEndClick = () => {
focusEndDate();
handlePopupOpen();
};
const getDateRangeWhenSetStartDate = day => {
const nextStartDate = day;
let nextEndDate = endDate;
if (day && endDate && isAfter(day, endDate)) {
nextEndDate = undefined;
}
return [nextStartDate, nextEndDate];
};
const getDateRangeWhenSetEndDate = day => {
let nextStartDate = startDate;
const nextEndDate = day;
if (day && startDate && isBefore(day, startDate)) {
nextStartDate = undefined;
}
return [nextStartDate, nextEndDate];
}; // This behavior refer from ant design range picker.
const handleSetDateNextAction = (startDate, endDate) => {
if (focused === 'start') {
setTouched(val => _objectSpread(_objectSpread({}, val), {}, {
start: true
}));
if (!endDate) {
focusEndDate();
} else {
handlePopupClose();
}
}
if (focused === 'end') {
setTouched(val => _objectSpread(_objectSpread({}, val), {}, {
end: true
}));
if (!startDate) {
focusStartDate();
} else {
handlePopupClose();
}
}
};
const handleTimeClick = time => {
if (focused === 'start') {
setStartTime(time);
}
if (focused === 'end') {
setEndTime(time);
}
};
const handleMenuConfirmClick = () => {
if (focused === 'start') {
handleSetDateNextAction(startDate, endDate);
}
if (focused === 'end') {
handleSetDateNextAction(startDate, endDate);
}
};
const handleMenuDayClick = day => {
if (onDayClickProp) {
onDayClickProp(day);
}
if (focused === 'start') {
const dateRange = getDateRangeWhenSetStartDate(day);
setStartDate(dateRange[0]);
setEndDate(dateRange[1]);
setStartTime(format(new Date(), 'HH:mm'));
if (startTime) {
handleSetDateNextAction(dateRange[0], dateRange[1]);
}
}
if (focused === 'end') {
const dateRange = getDateRangeWhenSetEndDate(day);
setStartDate(dateRange[0]);
setEndDate(dateRange[1]);
setEndTime(format(new Date(), 'HH:mm'));
if (endTime) {
handleSetDateNextAction(dateRange[0], dateRange[1]);
}
}
};
const handleRangeMenuDayClick = day => {
if (onDayClickProp) {
onDayClickProp(day);
}
if (focused === 'start') {
const dateRange = getDateRangeWhenSetStartDate(day);
setStartDate(dateRange[0]);
setEndDate(dateRange[1]);
handleSetDateNextAction(dateRange[0], dateRange[1]);
}
if (focused === 'end') {
const dateRange = getDateRangeWhenSetEndDate(day);
setStartDate(dateRange[0]);
setEndDate(dateRange[1]);
handleSetDateNextAction(dateRange[0], dateRange[1]);
}
};
const handleDayHover = date => {
if (showTime) {
if (startDate && !startTime) {
return;
}
if (endDate && !endTime) {
return;
}
}
if (!hoverDay || !isSameDay(date, hoverDay)) {
setHoverDay(date);
}
};
return /*#__PURE__*/React.createElement(ClickAwayListener, {
onClickAway: handlePopupClose
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(TextField, {
inputRef: startEl,
label: "startDate",
value: getStartDateTimeValue(),
onClick: handleStartClick
}), /*#__PURE__*/React.createElement(TextField, {
inputRef: endEl,
label: "endDate",
value: getEndDateTimeValue(),
onClick: handleEndClick
}), /*#__PURE__*/React.createElement(Popper, {
open: open,
transition: true,
anchorEl: startEl.current,
className: classes.root
}, ({
TransitionProps
}) => /*#__PURE__*/React.createElement(Fade, _extends({}, TransitionProps, {
timeout: 350
}), /*#__PURE__*/React.createElement(Paper, {
className: classes.paper,
elevation: 6
}, /*#__PURE__*/React.createElement(Hidden, {
smUp: true
}, /*#__PURE__*/React.createElement(IconButton, {
className: classes.close,
onClick: handlePopupClose
}, /*#__PURE__*/React.createElement(CloseIcon, null))), showTime ? /*#__PURE__*/React.createElement(Menu, {
startDate: startDate,
endDate: endDate,
minDate: minDate,
maxDate: maxDate,
hoverDay: hoverDay,
touched: touched,
focused: focused,
onDayClick: handleMenuDayClick,
onDayHover: handleDayHover,
onTimeClick: handleTimeClick,
onConfirmClick: handleMenuConfirmClick,
startTime: startTime,
endTime: endTime
}) : /*#__PURE__*/React.createElement(RangeMenu, {
startDate: startDate,
endDate: endDate,
minDate: minDate,
maxDate: maxDate,
hoverDay: hoverDay,
touched: touched,
focused: focused,
onDayClick: handleRangeMenuDayClick,
onDayHover: handleDayHover
}))))));
};
export default withStyles(styles, {
name: 'EgDateRangePicker'
})(DateRangePicker);