@varlet/ui
Version:
A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.
486 lines (485 loc) • 16.8 kB
JavaScript
import { computed, defineComponent, reactive, ref, watch } from "vue";
import { call, getRect, preventDefault, toNumber } from "@varlet/shared";
import dayjs from "dayjs/esm/index.js";
import { t } from "../locale/index.mjs";
import { injectLocaleProvider } from "../locale-provider/provide.mjs";
import { createNamespace, formatElevation } from "../utils/components.mjs";
import { padStart } from "../utils/shared.mjs";
import Clock from "./clock.mjs";
import { hours24, hoursAmpm, props } from "./props.mjs";
import { getIsDisableMinute, getIsDisableSecond, getNumberTime } from "./utils.mjs";
const { name, n, classes } = createNamespace("time-picker");
import { toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, normalizeStyle as _normalizeStyle, resolveComponent as _resolveComponent, createBlock as _createBlock, Transition as _Transition, withCtx as _withCtx, createVNode as _createVNode, renderSlot as _renderSlot } from "vue";
function __render__(_ctx, _cache) {
var _a;
const _component_clock = _resolveComponent("clock");
return _openBlock(), _createElementBlock(
"div",
{
ref: "picker",
class: _normalizeClass(_ctx.classes(_ctx.n(), _ctx.formatElevation(_ctx.elevation, 2)))
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.n("title")),
style: _normalizeStyle({ background: _ctx.titleColor || _ctx.color })
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.n("title-hint"))
},
_toDisplayString((_a = _ctx.hint) != null ? _a : (_ctx.pt ? _ctx.pt : _ctx.t)("timePickerHint")),
3
/* TEXT, CLASS */
),
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.n("title-time-container"))
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.n("title-time"))
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.classes(_ctx.n("title-btn"), [_ctx.type === "hour", _ctx.n("title-btn--active")])),
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.checkPanel("hour"))
},
_toDisplayString(_ctx.time.hour),
3
/* TEXT, CLASS */
),
_createElementVNode(
"span",
{
class: _normalizeClass(_ctx.n("title-splitter"))
},
":",
2
/* CLASS */
),
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.classes(_ctx.n("title-btn"), [_ctx.type === "minute", _ctx.n("title-btn--active")])),
onClick: _cache[1] || (_cache[1] = ($event) => _ctx.checkPanel("minute"))
},
_toDisplayString(_ctx.time.minute),
3
/* TEXT, CLASS */
),
_ctx.useSeconds ? (_openBlock(), _createElementBlock(
"span",
{
key: 0,
class: _normalizeClass(_ctx.n("title-splitter"))
},
":",
2
/* CLASS */
)) : _createCommentVNode("v-if", true),
_ctx.useSeconds ? (_openBlock(), _createElementBlock(
"div",
{
key: 1,
class: _normalizeClass(_ctx.classes(_ctx.n("title-btn"), [_ctx.type === "second", _ctx.n("title-btn--active")])),
onClick: _cache[2] || (_cache[2] = ($event) => _ctx.checkPanel("second"))
},
_toDisplayString(_ctx.time.second),
3
/* TEXT, CLASS */
)) : _createCommentVNode("v-if", true)
],
2
/* CLASS */
),
_ctx.format === "ampm" ? (_openBlock(), _createElementBlock(
"div",
{
key: 0,
class: _normalizeClass(_ctx.n("title-ampm"))
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.classes(_ctx.n("title-btn"), [_ctx.ampm === "am", _ctx.n("title-btn--active")])),
onClick: _cache[3] || (_cache[3] = ($event) => _ctx.checkAmpm("am"))
},
" AM ",
2
/* CLASS */
),
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.classes(_ctx.n("title-btn"), [_ctx.ampm === "pm", _ctx.n("title-btn--active")])),
onClick: _cache[4] || (_cache[4] = ($event) => _ctx.checkAmpm("pm"))
},
" PM ",
2
/* CLASS */
)
],
2
/* CLASS */
)) : _createCommentVNode("v-if", true)
],
2
/* CLASS */
)
],
6
/* CLASS, STYLE */
),
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.n("body"))
},
[
_createElementVNode(
"div",
{
ref: "container",
class: _normalizeClass(_ctx.n("clock-container")),
onTouchstart: _cache[5] || (_cache[5] = (...args) => _ctx.moveHand && _ctx.moveHand(...args)),
onTouchmove: _cache[6] || (_cache[6] = (...args) => _ctx.moveHand && _ctx.moveHand(...args)),
onTouchend: _cache[7] || (_cache[7] = (...args) => _ctx.end && _ctx.end(...args))
},
[
_createVNode(_Transition, {
name: `${_ctx.n()}-panel-fade`
}, {
default: _withCtx(() => [
(_openBlock(), _createBlock(_component_clock, {
key: _ctx.type,
ref: "inner",
type: _ctx.type,
ampm: _ctx.ampm,
color: _ctx.color,
"is-inner": _ctx.isInner,
format: _ctx.format,
"allowed-time": _ctx.allowedTime,
rad: _ctx.getRad,
time: _ctx.time,
"prevent-next-update": _ctx.isPreventNextUpdate,
"use-seconds": _ctx.useSeconds,
max: _ctx.max,
min: _ctx.min,
onUpdate: _ctx.update,
onChangePreventUpdate: _ctx.changePreventUpdate
}, null, 8, ["type", "ampm", "color", "is-inner", "format", "allowed-time", "rad", "time", "prevent-next-update", "use-seconds", "max", "min", "onUpdate", "onChangePreventUpdate"]))
]),
_: 1
/* STABLE */
}, 8, ["name"])
],
34
/* CLASS, NEED_HYDRATION */
)
],
2
/* CLASS */
),
_ctx.$slots.actions ? (_openBlock(), _createElementBlock(
"div",
{
key: 0,
class: _normalizeClass(_ctx.n("actions"))
},
[
_renderSlot(_ctx.$slots, "actions")
],
2
/* CLASS */
)) : _createCommentVNode("v-if", true)
],
2
/* CLASS */
);
}
const __sfc__ = defineComponent({
name,
components: { Clock },
props,
setup(props2) {
const container = ref(null);
const picker = ref(null);
const inner = ref(null);
const isInner = ref(false);
const isPreventNextUpdate = ref(false);
const isActualInner = ref(false);
const isChosenUsableHour = ref(false);
const isChosenUsableMinute = ref(false);
const isDisableHour = ref(false);
const isDisableMinute = ref(false);
const minuteRad = ref(0);
const secondRad = ref(0);
const hourRad = ref();
const type = ref("hour");
const ampm = ref("am");
const time = ref({
hour: "00",
minute: "00",
second: "00"
});
const center = reactive({
x: 0,
y: 0
});
const innerRange = reactive({
x: [],
y: []
});
const getRad = computed(() => {
if (type.value === "hour") {
return hourRad.value;
}
if (type.value === "minute") {
return minuteRad.value;
}
return secondRad.value;
});
const { t: pt } = injectLocaleProvider();
watch(
() => props2.modelValue,
(value) => {
if (value === void 0 || value === "") {
resetTime();
return;
}
const { hour, minute, second } = getNumberTime(value);
const formatHour12 = dayjs().hour(hour).format("hh");
const formatHour24 = dayjs().hour(hour).format("HH");
const formatMinute = dayjs().minute(minute).format("mm");
const formatSecond = dayjs().second(second).format("ss");
hourRad.value = (formatHour12 === "12" ? 0 : toNumber(formatHour12)) * 30;
minuteRad.value = toNumber(formatMinute) * 6;
secondRad.value = toNumber(formatSecond) * 6;
time.value = getTime(value);
if (props2.format !== "24hr") {
ampm.value = padStart(`${hour}`, 2, "0") === formatHour24 && hours24.includes(formatHour24) ? "pm" : "am";
}
isInner.value = props2.format === "24hr" && hours24.includes(formatHour24);
},
{ immediate: true }
);
function resetTime() {
hourRad.value = void 0;
minuteRad.value = 0;
secondRad.value = 0;
time.value = {
hour: "00",
minute: "00",
second: "00"
};
ampm.value = "am";
}
function update(newTime) {
call(props2["onUpdate:modelValue"], newTime);
call(props2.onChange, newTime);
}
function rad2deg(rad) {
return rad * 57.29577951308232;
}
function checkPanel(panelType) {
isChosenUsableHour.value = false;
isDisableMinute.value = false;
type.value = panelType;
}
function findAvailableHour(ampm2) {
const { disableHour } = inner.value;
const index = hoursAmpm.findIndex((hour) => toNumber(hour) === toNumber(time.value.hour));
const hours = ampm2 === "am" ? hoursAmpm : hours24;
const realignmentHours = [...hours.slice(index), ...hours.slice(0, index)];
return realignmentHours.find((hour, index2) => {
isPreventNextUpdate.value = index2 !== 0;
return !disableHour.includes(hour);
});
}
function checkAmpm(ampmType) {
if (props2.readonly) {
return;
}
ampm.value = ampmType;
const newHour = findAvailableHour(ampmType);
if (!newHour) {
return;
}
const second = props2.useSeconds ? `:${time.value.second}` : "";
const newTime = `${padStart(newHour, 2, "0")}:${time.value.minute}${second}`;
update(newTime);
}
function getInner(clientX, clientY) {
const xIsInRange = clientX >= innerRange.x[0] && clientX <= innerRange.x[1];
const yIsInRange = clientY >= innerRange.y[0] && clientY <= innerRange.y[1];
return xIsInRange && yIsInRange;
}
function getTime(value) {
const hourFormat = props2.format === "24hr" ? "HH" : "hh";
const { hour, minute, second } = getNumberTime(value);
return {
hour: dayjs().hour(hour).format(hourFormat),
minute: dayjs().minute(minute).format("mm"),
second: dayjs().second(second).format("ss")
};
}
function getHourIndex(rad) {
const value = rad / 30;
return value >= 0 ? value : value + 12;
}
function getRangeSize() {
const { width: innerWidth, height: innerHeight } = inner.value.getSize();
const rangeXMin = center.x - innerWidth / 2 - 8;
const rangeXMax = center.x + innerWidth / 2 + 8;
const rangeYMin = center.y - innerHeight / 2 - 8;
const rangeYMax = center.y + innerHeight / 2 + 8;
return {
rangeXMin,
rangeXMax,
rangeYMin,
rangeYMax
};
}
function setHourRad(clientX, clientY, roundDeg) {
const { disableHour } = inner.value;
isActualInner.value = getInner(clientX, clientY);
const rad = Math.round(roundDeg / 30) * 30 + 90;
const index = getHourIndex(rad);
const anotherHour = isInner.value ? hoursAmpm[index] : hours24[index];
if (!disableHour.includes(anotherHour)) {
isInner.value = props2.format === "24hr" ? getInner(clientX, clientY) : false;
}
if (isInner.value !== isActualInner.value) {
return;
}
const newHour = isInner.value || ampm.value === "pm" ? hours24[index] : hoursAmpm[index];
isDisableHour.value = disableHour.includes(newHour);
if (isDisableHour.value) {
return;
}
hourRad.value = rad;
isChosenUsableHour.value = true;
}
function setMinuteRad(roundDeg) {
const { disableHour } = inner.value;
const rad = Math.round(roundDeg / 6) * 6 + 90;
const radToMin = rad / 6 >= 0 ? rad / 6 : rad / 6 + 60;
const values = {
time: radToMin,
format: props2.format,
ampm: ampm.value,
hour: time.value.hour,
max: props2.max,
min: props2.min,
disableHour,
allowedTime: props2.allowedTime
};
isDisableMinute.value = getIsDisableMinute(values);
if (isDisableMinute.value) {
return;
}
minuteRad.value = rad;
isChosenUsableMinute.value = true;
}
function setSecondRad(roundDeg) {
const { disableHour } = inner.value;
const rad = Math.round(roundDeg / 6) * 6 + 90;
const radToSec = rad / 6 >= 0 ? rad / 6 : rad / 6 + 60;
const values = {
time: radToSec,
format: props2.format,
ampm: ampm.value,
hour: time.value.hour,
minute: toNumber(time.value.minute),
max: props2.max,
min: props2.min,
disableHour,
allowedTime: props2.allowedTime
};
if (!getIsDisableSecond(values)) {
secondRad.value = rad;
}
}
function setCenterAndRange() {
const { left, top, width, height } = getRect(container.value);
center.x = left + width / 2;
center.y = top + height / 2;
if (type.value === "hour" && props2.format === "24hr") {
const { rangeXMin, rangeXMax, rangeYMin, rangeYMax } = getRangeSize();
innerRange.x = [rangeXMin, rangeXMax];
innerRange.y = [rangeYMin, rangeYMax];
}
}
function moveHand(event) {
preventDefault(event);
if (props2.readonly) {
return;
}
setCenterAndRange();
const { clientX, clientY } = event.touches[0];
const x = clientX - center.x;
const y = clientY - center.y;
const roundDeg = Math.round(rad2deg(Math.atan2(y, x)));
if (type.value === "hour") {
setHourRad(clientX, clientY, roundDeg);
} else if (type.value === "minute") {
setMinuteRad(roundDeg);
} else {
setSecondRad(roundDeg);
}
}
function end() {
if (props2.readonly) {
return;
}
if (type.value === "hour" && isChosenUsableHour.value) {
type.value = "minute";
return;
}
if (type.value === "minute" && props2.useSeconds && isChosenUsableMinute.value) {
type.value = "second";
}
}
function changePreventUpdate() {
isPreventNextUpdate.value = false;
}
return {
getRad,
time,
container,
inner,
picker,
isInner,
type,
ampm,
isPreventNextUpdate,
n,
classes,
t,
pt,
moveHand,
checkPanel,
checkAmpm,
end,
update,
changePreventUpdate,
formatElevation
};
}
});
__sfc__.render = __render__;
var stdin_default = __sfc__;
export {
stdin_default as default
};