UNPKG

tdesign-react

Version:
353 lines (347 loc) 14.9 kB
/** * tdesign v1.15.1 * (c) 2025 tdesign * @license MIT */ import { _ as _defineProperty } from './dep-cb0a3966.js'; import { _ as _slicedToArray } from './dep-48805ab8.js'; import React, { useState, useRef, useMemo, useEffect, useCallback } from 'react'; import classNames from 'classnames'; import dayjs from 'dayjs'; import { c as customParseFormat } from './dep-f9b15bc8.js'; import { range, padStart } from 'lodash-es'; import { a as advancedFormat } from './dep-8ef7b882.js'; import useConfig from '../hooks/useConfig.js'; import noop from '../_util/noop.js'; import { useTimePickerTextConfig } from '../time-picker/hooks/useTimePickerTextConfig.js'; import useDebounce from '../hooks/useDebounce.js'; import { usePropRef } from '../hooks/usePropsRef.js'; var AM = "am"; var PM = "pm"; var MERIDIEM_LIST = [AM, PM]; var TIME_PICKER_EMPTY = [void 0, void 0]; var DEFAULT_STEPS = [1, 1, 1]; var DEFAULT_FORMAT = "HH:mm:ss"; var EPickerCols = /* @__PURE__ */function (EPickerCols2) { EPickerCols2["hour"] = "hour"; EPickerCols2["minute"] = "minute"; EPickerCols2["second"] = "second"; EPickerCols2["milliSecond"] = "millisecond"; EPickerCols2["meridiem"] = "meridiem"; return EPickerCols2; }(EPickerCols || {}); var TIME_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g; var TWELVE_HOUR_FORMAT = /[h]{1}/; dayjs.extend(advancedFormat); dayjs.extend(customParseFormat); function validateInputValue(value, format) { return dayjs(value, format).format(format) === value; } function formatInputValue(value, format) { return dayjs(value, format).format(format); } function closestLookup(availableArr, calcVal, step) { if (step <= 1) return calcVal; return availableArr.sort(function (a, b) { return Math.abs(calcVal + 1 - a) - Math.abs(calcVal + 1 - b); })[0]; } function getPickerCols(format) { var renderCol = []; var meridiem = EPickerCols.meridiem, hour = EPickerCols.hour, minute = EPickerCols.minute, second = EPickerCols.second, milliSecond = EPickerCols.milliSecond; var match = format.match(TIME_FORMAT); match.forEach(function (m) { switch (m) { case "H": case "HH": case "h": case "hh": renderCol.push(hour); break; case "a": case "A": renderCol.push(meridiem); break; case "m": case "mm": renderCol.push(minute); break; case "s": case "ss": renderCol.push(second); break; case "SSS": renderCol.push(milliSecond); break; } }); return renderCol; } var timeArr = [EPickerCols.hour, EPickerCols.minute, EPickerCols.second, EPickerCols.milliSecond]; var panelOffset = { top: 15, bottom: 21 }; dayjs.extend(customParseFormat); var SinglePanel = function SinglePanel(props) { var steps = props.steps, format = props.format, _props$onChange = props.onChange, onChange = _props$onChange === void 0 ? noop : _props$onChange, value = props.value, _props$hideDisabledTi = props.hideDisabledTime, hideDisabledTime = _props$hideDisabledTi === void 0 ? true : _props$hideDisabledTi, disableTime = props.disableTime, _props$position = props.position, position = _props$position === void 0 ? "start" : _props$position, triggerScroll = props.triggerScroll, resetTriggerScroll = props.resetTriggerScroll, isVisible = props.isVisible; var _useConfig = useConfig(), classPrefix = _useConfig.classPrefix; var TEXT_CONFIG = useTimePickerTextConfig(); var panelClassName = "".concat(classPrefix, "-time-picker__panel"); var _useState = useState([]), _useState2 = _slicedToArray(_useState, 2), cols = _useState2[0], setCols = _useState2[1]; var colsRef = useRef([]); var maskRef = useRef(null); var dayjsValue = useMemo(function () { var isStepsSet = !!steps.filter(function (v) { return Number(v) > 1; }).length; if (value) return dayjs(value, format); if (isStepsSet) return dayjs().hour(0).minute(0).second(0); return dayjs(); }, [value, format, steps]); useEffect(function () { colsRef.current = colsRef.current.slice(0, cols.length); }, [cols]); useEffect(function () { var renderCol = getPickerCols(format); setCols(renderCol); }, [format]); var getItemHeight = useCallback(function () { var _maskRef$current; var maskDom = maskRef === null || maskRef === void 0 || (_maskRef$current = maskRef.current) === null || _maskRef$current === void 0 ? void 0 : _maskRef$current.querySelector("div"); if (!maskDom) { return { offsetHeight: 0, margin: 0 }; } return { offsetHeight: maskDom.offsetHeight, margin: parseInt(getComputedStyle(maskDom).marginTop, 10) }; }, []); var timeItemCanUsed = useCallback(function (col, el) { var colIdx = timeArr.indexOf(col); if (colIdx !== -1) { var _ref; var params = [dayjsValue.hour(), dayjsValue.minute(), dayjsValue.second(), dayjsValue.millisecond()]; params[colIdx] = Number(el); return !((_ref = disableTime && (disableTime === null || disableTime === void 0 ? void 0 : disableTime.apply(void 0, params.concat([{ partial: position }])))) !== null && _ref !== void 0 && (_ref = _ref[col]) !== null && _ref !== void 0 && _ref.includes(Number(el))); } return true; }, [position, disableTime, dayjsValue]); var getColList = useCallback(function (col) { var count = 0; if (timeArr.includes(col)) { var colIdx = timeArr.indexOf(col); var colStep = steps[colIdx] || 1; if (col === EPickerCols.hour) count = TWELVE_HOUR_FORMAT.test(format) ? 11 : 23;else if (col === EPickerCols.milliSecond) count = 999;else count = 59; var colList = range(0, count + 1, Number(colStep)).map(function (v) { return padStart(String(v), 2, "0"); }) || []; return hideDisabledTime && !!disableTime ? colList.filter(function (t) { var _disableTime; var params = [dayjsValue.hour(), dayjsValue.minute(), dayjsValue.second(), dayjsValue.millisecond()]; params[colIdx] = Number(t); return !(disableTime !== null && disableTime !== void 0 && (_disableTime = disableTime.apply(void 0, params.concat([{ partial: position }]))) !== null && _disableTime !== void 0 && (_disableTime = _disableTime[col]) !== null && _disableTime !== void 0 && _disableTime.includes(Number(t))); }) : colList; } return MERIDIEM_LIST; }, [steps, format, hideDisabledTime, dayjsValue, disableTime, position]); var getScrollDistance = useCallback(function (col, time) { if (col === EPickerCols.hour && /[h]{1}/.test(format)) time = time % 12; var itemIdx = getColList(col).indexOf(padStart(String(time), 2, "0")); var _getItemHeight = getItemHeight(), offsetHeight = _getItemHeight.offsetHeight, margin = _getItemHeight.margin; var timeItemTotalHeight = offsetHeight + margin; var distance = Math.abs(Math.max(0, itemIdx) * timeItemTotalHeight); return distance; }, [getItemHeight, getColList, format]); var isVisibleRef = usePropRef(isVisible); var handleScroll = useDebounce(function (col, idx, e) { var _colsRef$current$idx; if (!isVisibleRef.current) { return; } var val; var formattedVal; var scrollTop = ((_colsRef$current$idx = colsRef.current[idx]) === null || _colsRef$current$idx === void 0 ? void 0 : _colsRef$current$idx.scrollTop) + panelOffset.top; var _getItemHeight2 = getItemHeight(), offsetHeight = _getItemHeight2.offsetHeight, margin = _getItemHeight2.margin; var timeItemTotalHeight = offsetHeight + margin; var colStep = Math.abs(Math.round(scrollTop / timeItemTotalHeight + 0.5)); var meridiem = MERIDIEM_LIST[Math.min(colStep - 1, 1)].toLowerCase(); if (Number.isNaN(colStep)) colStep = 1; if (timeArr.includes(col)) { var max = 59; if (col === EPickerCols.hour) max = /[h]{1}/.test(format) ? 11 : 23;else if (col === EPickerCols.milliSecond) max = 999; var colIdx = timeArr.indexOf(col); var availableArr = range(0, max + 1, Number(steps[colIdx]) || 1); val = closestLookup(availableArr, Number(getColList(col)[Math.min(colStep - 1, max + 1, availableArr.length - 1)]), Number(steps[colIdx]) || 1); if (Number.isNaN(val)) val = availableArr[availableArr.length - 1]; if (col === EPickerCols.hour && cols.includes(EPickerCols.meridiem) && dayjsValue.hour() >= 12) { val = Number(val) + 12; } } else val = meridiem; var distance = getScrollDistance(col, val); if (!dayjs(dayjsValue).isValid() || value && !dayjs(value, format, true).isValid()) { return; } if (timeArr.includes(col)) { var _dayjsValue$col; if (timeItemCanUsed(col, val)) formattedVal = (_dayjsValue$col = dayjsValue[col]) === null || _dayjsValue$col === void 0 ? void 0 : _dayjsValue$col.call(dayjsValue, val).format(format);else formattedVal = dayjsValue.format(format); } else { var currentHour = dayjsValue.hour(); if (meridiem === AM && currentHour >= 12) { formattedVal = dayjsValue.hour(currentHour - 12).format(format); } else if (meridiem === PM && currentHour < 12) { formattedVal = dayjsValue.hour(currentHour + 12).format(format); } else { formattedVal = dayjsValue.format(format); } } if (formattedVal !== value) { onChange(formattedVal, e); } if (distance !== scrollTop) { var _scrollCtrl$scrollTo; var scrollCtrl = colsRef.current[cols.indexOf(col)]; if (!scrollCtrl || scrollCtrl.scrollTop === distance) return; (_scrollCtrl$scrollTo = scrollCtrl.scrollTo) === null || _scrollCtrl$scrollTo === void 0 || _scrollCtrl$scrollTo.call(scrollCtrl, { top: distance, behavior: "smooth" }); } }, 50); var scrollToTime = useCallback(function (col, time, idx) { var _scrollCtrl$scrollTo2; var behavior = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "auto"; var distance = getScrollDistance(col, time); var scrollCtrl = colsRef.current[idx]; if (!scrollCtrl || scrollCtrl.scrollTop === distance || !timeItemCanUsed(col, time)) return; (_scrollCtrl$scrollTo2 = scrollCtrl.scrollTo) === null || _scrollCtrl$scrollTo2 === void 0 || _scrollCtrl$scrollTo2.call(scrollCtrl, { top: distance, behavior: behavior }); }, [getScrollDistance]); var updateTimeScrollPos = useCallback(function () { var isAutoScroll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var behavior = value && !isAutoScroll ? "smooth" : "auto"; var isStepsSet = !!steps.filter(function (v) { return Number(v) > 1; }).length; cols.forEach(function (col, idx) { if (!isStepsSet || isStepsSet && value) { var _dayjsValue$col2; scrollToTime(col, timeArr.includes(col) ? (_dayjsValue$col2 = dayjsValue[col]) === null || _dayjsValue$col2 === void 0 ? void 0 : _dayjsValue$col2.call(dayjsValue) : dayjsValue.format("a"), idx, behavior); } else { var _getColList; scrollToTime(col, (_getColList = getColList(col)) === null || _getColList === void 0 ? void 0 : _getColList[0], idx, behavior); } }); resetTriggerScroll(); }, [cols, scrollToTime, dayjsValue, value, steps, getColList, resetTriggerScroll]); var handleTimeItemClick = function handleTimeItemClick(col, el, idx, e) { if (!timeItemCanUsed(col, el)) return; if (timeArr.includes(col)) { if (col === EPickerCols.hour && dayjsValue.format("a") === PM && cols.includes(EPickerCols.meridiem)) { el = Number(el) + 12; } scrollToTime(col, el, idx, "smooth"); setTimeout(function () { var _dayjsValue$col3; onChange((_dayjsValue$col3 = dayjsValue[col]) === null || _dayjsValue$col3 === void 0 ? void 0 : _dayjsValue$col3.call(dayjsValue, el).format(format), e); }, 100); } else { var currentHour = dayjsValue.hour(); if (el === AM && currentHour >= 12) { onChange(dayjsValue.hour(currentHour - 12).format(format), e); } else if (el === PM && currentHour < 12) { onChange(dayjsValue.hour(currentHour + 12).format(format), e); } } }; useEffect(function () { if (value) updateTimeScrollPos(true); }, [value, updateTimeScrollPos]); useEffect(function () { if (triggerScroll) updateTimeScrollPos(true); }, [triggerScroll, updateTimeScrollPos]); var isCurrent = useCallback(function (col, colItem) { var _dayjsValue$col4; var colVal; if (col === EPickerCols.meridiem) { var currentMeridiem = dayjsValue.format("a"); return currentMeridiem === colItem; } colVal = (_dayjsValue$col4 = dayjsValue[col]) === null || _dayjsValue$col4 === void 0 ? void 0 : _dayjsValue$col4.call(dayjsValue); if (col === EPickerCols.hour && /[h]{1}/.test(format)) { colVal %= 12; } return colVal === Number(colItem); }, [format, dayjsValue]); function renderScrollCtrl() { return cols.map(function (col, idx) { return /* @__PURE__ */React.createElement("ul", { key: "".concat(col, "_").concat(idx), ref: function ref(el) { colsRef.current[idx] = el; }, className: "".concat(panelClassName, "-body-scroll"), onScroll: function onScroll(e) { return handleScroll(col, idx, e); }, style: { "--timePickerPanelOffsetTop": panelOffset.top, "--timePickerPanelOffsetBottom": panelOffset.bottom } }, getColList(col).map(function (el) { return /* @__PURE__ */React.createElement("li", { key: el, className: classNames("".concat(panelClassName, "-body-scroll-item"), _defineProperty(_defineProperty({}, "".concat(classPrefix, "-is-disabled"), !timeItemCanUsed(col, el)), "".concat(classPrefix, "-is-current"), isCurrent(col, el))), onClick: function onClick(e) { return handleTimeItemClick(col, el, idx, e); } }, timeArr.includes(col) ? TWELVE_HOUR_FORMAT.test(format) && col === EPickerCols.hour && el === "00" ? "12" : el : TEXT_CONFIG[el]); })); }); } return /* @__PURE__ */React.createElement("div", { className: "".concat(panelClassName, "-body") }, /* @__PURE__ */React.createElement("div", { className: "".concat(panelClassName, "-body-active-mask"), ref: maskRef }, cols.map(function (col, idx) { return /* @__PURE__ */React.createElement("div", { key: "".concat(col, "_").concat(idx) }); })), renderScrollCtrl()); }; export { DEFAULT_FORMAT as D, SinglePanel as S, TIME_PICKER_EMPTY as T, DEFAULT_STEPS as a, formatInputValue as f, validateInputValue as v }; //# sourceMappingURL=dep-2990bb49.js.map