maz-ui
Version:
A standalone components library for Vue.Js 3 & Nuxt.Js 3
511 lines (510 loc) • 22.3 kB
JavaScript
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
};