element-plus
Version:
A Component Library for Vue3.0
1,294 lines (1,275 loc) • 62 kB
JavaScript
import { defineComponent, inject, ref, watch, computed, provide, resolveComponent, resolveDirective, openBlock, createBlock, mergeProps, withCtx, withDirectives, createVNode, renderSlot, toDisplayString, withModifiers, onMounted, nextTick, Fragment, renderList, createTextVNode, createCommentVNode, Transition, h } from 'vue';
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import { ClickOutside, RepeatClick } from '../directives';
import ElInput from '../el-input';
import ElPopper from '../el-popper';
import { EVENT_CODE } from '../utils/aria';
import { useGlobalConfig } 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,
},
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: '',
},
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;
};
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 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;
ctx.emit('blur');
blurInput();
props.validateEvent && ((_a = elFormItem.formItemMitt) === null || _a === void 0 ? void 0 : _a.emit('el.form.blur'));
}
else {
valueOnOpen.value = props.modelValue;
}
});
const emitChange = val => {
var _a;
if (!valueEquals(val, valueOnOpen.value)) {
ctx.emit('change', val);
props.validateEvent && ((_a = elFormItem.formItemMitt) === null || _a === void 0 ? void 0 : _a.emit('el.form.change', val));
}
};
const emitInput = val => {
if (!valueEquals(props.modelValue, val)) {
ctx.emit('update:modelValue', 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);
emitChange(result);
};
const handleFocus = e => {
if (props.readonly || pickerDisabled.value)
return;
pickerVisible.value = true;
ctx.emit('focus', e);
};
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(_ => dayjs(_));
}
else {
result = dayjs(props.modelValue);
}
}
if (pickerOptions.value.getRangeAvaliableTime) {
result = pickerOptions.value.getRangeAvaliableTime(result);
}
return result;
});
const displayValue = computed(() => {
if (!pickerOptions.value.panelReady)
return;
if (!isTimePicker.value && valueIsEmpty.value)
return;
if (!pickerVisible.value && valueIsEmpty.value)
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 (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);
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 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(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) {
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) {
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 {
isDatesPicker,
handleEndChange,
handleStartChange,
handleStartInput,
handleEndInput,
onUserInput,
handleChange,
handleKeydown,
onClickOutside,
pickerSize,
isRangeInput,
onMouseLeave,
onMouseEnter,
onClearIconClick,
showClose,
triggerClass,
onPick,
handleFocus,
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}`,
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 /* CLASS */)
]),
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 /* CLASS */)
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["model-value", "name", "size", "disabled", "placeholder", "class", "readonly", "onInput", "onFocus", "onKeydown", "onChange", "onMouseenter", "onMouseleave"])), [
[_directive_clickoutside, _ctx.onClickOutside]
])
: 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 /* CLASS */),
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 /* PROPS, HYDRATE_EVENTS */, ["name", "placeholder", "value", "disabled", "readonly"]),
renderSlot(_ctx.$slots, "range-separator", {}, () => [
createVNode("span", _hoisted_1, toDisplayString(_ctx.rangeSeparator), 1 /* TEXT */)
]),
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 /* PROPS, HYDRATE_EVENTS */, ["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 /* CLASS */)
], 34 /* CLASS, HYDRATE_EVENTS */)), [
[_directive_clickoutside, _ctx.onClickOutside]
])
]),
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 /* STABLE */
}, 16 /* FULL_PROPS */, ["visible", "popper-class"]))
}
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 makeAvaliableArr = 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 getAvaliableArrs = (disabledHours, disabledMinutes, disabledSeconds) => {
const { getHoursList, getMinutesList, getSecondsList, } = getTimeLists(disabledHours, disabledMinutes, disabledSeconds);
const getAvaliableHours = (role, compare) => {
return makeAvaliableArr(getHoursList(role, compare));
};
const getAvaliableMinutes = (hour, role, compare) => {
return makeAvaliableArr(getMinutesList(hour, role, compare));
};
const getAvaliableSeconds = (hour, minute, role, compare) => {
return makeAvaliableArr(getSecondsList(hour, minute, role, compare));
};
return {
getAvaliableHours,
getAvaliableMinutes,
getAvaliableSeconds,
};
};
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 : undefined,
hour,
hour < 23 ? hour + 1 : undefined,
];
});
const arrowMinuteList = computed(() => {
const minute = minutes.value;
return [
minute > 0 ? minute - 1 : undefined,
minute,
minute < 59 ? minute + 1 : undefined,
];
});
const arrowSecondList = computed(() => {
const second = seconds.value;
return [
second > 0 ? second - 1 : undefined,
second,
second < 59 ? second + 1 : undefined,
];
});
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: 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 /* TEXT */)
], 64 /* STABLE_FRAGMENT */))
: (openBlock(), createBlock(Fragment, { key: 1 }, [
createTextVNode(toDisplayString(('0' + key).slice(-2)), 1 /* TEXT */)
], 64 /* STABLE_FRAGMENT */))
], 10 /* CLASS, PROPS */, ["onClick"]))
}), 128 /* KEYED_FRAGMENT */))
]),
_: 2 /* DYNAMIC */
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["onMouseenter", "onMousemove"]))
}), 128 /* KEYED_FRAGMENT */))
: 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 /* NEED_PATCH */), [
[_directive_repeat_click, _ctx.onDecreaseClick]
]),
withDirectives(createVNode("i", _hoisted_2, null, 512 /* NEED_PATCH */), [
[_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: key,
class: ["el-time-spinner__item", { 'active': time === _ctx.timePartsMap[item].value, 'disabled': _ctx.listMap[item].value[time] }]
}, toDisplayString(time === undefined ? '' : ('0' + (_ctx.amPmMode ? (time % 12 || 12) : time )).slice(-2) + _ctx.getAmPmFlag(time)), 3 /* TEXT, CLASS */))
}), 128 /* KEYED_FRAGMENT */))
])
], 40 /* PROPS, HYDRATE_EVENTS */, ["onMouseenter"]))
}), 128 /* KEYED_FRAGMENT */))
: createCommentVNode("v-if", true)
], 2 /* CLASS */))
}
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: undefined,
},
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 = ref(props.parsedValue);
const transitionName = computed(() => {
return props.actualVisible === undefined ? '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 = getRangeAvaliableTime(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 = getRangeAvaliableTime(_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;
timePickeOptions['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;
timePickeOptions['start_scrollDown'](step);
event.preventDefault();
return;
}
};
const getRangeAvaliableTime = (date) => {
const avaliableMap = {
hour: getAvaliableHours,
minute: getAvaliableMinutes,
second: getAvaliableSeconds,
};
let result = date;
['hour', 'minute', 'second'].forEach(_ => {
if (avaliableMap[_]) {
let avaliableArr;
const method = avaliableMap[_];
if (_ === 'minute') {
avaliableArr = method(result.hour(), props.datetimeRole);
}
else if (_ === 'second') {
avaliableArr = method(result.hour(), result.minute(), props.datetimeRole);
}
else {
avaliableArr = method(props.datetimeRole);
}
if (avaliableArr && avaliableArr.length && !avaliableArr.includes(result[_]())) {
result = result[_](avaliableArr[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', ['getRangeAvaliableTime', getRangeAvaliableTime]);
ctx.emit('set-picker-option', ['getDefaultValue', getDefaultValue]);
const timePickeOptions = {};
const onSetOption = e => {
timePickeOptions[e[0]] = e[1];
};
const pickerBase = inject('EP_PICKER_BASE');
const { arrowControl, disabledHours, disabledMinutes, disabledSeconds, defaultValue } = pickerBase.props;
const { getAvaliableHours, getAvaliableMinutes, getAvaliableSeconds, } = getAvaliableArrs(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 /* PROPS */, ["role", "arrow-control", "show-seconds", "am-pm-mode", "spinner-date", "disabled-hours", "disabled-minutes", "disabled-seconds", "onChange", "onSetOption", "onSelectRange"])
], 2 /* CLASS */),
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 /* TEXT */),
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 /* TEXT */)
])
]))
: createCommentVNode("v-if", true)
]),
_: 1 /* STABLE */
}, 8 /* PROPS */, ["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 = ref(props.parsedValue);
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 = getRangeAvaliableTime(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) {
timePickeOptions['start_emitSelectRange'](mapping[next]);
}
else {
timePickeOptions['end_emitSelectRange'](mapping[next - half]);
}
};
const handleKeydown = event => {
const code = even