UNPKG

12.3 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
3import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
4import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
5import _inherits from 'babel-runtime/helpers/inherits';
6
7var _class, _temp, _initialiseProps;
8
9import React, { Component } from 'react';
10import PropTypes from 'prop-types';
11import { polyfill } from 'react-lifecycles-compat';
12import moment from 'moment';
13import classnames from 'classnames';
14import ConfigProvider from '../config-provider';
15import nextLocale from '../locale/zh-cn';
16import { func, obj } from '../util';
17import CardHeader from './head/card-header';
18import DatePanelHeader from './head/date-panel-header';
19import MonthPanelHeader from './head/month-panel-header';
20import YearPanelHeader from './head/year-panel-header';
21import DateTable from './table/date-table';
22import MonthTable from './table/month-table';
23import YearTable from './table/year-table';
24import { checkMomentObj, formatDateValue, getVisibleMonth, isSameYearMonth, CALENDAR_MODES, CALENDAR_MODE_DATE, CALENDAR_MODE_MONTH, CALENDAR_MODE_YEAR, getLocaleData } from './utils';
25
26var isValueChanged = function isValueChanged(value, oldVlaue) {
27 if (value && oldVlaue) {
28 if (!moment.isMoment(value)) {
29 value = moment(value);
30 }
31 if (!moment.isMoment(oldVlaue)) {
32 oldVlaue = moment(oldVlaue);
33 }
34 return value.valueOf() !== oldVlaue.valueOf();
35 } else {
36 return value !== oldVlaue;
37 }
38};
39
40/** Calendar */
41var Calendar = (_temp = _class = function (_Component) {
42 _inherits(Calendar, _Component);
43
44 function Calendar(props, context) {
45 _classCallCheck(this, Calendar);
46
47 var _this = _possibleConstructorReturn(this, _Component.call(this, props, context));
48
49 _initialiseProps.call(_this);
50
51 var value = formatDateValue(props.value || props.defaultValue);
52 var visibleMonth = getVisibleMonth(props.defaultVisibleMonth, value);
53
54 _this.MODES = props.modes;
55 _this.today = moment();
56 _this.state = {
57 value: value,
58 mode: props.mode || _this.MODES[0],
59 MODES: _this.MODES,
60 visibleMonth: visibleMonth
61 };
62 return _this;
63 }
64
65 Calendar.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {
66 var st = {};
67 if ('value' in props) {
68 var value = formatDateValue(props.value);
69 if (value && isValueChanged(props.value, state.value)) {
70 st.visibleMonth = value;
71 }
72 st.value = value;
73 }
74
75 if (props.mode && state.MODES.indexOf(props.mode) > -1) {
76 st.mode = props.mode;
77 }
78
79 return st;
80 };
81
82 /**
83 * 根据日期偏移量设置当前展示的月份
84 * @param {Number} offset 日期偏移的数量
85 * @param {String} type 日期偏移的类型 days, months, years
86 */
87 Calendar.prototype.changeVisibleMonthByOffset = function changeVisibleMonthByOffset(offset, type) {
88 var cloneValue = this.state.visibleMonth.clone();
89 cloneValue.add(offset, type);
90 this.changeVisibleMonth(cloneValue, 'buttonClick');
91 };
92
93 Calendar.prototype.render = function render() {
94 var _classnames, _tables, _panelHeaders;
95
96 var _props = this.props,
97 prefix = _props.prefix,
98 rtl = _props.rtl,
99 className = _props.className,
100 shape = _props.shape,
101 showOtherMonth = _props.showOtherMonth,
102 format = _props.format,
103 locale = _props.locale,
104 dateCellRender = _props.dateCellRender,
105 monthCellRender = _props.monthCellRender,
106 yearCellRender = _props.yearCellRender,
107 disabledDate = _props.disabledDate,
108 yearRange = _props.yearRange,
109 disableChangeMode = _props.disableChangeMode,
110 others = _objectWithoutProperties(_props, ['prefix', 'rtl', 'className', 'shape', 'showOtherMonth', 'format', 'locale', 'dateCellRender', 'monthCellRender', 'yearCellRender', 'disabledDate', 'yearRange', 'disableChangeMode']);
111
112 var state = this.state;
113
114 var classNames = classnames((_classnames = {}, _classnames[prefix + 'calendar'] = true, _classnames[prefix + 'calendar-' + shape] = shape, _classnames), className);
115
116 if (rtl) {
117 others.dir = 'rtl';
118 }
119
120 var visibleMonth = state.visibleMonth;
121
122 // reset moment locale
123 if (locale.momentLocale) {
124 state.value && state.value.locale(locale.momentLocale);
125 visibleMonth.locale(locale.momentLocale);
126 }
127
128 var localeData = getLocaleData(locale.format || {}, visibleMonth.localeData());
129
130 var headerProps = {
131 prefix: prefix,
132 value: state.value,
133 mode: state.mode,
134 disableChangeMode: disableChangeMode,
135 yearRange: yearRange,
136 locale: locale,
137 rtl: rtl,
138 visibleMonth: visibleMonth,
139 momentLocale: localeData,
140 changeMode: this.changeMode,
141 changeVisibleMonth: this.changeVisibleMonth,
142 goNextDecade: this.goNextDecade,
143 goNextYear: this.goNextYear,
144 goNextMonth: this.goNextMonth,
145 goPrevDecade: this.goPrevDecade,
146 goPrevYear: this.goPrevYear,
147 goPrevMonth: this.goPrevMonth
148 };
149
150 var tableProps = {
151 prefix: prefix,
152 visibleMonth: visibleMonth,
153 showOtherMonth: showOtherMonth,
154 value: state.value,
155 mode: state.mode,
156 locale: locale,
157 dateCellRender: dateCellRender,
158 monthCellRender: monthCellRender,
159 yearCellRender: yearCellRender,
160 disabledDate: disabledDate,
161 momentLocale: localeData,
162 today: this.today,
163 goPrevDecade: this.goPrevDecade,
164 goNextDecade: this.goNextDecade
165 };
166
167 var tables = (_tables = {}, _tables[CALENDAR_MODE_DATE] = React.createElement(DateTable, _extends({ format: format }, tableProps, { onSelectDate: this.onSelectCell })), _tables[CALENDAR_MODE_MONTH] = React.createElement(MonthTable, _extends({}, tableProps, { onSelectMonth: this.onSelectCell })), _tables[CALENDAR_MODE_YEAR] = React.createElement(YearTable, _extends({}, tableProps, { rtl: rtl, onSelectYear: this.onSelectCell })), _tables);
168
169 var panelHeaders = (_panelHeaders = {}, _panelHeaders[CALENDAR_MODE_DATE] = React.createElement(DatePanelHeader, headerProps), _panelHeaders[CALENDAR_MODE_MONTH] = React.createElement(MonthPanelHeader, headerProps), _panelHeaders[CALENDAR_MODE_YEAR] = React.createElement(YearPanelHeader, headerProps), _panelHeaders);
170
171 return React.createElement(
172 'div',
173 _extends({}, obj.pickOthers(Calendar.propTypes, others), { className: classNames }),
174 shape === 'panel' ? panelHeaders[state.mode] : React.createElement(CardHeader, headerProps),
175 tables[state.mode]
176 );
177 };
178
179 return Calendar;
180}(Component), _class.propTypes = _extends({}, ConfigProvider.propTypes, {
181 prefix: PropTypes.string,
182 rtl: PropTypes.bool,
183 /**
184 * 默认选中的日期(moment 对象)
185 */
186 defaultValue: checkMomentObj,
187 /**
188 * 选中的日期值 (moment 对象)
189 */
190 value: checkMomentObj,
191 /**
192 * 面板模式
193 */
194 mode: PropTypes.oneOf(CALENDAR_MODES), // 生成 API 文档需要手动改回 ['date', 'month', 'year']
195 // 面板可变化的模式列表,仅初始化时接收一次
196 modes: PropTypes.array,
197 // 禁用更改面板模式,采用 dropdown 的方式切换显示日期 (暂不正式对外透出)
198 disableChangeMode: PropTypes.bool,
199 // 日期值的格式(用于日期title显示的格式)
200 format: PropTypes.string,
201 /**
202 * 是否展示非本月的日期
203 */
204 showOtherMonth: PropTypes.bool,
205 /**
206 * 默认展示的月份
207 */
208 defaultVisibleMonth: PropTypes.func,
209 /**
210 * 展现形态
211 */
212 shape: PropTypes.oneOf(['card', 'fullscreen', 'panel']),
213 /**
214 * 选择日期单元格时的回调
215 * @param {Object} value 对应的日期值 (moment 对象)
216 */
217 onSelect: PropTypes.func,
218 /**
219 * 面板模式变化时的回调
220 * @param {String} mode 对应面板模式 date month year
221 */
222 onModeChange: PropTypes.func,
223 /**
224 * 展现的月份变化时的回调
225 * @param {Object} value 显示的月份 (moment 对象)
226 * @param {String} reason 触发月份改变原因
227 */
228 onVisibleMonthChange: PropTypes.func,
229 /**
230 * 自定义样式类
231 */
232 className: PropTypes.string,
233 /**
234 * 自定义日期渲染函数
235 * @param {Object} value 日期值(moment对象)
236 * @returns {ReactNode}
237 */
238 dateCellRender: PropTypes.func,
239 /**
240 * 自定义月份渲染函数
241 * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象
242 * @returns {ReactNode}
243 */
244 monthCellRender: PropTypes.func,
245 yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender
246 /**
247 * 年份范围,[START_YEAR, END_YEAR] (只在shape 为 ‘card’, 'fullscreen' 下生效)
248 */
249 yearRange: PropTypes.arrayOf(PropTypes.number),
250 /**
251 * 不可选择的日期
252 * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象
253 * @param {String} view 当前视图类型,year: 年, month: 月, date: 日
254 * @returns {Boolean}
255 */
256 disabledDate: PropTypes.func,
257 /**
258 * 国际化配置
259 */
260 locale: PropTypes.object
261}), _class.defaultProps = {
262 prefix: 'next-',
263 rtl: false,
264 shape: 'fullscreen',
265 modes: CALENDAR_MODES,
266 disableChangeMode: false,
267 format: 'YYYY-MM-DD',
268 onSelect: func.noop,
269 onVisibleMonthChange: func.noop,
270 onModeChange: func.noop,
271 dateCellRender: function dateCellRender(value) {
272 return value.date();
273 },
274 locale: nextLocale.Calendar,
275 showOtherMonth: true
276}, _initialiseProps = function _initialiseProps() {
277 var _this2 = this;
278
279 this.onSelectCell = function (date, nextMode) {
280 var visibleMonth = _this2.state.visibleMonth;
281 var _props2 = _this2.props,
282 shape = _props2.shape,
283 showOtherMonth = _props2.showOtherMonth;
284
285 // 点击其他月份日期不生效
286
287 if (!showOtherMonth && !isSameYearMonth(visibleMonth, date)) {
288 return;
289 }
290
291 _this2.changeVisibleMonth(date, 'cellClick');
292
293 // 当用户所在的面板为初始化面板时,则选择动作为触发 onSelect 回调
294 if (_this2.state.mode === _this2.MODES[0]) {
295 _this2.props.onSelect(date);
296 }
297
298 if (shape === 'panel') {
299 _this2.changeMode(nextMode);
300 }
301 };
302
303 this.changeMode = function (nextMode) {
304 if (nextMode && _this2.MODES.indexOf(nextMode) > -1 && nextMode !== _this2.state.mode) {
305 _this2.setState({ mode: nextMode });
306 _this2.props.onModeChange(nextMode);
307 }
308 };
309
310 this.changeVisibleMonth = function (date, reason) {
311 if (!isSameYearMonth(date, _this2.state.visibleMonth)) {
312 _this2.setState({ visibleMonth: date });
313 _this2.props.onVisibleMonthChange(date, reason);
314 }
315 };
316
317 this.goPrevDecade = function () {
318 _this2.changeVisibleMonthByOffset(-10, 'years');
319 };
320
321 this.goNextDecade = function () {
322 _this2.changeVisibleMonthByOffset(10, 'years');
323 };
324
325 this.goPrevYear = function () {
326 _this2.changeVisibleMonthByOffset(-1, 'years');
327 };
328
329 this.goNextYear = function () {
330 _this2.changeVisibleMonthByOffset(1, 'years');
331 };
332
333 this.goPrevMonth = function () {
334 _this2.changeVisibleMonthByOffset(-1, 'months');
335 };
336
337 this.goNextMonth = function () {
338 _this2.changeVisibleMonthByOffset(1, 'months');
339 };
340}, _temp);
341Calendar.displayName = 'Calendar';
342
343
344export default polyfill(Calendar);
\No newline at end of file