@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
408 lines (407 loc) • 14.9 kB
JavaScript
import React__default, { useState, useEffect } from "react";
import classNames from "classnames";
import { View } from "@tarojs/components";
import { C as ComponentDefaults } from "./typings-DV9RBfhj.js";
import { c as getMonthPreDay, b as getMonthDays } from "./date-C7eJqrqk.js";
import { u as useConfig } from "./configprovider.taro-DpK4IiCE.js";
import { u as usePropsValue } from "./use-props-value-SH9krhkx.js";
const left = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDE4IDE4Ij48cGF0aCBkPSJNNi42MDUgOS40OWEuNzcxLjc3MSAwIDAgMSAwLS45OGwzLjYtNC4zNzJhLjc3MS43NzEgMCAwIDEgMS4xOS45ODFMOC4yIDlsMy4xOTcgMy44ODFhLjc3MS43NzEgMCAxIDEtMS4xOTEuOThsLTMuNi00LjM3eiIvPjwvc3ZnPg==";
const right = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDE4IDE4Ij48cGF0aCBkPSJNMTEuMzk2IDkuNDlhLjc3MS43NzEgMCAwIDAgMC0uOThsLTMuNi00LjM3MmEuNzcxLjc3MSAwIDAgMC0xLjE5MS45ODFMOS44IDlsLTMuMTk2IDMuODgxYS43NzEuNzcxIDAgMCAwIDEuMTkuOThsMy42LTQuMzd6Ii8+PC9zdmc+";
const doubleLeft = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDE4IDE4Ij48cGF0aCBkPSJNMTMuODUzIDQuMDI2YS43NzEuNzcxIDAgMCAxIC4xMiAxLjA4NUwxMC44NjQgOWwzLjExIDMuODg5YS43NzEuNzcxIDAgMSAxLTEuMjA0Ljk2M2wtMy40OTgtNC4zN2EuNzcxLjc3MSAwIDAgMSAwLS45NjRsMy40OTctNC4zNzFhLjc3MS43NzEgMCAwIDEgMS4wODQtLjEyem0tNS4yNDUgMGEuNzcxLjc3MSAwIDAgMSAuMTIgMS4wODVMNS42MTcgOWwzLjExMSAzLjg4OWEuNzcxLjc3MSAwIDAgMS0xLjIwNS45NjNsLTMuNDk3LTQuMzdhLjc3MS43NzEgMCAwIDEgMC0uOTY0bDMuNDk3LTQuMzcxYS43NzEuNzcxIDAgMCAxIDEuMDg1LS4xMnoiLz48L3N2Zz4=";
const doubleRight = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDE4IDE4Ij48cGF0aCBkPSJNNC4xNDcgMTMuOTc0YS43NzEuNzcxIDAgMCAxLS4xMi0xLjA4NUw3LjEzNiA5IDQuMDI4IDUuMTFhLjc3MS43NzEgMCAxIDEgMS4yMDQtLjk2M2wzLjQ5NyA0LjM3MWEuNzcxLjc3MSAwIDAgMSAwIC45NjRsLTMuNDk3IDQuMzcxYS43NzEuNzcxIDAgMCAxLTEuMDg0LjEyem01LjI0NSAwYS43NzEuNzcxIDAgMCAxLS4xMi0xLjA4NUwxMi4zODMgOSA5LjI3MiA1LjExYS43NzEuNzcxIDAgMSAxIDEuMjA1LS45NjNsMy40OTcgNC4zNzFhLjc3MS43NzEgMCAwIDEgMCAuOTY0bC0zLjQ5NyA0LjM3MWEuNzcxLjc3MSAwIDAgMS0xLjA4NS4xMnoiLz48L3N2Zz4=";
const Icon = ({ url }) => {
const style = {
background: `url('${url}') no-repeat center`,
backgroundSize: "100% 100%",
width: "18px",
height: "18px"
};
return React__default.createElement(View, { style });
};
const ArrowLeft = () => React__default.createElement(Icon, { url: left });
const ArrowRight = () => React__default.createElement(Icon, { url: right });
const DoubleLeft = () => React__default.createElement(Icon, { url: doubleLeft });
const DoubleRight = () => React__default.createElement(Icon, { url: doubleRight });
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 = getMonthPreDay(year, month);
days -= firstDayOfWeek;
if (days >= 7) {
days -= 7;
}
const preDates = 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 = 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 in innerValue) {
if (isSameDay(day, innerValue[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 [left2, right2] = getCurrentWeekDays(day, firstDayOfWeek);
change([left2, right2]);
} 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 C
};