@mijadesign/mjui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
290 lines (289 loc) • 12 kB
JavaScript
import { _ as __rest } from "./tslib.es6-iWu3F_1J.js";
import classNames from "classnames";
import React, { useState, useImperativeHandle, useEffect } from "react";
import { View } from "@tarojs/components";
import isEqual from "lodash.isequal";
import { useConfig } from "@nutui/nutui-react-taro";
import { P as Picker } from "./picker.taro-BG6OX7HW.js";
import { C as ComponentDefaults } from "./typings-DV9RBfhj.js";
import { u as usePropsValue } from "./use-props-value-DuhZMy4U.js";
const isDate = (val) => {
return Object.prototype.toString.call(val) === "[object Date]" && !Number.isNaN(val.getTime());
};
const padZero = (num, targetLength = 2) => {
let str = `${num}`;
while (str.length < targetLength) {
str = `0${str}`;
}
return str;
};
function getLastDayOfMonth(year, month) {
return new Date(year, month, 0).getDate();
}
const calculateDateBoundary = (type, value, startDate, endDate) => {
const boundary = type === "min" ? startDate : endDate;
const year = boundary.getFullYear();
const isMax = type === "max";
let month = isMax ? 12 : 1;
let date = isMax ? getLastDayOfMonth(value.getFullYear(), value.getMonth() + 1) : 1;
let hour = isMax ? 23 : 0;
let minute = isMax ? 59 : 0;
if (value.getFullYear() === year) {
month = boundary.getMonth() + 1;
if (value.getMonth() + 1 === month) {
date = boundary.getDate();
if (value.getDate() === date) {
hour = boundary.getHours();
if (value.getHours() === hour) {
minute = boundary.getMinutes();
}
}
}
}
return {
[`${type}Year`]: year,
[`${type}Month`]: month,
[`${type}Date`]: date,
[`${type}Hour`]: hour,
[`${type}Minute`]: minute,
[`${type}Seconds`]: minute
// 返回秒数(与分钟相同)
};
};
const generateDatePickerRanges = (type, selectedDate, startDate, endDate) => {
const selected = selectedDate ? new Date(selectedDate) : new Date(startDate);
if (!selected)
return [];
const { maxYear, maxDate, maxMonth, maxHour, maxMinute, maxSeconds } = calculateDateBoundary("max", selected, startDate, endDate);
const { minYear, minDate, minMonth, minHour, minMinute, minSeconds } = calculateDateBoundary("min", selected, startDate, endDate);
const fullRanges = [
{ type: "year", range: [minYear, maxYear] },
{ type: "month", range: [minMonth, maxMonth] },
{ type: "day", range: [minDate, maxDate] },
{ type: "hour", range: [minHour, maxHour] },
{ type: "minute", range: [minMinute, maxMinute] },
{ type: "seconds", range: [minSeconds, maxSeconds] }
];
switch (type.toLocaleLowerCase()) {
case "date":
return fullRanges.slice(0, 3);
case "datetime":
return fullRanges.slice(0, 5);
case "time":
return fullRanges.slice(3, 6);
case "year-month":
return fullRanges.slice(0, 2);
case "hour-minutes":
return fullRanges.slice(3, 5);
case "month-day":
return fullRanges.slice(1, 3);
case "datehour":
return fullRanges.slice(0, 4);
default:
return fullRanges;
}
};
const getDatePartValue = (type, selectedDate) => {
const date = new Date(selectedDate);
if (!selectedDate)
return 0;
switch (type) {
case "year":
return date.getFullYear();
case "month":
return date.getMonth() + 1;
case "day":
return date.getDate();
case "hour":
return date.getHours();
case "minute":
return date.getMinutes();
case "seconds":
return date.getSeconds();
default:
return 0;
}
};
const generatePickerColumnWithCallback = (min, max, currentValue, type, minuteStep, callback, showChinese, zhCNType, formatter) => {
let currentMin = min;
const options = [];
let selectedIndex = 0;
while (currentMin <= max) {
options.push(formatPickerOption(type, currentMin, showChinese, zhCNType, formatter));
if (type === "minute") {
currentMin += minuteStep;
} else {
currentMin++;
}
if (currentMin <= Number(currentValue)) {
selectedIndex++;
}
}
callback(selectedIndex, options);
return options;
};
const formatPickerOption = (type, value, showChinese, zhCNType, formatter) => {
if (formatter) {
return formatter(type, {
label: padZero(value, 2),
value: padZero(value, 2)
});
}
const paddedValue = padZero(value, 2);
const chineseText = showChinese ? zhCNType[type] : "";
return {
label: paddedValue + chineseText,
value: paddedValue
};
};
const formatValue = (value, startDate, endDate) => {
if (!value || value && !isDate(value)) {
value = startDate;
}
return Math.min(Math.max(value.getTime(), startDate.getTime()), endDate.getTime());
};
const handlePickerValueChange = (selectedOptions, selectedValue, index, type, defaultDate, handleDateComparison) => {
const rangeType = type.toLocaleLowerCase();
if (["date", "datetime", "datehour", "month-day", "year-month"].includes(rangeType)) {
const formattedDate = [];
selectedValue.forEach((item) => {
formattedDate.push(item);
});
if (rangeType === "month-day" && formattedDate.length < 3) {
formattedDate.unshift(new Date(defaultDate).getFullYear());
}
if (rangeType === "year-month" && formattedDate.length < 3) {
formattedDate.push(new Date(defaultDate).getDate());
}
const year = Number(formattedDate[0]);
const month = Number(formattedDate[1]) - 1;
const day = Math.min(Number(formattedDate[2]), getLastDayOfMonth(year, month + 1));
let date = null;
if (rangeType === "date" || rangeType === "month-day" || rangeType === "year-month") {
date = new Date(year, month, day);
} else if (rangeType === "datetime") {
date = new Date(year, month, day, Number(formattedDate[3]), Number(formattedDate[4]));
} else if (rangeType === "datehour") {
date = new Date(year, month, day, Number(formattedDate[3]));
}
handleDateComparison(date, selectedOptions, index);
} else {
const [hour, minute, seconds] = selectedValue;
const currentDate = new Date(defaultDate);
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
const day = currentDate.getDate();
const date = new Date(year, month, day, Number(hour), Number(minute), rangeType === "time" ? Number(seconds) : 0);
handleDateComparison(date, selectedOptions, index);
}
};
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { visible: false, title: "", type: "date", showChinese: false, threeDimensional: true, minuteStep: 1, startDate: new Date(currentYear - 10, 0, 1), endDate: new Date(currentYear + 10, 11, 31) });
const InternalPicker = (props, ref) => {
const _a = Object.assign(Object.assign({}, defaultProps), props), { startDate, endDate, type, showChinese, minuteStep, visible, title, defaultValue, pickerProps = {}, formatter, onClose, onCancel, onConfirm, filter, onChange, threeDimensional, className, style, children } = _a, rest = __rest(_a, ["startDate", "endDate", "type", "showChinese", "minuteStep", "visible", "title", "defaultValue", "pickerProps", "formatter", "onClose", "onCancel", "onConfirm", "filter", "onChange", "threeDimensional", "className", "style", "children"]);
const { locale } = useConfig();
const lang = locale.datepicker;
const zhCNType = {
day: lang.day,
year: lang.year,
month: lang.month,
hour: lang.hour,
minute: lang.min,
seconds: lang.seconds
};
const classPrefix = "nut-datepicker";
const cls = classNames(classPrefix, className);
const [pickerValue, setPickerValue] = useState([]);
const [pickerOptions, setPickerOptions] = useState([]);
const [selectedDate, setSelectedDate] = usePropsValue({
value: props.value && formatValue(props.value, startDate, endDate),
defaultValue: props.defaultValue && formatValue(props.defaultValue, startDate, endDate),
finalValue: 0
});
const [innerDate, setInnerDate] = useState(selectedDate);
const [innerVisible, setInnerVisible] = usePropsValue({
value: props.visible,
defaultValue: false,
finalValue: false
});
const actions = {
open: () => {
setInnerVisible(true);
},
close: () => {
setInnerVisible(false);
}
};
useImperativeHandle(ref, () => actions);
const handleDateComparison = (newDate, selectedOptions, index) => {
var _a2;
if (newDate && isDate(newDate)) {
if (!isEqual((_a2 = new Date(selectedDate)) === null || _a2 === void 0 ? void 0 : _a2.getTime(), newDate === null || newDate === void 0 ? void 0 : newDate.getTime())) {
setInnerDate(formatValue(newDate, startDate, endDate));
}
onChange === null || onChange === void 0 ? void 0 : onChange(selectedOptions, [String(newDate.getFullYear()), String(newDate.getMonth() + 1), String(newDate.getDate())], index);
}
};
const handleConfirmDateComparison = (newDate) => {
var _a2;
if (newDate && isDate(newDate)) {
if (!isEqual((_a2 = new Date(selectedDate)) === null || _a2 === void 0 ? void 0 : _a2.getTime(), newDate === null || newDate === void 0 ? void 0 : newDate.getTime())) {
setSelectedDate(formatValue(newDate, startDate, endDate));
}
}
};
const handleCancel = () => {
setInnerDate(selectedDate);
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
};
const handleClose = () => {
setInnerVisible(false);
onClose === null || onClose === void 0 ? void 0 : onClose();
};
const handleConfirm = (options, value) => {
handlePickerValueChange(options, value, 0, type, defaultValue || startDate || endDate, handleConfirmDateComparison);
onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(options, value);
};
const handleChange = (selectedOptions, selectedValue, index) => {
innerVisible && handlePickerValueChange(selectedOptions, selectedValue, index, type, defaultValue || startDate || endDate, handleDateComparison);
};
const generatePickerColumns = () => {
const dateRanges = generateDatePickerRanges(type, innerDate, startDate, endDate);
const columns = dateRanges.map((rangeConfig, columnIndex) => {
const { type: columnType, range } = rangeConfig;
const selectedValue = getDatePartValue(columnType, innerDate);
const pickerColumn = generatePickerColumnWithCallback(range[0], range[1], selectedValue, columnType, minuteStep, (selectedIndex, options) => {
var _a2;
pickerValue[columnIndex] = (_a2 = options[selectedIndex]) === null || _a2 === void 0 ? void 0 : _a2.value;
setPickerValue([...pickerValue]);
}, showChinese, zhCNType, formatter);
if (filter === null || filter === void 0 ? void 0 : filter(columnType, pickerColumn)) {
return filter(columnType, pickerColumn);
}
return pickerColumn;
});
return columns || [];
};
useEffect(() => {
setInnerDate(selectedDate);
}, [selectedDate]);
useEffect(() => {
setPickerOptions(generatePickerColumns());
}, [innerDate, startDate, endDate]);
return React.createElement(
React.Fragment,
null,
typeof children === "function" && children(selectedDate),
React.createElement(View, Object.assign({ className: cls, style }, rest), !!pickerOptions.length && React.createElement(Picker, Object.assign({}, pickerProps, { title, visible: innerVisible, value: pickerValue, options: pickerOptions, onClose: handleClose, onCancel: handleCancel, onConfirm: handleConfirm, onChange: ({ value, index, selectedOptions }) => {
handleChange(selectedOptions, value, index);
}, threeDimensional })))
);
};
const DatePicker$1 = React.forwardRef(InternalPicker);
const DatePicker = (props) => {
const { className, threeDimensional = false } = props, rest = __rest(props, ["className", "threeDimensional"]);
return React.createElement(DatePicker$1, Object.assign({ className: classNames("mj-datepicker", className), threeDimensional }, rest));
};
export {
DatePicker as D
};