UNPKG

maz-ui

Version:

A standalone components library for Vue.Js 3 & Nuxt.Js 3

511 lines (510 loc) 22.3 kB
import { defineComponent, mergeModels, defineAsyncComponent, computed, useModel, useTemplateRef, onBeforeMount, ref, watch, createBlock, openBlock, unref, normalizeStyle, normalizeClass, withCtx, createVNode, renderSlot, withDirectives, mergeProps, createCommentVNode, vShow } from "vue"; import { MazChevronDown, MazCalendar, MazClock } from "@maz-ui/icons"; import { useTranslations } from "@maz-ui/translations"; import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; import isBetween from "dayjs/plugin/isBetween"; import { useInstanceUniqId } from "../composables/useInstanceUniqId.js"; import { r } from "./capitalize.CVQ1jDrh.js"; import weekday from "dayjs/plugin/weekday"; import { _ as _export_sfc } from "./_plugin-vue_export-helper.B--vMWp3.js"; import '../assets/MazDatePicker.C_X4aMTR.css';const a = { month: "short", day: "numeric", year: "numeric" }; function n(t, r2, o) { if (r2 === void 0) throw new TypeError("[maz-ui](FilterDate) The `locale` attribute is required."); if (typeof r2 != "string") throw new TypeError("[maz-ui](FilterDate) The `locale` attribute must be a string."); const i = o ?? a; try { const e = t instanceof Date ? t : new Date(t); return new Intl.DateTimeFormat(r2, i).format(e); } catch (e) { throw new Error(`[maz-ui](FilterDate) ${e}`); } } dayjs.extend(weekday); function getFormattedDate({ value, locale, options }) { const formattedDate = value ? n(value, locale, options) : void 0; return formattedDate ? r(formattedDate) : void 0; } function getRangeFormattedDate({ value, locale, options }) { const startValue = getFormattedDate({ value: value.start, locale, options }), endValue = getFormattedDate({ value: value.end, locale, options }); return startValue || endValue ? `${startValue || "..."} - ${endValue || "..."}` : void 0; } function getFirstDayOfMonth(value) { return dayjs(value).startOf("month").day(); } function getDaysOfWeek(locale, firstDayOfWeek) { const currentDate = dayjs().locale(locale), days = []; for (let i = 0; i < 7; i++) { const day = currentDate.day(i + firstDayOfWeek).toDate(), dayName = n(day, locale, { weekday: "short" }); dayName && days.push(dayName); } return days; } function getDaysInMonth(date) { return dayjs(date).daysInMonth(); } function isSameDate(date, date2, unit) { return dayjs(date).isSame(date2, unit); } function isSameDay(date, dayNumber) { return dayjs(date).day() === dayNumber; } function getISODate(value, format = "YYYY-MM-DD") { if (value) return dayjs(value).format(format); } function getRangeISODate(value, format = "YYYY-MM-DD") { if (value) return { start: getISODate(value.start, format), end: getISODate(value.end, format) }; } function checkValueWithMinMaxDates({ value, minDate, maxDate, format, minMaxAuto }) { return minMaxAuto ? minDate && dayjs(value).isBefore(minDate) ? { newValue: minDate, newCurrentDate: dayjs(minDate, format).format() } : maxDate && dayjs(value).isAfter(maxDate) ? { newValue: maxDate, newCurrentDate: dayjs(maxDate, format).format() } : { newValue: void 0, newCurrentDate: void 0 } : { newValue: value, newCurrentDate: value }; } function isValueDisabledWeekly({ value, disabledWeekly }) { return disabledWeekly.some((dayNumber) => isSameDay(value, dayNumber)); } function isValueDisabledDate({ value, disabledDates }) { return disabledDates.some((disabledDate) => dayjs(value).isSame(dayjs(disabledDate), "date")); } function scrollToTarget(scrollContainer, target, offset = 0, hasSmoothEffect = !0) { scrollContainer.scrollTo({ top: target.offsetTop - offset, behavior: hasSmoothEffect ? "smooth" : "auto" }); } function findNearestNumberInList(list, number) { return list.reduce((prev, curr) => Math.abs(curr - number) < Math.abs(prev - number) ? curr : prev); } function isRangeValue(value) { return !!value && typeof value == "object"; } function isValidDate(value) { return !!value && (typeof value == "string" || typeof value == "number" || value instanceof Date) && dayjs(value).isValid(); } function getDefaultsShortcuts(t) { return [ { label: t.lastSevenDays, identifier: "last7Days", value: { start: dayjs().subtract(6, "day").format("YYYY-MM-DD"), end: dayjs().format("YYYY-MM-DD") } }, { label: t.lastThirtyDays, identifier: "last30Days", value: { start: dayjs().subtract(29, "day").format("YYYY-MM-DD"), end: dayjs().format("YYYY-MM-DD") } }, { label: t.thisWeek, identifier: "thisWeek", value: { start: dayjs().startOf("week").format("YYYY-MM-DD"), end: dayjs().endOf("week").format("YYYY-MM-DD") } }, { label: t.lastWeek, identifier: "lastWeek", value: { start: dayjs().subtract(1, "week").startOf("week").format("YYYY-MM-DD"), end: dayjs().subtract(1, "week").endOf("week").format("YYYY-MM-DD") } }, { label: t.thisMonth, identifier: "thisMonth", value: { start: dayjs().set("date", 1).format("YYYY-MM-DD"), end: dayjs().set("date", dayjs().daysInMonth()).format("YYYY-MM-DD") } }, { label: t.thisYear, identifier: "thisYear", value: { start: dayjs().startOf("year").format("YYYY-MM-DD"), end: dayjs().endOf("year").format("YYYY-MM-DD") } }, { label: t.lastYear, identifier: "lastYear", value: { start: dayjs().subtract(1, "year").startOf("year").format("YYYY-MM-DD"), end: dayjs().subtract(1, "year").endOf("year").format("YYYY-MM-DD") } } ]; } const _sfc_main = /* @__PURE__ */ defineComponent({ inheritAttrs: !1, __name: "MazDatePicker", props: /* @__PURE__ */ mergeModels({ id: {}, style: {}, class: {}, inputProps: {}, modelValue: {}, format: { default: "YYYY-MM-DD" }, open: { type: Boolean, default: !1 }, label: {}, placeholder: {}, inputDateFormat: { default: () => ({ dateStyle: "medium", timeStyle: "full" }) }, inputDateTransformer: {}, locale: {}, hideHeader: { type: Boolean, default: !1 }, disabled: { type: Boolean, default: !1 }, firstDayOfWeek: { default: 0 }, autoClose: { type: Boolean, default: !1 }, customElementSelector: {}, double: { type: Boolean, default: !1 }, inline: { type: Boolean, default: !1 }, color: { default: "primary" }, pickerPosition: { default: "bottom-start" }, time: { type: Boolean, default: !1 }, onlyTime: { type: Boolean, default: !1 }, minuteInterval: { default: 5 }, useBrowserLocale: { type: Boolean, default: !0 }, fetchLocal: { type: Boolean, default: !0 }, shortcuts: { type: [Array, Boolean], default: !0 }, shortcut: {}, minDate: { default: void 0 }, maxDate: { default: void 0 }, minMaxAuto: { type: Boolean, default: !0 }, disabledWeekly: { default: () => [] }, disabledDates: { default: () => [] }, disabledHours: { default: () => [] }, block: { type: Boolean }, range: { type: Boolean, default: !1 }, transition: { default: "scale-fade" } }, { locale: { default: void 0 }, localeModifiers: {}, open: { default: !1 }, openModifiers: {} }), emits: /* @__PURE__ */ mergeModels(["update:model-value", "close"], ["update:locale", "update:open"]), setup(__props, { emit: __emit }) { const props = __props, emits = __emit, { t, locale } = useTranslations(); dayjs.extend(customParseFormat), dayjs.extend(isBetween); const MazInput = defineAsyncComponent(() => import("../components/MazInput.js")), MazPopover = defineAsyncComponent(() => import("../components/MazPopover.js")), MazPickerContainer = defineAsyncComponent(() => import("./MazPickerContainer.DmvGYSZC.js")), instanceId = useInstanceUniqId({ componentName: "MazDatePicker", providedId: props.id }), currentValue = computed({ get: () => typeof props.modelValue == "object" || props.range ? { start: typeof props.modelValue == "object" && props.modelValue.start ? dayjs(props.modelValue.start, props.format).format() : void 0, end: typeof props.modelValue == "object" && props.modelValue.end ? dayjs(props.modelValue.end, props.format).format() : void 0 } : typeof props.modelValue == "string" && props.modelValue ? dayjs(props.modelValue, props.format).format() : void 0, set: (value) => { if (props.disabled) return; const emittedValue = props.range && !isRangeValue(value) ? { start: value, end: void 0 } : value; emitValue(emittedValue); const isRangeMode2 = typeof value == "object" || props.range; props.autoClose && (!isRangeMode2 || isRangeMode2 && typeof value == "object" && value.end) && closeCalendar(); } }), hasTime = computed(() => props.time || props.onlyTime), hasDouble = computed(() => props.double && !props.onlyTime), hasDate = computed(() => !props.onlyTime), isRangeMode = computed(() => typeof currentValue.value == "object" || props.range), internalShortcuts = computed(() => !isRangeMode.value || props.shortcuts === !1 ? !1 : getDefaultsShortcuts({ lastSevenDays: t("datePicker.shortcuts.lastSevenDays"), lastThirtyDays: t("datePicker.shortcuts.lastThirtyDays"), thisWeek: t("datePicker.shortcuts.thisWeek"), lastWeek: t("datePicker.shortcuts.lastWeek"), thisMonth: t("datePicker.shortcuts.thisMonth"), thisYear: t("datePicker.shortcuts.thisYear"), lastYear: t("datePicker.shortcuts.lastYear") })), localeModel = useModel(__props, "locale"); localeModel.value = props.locale ?? locale.value; const containerUniqueId = computed(() => `MazDatePickerContainer-${instanceId.value}`), popoverRef = useTemplateRef("popover"); onBeforeMount(() => { isRangeMode.value && hasTime.value && console.error("[maz-ui](MazDatePicker) You can't use time picker with range picker"), hasTime.value && !(props.format.includes("h") || props.format.includes("H")) && console.error( '[maz-ui](MazDatePicker) When you use the time picker, you must provided a format with time - Ex: "YYYY-MM-DD HH:mm"' ), props.format.includes("h") && !(props.format.includes("a") || props.format.includes("A")) && console.error( '[maz-ui](MazDatePicker) if you use the 12 format "h" or "hh", you must add "a" or "A" at the end of the format - Ex: "YYYY-MM-DD hh:mm a"' ); }); function getCalendarDate(value) { const baseDate = (typeof value == "object" ? value.start : value) ?? dayjs().format(); return props.minDate && dayjs(baseDate).isBefore(props.minDate) ? props.minDate : props.maxDate && dayjs(baseDate).isAfter(props.maxDate) ? props.minDate ?? props.maxDate : baseDate; } const calendarDate = ref(getCalendarDate(currentValue.value)), isHour12 = computed( () => props.format.includes("a") || props.format.includes("A") || props.format.includes("h") ), formatterOptions = computed(() => ({ ...props.inputDateFormat, timeStyle: props.inputDateFormat.timeStyle ?? hasTime.value ? "short" : void 0, hour12: hasTime.value ? props.inputDateFormat.hour12 ?? isHour12.value : void 0 })), inputValue = computed(() => { if (!currentValue.value) return; let formattedDate; return props.onlyTime && typeof currentValue.value == "string" && currentValue.value ? formattedDate = currentValue.value ? n(dayjs(currentValue.value).format(), localeModel.value, { timeStyle: formatterOptions.value.timeStyle, hour12: formatterOptions.value.hour12 }) : void 0 : isRangeMode.value && isRangeValue(currentValue.value) ? formattedDate = getRangeFormattedDate({ value: currentValue.value, locale: localeModel.value, options: formatterOptions.value }) : typeof currentValue.value == "string" && currentValue.value && (formattedDate = getFormattedDate({ value: dayjs(currentValue.value).format(), locale: localeModel.value, options: formatterOptions.value })), props.inputDateTransformer && formattedDate ? props.inputDateTransformer({ formattedDate, value: props.modelValue, locale: localeModel.value }) : formattedDate; }), hasPickerOpen = useModel(__props, "open"); function closeCalendar() { popoverRef.value?.close(), emits("close"); } function checkMinMaxValues(value) { if (!(!props.minDate && !props.maxDate)) { if (!isRangeMode.value && (typeof value == "string" && value || !value)) { const { newValue, newCurrentDate } = checkValueWithMinMaxDates({ value, minDate: props.minDate, maxDate: props.maxDate, format: props.format, minMaxAuto: props.minMaxAuto }); newValue && emitValue(newValue), newCurrentDate && setCalendarDate(newCurrentDate); } else if (isRangeMode.value && isRangeValue(value)) { let newStartValue = value.start, newEndValue = value.end; if (value.start) { const { newValue, newCurrentDate } = checkValueWithMinMaxDates({ value: value.start, minDate: props.minDate, maxDate: props.maxDate, format: props.format, minMaxAuto: props.minMaxAuto }); newValue && (newStartValue = newValue), newCurrentDate && setCalendarDate(newCurrentDate); } if (value.end) { const { newValue } = checkValueWithMinMaxDates({ value: value.end, minDate: props.minDate, maxDate: props.maxDate, format: props.format, minMaxAuto: props.minMaxAuto }); newValue && (newEndValue = newValue); } emitValue({ start: newStartValue, end: newEndValue }); } } } function setCalendarDate(value) { value && !dayjs(calendarDate.value).isSame(value, "month") && (calendarDate.value = value); } function emitValue(value) { if (isRangeMode.value && (typeof value == "object" || value === void 0)) { const newValue = getRangeISODate(value, props.format) ?? { start: void 0, end: void 0 }; emits("update:model-value", newValue), newValue.start && setCalendarDate(newValue.start); } else (typeof value == "string" && value || value === void 0) && emits("update:model-value", getISODate(value, props.format)); } return watch( () => [currentValue.value, props.minDate, props.maxDate], (values, oldValues) => { const value = values[0], oldValue = oldValues?.[0]; typeof value == "object" && (value.start || value.end) ? (!oldValue || typeof oldValue == "object" && (oldValue.start !== value.start || oldValue.end !== value.end)) && (emitValue(value), checkMinMaxValues(value)) : typeof value == "string" && value && value !== oldValue && (emitValue(value), checkMinMaxValues(value)); }, { immediate: !0 } ), watch( () => [currentValue.value, props.disabledWeekly, props.disabledDates], (values) => { const value = values[0], disabledWeekly = values[1], disabledDates = values[2]; typeof value == "object" && (value.start || value.end) ? ((value.start && isValueDisabledWeekly({ value: value.start, disabledWeekly }) || value.start && isValueDisabledDate({ value: value.start, disabledDates }) || value.end && isValueDisabledWeekly({ value: value.end, disabledWeekly }) || value.end && isValueDisabledDate({ value: value.end, disabledDates })) && (currentValue.value = { start: void 0, end: void 0 }), (value.end && isValueDisabledWeekly({ value: value.end, disabledWeekly }) || value.end && isValueDisabledDate({ value: value.end, disabledDates })) && (currentValue.value = { start: value.start, end: void 0 })) : typeof value == "string" && value && (isValueDisabledWeekly({ value, disabledWeekly }) || isValueDisabledDate({ value, disabledDates })) && (currentValue.value = void 0); }, { immediate: !0 } ), (_ctx, _cache) => _ctx.inline ? (openBlock(), createBlock(unref(MazPickerContainer), { key: 1, id: containerUniqueId.value, modelValue: currentValue.value, "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => currentValue.value = $event), "calendar-date": calendarDate.value, "onUpdate:calendarDate": _cache[4] || (_cache[4] = ($event) => calendarDate.value = $event), color: _ctx.color, locale: localeModel.value, "has-date": hasDate.value, double: hasDouble.value, "has-time": hasTime.value, "formatter-options": formatterOptions.value, "hide-header": _ctx.hideHeader, "min-date": _ctx.minDate, format: _ctx.format, "is-hour12": isHour12.value, "max-date": _ctx.maxDate, "disabled-weekly": _ctx.disabledWeekly, inline: _ctx.inline, "first-day-of-week": _ctx.firstDayOfWeek, shortcuts: internalShortcuts.value, shortcut: _ctx.shortcut, disabled: _ctx.disabled, "disabled-hours": _ctx.disabledHours, "disabled-dates": _ctx.disabledDates, "minute-interval": _ctx.minuteInterval, range: isRangeMode.value, onClose: closeCalendar }, null, 8, ["id", "modelValue", "calendar-date", "color", "locale", "has-date", "double", "has-time", "formatter-options", "hide-header", "min-date", "format", "is-hour12", "max-date", "disabled-weekly", "inline", "first-day-of-week", "shortcuts", "shortcut", "disabled", "disabled-hours", "disabled-dates", "minute-interval", "range"])) : (openBlock(), createBlock(unref(MazPopover), { key: 0, id: `${unref(instanceId)}-popover`, ref: "popover", modelValue: hasPickerOpen.value, "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => hasPickerOpen.value = $event), class: normalizeClass(["m-date-picker m-reset-css", [ `m-date-picker--${_ctx.color}`, { "--is-open": hasPickerOpen.value, "--is-disabled": _ctx.disabled }, props.class ]]), style: normalizeStyle(_ctx.style), offset: 0, trigger: "click", transition: _ctx.transition, disabled: _ctx.disabled, block: _ctx.block, position: _ctx.pickerPosition, "prefer-position": "bottom-start", "fallback-position": "top-start", "position-reference": `#${unref(instanceId)}-popover .m-input-wrapper` }, { trigger: withCtx(({ isOpen, close, open: openPicker, toggle: togglePicker }) => [ renderSlot(_ctx.$slots, "trigger", { isOpen, close, open: openPicker, toggle: togglePicker }, () => [ withDirectives(createVNode(unref(MazInput), mergeProps({ id: unref(instanceId), "model-value": inputValue.value, readonly: "" }, { ..._ctx.inputProps, ..._ctx.$attrs }, { block: "", autocomplete: "off", class: "m-date-picker__input", label: _ctx.label, disabled: _ctx.disabled, placeholder: _ctx.placeholder, color: _ctx.color }), { "left-icon": withCtx(() => [ hasDate.value ? (openBlock(), createBlock(unref(MazCalendar), { key: 0, class: "maz-text-xl" })) : hasTime.value ? (openBlock(), createBlock(unref(MazClock), { key: 1, class: "maz-text-xl" })) : createCommentVNode("", !0) ]), "right-icon": withCtx(() => [ createVNode(unref(MazChevronDown), { class: "m-date-picker__button__chevron maz-text-lg" }) ]), _: 1 }, 16, ["id", "model-value", "label", "disabled", "placeholder", "color"]), [ [vShow, !_ctx.customElementSelector && !_ctx.inline] ]) ], !0) ]), default: withCtx(() => [ createVNode(unref(MazPickerContainer), { id: containerUniqueId.value, modelValue: currentValue.value, "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => currentValue.value = $event), "calendar-date": calendarDate.value, "onUpdate:calendarDate": _cache[1] || (_cache[1] = ($event) => calendarDate.value = $event), color: _ctx.color, locale: localeModel.value, "has-date": hasDate.value, double: hasDouble.value, "has-time": hasTime.value, "formatter-options": formatterOptions.value, "hide-header": _ctx.hideHeader, "min-date": _ctx.minDate, format: _ctx.format, "is-hour12": isHour12.value, "max-date": _ctx.maxDate, "disabled-weekly": _ctx.disabledWeekly, inline: _ctx.inline, "first-day-of-week": _ctx.firstDayOfWeek, shortcuts: internalShortcuts.value, shortcut: _ctx.shortcut, disabled: _ctx.disabled, "disabled-hours": _ctx.disabledHours, "disabled-dates": _ctx.disabledDates, "minute-interval": _ctx.minuteInterval, range: isRangeMode.value, onClose: closeCalendar }, null, 8, ["id", "modelValue", "calendar-date", "color", "locale", "has-date", "double", "has-time", "formatter-options", "hide-header", "min-date", "format", "is-hour12", "max-date", "disabled-weekly", "inline", "first-day-of-week", "shortcuts", "shortcut", "disabled", "disabled-hours", "disabled-dates", "minute-interval", "range"]) ]), _: 3 }, 8, ["id", "modelValue", "style", "class", "transition", "disabled", "block", "position", "position-reference"])); } }), MazDatePicker = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-84c8118b"]]); export { MazDatePicker as M, getDaysInMonth as a, getFirstDayOfMonth as b, isRangeValue as c, isValidDate as d, isSameDay as e, findNearestNumberInList as f, getDaysOfWeek as g, isSameDate as i, n, scrollToTarget as s };