@startinfinity/vue-datepicker
Version:
A simple Vue.js datepicker component. Supports disabling of dates, inline mode, translations
2,062 lines (1,816 loc) • 89.3 kB
JavaScript
/*
* @startinfinity/vue-datepicker v3.2.6
* (c) 2018-2021 sum.cumo GmbH
* Released under the Apache-2.0 License.
*/
class Language {
// eslint-disable-next-line max-params
constructor(language, months, monthsAbbr, days, rtl = false, ymd = false, yearSuffix = '') {
this.language = language;
this.months = months;
this.monthsAbbr = monthsAbbr;
this.days = days;
this.rtl = rtl;
this.ymd = ymd;
this.yearSuffix = yearSuffix;
}
/* eslint-disable no-underscore-dangle */
get language() {
return this._language;
}
set language(language) {
if (typeof language !== 'string') {
throw new TypeError('Language must be a string');
}
this._language = language;
}
get months() {
return this._months;
}
set months(months) {
if (months.length !== 12) {
throw new RangeError(`There must be 12 months for ${this.language} language`);
}
this._months = months;
}
get monthsAbbr() {
return this._monthsAbbr;
}
set monthsAbbr(monthsAbbr) {
if (monthsAbbr.length !== 12) {
throw new RangeError(`There must be 12 abbreviated months for ${this.language} language`);
}
this._monthsAbbr = monthsAbbr;
}
get days() {
return this._days;
}
set days(days) {
if (days.length !== 7) {
throw new RangeError(`There must be 7 days for ${this.language} language`);
}
this._days = days;
}
getDaysStartingOn(firstDayOfWeek) {
const firstDays = this._days.slice(firstDayOfWeek);
const lastDays = this._days.slice(0, firstDayOfWeek);
return firstDays.concat(lastDays);
}
getMonthByAbbrName(name) {
const monthValue = this._monthsAbbr.findIndex(month => month === name) + 1;
return monthValue < 10 ? `0${monthValue}` : `${monthValue}`;
}
getMonthByName(name) {
const monthValue = this._months.findIndex(month => month === name) + 1;
return monthValue < 10 ? `0${monthValue}` : `${monthValue}`;
}
}
var en = new Language('English', ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
var calendarSlots = ['beforeCalendarHeaderDay', 'calendarFooterDay', 'beforeCalendarHeaderMonth', 'calendarFooterMonth', 'beforeCalendarHeaderYear', 'calendarFooterYear', 'nextIntervalBtn', 'prevIntervalBtn'];
const getParsedDate = ({
formatStr,
dateStr,
translation
}) => {
const splitter = formatStr.match(/-|\/|\s|\./) || ['-'];
const df = formatStr.split(splitter[0]);
const ds = dateStr.split(splitter[0]);
const ymd = [new Date().getFullYear(), '01', '01'];
for (let i = 0; i < df.length; i += 1) {
if (/yyyy/i.test(df[i])) {
ymd[0] = ds[i];
} else if (/mmmm/i.test(df[i])) {
ymd[1] = translation.getMonthByName(ds[i]);
} else if (/mmm/i.test(df[i])) {
ymd[1] = translation.getMonthByAbbrName(ds[i]);
} else if (/mm/i.test(df[i])) {
ymd[1] = ds[i];
} else if (/m/i.test(df[i])) {
ymd[1] = ds[i];
} else if (/dd/i.test(df[i])) {
ymd[2] = ds[i];
} else if (/d/i.test(df[i])) {
const tmp = ds[i].replace(/st|rd|nd|th/g, '');
ymd[2] = tmp < 10 ? `0${tmp}` : `${tmp}`;
}
}
return ymd;
};
const utils = {
/**
* @type {Boolean}
*/
useUtc: false,
/**
* Returns the full year, using UTC or not
* @param {Date} date
*/
getFullYear(date) {
return this.useUtc ? date.getUTCFullYear() : date.getFullYear();
},
/**
* Returns the month, using UTC or not
* @param {Date} date
*/
getMonth(date) {
return this.useUtc ? date.getUTCMonth() : date.getMonth();
},
/**
* Returns the number of days in the month, using UTC or not
* @param {Date} date
*/
getDaysInMonth(date) {
return this.daysInMonth(this.getFullYear(date), this.getMonth(date));
},
/**
* Returns the date, using UTC or not
* @param {Date} date
*/
getDate(date) {
return this.useUtc ? date.getUTCDate() : date.getDate();
},
/**
* Returns the day, using UTC or not
* @param {Date} date
*/
getDay(date) {
return this.useUtc ? date.getUTCDay() : date.getDay();
},
/**
* Returns the hours, using UTC or not
* @param {Date} date
*/
getHours(date) {
return this.useUtc ? date.getUTCHours() : date.getHours();
},
/**
* Returns the minutes, using UTC or not
* @param {Date} date
*/
getMinutes(date) {
return this.useUtc ? date.getUTCMinutes() : date.getMinutes();
},
/**
* Sets the full year, using UTC or not
* @param {Date} date
* @param {String, Number} value
*/
setFullYear(date, value) {
return this.useUtc ? date.setUTCFullYear(value) : date.setFullYear(value);
},
/**
* Sets the month, using UTC or not
* @param {Date} date
* @param {String, Number} value
*/
setMonth(date, value) {
return this.useUtc ? date.setUTCMonth(value) : date.setMonth(value);
},
/**
* Sets the date, using UTC or not
* @param {Date} date
* @param {String, Number} value
*/
setDate(date, value) {
return this.useUtc ? date.setUTCDate(value) : date.setDate(value);
},
/**
* Check if date1 is equivalent to date2, without comparing the time
* @see https://stackoverflow.com/a/6202196/4455925
* @param {Date} date1
* @param {Date} date2
*/
compareDates(date1, date2) {
const d1 = new Date(date1.valueOf());
const d2 = new Date(date2.valueOf());
this.resetDateTime(d1);
this.resetDateTime(d2);
return d1.valueOf() === d2.valueOf();
},
/**
* Validates a date object
* @param {Date} date - an object instantiated with the new Date constructor
* @return {Boolean}
*/
isValidDate(date) {
if (Object.prototype.toString.call(date) !== '[object Date]') {
return false;
}
return !Number.isNaN(date.valueOf());
},
/**
* Return abbreviated week day name
* @param {Date} date
* @param {Array} days
* @return {String}
*/
getDayNameAbbr(date, days) {
if (typeof date !== 'object') {
throw TypeError('Invalid Type');
}
return days[this.getDay(date)];
},
/**
* Return day number from abbreviated week day name
* @param {String} abbr
* @return {Number}
*/
getDayFromAbbr(abbr) {
for (let i = 0; i < en.days.length; i += 1) {
if (abbr.toLowerCase() === en.days[i].toLowerCase()) {
return i;
}
}
throw TypeError('Invalid week day');
},
/**
* Return name of the month
* @param {Number|Date} month
* @param {Array} months
* @return {String}
*/
getMonthName(month, months) {
if (!months) {
throw Error('missing 2nd parameter Months array');
}
if (typeof month === 'object') {
return months[this.getMonth(month)];
}
if (typeof month === 'number') {
return months[month];
}
throw TypeError('Invalid type');
},
/**
* Return an abbreviated version of the month
* @param {Number|Date} month
* @param {Array} monthsAbbr
* @return {String}
*/
getMonthNameAbbr(month, monthsAbbr) {
if (!monthsAbbr) {
throw Error('missing 2nd paramter Months array');
}
if (typeof month === 'object') {
return monthsAbbr[this.getMonth(month)];
}
if (typeof month === 'number') {
return monthsAbbr[month];
}
throw TypeError('Invalid type');
},
/**
* Alternative get total number of days in month
* @param {Number} year
* @param {Number} month
* @return {Number}
*/
// eslint-disable-next-line complexity
daysInMonth(year, month) {
if (/8|3|5|10/.test(month)) {
return 30;
}
if (month === 1) {
return !(year % 4) && year % 100 || !(year % 400) ? 29 : 28;
}
return 31;
},
/**
* Get nth suffix for date
* @param {Number} day
* @return {String}
*/
// eslint-disable-next-line complexity
getNthSuffix(day) {
switch (day) {
case 1:
case 21:
case 31:
return 'st';
case 2:
case 22:
return 'nd';
case 3:
case 23:
return 'rd';
default:
return 'th';
}
},
/**
* Formats date object
* @param {Date} date
* @param {String} formatStr
* @param {Object} translation
* @return {String}
*/
formatDate(date, formatStr, translation = en) {
const year = this.getFullYear(date);
const month = this.getMonth(date) + 1;
const day = this.getDate(date);
const matches = {
dd: `0${day}`.slice(-2),
d: day,
yyyy: year,
yy: String(year).slice(2),
MMMM: this.getMonthName(this.getMonth(date), translation.months),
MMM: this.getMonthNameAbbr(this.getMonth(date), translation.monthsAbbr),
MM: `0${month}`.slice(-2),
M: month,
o: this.getNthSuffix(this.getDate(date)),
E: this.getDayNameAbbr(date, translation.days)
};
const REGEX_FORMAT = /y{4}|y{2}|M{1,4}(?![aäe])|d{1,2}|o{1}|E{1}(?![eéi])/g;
return formatStr.replace(REGEX_FORMAT, match => matches[match] || match);
},
/**
* makes date parseable
* to use with international dates
* @param {String} dateStr
* @param {String|Function} formatStr
* @param {Object} translation
* @param {Function} parser
* @return {Date | String}
*/
// eslint-disable-next-line max-params,complexity,max-statements
parseDate(dateStr, formatStr, translation = en, parser = null) {
if (!(dateStr && formatStr)) {
return dateStr;
}
if (typeof formatStr === 'function') {
if (!parser || typeof parser !== 'function') {
throw new Error('Parser needs to be a function if you are using a custom formatter');
}
return parser(dateStr);
}
const ymd = getParsedDate({
formatStr,
dateStr,
translation
});
const dat = `${ymd.join('-')}${this.getTime()}`;
if (Number.isNaN(Date.parse(dat))) {
return dateStr;
}
return dat;
},
getTime() {
const time = 'T00:00:00';
if (this.useUtc) {
return `${time}Z`;
}
return time;
},
/**
* Creates an array of dates for each day in between two dates.
* @param {Date} start
* @param {Date} end
* @return {Array}
*/
createDateArray(start, end) {
const dates = [];
let startTemp = start;
while (startTemp <= end) {
dates.push(new Date(startTemp));
startTemp = this.setDate(new Date(startTemp), this.getDate(new Date(startTemp)) + 1);
}
return dates;
},
/**
* Remove hours/minutes/seconds/milliseconds from a date object
* @param {Date} date
* @return {Date}
*/
resetDateTime(date) {
return new Date(this.useUtc ? date.setUTCHours(0, 0, 0, 0) : date.setHours(0, 0, 0, 0));
},
/**
* Return a new date object with hours/minutes/seconds/milliseconds removed
* @return {Date}
*/
getNewDateObject(date) {
return date ? this.resetDateTime(new Date(date)) : this.resetDateTime(new Date());
}
};
var makeDateUtils = (useUtc => ({ ...utils,
useUtc
}));
var script$9 = {
props: {
autofocus: {
type: Boolean,
default: false
},
bootstrapStyling: {
type: Boolean,
default: false
},
clearButton: {
type: Boolean,
default: false
},
clearButtonIcon: {
type: String,
default: ''
},
calendarButton: {
type: Boolean,
default: false
},
calendarButtonIcon: {
type: String,
default: ''
},
calendarButtonIconContent: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
format: {
type: [String, Function],
default: 'dd MMM yyyy'
},
id: {
type: String,
default: null
},
inline: {
type: Boolean,
default: false
},
inputClass: {
type: [String, Object, Array],
default: null
},
maxlength: {
type: [Number, String],
default: null
},
name: {
type: String,
default: null
},
openDate: {
type: [String, Date, Number],
default: null,
validator: val => val === null || val instanceof Date || typeof val === 'string' || typeof val === 'number'
},
parser: {
type: Function,
default: null
},
pattern: {
type: String,
default: null
},
placeholder: {
type: String,
default: null
},
refName: {
type: String,
default: ''
},
required: {
type: Boolean,
default: false
},
showCalendarOnButtonClick: {
type: Boolean,
default: false
},
showCalendarOnFocus: {
type: Boolean,
default: false
},
tabindex: {
type: [Number, String],
default: null
},
typeable: {
type: Boolean,
default: false
},
useUtc: {
type: Boolean,
default: false
}
}
};
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
if (typeof shadowMode !== 'boolean') {
createInjectorSSR = createInjector;
createInjector = shadowMode;
shadowMode = false;
}
// Vue.extend constructor export interop.
const options = typeof script === 'function' ? script.options : script;
// render functions
if (template && template.render) {
options.render = template.render;
options.staticRenderFns = template.staticRenderFns;
options._compiled = true;
// functional template
if (isFunctionalTemplate) {
options.functional = true;
}
}
// scopedId
if (scopeId) {
options._scopeId = scopeId;
}
let hook;
if (moduleIdentifier) {
// server build
hook = function (context) {
// 2.3 injection
context =
context || // cached call
(this.$vnode && this.$vnode.ssrContext) || // stateful
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__;
}
// inject component styles
if (style) {
style.call(this, createInjectorSSR(context));
}
// register component module identifier for async chunk inference
if (context && context._registeredComponents) {
context._registeredComponents.add(moduleIdentifier);
}
};
// used by ssr in case component is cached and beforeCreate
// never gets called
options._ssrRegister = hook;
}
else if (style) {
hook = shadowMode
? function (context) {
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
}
: function (context) {
style.call(this, createInjector(context));
};
}
if (hook) {
if (options.functional) {
// register for functional component in vue file
const originalRender = options.render;
options.render = function renderWithStyleInjection(h, context) {
hook.call(context);
return originalRender(h, context);
};
}
else {
// inject component registration as beforeCreate hook
const existing = options.beforeCreate;
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
}
}
return script;
}
/* script */
const __vue_script__$9 = script$9;
/* template */
/* style */
const __vue_inject_styles__$9 = undefined;
/* scoped */
const __vue_scope_id__$9 = undefined;
/* module identifier */
const __vue_module_identifier__$9 = undefined;
/* functional template */
const __vue_is_functional_template__$9 = undefined;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__$9 = /*#__PURE__*/normalizeComponent(
{},
__vue_inject_styles__$9,
__vue_script__$9,
__vue_scope_id__$9,
__vue_is_functional_template__$9,
__vue_module_identifier__$9,
false,
undefined,
undefined,
undefined
);
//
var script$8 = {
name: 'DateInput',
mixins: [__vue_component__$9],
props: {
isOpen: {
type: Boolean,
default: false
},
selectedDate: {
type: Date,
default: null
},
translation: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
input: null,
isFocusedUsed: false,
isBlurred: false,
typedDate: '',
utils: makeDateUtils(this.useUtc)
};
},
computed: {
computedInputClass() {
if (this.bootstrapStyling) {
if (typeof this.inputClass === 'string') {
return [this.inputClass, 'form-control'].join(' ');
}
return {
'form-control': true,
...this.inputClass
};
}
return this.inputClass;
},
formattedDate() {
return typeof this.format === 'function' ? this.format(new Date(this.selectedDate)) : this.utils.formatDate(new Date(this.selectedDate), this.format, this.translation);
},
formattedValue() {
if (!this.selectedDate) {
return null;
}
if (this.typedDate.length) {
return this.typedDate;
}
return this.formattedDate;
}
},
mounted() {
this.input = this.$el.querySelector('input');
},
methods: {
/**
* Emits a `clear-date` event
*/
clearDate() {
this.$emit('clear-date');
},
/**
* Submit typedDate and emit a `blur` event
*/
handleInputBlur() {
this.isBlurred = this.isOpen;
if (this.typeable) {
this.submitTypedDate();
}
this.$emit('blur');
this.$emit('close');
this.isFocusedUsed = false;
},
/**
* Toggles the calendar (unless `show-calendar-on-button-click` is true)
*/
handleInputClick() {
const isFocusedUsed = this.showCalendarOnFocus && !this.isFocusedUsed;
if (!this.showCalendarOnButtonClick && !isFocusedUsed) {
this.toggle();
}
if (this.showCalendarOnFocus) {
this.isFocusedUsed = true;
}
},
/**
* Opens the calendar when `show-calendar-on-focus` is true
*/
handleInputFocus() {
if (this.showCalendarOnFocus) {
this.$emit('open');
}
this.isBlurred = false;
this.$emit('focus');
},
/**
* Submits a typed date
*/
handleKeydownEnter() {
if (this.typeable) {
this.submitTypedDate();
}
this.$emit('close');
},
/**
* Parses a date from a string
* @param {String} value
*/
parseDate(value) {
return this.utils.parseDate(value, this.format, this.translation, this.parser);
},
/**
* Attempt to parse a typed date
*/
parseTypedDate() {
if (this.typeable) {
const parsableDate = this.parseDate(this.input.value);
const parsedDate = Date.parse(parsableDate);
if (!Number.isNaN(parsedDate)) {
this.typedDate = this.input.value;
this.$emit('typed-date', new Date(parsedDate));
}
}
},
/**
* Submits a typed date if it's valid
*/
submitTypedDate() {
const parsableDate = this.parseDate(this.input.value);
const parsedDate = Date.parse(parsableDate);
if (Number.isNaN(parsedDate)) {
this.clearDate();
} else {
this.input.value = this.formattedDate;
this.typedDate = '';
this.$emit('typed-date', parsedDate);
}
},
/**
* Opens or closes the calendar
*/
toggle() {
if (!this.isOpen && this.isBlurred) {
this.isBlurred = false;
return;
}
this.$emit(this.isOpen ? 'close' : 'open');
}
}
};
/* script */
const __vue_script__$8 = script$8;
/* template */
var __vue_render__$6 = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
{ class: { "input-group": _vm.bootstrapStyling } },
[
_vm._t("beforeDateInput"),
_vm._v(" "),
_vm.calendarButton
? _c(
"span",
{
staticClass: "vdp-datepicker__calendar-button",
class: {
"input-group-prepend": _vm.bootstrapStyling,
"calendar-btn-disabled": _vm.disabled
},
on: { click: _vm.toggle }
},
[
_c(
"span",
{ class: { "input-group-text": _vm.bootstrapStyling } },
[
_vm._t("calendarBtn", [
_c("i", { class: _vm.calendarButtonIcon }, [
_vm._v(
"\n " +
_vm._s(_vm.calendarButtonIconContent) +
"\n "
),
!_vm.calendarButtonIcon
? _c("span", [_vm._v("…")])
: _vm._e()
])
])
],
2
)
]
)
: _vm._e(),
_vm._v(" "),
_c("input", {
ref: _vm.refName,
class: _vm.computedInputClass,
attrs: {
id: _vm.id,
autocomplete: "off",
autofocus: _vm.autofocus,
"clear-button": _vm.clearButton,
disabled: _vm.disabled,
maxlength: _vm.maxlength,
name: _vm.name,
pattern: _vm.pattern,
placeholder: _vm.placeholder,
readonly: !_vm.typeable,
required: _vm.required,
tabindex: _vm.tabindex,
type: _vm.inline ? "hidden" : null
},
domProps: { value: _vm.formattedValue },
on: {
blur: _vm.handleInputBlur,
click: _vm.handleInputClick,
focus: _vm.handleInputFocus,
keydown: [
function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k($event.keyCode, "enter", 13, $event.key, "Enter")
) {
return null
}
$event.preventDefault();
return _vm.handleKeydownEnter($event)
},
function($event) {
if (
!$event.type.indexOf("key") &&
_vm._k(
$event.keyCode,
"escape",
undefined,
$event.key,
undefined
)
) {
return null
}
$event.preventDefault();
return _vm.$emit("close")
}
],
keyup: _vm.parseTypedDate
}
}),
_vm._v(" "),
_vm.clearButton && _vm.selectedDate
? _c(
"span",
{
staticClass: "vdp-datepicker__clear-button",
class: { "input-group-append": _vm.bootstrapStyling },
on: {
click: function($event) {
return _vm.clearDate()
}
}
},
[
_c(
"span",
{ class: { "input-group-text": _vm.bootstrapStyling } },
[
_vm._t("clearBtn", [
_c("i", { class: _vm.clearButtonIcon }, [
!_vm.clearButtonIcon
? _c("span", [_vm._v("×")])
: _vm._e()
])
])
],
2
)
]
)
: _vm._e(),
_vm._v(" "),
_vm._t("afterDateInput")
],
2
)
};
var __vue_staticRenderFns__$6 = [];
__vue_render__$6._withStripped = true;
/* style */
const __vue_inject_styles__$8 = undefined;
/* scoped */
const __vue_scope_id__$8 = undefined;
/* module identifier */
const __vue_module_identifier__$8 = undefined;
/* functional template */
const __vue_is_functional_template__$8 = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__$8 = /*#__PURE__*/normalizeComponent(
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
__vue_inject_styles__$8,
__vue_script__$8,
__vue_scope_id__$8,
__vue_is_functional_template__$8,
__vue_module_identifier__$8,
false,
undefined,
undefined,
undefined
);
const cellUtils = {
configExists(obj) {
return typeof obj !== 'undefined' && Object.keys(obj).length > 0;
},
isDefined(obj, prop) {
return this.configExists(obj) && typeof obj[prop] !== 'undefined';
},
hasArray(obj, prop) {
return this.isDefined(obj, prop) && obj[prop].length > 0;
},
hasDate(obj, prop) {
return this.isDefined(obj, prop) && this.utils.isValidDate(obj[prop]);
},
dayMonthYear(obj, prop) {
const {
utils
} = this;
const hasDate = this.hasDate(obj, prop);
if (!hasDate) {
return {
day: undefined,
month: undefined,
year: undefined
};
}
const d = obj[prop];
return {
day: utils.getDate(d),
month: utils.getMonth(d),
year: utils.getFullYear(d)
};
}
};
var makeCellUtils = (utils => ({ ...cellUtils,
utils
}));
/* eslint-disable no-underscore-dangle */
class DisabledDate {
constructor(utils, disabledDates) {
this._utils = utils;
this._disabledDates = disabledDates;
}
get config() {
const disabledDates = this._disabledDates;
const utils = makeCellUtils(this._utils);
return {
exists: utils.configExists(disabledDates),
to: utils.dayMonthYear(disabledDates, 'to'),
from: utils.dayMonthYear(disabledDates, 'from'),
has: {
customPredictor: utils.isDefined(disabledDates, 'customPredictor'),
daysOfMonth: utils.hasArray(disabledDates, 'daysOfMonth'),
daysOfWeek: utils.hasArray(disabledDates, 'days'),
from: utils.hasDate(disabledDates, 'from'),
ranges: utils.hasArray(disabledDates, 'ranges'),
specificDates: utils.hasArray(disabledDates, 'dates'),
to: utils.hasDate(disabledDates, 'to')
}
};
}
daysInMonth(date) {
const utils = this._utils;
const month = utils.getMonth(date);
const year = utils.getFullYear(date);
return utils.daysInMonth(year, month);
}
isDateDisabledVia(date) {
const disabledDates = this._disabledDates;
const {
has
} = this.config;
return {
to: () => {
return has.to && date < disabledDates.to;
},
from: () => {
return has.from && date > disabledDates.from;
},
range: () => {
if (!has.ranges) return false;
const {
ranges
} = disabledDates;
const u = makeCellUtils(this._utils);
return ranges.some(thisRange => {
const hasFrom = u.isDefined(thisRange, 'from');
const hasTo = u.isDefined(thisRange, 'to');
return hasFrom && hasTo && date < thisRange.to && date > thisRange.from;
});
},
customPredictor: () => {
return has.customPredictor && disabledDates.customPredictor(date);
},
specificDate: () => {
if (!has.specificDates) return false;
return disabledDates.dates.some(d => {
return this._utils.compareDates(date, d);
});
},
daysOfWeek: () => {
if (!has.daysOfWeek) return false;
return disabledDates.days.indexOf(this._utils.getDay(date)) !== -1;
},
daysOfMonth: () => {
if (!has.daysOfMonth) return false;
return disabledDates.daysOfMonth.indexOf(this._utils.getDate(date)) !== -1;
}
};
}
isMonthDisabledVia(date) {
const {
from,
has,
to
} = this.config;
const month = this._utils.getMonth(date);
const year = this._utils.getFullYear(date);
return {
to: () => {
const isYearInPast = has.to && year < to.year;
if (isYearInPast) {
return true;
}
return has.to && month < to.month && year <= to.year;
},
from: () => {
const isYearInFuture = has.from && year > from.year;
if (isYearInFuture) {
return true;
}
return has.from && month > from.month && year >= from.year;
}
};
}
isYearDisabledVia(date) {
const {
from,
has,
to
} = this.config;
const year = this._utils.getFullYear(date);
return {
to: () => {
return has.to && year < to.year;
},
from: () => {
return has.from && year > from.year;
}
};
}
/**
* Checks if the given date should be disabled
* @param {Date} date
* @return {Boolean}
*/
// eslint-disable-next-line complexity,max-statements
isDateDisabled(date) {
if (!this.config.exists) return false;
const isDisabledVia = this.isDateDisabledVia(date);
return isDisabledVia.to() || isDisabledVia.from() || isDisabledVia.range() || isDisabledVia.specificDate() || isDisabledVia.daysOfWeek() || isDisabledVia.daysOfMonth() || isDisabledVia.customPredictor();
}
/**
* Checks if the given month should be disabled
* @param {Date} date
* @return {Boolean}
*/
// eslint-disable-next-line complexity,max-statements
isMonthDisabled(date) {
const {
config
} = this;
const isDisabledVia = this.isMonthDisabledVia(date);
if (!config.exists) {
return false;
}
if (isDisabledVia.to() || isDisabledVia.from()) {
return true;
} // now we have to check each day of the month
for (let i = 1; i <= this.daysInMonth(date); i += 1) {
const dayDate = new Date(date);
dayDate.setDate(i); // if at least one day of this month is NOT disabled,
// we can conclude that this month SHOULD be selectable
if (!this.isDateDisabled(dayDate)) {
return false;
}
}
return true;
}
/**
* Checks if the given year should be disabled
* @param {Date} date
* @return {Boolean}
*/
// eslint-disable-next-line complexity,max-statements
isYearDisabled(date) {
const {
config
} = this;
const isDisabledVia = this.isYearDisabledVia(date);
if (!config.exists) {
return false;
}
if (isDisabledVia.to() || isDisabledVia.from()) {
return true;
} // now we have to check each month of the year
for (let i = 0; i < 12; i += 1) {
const monthDate = new Date(date);
monthDate.setMonth(i); // if at least one month of this year is NOT disabled,
// we can conclude that this year SHOULD be selectable
if (!this.isMonthDisabled(monthDate)) {
return false;
}
}
return true;
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
var script$7 = {
name: 'PickerHeader',
props: {
isNextDisabled: {
type: Boolean,
required: true
},
isPreviousDisabled: {
type: Boolean,
required: true
},
isRtl: {
type: Boolean,
required: true
}
}
};
/* script */
const __vue_script__$7 = script$7;
/* template */
var __vue_render__$5 = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"header",
[
_c(
"span",
{
staticClass: "prev",
class: { disabled: _vm.isPreviousDisabled, rtl: _vm.isRtl },
on: {
click: function($event) {
_vm.isPreviousDisabled ? null : _vm.$emit("page-change", -1);
}
}
},
[
_vm._t("prevIntervalBtn", [
_c("span", { staticClass: "default" }, [_vm._v("<")])
])
],
2
),
_vm._v(" "),
_vm._t("default"),
_vm._v(" "),
_c(
"span",
{
staticClass: "next",
class: { disabled: _vm.isNextDisabled, rtl: _vm.isRtl },
on: {
click: function($event) {
_vm.isNextDisabled ? null : _vm.$emit("page-change", 1);
}
}
},
[
_vm._t("nextIntervalBtn", [
_c("span", { staticClass: "default" }, [_vm._v(">")])
])
],
2
)
],
2
)
};
var __vue_staticRenderFns__$5 = [];
__vue_render__$5._withStripped = true;
/* style */
const __vue_inject_styles__$7 = undefined;
/* scoped */
const __vue_scope_id__$7 = undefined;
/* module identifier */
const __vue_module_identifier__$7 = undefined;
/* functional template */
const __vue_is_functional_template__$7 = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__$7 = /*#__PURE__*/normalizeComponent(
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
__vue_inject_styles__$7,
__vue_script__$7,
__vue_scope_id__$7,
__vue_is_functional_template__$7,
__vue_module_identifier__$7,
false,
undefined,
undefined,
undefined
);
var script$6 = {
components: {
PickerHeader: __vue_component__$7
},
inheritAttrs: false,
props: {
disabledDates: {
type: Object,
default() {
return {};
}
},
isRtl: {
type: Boolean,
default: false
},
isUpDisabled: {
type: Boolean,
default: false
},
pageDate: {
type: Date,
default: null
},
selectedDate: {
type: Date,
default: null
},
showHeader: {
type: Boolean,
default: true
},
transitionName: {
type: String,
default: ''
},
translation: {
type: Object,
default() {
return {};
}
},
useUtc: {
type: Boolean,
default: false
},
view: {
type: String,
default: 'day'
}
},
data() {
return {
utils: makeDateUtils(this.useUtc)
};
},
computed: {
/**
* A look-up object created from 'disabledDates' prop
* @return {Object}
*/
disabledConfig() {
return new DisabledDate(this.utils, this.disabledDates).config;
},
/**
* Returns the current page's full year as an integer.
* @return {Number}
*/
pageYear() {
return this.utils.getFullYear(this.pageDate);
}
},
methods: {
/**
* Changes the page up or down
* @param {Number} incrementBy
*/
changePage(incrementBy) {
const {
pageDate,
utils
} = this;
const units = this.view === 'year' ? incrementBy * this.yearRange : incrementBy;
this.$emit('set-transition-name', incrementBy);
if (this.view === 'day') {
utils.setMonth(pageDate, utils.getMonth(pageDate) + units);
} else {
utils.setFullYear(pageDate, utils.getFullYear(pageDate) + units);
}
this.$emit('page-change', pageDate);
},
/**
* Determines which transition to use (for edge dates) and emits a 'select' or 'select-disabled' event
* @param {Object} cell
*/
select(cell) {
if (cell.isDisabled) {
this.$emit('select-disabled', cell);
return;
}
if (cell.isPreviousMonth) {
this.$emit('set-transition-name', -1);
}
if (cell.isNextMonth) {
this.$emit('set-transition-name', 1);
}
this.$emit('select', cell);
}
}
};
/* script */
const __vue_script__$6 = script$6;
/* template */
/* style */
const __vue_inject_styles__$6 = undefined;
/* scoped */
const __vue_scope_id__$6 = undefined;
/* module identifier */
const __vue_module_identifier__$6 = undefined;
/* functional template */
const __vue_is_functional_template__$6 = undefined;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__$6 = /*#__PURE__*/normalizeComponent(
{},
__vue_inject_styles__$6,
__vue_script__$6,
__vue_scope_id__$6,
__vue_is_functional_template__$6,
__vue_module_identifier__$6,
false,
undefined,
undefined,
undefined
);
/* eslint-disable no-underscore-dangle */
class HighlightedDate {
constructor(utils, disabledDates, highlighted) {
this._utils = utils;
this._disabledDates = disabledDates;
this._highlighted = highlighted;
}
get config() {
const highlightedDates = this._highlighted;
const utils = makeCellUtils(this._utils);
return {
exists: utils.configExists(highlightedDates),
to: utils.dayMonthYear(highlightedDates, 'to'),
from: utils.dayMonthYear(highlightedDates, 'from'),
has: {
customPredictor: utils.isDefined(highlightedDates, 'customPredictor'),
daysOfMonth: utils.hasArray(highlightedDates, 'daysOfMonth'),
daysOfWeek: utils.hasArray(highlightedDates, 'days'),
from: utils.hasDate(highlightedDates, 'from'),
specificDates: utils.hasArray(highlightedDates, 'dates'),
to: utils.hasDate(highlightedDates, 'to'),
includeDisabled: utils.isDefined(highlightedDates, 'includeDisabled') && highlightedDates.includeDisabled
}
};
}
isDateDisabled(date) {
const utils = this._utils;
const disabledDates = this._disabledDates;
return new DisabledDate(utils, disabledDates).isDateDisabled(date);
}
isHighlightingNotPossible(date) {
const {
config
} = this;
if (!config.exists) return false;
return !config.has.includeDisabled && this.isDateDisabled(date);
}
isDateHighlightedVia(date) {
const highlightedDates = this._highlighted;
const {
has
} = this.config;
return {
to: () => {
return has.to && date <= highlightedDates.to;
},
from: () => {
return has.from && date >= highlightedDates.from;
},
customPredictor: () => {
return has.customPredictor && highlightedDates.customPredictor(date);
},
specificDate: () => {
if (!has.specificDates) return false;
return highlightedDates.dates.some(d => {
return this._utils.compareDates(date, d);
});
},
daysOfWeek: () => {
if (!has.daysOfWeek) return false;
return highlightedDates.days.indexOf(this._utils.getDay(date)) !== -1;
},
daysOfMonth: () => {
if (!has.daysOfMonth) return false;
return highlightedDates.daysOfMonth.indexOf(this._utils.getDate(date)) !== -1;
}
};
} // eslint-disable-next-line complexity,max-statements
isDateHighlighted(date) {
if (this.isHighlightingNotPossible(date)) return false;
const isHighlightedVia = this.isDateHighlightedVia(date);
return isHighlightedVia.to() && isHighlightedVia.from() || isHighlightedVia.specificDate() || isHighlightedVia.daysOfWeek() || isHighlightedVia.daysOfMonth() || isHighlightedVia.customPredictor();
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
var script$5 = {
name: 'PickerCells',
props: {
cells: {
type: Array,
required: true
},
showEdgeDates: {
type: Boolean,
default: true
},
view: {
type: String,
validator: val => ['day', 'month', 'year'].includes(val),
required: true
}
},
methods: {
/**
* Set the classes for a specific cell
* @return {Array}
*/
// eslint-disable-next-line complexity
cellClasses(cell) {
return ['cell', this.view, {
'disabled': cell.isDisabled,
'highlight-start': cell.isHighlightStart,
'highlight-end': cell.isHighlightEnd,
'highlighted': cell.isHighlighted,
'muted': cell.isPreviousMonth || cell.isNextMonth,
'sat': cell.isSaturday,
'sun': cell.isSunday,
'selected': this.showEdgeDates ? cell.isSelected : cell.isSelected && !cell.isPreviousMonth && !cell.isNextMonth,
'today': this.showEdgeDates ? cell.isToday : cell.isToday && !cell.isPreviousMonth && !cell.isNextMonth,
'weekend': cell.isWeekend
}];
}
}
};
/* script */
const __vue_script__$5 = script$5;
/* template */
var __vue_render__$4 = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(
"div",
{ staticClass: "picker-cells" },
_vm._l(_vm.cells, function(cell) {
return _c(
"span",
{
key: cell.timestamp,
class: _vm.cellClasses(cell),
on: {
click: function($event) {
return _vm.$emit("select", cell)
}
}
},
[_vm._t("default", null, { cell: cell })],
2
)
}),
0
)
};
var __vue_staticRenderFns__$4 = [];
__vue_render__$4._withStripped = true;
/* style */
const __vue_inject_styles__$5 = undefined;
/* scoped */
const __vue_scope_id__$5 = undefined;
/* module identifier */
const __vue_module_identifier__$5 = undefined;
/* functional template */
const __vue_is_functional_template__$5 = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__$5 = /*#__PURE__*/normalizeComponent(
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
__vue_inject_styles__$5,
__vue_script__$5,
__vue_scope_id__$5,
__vue_is_functional_template__$5,
__vue_module_identifier__$5,
false,
undefined,
undefined,
undefined
);
//
var script$4 = {
name: 'PickerDay',
components: {
PickerCells: __vue_component__$5
},
mixins: [__vue_component__$6],
props: {
dayCellContent: {
type: Function,
default: day => day.date
},
firstDayOfWeek: {
type: String,
default: 'sun'
},
highlighted: {
type: Object,
default() {
return {};
}
},
showFullMonthName: {
type: Boolean,
default: false
},
showEdgeDates: {
type: Boolean,
default: true
}
},
computed: {
/**
* Sets an array with all days to show this month
* @return {Array}
*/
cells() {
const days = [];
const daysInCalendar = this.daysFromPrevMonth + this.daysInMonth + this.daysFromNextMonth;
const dObj = this.firstCellDate();
for (let i = 0; i < daysInCalendar; i += 1) {
days.push(this.makeDay(i, dObj));
this.utils.setDate(dObj, this.utils.getDate(dObj) + 1);
}
return days;
},
/**
* Gets the name of the month the current page is on
* @return {String}
*/
currMonthName() {
const monthName = this.showFullMonthName ? this.translation.months : this.translation.monthsAbbr;
return this.utils.getMonthNameAbbr(this.pageMonth, monthName);
},
/**
* Gets the name of the year that current page is on
* @return {String}
*/
currYearName() {
const {
yearSuffix
} = this.translation;
return `${this.pageYear}${yearSuffix}`;
},
/**
* Returns an array of day names
* @return {String[]}
*/
daysOfWeek() {
return this.translation.getDaysStartingOn(this.firstDayOfWeekNumber);
},
/**
* Returns the number of days in this month
* @return {String[]}
*/
daysInMonth() {
return this.utils.getDaysInMonth(this.pageDate);
},
/**
* Calculates how many days to show from the previous month
* @return {number}
*/
daysFromPrevMonth() {
const firstOfMonthDayNumber = this.utils.getDay(this.pageDate);
return (7 - this.firstDayOfWeekNumber + firstOfMonthDayNumber) % 7;
},
/**
* Calculates how many days to show from the next month
* @return {number}
*/
daysFromNextMonth() {
const daysThisAndPrevMonth = this.daysFromPrevMonth + this.daysInMonth;
return Math.ceil(daysThisAndPrevMonth / 7) * 7 - daysThisAndPrevMonth;
},
/**
* Returns first-day-of-week as a number (Sunday is 0)
* @return {Number}
*/
firstDayOfWeekNumber() {
return this.utils.getDayFromAbbr(this.firstDayOfWeek);
},
/**
* The first day of the next page's month.
* @return {Date}
*/
firstOfNextMonth() {
const d = new Date(this.pageDate);
return new Date(this.utils.setMonth(d, this.utils.getMonth(d) + 1));
},
/**
* A look-up object created from 'highlighted' prop
* @return {Object}
*/
highlightedConfig() {
return new HighlightedDate(this.utils, this.disabledDates, this.highlighted).config;
},
/**
* Is the next month disabled?
* @return {Boolean}
*/
isNextDisabled() {
if (!this.disabledConfig.has.from) {
return false;
}
return this.disabledConfig.from.month <= this.pageMonth && this.disabledConfig.from.year <= this.pageYear;
},
/**
* Is the previous month disabled?
* @return {Boolean}
*/
isPreviousDisabled() {
if (!this.disabledConfig.has.to) {
return false;
}
return this.disabledConfig.to.month >= this.pageMonth && this.disabledConfig.to.year >= this.pageYear;
},
/**
* Returns the current page's month as an integer.
* @return {Number}
*/
pageMonth() {
return this.utils.getMonth(this.pageDate);
},
/**
* Display the current page's month & year as the title.
* @return {String}
*/
pageTitleDay() {
return this.translation.ymd ? `${this.currYearName} ${this.currMonthName}` : `${this.currMonthName} ${this.currYearName}`;
}
},
methods: {
/**
* Set up a new date object to the first day of the current 'page'
* @return Date
*/
firstCellDate() {
const d = this.pageDate;
const firstOfMonth = this.useUtc ? new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)) : new Date(d.getFullYear(), d.getMonth(), 1, d.getHours(), d.getMinutes());
return new Date(firstOfMonth.setDate(firstOfMonth.getDate() - this.daysFromPrevMonth));
},
/**
* Whether a day is disabled
* @param {Date} date to check if disabled
* @return {Boolean}
*/
isDisabledDate(date) {
return new DisabledDate(this.utils, this.disabledDates).isDateDisabled(date);
},
/**
* Whether a day is highlighted
* (only if it is not disabled already except when highlighted.includeDisabled is true)
* @param {Date} date to check if highlighted
* @return {Boolean}
*/
isHighlightedDate(date) {
const dateWithoutTime = this.utils.resetDateTime(date);
return new HighlightedDate(this.utils, this.disabledDates, this.highlighted).isDateHighlighted(dateWithoutTime);
},
/**
* Whether a day is highlighted and it is the last date
* in the highlighted range of dates
* @param {Date} date end highlight
* @return {Boolean}
*/
isHighlightEnd(date) {
const config = this.highlightedConfig;
return this.isHighlightedDate(date) && config.to.year === this.utils.getFullYear(date) && config.to.month === this.utils.getMonth(date) && config.to.day === this.utils.getDate(date);
},
/**
* Whether a day is highlighted and it is the first date
* in the highlighted range of dates
* @param {Date} date start highlight
* @return {Boolean}
*/
isHighlightStart(date) {
const config = this.highlightedConfig;
return this.isHighlightedDate(date) && config.from.year === this.utils.getFullYear(date) && config.from.month === this.utils.getMonth(date) && config.from.day === this.utils.getDate(date);
},
/**
* Whether a day is selected
* @param {Date} dObj to check if selected
* @return {Boolean}
*/
isSelectedDate(dObj) {
return this.selectedDate && this.utils.compareDates(this.selectedDate, dObj);
},
/**
* Defines the objects within the days array
* @param {id} id
* @param {Date} dObj
* @return {Object}
*/
// eslint-disable-next-line complexity
makeDay(id, dObj) {
const isNextMonth = dObj >= this.firstOfNextMonth;
const isPreviousMonth = dObj < this.pageDate;
const isSaturday = this.utils.getDay(dObj) === 6;
const isSunday = this.utils.getDay(dObj) === 0;
const showDate = this.showEdgeDates || !(isPreviousMonth || isNextMonth);
return {
date: showDate ? this.utils.getDate(dObj) : '',
timestamp: dObj.valueOf(),
isSelected: this.isSelectedDate(dObj),
isDisabled: showDate ? this.isDisabledDate(dObj) : true,
isHighlighted: this.isHighlightedDate(dObj),
isHighlightStart: this.isHighlightStart(dObj),
isHighlightEnd: this.isHighlightEnd(dObj),
isToday: this.utils.compareDates(dObj, new Date()),
isWeekend: isSaturday || isSunday,
isSaturday,
isSunday,
isPreviousMonth,
isNextMonth
};
}
}
};
/* script */
const __vue_script__$4 = script$4;
/* template */
var __vue_render__$3 = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _