vue3-year-calendar
Version:
A customizable year calendar component for Vue 3 applications
217 lines (216 loc) • 8.9 kB
JavaScript
import { defineComponent as T, ref as z, computed as S, watch as U, createElementBlock as d, openBlock as m, normalizeClass as E, createElementVNode as v, withModifiers as W, toDisplayString as w, Fragment as D, renderList as g, normalizeStyle as R, createCommentVNode as q, createVNode as G } from "vue";
import u from "dayjs";
const H = { class: "yc-calendar__title" }, P = { class: "yc-calendar__body" }, Q = ["onMouseover", "onMousedown"], X = /* @__PURE__ */ T({
__name: "MonthCalendar",
props: {
activeDates: { default: () => [] },
month: { default: () => u().month() + 1 },
year: { default: () => u().year() },
lang: { default: "en" },
activeClass: { default: "red" },
prefixClass: { default: "yc-calendar--active" },
darkmode: { type: Boolean, default: !1 }
},
emits: ["toggleDate", "overDay"],
setup(p, { emit: f }) {
const t = p, l = f, y = z([]), i = z(!1), b = S(() => ({
tw: "16px",
en: "14px",
pt: "14px",
de: "14px",
es: "14px"
})[t.lang] ?? "14px"), Y = S(() => {
var s;
const e = {
tw: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
en: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
pt: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
de: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
es: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
};
return ((s = e[t.lang]) == null ? void 0 : s[Number(t.month) - 1]) ?? e.en[Number(t.month) - 1];
}), _ = () => {
if (!t.year || !t.month) {
y.value = [];
return;
}
const e = u().set("date", 1).set("year", Number(t.year)).set("month", Number(t.month) - 1);
let s = e.startOf("month").day() - 1;
s < 0 && (s += 7);
const c = e.endOf("month").date(), J = s >= 5 ? 6 : 5, $ = 7;
let F = 0;
const N = Array.from({ length: J * $ }, (k, h) => ({
value: s <= h ? ++F % (c + 1) || 1 : "",
active: !1,
isOtherMonth: s > h || F > c,
className: ""
})), L = ["red", "blue", "your_customized_classname", "custom-day"];
t.activeDates.forEach((k) => {
const h = typeof k == "string" ? { date: k, className: t.activeClass } : k, C = u(h.date);
if (C.year() !== Number(t.year) || C.month() + 1 !== Number(t.month)) return;
const V = C.date(), K = Math.floor((V - 1) / 7), x = (V - 1) % 7 + s + 7 * K;
if (N[x]) {
N[x].active = !0;
const I = h.className || t.activeClass || "red";
N[x].className = L.includes(I) ? I : "red";
}
}), y.value = N;
}, A = (e) => {
var c;
const s = {
tw: ["一", "二", "三", "四", "五", "六", "日"],
en: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
pt: ["2ª", "3ª", "4ª", "5ª", "6ª", "Sa", "Do"],
de: ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
es: ["Lu", "Ma", "Mi", "Ju", "Vi", "Sá", "Do"]
};
return ((c = s[t.lang]) == null ? void 0 : c[e - 1]) ?? s.en[e - 1];
}, M = (e) => {
if (e.isOtherMonth || !e.value) return;
const s = u().set("year", Number(t.year)).set("month", Number(t.month) - 1).set("date", Number(e.value)).format("YYYY-MM-DD");
l("toggleDate", {
date: s,
selected: !e.active,
className: t.activeClass || "red"
});
}, a = (e) => {
if (i.value && M(e), e.isOtherMonth || !e.value) return;
const s = u().set("year", Number(t.year)).set("month", Number(t.month) - 1).set("date", Number(e.value)).format("YYYY-MM-DD");
l("overDay", {
date: s,
selected: !e.active,
className: t.activeClass || "red"
});
}, n = (e) => {
M(e), i.value = !0;
}, o = () => {
i.value = !1;
}, r = (e) => {
const s = {
"yc-calendar__day--otherMonth": e.isOtherMonth,
[t.prefixClass]: e.active
};
return e.active && e.className && (s[e.className] = !0), s;
};
return U([() => t.year, () => t.month, () => t.activeDates], () => {
_();
}), _(), (e, s) => (m(), d("div", {
class: E(["yc-wrapper", { "yc-dark": e.darkmode }])
}, [
v("div", {
class: "yc-calendar",
onMouseup: o,
onMouseleave: W(o, ["stop"])
}, [
v("div", H, w(Y.value), 1),
v("div", P, [
(m(), d(D, null, g(7, (c) => v("div", {
key: `title${c}`,
class: "yc-calendar__day yc-day__weektitle",
style: R({ fontSize: b.value })
}, w(A(c)), 5)), 64)),
(m(!0), d(D, null, g(y.value, (c, J) => (m(), d("div", {
key: `day${J}`,
class: "yc-calendar__day"
}, [
v("div", {
class: E(["yc-day", r(c)]),
onMouseover: ($) => a(c),
onMousedown: ($) => n(c)
}, w(c.value), 43, Q)
]))), 128))
])
], 32)
], 2));
}
}), B = (p, f) => {
const t = p.__vccOpts || p;
for (const [l, y] of f)
t[l] = y;
return t;
}, Z = /* @__PURE__ */ B(X, [["__scopeId", "data-v-8b6a436b"]]), O = {
key: 0,
class: "yc-year"
}, j = ["onClick"], ee = { class: "yc-months" }, te = /* @__PURE__ */ T({
__name: "YearCalendar",
props: {
showYearSelector: { type: Boolean, default: !0 },
activeDates: { default: () => [] },
modelValue: { default: void 0 },
lang: { default: "en" },
activeClass: { default: "" },
prefixClass: { default: "yc-calendar--active" },
darkmode: { type: Boolean, default: !1 }
},
emits: ["update:modelValue", "update:activeDates", "toggleDate", "overDay"],
setup(p, { emit: f }) {
const t = p, l = f, y = z(t.activeDates.length && typeof t.activeDates[0] == "string"), i = S({
get: () => parseInt(String(t.modelValue)) || u().year(),
set: (a) => l("update:modelValue", a)
}), b = S(() => {
const a = {};
return t.activeDates.forEach((n) => {
const o = typeof n == "string" ? { date: n, className: t.activeClass } : { date: n.date, className: n.className ?? "" };
if (u(o.date).year() !== i.value) return;
const r = (u(o.date).month() + 1).toString();
a[r] || (a[r] = []), a[r].push(o);
}), a;
}), Y = (a) => {
i.value = a + i.value - 3;
}, _ = (a) => {
l("toggleDate", {
date: a.date,
selected: a.selected,
className: a.className
});
const n = [...t.activeDates], o = y.value ? a.date : { date: a.date, className: a.className }, r = n.findIndex((e) => (typeof e == "string" ? e : e.date) === a.date);
a.selected && r === -1 ? n.push(o) : !a.selected && r !== -1 && n.splice(r, 1), l("update:activeDates", n);
}, A = (a) => {
l("overDay", {
date: a.date,
selected: a.selected,
className: a.className
});
}, M = (a) => a.every((n) => {
const o = typeof n == "string" ? n : n.date;
if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(o)) return !1;
const [r, e, s] = o.split("-").map(Number);
if (r < 1e3 || r > 3e3 || e === 0 || e > 12) return !1;
const c = [31, r % 4 === 0 && r % 100 !== 0 || r % 400 === 0 ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return s > 0 && s <= c[e - 1];
});
return t.activeDates.length && !M(t.activeDates) && console.warn("Invalid activeDates provided"), (a, n) => (m(), d("div", {
class: E(["yc-container", { "yc-dark": a.darkmode }])
}, [
a.showYearSelector ? (m(), d("div", O, [
(m(), d(D, null, g(5, (o) => v("span", {
key: o,
class: "yc-year-chooser",
onClick: (r) => Y(o)
}, w(o + i.value - 3), 9, j)), 64))
])) : q("", !0),
v("div", ee, [
(m(), d(D, null, g(12, (o) => G(Z, {
class: "yc-month",
key: `month-${o}`,
year: i.value,
month: o,
"active-dates": b.value[o] ?? [],
"active-class": a.activeClass,
lang: a.lang,
"prefix-class": a.prefixClass,
darkmode: a.darkmode,
onToggleDate: _,
onOverDay: A
}, null, 8, ["year", "month", "active-dates", "active-class", "lang", "prefix-class", "darkmode"])), 64)),
(m(), d(D, null, g(5, (o) => v("div", {
key: `empty-${o}`,
class: "yc-month yc-empty"
})), 64))
])
], 2));
}
}), oe = /* @__PURE__ */ B(te, [["__scopeId", "data-v-5fa84686"]]);
export {
oe as YearCalendar
};