element-plus
Version:
A Component Library for Vue 3
384 lines (381 loc) • 13.7 kB
JavaScript
import { defineComponent, ref, computed, nextTick, onMounted, watch, resolveComponent, resolveDirective, openBlock, createElementBlock, normalizeClass, Fragment, renderList, createBlock, withCtx, createTextVNode, toDisplayString, createCommentVNode, withDirectives, createVNode, createElementVNode } from 'vue';
import { debounce } from 'lodash-unified';
import '../../../../directives/index.mjs';
import { ElScrollbar } from '../../../scrollbar/index.mjs';
import { ElIcon } from '../../../icon/index.mjs';
import { ArrowUp, ArrowDown } from '@element-plus/icons-vue';
import '../../../../hooks/index.mjs';
import { getTimeLists } from './useTimePicker.mjs';
import _export_sfc from '../../../../_virtual/plugin-vue_export-helper.mjs';
import RepeatClick from '../../../../directives/repeat-click/index.mjs';
import { useNamespace } from '../../../../hooks/use-namespace/index.mjs';
const _sfc_main = defineComponent({
directives: {
repeatClick: RepeatClick
},
components: {
ElScrollbar,
ElIcon,
ArrowUp,
ArrowDown
},
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) {
const ns = useNamespace("time");
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) => {
const shouldShowAmPm = !!props.amPmMode;
if (!shouldShowAmPm)
return "";
const 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 getScrollbarElement = (el) => el.querySelector(`.${ns.namespace.value}-scrollbar__wrap`);
const adjustSpinner = (type, value) => {
if (props.arrowControl)
return;
const el = listRefsMap[type];
if (el && el.$el) {
getScrollbarElement(el.$el).scrollTop = Math.max(0, value * typeItemHeight(type));
}
};
const typeItemHeight = (type) => {
const el = listRefsMap[type];
return el.$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((getScrollbarElement(listRefsMap[type].$el).scrollTop - (scrollBarHeight(type) * 0.5 - 10) / typeItemHeight(type) + 3) / typeItemHeight(type)), type === "hours" ? 23 : 59);
modifyDateField(type, value);
};
const scrollBarHeight = (type) => {
return listRefsMap[type].$el.offsetHeight;
};
const bindScrollEvent = () => {
const bindFunction = (type) => {
if (listRefsMap[type] && listRefsMap[type].$el) {
getScrollbarElement(listRefsMap[type].$el).onscroll = () => {
handleScroll(type);
};
}
};
bindFunction("hours");
bindFunction("minutes");
bindFunction("seconds");
};
onMounted(() => {
nextTick(() => {
!props.arrowControl && bindScrollEvent();
adjustSpinners();
if (props.role === "start")
emitSelectRange("hours");
});
});
const setRef = (scrollbar, type) => {
listRefsMap[type] = scrollbar;
};
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 {
ns,
setRef,
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 = ["onClick"];
const _hoisted_2 = ["onMouseenter"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_el_scrollbar = resolveComponent("el-scrollbar");
const _component_arrow_up = resolveComponent("arrow-up");
const _component_el_icon = resolveComponent("el-icon");
const _component_arrow_down = resolveComponent("arrow-down");
const _directive_repeat_click = resolveDirective("repeat-click");
return openBlock(), createElementBlock("div", {
class: normalizeClass([_ctx.ns.b("spinner"), { "has-seconds": _ctx.showSeconds }])
}, [
!_ctx.arrowControl ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(_ctx.spinnerItems, (item) => {
return openBlock(), createBlock(_component_el_scrollbar, {
key: item,
ref_for: true,
ref: (scollbar) => _ctx.setRef(scollbar, item),
class: normalizeClass(_ctx.ns.be("spinner", "wrapper")),
"wrap-style": "max-height: inherit;",
"view-class": _ctx.ns.be("spinner", "list"),
noresize: "",
tag: "ul",
onMouseenter: ($event) => _ctx.emitSelectRange(item),
onMousemove: ($event) => _ctx.adjustCurrentSpinner(item)
}, {
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.listMap[item].value, (disabled, key) => {
return openBlock(), createElementBlock("li", {
key,
class: normalizeClass([
_ctx.ns.be("spinner", "item"),
_ctx.ns.is("active", key === _ctx.timePartsMap[item].value),
_ctx.ns.is("disabled", disabled)
]),
onClick: ($event) => _ctx.handleClick(item, { value: key, disabled })
}, [
item === "hours" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
createTextVNode(toDisplayString(("0" + (_ctx.amPmMode ? key % 12 || 12 : key)).slice(-2)) + toDisplayString(_ctx.getAmPmFlag(key)), 1)
], 2112)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
createTextVNode(toDisplayString(("0" + key).slice(-2)), 1)
], 2112))
], 10, _hoisted_1);
}), 128))
]),
_: 2
}, 1032, ["class", "view-class", "onMouseenter", "onMousemove"]);
}), 128)) : createCommentVNode("v-if", true),
_ctx.arrowControl ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(_ctx.spinnerItems, (item) => {
return openBlock(), createElementBlock("div", {
key: item,
class: normalizeClass([_ctx.ns.be("spinner", "wrapper"), _ctx.ns.is("arrow")]),
onMouseenter: ($event) => _ctx.emitSelectRange(item)
}, [
withDirectives((openBlock(), createBlock(_component_el_icon, {
class: normalizeClass(["arrow-up", _ctx.ns.be("spinner", "arrow")])
}, {
default: withCtx(() => [
createVNode(_component_arrow_up)
]),
_: 1
}, 8, ["class"])), [
[_directive_repeat_click, _ctx.onDecreaseClick]
]),
withDirectives((openBlock(), createBlock(_component_el_icon, {
class: normalizeClass(["arrow-down", _ctx.ns.be("spinner", "arrow")])
}, {
default: withCtx(() => [
createVNode(_component_arrow_down)
]),
_: 1
}, 8, ["class"])), [
[_directive_repeat_click, _ctx.onIncreaseClick]
]),
createElementVNode("ul", {
class: normalizeClass(_ctx.ns.be("spinner", "list"))
}, [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.arrowListMap[item].value, (time, key) => {
return openBlock(), createElementBlock("li", {
key,
class: normalizeClass([
_ctx.ns.be("spinner", "item"),
_ctx.ns.is("active", time === _ctx.timePartsMap[item].value),
_ctx.ns.is("disabled", _ctx.listMap[item].value[time])
])
}, [
typeof time === "number" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
item === "hours" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
createTextVNode(toDisplayString(("0" + (_ctx.amPmMode ? time % 12 || 12 : time)).slice(-2)) + toDisplayString(_ctx.getAmPmFlag(time)), 1)
], 2112)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
createTextVNode(toDisplayString(("0" + time).slice(-2)), 1)
], 2112))
], 2112)) : createCommentVNode("v-if", true)
], 2);
}), 128))
], 2)
], 42, _hoisted_2);
}), 128)) : createCommentVNode("v-if", true)
], 2);
}
var TimeSpinner = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "/home/runner/work/element-plus/element-plus/packages/components/time-picker/src/time-picker-com/basic-time-spinner.vue"]]);
export { TimeSpinner as default };
//# sourceMappingURL=basic-time-spinner.mjs.map