@dialpad/dialtone-vue
Version:
Vue component library for Dialpad's design system Dialtone
395 lines (394 loc) • 15.4 kB
JavaScript
import { DtIconChevronsRight as D, DtIconChevronRight as _, DtIconChevronsLeft as y, DtIconChevronLeft as m } from "@dialpad/dialtone-icons/vue2";
import { set as k, addMonths as $, subMonths as v, getMonth as c, getYear as l, getDate as R } from "date-fns";
import { formatMonth as E, getCalendarDays as b, calculateNextFocusDate as T, calculatePrevFocusDate as g, formatDate as A, getWeekDayNames as M } from "./utils.js";
import { INTL_MONTH_FORMAT as u, WEEK_START as C } from "./datepicker-constants.js";
import { DialtoneLocalization as d } from "../../localization/index.js";
import { n as i } from "../../_plugin-vue2_normalizer-DSLOjnn3.js";
import f from "../stack/stack.js";
import P from "../tooltip/tooltip.js";
import p from "../button/button.js";
import { warnIfUnmounted as I } from "../../common/utils/index.js";
const N = {
name: "DtDatepickerMonthYearPicker",
components: {
DtButton: p,
DtTooltip: P,
DtStack: f,
DtIconChevronLeft: m,
DtIconChevronsLeft: y,
DtIconChevronRight: _,
DtIconChevronsRight: D
},
props: {
selectedDate: {
type: Date,
required: !0
}
},
emits: [
/**
* Will retrieve the calendar days of the given date
*
* @event calendar-days
* @type {Array}
*/
"calendar-days",
/**
* Will focus first day in calendar
*
* @event focus-first-day
*/
"focus-first-day",
/**
* Will focus last day in calendar
*
* @event focus-last-day
*/
"focus-last-day",
/**
* Will close the datepicker
*
* @event close-datepicker
*/
"close-datepicker"
],
data() {
return {
selectMonth: c(this.selectedDate),
selectYear: l(this.selectedDate),
highlightedDay: null,
focusPicker: 0,
focusRefs: [],
refNames: ["prevYearButtonRef", "prevMonthButtonRef", "nextMonthButtonRef", "nextYearButtonRef"],
i18n: new d()
};
},
computed: {
// Get days for the currently selected month and year and highlight the selected day
calendarDays() {
return b(this.selectMonth, this.selectYear, this.highlightedDay);
},
formattedMonth() {
return (e) => E(e, u, this.i18n.currentLocale);
},
previousYearAriaLabel() {
return `${this.i18n.$t("DIALTONE_DATEPICKER_CHANGE_TO")} ${this.i18n.$t("DIALTONE_DATEPICKER_PREVIOUS_YEAR")} ${this.selectYear - 1}`;
},
previousMonthAriaLabel() {
return `${this.i18n.$t("DIALTONE_DATEPICKER_CHANGE_TO")} ${this.i18n.$t("DIALTONE_DATEPICKER_PREVIOUS_MONTH")} ${this.formattedMonth(this.selectMonth - 1)}`;
},
nextYearAriaLabel() {
return `${this.i18n.$t("DIALTONE_DATEPICKER_CHANGE_TO")} ${this.i18n.$t("DIALTONE_DATEPICKER_NEXT_YEAR")} ${this.selectYear + 1}`;
},
nextMonthAriaLabel() {
return `${this.i18n.$t("DIALTONE_DATEPICKER_CHANGE_TO")} ${this.i18n.$t("DIALTONE_DATEPICKER_NEXT_MONTH")} ${this.formattedMonth(this.selectMonth + 1)}`;
}
},
watch: {
selectMonth: {
handler() {
this.highlightDay(), this.$emit("calendar-days", this.calendarDays);
},
immediate: !0
},
selectYear: {
handler() {
this.highlightDay(), this.$emit("calendar-days", this.calendarDays);
},
immediate: !0
}
},
mounted() {
this.setButtonsRef(), this.focusMonthYearPicker();
},
methods: {
setButtonsRef() {
this.focusRefs = this.refNames.map((e) => this.$refs[e]);
},
focusMonthYearPicker() {
this.focusPicker = 0, this.focusRefs[0].$el.focus();
},
handleKeyDown(e) {
switch (e.key) {
case "ArrowLeft":
e.preventDefault(), this.focusPicker === 0 ? (this.focusPicker = 3, this.focusRefs[this.focusPicker].$el.focus()) : (this.focusPicker--, this.focusRefs[this.focusPicker].$el.focus());
break;
case "ArrowRight":
e.preventDefault(), this.focusPicker === 3 ? (this.focusPicker = 0, this.focusRefs[this.focusPicker].$el.focus()) : (this.focusPicker++, this.focusRefs[this.focusPicker].$el.focus());
break;
case "ArrowDown":
e.preventDefault(), this.$emit("focus-first-day");
break;
case "Tab":
e.preventDefault(), this.$emit("focus-first-day");
break;
case "Escape":
this.$emit("close-datepicker");
break;
}
},
highlightDay() {
const e = l(this.selectedDate), t = c(this.selectedDate);
e !== this.selectYear || t !== this.selectMonth ? this.highlightedDay = null : this.highlightedDay = R(this.selectedDate);
},
changeMonth(e) {
(this.selectMonth === 0 && e === -1 || this.selectMonth === 11 && e === 1) && (this.selectYear += e);
const t = k(this.selectedDate, { month: this.selectMonth, year: this.selectYear }), s = e === 1 ? $(t, 1) : v(t, 1);
this.selectMonth = c(s);
},
changeYear(e) {
this.selectYear = this.selectYear + e;
},
goToNextMonth() {
this.changeMonth(1);
},
goToPrevMonth() {
this.changeMonth(-1);
}
}
};
var Y = function() {
var t = this, s = t._self._c;
return s("dt-stack", { staticClass: "d-datepicker__month-year", attrs: { direction: "row", gap: "300" } }, [s("dt-stack", { staticClass: "d-datepicker__nav", attrs: { as: "nav", direction: "row", gap: "200" } }, [s("dt-tooltip", { attrs: { "fallback-placements": ["top-start", "auto"], message: t.i18n.$t("DIALTONE_DATEPICKER_PREVIOUS_YEAR"), placement: "top" }, scopedSlots: t._u([{ key: "anchor", fn: function() {
return [s("dt-button", { ref: t.refNames[0], staticClass: "d-datepicker__nav-btn", attrs: { id: "prevYearButton", "aria-label": t.previousYearAriaLabel, circle: !0, importance: "clear", kind: "muted", size: "xs", type: "button" }, on: { click: function(a) {
return t.changeYear(-1);
}, keydown: function(a) {
return t.handleKeyDown(a);
} } }, [s("dt-icon-chevrons-left", { attrs: { size: "200" } })], 1)];
}, proxy: !0 }]) }), s("dt-tooltip", { attrs: { "fallback-placements": ["top-start", "auto"], message: t.i18n.$t("DIALTONE_DATEPICKER_PREVIOUS_MONTH"), placement: "top" }, scopedSlots: t._u([{ key: "anchor", fn: function() {
return [s("dt-button", { ref: t.refNames[1], staticClass: "d-datepicker__nav-btn", attrs: { id: "prevMonthButton", "aria-label": t.previousMonthAriaLabel, circle: !0, importance: "clear", kind: "muted", size: "xs", type: "button" }, on: { click: function(a) {
return t.changeMonth(-1);
}, keydown: function(a) {
return t.handleKeyDown(a);
} } }, [s("dt-icon-chevron-left", { attrs: { size: "200" } })], 1)];
}, proxy: !0 }]) })], 1), s("div", { staticClass: "d-datepicker__month-year-title", attrs: { id: "calendar-heading" } }, [t._v(" " + t._s(t.formattedMonth(t.selectMonth)) + " " + t._s(t.selectYear) + " ")]), s("dt-stack", { staticClass: "d-datepicker__nav", attrs: { as: "nav", direction: "row", gap: "200" } }, [s("dt-tooltip", { attrs: { "fallback-placements": ["top-end", "auto"], message: t.i18n.$t("DIALTONE_DATEPICKER_NEXT_MONTH"), placement: "top" }, scopedSlots: t._u([{ key: "anchor", fn: function() {
return [s("dt-button", { ref: t.refNames[2], staticClass: "d-datepicker__nav-btn", attrs: { id: "nextMonthButton", "aria-label": t.nextMonthAriaLabel, circle: !0, importance: "clear", kind: "muted", size: "xs", type: "button" }, on: { click: function(a) {
return t.changeMonth(1);
}, keydown: function(a) {
return t.handleKeyDown(a);
} } }, [s("dt-icon-chevron-right", { attrs: { size: "200" } })], 1)];
}, proxy: !0 }]) }), s("dt-tooltip", { attrs: { "fallback-placements": ["top-end", "auto"], message: t.i18n.$t("DIALTONE_DATEPICKER_NEXT_YEAR"), placement: "top" }, scopedSlots: t._u([{ key: "anchor", fn: function() {
return [s("dt-button", { ref: t.refNames[3], staticClass: "d-datepicker__nav-btn", attrs: { id: "nextYearButton", "aria-label": t.nextYearAriaLabel, circle: !0, importance: "clear", kind: "muted", size: "xs", type: "button" }, on: { click: function(a) {
return t.changeYear(1);
}, keydown: function(a) {
return t.handleKeyDown(a);
} } }, [s("dt-icon-chevrons-right", { attrs: { size: "200" } })], 1)];
}, proxy: !0 }]) })], 1)], 1);
}, w = [], x = /* @__PURE__ */ i(
N,
Y,
w
);
const L = x.exports, O = {
name: "DtDatepickerCalendar",
components: { DtButton: p },
props: {
calendarDays: {
type: Array,
required: !0
}
},
emits: [
/**
* Event fired when a date is selected
*
* @event select-date
* @type {Date}
*/
"select-date",
/**
* Will focus the month and year picker
*
* @event focus-month-year-picker
*/
"focus-month-year-picker",
/**
* Will close the datepicker
*
* @event close-datepicker
*/
"close-datepicker"
],
data() {
return {
// local selectedDay to override the received by props calendarDays
selectedDay: null,
focusDay: 0,
daysRef: [],
i18n: new d()
};
},
computed: {
weekDays() {
return M(this.i18n.currentLocale, C);
}
},
watch: {
calendarDays() {
this.focusDay = 0, this.selectedDay = null, this.daysRef = [], this.$nextTick(() => {
this.daysRef = [], this.setDayRef();
});
}
},
methods: {
dayAriaLabel(e) {
return this.i18n.$t("DIALTONE_DATEPICKER_SELECT_DAY") + ` ${A(e.value, u, this.i18n.currentLocale)}`;
},
setDayRef() {
this.calendarDays.forEach((e, t) => {
e.days.forEach((s, a) => {
const n = `buttonRef_${t}_${a}`, r = this.$refs[n];
r && s.currentMonth && this.daysRef.push({ el: r[0], day: s });
});
});
},
handleKeyDown(e) {
switch (e.key) {
case "ArrowUp":
e.preventDefault(), this.focusDay -= 7;
try {
this.daysRef[this.focusDay].el.$el.focus();
} catch {
const t = g(this.daysRef[this.focusDay + 7].day.value);
this.$emit("go-to-prev-month"), this.$nextTick(() => {
this.setDayRef(), this.daysRef[t - 1].el.$el.focus(), this.focusDay += t - 1;
});
}
break;
case "ArrowDown":
e.preventDefault(), this.focusDay += 7;
try {
this.daysRef[this.focusDay].el.$el.focus();
} catch {
const t = T(this.daysRef[this.focusDay - 7].day.value);
this.$emit("go-to-next-month"), this.$nextTick(() => {
this.setDayRef(), this.daysRef[t - 1].el.$el.focus(), this.focusDay += t - 1;
});
}
break;
case "ArrowLeft":
e.preventDefault(), this.focusDay > 0 ? (this.focusDay -= 1, this.daysRef[this.focusDay].el.$el.focus()) : (this.$emit("go-to-prev-month"), this.$nextTick(() => {
this.focusLastDay();
}));
break;
case "ArrowRight":
e.preventDefault(), this.focusDay < this.daysRef.length - 1 ? (this.focusDay += 1, this.daysRef[this.focusDay].el.$el.focus()) : (this.$emit("go-to-next-month"), this.$nextTick(() => {
this.focusFirstDay();
}));
break;
case "Tab":
e.preventDefault(), this.$emit("focus-month-year-picker");
break;
case "Escape":
this.$emit("close-datepicker");
break;
}
},
focusFirstDay() {
this.focusDay = 0, this.$nextTick(() => {
this.daysRef[this.focusDay].el.$el.focus();
});
},
focusLastDay() {
this.$nextTick(() => {
this.focusDay = this.daysRef.length - 1, this.daysRef[this.focusDay].el.$el.focus();
});
},
selectDay(e) {
e.currentMonth && (this.selectedDay = e.text, this.$emit("select-date", e.value));
}
}
};
var K = function() {
var t = this, s = t._self._c;
return s("table", { staticClass: "d-datepicker__calendar", attrs: { "aria-labelledby": "calendar-heading" } }, [s("thead", [s("tr", t._l(t.weekDays, function(a) {
return s("th", { key: a, staticClass: "d-datepicker__cell d-datepicker__cell--header", attrs: { scope: "col" } }, [s("span", { staticClass: "d-datepicker__weekday", attrs: { title: a, "aria-label": a } }, [t._v(" " + t._s(a))])]);
}), 0)]), s("tbody", t._l(t.calendarDays, function(a, n) {
return s("tr", { key: n }, t._l(a.days, function(r, o) {
return s("td", { key: n + o, staticClass: "d-datepicker__cell", attrs: { role: "listbox" } }, [s("dt-button", { ref: `buttonRef_${n}_${o}`, refInFor: !0, staticClass: "d-datepicker__day", class: {
"d-datepicker__day--disabled": !r.currentMonth,
"d-datepicker__day--selected": t.selectedDay ? r.text === t.selectedDay && r.currentMonth : r.selected
}, attrs: { circle: !0, size: "sm", importance: "clear", disabled: !r.currentMonth, type: "button", "aria-selected": t.selectedDay ? r.text === t.selectedDay && r.currentMonth : r.selected, "aria-label": t.dayAriaLabel(r), role: "option" }, on: { click: function(h) {
return t.selectDay(r);
}, keydown: function(h) {
return t.handleKeyDown(h);
} } }, [t._v(" " + t._s(r.text) + " ")])], 1);
}), 0);
}), 0)]);
}, B = [], F = /* @__PURE__ */ i(
O,
K,
B
);
const z = F.exports, S = {
name: "DtDatepicker",
components: { DtStack: f, MonthYearPicker: L, Calendar: z },
props: {
/**
* Selected date
*
* @type {Date}
*/
selectedDate: {
type: Date,
default: () => /* @__PURE__ */ new Date()
}
},
emits: [
/**
* Event fired when a date is selected
*
* @event selected-date
* @type {Date}
*/
"selected-date",
/**
* Event fired when user presses the esc key
*
* @event close-datepicker
*/
"close-datepicker"
],
data() {
return {
calendarDays: []
};
},
mounted() {
I(this.$el, this.$options.name);
},
methods: {
updateCalendarDays(e) {
this.calendarDays = e;
}
}
};
var H = function() {
var t = this, s = t._self._c;
return s("dt-stack", { staticClass: "d-datepicker", attrs: { gap: "400" } }, [s("div", { staticClass: "d-datepicker__hd" }, [s("month-year-picker", { ref: "monthYearPicker", attrs: { "selected-date": t.selectedDate }, on: { "calendar-days": t.updateCalendarDays, "focus-first-day": function(a) {
return t.$refs.calendar.focusFirstDay();
}, "focus-last-day": function(a) {
return t.$refs.calendar.focusLastDay();
}, "close-datepicker": function(a) {
return t.$emit("close-datepicker");
} } })], 1), s("div", { staticClass: "d-datepicker__bd" }, [s("calendar", { ref: "calendar", attrs: { "calendar-days": t.calendarDays }, on: { "select-date": function(a) {
return t.$emit("selected-date", a);
}, "focus-month-year-picker": function(a) {
return t.$refs.monthYearPicker.focusMonthYearPicker();
}, "close-datepicker": function(a) {
return t.$emit("close-datepicker");
}, "go-to-next-month": function(a) {
return t.$refs.monthYearPicker.goToNextMonth();
}, "go-to-prev-month": function(a) {
return t.$refs.monthYearPicker.goToPrevMonth();
} } })], 1)]);
}, U = [], G = /* @__PURE__ */ i(
S,
H,
U
);
const st = G.exports;
export {
st as default
};
//# sourceMappingURL=datepicker.js.map