UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

249 lines (248 loc) 9.29 kB
import { _ as __rest } from "./tslib.es6.js"; import React__default, { useState, useEffect } from "react"; import Picker__default from "./Picker.js"; import { useConfig } from "./ConfigProvider.js"; import { u as usePropsValue } from "./use-props-value.js"; import { C as ComponentDefaults } from "./typings.js"; import { p as padZero } from "./pad-zero.js"; const isDate = (val) => { return Object.prototype.toString.call(val) === "[object Date]" && !Number.isNaN(val.getTime()); }; 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 DatePicker = (props) => { 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 } = _a, rest = __rest(_a, ["startDate", "endDate", "type", "showChinese", "minuteStep", "visible", "title", "defaultValue", "pickerProps", "formatter", "onClose", "onCancel", "onConfirm", "filter", "onChange", "threeDimensional", "className", "style"]); 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 [pickerValue, setPickerValue] = useState([]); const [pickerOptions, setPickerOptions] = useState([]); const formatValue = (value) => { if (!value || value && !isDate(value)) { value = startDate; } return Math.min(Math.max(value.getTime(), startDate.getTime()), endDate.getTime()); }; const [selectedDate, setSelectedDate] = usePropsValue({ value: props.value && formatValue(props.value), defaultValue: props.defaultValue && formatValue(props.defaultValue), finalValue: 0 }); function getMonthEndDay(year, month) { return new Date(year, month, 0).getDate(); } const getBoundary = (type2, value) => { const boundary = type2 === "min" ? startDate : endDate; const year = boundary.getFullYear(); let month = 1; let date = 1; let hour = 0; let minute = 0; if (type2 === "max") { month = 12; date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); hour = 23; minute = 59; } const seconds = minute; 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 { [`${type2}Year`]: year, [`${type2}Month`]: month, [`${type2}Date`]: date, [`${type2}Hour`]: hour, [`${type2}Minute`]: minute, [`${type2}Seconds`]: seconds }; }; const ranges = () => { const selected = new Date(selectedDate); if (!selected) return []; const { maxYear, maxDate, maxMonth, maxHour, maxMinute, maxSeconds } = getBoundary("max", selected); const { minYear, minDate, minMonth, minHour, minMinute, minSeconds } = getBoundary("min", selected); const result = [ { 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 result.slice(0, 3); case "datetime": return result.slice(0, 5); case "time": return result.slice(3, 6); case "year-month": return result.slice(0, 2); case "hour-minutes": return result.slice(3, 5); case "month-day": return result.slice(1, 3); case "datehour": return result.slice(0, 4); default: return result; } }; const compareDateChange = (currentDate, newDate, selectedOptions, index) => { var _a2; const isEqual = ((_a2 = new Date(currentDate)) === null || _a2 === void 0 ? void 0 : _a2.getTime()) === (newDate === null || newDate === void 0 ? void 0 : newDate.getTime()); if (newDate && isDate(newDate)) { if (!isEqual) { setSelectedDate(formatValue(newDate)); } onChange === null || onChange === void 0 ? void 0 : onChange(selectedOptions, [ String(newDate.getFullYear()), String(newDate.getMonth() + 1), String(newDate.getDate()) ], index); } }; const handlePickerChange = (selectedOptions, selectedValue, index) => { const rangeType = type.toLocaleLowerCase(); if (["date", "datetime", "datehour", "month-day", "year-month"].includes(rangeType)) { const formatDate = []; selectedValue.forEach((item) => { formatDate.push(item); }); if (rangeType === "month-day" && formatDate.length < 3) { formatDate.unshift(new Date(defaultValue || startDate || endDate).getFullYear()); } if (rangeType === "year-month" && formatDate.length < 3) { formatDate.push(new Date(defaultValue || startDate || endDate).getDate()); } const year = Number(formatDate[0]); const month = Number(formatDate[1]) - 1; const day = Math.min(Number(formatDate[2]), getMonthEndDay(Number(formatDate[0]), Number(formatDate[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(formatDate[3]), Number(formatDate[4])); } else if (rangeType === "datehour") { date = new Date(year, month, day, Number(formatDate[3])); } compareDateChange(selectedDate, date, selectedOptions, index); } else { const [hour, minute, seconds] = selectedValue; const currentDate = new Date(selectedDate); 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); compareDateChange(selectedDate, date, selectedOptions, index); } }; const formatOption = (type2, value) => { if (formatter) { return formatter(type2, { text: padZero(value, 2), value: padZero(value, 2) }); } const padMin = padZero(value, 2); const fatter = showChinese ? zhCNType[type2] : ""; return { text: padMin + fatter, value: padMin }; }; const generateColumn = (min, max, val, type2, columnIndex) => { var _a2; let cmin = min; const arr = []; let index = 0; while (cmin <= max) { arr.push(formatOption(type2, cmin)); if (type2 === "minute") { cmin += minuteStep; } else { cmin++; } if (cmin <= Number(val)) { index++; } } pickerValue[columnIndex] = (_a2 = arr[index]) === null || _a2 === void 0 ? void 0 : _a2.value; setPickerValue([...pickerValue]); if (filter === null || filter === void 0 ? void 0 : filter(type2, arr)) { return filter === null || filter === void 0 ? void 0 : filter(type2, arr); } return arr; }; const getDateIndex = (type2) => { const date = new Date(selectedDate); if (!selectedDate) return 0; if (type2 === "year") { return date.getFullYear(); } if (type2 === "month") { return date.getMonth() + 1; } if (type2 === "day") { return date.getDate(); } if (type2 === "hour") { return date.getHours(); } if (type2 === "minute") { return date.getMinutes(); } if (type2 === "seconds") { return date.getSeconds(); } return 0; }; const columns = () => { const val = ranges().map((res, columnIndex) => { return generateColumn(res.range[0], res.range[1], getDateIndex(res.type), res.type, columnIndex); }); return val || []; }; useEffect(() => { setPickerOptions(columns()); }, [selectedDate, startDate, endDate]); return React__default.createElement("div", Object.assign({ className: `nut-datepicker ${className}`, style }, rest), pickerOptions.length > 0 && React__default.createElement(Picker__default, Object.assign({}, pickerProps, { title, visible, options: pickerOptions, onClose, onCancel, value: pickerValue, onConfirm: (options, value) => onConfirm && onConfirm(options, value), onChange: (options, value, index) => handlePickerChange(options, value, index), threeDimensional }))); }; DatePicker.displayName = "NutDatePicker"; export { DatePicker as default };