@6thquake/react-material
Version:
React components that implement Google's Material Design.
190 lines (172 loc) • 4.76 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
/**
* @ignore - do not document.
*/
import React, { useState, useContext } from 'react';
import compose from 'recompose/compose';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import moment from 'moment';
import { Calendar, MuiPickersContext } from '@material-ui/pickers';
import withStyles from '../styles/withStyles';
import { withLocale } from '../LocaleProvider';
const sort = ([a, b]) => {
if (!(a && b)) {
return [a, b];
}
if (b.isBefore(a)) {
return [b, a];
}
return [a, b];
};
const isWithinRange = (day, [min, max]) => {
max = max || min;
const isAfterMin = day.diff(min) >= 0;
const isBeforeMax = day.diff(max) <= 0;
return isAfterMin && isBeforeMax;
};
const CalendarPicker = React.forwardRef(function CalendarPicker(props, ref) {
const {
className: classNamePro,
classes,
value,
onChange
} = props,
other = _objectWithoutPropertiesLoose(props, ["className", "classes", "value", "onChange"]);
const className = classNames(classNamePro);
const classesPro = _extends({}, classes);
const {
start: startDate,
end: endDate
} = value || {};
const [preBegin, setPreBegin] = useState(null);
const [preEnd, setPreEnd] = useState(null);
const [begin, setBegin] = useState(moment(startDate));
const [end, setEnd] = useState(moment(endDate));
const utils = useContext(MuiPickersContext);
if (preBegin !== startDate) {
setPreBegin(startDate);
setBegin(moment(startDate));
}
if (preEnd !== endDate) {
setPreEnd(endDate);
setEnd(moment(endDate));
}
const [min, max] = sort([begin, end]);
function renderDay(day, selectedDate, dayInCurrentMonth, dayComponent) {
return React.cloneElement(dayComponent, {
onClick: e => {
e.stopPropagation();
if (!begin) {
setBegin(day);
} else if (!end) {
setEnd(day);
const days = sort([begin, day]).map(item => item.format('YYYY-MM-DD'));
const [start, end] = days;
onChange({
start,
end
});
} else {
setBegin(day);
setEnd(undefined);
}
},
// onMouseEnter: e => setHover(day),
className: classNames(classes.day, {
[classes.hidden]: dayComponent.props.hidden,
[classes.current]: dayComponent.props.current,
[classes.dayDisabled]: dayComponent.props.disabled,
[classes.daySelected]: isWithinRange(day, [min, max]),
[classes.beginCap]: utils.isSameDay(day, min),
[classes.endCap]: utils.isSameDay(day, max)
})
});
}
return React.createElement(Calendar, _extends({
date: begin,
renderDay: renderDay,
classes: classesPro,
className: className,
ref: ref
}, other));
});
export const styles = theme => {
const base = {
day: {
width: 36,
height: 36,
fontSize: theme.typography.caption.fontSize,
margin: '0 2px',
color: theme.palette.text.primary,
fontWeight: theme.typography.fontWeightMedium,
padding: 0
},
hidden: {
opacity: 0,
pointerEvents: 'none'
},
current: {
color: theme.palette.primary.main,
fontWeight: 600
},
daySelected: {
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.main,
fontWeight: theme.typography.fontWeightMedium,
'&:hover': {
backgroundColor: theme.palette.primary.main
}
},
dayDisabled: {
pointerEvents: 'none',
color: theme.palette.text.hint
}
};
return _extends({}, base, {
day: _extends({}, base.day, {
margin: 0,
width: 40,
borderRadius: '0'
}),
beginCap: {
borderTopLeftRadius: '50%',
borderBottomLeftRadius: '50%'
},
endCap: {
borderTopRightRadius: '50%',
borderBottomRightRadius: '50%'
}
});
};
process.env.NODE_ENV !== "production" ? CalendarPicker.propTypes = {
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css-api) below for more details.
*/
classes: PropTypes.object,
/**
* @ignore
*/
className: PropTypes.string,
/**
* Calendar onChange
*/
onChange: PropTypes.func,
/**
* the start date and end date of calendar
*/
value: PropTypes.shape({
end: PropTypes.string,
start: PropTypes.string
})
} : void 0;
CalendarPicker.defaultProps = {
onChange: () => {}
};
export default compose(withLocale({
name: 'CalendarPicker'
}), withStyles(styles, {
name: 'CalendarPicker'
}))(CalendarPicker);