@logscl/ng2-date-picker
Version:
https://github.com/vlio20/angular-datepicker
964 lines (953 loc) • 150 kB
JavaScript
import * as i0 from '@angular/core';
import { ElementRef, Injectable, EventEmitter, Output, HostBinding, Input, ChangeDetectionStrategy, ViewEncapsulation, Component, forwardRef, ViewChild, HostListener, Optional, Directive, NgModule } from '@angular/core';
import * as i4 from '@angular/forms';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule } from '@angular/forms';
import * as i3 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i5 from '@angular/cdk/overlay';
import { OverlayModule } from '@angular/cdk/overlay';
import dayjs from 'dayjs';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import isBetween from 'dayjs/plugin/isBetween';
import isoWeek from 'dayjs/plugin/isoWeek';
import customParseFormat from 'dayjs/plugin/customParseFormat';
var ECalendarMode;
(function (ECalendarMode) {
ECalendarMode[ECalendarMode["Day"] = 0] = "Day";
ECalendarMode[ECalendarMode["DayTime"] = 1] = "DayTime";
ECalendarMode[ECalendarMode["Month"] = 2] = "Month";
ECalendarMode[ECalendarMode["Time"] = 3] = "Time";
})(ECalendarMode || (ECalendarMode = {}));
var ECalendarValue;
(function (ECalendarValue) {
ECalendarValue[ECalendarValue["Dayjs"] = 1] = "Dayjs";
ECalendarValue[ECalendarValue["DayjsArr"] = 2] = "DayjsArr";
ECalendarValue[ECalendarValue["String"] = 3] = "String";
ECalendarValue[ECalendarValue["StringArr"] = 4] = "StringArr";
})(ECalendarValue || (ECalendarValue = {}));
var SelectEvent;
(function (SelectEvent) {
SelectEvent["INPUT"] = "input";
SelectEvent["SELECTION"] = "selection";
})(SelectEvent || (SelectEvent = {}));
dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);
dayjs.extend(isBetween);
dayjs.extend(isoWeek);
dayjs.extend(customParseFormat);
const dayjsRef = dayjs;
class UtilsService {
static debounce(func, wait) {
let timeout;
return function () {
const context = this, args = arguments;
timeout = clearTimeout(timeout);
setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
;
createArray(size) {
return new Array(size).fill(1);
}
convertToDayjs(date, format) {
if (!date) {
return null;
}
else if (typeof date === 'string') {
return dayjsRef(date, format);
}
else {
return dayjsRef(date.toDate());
}
}
isDateValid(date, format) {
if (date === '') {
return true;
}
return dayjsRef(date, format, true).isValid();
}
// todo:: add unit test
getDefaultDisplayDate(current, selected, allowMultiSelect, minDate) {
if (current) {
return dayjsRef(current.toDate());
}
else if (minDate && minDate.isAfter(dayjsRef())) {
return dayjsRef(minDate.toDate());
}
else if (allowMultiSelect) {
if (selected && selected[selected.length]) {
return dayjsRef(selected[selected.length].toDate());
}
}
else if (selected && selected[0]) {
return dayjsRef(selected[0].toDate());
}
return dayjsRef();
}
// todo:: add unit test
getInputType(value, allowMultiSelect) {
if (Array.isArray(value)) {
if (!value.length) {
return ECalendarValue.DayjsArr;
}
else if (typeof value[0] === 'string') {
return ECalendarValue.StringArr;
}
else if (dayjsRef.isDayjs(value[0])) {
return ECalendarValue.DayjsArr;
}
}
else {
if (typeof value === 'string') {
return ECalendarValue.String;
}
else if (dayjsRef.isDayjs(value)) {
return ECalendarValue.Dayjs;
}
}
return allowMultiSelect ? ECalendarValue.DayjsArr : ECalendarValue.Dayjs;
}
// todo:: add unit test
convertToDayjsArray(value, config) {
let retVal;
switch (this.getInputType(value, config.allowMultiSelect)) {
case (ECalendarValue.String):
retVal = value ? [dayjsRef(value, config.format, true)] : [];
break;
case (ECalendarValue.StringArr):
retVal = value.map(v => v ? dayjsRef(v, config.format, true) : null).filter(Boolean);
break;
case (ECalendarValue.Dayjs):
retVal = value ? [dayjsRef(value.toDate())] : [];
break;
case (ECalendarValue.DayjsArr):
retVal = (value || []).map(v => dayjsRef(v.toDate()));
break;
default:
retVal = [];
}
return retVal;
}
// todo:: add unit test
convertFromDayjsArray(format, value, convertTo) {
switch (convertTo) {
case (ECalendarValue.String):
return value[0] && value[0].format(format);
case (ECalendarValue.StringArr):
return value.filter(Boolean).map(v => v.format(format));
case (ECalendarValue.Dayjs):
return value[0] ? dayjsRef(value[0].toDate()) : value[0];
case (ECalendarValue.DayjsArr):
return value ? value.map(v => dayjsRef(v.toDate())) : value;
default:
return value;
}
}
convertToString(value, format) {
let tmpVal;
if (typeof value === 'string') {
tmpVal = [value];
}
else if (Array.isArray(value)) {
if (value.length) {
tmpVal = value.map((v) => {
return this.convertToDayjs(v, format).format(format);
});
}
else {
tmpVal = value;
}
}
else if (dayjsRef.isDayjs(value)) {
tmpVal = [value.format(format)];
}
else {
return '';
}
return tmpVal.filter(Boolean).join(' | ');
}
// todo:: add unit test
clearUndefined(obj) {
if (!obj) {
return obj;
}
Object.keys(obj).forEach((key) => (obj[key] === undefined) && delete obj[key]);
return obj;
}
updateSelected(isMultiple, currentlySelected, date, granularity = 'day') {
if (isMultiple) {
return !date.selected
? currentlySelected.concat([date.date])
: currentlySelected.filter(d => !d.isSame(date.date, granularity));
}
else {
return !date.selected ? [date.date] : [];
}
}
closestParent(element, selector) {
if (!element) {
return undefined;
}
const match = element.querySelector(selector);
return match || this.closestParent(element.parentElement, selector);
}
onlyTime(m) {
return m && dayjsRef.isDayjs(m) && dayjsRef(m.format('HH:mm:ss'), 'HH:mm:ss');
}
granularityFromType(calendarType) {
switch (calendarType) {
case 'time':
return 'second';
case 'daytime':
return 'second';
default:
return calendarType;
}
}
createValidator({ minDate, maxDate, minTime, maxTime }, format, calendarType) {
let isValid;
let value;
const validators = [];
const granularity = this.granularityFromType(calendarType);
if (minDate) {
const md = this.convertToDayjs(minDate, format);
validators.push({
key: 'minDate',
isValid: () => {
const _isValid = value.every(val => val.isSameOrAfter(md, granularity));
isValid = isValid ? _isValid : false;
return _isValid;
}
});
}
if (maxDate) {
const md = this.convertToDayjs(maxDate, format);
validators.push({
key: 'maxDate',
isValid: () => {
const _isValid = value.every(val => val.isSameOrBefore(md, granularity));
isValid = isValid ? _isValid : false;
return _isValid;
}
});
}
if (minTime) {
const md = this.onlyTime(this.convertToDayjs(minTime, format));
validators.push({
key: 'minTime',
isValid: () => {
const _isValid = value.every(val => this.onlyTime(val).isSameOrAfter(md));
isValid = isValid ? _isValid : false;
return _isValid;
}
});
}
if (maxTime) {
const md = this.onlyTime(this.convertToDayjs(maxTime, format));
validators.push({
key: 'maxTime',
isValid: () => {
const _isValid = value.every(val => this.onlyTime(val).isSameOrBefore(md));
isValid = isValid ? _isValid : false;
return _isValid;
}
});
}
return (inputVal) => {
isValid = true;
value = this.convertToDayjsArray(inputVal, {
format,
allowMultiSelect: true
}).filter(Boolean);
if (!value.every(val => val.isValid())) {
return {
format: {
given: inputVal
}
};
}
const errors = validators.reduce((map, err) => {
if (!err.isValid()) {
map[err.key] = {
given: value
};
}
return map;
}, {});
return !isValid ? errors : null;
};
}
datesStringToStringArray(value) {
return (value || '').split('|').map(m => m.trim()).filter(Boolean);
}
getValidDayjsArray(value, format) {
return this.datesStringToStringArray(value)
.filter(d => this.isDateValid(d, format))
.map(d => dayjsRef(d, format));
}
shouldShowCurrent(showGoToCurrent, mode, min, max) {
return showGoToCurrent &&
mode !== 'time' &&
this.isDateInRange(dayjsRef(), min, max);
}
isDateInRange(date, from, to) {
if (!date) {
return false;
}
if (!from && !to) {
return true;
}
if (!from && to) {
return date.isSameOrBefore(to);
}
if (from && !to) {
return date.isSameOrAfter(from);
}
return date.isBetween(from, to, 'day', '[]');
}
convertPropsToDayjs(obj, format, props) {
props.forEach((prop) => {
if (obj.hasOwnProperty(prop)) {
obj[prop] = this.convertToDayjs(obj[prop], format);
}
});
}
shouldResetCurrentView(prevConf, currentConf) {
if (prevConf && currentConf) {
if (!prevConf.min && currentConf.min) {
return true;
}
else if (prevConf.min && currentConf.min && !prevConf.min.isSame(currentConf.min, 'd')) {
return true;
}
else if (!prevConf.max && currentConf.max) {
return true;
}
else if (prevConf.max && currentConf.max && !prevConf.max.isSame(currentConf.max, 'd')) {
return true;
}
return false;
}
return false;
}
getNativeElement(elem) {
if (!elem) {
return null;
}
else if (typeof elem === 'string') {
return document.querySelector(elem);
}
else if (elem instanceof ElementRef) {
return elem.nativeElement;
}
else {
return elem;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: UtilsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: UtilsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class DayCalendarService {
constructor(utilsService) {
this.utilsService = utilsService;
this.DEFAULT_CONFIG = {
showNearMonthDays: true,
showWeekNumbers: false,
firstDayOfWeek: 'su',
weekDayFormat: 'ddd',
format: 'DD-MM-YYYY',
allowMultiSelect: false,
monthFormat: 'MMM, YYYY',
enableMonthSelector: true,
dayBtnFormat: 'DD',
unSelectOnClick: true
};
this.DAYS = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];
}
getConfig(config) {
const _config = {
...this.DEFAULT_CONFIG,
...this.utilsService.clearUndefined(config)
};
this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);
return _config;
}
generateDaysMap(firstDayOfWeek) {
const firstDayIndex = this.DAYS.indexOf(firstDayOfWeek);
const daysArr = this.DAYS.slice(firstDayIndex, 7).concat(this.DAYS.slice(0, firstDayIndex));
return daysArr.reduce((map, day, index) => {
map[day] = index;
return map;
}, {});
}
generateMonthArray(config, month, selected) {
const parsedMonth = month.isValid() ? dayjsRef(month.toDate()) : dayjsRef();
let monthArray = [];
const firstDayOfWeekIndex = this.DAYS.indexOf(config.firstDayOfWeek);
let firstDayOfBoard = parsedMonth.startOf('month');
while (firstDayOfBoard.day() !== firstDayOfWeekIndex) {
firstDayOfBoard = firstDayOfBoard.subtract(1, 'day');
}
let current = dayjsRef(firstDayOfBoard.toDate());
const prevMonth = parsedMonth.subtract(1, 'month');
const nextMonth = parsedMonth.add(1, 'month');
const today = dayjsRef();
const daysOfCalendar = this.utilsService.createArray(42)
.reduce((array) => {
array.push({
date: dayjsRef(current.toDate()),
selected: !!selected.find(selectedDay => current.isSame(selectedDay, 'day')),
currentMonth: current.isSame(parsedMonth, 'month'),
prevMonth: current.isSame(prevMonth, 'month'),
nextMonth: current.isSame(nextMonth, 'month'),
currentDay: current.isSame(today, 'day'),
disabled: this.isDateDisabled(current, config)
});
current = current.add(1, 'day');
return array;
}, []);
daysOfCalendar.forEach((day, index) => {
const weekIndex = Math.floor(index / 7);
if (!monthArray[weekIndex]) {
monthArray.push([]);
}
monthArray[weekIndex].push(day);
});
if (!config.showNearMonthDays) {
monthArray = this.removeNearMonthWeeks(parsedMonth, monthArray);
}
return monthArray;
}
generateWeekdays(firstDayOfWeek) {
const weekdayNames = {
su: dayjsRef().day(0),
mo: dayjsRef().day(1),
tu: dayjsRef().day(2),
we: dayjsRef().day(3),
th: dayjsRef().day(4),
fr: dayjsRef().day(5),
sa: dayjsRef().day(6)
};
const weekdays = [];
const daysMap = this.generateDaysMap(firstDayOfWeek);
for (const dayKey in daysMap) {
if (daysMap.hasOwnProperty(dayKey)) {
weekdays[daysMap[dayKey]] = weekdayNames[dayKey];
}
}
return weekdays;
}
isDateDisabled(date, config) {
if (config.isDayDisabledCallback) {
return config.isDayDisabledCallback(date);
}
if (config.min && date.isBefore(config.min, 'day')) {
return true;
}
return !!(config.max && date.isAfter(config.max, 'day'));
}
// todo:: add unit tests
getHeaderLabel(config, month) {
if (config.monthFormatter) {
return config.monthFormatter(month);
}
return month.format(config.monthFormat);
}
// todo:: add unit tests
shouldShowLeft(min, currentMonthView) {
return min ? min.isBefore(currentMonthView, 'month') : true;
}
// todo:: add unit tests
shouldShowRight(max, currentMonthView) {
return max ? max.isAfter(currentMonthView, 'month') : true;
}
generateDaysIndexMap(firstDayOfWeek) {
const firstDayIndex = this.DAYS.indexOf(firstDayOfWeek);
const daysArr = this.DAYS.slice(firstDayIndex, 7).concat(this.DAYS.slice(0, firstDayIndex));
return daysArr.reduce((map, day, index) => {
map[index] = day;
return map;
}, {});
}
getMonthCalendarConfig(componentConfig) {
return this.utilsService.clearUndefined({
min: componentConfig.min,
max: componentConfig.max,
format: componentConfig.format,
isNavHeaderBtnClickable: true,
allowMultiSelect: false,
yearFormat: componentConfig.yearFormat,
yearFormatter: componentConfig.yearFormatter,
monthBtnFormat: componentConfig.monthBtnFormat,
monthBtnFormatter: componentConfig.monthBtnFormatter,
monthBtnCssClassCallback: componentConfig.monthBtnCssClassCallback,
isMonthDisabledCallback: componentConfig.isMonthDisabledCallback,
multipleYearsNavigateBy: componentConfig.multipleYearsNavigateBy,
showMultipleYearsNavigation: componentConfig.showMultipleYearsNavigation,
showGoToCurrent: componentConfig.showGoToCurrent,
numOfMonthRows: componentConfig.numOfMonthRows
});
}
getDayBtnText(config, day) {
if (config.dayBtnFormatter) {
return config.dayBtnFormatter(day);
}
return day.format(config.dayBtnFormat);
}
getDayBtnCssClass(config, day) {
if (config.dayBtnCssClassCallback) {
return config.dayBtnCssClassCallback(day);
}
return '';
}
removeNearMonthWeeks(currentMonth, monthArray) {
if (monthArray[monthArray.length - 1].find((day) => day.date.isSame(currentMonth, 'month'))) {
return monthArray;
}
else {
return monthArray.slice(0, -1);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayCalendarService, deps: [{ token: UtilsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayCalendarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayCalendarService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: UtilsService }] });
const FIRST_PM_HOUR = 12;
class TimeSelectService {
constructor(utilsService) {
this.utilsService = utilsService;
this.DEFAULT_CONFIG = {
hours12Format: 'hh',
hours24Format: 'HH',
meridiemFormat: 'A',
minutesFormat: 'mm',
minutesInterval: 1,
secondsFormat: 'ss',
secondsInterval: 1,
showSeconds: false,
showTwentyFourHours: false,
timeSeparator: ':',
};
}
getConfig(config) {
const timeConfigs = {
maxTime: this.utilsService.onlyTime(config && config.maxTime),
minTime: this.utilsService.onlyTime(config && config.minTime)
};
return {
...this.DEFAULT_CONFIG,
...this.utilsService.clearUndefined(config),
...timeConfigs
};
}
getTimeFormat(config) {
return (config.showTwentyFourHours ? config.hours24Format : config.hours12Format)
+ config.timeSeparator + config.minutesFormat
+ (config.showSeconds ? (config.timeSeparator + config.secondsFormat) : '')
+ (config.showTwentyFourHours ? '' : ' ' + config.meridiemFormat);
}
getHours(config, t) {
const time = t || dayjsRef();
return time && time.format(config.showTwentyFourHours ? config.hours24Format : config.hours12Format);
}
getMinutes(config, t) {
const time = t || dayjsRef();
return time && time.format(config.minutesFormat);
}
getSeconds(config, t) {
const time = t || dayjsRef();
return time && time.format(config.secondsFormat);
}
getMeridiem(config, time) {
return time && time.format(config.meridiemFormat);
}
decrease(config, time, unit) {
let amount = 1;
switch (unit) {
case 'minute':
amount = config.minutesInterval;
break;
case 'second':
amount = config.secondsInterval;
break;
}
return time.subtract(amount, unit);
}
increase(config, time, unit) {
let amount = 1;
switch (unit) {
case 'minute':
amount = config.minutesInterval;
break;
case 'second':
amount = config.secondsInterval;
break;
}
return time.add(amount, unit);
}
toggleMeridiem(time) {
if (time.hour() < FIRST_PM_HOUR) {
return time.add(12, 'hour');
}
else {
return time.subtract(12, 'hour');
}
}
shouldShowDecrease(config, time, unit) {
if (!config.min && !config.minTime) {
return true;
}
const newTime = this.decrease(config, time, unit);
return (!config.min || config.min.isSameOrBefore(newTime))
&& (!config.minTime || config.minTime.isSameOrBefore(this.utilsService.onlyTime(newTime)));
}
shouldShowIncrease(config, time, unit) {
if (!config.max && !config.maxTime) {
return true;
}
const newTime = this.increase(config, time, unit);
return (!config.max || config.max.isSameOrAfter(newTime))
&& (!config.maxTime || config.maxTime.isSameOrAfter(this.utilsService.onlyTime(newTime)));
}
shouldShowToggleMeridiem(config, time) {
if (!config.min && !config.max && !config.minTime && !config.maxTime) {
return true;
}
const newTime = this.toggleMeridiem(time);
return (!config.max || config.max.isSameOrAfter(newTime))
&& (!config.min || config.min.isSameOrBefore(newTime))
&& (!config.maxTime || config.maxTime.isSameOrAfter(this.utilsService.onlyTime(newTime)))
&& (!config.minTime || config.minTime.isSameOrBefore(this.utilsService.onlyTime(newTime)));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TimeSelectService, deps: [{ token: UtilsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TimeSelectService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TimeSelectService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: UtilsService }] });
const DAY_FORMAT = 'YYYYMMDD';
const TIME_FORMAT = 'HH:mm:ss';
const COMBINED_FORMAT = DAY_FORMAT + TIME_FORMAT;
class DayTimeCalendarService {
constructor(utilsService, dayCalendarService, timeSelectService) {
this.utilsService = utilsService;
this.dayCalendarService = dayCalendarService;
this.timeSelectService = timeSelectService;
this.DEFAULT_CONFIG = {};
}
getConfig(config) {
const _config = {
...this.DEFAULT_CONFIG,
...this.timeSelectService.getConfig(config),
...this.dayCalendarService.getConfig(config)
};
this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);
return _config;
}
updateDay(current, day, config) {
const time = current ? current : dayjsRef();
let updated = dayjsRef(day.format(DAY_FORMAT) + time.format(TIME_FORMAT), COMBINED_FORMAT);
if (config.min) {
const min = config.min;
updated = min.isAfter(updated) ? min : updated;
}
if (config.max) {
const max = config.max;
updated = max.isBefore(updated) ? max : updated;
}
return updated;
}
updateTime(current, time) {
const day = current ? current : dayjsRef();
return dayjsRef(day.format(DAY_FORMAT) + time.format(TIME_FORMAT), COMBINED_FORMAT);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayTimeCalendarService, deps: [{ token: UtilsService }, { token: DayCalendarService }, { token: TimeSelectService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayTimeCalendarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DayTimeCalendarService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: UtilsService }, { type: DayCalendarService }, { type: TimeSelectService }] });
class DatePickerService {
constructor(utilsService, timeSelectService, daytimeCalendarService) {
this.utilsService = utilsService;
this.timeSelectService = timeSelectService;
this.daytimeCalendarService = daytimeCalendarService;
this.onPickerClosed = new EventEmitter();
this.defaultConfig = {
closeOnSelect: true,
closeOnSelectDelay: 100,
closeOnEnter: true,
format: 'DD-MM-YYYY',
openOnFocus: true,
openOnClick: true,
onOpenDelay: 0,
disableKeypress: false,
showNearMonthDays: true,
showWeekNumbers: false,
enableMonthSelector: true,
showGoToCurrent: true,
hideOnOutsideClick: true,
};
}
// todo:: add unit tests
getConfig(config, mode = 'daytime') {
const _config = {
...this.defaultConfig,
format: DatePickerService.getDefaultFormatByMode(mode),
...this.utilsService.clearUndefined(config)
};
this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);
if (config && config.allowMultiSelect && config.closeOnSelect === undefined) {
_config.closeOnSelect = false;
}
return _config;
}
getDayConfigService(pickerConfig) {
return {
min: pickerConfig.min,
max: pickerConfig.max,
isDayDisabledCallback: pickerConfig.isDayDisabledCallback,
weekDayFormat: pickerConfig.weekDayFormat,
weekDayFormatter: pickerConfig.weekDayFormatter,
showNearMonthDays: pickerConfig.showNearMonthDays,
showWeekNumbers: pickerConfig.showWeekNumbers,
firstDayOfWeek: pickerConfig.firstDayOfWeek,
format: pickerConfig.format,
allowMultiSelect: pickerConfig.allowMultiSelect,
monthFormat: pickerConfig.monthFormat,
monthFormatter: pickerConfig.monthFormatter,
enableMonthSelector: pickerConfig.enableMonthSelector,
yearFormat: pickerConfig.yearFormat,
yearFormatter: pickerConfig.yearFormatter,
dayBtnFormat: pickerConfig.dayBtnFormat,
dayBtnFormatter: pickerConfig.dayBtnFormatter,
dayBtnCssClassCallback: pickerConfig.dayBtnCssClassCallback,
monthBtnFormat: pickerConfig.monthBtnFormat,
monthBtnFormatter: pickerConfig.monthBtnFormatter,
monthBtnCssClassCallback: pickerConfig.monthBtnCssClassCallback,
isMonthDisabledCallback: pickerConfig.isMonthDisabledCallback,
multipleYearsNavigateBy: pickerConfig.multipleYearsNavigateBy,
showMultipleYearsNavigation: pickerConfig.showMultipleYearsNavigation,
returnedValueType: pickerConfig.returnedValueType,
showGoToCurrent: pickerConfig.showGoToCurrent,
unSelectOnClick: pickerConfig.unSelectOnClick,
numOfMonthRows: pickerConfig.numOfMonthRows
};
}
getDayTimeConfig(pickerConfig) {
return this.daytimeCalendarService.getConfig(pickerConfig);
}
getTimeConfig(pickerConfig) {
return this.timeSelectService.getConfig(pickerConfig);
}
pickerClosed() {
this.onPickerClosed.emit();
}
// todo:: add unit tests
isValidInputDateValue(value, config) {
value = value ? value : '';
const datesStrArr = this.utilsService.datesStringToStringArray(value);
return datesStrArr.every(date => this.utilsService.isDateValid(date, config.format));
}
// todo:: add unit tests
convertInputValueToDayjsArray(value, config) {
value = value ? value : '';
const datesStrArr = this.utilsService.datesStringToStringArray(value);
return this.utilsService.convertToDayjsArray(datesStrArr, config);
}
getOverlayPosition({ drops, opens }) {
if (!drops && !opens) {
return undefined;
}
return [{
originX: opens ? opens === 'left' ? 'start' : 'end' : 'start',
originY: drops ? drops === 'up' ? 'top' : 'bottom' : 'bottom',
overlayX: opens ? opens === 'left' ? 'start' : 'end' : 'start',
overlayY: drops ? drops === 'up' ? 'bottom' : 'top' : 'top',
}];
}
static getDefaultFormatByMode(mode) {
switch (mode) {
case 'day':
return 'DD-MM-YYYY';
case 'daytime':
return 'DD-MM-YYYY HH:mm:ss';
case 'time':
return 'HH:mm:ss';
case 'month':
return 'MMM, YYYY';
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DatePickerService, deps: [{ token: UtilsService }, { token: TimeSelectService }, { token: DayTimeCalendarService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DatePickerService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DatePickerService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: UtilsService }, { type: TimeSelectService }, { type: DayTimeCalendarService }] });
class MonthCalendarService {
constructor(utilsService) {
this.utilsService = utilsService;
this.DEFAULT_CONFIG = {
allowMultiSelect: false,
yearFormat: 'YYYY',
format: 'MM-YYYY',
isNavHeaderBtnClickable: false,
monthBtnFormat: 'MMM',
multipleYearsNavigateBy: 10,
showMultipleYearsNavigation: false,
unSelectOnClick: true,
numOfMonthRows: 3
};
}
getConfig(config) {
const _config = {
...this.DEFAULT_CONFIG,
...this.utilsService.clearUndefined(config)
};
MonthCalendarService.validateConfig(_config);
this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);
return _config;
}
generateYear(config, year, selected = null) {
let index = year.startOf('year');
return this.utilsService.createArray(config.numOfMonthRows).map(() => {
return this.utilsService.createArray(12 / config.numOfMonthRows).map(() => {
const date = dayjsRef(index);
const month = {
date,
selected: !!selected.find(s => index.isSame(s, 'month')),
currentMonth: index.isSame(dayjsRef(), 'month'),
disabled: this.isMonthDisabled(date, config),
text: this.getMonthBtnText(config, date)
};
index = index.add(1, 'month');
return month;
});
});
}
isMonthDisabled(date, config) {
if (config.isMonthDisabledCallback) {
return config.isMonthDisabledCallback(date);
}
if (config.min && date.isBefore(config.min, 'month')) {
return true;
}
return !!(config.max && date.isAfter(config.max, 'month'));
}
shouldShowLeft(min, currentMonthView) {
return min ? min.isBefore(currentMonthView, 'year') : true;
}
shouldShowRight(max, currentMonthView) {
return max ? max.isAfter(currentMonthView, 'year') : true;
}
getHeaderLabel(config, year) {
if (config.yearFormatter) {
return config.yearFormatter(year);
}
return year.format(config.yearFormat);
}
getMonthBtnText(config, month) {
if (config.monthBtnFormatter) {
return config.monthBtnFormatter(month);
}
return month.format(config.monthBtnFormat);
}
getMonthBtnCssClass(config, month) {
if (config.monthBtnCssClassCallback) {
return config.monthBtnCssClassCallback(month);
}
return '';
}
static validateConfig(config) {
if (config.numOfMonthRows < 1 || config.numOfMonthRows > 12 || !Number.isInteger(12 / config.numOfMonthRows)) {
throw new Error('numOfMonthRows has to be between 1 - 12 and divide 12 to integer');
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: MonthCalendarService, deps: [{ token: UtilsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: MonthCalendarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: MonthCalendarService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: UtilsService }] });
class CalendarNavComponent {
constructor() {
this.isLabelClickable = false;
this.showLeftNav = true;
this.showLeftSecondaryNav = false;
this.showRightNav = true;
this.showRightSecondaryNav = false;
this.leftNavDisabled = false;
this.leftSecondaryNavDisabled = false;
this.rightNavDisabled = false;
this.rightSecondaryNavDisabled = false;
this.showGoToCurrent = true;
this.onLeftNav = new EventEmitter();
this.onLeftSecondaryNav = new EventEmitter();
this.onRightNav = new EventEmitter();
this.onRightSecondaryNav = new EventEmitter();
this.onLabelClick = new EventEmitter();
this.onGoToCurrent = new EventEmitter();
}
leftNavClicked() {
this.onLeftNav.emit();
}
leftSecondaryNavClicked() {
this.onLeftSecondaryNav.emit();
}
rightNavClicked() {
this.onRightNav.emit();
}
rightSecondaryNavClicked() {
this.onRightSecondaryNav.emit();
}
labelClicked() {
this.onLabelClick.emit();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CalendarNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: CalendarNavComponent, isStandalone: false, selector: "dp-calendar-nav", inputs: { label: "label", isLabelClickable: "isLabelClickable", showLeftNav: "showLeftNav", showLeftSecondaryNav: "showLeftSecondaryNav", showRightNav: "showRightNav", showRightSecondaryNav: "showRightSecondaryNav", leftNavDisabled: "leftNavDisabled", leftSecondaryNavDisabled: "leftSecondaryNavDisabled", rightNavDisabled: "rightNavDisabled", rightSecondaryNavDisabled: "rightSecondaryNavDisabled", showGoToCurrent: "showGoToCurrent", theme: "theme" }, outputs: { onLeftNav: "onLeftNav", onLeftSecondaryNav: "onLeftSecondaryNav", onRightNav: "onRightNav", onRightSecondaryNav: "onRightSecondaryNav", onLabelClick: "onLabelClick", onGoToCurrent: "onGoToCurrent" }, host: { properties: { "class": "this.theme" } }, ngImport: i0, template: "<div class=\"dp-calendar-nav-container\" dir=\"ltr\">\n <div class=\"dp-nav-header\">\n <span [attr.data-hidden]=\"isLabelClickable\"\n [hidden]=\"isLabelClickable\"\n [innerText]=\"label\">\n </span>\n <button (click)=\"labelClicked()\"\n [attr.data-hidden]=\"!isLabelClickable\"\n [hidden]=\"!isLabelClickable\"\n [innerText]=\"label\"\n class=\"dp-nav-header-btn\"\n type=\"button\">\n </button>\n </div>\n\n <div class=\"dp-nav-btns-container\">\n <div class=\"dp-calendar-nav-container-left\">\n <button (click)=\"leftSecondaryNavClicked()\"\n *ngIf=\"showLeftSecondaryNav\"\n [disabled]=\"leftSecondaryNavDisabled\"\n class=\"dp-calendar-secondary-nav-left\"\n type=\"button\">\n </button>\n <button (click)=\"leftNavClicked()\"\n [attr.data-hidden]=\"!showLeftNav\"\n [disabled]=\"leftNavDisabled\"\n [hidden]=\"!showLeftNav\"\n class=\"dp-calendar-nav-left\"\n type=\"button\">\n </button>\n </div>\n <button (click)=\"onGoToCurrent.emit()\"\n *ngIf=\"showGoToCurrent\"\n class=\"dp-current-location-btn\"\n type=\"button\">\n </button>\n <div class=\"dp-calendar-nav-container-right\">\n <button (click)=\"rightNavClicked()\"\n [attr.data-hidden]=\"!showRightNav\"\n [disabled]=\"rightNavDisabled\"\n [hidden]=\"!showRightNav\"\n class=\"dp-calendar-nav-right\"\n type=\"button\">\n </button>\n <button (click)=\"rightSecondaryNavClicked()\"\n *ngIf=\"showRightSecondaryNav\"\n [disabled]=\"rightSecondaryNavDisabled\"\n class=\"dp-calendar-secondary-nav-right\"\n type=\"button\">\n </button>\n </div>\n </div>\n</div>\n", styles: ["dp-calendar-nav .dp-calendar-nav-container{position:relative;box-sizing:border-box;height:25px;border:1px solid #000000;border-bottom:none}dp-calendar-nav .dp-nav-date-btn{box-sizing:border-box;height:25px;border:1px solid #000000;border-bottom:none}dp-calendar-nav .dp-nav-btns-container{position:absolute;top:50%;transform:translateY(-50%);right:5px;display:inline-block}dp-calendar-nav .dp-calendar-nav-container-left,dp-calendar-nav .dp-calendar-nav-container-right{display:inline-block}dp-calendar-nav .dp-calendar-nav-left,dp-calendar-nav .dp-calendar-nav-right,dp-calendar-nav .dp-calendar-secondary-nav-left,dp-calendar-nav .dp-calendar-secondary-nav-right{position:relative;width:16px;cursor:pointer}dp-calendar-nav .dp-calendar-nav-left,dp-calendar-nav .dp-calendar-nav-right{line-height:0}dp-calendar-nav .dp-calendar-nav-left:before,dp-calendar-nav .dp-calendar-nav-right:before{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(45deg)}dp-calendar-nav .dp-calendar-secondary-nav-left,dp-calendar-nav .dp-calendar-secondary-nav-right{padding:0}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-right:before,dp-calendar-nav .dp-calendar-secondary-nav-left:after,dp-calendar-nav .dp-calendar-secondary-nav-right:after{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(45deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-right:before{right:-10px}dp-calendar-nav .dp-calendar-secondary-nav-right{left:initial;right:5px}dp-calendar-nav .dp-calendar-nav-left:before{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(-135deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-left:after{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(-135deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before{right:-10px}dp-calendar-nav .dp-nav-header{position:absolute;top:50%;transform:translateY(-50%);left:5px;display:inline-block;font-size:13px}dp-calendar-nav .dp-nav-header-btn{cursor:pointer}dp-calendar-nav .dp-current-location-btn{position:relative;top:-1px;height:16px;width:16px;vertical-align:middle;background:#0009;border:1px solid rgba(0,0,0,.6);outline:none;border-radius:50%;box-shadow:inset 0 0 0 3px #fff;cursor:pointer}dp-calendar-nav .dp-current-location-btn:hover{background:#000}dp-calendar-nav.dp-material .dp-calendar-nav-container{height:30px;border:1px solid #E0E0E0}dp-calendar-nav.dp-material .dp-calendar-nav-left,dp-calendar-nav.dp-material .dp-calendar-nav-right,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-left,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-right{border:none;background:#fff;outline:none;font-size:16px;padding:0}dp-calendar-nav.dp-material .dp-calendar-secondary-nav-left,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-right{width:20px}dp-calendar-nav.dp-material .dp-nav-header-btn{height:20px;width:80px;border:none;background:#fff;outline:none}dp-calendar-nav.dp-material .dp-nav-header-btn:hover{background:#0000000d}dp-calendar-nav.dp-material .dp-nav-header-btn:active{background:#0000001a}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵɵDir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CalendarNavComponent, decorators: [{
type: Component,
args: [{ selector: 'dp-calendar-nav', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div class=\"dp-calendar-nav-container\" dir=\"ltr\">\n <div class=\"dp-nav-header\">\n <span [attr.data-hidden]=\"isLabelClickable\"\n [hidden]=\"isLabelClickable\"\n [innerText]=\"label\">\n </span>\n <button (click)=\"labelClicked()\"\n [attr.data-hidden]=\"!isLabelClickable\"\n [hidden]=\"!isLabelClickable\"\n [innerText]=\"label\"\n class=\"dp-nav-header-btn\"\n type=\"button\">\n </button>\n </div>\n\n <div class=\"dp-nav-btns-container\">\n <div class=\"dp-calendar-nav-container-left\">\n <button (click)=\"leftSecondaryNavClicked()\"\n *ngIf=\"showLeftSecondaryNav\"\n [disabled]=\"leftSecondaryNavDisabled\"\n class=\"dp-calendar-secondary-nav-left\"\n type=\"button\">\n </button>\n <button (click)=\"leftNavClicked()\"\n [attr.data-hidden]=\"!showLeftNav\"\n [disabled]=\"leftNavDisabled\"\n [hidden]=\"!showLeftNav\"\n class=\"dp-calendar-nav-left\"\n type=\"button\">\n </button>\n </div>\n <button (click)=\"onGoToCurrent.emit()\"\n *ngIf=\"showGoToCurrent\"\n class=\"dp-current-location-btn\"\n type=\"button\">\n </button>\n <div class=\"dp-calendar-nav-container-right\">\n <button (click)=\"rightNavClicked()\"\n [attr.data-hidden]=\"!showRightNav\"\n [disabled]=\"rightNavDisabled\"\n [hidden]=\"!showRightNav\"\n class=\"dp-calendar-nav-right\"\n type=\"button\">\n </button>\n <button (click)=\"rightSecondaryNavClicked()\"\n *ngIf=\"showRightSecondaryNav\"\n [disabled]=\"rightSecondaryNavDisabled\"\n class=\"dp-calendar-secondary-nav-right\"\n type=\"button\">\n </button>\n </div>\n </div>\n</div>\n", styles: ["dp-calendar-nav .dp-calendar-nav-container{position:relative;box-sizing:border-box;height:25px;border:1px solid #000000;border-bottom:none}dp-calendar-nav .dp-nav-date-btn{box-sizing:border-box;height:25px;border:1px solid #000000;border-bottom:none}dp-calendar-nav .dp-nav-btns-container{position:absolute;top:50%;transform:translateY(-50%);right:5px;display:inline-block}dp-calendar-nav .dp-calendar-nav-container-left,dp-calendar-nav .dp-calendar-nav-container-right{display:inline-block}dp-calendar-nav .dp-calendar-nav-left,dp-calendar-nav .dp-calendar-nav-right,dp-calendar-nav .dp-calendar-secondary-nav-left,dp-calendar-nav .dp-calendar-secondary-nav-right{position:relative;width:16px;cursor:pointer}dp-calendar-nav .dp-calendar-nav-left,dp-calendar-nav .dp-calendar-nav-right{line-height:0}dp-calendar-nav .dp-calendar-nav-left:before,dp-calendar-nav .dp-calendar-nav-right:before{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(45deg)}dp-calendar-nav .dp-calendar-secondary-nav-left,dp-calendar-nav .dp-calendar-secondary-nav-right{padding:0}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-right:before,dp-calendar-nav .dp-calendar-secondary-nav-left:after,dp-calendar-nav .dp-calendar-secondary-nav-right:after{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(45deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-right:before{right:-10px}dp-calendar-nav .dp-calendar-secondary-nav-right{left:initial;right:5px}dp-calendar-nav .dp-calendar-nav-left:before{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(-135deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before,dp-calendar-nav .dp-calendar-secondary-nav-left:after{position:relative;content:\"\";display:inline-block;height:8px;width:8px;vertical-align:baseline;border-style:solid;border-width:2px 2px 0 0;transform:rotate(-135deg)}dp-calendar-nav .dp-calendar-secondary-nav-left:before{right:-10px}dp-calendar-nav .dp-nav-header{position:absolute;top:50%;transform:translateY(-50%);left:5px;display:inline-block;font-size:13px}dp-calendar-nav .dp-nav-header-btn{cursor:pointer}dp-calendar-nav .dp-current-location-btn{position:relative;top:-1px;height:16px;width:16px;vertical-align:middle;background:#0009;border:1px solid rgba(0,0,0,.6);outline:none;border-radius:50%;box-shadow:inset 0 0 0 3px #fff;cursor:pointer}dp-calendar-nav .dp-current-location-btn:hover{background:#000}dp-calendar-nav.dp-material .dp-calendar-nav-container{height:30px;border:1px solid #E0E0E0}dp-calendar-nav.dp-material .dp-calendar-nav-left,dp-calendar-nav.dp-material .dp-calendar-nav-right,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-left,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-right{border:none;background:#fff;outline:none;font-size:16px;padding:0}dp-calendar-nav.dp-material .dp-calendar-secondary-nav-left,dp-calendar-nav.dp-material .dp-calendar-secondary-nav-right{width:20px}dp-calendar-nav.dp-material .dp-nav-header-btn{height:20px;width:80px;border:none;background:#fff;outline:none}dp-calendar-nav.dp-material .dp-nav-header-btn:hover{background:#0000000d}dp-calendar-nav.dp-material .dp-nav-header-btn:active{background:#0000001a}\n"] }]
}], propDecorators: { label: [{
type: Input
}], isLabelClickable: [{
type: Input
}], showLeftNav: [{
type: Input
}], showLeftSecondaryNav: [{
type: Input
}], showRightNav: [{
type: Input
}], showRightSecondaryNav: [{
type: Input
}], leftNavDisabled: [{
type: Input
}], leftSecondaryNavDisabled: [{
type: