@alifd/next
Version:
A configurable component library for web built on React.
491 lines (390 loc) • 17.3 kB
JavaScript
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _extends from 'babel-runtime/helpers/extends';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
var _class, _temp, _initialiseProps;
import React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classnames from 'classnames';
import * as PT from 'prop-types';
import SharedPT from '../prop-types';
import { func, datejs, obj } from '../../util';
import { setTime, switchInputType, mode2unit } from '../util';
import { DATE_INPUT_TYPE } from '../constant';
import { DATE_PANEL_MODE, CALENDAR_CELL_STATE } from '../../calendar2/constant';
import Calendar from '../../calendar2';
import TimePanel from './time-panel';
var DATE = DATE_PANEL_MODE.DATE,
WEEK = DATE_PANEL_MODE.WEEK,
MONTH = DATE_PANEL_MODE.MONTH,
QUARTER = DATE_PANEL_MODE.QUARTER,
YEAR = DATE_PANEL_MODE.YEAR;
var UN_SELECTED = CALENDAR_CELL_STATE.UN_SELECTED,
SELECTED = CALENDAR_CELL_STATE.SELECTED,
SELECTED_BEGIN = CALENDAR_CELL_STATE.SELECTED_BEGIN,
SELECTED_END = CALENDAR_CELL_STATE.SELECTED_END;
var BEGIN = DATE_INPUT_TYPE.BEGIN,
END = DATE_INPUT_TYPE.END;
var operate = function operate(mode, value, operator) {
var newVal = value.clone();
switch (mode) {
case DATE:
case WEEK:
return newVal[operator](1, 'month');
case QUARTER:
case MONTH:
return newVal[operator](1, 'year');
case YEAR:
return newVal[operator](10, 'year');
}
};
var isSamePanel = function isSamePanel(a, b, mode) {
switch (mode) {
case DATE:
case WEEK:
return a.isSame(b, 'month');
case QUARTER:
case MONTH:
return a.isSame(b, 'year');
case YEAR:
{
var begin = a.year() - a.year() % 20;
var byear = b.year();
return byear >= begin && byear < begin + 20;
}
}
};
// 计算 面板日期
var getPanelValue = function getPanelValue(_ref, defaultValue) {
var mode = _ref.mode,
value = _ref.value,
inputType = _ref.inputType,
showTime = _ref.showTime;
var begin = value[0],
end = value[1];
var otherType = inputType === BEGIN ? END : BEGIN;
var _inputType = inputType;
if (!value[inputType] && value[otherType]) {
_inputType = otherType;
}
var panelValue = value[_inputType] || datejs(defaultValue);
// https://github.com/alibaba-fusion/next/issues/3186
if (!showTime && _inputType === END && end && (begin && !isSamePanel(begin, end, mode) || !begin)) {
panelValue = operate(mode, panelValue, 'subtract');
}
return panelValue && panelValue.isValid() ? panelValue : datejs();
};
var RangePanel = (_temp = _class = function (_React$Component) {
_inherits(RangePanel, _React$Component);
function RangePanel(props) {
_classCallCheck(this, RangePanel);
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
_initialiseProps.call(_this);
var mode = props.mode,
defaultPanelValue = props.defaultPanelValue,
_props$timePanelProps = props.timePanelProps,
timePanelProps = _props$timePanelProps === undefined ? {} : _props$timePanelProps;
// 默认时间
var defaultTime = timePanelProps.defaultValue || [];
if (!Array.isArray(defaultTime)) {
defaultTime = [defaultTime, defaultTime];
}
defaultTime = defaultTime.map(function (t) {
return datejs(t, timePanelProps.format || 'HH:mm:ss');
});
_this.state = {
mode: mode,
panelValue: getPanelValue(props, defaultPanelValue),
inputType: props.inputType,
curHoverValue: null,
defaultTime: defaultTime
};
return _this;
}
RangePanel.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {
if (props.inputType !== state.inputType) {
return {
inputType: props.inputType,
panelValue: getPanelValue(props, state.panelValue)
};
}
return null;
};
RangePanel.prototype.componentWillUnmount = function componentWillUnmount() {
this.currentRaf && window.cancelAnimationFrame(this.currentRaf);
};
// 日期面板显示的日期区间
RangePanel.prototype.getRanges = function getRanges() {
var mode = this.props.mode;
var v = this.state.panelValue;
var begin = v.clone();
var end = operate(mode, v, 'add');
return [begin, end];
};
// 日期cell状态
RangePanel.prototype.handleCellState = function handleCellState(v, value) {
var mode = this.props.mode;
var begin = value[0],
end = value[1];
var unit = this.getUnitByMode(mode);
return begin && begin.isSame(v, unit) ? SELECTED_BEGIN : end && end.isSame(v, unit) ? SELECTED_END : begin && end && v.isAfter(begin, unit) && v.isBefore(end, unit) ? SELECTED : UN_SELECTED;
};
RangePanel.prototype.getUnitByMode = function getUnitByMode(mode) {
return mode === DATE ? 'day' : mode;
};
// 头部面板日期切换点击事件
RangePanel.prototype.renderRange = function renderRange(sharedProps) {
var _classnames;
var handlePanelChange = this.handlePanelChange,
handleCanlendarClick = this.handleCanlendarClick,
hasModeChanged = this.hasModeChanged;
var _props = this.props,
value = _props.value,
prefix = _props.prefix;
var ranges = this.getRanges();
var calendarProps = function calendarProps(idx) {
return _extends({}, sharedProps, {
value: value[idx],
panelValue: ranges[idx],
onPanelChange: function onPanelChange(v, m) {
return handlePanelChange(v, m, idx);
}
});
};
var calendarNodes = [React.createElement(Calendar, _extends({}, calendarProps(0), { className: prefix + 'range-picker-left', key: 'range-panel-calendar-left' })), React.createElement(Calendar, _extends({}, calendarProps(1), {
className: prefix + 'range-picker-right',
key: 'range-panel-calendar-right',
onNext: handleCanlendarClick,
onSuperNext: handleCanlendarClick
}))];
var className = classnames(prefix + 'range-picker2-panel', (_classnames = {}, _classnames[prefix + 'range-picker2-panel-single'] = hasModeChanged, _classnames));
return React.createElement(
'div',
{ key: 'range-panel', className: className },
!this.hasModeChanged ? calendarNodes : calendarNodes[this.state.calendarIdx]
);
};
RangePanel.prototype.render = function render() {
var handleSelect = this.handleSelect,
getCellClassName = this.getCellClassName,
handleMouseEnter = this.handleMouseEnter,
handleMouseLeave = this.handleMouseLeave;
var _props2 = this.props,
mode = _props2.mode,
justBeginInput = _props2.justBeginInput,
dateCellRender = _props2.dateCellRender,
restProps = _objectWithoutProperties(_props2, ['mode', 'justBeginInput', 'dateCellRender']);
// 切换面板mode
this.hasModeChanged = this.state.mode !== this.props.mode;
var sharedProps = _extends({}, obj.pickProps(Calendar.propTypes, restProps), {
shape: 'panel',
panelMode: mode,
dateCellRender: dateCellRender
});
sharedProps.disabledDate = justBeginInput ? this.props.disabledDate : this.disabledDate;
// 日期面板固定列数 保证对齐
if ([DATE, WEEK].includes(mode)) {
sharedProps.colNum = 6;
}
if (!this.hasModeChanged) {
sharedProps = _extends({}, sharedProps, {
onSelect: handleSelect,
cellClassName: getCellClassName,
cellProps: {
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave
}
});
}
return this.props.showTime ? this.renderRangeTime(sharedProps) : this.renderRange(sharedProps);
};
return RangePanel;
}(React.Component), _class.propTypes = {
rtl: PT.bool,
prefix: PT.string,
locale: PT.object,
mode: SharedPT.mode,
value: PT.arrayOf(SharedPT.date),
inputType: SharedPT.inputType,
handleCellState: PT.func,
disabledDate: PT.func,
justBeginInput: PT.bool,
resetTime: PT.bool,
showTime: PT.bool,
timePanelProps: PT.object,
disabledTime: PT.object,
dateCellRender: PT.func
}, _class.defaultProps = {
disabledDate: function disabledDate() {
return false;
},
justBeginInput: true
}, _initialiseProps = function _initialiseProps() {
var _this2 = this;
this.disabledDate = function (v) {
var _props3 = _this2.props,
mode = _props3.mode,
inputType = _props3.inputType,
disabledDate = _props3.disabledDate,
_props3$value = _props3.value,
begin = _props3$value[0],
end = _props3$value[1];
var unit = mode2unit(mode);
return disabledDate(v, mode) || inputType === END && begin && begin.isAfter(v, unit) || inputType === BEGIN && end && end.isBefore(v, unit);
};
this.onTimeSelect = function (v) {
var _props4 = _this2.props,
value = _props4.value,
inputType = _props4.inputType;
var begin = value[0],
end = value[1];
var curDateVal = value[inputType];
if (!curDateVal) {
curDateVal = inputType === BEGIN && end ? end.subtract(1, 'day') : inputType === END && begin ? begin.add(1, 'day') : datejs();
}
curDateVal = setTime(curDateVal, v);
_this2.handleSelect(curDateVal, true);
};
this.handleSelect = function (v, fromTimeChange) {
var _props5 = _this2.props,
value = _props5.value,
inputType = _props5.inputType,
resetTime = _props5.resetTime;
var otherType = switchInputType(inputType);
var newValue = [].concat(value);
var defaultTime = _this2.state.defaultTime[inputType];
var timeVal = null;
// 如果不是选择时间面板触发的时间改变或不需要重置时间
// 则需要设置时间值,优先级如下:
// - 目前这个日期时间
// - 默认时间
// - 另一日期时间
// - 当前时间
if (!fromTimeChange && !resetTime) {
timeVal = value[inputType] || defaultTime || value[otherType] || datejs();
}
newValue[inputType === BEGIN ? 0 : 1] = setTime(v, timeVal);
func.invoke(_this2.props, 'onSelect', [newValue]);
};
this.handlePanelChange = function (v, mode, idx) {
_this2.setState({
mode: mode,
panelValue: v,
calendarIdx: idx
});
func.invoke(_this2.props, 'onPanelChange', [v, mode]);
};
this.handleMouseEnter = function (value) {
_this2.currentRaf && window.cancelAnimationFrame(_this2.currentRaf);
_this2.currentRaf = window.requestAnimationFrame(function () {
_this2.setState({
curHoverValue: value
});
});
};
this.handleMouseLeave = function () {
_this2.currentRaf && window.cancelAnimationFrame(_this2.currentRaf);
_this2.setState({
curHoverValue: null
});
};
this.handleEdgeState = function (value, mode) {
var unit = _this2.getUnitByMode(mode);
switch (mode) {
case DATE:
{
var endDate = value.endOf('month');
var beginDate = value.startOf('month');
return beginDate.isSame(value, unit) ? 1 : endDate.isSame(value, unit) ? 2 : 0;
}
case YEAR:
{
var year = value.year();
var beginYear = value.year() - value.year() % 10;
var endYear = beginYear + 9;
return year === beginYear ? 1 : year === endYear ? 2 : 0;
}
default:
return 0;
}
};
this.getCellClassName = function (value) {
var _extends2;
var _props6 = _this2.props,
prefix = _props6.prefix,
inputType = _props6.inputType,
mode = _props6.mode;
var curHoverValue = _this2.state.curHoverValue;
var _props$value = _this2.props.value,
begin = _props$value[0],
end = _props$value[1];
var unit = _this2.getUnitByMode(mode);
var state = _this2.handleCellState(value, _this2.props.value);
var prefixCls = prefix + 'calendar2-cell';
var hoverClassName = void 0;
if (curHoverValue) {
var hoverValue = [].concat(_this2.props.value);
hoverValue[inputType] = curHoverValue;
var hoverBegin = hoverValue[0],
hoverEnd = hoverValue[1];
if (hoverBegin && hoverEnd && hoverBegin.isBefore(hoverEnd, unit)) {
var _hoverClassName;
var hoverState = _this2.handleCellState(value, hoverValue);
hoverClassName = (_hoverClassName = {}, _hoverClassName[prefixCls + '-hover'] = hoverState >= SELECTED, _hoverClassName[prefixCls + '-hover-begin'] = hoverState === SELECTED_BEGIN, _hoverClassName[prefixCls + '-hover-end'] = hoverState === SELECTED_END, _hoverClassName[prefixCls + '-hover-end'] = hoverState === SELECTED_END, _hoverClassName);
}
}
var rangeClassName = void 0;
if (!_this2.hasModeChanged) {
var _ref2, _ref3;
var edgeState = _this2.handleEdgeState(value, mode);
var isIllegal = end && begin && begin.isAfter(end);
rangeClassName = mode === WEEK ? (_ref2 = {}, _ref2[prefixCls + '-week-range-begin'] = state === SELECTED_BEGIN, _ref2[prefixCls + '-week-range-end'] = state === SELECTED_END, _ref2) : (_ref3 = {}, _ref3[prefixCls + '-range-begin'] = state === SELECTED_BEGIN, _ref3[prefixCls + '-range-end'] = state === SELECTED_END, _ref3[prefixCls + '-range-begin-single'] = state >= SELECTED && (!end || end.isSame(begin, unit) || isIllegal), _ref3[prefixCls + '-range-end-single'] = state >= SELECTED && (!begin || begin.isSame(end, unit) || isIllegal), _ref3[prefixCls + '-edge-begin'] = edgeState === 1, _ref3[prefixCls + '-edge-end'] = edgeState === 2, _ref3);
}
return _extends((_extends2 = {}, _extends2[prefixCls + '-selected'] = state >= SELECTED, _extends2), rangeClassName, hoverClassName);
};
this.handleCanlendarClick = function (_, _ref4) {
var unit = _ref4.unit,
num = _ref4.num;
_this2.setState({
panelValue: _this2.state.panelValue.clone().add(num, unit)
});
};
this.renderRangeTime = function (sharedProps) {
var _classnames2;
var _props7 = _this2.props,
value = _props7.value,
prefix = _props7.prefix,
showTime = _props7.showTime,
inputType = _props7.inputType,
_props7$timePanelProp = _props7.timePanelProps,
timePanelProps = _props7$timePanelProp === undefined ? {} : _props7$timePanelProp,
disabledTime = _props7.disabledTime;
var className = classnames(prefix + 'range-picker2-panel', (_classnames2 = {}, _classnames2[prefix + 'range-picker2-panel-single'] = _this2.hasModeChanged, _classnames2));
// 禁用时间
var _disabledTime = void 0;
if (showTime && !_this2.hasModeChanged && disabledTime) {
_disabledTime = typeof disabledTime === 'function' ? disabledTime(value, inputType) : disabledTime;
}
return React.createElement(
'div',
{ key: 'range-time-panel', className: className },
React.createElement(Calendar, _extends({
panelValue: _this2.state.panelValue
}, sharedProps, {
value: value[inputType],
onPanelChange: _this2.handlePanelChange
})),
showTime && !_this2.hasModeChanged ? React.createElement(TimePanel, {
prefix: prefix,
inputType: inputType,
value: value[inputType] || _this2.state.defaultTime[inputType],
onSelect: _this2.onTimeSelect,
disabledTime: disabledTime,
timePanelProps: _extends({}, _disabledTime, timePanelProps)
}) : null
);
};
}, _temp);
RangePanel.displayName = 'RangePanel';
export default polyfill(RangePanel);