UNPKG

buefy

Version:

Lightweight UI components for Vue.js (v3) based on Bulma

1,458 lines (1,450 loc) 77.4 kB
'use strict'; var vue = require('vue'); var CompatFallthroughMixin = require('./CompatFallthroughMixin-hhK0Gkhr.js'); var FormElementMixin = require('./FormElementMixin-DavX4iOv.js'); var helpers = require('./helpers.js'); var config = require('./config-DR826Ki2.js'); var Dropdown = require('./Dropdown-DtpKU9qf.js'); var DropdownItem = require('./DropdownItem-IMOKyRGV.js'); var Input = require('./Input-BcloGeZ3.js'); var Field = require('./Field-19ZCJFF8.js'); var Select = require('./Select-DayPKwCY.js'); var Icon = require('./Icon-lsDKE2wQ.js'); var _pluginVue_exportHelper = require('./_plugin-vue_export-helper-Die8u8yB.js'); var _sfc_main$3 = vue.defineComponent({ name: "BDatepickerTableRow", inject: { $datepicker: { name: "$datepicker", default: false } }, props: { selectedDate: { type: [Date, Array] }, hoveredDateRange: Array, day: { type: Number }, week: { type: Array, required: true }, month: { type: Number, required: true }, minDate: [Date, null], maxDate: [Date, null], disabled: Boolean, unselectableDates: [Array, Function, null], unselectableDaysOfWeek: [Array, null], selectableDates: [Array, Function, null], events: Array, indicators: String, dateCreator: Function, nearbyMonthDays: Boolean, nearbySelectableMonthDays: Boolean, showWeekNumber: Boolean, weekNumberClickable: Boolean, range: Boolean, multiple: Boolean, rulesForFirstWeek: Number, firstDayOfWeek: [Number, null] }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ "change-focus": (_day) => true, rangeHoverEndDate: (_day) => true, select: (_day) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, watch: { day(day) { const refName = `day-${this.month}-${day}`; this.$nextTick(() => { let cell; if (Array.isArray(this.$refs[refName])) { cell = this.$refs[refName][0]; } else { cell = this.$refs[refName]; } if (cell) { cell.focus(); } }); } }, methods: { firstWeekOffset(year, dow, doy) { const fwd = 7 + dow - doy; const firstJanuary = new Date(year, 0, fwd); const fwdlw = (7 + firstJanuary.getDay() - dow) % 7; return -fwdlw + fwd - 1; }, daysInYear(year) { return this.isLeapYear(year) ? 366 : 365; }, isLeapYear(year) { return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; }, getSetDayOfYear(input) { return Math.round((+input - +new Date(input.getFullYear(), 0, 1)) / 864e5) + 1; }, weeksInYear(year, dow, doy) { const weekOffset = this.firstWeekOffset(year, dow, doy); const weekOffsetNext = this.firstWeekOffset(year + 1, dow, doy); return (this.daysInYear(year) - weekOffset + weekOffsetNext) / 7; }, getWeekNumber(mom) { const dow = this.firstDayOfWeek; const doy = this.rulesForFirstWeek; const weekOffset = this.firstWeekOffset(mom.getFullYear(), dow, doy); const week = Math.floor((this.getSetDayOfYear(mom) - weekOffset - 1) / 7) + 1; let resWeek; let resYear; if (week < 1) { resYear = mom.getFullYear() - 1; resWeek = week + this.weeksInYear(resYear, dow, doy); } else if (week > this.weeksInYear(mom.getFullYear(), dow, doy)) { resWeek = week - this.weeksInYear(mom.getFullYear(), dow, doy); resYear = mom.getFullYear() + 1; } else { resYear = mom.getFullYear(); resWeek = week; } return { week: resWeek, year: resYear }; }, clickWeekNumber(weekData) { if (this.weekNumberClickable) { this.$datepicker.$emit("week-number-click", weekData.week, weekData.year); } }, /* * Check that selected day is within earliest/latest params and * is within this month */ selectableDate(day) { const validity = []; if (this.minDate) { validity.push(day >= this.minDate); } if (this.maxDate) { validity.push(day <= this.maxDate); } if (this.nearbyMonthDays && !this.nearbySelectableMonthDays) { validity.push(day.getMonth() === this.month); } if (this.selectableDates) { if (typeof this.selectableDates === "function") { if (this.selectableDates(day)) { return true; } else { validity.push(false); } } else { for (let i = 0; i < this.selectableDates.length; i++) { const enabledDate = this.selectableDates[i]; if (day.getDate() === enabledDate.getDate() && day.getFullYear() === enabledDate.getFullYear() && day.getMonth() === enabledDate.getMonth()) { return true; } else { validity.push(false); } } } } if (this.unselectableDates) { if (typeof this.unselectableDates === "function") { validity.push(!this.unselectableDates(day)); } else { for (let i = 0; i < this.unselectableDates.length; i++) { const disabledDate = this.unselectableDates[i]; validity.push( day.getDate() !== disabledDate.getDate() || day.getFullYear() !== disabledDate.getFullYear() || day.getMonth() !== disabledDate.getMonth() ); } } } if (this.unselectableDaysOfWeek) { for (let i = 0; i < this.unselectableDaysOfWeek.length; i++) { const dayOfWeek = this.unselectableDaysOfWeek[i]; validity.push(day.getDay() !== dayOfWeek); } } return validity.indexOf(false) < 0; }, /* * Emit select event with chosen date as payload */ emitChosenDate(day) { if (this.disabled) return; if (this.selectableDate(day)) { this.$emit("select", day); } }, // TODO: return undefined instead of boolean if no events eventsDateMatch(day) { if (!this.events || !this.events.length) return false; const dayEvents = []; for (let i = 0; i < this.events.length; i++) { if (this.events[i].date.getDay() === day.getDay()) { dayEvents.push(this.events[i]); } } if (!dayEvents.length) { return false; } return dayEvents; }, /* * Build classObject for cell using validations */ classObject(day) { function dateMatch(dateOne, dateTwo, multiple) { if (!dateOne || !dateTwo || multiple) { return false; } if (Array.isArray(dateTwo)) { return dateTwo.some((date) => dateOne.getDate() === date.getDate() && dateOne.getFullYear() === date.getFullYear() && dateOne.getMonth() === date.getMonth()); } return dateOne.getDate() === dateTwo.getDate() && dateOne.getFullYear() === dateTwo.getFullYear() && dateOne.getMonth() === dateTwo.getMonth(); } function dateWithin(dateOne, dates, multiple) { if (!Array.isArray(dates) || multiple) { return false; } return dateOne > dates[0] && dateOne < dates[1]; } return { "is-selected": dateMatch(day, this.selectedDate) || dateWithin(day, this.selectedDate, this.multiple), "is-first-selected": dateMatch( day, Array.isArray(this.selectedDate) ? this.selectedDate[0] : void 0, this.multiple ), "is-within-selected": dateWithin(day, this.selectedDate, this.multiple), "is-last-selected": dateMatch( day, Array.isArray(this.selectedDate) ? this.selectedDate[1] : void 0, this.multiple ), "is-within-hovered-range": this.hoveredDateRange && this.hoveredDateRange.length === 2 && (dateMatch(day, this.hoveredDateRange) || dateWithin(day, this.hoveredDateRange)), "is-first-hovered": dateMatch( day, Array.isArray(this.hoveredDateRange) ? this.hoveredDateRange[0] : void 0 ), "is-within-hovered": dateWithin(day, this.hoveredDateRange), "is-last-hovered": dateMatch( day, Array.isArray(this.hoveredDateRange) ? this.hoveredDateRange[1] : void 0 ), "is-today": dateMatch(day, this.dateCreator()), "is-selectable": this.selectableDate(day) && !this.disabled, "is-unselectable": !this.selectableDate(day) || this.disabled, "is-invisible": !this.nearbyMonthDays && day.getMonth() !== this.month, "is-nearby": this.nearbySelectableMonthDays && day.getMonth() !== this.month, "has-event": this.eventsDateMatch(day), [this.indicators]: this.eventsDateMatch(day) }; }, setRangeHoverEndDate(day) { if (this.range) { this.$emit("rangeHoverEndDate", day); } }, manageKeydown(event, weekDay) { const { key } = event; let preventDefault = true; switch (key) { case "Tab": { preventDefault = false; break; } case " ": case "Space": case "Spacebar": case "Enter": { this.emitChosenDate(weekDay); break; } case "ArrowLeft": case "Left": { this.changeFocus(weekDay, -1); break; } case "ArrowRight": case "Right": { this.changeFocus(weekDay, 1); break; } case "ArrowUp": case "Up": { this.changeFocus(weekDay, -7); break; } case "ArrowDown": case "Down": { this.changeFocus(weekDay, 7); break; } } if (preventDefault) { event.preventDefault(); } }, changeFocus(day, inc) { const nextDay = new Date(day.getTime()); nextDay.setDate(day.getDate() + inc); while ((!this.minDate || nextDay > this.minDate) && (!this.maxDate || nextDay < this.maxDate) && !this.selectableDate(nextDay)) { nextDay.setDate(nextDay.getDate() + Math.sign(inc)); } this.setRangeHoverEndDate(nextDay); this.$emit("change-focus", nextDay); } } }); const _hoisted_1$3 = { class: "datepicker-row" }; const _hoisted_2$3 = ["disabled", "onClick", "onMouseenter", "onKeydown", "tabindex"]; const _hoisted_3$2 = { key: 0, class: "events" }; const _hoisted_4$2 = { key: 0, class: "events" }; function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createCommentVNode(" eslint-disable max-len "), vue.createElementVNode("div", _hoisted_1$3, [ _ctx.showWeekNumber ? (vue.openBlock(), vue.createElementBlock( "a", { key: 0, class: vue.normalizeClass(["datepicker-cell is-week-number", { "is-clickable": _ctx.weekNumberClickable }]), onClick: _cache[0] || (_cache[0] = vue.withModifiers(($event) => _ctx.clickWeekNumber(_ctx.getWeekNumber(_ctx.week[6])), ["prevent"])) }, [ vue.createElementVNode( "span", null, vue.toDisplayString(_ctx.getWeekNumber(_ctx.week[6]).week), 1 /* TEXT */ ) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true), (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.week, (weekDay, index) => { return vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: index }, [ _ctx.selectableDate(weekDay) && !_ctx.disabled ? (vue.openBlock(), vue.createElementBlock("a", { key: 0, ref_for: true, ref: `day-${weekDay.getMonth()}-${weekDay.getDate()}`, class: vue.normalizeClass([_ctx.classObject(weekDay), "datepicker-cell"]), role: "button", href: "#", disabled: _ctx.disabled || void 0, onClick: vue.withModifiers(($event) => _ctx.emitChosenDate(weekDay), ["prevent"]), onMouseenter: ($event) => _ctx.setRangeHoverEndDate(weekDay), onKeydown: ($event) => _ctx.manageKeydown($event, weekDay), tabindex: _ctx.day === weekDay.getDate() && _ctx.month === weekDay.getMonth() ? void 0 : -1 }, [ vue.createElementVNode( "span", null, vue.toDisplayString(weekDay.getDate()), 1 /* TEXT */ ), _ctx.eventsDateMatch(weekDay) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$2, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.eventsDateMatch(weekDay), (event, evIdx) => { return vue.openBlock(), vue.createElementBlock( "div", { class: vue.normalizeClass(["event", event.type]), key: evIdx }, null, 2 /* CLASS */ ); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ], 42, _hoisted_2$3)) : (vue.openBlock(), vue.createElementBlock( "div", { key: 1, class: vue.normalizeClass([_ctx.classObject(weekDay), "datepicker-cell"]) }, [ vue.createElementVNode( "span", null, vue.toDisplayString(weekDay.getDate()), 1 /* TEXT */ ), _ctx.eventsDateMatch(weekDay) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$2, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.eventsDateMatch(weekDay), (event, evIdx) => { return vue.openBlock(), vue.createElementBlock( "div", { class: vue.normalizeClass(["event", event.type]), key: evIdx }, null, 2 /* CLASS */ ); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ )) ], 64 /* STABLE_FRAGMENT */ ); }), 128 /* KEYED_FRAGMENT */ )) ]), vue.createCommentVNode(" eslint-enable max-len ") ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */ ); } var BDatepickerTableRow = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$3, [["render", _sfc_render$3]]); var _sfc_main$2 = vue.defineComponent({ name: "BDatepickerTable", components: { BDatepickerTableRow }, props: { modelValue: { type: [Date, Array, null] }, dayNames: [Array, null], monthNames: [Array, null], firstDayOfWeek: [Number, null], events: Array, indicators: String, minDate: [Date, null], maxDate: [Date, null], focused: Object, disabled: Boolean, dateCreator: Function, unselectableDates: [Array, Function, null], unselectableDaysOfWeek: [Array, null], selectableDates: [Array, Function, null], nearbyMonthDays: Boolean, nearbySelectableMonthDays: Boolean, showWeekNumber: Boolean, weekNumberClickable: Boolean, rulesForFirstWeek: Number, range: Boolean, multiple: Boolean }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ "range-end": (_date) => true, "range-start": (_date) => true, "update:focused": (_focused) => true, "update:modelValue": (_value) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, data() { return { selectedBeginDate: void 0, selectedEndDate: void 0, hoveredEndDate: void 0 }; }, computed: { multipleSelectedDates: { get() { return this.multiple && this.modelValue ? this.modelValue : []; }, set(value) { this.$emit("update:modelValue", value); } }, visibleDayNames() { const visibleDayNames = []; let index = this.firstDayOfWeek; while (visibleDayNames.length < this.dayNames.length) { const currentDayName = this.dayNames[index % this.dayNames.length]; visibleDayNames.push(currentDayName); index++; } if (this.showWeekNumber) visibleDayNames.unshift(""); return visibleDayNames; }, hasEvents() { return this.events && this.events.length; }, /* * Return array of all events in the specified month */ eventsInThisMonth() { if (!this.events) return []; const monthEvents = []; for (let i = 0; i < this.events.length; i++) { let event = this.events[i]; if (!Object.prototype.hasOwnProperty.call(event, "date")) { event = { date: event, type: "is-primary" }; } if (!Object.prototype.hasOwnProperty.call(event, "type")) { event.type = "is-primary"; } if (event.date.getMonth() === this.focused.month && event.date.getFullYear() === this.focused.year) { monthEvents.push(event); } } return monthEvents; }, /* * Return array of all weeks in the specified month */ weeksInThisMonth() { this.validateFocusedDay(); const month = this.focused.month; const year = this.focused.year; const weeksInThisMonth = []; let startingDay = 1; while (weeksInThisMonth.length < 6) { const newWeek = this.weekBuilder(startingDay, month, year); weeksInThisMonth.push(newWeek); startingDay += 7; } return weeksInThisMonth; }, hoveredDateRange() { var _a, _b; if (!this.range) { return []; } if (!isNaN((_b = (_a = this.selectedEndDate) == null ? void 0 : _a.valueOf()) != null ? _b : NaN)) { return []; } if (this.hoveredEndDate < this.selectedBeginDate) { return [this.hoveredEndDate, this.selectedBeginDate].filter(helpers.isDefined); } return [this.selectedBeginDate, this.hoveredEndDate].filter(helpers.isDefined); }, disabledOrUndefined() { return this.disabled || void 0; } }, methods: { /* * Emit input event with selected date as payload for v-model in parent */ updateSelectedDate(date) { if (!this.range && !this.multiple) { this.$emit("update:modelValue", date); } else if (this.range) { this.handleSelectRangeDate(date); } else if (this.multiple) { this.handleSelectMultipleDates(date); } }, /* * If both begin and end dates are set, reset the end date and set the begin date. * If only begin date is selected, emit an array of the begin date and the new date. * If not set, only set the begin date. */ handleSelectRangeDate(date) { if (this.selectedBeginDate && this.selectedEndDate) { this.selectedBeginDate = date; this.selectedEndDate = void 0; this.$emit("range-start", date); } else if (this.selectedBeginDate && !this.selectedEndDate) { if (this.selectedBeginDate > date) { this.selectedEndDate = this.selectedBeginDate; this.selectedBeginDate = date; } else { this.selectedEndDate = date; } this.$emit("range-end", date); this.$emit("update:modelValue", [this.selectedBeginDate, this.selectedEndDate]); } else { this.selectedBeginDate = date; this.$emit("range-start", date); } }, /* * If selected date already exists list of selected dates, remove it from the list * Otherwise, add date to list of selected dates */ handleSelectMultipleDates(date) { const multipleSelect = this.multipleSelectedDates.filter( (selectedDate) => selectedDate.getDate() === date.getDate() && selectedDate.getFullYear() === date.getFullYear() && selectedDate.getMonth() === date.getMonth() ); if (multipleSelect.length) { this.multipleSelectedDates = this.multipleSelectedDates.filter( (selectedDate) => selectedDate.getDate() !== date.getDate() || selectedDate.getFullYear() !== date.getFullYear() || selectedDate.getMonth() !== date.getMonth() ); } else { this.multipleSelectedDates = [...this.multipleSelectedDates, date]; } }, /* * Return array of all days in the week that the startingDate is within */ weekBuilder(startingDate, month, year) { const thisMonth = new Date(year, month); const thisWeek = []; const dayOfWeek = new Date(year, month, startingDate).getDay(); const end = dayOfWeek >= this.firstDayOfWeek ? dayOfWeek - this.firstDayOfWeek : 7 - this.firstDayOfWeek + dayOfWeek; let daysAgo = 1; for (let i = 0; i < end; i++) { thisWeek.unshift( new Date( thisMonth.getFullYear(), thisMonth.getMonth(), startingDate - daysAgo ) ); daysAgo++; } thisWeek.push(new Date(year, month, startingDate)); let daysForward = 1; while (thisWeek.length < 7) { thisWeek.push(new Date(year, month, startingDate + daysForward)); daysForward++; } return thisWeek; }, validateFocusedDay() { const focusedDate = new Date(this.focused.year, this.focused.month, this.focused.day); if (this.selectableDate(focusedDate)) return; let day = 0; const monthDays = new Date(this.focused.year, this.focused.month + 1, 0).getDate(); let firstFocusable = null; while (!firstFocusable && ++day < monthDays) { const date = new Date(this.focused.year, this.focused.month, day); if (this.selectableDate(date)) { firstFocusable = focusedDate; const focused = { day: date.getDate(), month: date.getMonth(), year: date.getFullYear() }; this.$emit("update:focused", focused); } } }, /* * Check that selected day is within earliest/latest params and * is within this month */ selectableDate(day) { const validity = []; if (this.minDate) { validity.push(day >= this.minDate); } if (this.maxDate) { validity.push(day <= this.maxDate); } if (this.nearbyMonthDays && !this.nearbySelectableMonthDays) { validity.push(day.getMonth() === this.focused.month); } if (this.selectableDates) { if (typeof this.selectableDates === "function") { if (this.selectableDates(day)) { return true; } else { validity.push(false); } } else { for (let i = 0; i < this.selectableDates.length; i++) { const enabledDate = this.selectableDates[i]; if (day.getDate() === enabledDate.getDate() && day.getFullYear() === enabledDate.getFullYear() && day.getMonth() === enabledDate.getMonth()) { return true; } else { validity.push(false); } } } } if (this.unselectableDates) { if (typeof this.unselectableDates === "function") { validity.push(!this.unselectableDates(day)); } else { for (let i = 0; i < this.unselectableDates.length; i++) { const disabledDate = this.unselectableDates[i]; validity.push( day.getDate() !== disabledDate.getDate() || day.getFullYear() !== disabledDate.getFullYear() || day.getMonth() !== disabledDate.getMonth() ); } } } if (this.unselectableDaysOfWeek) { for (let i = 0; i < this.unselectableDaysOfWeek.length; i++) { const dayOfWeek = this.unselectableDaysOfWeek[i]; validity.push(day.getDay() !== dayOfWeek); } } return validity.indexOf(false) < 0; }, eventsInThisWeek(week) { return this.eventsInThisMonth.filter((event) => { const stripped = new Date(Date.parse(event.date + "")); stripped.setHours(0, 0, 0, 0); const timed = stripped.getTime(); return week.some((weekDate) => weekDate.getTime() === timed); }); }, setRangeHoverEndDate(day) { this.hoveredEndDate = day; }, changeFocus(day) { const focused = { day: day.getDate(), month: day.getMonth(), year: day.getFullYear() }; this.$emit("update:focused", focused); } } }); const _hoisted_1$2 = { class: "datepicker-table" }; const _hoisted_2$2 = { class: "datepicker-header" }; function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { const _component_b_datepicker_table_row = vue.resolveComponent("b-datepicker-table-row"); return vue.openBlock(), vue.createElementBlock("section", _hoisted_1$2, [ vue.createElementVNode("header", _hoisted_2$2, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.visibleDayNames, (day, index) => { return vue.openBlock(), vue.createElementBlock("div", { key: index, class: "datepicker-cell" }, [ vue.createElementVNode( "span", null, vue.toDisplayString(day), 1 /* TEXT */ ) ]); }), 128 /* KEYED_FRAGMENT */ )) ]), vue.createElementVNode( "div", { class: vue.normalizeClass(["datepicker-body", { "has-events": _ctx.hasEvents }]) }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.weeksInThisMonth, (week, index) => { return vue.openBlock(), vue.createBlock(_component_b_datepicker_table_row, { key: index, "selected-date": _ctx.modelValue ?? void 0, day: _ctx.focused.day, week, month: _ctx.focused.month, "min-date": _ctx.minDate, "max-date": _ctx.maxDate, disabled: _ctx.disabledOrUndefined, "unselectable-dates": _ctx.unselectableDates, "unselectable-days-of-week": _ctx.unselectableDaysOfWeek, "selectable-dates": _ctx.selectableDates, events: _ctx.eventsInThisWeek(week), indicators: _ctx.indicators, "date-creator": _ctx.dateCreator, "nearby-month-days": _ctx.nearbyMonthDays, "nearby-selectable-month-days": _ctx.nearbySelectableMonthDays, "show-week-number": _ctx.showWeekNumber, "week-number-clickable": _ctx.weekNumberClickable, "first-day-of-week": _ctx.firstDayOfWeek, "rules-for-first-week": _ctx.rulesForFirstWeek, range: _ctx.range, "hovered-date-range": _ctx.hoveredDateRange, onSelect: _ctx.updateSelectedDate, onRangeHoverEndDate: _ctx.setRangeHoverEndDate, multiple: _ctx.multiple, onChangeFocus: _ctx.changeFocus }, null, 8, ["selected-date", "day", "week", "month", "min-date", "max-date", "disabled", "unselectable-dates", "unselectable-days-of-week", "selectable-dates", "events", "indicators", "date-creator", "nearby-month-days", "nearby-selectable-month-days", "show-week-number", "week-number-clickable", "first-day-of-week", "rules-for-first-week", "range", "hovered-date-range", "onSelect", "onRangeHoverEndDate", "multiple", "onChangeFocus"]); }), 128 /* KEYED_FRAGMENT */ )) ], 2 /* CLASS */ ) ]); } var BDatepickerTable = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$2, [["render", _sfc_render$2]]); var _sfc_main$1 = vue.defineComponent({ name: "BDatepickerMonth", props: { modelValue: { type: [Date, Array, null] }, monthNames: [Array, null], events: Array, indicators: String, minDate: [Date, null], maxDate: [Date, null], focused: Object, disabled: Boolean, dateCreator: Function, unselectableDates: [Array, Function, null], unselectableDaysOfWeek: [Array, null], selectableDates: [Array, Function, null], range: Boolean, multiple: Boolean }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ "change-focus": (_date) => true, "range-end": (_date) => true, "range-start": (_date) => true, "update:modelValue": (_date) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, data() { return { selectedBeginDate: void 0, selectedEndDate: void 0, hoveredEndDate: void 0, multipleSelectedDates: this.multiple && this.modelValue ? this.modelValue : [] }; }, computed: { hasEvents() { return this.events && this.events.length; }, /* * Return array of all events in the specified month */ eventsInThisYear() { if (!this.events) return []; const yearEvents = []; for (let i = 0; i < this.events.length; i++) { let event = this.events[i]; if (!Object.prototype.hasOwnProperty.call(event, "date")) { event = { date: event, type: "is-primary" }; } if (!Object.prototype.hasOwnProperty.call(event, "type")) { event.type = "is-primary"; } if (event.date.getFullYear() === this.focused.year) { yearEvents.push(event); } } return yearEvents; }, monthDates() { const year = this.focused.year; const months = []; for (let i = 0; i < 12; i++) { const d = new Date(year, i, 1); d.setHours(0, 0, 0, 0); months.push(d); } return months; }, focusedMonth() { return this.focused.month; }, hoveredDateRange() { var _a, _b; if (!this.range) { return []; } if (!isNaN((_b = (_a = this.selectedEndDate) == null ? void 0 : _a.valueOf()) != null ? _b : NaN)) { return []; } if (this.hoveredEndDate < this.selectedBeginDate) { return [this.hoveredEndDate, this.selectedBeginDate].filter(helpers.isDefined); } return [this.selectedBeginDate, this.hoveredEndDate].filter(helpers.isDefined); }, disabledOrUndefined() { return this.disabled || void 0; } }, watch: { focusedMonth(month) { const refName = `month-${month}`; this.$nextTick(() => { let cell; if (Array.isArray(this.$refs[refName])) { cell = this.$refs[refName][0]; } else { cell = this.$refs[refName]; } if (cell) { cell.focus(); } }); } }, methods: { selectMultipleDates(date) { const multipleSelect = this.multipleSelectedDates.filter( (selectedDate) => selectedDate.getDate() === date.getDate() && selectedDate.getFullYear() === date.getFullYear() && selectedDate.getMonth() === date.getMonth() ); if (multipleSelect.length) { this.multipleSelectedDates = this.multipleSelectedDates.filter( (selectedDate) => selectedDate.getDate() !== date.getDate() || selectedDate.getFullYear() !== date.getFullYear() || selectedDate.getMonth() !== date.getMonth() ); } else { this.multipleSelectedDates.push(date); } this.$emit("update:modelValue", this.multipleSelectedDates); }, selectableDate(day) { const validity = []; if (this.minDate) { validity.push(day >= this.minDate); } if (this.maxDate) { validity.push(day <= this.maxDate); } validity.push(day.getFullYear() === this.focused.year); if (this.selectableDates) { if (typeof this.selectableDates === "function") { if (this.selectableDates(day)) { return true; } else { validity.push(false); } } else { for (let i = 0; i < this.selectableDates.length; i++) { const enabledDate = this.selectableDates[i]; if (day.getFullYear() === enabledDate.getFullYear() && day.getMonth() === enabledDate.getMonth()) { return true; } else { validity.push(false); } } } } if (this.unselectableDates) { if (typeof this.unselectableDates === "function") { validity.push(!this.unselectableDates(day)); } else { for (let i = 0; i < this.unselectableDates.length; i++) { const disabledDate = this.unselectableDates[i]; validity.push( day.getFullYear() !== disabledDate.getFullYear() || day.getMonth() !== disabledDate.getMonth() ); } } } if (this.unselectableDaysOfWeek) { for (let i = 0; i < this.unselectableDaysOfWeek.length; i++) { const dayOfWeek = this.unselectableDaysOfWeek[i]; validity.push(day.getDay() !== dayOfWeek); } } return validity.indexOf(false) < 0; }, // TODO: return undefined instead of false if no events eventsDateMatch(day) { if (!this.eventsInThisYear.length) return false; const monthEvents = []; for (let i = 0; i < this.eventsInThisYear.length; i++) { if (this.eventsInThisYear[i].date.getMonth() === day.getMonth()) { monthEvents.push(this.events[i]); } } if (!monthEvents.length) { return false; } return monthEvents; }, /* * Build classObject for cell using validations */ classObject(day) { function dateMatch(dateOne, dateTwo, multiple) { if (!dateOne || !dateTwo || multiple) { return false; } if (Array.isArray(dateTwo)) { return dateTwo.some((date) => dateOne.getFullYear() === date.getFullYear() && dateOne.getMonth() === date.getMonth()); } return dateOne.getFullYear() === dateTwo.getFullYear() && dateOne.getMonth() === dateTwo.getMonth(); } function dateWithin(dateOne, dates, multiple) { if (!Array.isArray(dates) || multiple) { return false; } return dateOne > dates[0] && dateOne < dates[1]; } function dateMultipleSelected(dateOne, dates, multiple) { if (!Array.isArray(dates) || !multiple) { return false; } return dates.some((date) => dateOne.getDate() === date.getDate() && dateOne.getFullYear() === date.getFullYear() && dateOne.getMonth() === date.getMonth()); } return { "is-selected": dateMatch(day, this.modelValue, this.multiple) || dateWithin(day, this.modelValue, this.multiple) || dateMultipleSelected(day, this.multipleSelectedDates, this.multiple), "is-first-selected": dateMatch( day, Array.isArray(this.modelValue) ? this.modelValue[0] : void 0, this.multiple ), "is-within-selected": dateWithin(day, this.modelValue, this.multiple), "is-last-selected": dateMatch( day, Array.isArray(this.modelValue) ? this.modelValue[1] : void 0, this.multiple ), "is-within-hovered-range": this.hoveredDateRange && this.hoveredDateRange.length === 2 && (dateMatch(day, this.hoveredDateRange) || dateWithin(day, this.hoveredDateRange)), "is-first-hovered": dateMatch( day, Array.isArray(this.hoveredDateRange) ? this.hoveredDateRange[0] : void 0 ), "is-within-hovered": dateWithin(day, this.hoveredDateRange), "is-last-hovered": dateMatch( day, Array.isArray(this.hoveredDateRange) ? this.hoveredDateRange[1] : void 0 ), "is-today": dateMatch(day, this.dateCreator()), "is-selectable": this.selectableDate(day) && !this.disabled, "is-unselectable": !this.selectableDate(day) || this.disabled }; }, manageKeydown({ key }, date) { switch (key) { case " ": case "Space": case "Spacebar": case "Enter": { this.updateSelectedDate(date); break; } case "ArrowLeft": case "Left": { this.changeFocus(date, -1); break; } case "ArrowRight": case "Right": { this.changeFocus(date, 1); break; } case "ArrowUp": case "Up": { this.changeFocus(date, -3); break; } case "ArrowDown": case "Down": { this.changeFocus(date, 3); break; } } }, /* * Emit input event with selected date as payload for v-model in parent */ updateSelectedDate(date) { if (!this.range && !this.multiple) { this.emitChosenDate(date); } else if (this.range) { this.handleSelectRangeDate(date); } else if (this.multiple) { this.selectMultipleDates(date); } }, /* * Emit select event with chosen date as payload */ emitChosenDate(day) { if (this.disabled) return; if (!this.multiple) { if (this.selectableDate(day)) { this.$emit("update:modelValue", day); } } else { this.selectMultipleDates(day); } }, /* * If both begin and end dates are set, reset the end date and set the begin date. * If only begin date is selected, emit an array of the begin date and the new date. * If not set, only set the begin date. */ handleSelectRangeDate(date) { if (this.disabled) return; if (this.selectedBeginDate && this.selectedEndDate) { this.selectedBeginDate = date; this.selectedEndDate = void 0; this.$emit("range-start", date); } else if (this.selectedBeginDate && !this.selectedEndDate) { if (this.selectedBeginDate > date) { this.selectedEndDate = this.selectedBeginDate; this.selectedBeginDate = date; } else { this.selectedEndDate = date; } this.$emit("range-end", date); this.$emit("update:modelValue", [this.selectedBeginDate, this.selectedEndDate]); } else { this.selectedBeginDate = date; this.$emit("range-start", date); } }, setRangeHoverEndDate(day) { if (this.range) { this.hoveredEndDate = day; } }, changeFocus(month, inc) { const nextMonth = month; nextMonth.setMonth(month.getMonth() + inc); this.$emit("change-focus", nextMonth); } } }); const _hoisted_1$1 = { class: "datepicker-table" }; const _hoisted_2$1 = { class: "datepicker-months" }; const _hoisted_3$1 = ["disabled", "onClick", "onMouseenter", "onKeydown", "tabindex"]; const _hoisted_4$1 = { key: 0, class: "events" }; function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("section", _hoisted_1$1, [ vue.createElementVNode( "div", { class: vue.normalizeClass(["datepicker-body", { "has-events": _ctx.hasEvents }]) }, [ vue.createElementVNode("div", _hoisted_2$1, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.monthDates, (date, index) => { return vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: index }, [ _ctx.selectableDate(date) && !_ctx.disabled ? (vue.openBlock(), vue.createElementBlock("a", { key: 0, ref_for: true, ref: `month-${date.getMonth()}`, class: vue.normalizeClass([[ _ctx.classObject(date), { "has-event": _ctx.eventsDateMatch(date) }, _ctx.indicators ], "datepicker-cell"]), role: "button", href: "#", disabled: _ctx.disabledOrUndefined, onClick: vue.withModifiers(($event) => _ctx.updateSelectedDate(date), ["prevent"]), onMouseenter: ($event) => _ctx.setRangeHoverEndDate(date), onKeydown: vue.withModifiers(($event) => _ctx.manageKeydown($event, date), ["prevent"]), tabindex: _ctx.focused.month === date.getMonth() ? void 0 : -1 }, [ vue.createTextVNode( vue.toDisplayString(_ctx.monthNames[date.getMonth()]) + " ", 1 /* TEXT */ ), _ctx.eventsDateMatch(date) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$1, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.eventsDateMatch(date), (event, evIdx) => { return vue.openBlock(), vue.createElementBlock( "div", { class: vue.normalizeClass(["event", event.type]), key: evIdx }, null, 2 /* CLASS */ ); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ], 42, _hoisted_3$1)) : (vue.openBlock(), vue.createElementBlock( "div", { key: 1, class: vue.normalizeClass([_ctx.classObject(date), "datepicker-cell"]) }, vue.toDisplayString(_ctx.monthNames[date.getMonth()]), 3 /* TEXT, CLASS */ )) ], 64 /* STABLE_FRAGMENT */ ); }), 128 /* KEYED_FRAGMENT */ )) ]) ], 2 /* CLASS */ ) ]); } var BDatepickerMonth = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$1, [["render", _sfc_render$1]]); const defaultDateFormatter = (date, vm) => { const targetDates = Array.isArray(date) ? date : [date]; const dates = targetDates.map((date2) => { const d = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), 12); return !vm.isTypeMonth ? vm.dtf.format(d) : vm.dtfMonth.format(d); }); return !vm.multiple ? dates.join(" - ") : dates.join(", "); }; const defaultDateParser = (date, vm) => { if (vm.dtf.formatToParts && typeof vm.dtf.formatToParts === "function") { const formatRegex = (vm.isTypeMonth ? vm.dtfMonth : vm.dtf).formatToParts(new Date(2e3, 11, 25)).map((part) => { if (part.type === "literal") { return part.value; } return `((?!=<${part.type}>)\\d+)`; }).join(""); const dateGroups = helpers.matchWithGroups(formatRegex, date); if (dateGroups.year && dateGroups.year.length === 4 && dateGroups.month && +dateGroups.month <= 12) { if (vm.isTypeMonth) return new Date(+dateGroups.year, +dateGroups.month - 1); else if (dateGroups.day && +dateGroups.day <= 31) { return new Date(+dateGroups.year, +dateGroups.month - 1, +dateGroups.day, 12); } } } if (!vm.isTypeMonth) return new Date(Date.parse(date)); if (date) { const s = date.split("/"); const year = s[0].length === 4 ? s[0] : s[1]; const month = s[0].length === 2 ? s[0] : s[1]; if (year && month) { return new Date(parseInt(year, 10), parseInt(month, 10) - 1, 1, 0, 0, 0, 0); } } return null; }; var _sfc_main = vue.defineComponent({ name: "BDatepicker", components: { BDatepickerTable, BDatepickerMonth, BInput: Input.BInput, BField: Field.Field, BSelect: Select.BSelect, BIcon: Icon.BIcon, BDropdown: Dropdown.BDropdown, BDropdownItem: DropdownItem.BDropdownItem }, mixins: [CompatFallthroughMixin.CompatFallthroughMixin, FormElementMixin.FormElementMixin], provide() { return { $datepicker: this }; }, props: { modelValue: { type: [Date, Array, null] }, dayNames: { type: [Array, null], default: () => { if (!Array.isArray(config.config.defaultDayNames)) { return void 0; } return config.config.defaultDayNames; } }, monthNames: { type: [Array, null], default: () => { if (!Array.isArray(config.config.defaultMonthNames)) { return void 0; } return config.config.defaultMonthNames; } }, firstDayOfWeek: { type: Number, default: () => { if (typeof config.config.defaultFirstDayOfWeek === "number") { return config.config.defaultFirstDayOfWeek; } else { return 0; } } }, inline: Boolean, minDate: [Date, null], maxDate: [Date, null], focusedDate: Date, placeholder: String, editable: Boolean, disabled: Boolean, horizontalTimePicker: Boolean, unselectableDates: [Array, Function], unselectableDaysOfWeek: { type: [Array, null], default: () => config.config.defaultUnselectableDaysOfWeek }, selectableDates: [Array, Function], dateFormatter: { type: Function, default: (date, vm) => { if (typeof config.config.defaultDateFormatter === "function") { return config.config.defaultDateFormatter(date); } else { return defaultDateFormatter(date, vm); } } }, dateParser: { type: Function, default: (date, vm) => { if (typeof config.config.defaultDateParser === "function") { return config.config.defaultDateParser(date); } else { return defaultDateParser(date, vm); } } }, dateCreator: { type: Function, default: () => { if (typeof config.config.defaultDateCreator === "function") { return config.config.defaultDateCreator(); } else { return /* @__PURE__ */ new Date(); } } }, mobileNative: { type: Boolean, default: () => config.config.defaultDatepickerMobileNative }, position: String, iconRight: String, iconRightClickable: Boolean, events: Array, indicators: { type: String, default: "dots" }, openOnFocus: Boolean, iconPrev: { type: String, default: () => config.config.defaultIconPrev }, iconNext: { type: String, default: () => config.config.defaultIconNext }, yearsRange: { type: Array, default: () => config.config.defaultDatepickerYearsRange }, type: { type: String, validator: (value) => { return [ "month" ].indexOf(value) >= 0; } }, nearbyMonthDays: { type: Boolean, default: () => config.config.defaultDatepickerNearbyMonthDays }, nearbySelectableMonthDays: { type: Boolean, default: () => config.config.defaultDatepickerNearbySelectableMonthDays }, showWeekNumber: { type: Boolean, default: () => config.config.defaultDatepickerShowWeekNumber }, weekNumberClickable: { type: Boolean, default: () => config.config.defaultDatepickerWeekNumberClickable }, rulesForFirstWeek: { type: Number, default: () => 4 }, range: { type: Boolean, default: false }, closeOnClick: { type: Boolean, default: true }, multiple: { type: Boolean, default: false }, mobileModal: { type: Boolean, default: () => config.config.defaultDatepickerMobileModal }, focusable: { type: Boolean, default: true }, trapFocus: { type: Boolean, default: () => config.config.defaultTrapFocus }, appendToBody: Boolean, ariaNextLabel: String, ariaPreviousLabel: String }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ "active-change": (_active) => true, "change-month": (_month) => true, "change-year": (_year) => true, "icon-right-click": (_event) => true, "range-end": (_date) => true, "range-start": (_date) => true, "update:modelValue": (_value) => true, "week-number-click": (_we