tdesign-react
Version:
TDesign Component for React
353 lines (347 loc) • 14.9 kB
JavaScript
/**
* 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