UNPKG

element-plus

Version:

A Component Library for Vue3.0

1,477 lines (1,463 loc) 56 kB
import { defineComponent, inject, ref, watch, nextTick, computed, provide, resolveComponent, resolveDirective, openBlock, createBlock, mergeProps, withCtx, withDirectives, createVNode, renderSlot, toDisplayString, withModifiers, onMounted, Fragment, renderList, createTextVNode, createCommentVNode, Transition, h } from 'vue'; import dayjs from 'dayjs'; import customParseFormat from 'dayjs/plugin/customParseFormat'; import isEqual from 'lodash/isEqual'; import { ClickOutside, RepeatClick } from '../directives'; import ElInput from '../el-input'; import ElPopper from '../el-popper'; import { EVENT_CODE } from '../utils/aria'; import { useGlobalConfig, isEmpty } from '../utils/util'; import { elFormKey, elFormItemKey } from '../el-form'; import { isValidComponentSize } from '../utils/validators'; import { t } from '../locale'; import debounce from 'lodash/debounce'; import ElScrollbar from '../el-scrollbar'; import union from 'lodash/union'; const DEFAULT_FORMATS_TIME = "HH:mm:ss"; const DEFAULT_FORMATS_DATE = "YYYY-MM-DD"; const DEFAULT_FORMATS_DATEPICKER = { date: DEFAULT_FORMATS_DATE, week: "gggg[w]ww", year: "YYYY", month: "YYYY-MM", datetime: `${DEFAULT_FORMATS_DATE} ${DEFAULT_FORMATS_TIME}`, monthrange: "YYYY-MM", daterange: DEFAULT_FORMATS_DATE, datetimerange: `${DEFAULT_FORMATS_DATE} ${DEFAULT_FORMATS_TIME}` }; const defaultProps = { name: { type: [Array, String], default: "" }, popperClass: { type: String, default: "" }, format: { type: String }, valueFormat: { type: String }, type: { type: String, default: "" }, clearable: { type: Boolean, default: true }, clearIcon: { type: String, default: "el-icon-circle-close" }, editable: { type: Boolean, default: true }, prefixIcon: { type: String, default: "" }, size: { type: String, validator: isValidComponentSize }, readonly: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, placeholder: { type: String, default: "" }, popperOptions: { type: Object, default: () => ({}) }, modelValue: { type: [Date, Array, String], default: "" }, rangeSeparator: { type: String, default: "-" }, startPlaceholder: String, endPlaceholder: String, defaultValue: { type: [Date, Array] }, defaultTime: { type: [Date, Array] }, isRange: { type: Boolean, default: false }, disabledHours: { type: Function }, disabledMinutes: { type: Function }, disabledSeconds: { type: Function }, disabledDate: { type: Function }, cellClassName: { type: Function }, shortcuts: { type: Array, default: () => [] }, arrowControl: { type: Boolean, default: false }, validateEvent: { type: Boolean, default: true }, unlinkPanels: Boolean }; const dateEquals = function(a, b) { const aIsDate = a instanceof Date; const bIsDate = b instanceof Date; if (aIsDate && bIsDate) { return a.getTime() === b.getTime(); } if (!aIsDate && !bIsDate) { return a === b; } return false; }; const valueEquals = function(a, b) { const aIsArray = a instanceof Array; const bIsArray = b instanceof Array; if (aIsArray && bIsArray) { if (a.length !== b.length) { return false; } return a.every((item, index) => dateEquals(item, b[index])); } if (!aIsArray && !bIsArray) { return dateEquals(a, b); } return false; }; const parser = function(date, format) { const day = isEmpty(format) ? dayjs(date) : dayjs(date, format); return day.isValid() ? day : void 0; }; const formatter = function(date, format) { return isEmpty(format) ? date : dayjs(date).format(format); }; var script = defineComponent({ name: "Picker", components: { ElInput, ElPopper }, directives: { clickoutside: ClickOutside }, props: defaultProps, emits: ["update:modelValue", "change", "focus", "blur"], setup(props, ctx) { const ELEMENT = useGlobalConfig(); const elForm = inject(elFormKey, {}); const elFormItem = inject(elFormItemKey, {}); const elPopperOptions = inject("ElPopperOptions", {}); const refPopper = ref(null); const pickerVisible = ref(false); const pickerActualVisible = ref(false); const valueOnOpen = ref(null); watch(pickerVisible, (val) => { var _a; if (!val) { userInput.value = null; nextTick(() => { emitChange(props.modelValue); }); ctx.emit("blur"); blurInput(); props.validateEvent && ((_a = elFormItem.formItemMitt) == null ? void 0 : _a.emit("el.form.blur")); } else { valueOnOpen.value = props.modelValue; } }); const emitChange = (val, isClear) => { var _a; if (isClear || !valueEquals(val, valueOnOpen.value)) { ctx.emit("change", val); props.validateEvent && ((_a = elFormItem.formItemMitt) == null ? void 0 : _a.emit("el.form.change", val)); } }; const emitInput = (val) => { if (!valueEquals(props.modelValue, val)) { let formatValue; if (Array.isArray(val)) { formatValue = val.map((_) => formatter(_, props.valueFormat)); } else if (val) { formatValue = formatter(val, props.valueFormat); } ctx.emit("update:modelValue", val ? formatValue : val); } }; const refInput = computed(() => { if (refPopper.value.triggerRef) { const _r = isRangeInput.value ? refPopper.value.triggerRef : refPopper.value.triggerRef.$el; return [].slice.call(_r.querySelectorAll("input")); } return []; }); const setSelectionRange = (start, end, pos) => { const _inputs = refInput.value; if (!_inputs.length) return; if (!pos || pos === "min") { _inputs[0].setSelectionRange(start, end); _inputs[0].focus(); } else if (pos === "max") { _inputs[1].setSelectionRange(start, end); _inputs[1].focus(); } }; const onPick = (date = "", visible = false) => { pickerVisible.value = visible; let result; if (Array.isArray(date)) { result = date.map((_) => _.toDate()); } else { result = date ? date.toDate() : date; } userInput.value = null; emitInput(result); }; const handleFocus = (e) => { if (props.readonly || pickerDisabled.value || pickerVisible.value) return; pickerVisible.value = true; ctx.emit("focus", e); }; const handleBlur = () => { pickerVisible.value = false; blurInput(); }; const pickerDisabled = computed(() => { return props.disabled || elForm.disabled; }); const parsedValue = computed(() => { let result; if (valueIsEmpty.value) { if (pickerOptions.value.getDefaultValue) { result = pickerOptions.value.getDefaultValue(); } } else { if (Array.isArray(props.modelValue)) { result = props.modelValue.map((_) => parser(_, props.valueFormat)); } else { result = parser(props.modelValue, props.valueFormat); } } if (pickerOptions.value.getRangeAvailableTime) { const availableResult = pickerOptions.value.getRangeAvailableTime(result); if (!isEqual(availableResult, result)) { result = availableResult; emitInput(Array.isArray(result) ? result.map((_) => _.toDate()) : result.toDate()); } } if (Array.isArray(result) && result.some((_) => !_)) { result = []; } return result; }); const displayValue = computed(() => { if (!pickerOptions.value.panelReady) return; const formattedValue = formatDayjsToString(parsedValue.value); if (Array.isArray(userInput.value)) { return [ userInput.value[0] || formattedValue && formattedValue[0] || "", userInput.value[1] || formattedValue && formattedValue[1] || "" ]; } else if (userInput.value !== null) { return userInput.value; } if (!isTimePicker.value && valueIsEmpty.value) return; if (!pickerVisible.value && valueIsEmpty.value) return; if (formattedValue) { return isDatesPicker.value ? formattedValue.join(", ") : formattedValue; } return ""; }); const isTimeLikePicker = computed(() => { return props.type.indexOf("time") !== -1; }); const isTimePicker = computed(() => { return props.type.indexOf("time") === 0; }); const isDatesPicker = computed(() => { return props.type === "dates"; }); const triggerClass = computed(() => { return props.prefixIcon || (isTimeLikePicker.value ? "el-icon-time" : "el-icon-date"); }); const showClose = ref(false); const onClearIconClick = (event) => { if (props.readonly || pickerDisabled.value) return; if (showClose.value) { event.stopPropagation(); emitInput(null); emitChange(null, true); showClose.value = false; pickerVisible.value = false; pickerOptions.value.handleClear && pickerOptions.value.handleClear(); } }; const valueIsEmpty = computed(() => { return !props.modelValue || Array.isArray(props.modelValue) && !props.modelValue.length; }); const onMouseEnter = () => { if (props.readonly || pickerDisabled.value) return; if (!valueIsEmpty.value && props.clearable) { showClose.value = true; } }; const onMouseLeave = () => { showClose.value = false; }; const isRangeInput = computed(() => { return props.type.indexOf("range") > -1; }); const pickerSize = computed(() => { return props.size || elFormItem.size || ELEMENT.size; }); const popperPaneRef = computed(() => { var _a; return (_a = refPopper.value) == null ? void 0 : _a.popperRef; }); const onClickOutside = () => { if (!pickerVisible.value) return; pickerVisible.value = false; }; const userInput = ref(null); const handleChange = () => { if (userInput.value) { const value = parseUserInputToDayjs(displayValue.value); if (value) { if (isValidValue(value)) { emitInput(Array.isArray(value) ? value.map((_) => _.toDate()) : value.toDate()); userInput.value = null; } } } if (userInput.value === "") { emitInput(null); emitChange(null); userInput.value = null; } }; const blurInput = () => { refInput.value.forEach((input) => input.blur()); }; const parseUserInputToDayjs = (value) => { if (!value) return null; return pickerOptions.value.parseUserInput(value); }; const formatDayjsToString = (value) => { if (!value) return null; return pickerOptions.value.formatToString(value); }; const isValidValue = (value) => { return pickerOptions.value.isValidValue(value); }; const handleKeydown = (event) => { const code = event.code; if (code === EVENT_CODE.esc) { pickerVisible.value = false; event.stopPropagation(); return; } if (code === EVENT_CODE.tab) { if (!isRangeInput.value) { handleChange(); pickerVisible.value = false; event.stopPropagation(); } else { setTimeout(() => { if (refInput.value.indexOf(document.activeElement) === -1) { pickerVisible.value = false; blurInput(); } }, 0); } return; } if (code === EVENT_CODE.enter) { if (userInput.value === "" || isValidValue(parseUserInputToDayjs(displayValue.value))) { handleChange(); pickerVisible.value = false; } event.stopPropagation(); return; } if (userInput.value) { event.stopPropagation(); return; } if (pickerOptions.value.handleKeydown) { pickerOptions.value.handleKeydown(event); } }; const onUserInput = (e) => { userInput.value = e; }; const handleStartInput = (event) => { if (userInput.value) { userInput.value = [event.target.value, userInput.value[1]]; } else { userInput.value = [event.target.value, null]; } }; const handleEndInput = (event) => { if (userInput.value) { userInput.value = [userInput.value[0], event.target.value]; } else { userInput.value = [null, event.target.value]; } }; const handleStartChange = () => { const value = parseUserInputToDayjs(userInput.value && userInput.value[0]); if (value && value.isValid()) { userInput.value = [formatDayjsToString(value), displayValue.value[1]]; const newValue = [value, parsedValue.value && parsedValue.value[1]]; if (isValidValue(newValue)) { emitInput(newValue); userInput.value = null; } } }; const handleEndChange = () => { const value = parseUserInputToDayjs(userInput.value && userInput.value[1]); if (value && value.isValid()) { userInput.value = [displayValue.value[0], formatDayjsToString(value)]; const newValue = [parsedValue.value && parsedValue.value[0], value]; if (isValidValue(newValue)) { emitInput(newValue); userInput.value = null; } } }; const pickerOptions = ref({}); const onSetPickerOption = (e) => { pickerOptions.value[e[0]] = e[1]; pickerOptions.value.panelReady = true; }; provide("EP_PICKER_BASE", { props }); return { elPopperOptions, isDatesPicker, handleEndChange, handleStartChange, handleStartInput, handleEndInput, onUserInput, handleChange, handleKeydown, popperPaneRef, onClickOutside, pickerSize, isRangeInput, onMouseLeave, onMouseEnter, onClearIconClick, showClose, triggerClass, onPick, handleFocus, handleBlur, pickerVisible, pickerActualVisible, displayValue, parsedValue, setSelectionRange, refPopper, pickerDisabled, onSetPickerOption }; } }); const _hoisted_1 = { class: "el-range-separator" }; function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_el_input = resolveComponent("el-input"); const _component_el_popper = resolveComponent("el-popper"); const _directive_clickoutside = resolveDirective("clickoutside"); return openBlock(), createBlock(_component_el_popper, mergeProps({ ref: "refPopper", visible: _ctx.pickerVisible, "onUpdate:visible": _cache[18] || (_cache[18] = ($event) => _ctx.pickerVisible = $event), "manual-mode": "", effect: "light", pure: "", trigger: "click" }, _ctx.$attrs, { "popper-class": `el-picker__popper ${_ctx.popperClass}`, "popper-options": _ctx.elPopperOptions, "fallback-placements": ["bottom", "top", "right", "left"], transition: "el-zoom-in-top", "gpu-acceleration": false, "stop-popper-mouse-event": false, "append-to-body": "", onBeforeEnter: _cache[19] || (_cache[19] = ($event) => _ctx.pickerActualVisible = true), onAfterLeave: _cache[20] || (_cache[20] = ($event) => _ctx.pickerActualVisible = false) }), { trigger: withCtx(() => [ !_ctx.isRangeInput ? withDirectives((openBlock(), createBlock(_component_el_input, { key: 0, "model-value": _ctx.displayValue, name: _ctx.name, size: _ctx.pickerSize, disabled: _ctx.pickerDisabled, placeholder: _ctx.placeholder, class: ["el-date-editor", "el-date-editor--" + _ctx.type], readonly: !_ctx.editable || _ctx.readonly || _ctx.isDatesPicker || _ctx.type === "week", onInput: _ctx.onUserInput, onFocus: _ctx.handleFocus, onKeydown: _ctx.handleKeydown, onChange: _ctx.handleChange, onMouseenter: _ctx.onMouseEnter, onMouseleave: _ctx.onMouseLeave }, { prefix: withCtx(() => [ createVNode("i", { class: ["el-input__icon", _ctx.triggerClass], onClick: _cache[1] || (_cache[1] = (...args) => _ctx.handleFocus && _ctx.handleFocus(...args)) }, null, 2) ]), suffix: withCtx(() => [ createVNode("i", { class: ["el-input__icon", [_ctx.showClose ? "" + _ctx.clearIcon : ""]], onClick: _cache[2] || (_cache[2] = (...args) => _ctx.onClearIconClick && _ctx.onClearIconClick(...args)) }, null, 2) ]), _: 1 }, 8, ["model-value", "name", "size", "disabled", "placeholder", "class", "readonly", "onInput", "onFocus", "onKeydown", "onChange", "onMouseenter", "onMouseleave"])), [ [_directive_clickoutside, _ctx.onClickOutside, _ctx.popperPaneRef] ]) : withDirectives((openBlock(), createBlock("div", { key: 1, class: ["el-date-editor el-range-editor el-input__inner", [ "el-date-editor--" + _ctx.type, _ctx.pickerSize ? `el-range-editor--${_ctx.pickerSize}` : "", _ctx.pickerDisabled ? "is-disabled" : "", _ctx.pickerVisible ? "is-active" : "" ]], onClick: _cache[10] || (_cache[10] = (...args) => _ctx.handleFocus && _ctx.handleFocus(...args)), onMouseenter: _cache[11] || (_cache[11] = (...args) => _ctx.onMouseEnter && _ctx.onMouseEnter(...args)), onMouseleave: _cache[12] || (_cache[12] = (...args) => _ctx.onMouseLeave && _ctx.onMouseLeave(...args)), onKeydown: _cache[13] || (_cache[13] = (...args) => _ctx.handleKeydown && _ctx.handleKeydown(...args)) }, [ createVNode("i", { class: ["el-input__icon", "el-range__icon", _ctx.triggerClass] }, null, 2), createVNode("input", { autocomplete: "off", name: _ctx.name && _ctx.name[0], placeholder: _ctx.startPlaceholder, value: _ctx.displayValue && _ctx.displayValue[0], disabled: _ctx.pickerDisabled, readonly: !_ctx.editable || _ctx.readonly, class: "el-range-input", onInput: _cache[3] || (_cache[3] = (...args) => _ctx.handleStartInput && _ctx.handleStartInput(...args)), onChange: _cache[4] || (_cache[4] = (...args) => _ctx.handleStartChange && _ctx.handleStartChange(...args)), onFocus: _cache[5] || (_cache[5] = (...args) => _ctx.handleFocus && _ctx.handleFocus(...args)) }, null, 40, ["name", "placeholder", "value", "disabled", "readonly"]), renderSlot(_ctx.$slots, "range-separator", {}, () => [ createVNode("span", _hoisted_1, toDisplayString(_ctx.rangeSeparator), 1) ]), createVNode("input", { autocomplete: "off", name: _ctx.name && _ctx.name[1], placeholder: _ctx.endPlaceholder, value: _ctx.displayValue && _ctx.displayValue[1], disabled: _ctx.pickerDisabled, readonly: !_ctx.editable || _ctx.readonly, class: "el-range-input", onFocus: _cache[6] || (_cache[6] = (...args) => _ctx.handleFocus && _ctx.handleFocus(...args)), onInput: _cache[7] || (_cache[7] = (...args) => _ctx.handleEndInput && _ctx.handleEndInput(...args)), onChange: _cache[8] || (_cache[8] = (...args) => _ctx.handleEndChange && _ctx.handleEndChange(...args)) }, null, 40, ["name", "placeholder", "value", "disabled", "readonly"]), createVNode("i", { class: [[_ctx.showClose ? "" + _ctx.clearIcon : ""], "el-input__icon el-range__close-icon"], onClick: _cache[9] || (_cache[9] = (...args) => _ctx.onClearIconClick && _ctx.onClearIconClick(...args)) }, null, 2) ], 34)), [ [_directive_clickoutside, _ctx.onClickOutside, _ctx.popperPaneRef] ]) ]), default: withCtx(() => [ renderSlot(_ctx.$slots, "default", { visible: _ctx.pickerVisible, actualVisible: _ctx.pickerActualVisible, parsedValue: _ctx.parsedValue, format: _ctx.format, unlinkPanels: _ctx.unlinkPanels, type: _ctx.type, defaultValue: _ctx.defaultValue, onPick: _cache[14] || (_cache[14] = (...args) => _ctx.onPick && _ctx.onPick(...args)), onSelectRange: _cache[15] || (_cache[15] = (...args) => _ctx.setSelectionRange && _ctx.setSelectionRange(...args)), onSetPickerOption: _cache[16] || (_cache[16] = (...args) => _ctx.onSetPickerOption && _ctx.onSetPickerOption(...args)), onMousedown: _cache[17] || (_cache[17] = withModifiers(() => { }, ["stop"])) }) ]), _: 1 }, 16, ["visible", "popper-class", "popper-options"]); } script.render = render; script.__file = "packages/time-picker/src/common/picker.vue"; const makeList = (total, method, methodFunc) => { const arr = []; const disabledArr = method && methodFunc(); for (let i = 0; i < total; i++) { arr[i] = disabledArr ? disabledArr.includes(i) : false; } return arr; }; const makeAvailableArr = (list) => { return list.map((_, index) => !_ ? index : _).filter((_) => _ !== true); }; const getTimeLists = (disabledHours, disabledMinutes, disabledSeconds) => { const getHoursList = (role, compare) => { return makeList(24, disabledHours, () => disabledHours(role, compare)); }; const getMinutesList = (hour, role, compare) => { return makeList(60, disabledMinutes, () => disabledMinutes(hour, role, compare)); }; const getSecondsList = (hour, minute, role, compare) => { return makeList(60, disabledSeconds, () => disabledSeconds(hour, minute, role, compare)); }; return { getHoursList, getMinutesList, getSecondsList }; }; const getAvailableArrs = (disabledHours, disabledMinutes, disabledSeconds) => { const { getHoursList, getMinutesList, getSecondsList } = getTimeLists(disabledHours, disabledMinutes, disabledSeconds); const getAvailableHours = (role, compare) => { return makeAvailableArr(getHoursList(role, compare)); }; const getAvailableMinutes = (hour, role, compare) => { return makeAvailableArr(getMinutesList(hour, role, compare)); }; const getAvailableSeconds = (hour, minute, role, compare) => { return makeAvailableArr(getSecondsList(hour, minute, role, compare)); }; return { getAvailableHours, getAvailableMinutes, getAvailableSeconds }; }; const useOldValue = (props) => { const oldValue = ref(props.parsedValue); watch(() => props.visible, (val) => { if (!val) { oldValue.value = props.parsedValue; } }); return oldValue; }; var script$1 = defineComponent({ directives: { repeatClick: RepeatClick }, components: { ElScrollbar }, props: { role: { type: String, required: true }, spinnerDate: { type: Object, required: true }, showSeconds: { type: Boolean, default: true }, arrowControl: Boolean, amPmMode: { type: String, default: "" }, disabledHours: { type: Function }, disabledMinutes: { type: Function }, disabledSeconds: { type: Function } }, emits: ["change", "select-range", "set-option"], setup(props, ctx) { let isScrolling = false; const debouncedResetScroll = debounce((type) => { isScrolling = false; adjustCurrentSpinner(type); }, 200); const currentScrollbar = ref(null); const listHoursRef = ref(null); const listMinutesRef = ref(null); const listSecondsRef = ref(null); const listRefsMap = { hours: listHoursRef, minutes: listMinutesRef, seconds: listSecondsRef }; const spinnerItems = computed(() => { const arr = ["hours", "minutes", "seconds"]; return props.showSeconds ? arr : arr.slice(0, 2); }); const hours = computed(() => { return props.spinnerDate.hour(); }); const minutes = computed(() => { return props.spinnerDate.minute(); }); const seconds = computed(() => { return props.spinnerDate.second(); }); const timePartsMap = computed(() => ({ hours, minutes, seconds })); const hoursList = computed(() => { return getHoursList(props.role); }); const minutesList = computed(() => { return getMinutesList(hours.value, props.role); }); const secondsList = computed(() => { return getSecondsList(hours.value, minutes.value, props.role); }); const listMap = computed(() => ({ hours: hoursList, minutes: minutesList, seconds: secondsList })); const arrowHourList = computed(() => { const hour = hours.value; return [ hour > 0 ? hour - 1 : void 0, hour, hour < 23 ? hour + 1 : void 0 ]; }); const arrowMinuteList = computed(() => { const minute = minutes.value; return [ minute > 0 ? minute - 1 : void 0, minute, minute < 59 ? minute + 1 : void 0 ]; }); const arrowSecondList = computed(() => { const second = seconds.value; return [ second > 0 ? second - 1 : void 0, second, second < 59 ? second + 1 : void 0 ]; }); const arrowListMap = computed(() => ({ hours: arrowHourList, minutes: arrowMinuteList, seconds: arrowSecondList })); const getAmPmFlag = (hour) => { let shouldShowAmPm = !!props.amPmMode; if (!shouldShowAmPm) return ""; let isCapital = props.amPmMode === "A"; let content = hour < 12 ? " am" : " pm"; if (isCapital) content = content.toUpperCase(); return content; }; const emitSelectRange = (type) => { if (type === "hours") { ctx.emit("select-range", 0, 2); } else if (type === "minutes") { ctx.emit("select-range", 3, 5); } else if (type === "seconds") { ctx.emit("select-range", 6, 8); } currentScrollbar.value = type; }; const adjustCurrentSpinner = (type) => { adjustSpinner(type, timePartsMap.value[type].value); }; const adjustSpinners = () => { adjustCurrentSpinner("hours"); adjustCurrentSpinner("minutes"); adjustCurrentSpinner("seconds"); }; const adjustSpinner = (type, value) => { if (props.arrowControl) return; const el = listRefsMap[type]; if (el.value) { el.value.$el.querySelector(".el-scrollbar__wrap").scrollTop = Math.max(0, value * typeItemHeight(type)); } }; const typeItemHeight = (type) => { const el = listRefsMap[type]; return el.value.$el.querySelector("li").offsetHeight; }; const onIncreaseClick = () => { scrollDown(1); }; const onDecreaseClick = () => { scrollDown(-1); }; const scrollDown = (step) => { if (!currentScrollbar.value) { emitSelectRange("hours"); } const label = currentScrollbar.value; let now = timePartsMap.value[label].value; const total = currentScrollbar.value === "hours" ? 24 : 60; now = (now + step + total) % total; modifyDateField(label, now); adjustSpinner(label, now); nextTick(() => emitSelectRange(currentScrollbar.value)); }; const modifyDateField = (type, value) => { const list = listMap.value[type].value; const isDisabled = list[value]; if (isDisabled) return; switch (type) { case "hours": ctx.emit("change", props.spinnerDate.hour(value).minute(minutes.value).second(seconds.value)); break; case "minutes": ctx.emit("change", props.spinnerDate.hour(hours.value).minute(value).second(seconds.value)); break; case "seconds": ctx.emit("change", props.spinnerDate.hour(hours.value).minute(minutes.value).second(value)); break; } }; const handleClick = (type, { value, disabled }) => { if (!disabled) { modifyDateField(type, value); emitSelectRange(type); adjustSpinner(type, value); } }; const handleScroll = (type) => { isScrolling = true; debouncedResetScroll(type); const value = Math.min(Math.round((listRefsMap[type].value.$el.querySelector(".el-scrollbar__wrap").scrollTop - (scrollBarHeight(type) * 0.5 - 10) / typeItemHeight(type) + 3) / typeItemHeight(type)), type === "hours" ? 23 : 59); modifyDateField(type, value); }; const scrollBarHeight = (type) => { return listRefsMap[type].value.$el.offsetHeight; }; const bindScrollEvent = () => { const bindFuntion = (type) => { if (listRefsMap[type].value) { listRefsMap[type].value.$el.querySelector(".el-scrollbar__wrap").onscroll = () => { handleScroll(type); }; } }; bindFuntion("hours"); bindFuntion("minutes"); bindFuntion("seconds"); }; onMounted(() => { nextTick(() => { !props.arrowControl && bindScrollEvent(); adjustSpinners(); if (props.role === "start") emitSelectRange("hours"); }); }); const getRefId = (item) => { return `list${item.charAt(0).toUpperCase() + item.slice(1)}Ref`; }; ctx.emit("set-option", [`${props.role}_scrollDown`, scrollDown]); ctx.emit("set-option", [`${props.role}_emitSelectRange`, emitSelectRange]); const { getHoursList, getMinutesList, getSecondsList } = getTimeLists(props.disabledHours, props.disabledMinutes, props.disabledSeconds); watch(() => props.spinnerDate, () => { if (isScrolling) return; adjustSpinners(); }); return { getRefId, spinnerItems, currentScrollbar, hours, minutes, seconds, hoursList, minutesList, arrowHourList, arrowMinuteList, arrowSecondList, getAmPmFlag, emitSelectRange, adjustCurrentSpinner, typeItemHeight, listHoursRef, listMinutesRef, listSecondsRef, onIncreaseClick, onDecreaseClick, handleClick, secondsList, timePartsMap, arrowListMap, listMap }; } }); const _hoisted_1$1 = { class: "el-time-spinner__arrow el-icon-arrow-up" }; const _hoisted_2 = { class: "el-time-spinner__arrow el-icon-arrow-down" }; const _hoisted_3 = { class: "el-time-spinner__list" }; function render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_el_scrollbar = resolveComponent("el-scrollbar"); const _directive_repeat_click = resolveDirective("repeat-click"); return openBlock(), createBlock("div", { class: ["el-time-spinner", { "has-seconds": _ctx.showSeconds }] }, [ !_ctx.arrowControl ? (openBlock(true), createBlock(Fragment, { key: 0 }, renderList(_ctx.spinnerItems, (item) => { return openBlock(), createBlock(_component_el_scrollbar, { key: item, ref: _ctx.getRefId(item), class: "el-time-spinner__wrapper", "wrap-style": "max-height: inherit;", "view-class": "el-time-spinner__list", noresize: "", tag: "ul", onMouseenter: ($event) => _ctx.emitSelectRange(item), onMousemove: ($event) => _ctx.adjustCurrentSpinner(item) }, { default: withCtx(() => [ (openBlock(true), createBlock(Fragment, null, renderList(_ctx.listMap[item].value, (disabled, key) => { return openBlock(), createBlock("li", { key, class: ["el-time-spinner__item", { "active": key === _ctx.timePartsMap[item].value, disabled }], onClick: ($event) => _ctx.handleClick(item, { value: key, disabled }) }, [ item === "hours" ? (openBlock(), createBlock(Fragment, { key: 0 }, [ createTextVNode(toDisplayString(("0" + (_ctx.amPmMode ? key % 12 || 12 : key)).slice(-2)) + toDisplayString(_ctx.getAmPmFlag(key)), 1) ], 2112)) : (openBlock(), createBlock(Fragment, { key: 1 }, [ createTextVNode(toDisplayString(("0" + key).slice(-2)), 1) ], 2112)) ], 10, ["onClick"]); }), 128)) ]), _: 2 }, 1032, ["onMouseenter", "onMousemove"]); }), 128)) : createCommentVNode("v-if", true), _ctx.arrowControl ? (openBlock(true), createBlock(Fragment, { key: 1 }, renderList(_ctx.spinnerItems, (item) => { return openBlock(), createBlock("div", { key: item, class: "el-time-spinner__wrapper is-arrow", onMouseenter: ($event) => _ctx.emitSelectRange(item) }, [ withDirectives(createVNode("i", _hoisted_1$1, null, 512), [ [_directive_repeat_click, _ctx.onDecreaseClick] ]), withDirectives(createVNode("i", _hoisted_2, null, 512), [ [_directive_repeat_click, _ctx.onIncreaseClick] ]), createVNode("ul", _hoisted_3, [ (openBlock(true), createBlock(Fragment, null, renderList(_ctx.arrowListMap[item].value, (time, key) => { return openBlock(), createBlock("li", { key, class: ["el-time-spinner__item", { "active": time === _ctx.timePartsMap[item].value, "disabled": _ctx.listMap[item].value[time] }] }, toDisplayString(time === void 0 ? "" : ("0" + (_ctx.amPmMode ? time % 12 || 12 : time)).slice(-2) + _ctx.getAmPmFlag(time)), 3); }), 128)) ]) ], 40, ["onMouseenter"]); }), 128)) : createCommentVNode("v-if", true) ], 2); } script$1.render = render$1; script$1.__file = "packages/time-picker/src/time-picker-com/basic-time-spinner.vue"; var script$2 = defineComponent({ components: { TimeSpinner: script$1 }, props: { visible: Boolean, actualVisible: { type: Boolean, default: void 0 }, datetimeRole: { type: String }, parsedValue: { type: [Object, String] }, format: { type: String, default: "" } }, emits: ["pick", "select-range", "set-picker-option"], setup(props, ctx) { const selectionRange = ref([0, 2]); const oldValue = useOldValue(props); const transitionName = computed(() => { return props.actualVisible === void 0 ? "el-zoom-in-top" : ""; }); const showSeconds = computed(() => { return props.format.includes("ss"); }); const amPmMode = computed(() => { if (props.format.includes("A")) return "A"; if (props.format.includes("a")) return "a"; return ""; }); const isValidValue = (_date) => { const parsedDate = dayjs(_date); const result = getRangeAvailableTime(parsedDate); return parsedDate.isSame(result); }; const handleCancel = () => { ctx.emit("pick", oldValue.value, false); }; const handleConfirm = (visible = false, first) => { if (first) return; ctx.emit("pick", props.parsedValue, visible); }; const handleChange = (_date) => { if (!props.visible) { return; } const result = getRangeAvailableTime(_date).millisecond(0); ctx.emit("pick", result, true); }; const setSelectionRange = (start, end) => { ctx.emit("select-range", start, end); selectionRange.value = [start, end]; }; const changeSelectionRange = (step) => { const list = [0, 3].concat(showSeconds.value ? [6] : []); const mapping = ["hours", "minutes"].concat(showSeconds.value ? ["seconds"] : []); const index = list.indexOf(selectionRange.value[0]); const next = (index + step + list.length) % list.length; timePickerOptions["start_emitSelectRange"](mapping[next]); }; const handleKeydown = (event) => { const code = event.code; if (code === EVENT_CODE.left || code === EVENT_CODE.right) { const step = code === EVENT_CODE.left ? -1 : 1; changeSelectionRange(step); event.preventDefault(); return; } if (code === EVENT_CODE.up || code === EVENT_CODE.down) { const step = code === EVENT_CODE.up ? -1 : 1; timePickerOptions["start_scrollDown"](step); event.preventDefault(); return; } }; const getRangeAvailableTime = (date) => { const availableMap = { hour: getAvailableHours, minute: getAvailableMinutes, second: getAvailableSeconds }; let result = date; ["hour", "minute", "second"].forEach((_) => { if (availableMap[_]) { let availableArr; const method = availableMap[_]; if (_ === "minute") { availableArr = method(result.hour(), props.datetimeRole); } else if (_ === "second") { availableArr = method(result.hour(), result.minute(), props.datetimeRole); } else { availableArr = method(props.datetimeRole); } if (availableArr && availableArr.length && !availableArr.includes(result[_]())) { result = result[_](availableArr[0]); } } }); return result; }; const parseUserInput = (value) => { if (!value) return null; return dayjs(value, props.format); }; const formatToString = (value) => { if (!value) return null; return value.format(props.format); }; const getDefaultValue = () => { return dayjs(defaultValue); }; ctx.emit("set-picker-option", ["isValidValue", isValidValue]); ctx.emit("set-picker-option", ["formatToString", formatToString]); ctx.emit("set-picker-option", ["parseUserInput", parseUserInput]); ctx.emit("set-picker-option", ["handleKeydown", handleKeydown]); ctx.emit("set-picker-option", ["getRangeAvailableTime", getRangeAvailableTime]); ctx.emit("set-picker-option", ["getDefaultValue", getDefaultValue]); const timePickerOptions = {}; const onSetOption = (e) => { timePickerOptions[e[0]] = e[1]; }; const pickerBase = inject("EP_PICKER_BASE"); const { arrowControl, disabledHours, disabledMinutes, disabledSeconds, defaultValue } = pickerBase.props; const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } = getAvailableArrs(disabledHours, disabledMinutes, disabledSeconds); return { transitionName, arrowControl, onSetOption, t, handleConfirm, handleChange, setSelectionRange, amPmMode, showSeconds, handleCancel, disabledHours, disabledMinutes, disabledSeconds }; } }); const _hoisted_1$2 = { key: 0, class: "el-time-panel" }; const _hoisted_2$1 = { class: "el-time-panel__footer" }; function render$2(_ctx, _cache, $props, $setup, $data, $options) { const _component_time_spinner = resolveComponent("time-spinner"); return openBlock(), createBlock(Transition, { name: _ctx.transitionName }, { default: withCtx(() => [ _ctx.actualVisible || _ctx.visible ? (openBlock(), createBlock("div", _hoisted_1$2, [ createVNode("div", { class: ["el-time-panel__content", { "has-seconds": _ctx.showSeconds }] }, [ createVNode(_component_time_spinner, { ref: "spinner", role: _ctx.datetimeRole || "start", "arrow-control": _ctx.arrowControl, "show-seconds": _ctx.showSeconds, "am-pm-mode": _ctx.amPmMode, "spinner-date": _ctx.parsedValue, "disabled-hours": _ctx.disabledHours, "disabled-minutes": _ctx.disabledMinutes, "disabled-seconds": _ctx.disabledSeconds, onChange: _ctx.handleChange, onSetOption: _ctx.onSetOption, onSelectRange: _ctx.setSelectionRange }, null, 8, ["role", "arrow-control", "show-seconds", "am-pm-mode", "spinner-date", "disabled-hours", "disabled-minutes", "disabled-seconds", "onChange", "onSetOption", "onSelectRange"]) ], 2), createVNode("div", _hoisted_2$1, [ createVNode("button", { type: "button", class: "el-time-panel__btn cancel", onClick: _cache[1] || (_cache[1] = (...args) => _ctx.handleCancel && _ctx.handleCancel(...args)) }, toDisplayString(_ctx.t("el.datepicker.cancel")), 1), createVNode("button", { type: "button", class: "el-time-panel__btn confirm", onClick: _cache[2] || (_cache[2] = ($event) => _ctx.handleConfirm()) }, toDisplayString(_ctx.t("el.datepicker.confirm")), 1) ]) ])) : createCommentVNode("v-if", true) ]), _: 1 }, 8, ["name"]); } script$2.render = render$2; script$2.__file = "packages/time-picker/src/time-picker-com/panel-time-pick.vue"; const makeSelectRange = (start, end) => { const result = []; for (let i = start; i <= end; i++) { result.push(i); } return result; }; var script$3 = defineComponent({ components: { TimeSpinner: script$1 }, props: { visible: Boolean, actualVisible: Boolean, parsedValue: { type: [Array, String] }, format: { type: String, default: "" } }, emits: ["pick", "select-range", "set-picker-option"], setup(props, ctx) { const minDate = computed(() => props.parsedValue[0]); const maxDate = computed(() => props.parsedValue[1]); const oldValue = useOldValue(props); const handleCancel = () => { ctx.emit("pick", oldValue.value, null); }; const showSeconds = computed(() => { return props.format.includes("ss"); }); const amPmMode = computed(() => { if (props.format.includes("A")) return "A"; if (props.format.includes("a")) return "a"; return ""; }); const minSelectableRange = ref([]); const maxSelectableRange = ref([]); const handleConfirm = (visible = false) => { ctx.emit("pick", [minDate.value, maxDate.value], visible); }; const handleMinChange = (date) => { handleChange(date.millisecond(0), maxDate.value); }; const handleMaxChange = (date) => { handleChange(minDate.value, date.millisecond(0)); }; const isValidValue = (_date) => { const parsedDate = _date.map((_) => dayjs(_)); const result = getRangeAvailableTime(parsedDate); return parsedDate[0].isSame(result[0]) && parsedDate[1].isSame(result[1]); }; const handleChange = (_minDate, _maxDate) => { ctx.emit("pick", [_minDate, _maxDate], true); }; const btnConfirmDisabled = computed(() => { return minDate.value > maxDate.value; }); const selectionRange = ref([0, 2]); const setMinSelectionRange = (start, end) => { ctx.emit("select-range", start, end, "min"); selectionRange.value = [start, end]; }; const offset = computed(() => showSeconds.value ? 11 : 8); const setMaxSelectionRange = (start, end) => { ctx.emit("select-range", start, end, "max"); selectionRange.value = [start + offset.value, end + offset.value]; }; const changeSelectionRange = (step) => { const list = showSeconds.value ? [0, 3, 6, 11, 14, 17] : [0, 3, 8, 11]; const mapping = ["hours", "minutes"].concat(showSeconds.value ? ["seconds"] : []); const index = list.indexOf(selectionRange.value[0]); const next = (index + step + list.length) % list.length; const half = list.length / 2; if (next < half) { timePickerOptions["start_emitSelectRange"](mapping[next]); } else { timePickerOptions["end_emitSelectRange"](mapping[next - half]); } }; const handleKeydown = (event) => { const code = event.code; if (code === EVENT_CODE.left || code === EVENT_CODE.right) { const step = code === EVENT_CODE.left ? -1 : 1; changeSelectionRange(step); event.preventDefault(); return; } if (code === EVENT_CODE.up || code === EVENT_CODE.down) { const step = code === EVENT_CODE.up ? -1 : 1; const role = selectionRange.value[0] < offset.value ? "start" : "end"; timePickerOptions[`${role}_scrollDown`](step); event.preventDefault(); return; } }; const disabledHours_ = (role, compare) => { const defaultDisable = disabledHours ? disabledHours(role) : []; const isStart = role === "start"; const compareDate = compare || (isStart ? maxDate.value : minDate.value); const compareHour = compareDate.hour(); const nextDisable = isStart ? makeSelectRange(compareHour + 1, 23) : makeSelectRange(0, compareHour - 1); return union(defaultDisable, nextDisable); }; const disabledMinutes_ = (hour, role, compare) => { const defaultDisable = disabledMinutes ? disabledMinutes(hour, role) : []; const isStart = role === "start"; const compareDate = compare || (isStart ? maxDate.value : minDate.value); const compareHour = compareDate.hour(); if (hour !== compareHour) { return defaultDisable; } const compareMinute = compareDate.minute(); const nextDisable = isStart ? makeSelectRange(compareMinute + 1, 59) : makeSelectRange(0, compareMinute - 1); return union(defaultDisable, nextDisable); }; const disabledSeconds_ = (hour, minute, role, compare) => { const defaultDisable = disabledSeconds ? disabledSeconds(hour, minute, role) : []; const isStart = role === "start"; const compareDate = compare || (isStart ? maxDate.value : minDate.value); const compareHour = compareDate.hour(); const compareMinute = compareDate.minute(); if (hour !== compareHour || minute !== compareMinute) { return defaultDisable; } const compareSecond = compareDate.second(); const nextDisable = isStart ? makeSelectRange(compareSecond + 1, 59) : makeSelectRange(0, compareSecond - 1); return union(defaultDisable, nextDisable); }; const getRangeAvailableTime = (dates) => { return dates.map((_, index) => getRangeAvailableTimeEach(dates[0], dates[1], index === 0 ? "start" : "end")); }; const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } = getAvailableArrs(disabledHours_, disabledMinutes_, disabledSeconds_); const getRangeAvailableTimeEach = (startDate, endDate, role) => { const availableMap = { hour: getAvailableHours, minute: getAvailableMinutes, second: getAvailableSeconds }; const isStart = role === "start"; let result = isStart ? startDate : endDate; const compareDate = isStart ? endDate : startDate; ["hour", "minute", "second"].forEach((_) => { if (availableMap[_]) { let availableArr; const method = availableMap[_]; if (_ === "minute") { availableArr = method(result.hour(), role, compareDate); } else if (_ === "second") { availableArr = method(result.hour(), result.minute(), role, compareDate); } else { availableArr = method(role, compareDate); } if (availableArr && availableArr.length && !availableArr.includes(result[_]())) { const pos = isStart ? 0 : availableArr.length - 1; result = result[_](availableArr[pos]); } } }); return result; }; const parseUserInput = (value) => { if (!value) return null; if (Array.isArray(value)) { return value.map((_) => dayjs(_, props.format)); } return dayjs(value, props.format); }; const formatToString = (value) => { if (!value) return null; if (Array.isArray(value)) { return value.map((_) => _.format(props.format)); } return value.format(props.format); }; const getDefaultValue = () => { if (Array.isArray(defaultValue)) { return defaultValue.map((_) => dayjs(_)); } return [ dayjs(defaultValue), dayjs(defaultValue).add(60, "m") ]; }; ctx.emit("set-picker-option", ["formatToString", formatToString]); ctx.emit("set-picker-option", ["parseUserInput", parseUserInput]); ctx.emit("set-picker-option", ["isValidValue", isValidValue]); ctx.emit("set-picker-option", ["handleKeydown", handleKeydown]); ctx.emit("set-picker-option", ["getDefaultValue", getDefaultValue]); ctx.emit("set-picker-option", ["getRangeAvailableTime", getRangeAvailableTime]); const timePickerOptions = {}; const onSetOption = (e) => { timePickerOptions[e[0]] = e[1]; }; const pickerBase = inject("EP_PICKER_BASE"); const { arrowControl, disabledHours, disabledMinutes, disabledSeconds, defaultValue } = pickerBase.props; return { arrowControl, onSetOption, setMaxSelectionRange, setMinSelectionRange, btnConfirmDisabled, handleCancel, handleConfirm, t, showSeconds, minDate, maxDate, amPmMode, handleMinChange, handleMaxChange, minSelectableRange, maxSelectableRange, disabledHours_, disabledMinutes_, disabledSeconds_ }; } }); const _hoisted_1$3 = { key: 0, class: "el-time-range-picker el-picker-panel" }; const _hoisted_2$2 = { class: "el-time-range-picker__content" }; const _hoisted_3$1 = { class: "el-time-range-picker__cell" }; const _hoisted_4 = { class: "el-time-range-picker__header" }; const _hoisted_5 = { class: "el-time-range-picker__cell" }; const _hoisted_6 = { class: "el-time-range-picker__header" }; const _hoisted_7 = { class: "el-time-panel__fo