@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
418 lines (417 loc) • 14.2 kB
JavaScript
import React__default, { useState, useEffect } from "react";
import classNames from "classnames";
import { C as ComponentDefaults } from "./typings.js";
import { U as Utils } from "./date.js";
import { u as useConfig } from "./configprovider2.js";
import { u as usePropsValue } from "./use-props-value.js";
const ArrowLeft = () => {
return React__default.createElement(
"svg",
{ xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 18 18" },
React__default.createElement("path", { d: "M6.605 9.49a.771.771 0 0 1 0-.98l3.6-4.372a.771.771 0 0 1 1.19.981L8.2 9l3.197 3.881a.771.771 0 1 1-1.191.98l-3.6-4.37Z" })
);
};
const ArrowRight = () => {
return React__default.createElement(
"svg",
{ xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 18 18" },
React__default.createElement("path", { d: "M11.396 9.49a.771.771 0 0 0 0-.98l-3.6-4.372a.771.771 0 0 0-1.191.981L9.8 9l-3.196 3.881a.771.771 0 0 0 1.19.98l3.6-4.37Z" })
);
};
const DoubleLeft = () => {
return React__default.createElement(
"svg",
{ xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 18 18" },
React__default.createElement("path", { d: "M13.853 4.026a.771.771 0 0 1 .12 1.085L10.864 9l3.11 3.889a.771.771 0 1 1-1.204.963L9.272 9.482a.771.771 0 0 1 0-.964l3.497-4.371a.771.771 0 0 1 1.084-.12Zm-5.245 0a.771.771 0 0 1 .12 1.085L5.617 9l3.111 3.889a.771.771 0 0 1-1.205.963L4.026 9.482a.771.771 0 0 1 0-.964l3.497-4.371a.771.771 0 0 1 1.085-.12Z" })
);
};
const DoubleRight = () => {
return React__default.createElement(
"svg",
{ xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 18 18" },
React__default.createElement("path", { d: "M4.147 13.974a.771.771 0 0 1-.12-1.085L7.136 9 4.028 5.11a.771.771 0 1 1 1.204-.963l3.497 4.371a.771.771 0 0 1 0 .964l-3.497 4.371a.771.771 0 0 1-1.084.12Zm5.245 0a.771.771 0 0 1-.12-1.085L12.383 9 9.272 5.11a.771.771 0 1 1 1.205-.963l3.497 4.371a.771.771 0 0 1 0 .964l-3.497 4.371a.771.771 0 0 1-1.085.12Z" })
);
};
const convertDateToDay = (date) => {
return date ? {
year: date.getFullYear(),
month: date.getMonth() + 1,
date: date.getDate()
} : null;
};
const convertDayToDate = (day) => {
return day ? new Date(day.year, day.month - 1, day.date) : null;
};
const getPrevMonthDays = (year, month, firstDayOfWeek) => {
let prevMonth = month - 1;
let prevYear = year;
if (prevMonth <= 0) {
prevMonth = 12;
prevYear -= 1;
}
let days = Utils.getMonthPreDay(year, month);
days -= firstDayOfWeek;
if (days >= 7) {
days -= 7;
}
const preDates = Utils.getMonthDays(`${prevYear}`, `${prevMonth}`);
const months = Array.from(Array(preDates), (_, k) => {
return {
type: "prev",
year: prevYear,
month: prevMonth,
date: k + 1
};
});
return months.slice(preDates - days);
};
const getCurrentMonthDays = (year, month) => {
const days = Utils.getMonthDays(`${year}`, `${month}`);
return Array.from(Array(days), (_, k) => {
return {
type: "current",
year,
month,
date: k + 1
};
});
};
const getCurrentWeekDays = (day, firstDayOfWeek) => {
const current = new Date(day.year, day.month - 1, day.date);
const count = (current.getDay() + 7 - firstDayOfWeek) % 7;
return [
convertDateToDay(new Date(current.getTime() - 24 * 60 * 60 * 1e3 * count)),
convertDateToDay(new Date(current.getTime() + 24 * 60 * 60 * 1e3 * (6 - count)))
];
};
const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { type: "single", firstDayOfWeek: 0 });
const prefixCls = "nut-calendarcard";
const CalendarCard = React__default.forwardRef((props, ref) => {
const { locale } = useConfig();
const { style, className, type, value, defaultValue, firstDayOfWeek, startDate, endDate, disableDay, renderDay, renderDayTop, renderDayBottom, onDayClick, onPageChange, onChange } = Object.assign(Object.assign({}, defaultProps), props);
const [month, setMonth] = useState(() => {
let date = new Date(Date.now());
const val = value || defaultValue;
if (Array.isArray(val)) {
if (val.length) {
date = val[0];
}
} else if (val) {
date = val;
}
return {
year: date.getFullYear(),
month: date.getMonth() + 1
};
});
const [days, setDays] = useState([]);
const valueToRange = (val) => {
if (Array.isArray(val)) {
return val.map((date) => {
return convertDateToDay(date);
});
}
return val ? [convertDateToDay(val)] : [];
};
const rangeTovalue = (range) => {
if (Array.isArray(range)) {
return range.map((day) => {
return convertDayToDate(day);
});
}
return range ? [convertDayToDate(range)] : [];
};
const [innerValue, setInnerValue] = usePropsValue({
value: value ? valueToRange(value) : void 0,
defaultValue: defaultValue ? valueToRange(defaultValue) : void 0,
finalValue: []
});
const change = (v) => {
setInnerValue(v);
if (type === "single") {
const date = convertDayToDate(v[0]);
onChange === null || onChange === void 0 ? void 0 : onChange(date);
} else if (type === "multiple" || type === "range" || type === "week") {
const val = rangeTovalue(v);
onChange === null || onChange === void 0 ? void 0 : onChange(val);
}
};
const getDays = (month2) => {
const y = month2.year;
const m = month2.month;
const days2 = [
...getPrevMonthDays(y, m, firstDayOfWeek),
...getCurrentMonthDays(y, m)
];
const size = days2.length;
const yearOfNextMonth = month2.month === 12 ? month2.year + 1 : month2.year;
const monthOfNextMonth = month2.month === 12 ? 1 : month2.month + 1;
for (let i = 1; i <= 42 - size; i++) {
days2.push({
type: "next",
year: yearOfNextMonth,
month: monthOfNextMonth,
date: i
});
}
return days2;
};
useEffect(() => {
const newDays = getDays(month);
setDays(newDays);
onPageChange === null || onPageChange === void 0 ? void 0 : onPageChange(month);
}, [month]);
const isSameDay = (day1, day2) => {
return (day1 === null || day1 === void 0 ? void 0 : day1.year) === (day2 === null || day2 === void 0 ? void 0 : day2.year) && (day1 === null || day1 === void 0 ? void 0 : day1.month) === (day2 === null || day2 === void 0 ? void 0 : day2.month) && (day1 === null || day1 === void 0 ? void 0 : day1.date) === (day2 === null || day2 === void 0 ? void 0 : day2.date);
};
const compareDay = (day1, day2) => {
if (day1 && day2) {
if (day1.year === day2.year) {
if (day1.month === day2.month) {
return day1.date - day2.date;
}
return day1.month - day2.month;
}
return day1.year - day2.year;
}
};
const isDisable = (day) => {
if (disableDay && disableDay(day)) {
return true;
}
if (startDate && Number(compareDay(day, convertDateToDay(startDate))) < 0) {
return true;
}
if (endDate && Number(compareDay(day, convertDateToDay(endDate))) > 0) {
return true;
}
return false;
};
const isActive = (day) => {
if (type === "single" || type === "multiple") {
for (const val of innerValue) {
if (isSameDay(day, val)) {
return true;
}
}
} else if (type === "range" && innerValue.length === 1 && isSameDay(innerValue[0], day)) {
return true;
}
return false;
};
const isStart = (day) => {
return (type === "range" || type === "week") && innerValue.length === 2 && isSameDay(day, innerValue[0]);
};
const isEnd = (day) => {
return (type === "range" || type === "week") && innerValue.length === 2 && isSameDay(day, innerValue[1]);
};
const isMid = (day) => {
if (type === "range" || type === "week") {
if (innerValue.length === 2) {
const c1 = compareDay(innerValue[0], day);
const c2 = compareDay(day, innerValue[1]);
if (c1 && c1 < 0 && c2 && c2 < 0) {
return true;
}
}
}
return false;
};
const isWeekend = (day) => {
const d = new Date(day.year, day.month - 1, day.date).getDay();
return d === 0 || d === 6;
};
const getClasses = (day) => {
if (isDisable(day)) {
return ["disabled"];
}
const res = [];
if (day.type === "current") {
if (isActive(day)) {
res.push("active");
}
if (isStart(day)) {
res.push("start");
}
if (isEnd(day)) {
res.push("end");
}
if (isMid(day)) {
res.push("mid");
}
if (isWeekend(day)) {
res.push("weekend");
}
}
return res;
};
const jumpTo = (year, month2) => {
if (startDate) {
const c = compareDay({
year,
month: month2,
date: 31
}, convertDateToDay(startDate));
if (c && c < 0) {
return;
}
}
if (endDate) {
const c = compareDay({
year,
month: month2,
date: 1
}, convertDateToDay(endDate));
if (c && c > 0) {
return;
}
}
setMonth({ year, month: month2 });
};
const jump = (step = 1) => {
const current = month.year * 12 + month.month;
let newMonth = (current + step) % 12;
if (newMonth === 0) {
newMonth = 12;
}
const newYear = Math.floor((current + step - newMonth) / 12);
jumpTo(newYear, newMonth);
};
React__default.useImperativeHandle(ref, () => {
return {
jump,
jumpTo
};
});
const handleDayClick = (day) => {
onDayClick === null || onDayClick === void 0 ? void 0 : onDayClick(day);
if (day.type === "prev" || day.type === "next" || isDisable(day)) {
return;
}
switch (type) {
case "single": {
if (innerValue[0] && isSameDay(innerValue[0], day)) {
change([]);
} else {
change([day]);
}
break;
}
case "multiple": {
const t = innerValue.find((i) => isSameDay(i, day));
if (t) {
change(innerValue.filter((i) => i !== t));
} else {
change([...innerValue, day]);
}
break;
}
case "range": {
const len = innerValue.length;
if (len === 0 || len === 2) {
change([day]);
} else if (len === 1) {
const t = compareDay(innerValue[0], day);
if (t === null || t === void 0) {
change([]);
} else if (t < 0) {
change([innerValue[0], day]);
} else {
change([day, innerValue[0]]);
}
} else {
console.warn("[NutUI] Calendar range error");
}
break;
}
case "week": {
if (innerValue.length === 2 || innerValue.length === 0) {
const [left, right] = getCurrentWeekDays(day, firstDayOfWeek);
change([left, right]);
} else {
console.warn("[NutUI] Calendar week error");
}
break;
}
default: {
console.warn("[NutUI] Calendar type error");
}
}
};
const monthTitle = locale.calendaritem.monthTitle;
const renderHeader = () => {
return React__default.createElement(
"div",
{ className: `${prefixCls}-header` },
React__default.createElement(
"div",
{ className: `${prefixCls}-header-left` },
React__default.createElement(
"div",
{ className: "double-left", onClick: () => jump(-12) },
React__default.createElement(DoubleLeft, null)
),
React__default.createElement(
"div",
{ className: "left", onClick: () => jump(-1) },
React__default.createElement(ArrowLeft, null)
)
),
React__default.createElement("div", { className: `${prefixCls}-header-title` }, monthTitle(month.year, month.month)),
React__default.createElement(
"div",
{ className: `${prefixCls}-header-right` },
React__default.createElement(
"div",
{ className: "right", onClick: () => jump(1) },
React__default.createElement(ArrowRight, null)
),
React__default.createElement(
"div",
{ className: "double-right", onClick: () => jump(12) },
React__default.createElement(DoubleRight, null)
)
)
);
};
const [weekHeader] = useState(() => {
const weekdays = locale.calendaritem.weekdays.map((day, index) => {
return {
name: day,
key: index
};
});
return [
...weekdays.slice(firstDayOfWeek, 7),
...weekdays.slice(0, firstDayOfWeek)
];
});
const renderContent = () => {
return React__default.createElement(
"div",
{ className: `${prefixCls}-content` },
React__default.createElement("div", { className: `${prefixCls}-days` }, weekHeader.map((day) => {
return React__default.createElement("div", { className: classNames(`${prefixCls}-day`, "header", {
weekend: day.key === 0 || day.key === 6
}), key: day.key }, day.name);
})),
React__default.createElement("div", { className: `${prefixCls}-days` }, days.map((day) => React__default.createElement(
"div",
{ className: classNames(`${prefixCls}-day`, day.type, getClasses(day)), key: `${day.year}-${day.month}-${day.date}`, onClick: () => handleDayClick(day) },
React__default.createElement("div", { className: `${prefixCls}-day-top` }, renderDayTop ? renderDayTop(day) : ""),
React__default.createElement("div", { className: `${prefixCls}-day-inner` }, renderDay ? renderDay(day) : day.date),
React__default.createElement("div", { className: `${prefixCls}-day-bottom` }, renderDayBottom ? renderDayBottom(day) : "")
)))
);
};
return days.length > 0 ? React__default.createElement(
"div",
{ className: classNames(prefixCls, className), style },
renderHeader(),
renderContent()
) : null;
});
CalendarCard.displayName = "NutCalendarCard";
export {
CalendarCard as default
};