UNPKG

@varlet/ui

Version:

A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.

711 lines (710 loc) • 26.8 kB
var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; import { computed, defineComponent, ref, watch } from "vue"; import { call, doubleRaf, error, isArray, 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 { MONTH_LIST, props, WEEK_HEADER } from "./props.mjs"; import DayPickerPanel from "./src/day-picker-panel.mjs"; import MonthPickerPanel from "./src/month-picker-panel.mjs"; import YearPickerPanel from "./src/year-picker-panel.mjs"; const { name, n, classes } = createNamespace("date-picker"); import { toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, renderSlot as _renderSlot, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, normalizeProps as _normalizeProps, mergeProps as _mergeProps, Transition as _Transition, withCtx as _withCtx, createVNode as _createVNode, normalizeStyle as _normalizeStyle, resolveComponent as _resolveComponent, createBlock as _createBlock } from "vue"; function __render__(_ctx, _cache) { var _a; const _component_year_picker_panel = _resolveComponent("year-picker-panel"); const _component_month_picker_panel = _resolveComponent("month-picker-panel"); const _component_day_picker_panel = _resolveComponent("day-picker-panel"); return _openBlock(), _createElementBlock( "div", { 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-select")) }, [ _createElementVNode( "div", { class: _normalizeClass(_ctx.n("title-hint")) }, _toDisplayString((_a = _ctx.hint) != null ? _a : (_ctx.pt ? _ctx.pt : _ctx.t)("datePickerHint")), 3 /* TEXT, CLASS */ ), _ctx.type !== "year" ? (_openBlock(), _createElementBlock( "div", { key: 0, class: _normalizeClass(_ctx.classes(_ctx.n("title-year"), [_ctx.isYearPanel, _ctx.n("title-year--active")])), onClick: _cache[0] || (_cache[0] = ($event) => _ctx.clickEl("year")) }, [ _renderSlot(_ctx.$slots, "year", { year: _ctx.chooseYear }, () => [ _createTextVNode( _toDisplayString(_ctx.chooseYear), 1 /* TEXT */ ) ]) ], 2 /* CLASS */ )) : _createCommentVNode("v-if", true) ], 2 /* CLASS */ ), _createElementVNode( "div", { class: _normalizeClass( _ctx.classes( _ctx.n("title-date"), [!_ctx.isYearPanel || _ctx.type === "year", _ctx.n("title-date--active")], [_ctx.range, _ctx.n("title-date--range")] ) ), onClick: _cache[1] || (_cache[1] = ($event) => _ctx.clickEl("date")) }, [ _createVNode(_Transition, { name: _ctx.multiple ? "" : `${_ctx.n()}${_ctx.reverse ? "-reverse" : ""}-translatey` }, { default: _withCtx(() => [ _ctx.type === "year" ? (_openBlock(), _createElementBlock("div", { key: `${_ctx.chooseYear}` }, [ _ctx.range ? _renderSlot(_ctx.$slots, "range", { key: 0, choose: _ctx.getChoose.chooseRangeYear }, () => [ _createTextVNode( _toDisplayString(_ctx.getYearTitle), 1 /* TEXT */ ) ]) : _ctx.multiple ? _renderSlot(_ctx.$slots, "multiple", { key: 1, choose: _ctx.getChoose.chooseYears }, () => [ _createTextVNode( _toDisplayString(_ctx.getYearTitle), 1 /* TEXT */ ) ]) : _renderSlot(_ctx.$slots, "year", { key: 2, year: _ctx.chooseYear }, () => [ _createTextVNode( _toDisplayString(_ctx.getYearTitle), 1 /* TEXT */ ) ]) ])) : _ctx.type === "month" ? (_openBlock(), _createElementBlock("div", { key: `${_ctx.chooseYear}${_ctx.chooseMonth}` }, [ _ctx.range ? _renderSlot(_ctx.$slots, "range", { key: 0, choose: _ctx.getChoose.chooseRangeMonth }, () => [ _createTextVNode( _toDisplayString(_ctx.getMonthTitle), 1 /* TEXT */ ) ]) : _ctx.multiple ? _renderSlot(_ctx.$slots, "multiple", { key: 1, choose: _ctx.getChoose.chooseMonths }, () => [ _createTextVNode( _toDisplayString(_ctx.getMonthTitle), 1 /* TEXT */ ) ]) : _renderSlot(_ctx.$slots, "month", { key: 2, month: _ctx.chooseMonth, year: _ctx.chooseYear }, () => [ _createTextVNode( _toDisplayString(_ctx.getMonthTitle), 1 /* TEXT */ ) ]) ])) : (_openBlock(), _createElementBlock("div", { key: `${_ctx.chooseYear}${_ctx.chooseMonth}${_ctx.chooseDay}` }, [ _ctx.range ? _renderSlot(_ctx.$slots, "range", { key: 0, choose: _ctx.formatRange }, () => [ _createTextVNode( _toDisplayString(_ctx.getDateTitle), 1 /* TEXT */ ) ]) : _ctx.multiple ? _renderSlot(_ctx.$slots, "multiple", { key: 1, choose: _ctx.getChoose.chooseDays }, () => [ _createTextVNode( _toDisplayString(_ctx.getDateTitle), 1 /* TEXT */ ) ]) : _renderSlot(_ctx.$slots, "date", _normalizeProps(_mergeProps({ key: 2 }, _ctx.slotProps)), () => [ _createTextVNode( _toDisplayString(_ctx.getDateTitle), 1 /* TEXT */ ) ]) ])) ]), _: 3 /* FORWARDED */ }, 8, ["name"]) ], 2 /* CLASS */ ) ], 6 /* CLASS, STYLE */ ), _createElementVNode( "div", { class: _normalizeClass(_ctx.n("body")), onTouchstart: _cache[2] || (_cache[2] = (...args) => _ctx.handleTouchstart && _ctx.handleTouchstart(...args)), onTouchmove: _cache[3] || (_cache[3] = (...args) => _ctx.handleTouchmove && _ctx.handleTouchmove(...args)), onTouchend: _cache[4] || (_cache[4] = (...args) => _ctx.handleTouchend && _ctx.handleTouchend(...args)) }, [ _createVNode(_Transition, { name: `${_ctx.n()}-panel-fade` }, { default: _withCtx(() => [ _ctx.getPanelType === "year" ? (_openBlock(), _createBlock(_component_year_picker_panel, { key: 0, ref: "yearPanelEl", choose: _ctx.getChoose, current: _ctx.currentDate, "component-props": _ctx.componentProps, preview: _ctx.previewYear, onChooseYear: _ctx.getChooseYear }, null, 8, ["choose", "current", "component-props", "preview", "onChooseYear"])) : _ctx.getPanelType === "month" ? (_openBlock(), _createBlock(_component_month_picker_panel, { key: 1, ref: "monthPanelEl", current: _ctx.currentDate, choose: _ctx.getChoose, preview: _ctx.getPreview, "click-year": () => _ctx.clickEl("year"), "component-props": _ctx.componentProps, onChooseMonth: _ctx.getChooseMonth, onCheckPreview: _ctx.checkPreview }, null, 8, ["current", "choose", "preview", "click-year", "component-props", "onChooseMonth", "onCheckPreview"])) : _ctx.getPanelType === "date" ? (_openBlock(), _createBlock(_component_day_picker_panel, { key: 2, ref: "dayPanelEl", current: _ctx.currentDate, choose: _ctx.getChoose, preview: _ctx.getPreview, "component-props": _ctx.componentProps, "click-month": () => _ctx.clickEl("month"), onChooseDay: _ctx.getChooseDay, onCheckPreview: _ctx.checkPreview }, null, 8, ["current", "choose", "preview", "component-props", "click-month", "onChooseDay", "onCheckPreview"])) : _createCommentVNode("v-if", true) ]), _: 1 /* STABLE */ }, 8, ["name"]) ], 34 /* CLASS, NEED_HYDRATION */ ), _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: { MonthPickerPanel, YearPickerPanel, DayPickerPanel }, props, setup(props2) { const { t: pt } = injectLocaleProvider(); const currentDate = dayjs().format("YYYY-MM-D"); const [currentYear, currentMonth] = currentDate.split("-"); const monthDes = MONTH_LIST.find((month) => month === currentMonth); const isYearPanel = ref(false); const isMonthPanel = ref(false); const rangeDone = ref(true); const chooseMonth = ref(); const chooseYear = ref(); const chooseDay = ref(); const previewMonth = ref(monthDes); const previewYear = ref(currentYear); const reverse = ref(false); const chooseYears = ref([]); const chooseMonths = ref([]); const chooseDays = ref([]); const chooseRangeYear = ref([]); const chooseRangeMonth = ref([]); const chooseRangeDay = ref([]); const yearPanelEl = ref(null); const monthPanelEl = ref(null); const dayPanelEl = ref(null); const componentProps = computed(() => ({ allowedDates: props2.allowedDates, type: props2.type, color: props2.color, firstDayOfWeek: props2.firstDayOfWeek, min: props2.min, max: props2.max, showCurrent: props2.showCurrent, multiple: props2.multiple, range: props2.range, buttonElevation: props2.buttonElevation })); const getChoose = computed(() => ({ chooseMonth: chooseMonth.value, chooseYear: chooseYear.value, chooseDay: chooseDay.value, chooseYears: chooseYears.value, chooseMonths: chooseMonths.value, chooseDays: chooseDays.value, chooseRangeYear: chooseRangeYear.value, chooseRangeMonth: chooseRangeMonth.value, chooseRangeDay: chooseRangeDay.value })); const getPreview = computed(() => ({ previewMonth: previewMonth.value, previewYear: previewYear.value })); const getYearTitle = computed(() => { var _a; const { multiple, range } = props2; if (range) { return chooseRangeYear.value.length ? `${chooseRangeYear.value[0]} ~ ${chooseRangeYear.value[1]}` : ""; } return multiple ? `${chooseYears.value.length}${(pt || t)("datePickerSelected")}` : (_a = chooseYear.value) != null ? _a : ""; }); const getMonthTitle = computed(() => { var _a, _b; const { multiple, range } = props2; if (range) { return chooseRangeMonth.value.length ? `${chooseRangeMonth.value[0]} ~ ${chooseRangeMonth.value[1]}` : ""; } let monthName = ""; if (chooseMonth.value) { monthName = (_b = (_a = (pt || t)("datePickerMonthDict")) == null ? void 0 : _a[chooseMonth.value].name) != null ? _b : ""; } return multiple ? `${chooseMonths.value.length}${(pt || t)("datePickerSelected")}` : monthName; }); const getDateTitle = computed(() => { var _a, _b, _c, _d; const { multiple, range } = props2; if (range) { const formatRangeDays = chooseRangeDay.value.map((date) => dayjs(date).format("YYYY-MM-DD")); return formatRangeDays.length ? `${formatRangeDays[0]} ~ ${formatRangeDays[1]}` : ""; } if (multiple) { return `${chooseDays.value.length}${(pt || t)("datePickerSelected")}`; } if (!chooseYear.value || !chooseMonth.value || !chooseDay.value) { return ""; } const weekIndex = dayjs(`${chooseYear.value}-${chooseMonth.value}-${chooseDay.value}`).day(); const week = WEEK_HEADER.find((value) => value === `${weekIndex}`); const weekName = (_b = (_a = (pt || t)("datePickerWeekDict")) == null ? void 0 : _a[week].name) != null ? _b : ""; const monthName = (_d = (_c = (pt || t)("datePickerMonthDict")) == null ? void 0 : _c[chooseMonth.value].name) != null ? _d : ""; const showDay = padStart(chooseDay.value, 2, "0"); if ((pt || t)("lang") === "zh-CN") { return `${chooseMonth.value}-${showDay} ${weekName.slice(0, 3)}`; } return `${weekName.slice(0, 3)}, ${monthName.slice(0, 3)} ${chooseDay.value}`; }); const getPanelType = computed(() => { if (props2.type === "year" || isYearPanel.value) { return "year"; } if (props2.type === "month" || isMonthPanel.value) { return "month"; } if (props2.type === "date") { return "date"; } return ""; }); const isUntouchable = computed(() => !props2.touchable || !getPanelType.value); const slotProps = computed(() => { var _a, _b; const weekIndex = dayjs(`${chooseYear.value}-${chooseMonth.value}-${chooseDay.value}`).day(); const date = chooseDay.value ? padStart(chooseDay.value, 2, "0") : ""; return { week: `${weekIndex}`, year: (_a = chooseYear.value) != null ? _a : "", month: (_b = chooseMonth.value) != null ? _b : "", date }; }); const formatRange = computed( () => getChoose.value.chooseRangeDay.map((choose) => dayjs(choose).format("YYYY-MM-DD")) ); const isSameYear = computed(() => chooseYear.value === previewYear.value); const isSameMonth = computed(() => chooseMonth.value === previewMonth.value); let startX = 0; let startY = 0; let checkType = ""; let touchDirection; watch( () => props2.modelValue, (value) => { if (!checkValue() || invalidFormatDate(value)) { return; } if (props2.range) { if (!isArray(value)) { return; } rangeDone.value = value.length !== 1; rangeInit(value, props2.type); } else if (props2.multiple) { if (!isArray(value)) { return; } multipleInit(value, props2.type); } else { dateInit(value); } }, { immediate: true } ); watch(getPanelType, resetState); function clickEl(type) { if (type === "year") { isYearPanel.value = true; } else if (type === "month") { isMonthPanel.value = true; } else { isYearPanel.value = false; isMonthPanel.value = false; } } function handleTouchstart(event) { if (isUntouchable.value) { return; } const { clientX, clientY } = event.touches[0]; startX = clientX; startY = clientY; } function getDirection(x, y) { return x >= y && x > 20 ? "x" : "y"; } function handleTouchmove(event) { if (isUntouchable.value) { return; } const { clientX, clientY } = event.touches[0]; const x = clientX - startX; const y = clientY - startY; touchDirection = getDirection(Math.abs(x), Math.abs(y)); checkType = x > 0 ? "prev" : "next"; } function handleTouchend() { return __async(this, null, function* () { if (isUntouchable.value || touchDirection !== "x") { return; } const componentRef = getPanelType.value === "year" ? yearPanelEl : getPanelType.value === "month" ? monthPanelEl : dayPanelEl; yield doubleRaf(); componentRef.value.forwardRef(checkType); resetState(); }); } function updateRange(date, type) { const rangeDate = type === "year" ? chooseRangeYear : type === "month" ? chooseRangeMonth : chooseRangeDay; rangeDate.value = rangeDone.value ? [date, date] : [rangeDate.value[0], date]; rangeDone.value = !rangeDone.value; if (rangeDone.value) { const isChangeOrder = dayjs(rangeDate.value[0]).isAfter(rangeDate.value[1]); const date2 = isChangeOrder ? [rangeDate.value[1], rangeDate.value[0]] : [...rangeDate.value]; call(props2["onUpdate:modelValue"], date2); call(props2.onChange, date2); } } function updateMultiple(date, type) { const multipleDates = type === "year" ? chooseYears : type === "month" ? chooseMonths : chooseDays; const formatType = type === "year" ? "YYYY" : type === "month" ? "YYYY-MM" : "YYYY-MM-DD"; const formatDates = multipleDates.value.map((date2) => dayjs(date2).format(formatType)); const index = formatDates.findIndex((choose) => choose === date); if (index === -1) { formatDates.push(date); } else { formatDates.splice(index, 1); } call(props2["onUpdate:modelValue"], formatDates); call(props2.onChange, formatDates); } function getReverse(dateType, date) { if (!chooseYear.value || !chooseMonth.value) { return false; } if (!isSameYear.value) { return chooseYear.value > previewYear.value; } if (dateType === "year") { return date < toNumber(chooseYear.value); } if (dateType === "month") { return date < chooseMonth.value; } return isSameMonth.value ? date < toNumber(chooseDay.value) : chooseMonth.value > previewMonth.value; } function getChooseDay(day) { const { readonly, range, multiple, onChange, "onUpdate:modelValue": updateModelValue } = props2; if (day < 0 || readonly) { return; } reverse.value = getReverse("day", day); const date = `${previewYear.value}-${previewMonth.value}-${day}`; const formatDate = dayjs(date).format("YYYY-MM-DD"); if (range) { updateRange(formatDate, "day"); } else if (multiple) { updateMultiple(formatDate, "day"); } else { call(updateModelValue, formatDate); call(onChange, formatDate); } } function getChooseMonth(month) { const { type, readonly, range, multiple, onChange, onPreview, "onUpdate:modelValue": updateModelValue } = props2; reverse.value = getReverse("month", month); if (type === "month" && !readonly) { const date = `${previewYear.value}-${month}`; if (range) { updateRange(date, "month"); } else if (multiple) { updateMultiple(date, "month"); } else { call(updateModelValue, date); call(onChange, date); } } else { previewMonth.value = month; call( onPreview, toNumber(previewYear.value), toNumber(previewMonth.value), type === "date" ? toNumber(chooseDay.value) : void 0 ); } isMonthPanel.value = false; } function getChooseYear(year) { const { type, readonly, range, multiple, onChange, onPreview, "onUpdate:modelValue": updateModelValue } = props2; reverse.value = getReverse("year", year); if (type === "year" && !readonly) { if (range) { updateRange(`${year}`, "year"); } else if (multiple) { updateMultiple(`${year}`, "year"); } else { call(updateModelValue, `${year}`); call(onChange, `${year}`); } } else { previewYear.value = `${year}`; call( onPreview, toNumber(previewYear.value), toNumber(previewMonth.value), type === "date" ? toNumber(chooseDay.value) : void 0 ); } isYearPanel.value = false; } function checkPreview(type, checkType2) { const changeValue = checkType2 === "prev" ? -1 : 1; if (type === "year") { previewYear.value = `${toNumber(previewYear.value) + changeValue}`; } else { let checkIndex = toNumber(previewMonth.value) + changeValue; if (checkIndex < 1) { previewYear.value = `${toNumber(previewYear.value) - 1}`; checkIndex = 12; } if (checkIndex > 12) { previewYear.value = `${toNumber(previewYear.value) + 1}`; checkIndex = 1; } previewMonth.value = MONTH_LIST.find((month) => toNumber(month) === checkIndex); } call( props2.onPreview, toNumber(previewYear.value), toNumber(previewMonth.value), props2.type === "date" ? toNumber(chooseDay.value) : void 0 ); } function checkValue() { if ((props2.multiple || props2.range) && !isArray(props2.modelValue)) { error("DatePicker", 'type of prop "modelValue" should be an Array'); return false; } if (!props2.multiple && !props2.range && isArray(props2.modelValue)) { error("DatePicker", 'type of prop "modelValue" should be a String'); return false; } return true; } function invalidFormatDate(date) { if (isArray(date)) { return false; } if (date === "Invalid Date") { error("DatePicker", '"modelValue" is an Invalid Date'); return true; } return false; } function rangeInit(value, type) { const rangeDate = type === "year" ? chooseRangeYear : type === "month" ? chooseRangeMonth : chooseRangeDay; const formatType = type === "year" ? "YYYY" : type === "month" ? "YYYY-MM" : "YYYY-MM-D"; const formatDateList = value.map((choose) => dayjs(choose).format(formatType)).slice(0, 2); const isValid = rangeDate.value.some((date) => invalidFormatDate(date)); if (isValid) { return; } rangeDate.value = formatDateList; const isChangeOrder = dayjs(rangeDate.value[0]).isAfter(rangeDate.value[1]); if (rangeDate.value.length === 2 && isChangeOrder) { rangeDate.value = [rangeDate.value[1], rangeDate.value[0]]; } } function multipleInit(value, type) { const rangeDate = type === "year" ? chooseYears : type === "month" ? chooseMonths : chooseDays; const formatType = type === "year" ? "YYYY" : type === "month" ? "YYYY-MM" : "YYYY-MM-D"; const formatDateList = Array.from(new Set(value.map((choose) => dayjs(choose).format(formatType)))); rangeDate.value = formatDateList.filter((date) => date !== "Invalid Date"); } function dateInit(value) { const handleValue = value ? dayjs(value) : dayjs(); const formatDate = handleValue.format("YYYY-MM-D"); if (invalidFormatDate(formatDate)) { return; } const [yearValue, monthValue, dayValue] = formatDate.split("-"); const monthDes2 = MONTH_LIST.find((month) => month === monthValue); chooseMonth.value = monthDes2; chooseYear.value = yearValue; chooseDay.value = dayValue; previewMonth.value = monthDes2; previewYear.value = yearValue; } function resetState() { startY = 0; startX = 0; checkType = ""; touchDirection = void 0; } return { yearPanelEl, monthPanelEl, dayPanelEl, reverse, currentDate, chooseMonth, chooseYear, chooseDay, previewYear, isYearPanel, isMonthPanel, getMonthTitle, getDateTitle, getYearTitle, getPanelType, getChoose, getPreview, componentProps, slotProps, formatRange, pt, t, n, classes, clickEl, handleTouchstart, handleTouchmove, handleTouchend, getChooseDay, getChooseMonth, getChooseYear, checkPreview, formatElevation }; } }); __sfc__.render = __render__; var stdin_default = __sfc__; export { stdin_default as default };