UNPKG

@mijadesign/mjui-react-taro

Version:

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

290 lines (289 loc) 12 kB
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 };