UNPKG

@alifd/next

Version:

A configurable component library for web built on React.

408 lines (407 loc) 23.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = tslib_1.__importStar(require("react")); var prop_types_1 = tslib_1.__importDefault(require("prop-types")); var react_lifecycles_compat_1 = require("react-lifecycles-compat"); var classnames_1 = tslib_1.__importDefault(require("classnames")); var config_provider_1 = tslib_1.__importDefault(require("../config-provider")); var input_1 = tslib_1.__importDefault(require("../input")); var button_1 = tslib_1.__importDefault(require("../button")); var overlay_1 = tslib_1.__importDefault(require("../overlay")); var zh_cn_1 = tslib_1.__importDefault(require("../locale/zh-cn")); var util_1 = require("../util"); var panel_1 = tslib_1.__importDefault(require("./panel")); var utils_1 = require("./utils"); var prop_types_2 = tslib_1.__importDefault(require("./prop-types")); var util_2 = require("../date-picker2/util"); var footer_panel_1 = tslib_1.__importDefault(require("../date-picker2/panels/footer-panel")); var date_input_1 = tslib_1.__importDefault(require("./module/date-input")); var constant_1 = require("./constant"); var Popup = overlay_1.default.Popup; var noop = util_1.func.noop, checkDate = util_1.func.checkDate, checkRangeDate = util_1.func.checkRangeDate; var timePickerLocale = zh_cn_1.default.TimePicker; var presetPropType = prop_types_1.default.shape(tslib_1.__assign({ label: prop_types_1.default.string, value: prop_types_1.default.oneOfType([prop_types_1.default.func, utils_1.checkDateValue]) }, button_1.default.propTypes)); var TimePicker2 = /** @class */ (function (_super) { tslib_1.__extends(TimePicker2, _super); function TimePicker2(props) { var _this = _super.call(this, props) || this; /** * 获取初始值 */ _this.getInitValue = function () { var props = _this.props; var type = props.type, value = props.value, defaultValue = props.defaultValue; var val = type === constant_1.TIME_PICKER_TYPE.RANGE ? [null, null] : null; val = 'value' in props ? value : 'defaultValue' in props ? defaultValue : val; return _this.checkValue(val); }; /** * 获取 RangePicker 输入框初始输入状态 * @returns inputState - Object * @returns inputState.justBeginInput 是否初始输入 - boolean * @returns inputState.inputType 当前输入框 - number */ _this.getInitRangeInputState = function () { return { justBeginInput: _this.isEnabled(), inputType: (_this.isEnabled(0) ? constant_1.TIME_INPUT_TYPE.BEGIN : constant_1.TIME_INPUT_TYPE.END), }; }; _this.onKeyDown = function (e) { if (e.keyCode === util_1.KEYCODE.ENTER) { var inputValue = _this.state.inputValue; _this.handleChange(inputValue, 'KEYDOWN_ENTER'); _this.onClick(); return; } var _a = _this.state, value = _a.value, inputStr = _a.inputStr, inputType = _a.inputType, isRange = _a.isRange; var _b = _this.props, format = _b.format, _c = _b.hourStep, hourStep = _c === void 0 ? 1 : _c, _d = _b.minuteStep, minuteStep = _d === void 0 ? 1 : _d, _e = _b.secondStep, secondStep = _e === void 0 ? 1 : _e, disabledMinutes = _b.disabledMinutes, disabledSeconds = _b.disabledSeconds; var unit = 'second'; if (disabledSeconds) { unit = disabledMinutes ? 'hour' : 'minute'; } var timeStr = (0, utils_1.onTimeKeydown)(e, { format: format, timeInputStr: isRange ? inputStr[inputType] : inputStr, steps: { hour: hourStep, minute: minuteStep, second: secondStep, }, // @ts-expect-error 此处的 value 没有考虑到数组的情况 value: value, }, unit); if (!timeStr) return; var newInputStr = timeStr; if (isRange) { newInputStr = inputStr; newInputStr[inputType] = timeStr; } _this.handleChange(newInputStr, 'KEYDOWN_CODE'); }; _this.onVisibleChange = function (visible, type) { if (!('visible' in _this.props)) { _this.setState({ visible: visible, }); } _this.props.onVisibleChange(visible, type); }; _this.onClick = function () { var _a = _this.state, visible = _a.visible, inputType = _a.inputType; if (!visible) { _this.onVisibleChange(true); _this.handleInputFocus(inputType); } }; /** * 处理点击文档区域导致的弹层收起逻辑 * @param visible - 是否可见 * @param type - 事件类型 */ _this.handleVisibleChange = function (visible, targetType) { if (targetType === 'docClick') { // 弹层收起 触发 Change 逻辑 if (!visible) { _this.handleChange(_this.state.curValue, 'VISIBLE_CHANGE'); } _this.onVisibleChange(visible); } }; _this.handleInputFocus = function (inputType) { var inputEl = _this.dateInput && _this.dateInput.input; if (_this.state.isRange) { inputEl = inputEl && inputEl[inputType]; } inputEl && inputEl.focus(); }; _this.onOk = function () { var curValue = _this.state.curValue; var checkedValue = _this.checkValue(curValue); util_1.func.invoke(_this.props, 'onOk', _this.getOutputArgs(checkedValue)); _this.setState({ value: checkedValue }); _this.handleChange(checkedValue, 'CLICK_OK'); }; _this.onInputTypeChange = function (idx) { var _a = _this.state, inputType = _a.inputType, visible = _a.visible; if (idx !== inputType) { _this.setState({ inputType: idx, justBeginInput: !(idx !== null && visible), }); } }; _this.checkValue = function (value, strictly) { var inputType = _this.state.inputType; var _a = _this.props, format = _a.format, type = _a.type, disabled = _a.disabled; var formatter = function (v) { return typeof v === 'string' ? (0, util_1.datejs)(v, format) : v; }; var formattedValue = Array.isArray(value) ? value.map(function (v) { return formatter(v); }) : formatter(value); return type === constant_1.TIME_PICKER_TYPE.RANGE ? checkRangeDate(formattedValue, inputType, disabled, strictly) : checkDate(formattedValue); }; /** * 获取 `onChange` 和 `onOk` 方法的输出参数 * @param value - Dayjs * @returns 默认返回 `Dayjs` 实例和 `format` 格式化的值 * 如果传了了 `outputFormat` 属性则返回 `outputFormat` 格式化的值 */ _this.getOutputArgs = function (value) { var format = _this.props.format; return [value, (0, util_2.fmtValue)(value, format)]; }; _this.onChange = function (v) { var _a = _this, state = _a.state, props = _a.props; var format = props.format; var nextValue = v === undefined ? state.value : v; var value = _this.checkValue(nextValue); _this.setState({ curValue: value, preValue: value, inputStr: (0, util_2.fmtValue)(value, format), inputValue: (0, util_2.fmtValue)(value, format), }); util_1.func.invoke(_this.props, 'onChange', _this.getOutputArgs(nextValue)); }; _this.shouldSwitchInput = function (value) { var _a = _this.state, inputType = _a.inputType, justBeginInput = _a.justBeginInput; var idx = justBeginInput ? (0, util_2.switchInputType)(inputType) : value.indexOf(null); if (idx !== -1 && _this.isEnabled(idx)) { _this.onInputTypeChange(idx); _this.handleInputFocus(idx); return true; } return false; }; _this.handleChange = function (v, eventType) { var format = _this.props.format; var _a = _this.state, isRange = _a.isRange, value = _a.value, preValue = _a.preValue; var forceEvents = [ 'KEYDOWN_ENTER', 'CLICK_PRESET', 'CLICK_OK', 'INPUT_CLEAR', 'VISIBLE_CHANGE', ]; var isTemporary = isRange && !forceEvents.includes(eventType); // 面板收起时候,将值设置为确认值 v = eventType === 'VISIBLE_CHANGE' ? value : _this.checkValue(v, !isTemporary); var stringV = (0, util_2.fmtValue)(v, format); _this.setState({ curValue: v, inputStr: stringV, inputValue: stringV, inputing: false, selecting: eventType === 'start' || eventType === 'end', }); if (!isTemporary) { _this.setState({ value: v, }, function () { // 判断当前选择结束,收起面板: // 1. 非 Range 选择 // 2. 非 选择预设时间、面板收起、清空输入 操作 // 3. 不需要切换输入框 var shouldHidePanel = [ 'CLICK_PRESET', 'VISIBLE_CHANGE', 'KEYDOWN_ENTER', 'INPUT_CLEAR', 'CLICK_OK', ].includes(eventType) || (isRange && !_this.shouldSwitchInput(v)); if (shouldHidePanel) { _this.onVisibleChange(false); } if ((0, util_2.isValueChanged)(v, preValue)) { _this.onChange(v); } }); } }; /** * 获取输入框的禁用状态 */ _this.isEnabled = function (idx) { var disabled = _this.props.disabled; return Array.isArray(disabled) ? idx === undefined ? !disabled[0] && !disabled[1] : !disabled[idx] : !disabled; }; _this.handleClear = function () { /** * 清空输入之后 input 组件内部会让第二个输入框获得焦点 * 所以这里需要设置 setTimeout 才能让第一个 input 获得焦点 */ _this.clearTimeoutId = window.setTimeout(function () { _this.handleInputFocus(0); }); _this.setState({ inputType: constant_1.TIME_INPUT_TYPE.BEGIN, justBeginInput: _this.isEnabled(), }); }; _this.handleInput = function (v, eventType) { var isRange = _this.state.isRange; if (eventType === 'clear') { _this.handleChange(v, 'INPUT_CLEAR'); if (isRange) { _this.handleClear(); } } else { _this.setState({ inputStr: v, inputValue: v, curValue: _this.checkValue(v), inputing: true, visible: true, }); } }; var isRange = props.type === constant_1.TIME_PICKER_TYPE.RANGE; _this.state = {}; if (isRange) { var _a = _this.getInitRangeInputState(), inputType = _a.inputType, justBeginInput = _a.justBeginInput; _this.state = { inputType: inputType, justBeginInput: justBeginInput, }; } var _b = _this.props, format = _b.format, visible = _b.visible, defaultVisible = _b.defaultVisible, prefix = _b.prefix; var value = _this.getInitValue(); // const value = formatInputTimeValue(props.value || props.defaultValue, props.format, isRange); _this.state = tslib_1.__assign(tslib_1.__assign({}, _this.state), { isRange: isRange, inputStr: '', // 输入框的输入值,string 类型 value: value, curValue: value, preValue: value, inputValue: (0, util_2.fmtValue)(value, format), inputing: false, visible: 'visible' in _this.props ? visible : defaultVisible }); _this.prefixCls = "".concat(prefix, "time-picker2"); return _this; } TimePicker2.getDerivedStateFromProps = function (props, prevState) { var disabled = props.disabled, type = props.type, format = props.format, propsValue = props.value; var isRange = type === constant_1.TIME_PICKER_TYPE.RANGE; var state = { isRange: isRange, }; if ('value' in props) { // checkDate function doesn't support hh:mm:ss format, convert to valid dayjs value in advance var formatter_1 = function (v) { return typeof v === 'string' ? (0, util_1.datejs)(v, format) : v; }; var formattedValue = Array.isArray(propsValue) ? propsValue.map(function (v) { return formatter_1(v); }) : formatter_1(propsValue); var value = isRange ? checkRangeDate(formattedValue, state.inputType, disabled) : checkDate(formattedValue); if ((0, util_2.isValueChanged)(value, state.preValue)) { state = tslib_1.__assign(tslib_1.__assign({}, state), { value: value, preValue: value }); if (isRange && !prevState.selecting) { state.inputValue = (0, util_2.fmtValue)(value, format); state.curValue = formattedValue || []; } } } if ('visible' in props) { state.visible = props.visible; } return state; }; TimePicker2.prototype.renderPreview = function (others) { var _a = this.props, prefix = _a.prefix, format = _a.format, className = _a.className, renderPreview = _a.renderPreview; var value = this.state.value; var previewCls = (0, classnames_1.default)(className, "".concat(prefix, "form-preview")); var label = ''; if (value) { var valueArr = Array.isArray(value) ? value : [value]; label = valueArr.map(function (v) { return (v ? v.format(format) : ''); }).join('-'); } if (typeof renderPreview === 'function') { return (react_1.default.createElement("div", tslib_1.__assign({}, others, { className: previewCls }), renderPreview(value, this.props))); } return (react_1.default.createElement("p", tslib_1.__assign({}, others, { className: previewCls }), label)); }; TimePicker2.prototype.render = function () { var _a, _b; var _this = this; var _c = this.props, prefix = _c.prefix, label = _c.label, state = _c.state, placeholder = _c.placeholder, size = _c.size, format = _c.format, hasClear = _c.hasClear, hourStep = _c.hourStep, minuteStep = _c.minuteStep, secondStep = _c.secondStep, disabledHours = _c.disabledHours, disabledMinutes = _c.disabledMinutes, disabledSeconds = _c.disabledSeconds, renderTimeMenuItems = _c.renderTimeMenuItems, inputProps = _c.inputProps, popupAlign = _c.popupAlign, popupTriggerType = _c.popupTriggerType, popupContainer = _c.popupContainer, popupStyle = _c.popupStyle, popupClassName = _c.popupClassName, popupProps = _c.popupProps, popupComponent = _c.popupComponent, followTrigger = _c.followTrigger, disabled = _c.disabled, hasBorder = _c.hasBorder, className = _c.className, locale = _c.locale, rtl = _c.rtl, isPreview = _c.isPreview, preset = _c.preset, others = tslib_1.__rest(_c, ["prefix", "label", "state", "placeholder", "size", "format", "hasClear", "hourStep", "minuteStep", "secondStep", "disabledHours", "disabledMinutes", "disabledSeconds", "renderTimeMenuItems", "inputProps", "popupAlign", "popupTriggerType", "popupContainer", "popupStyle", "popupClassName", "popupProps", "popupComponent", "followTrigger", "disabled", "hasBorder", "className", "locale", "rtl", "isPreview", "preset"]); var _d = this.state, value = _d.value, inputStr = _d.inputStr, inputValue = _d.inputValue, curValue = _d.curValue, inputing = _d.inputing, visible = _d.visible, isRange = _d.isRange, inputType = _d.inputType; var triggerCls = (0, classnames_1.default)((_a = {}, _a["".concat(this.prefixCls, "-trigger")] = true, _a)); if (rtl) { others.dir = 'rtl'; } if (isPreview) { // @ts-expect-error TimePicker2 上不存在 PropTypes 属性,应该是 propTypes return this.renderPreview(util_1.obj.pickOthers(others, TimePicker2.PropTypes)); } var sharedInputProps = tslib_1.__assign(tslib_1.__assign({ prefix: prefix, locale: locale, label: label, state: state, placeholder: placeholder }, inputProps), { size: size, disabled: disabled, // RangePicker 有临时输入态在 inputValue 里面 value: inputing ? inputStr : isRange ? inputValue : (0, util_2.fmtValue)(value, format) || '', hasClear: value && hasClear, inputType: inputType, isRange: isRange, focus: visible, onInputTypeChange: this.onInputTypeChange, onInput: this.handleInput, onKeyDown: this.onKeyDown, ref: function (el) { return (_this.dateInput = el); } }); var triggerInput = (react_1.default.createElement("div", { className: triggerCls }, react_1.default.createElement(date_input_1.default, tslib_1.__assign({}, sharedInputProps, { label: label, state: state, onClick: this.onClick, hasBorder: hasBorder, placeholder: placeholder || locale.placeholder, className: (0, classnames_1.default)("".concat(this.prefixCls, "-input")) })))); var panelProps = { prefix: prefix, locale: locale, value: inputing ? this.checkValue(inputStr) : curValue, // value: curValue, isRange: isRange, disabled: disabled, showHour: format.indexOf('H') > -1, showSecond: format.indexOf('s') > -1, showMinute: format.indexOf('m') > -1, hourStep: hourStep, minuteStep: minuteStep, secondStep: secondStep, disabledHours: disabledHours, disabledMinutes: disabledMinutes, disabledSeconds: disabledSeconds, renderTimeMenuItems: renderTimeMenuItems, onSelect: this.handleChange, }; var classNames = (0, classnames_1.default)((_b = {}, _b["".concat(this.prefixCls)] = true, _b["".concat(this.prefixCls, "-").concat(size)] = size, _b["".concat(prefix, "disabled")] = disabled, _b), className); var PopupComponent = popupComponent ? popupComponent : Popup; var oKable = !!(isRange ? inputValue && inputValue[inputType] : inputValue); return (react_1.default.createElement("div", tslib_1.__assign({}, util_1.obj.pickOthers(TimePicker2.propTypes, others), { className: classNames }), react_1.default.createElement(PopupComponent, tslib_1.__assign({ align: popupAlign }, popupProps, { followTrigger: followTrigger, visible: visible, onVisibleChange: this.handleVisibleChange, trigger: triggerInput, container: popupContainer, // @ts-expect-error disabled 为 boolean | boolean[],此处没有考虑到 boolean[] 这种情况 disabled: disabled, triggerType: popupTriggerType, style: popupStyle, className: popupClassName }), react_1.default.createElement("div", { dir: others.dir, className: "".concat(this.prefixCls, "-wrapper") }, react_1.default.createElement("div", { className: "".concat(this.prefixCls, "-body") }, react_1.default.createElement(panel_1.default, tslib_1.__assign({}, panelProps)), preset || isRange ? (react_1.default.createElement(footer_panel_1.default, { prefix: prefix, className: "".concat(this.prefixCls, "-footer"), showTime: true, locale: locale, oKable: oKable, showOk: isRange, onOk: this.onOk, onChange: this.handleChange, preset: preset })) : null))))); }; TimePicker2.displayName = 'TimePicker2'; TimePicker2.propTypes = tslib_1.__assign(tslib_1.__assign({}, config_provider_1.default.propTypes), { prefix: prop_types_1.default.string, rtl: prop_types_1.default.bool, label: prop_types_1.default.node, state: prop_types_1.default.oneOf(['error', 'success']), placeholder: prop_types_1.default.oneOfType([prop_types_1.default.arrayOf(prop_types_1.default.string), prop_types_1.default.string]), value: prop_types_2.default.value, defaultValue: prop_types_2.default.value, size: prop_types_1.default.oneOf(['small', 'medium', 'large']), hasClear: prop_types_1.default.bool, format: prop_types_1.default.string, hourStep: prop_types_1.default.number, minuteStep: prop_types_1.default.number, secondStep: prop_types_1.default.number, disabledHours: prop_types_1.default.func, disabledMinutes: prop_types_1.default.func, disabledSeconds: prop_types_1.default.func, renderTimeMenuItems: prop_types_1.default.func, visible: prop_types_1.default.bool, defaultVisible: prop_types_1.default.bool, popupContainer: prop_types_1.default.any, popupAlign: prop_types_1.default.string, popupTriggerType: prop_types_1.default.oneOf(['click', 'hover']), onVisibleChange: prop_types_1.default.func, popupStyle: prop_types_1.default.object, popupClassName: prop_types_1.default.string, popupProps: prop_types_1.default.object, followTrigger: prop_types_1.default.bool, disabled: prop_types_1.default.bool, hasBorder: prop_types_1.default.bool, isPreview: prop_types_1.default.bool, renderPreview: prop_types_1.default.func, onChange: prop_types_1.default.func, className: prop_types_1.default.string, name: prop_types_1.default.string, preset: prop_types_1.default.oneOfType([prop_types_1.default.arrayOf(presetPropType), presetPropType]), inputProps: prop_types_1.default.shape(input_1.default.propTypes), popupComponent: prop_types_1.default.elementType, type: prop_types_1.default.oneOf(['time', 'range']) }); TimePicker2.defaultProps = { prefix: 'next-', rtl: false, locale: timePickerLocale, size: 'medium', format: 'HH:mm:ss', hasClear: true, disabled: false, hasBorder: true, type: 'time', popupAlign: 'tl bl', popupTriggerType: 'click', onChange: noop, onVisibleChange: noop, }; return TimePicker2; }(react_1.Component)); exports.default = (0, react_lifecycles_compat_1.polyfill)(TimePicker2);