ant-design-vue/components/vc-calendar/src/date/DateTBody.jsx

264 lines
8.0 KiB
Vue

import PropTypes from '../../../_util/vue-types';
import { getOptionProps } from '../../../_util/props-util';
import cx from 'classnames';
import DateConstants from './DateConstants';
import { getTitleString, getTodayTime } from '../util/';
function noop() {}
function isSameDay(one, two) {
return one && two && one.isSame(two, 'day');
}
function beforeCurrentMonthYear(current, today) {
if (current.year() < today.year()) {
return 1;
}
return current.year() === today.year() && current.month() < today.month();
}
function afterCurrentMonthYear(current, today) {
if (current.year() > today.year()) {
return 1;
}
return current.year() === today.year() && current.month() > today.month();
}
function getIdFromDate(date) {
return `rc-calendar-${date.year()}-${date.month()}-${date.date()}`;
}
const DateTBody = {
name: 'DateTBody',
inheritAttrs: false,
props: {
contentRender: PropTypes.func,
dateRender: PropTypes.func,
disabledDate: PropTypes.func,
prefixCls: PropTypes.string,
selectedValue: PropTypes.oneOfType([PropTypes.any, PropTypes.arrayOf(PropTypes.any)]),
value: PropTypes.object,
hoverValue: PropTypes.any.def([]),
showWeekNumber: PropTypes.bool,
},
render() {
const props = getOptionProps(this);
const {
contentRender,
prefixCls,
selectedValue,
value,
showWeekNumber,
dateRender,
disabledDate,
hoverValue,
} = props;
const { onSelect = noop, onDayHover = noop } = this.$attrs;
let iIndex;
let jIndex;
let current;
const dateTable = [];
const today = getTodayTime(value);
const cellClass = `${prefixCls}-cell`;
const weekNumberCellClass = `${prefixCls}-week-number-cell`;
const dateClass = `${prefixCls}-date`;
const todayClass = `${prefixCls}-today`;
const selectedClass = `${prefixCls}-selected-day`;
const selectedDateClass = `${prefixCls}-selected-date`; // do not move with mouse operation
const selectedStartDateClass = `${prefixCls}-selected-start-date`;
const selectedEndDateClass = `${prefixCls}-selected-end-date`;
const inRangeClass = `${prefixCls}-in-range-cell`;
const lastMonthDayClass = `${prefixCls}-last-month-cell`;
const nextMonthDayClass = `${prefixCls}-next-month-btn-day`;
const disabledClass = `${prefixCls}-disabled-cell`;
const firstDisableClass = `${prefixCls}-disabled-cell-first-of-row`;
const lastDisableClass = `${prefixCls}-disabled-cell-last-of-row`;
const lastDayOfMonthClass = `${prefixCls}-last-day-of-month`;
const month1 = value.clone();
month1.date(1);
const day = month1.day();
const lastMonthDiffDay = (day + 7 - value.localeData().firstDayOfWeek()) % 7;
// calculate last month
const lastMonth1 = month1.clone();
lastMonth1.add(0 - lastMonthDiffDay, 'days');
let passed = 0;
for (iIndex = 0; iIndex < DateConstants.DATE_ROW_COUNT; iIndex++) {
for (jIndex = 0; jIndex < DateConstants.DATE_COL_COUNT; jIndex++) {
current = lastMonth1;
if (passed) {
current = current.clone();
current.add(passed, 'days');
}
dateTable.push(current);
passed++;
}
}
const tableHtml = [];
passed = 0;
for (iIndex = 0; iIndex < DateConstants.DATE_ROW_COUNT; iIndex++) {
let isCurrentWeek;
let weekNumberCell;
let isActiveWeek = false;
const dateCells = [];
if (showWeekNumber) {
weekNumberCell = (
<td key={`week-${dateTable[passed].week()}`} role="gridcell" class={weekNumberCellClass}>
{dateTable[passed].week()}
</td>
);
}
for (jIndex = 0; jIndex < DateConstants.DATE_COL_COUNT; jIndex++) {
let next = null;
let last = null;
current = dateTable[passed];
if (jIndex < DateConstants.DATE_COL_COUNT - 1) {
next = dateTable[passed + 1];
}
if (jIndex > 0) {
last = dateTable[passed - 1];
}
let cls = cellClass;
let disabled = false;
let selected = false;
if (isSameDay(current, today)) {
cls += ` ${todayClass}`;
isCurrentWeek = true;
}
const isBeforeCurrentMonthYear = beforeCurrentMonthYear(current, value);
const isAfterCurrentMonthYear = afterCurrentMonthYear(current, value);
if (selectedValue && Array.isArray(selectedValue)) {
const rangeValue = hoverValue.length ? hoverValue : selectedValue;
if (!isBeforeCurrentMonthYear && !isAfterCurrentMonthYear) {
const startValue = rangeValue[0];
const endValue = rangeValue[1];
if (startValue) {
if (isSameDay(current, startValue)) {
selected = true;
isActiveWeek = true;
cls += ` ${selectedStartDateClass}`;
}
}
if (startValue || endValue) {
if (isSameDay(current, endValue)) {
selected = true;
isActiveWeek = true;
cls += ` ${selectedEndDateClass}`;
} else if (
(startValue === null || startValue === undefined) &&
current.isBefore(endValue, 'day')
) {
cls += ` ${inRangeClass}`;
} else if (
(endValue === null || endValue === undefined) &&
current.isAfter(startValue, 'day')
) {
cls += ` ${inRangeClass}`;
} else if (current.isAfter(startValue, 'day') && current.isBefore(endValue, 'day')) {
cls += ` ${inRangeClass}`;
}
}
}
} else if (isSameDay(current, value)) {
// keyboard change value, highlight works
selected = true;
isActiveWeek = true;
}
if (isSameDay(current, selectedValue)) {
cls += ` ${selectedDateClass}`;
}
if (isBeforeCurrentMonthYear) {
cls += ` ${lastMonthDayClass}`;
}
if (isAfterCurrentMonthYear) {
cls += ` ${nextMonthDayClass}`;
}
if (
current
.clone()
.endOf('month')
.date() === current.date()
) {
cls += ` ${lastDayOfMonthClass}`;
}
if (disabledDate) {
if (disabledDate(current, value)) {
disabled = true;
if (!last || !disabledDate(last, value)) {
cls += ` ${firstDisableClass}`;
}
if (!next || !disabledDate(next, value)) {
cls += ` ${lastDisableClass}`;
}
}
}
if (selected) {
cls += ` ${selectedClass}`;
}
if (disabled) {
cls += ` ${disabledClass}`;
}
let dateHtml;
if (dateRender) {
dateHtml = dateRender({ current, today: value });
} else {
const content = contentRender ? contentRender({ current, today: value }) : current.date();
dateHtml = (
<div
key={getIdFromDate(current)}
class={dateClass}
aria-selected={selected}
aria-disabled={disabled}
>
{content}
</div>
);
}
dateCells.push(
<td
key={passed}
onClick={disabled ? noop : onSelect.bind(null, current)}
onMouseenter={disabled ? noop : onDayHover.bind(null, current)}
role="gridcell"
title={getTitleString(current)}
class={cls}
>
{dateHtml}
</td>,
);
passed++;
}
tableHtml.push(
<tr
key={iIndex}
role="row"
class={cx({
[`${prefixCls}-current-week`]: isCurrentWeek,
[`${prefixCls}-active-week`]: isActiveWeek,
})}
>
{weekNumberCell}
{dateCells}
</tr>,
);
}
return <tbody class={`${prefixCls}-tbody`}>{tableHtml}</tbody>;
},
};
export default DateTBody;