UNPKG

@logscl/ng2-date-picker

Version:

https://github.com/vlio20/angular-datepicker

1 lines 197 kB
{"version":3,"file":"logscl-ng2-date-picker.mjs","sources":["../../../projects/ng2-date-picker/src/lib/common/types/calendar-mode-enum.ts","../../../projects/ng2-date-picker/src/lib/common/types/calendar-value-enum.ts","../../../projects/ng2-date-picker/src/lib/common/types/selection-event.enum.ts","../../../projects/ng2-date-picker/src/lib/common/dayjs/dayjs.ref.ts","../../../projects/ng2-date-picker/src/lib/common/services/utils/utils.service.ts","../../../projects/ng2-date-picker/src/lib/day-calendar/day-calendar.service.ts","../../../projects/ng2-date-picker/src/lib/time-select/time-select.service.ts","../../../projects/ng2-date-picker/src/lib/day-time-calendar/day-time-calendar.service.ts","../../../projects/ng2-date-picker/src/lib/date-picker/date-picker.service.ts","../../../projects/ng2-date-picker/src/lib/month-calendar/month-calendar.service.ts","../../../projects/ng2-date-picker/src/lib/calendar-nav/calendar-nav.component.ts","../../../projects/ng2-date-picker/src/lib/calendar-nav/calendar-nav.component.html","../../../projects/ng2-date-picker/src/lib/month-calendar/month-calendar.component.ts","../../../projects/ng2-date-picker/src/lib/month-calendar/month-calendar.component.html","../../../projects/ng2-date-picker/src/lib/day-calendar/day-calendar.component.ts","../../../projects/ng2-date-picker/src/lib/day-calendar/day-calendar.component.html","../../../projects/ng2-date-picker/src/lib/time-select/time-select.component.ts","../../../projects/ng2-date-picker/src/lib/time-select/time-select.component.html","../../../projects/ng2-date-picker/src/lib/day-time-calendar/day-time-calendar.component.ts","../../../projects/ng2-date-picker/src/lib/day-time-calendar/day-time-calendar.component.html","../../../projects/ng2-date-picker/src/lib/date-picker/date-picker.component.ts","../../../projects/ng2-date-picker/src/lib/date-picker/date-picker.component.html","../../../projects/ng2-date-picker/src/lib/date-picker/date-picker.directive.ts","../../../projects/ng2-date-picker/src/lib/date-picker.module.ts","../../../projects/ng2-date-picker/src/logscl-ng2-date-picker.ts"],"sourcesContent":["export enum ECalendarMode {\n Day,\n DayTime,\n Month,\n Time\n}\n","export enum ECalendarValue {\n Dayjs = 1,\n DayjsArr,\n String,\n StringArr\n}\n","export enum SelectEvent {\n INPUT = 'input',\n SELECTION = 'selection'\n}\n","import dayjs from 'dayjs';\nimport isSameOrAfter from 'dayjs/plugin/isSameOrAfter';\nimport isSameOrBefore from 'dayjs/plugin/isSameOrBefore';\nimport isBetween from 'dayjs/plugin/isBetween';\nimport isoWeek from 'dayjs/plugin/isoWeek';\nimport customParseFormat from 'dayjs/plugin/customParseFormat';\n\ndayjs.extend(isSameOrAfter);\ndayjs.extend(isSameOrBefore);\ndayjs.extend(isBetween);\ndayjs.extend(isoWeek);\ndayjs.extend(customParseFormat);\n\nexport const dayjsRef = dayjs;\n","import {ECalendarValue} from '../../types/calendar-value-enum';\nimport {SingleCalendarValue} from '../../types/single-calendar-value';\nimport {ElementRef, Injectable} from '@angular/core';\n\nimport {Dayjs, UnitType} from 'dayjs';\nimport {CalendarValue} from '../../types/calendar-value';\nimport {IDate} from '../../models/date.model';\nimport {CalendarMode} from '../../types/calendar-mode';\nimport {DateValidator} from '../../types/validator.type';\nimport {ICalendarInternal} from '../../models/calendar.model';\nimport {dayjsRef} from '../../dayjs/dayjs.ref';\n\nexport interface DateLimits {\n minDate?: SingleCalendarValue;\n maxDate?: SingleCalendarValue;\n minTime?: SingleCalendarValue;\n maxTime?: SingleCalendarValue;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class UtilsService {\n static debounce(func: Function, wait: number) {\n let timeout;\n return function () {\n const context = this, args = arguments;\n timeout = clearTimeout(timeout);\n setTimeout(() => {\n func.apply(context, args);\n }, wait);\n };\n };\n\n createArray(size: number): number[] {\n return new Array(size).fill(1);\n }\n\n convertToDayjs(date: SingleCalendarValue, format: string): Dayjs {\n if (!date) {\n return null;\n } else if (typeof date === 'string') {\n return dayjsRef(date, format);\n } else {\n return dayjsRef(date.toDate());\n }\n }\n\n isDateValid(date: string, format: string): boolean {\n if (date === '') {\n return true;\n }\n\n return dayjsRef(date, format, true).isValid();\n }\n\n // todo:: add unit test\n getDefaultDisplayDate(current: Dayjs,\n selected: Dayjs[],\n allowMultiSelect: boolean,\n minDate: Dayjs): Dayjs {\n if (current) {\n return dayjsRef(current.toDate());\n } else if (minDate && minDate.isAfter(dayjsRef())) {\n return dayjsRef(minDate.toDate());\n } else if (allowMultiSelect) {\n if (selected && selected[selected.length]) {\n return dayjsRef(selected[selected.length].toDate());\n }\n } else if (selected && selected[0]) {\n return dayjsRef(selected[0].toDate());\n }\n\n return dayjsRef();\n }\n\n // todo:: add unit test\n getInputType(value: CalendarValue, allowMultiSelect: boolean): ECalendarValue {\n if (Array.isArray(value)) {\n if (!value.length) {\n return ECalendarValue.DayjsArr;\n } else if (typeof value[0] === 'string') {\n return ECalendarValue.StringArr;\n } else if (dayjsRef.isDayjs(value[0])) {\n return ECalendarValue.DayjsArr;\n }\n } else {\n if (typeof value === 'string') {\n return ECalendarValue.String;\n } else if (dayjsRef.isDayjs(value)) {\n return ECalendarValue.Dayjs;\n }\n }\n\n return allowMultiSelect ? ECalendarValue.DayjsArr : ECalendarValue.Dayjs;\n }\n\n // todo:: add unit test\n convertToDayjsArray(value: CalendarValue,\n config: { allowMultiSelect?: boolean, format?: string }): Dayjs[] {\n let retVal: Dayjs[];\n switch (this.getInputType(value, config.allowMultiSelect)) {\n case (ECalendarValue.String):\n retVal = value ? [dayjsRef(<string>value, config.format, true)] : [];\n break;\n case (ECalendarValue.StringArr):\n retVal = (<string[]>value).map(v => v ? dayjsRef(v, config.format, true) : null).filter(Boolean);\n break;\n case (ECalendarValue.Dayjs):\n retVal = value ? [dayjsRef((<Dayjs>value).toDate())] : [];\n break;\n case (ECalendarValue.DayjsArr):\n retVal = (<Dayjs[]>value || []).map(v => dayjsRef(v.toDate()));\n break;\n default:\n retVal = [];\n }\n\n return retVal;\n }\n\n // todo:: add unit test\n convertFromDayjsArray(format: string,\n value: Dayjs[],\n convertTo: ECalendarValue): CalendarValue {\n switch (convertTo) {\n case (ECalendarValue.String):\n return value[0] && value[0].format(format);\n case (ECalendarValue.StringArr):\n return value.filter(Boolean).map(v => v.format(format));\n case (ECalendarValue.Dayjs):\n return value[0] ? dayjsRef(value[0].toDate()) : value[0];\n case (ECalendarValue.DayjsArr):\n return value ? value.map(v => dayjsRef(v.toDate())) : value;\n default:\n return value;\n }\n }\n\n convertToString(value: CalendarValue, format: string): string {\n let tmpVal: string[];\n\n if (typeof value === 'string') {\n tmpVal = [value];\n } else if (Array.isArray(value)) {\n if (value.length) {\n tmpVal = (<SingleCalendarValue[]>value).map((v) => {\n return this.convertToDayjs(v, format).format(format);\n });\n } else {\n tmpVal = <string[]>value;\n }\n } else if (dayjsRef.isDayjs(value)) {\n tmpVal = [value.format(format)];\n } else {\n return '';\n }\n\n return tmpVal.filter(Boolean).join(' | ');\n }\n\n // todo:: add unit test\n clearUndefined<T>(obj: T): T {\n if (!obj) {\n return obj;\n }\n\n Object.keys(obj).forEach((key) => (obj[key] === undefined) && delete obj[key]);\n return obj;\n }\n\n updateSelected(isMultiple: boolean,\n currentlySelected: Dayjs[],\n date: IDate,\n granularity: UnitType = 'day'): Dayjs[] {\n if (isMultiple) {\n return !date.selected\n ? currentlySelected.concat([date.date])\n : currentlySelected.filter(d => !d.isSame(date.date, granularity));\n } else {\n return !date.selected ? [date.date] : [];\n }\n }\n\n closestParent(element: HTMLElement, selector: string): HTMLElement {\n if (!element) {\n return undefined;\n }\n const match = <HTMLElement>element.querySelector(selector);\n return match || this.closestParent(element.parentElement, selector);\n }\n\n onlyTime(m: Dayjs): Dayjs {\n return m && dayjsRef.isDayjs(m) && dayjsRef(m.format('HH:mm:ss'), 'HH:mm:ss');\n }\n\n granularityFromType(calendarType: CalendarMode): UnitType {\n switch (calendarType) {\n case 'time':\n return 'second';\n case 'daytime':\n return 'second';\n default:\n return calendarType;\n }\n }\n\n createValidator({minDate, maxDate, minTime, maxTime}: DateLimits,\n format: string,\n calendarType: CalendarMode): DateValidator {\n let isValid: boolean;\n let value: Dayjs[];\n const validators = [];\n const granularity = this.granularityFromType(calendarType);\n\n if (minDate) {\n const md = this.convertToDayjs(minDate, format);\n validators.push({\n key: 'minDate',\n isValid: () => {\n const _isValid = value.every(val => val.isSameOrAfter(md, granularity));\n isValid = isValid ? _isValid : false;\n return _isValid;\n }\n });\n }\n\n if (maxDate) {\n const md = this.convertToDayjs(maxDate, format);\n validators.push({\n key: 'maxDate',\n isValid: () => {\n const _isValid = value.every(val => val.isSameOrBefore(md, granularity));\n isValid = isValid ? _isValid : false;\n return _isValid;\n }\n });\n }\n\n if (minTime) {\n const md = this.onlyTime(this.convertToDayjs(minTime, format));\n validators.push({\n key: 'minTime',\n isValid: () => {\n const _isValid = value.every(val => this.onlyTime(val).isSameOrAfter(md));\n isValid = isValid ? _isValid : false;\n return _isValid;\n }\n });\n }\n\n if (maxTime) {\n const md = this.onlyTime(this.convertToDayjs(maxTime, format));\n validators.push({\n key: 'maxTime',\n isValid: () => {\n const _isValid = value.every(val => this.onlyTime(val).isSameOrBefore(md));\n isValid = isValid ? _isValid : false;\n return _isValid;\n }\n });\n }\n\n return (inputVal: CalendarValue) => {\n isValid = true;\n\n value = this.convertToDayjsArray(inputVal, {\n format,\n allowMultiSelect: true\n }).filter(Boolean);\n\n if (!value.every(val => val.isValid())) {\n return {\n format: {\n given: inputVal\n }\n };\n }\n\n const errors = validators.reduce((map, err) => {\n if (!err.isValid()) {\n map[err.key] = {\n given: value\n };\n }\n\n return map;\n }, {});\n\n return !isValid ? errors : null;\n };\n }\n\n datesStringToStringArray(value: string): string[] {\n return (value || '').split('|').map(m => m.trim()).filter(Boolean);\n }\n\n getValidDayjsArray(value: string, format: string): Dayjs[] {\n return this.datesStringToStringArray(value)\n .filter(d => this.isDateValid(d, format))\n .map(d => dayjsRef(d, format));\n }\n\n shouldShowCurrent(showGoToCurrent: boolean,\n mode: CalendarMode,\n min: Dayjs,\n max: Dayjs): boolean {\n return showGoToCurrent &&\n mode !== 'time' &&\n this.isDateInRange(dayjsRef(), min, max);\n }\n\n isDateInRange(date: Dayjs, from: Dayjs, to: Dayjs): boolean {\n if (!date) {\n return false;\n }\n\n if (!from && !to) {\n return true;\n }\n\n if (!from && to) {\n return date.isSameOrBefore(to);\n }\n\n if (from && !to) {\n return date.isSameOrAfter(from);\n }\n\n return date.isBetween(from, to, 'day', '[]');\n }\n\n convertPropsToDayjs(obj: { [key: string]: any }, format: string, props: string[]): void {\n props.forEach((prop) => {\n if (obj.hasOwnProperty(prop)) {\n obj[prop] = this.convertToDayjs(obj[prop], format);\n }\n });\n }\n\n shouldResetCurrentView<T extends ICalendarInternal>(prevConf: T, currentConf: T): boolean {\n if (prevConf && currentConf) {\n if (!prevConf.min && currentConf.min) {\n return true;\n } else if (prevConf.min && currentConf.min && !prevConf.min.isSame(currentConf.min, 'd')) {\n return true;\n } else if (!prevConf.max && currentConf.max) {\n return true;\n } else if (prevConf.max && currentConf.max && !prevConf.max.isSame(currentConf.max, 'd')) {\n return true;\n }\n\n return false;\n }\n\n return false;\n }\n\n getNativeElement(elem: HTMLElement | string | ElementRef): HTMLElement {\n if (!elem) {\n return null;\n } else if (typeof elem === 'string') {\n return document.querySelector(elem);\n } else if (elem instanceof ElementRef) {\n return elem.nativeElement;\n } else {\n return elem;\n }\n }\n}\n","import {Injectable} from '@angular/core';\n\nimport {WeekDays} from '../common/types/week-days.type';\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {IDay} from './day.model';\nimport {IDayCalendarConfig, IDayCalendarConfigInternal} from './day-calendar-config.model';\nimport {IMonthCalendarConfig} from '../month-calendar/month-calendar-config';\nimport {Dayjs} from 'dayjs';\nimport {dayjsRef} from '../common/dayjs/dayjs.ref';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class DayCalendarService {\n readonly DEFAULT_CONFIG: IDayCalendarConfig = {\n showNearMonthDays: true,\n showWeekNumbers: false,\n firstDayOfWeek: 'su',\n weekDayFormat: 'ddd',\n format: 'DD-MM-YYYY',\n allowMultiSelect: false,\n monthFormat: 'MMM, YYYY',\n enableMonthSelector: true,\n dayBtnFormat: 'DD',\n unSelectOnClick: true\n };\n private readonly DAYS = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'];\n\n constructor(private utilsService: UtilsService) {\n }\n\n getConfig(config: IDayCalendarConfig): IDayCalendarConfigInternal {\n const _config = {\n ...this.DEFAULT_CONFIG,\n ...this.utilsService.clearUndefined(config)\n };\n\n this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);\n\n return _config as IDayCalendarConfigInternal;\n }\n\n generateDaysMap(firstDayOfWeek: WeekDays) {\n const firstDayIndex = this.DAYS.indexOf(firstDayOfWeek);\n const daysArr = this.DAYS.slice(firstDayIndex, 7).concat(this.DAYS.slice(0, firstDayIndex));\n return daysArr.reduce((map, day, index) => {\n map[day] = index;\n\n return map;\n }, <{[key: string]: number}>{});\n }\n\n generateMonthArray(config: IDayCalendarConfigInternal, month: Dayjs, selected: Dayjs[]): IDay[][] {\n const parsedMonth = month.isValid() ? dayjsRef(month.toDate()) : dayjsRef();\n let monthArray: IDay[][] = [];\n const firstDayOfWeekIndex = this.DAYS.indexOf(config.firstDayOfWeek);\n let firstDayOfBoard = parsedMonth.startOf('month');\n\n while (firstDayOfBoard.day() !== firstDayOfWeekIndex) {\n firstDayOfBoard = firstDayOfBoard.subtract(1, 'day');\n }\n\n let current = dayjsRef(firstDayOfBoard.toDate());\n const prevMonth = parsedMonth.subtract(1, 'month');\n const nextMonth = parsedMonth.add(1, 'month');\n const today = dayjsRef();\n\n const daysOfCalendar: IDay[] = this.utilsService.createArray(42)\n .reduce((array: IDay[]) => {\n array.push({\n date: dayjsRef(current.toDate()),\n selected: !!selected.find(selectedDay => current.isSame(selectedDay, 'day')),\n currentMonth: current.isSame(parsedMonth, 'month'),\n prevMonth: current.isSame(prevMonth, 'month'),\n nextMonth: current.isSame(nextMonth, 'month'),\n currentDay: current.isSame(today, 'day'),\n disabled: this.isDateDisabled(current, config)\n });\n current = current.add(1, 'day');\n\n return array;\n }, []);\n\n daysOfCalendar.forEach((day, index) => {\n const weekIndex = Math.floor(index / 7);\n\n if (!monthArray[weekIndex]) {\n monthArray.push([]);\n }\n\n monthArray[weekIndex].push(day);\n });\n\n if (!config.showNearMonthDays) {\n monthArray = this.removeNearMonthWeeks(parsedMonth, monthArray);\n }\n\n return monthArray;\n }\n\n generateWeekdays(firstDayOfWeek: WeekDays): Dayjs[] {\n const weekdayNames: {[key: string]: Dayjs} = {\n su: dayjsRef().day(0),\n mo: dayjsRef().day(1),\n tu: dayjsRef().day(2),\n we: dayjsRef().day(3),\n th: dayjsRef().day(4),\n fr: dayjsRef().day(5),\n sa: dayjsRef().day(6)\n };\n const weekdays: Dayjs[] = [];\n const daysMap = this.generateDaysMap(firstDayOfWeek);\n\n for (const dayKey in daysMap) {\n if (daysMap.hasOwnProperty(dayKey)) {\n weekdays[daysMap[dayKey]] = weekdayNames[dayKey];\n }\n }\n\n return weekdays;\n }\n\n isDateDisabled(date: Dayjs, config: IDayCalendarConfigInternal): boolean {\n if (config.isDayDisabledCallback) {\n return config.isDayDisabledCallback(date);\n }\n\n if (config.min && date.isBefore(config.min, 'day')) {\n return true;\n }\n\n return !!(config.max && date.isAfter(config.max, 'day'));\n }\n\n // todo:: add unit tests\n getHeaderLabel(config: IDayCalendarConfigInternal, month: Dayjs): string {\n if (config.monthFormatter) {\n return config.monthFormatter(month);\n }\n\n return month.format(config.monthFormat);\n }\n\n // todo:: add unit tests\n shouldShowLeft(min: Dayjs, currentMonthView: Dayjs): boolean {\n return min ? min.isBefore(currentMonthView, 'month') : true;\n }\n\n // todo:: add unit tests\n shouldShowRight(max: Dayjs, currentMonthView: Dayjs): boolean {\n return max ? max.isAfter(currentMonthView, 'month') : true;\n }\n\n generateDaysIndexMap(firstDayOfWeek: WeekDays) {\n const firstDayIndex = this.DAYS.indexOf(firstDayOfWeek);\n const daysArr = this.DAYS.slice(firstDayIndex, 7).concat(this.DAYS.slice(0, firstDayIndex));\n return daysArr.reduce((map, day, index) => {\n map[index] = day;\n\n return map;\n }, <{[key: number]: string}>{});\n }\n\n getMonthCalendarConfig(componentConfig: IDayCalendarConfigInternal): IMonthCalendarConfig {\n return this.utilsService.clearUndefined({\n min: componentConfig.min,\n max: componentConfig.max,\n format: componentConfig.format,\n isNavHeaderBtnClickable: true,\n allowMultiSelect: false,\n yearFormat: componentConfig.yearFormat,\n yearFormatter: componentConfig.yearFormatter,\n monthBtnFormat: componentConfig.monthBtnFormat,\n monthBtnFormatter: componentConfig.monthBtnFormatter,\n monthBtnCssClassCallback: componentConfig.monthBtnCssClassCallback,\n isMonthDisabledCallback: componentConfig.isMonthDisabledCallback,\n multipleYearsNavigateBy: componentConfig.multipleYearsNavigateBy,\n showMultipleYearsNavigation: componentConfig.showMultipleYearsNavigation,\n showGoToCurrent: componentConfig.showGoToCurrent,\n numOfMonthRows: componentConfig.numOfMonthRows\n });\n }\n\n getDayBtnText(config: IDayCalendarConfigInternal, day: Dayjs): string {\n if (config.dayBtnFormatter) {\n return config.dayBtnFormatter(day);\n }\n\n return day.format(config.dayBtnFormat);\n }\n\n getDayBtnCssClass(config: IDayCalendarConfigInternal, day: Dayjs): string {\n if (config.dayBtnCssClassCallback) {\n return config.dayBtnCssClassCallback(day);\n }\n\n return '';\n }\n\n private removeNearMonthWeeks(currentMonth: Dayjs, monthArray: IDay[][]): IDay[][] {\n if (monthArray[monthArray.length - 1].find((day) => day.date.isSame(currentMonth, 'month'))) {\n return monthArray;\n } else {\n return monthArray.slice(0, -1);\n }\n }\n}\n","import {Injectable} from '@angular/core';\n\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {ITimeSelectConfig, ITimeSelectConfigInternal} from './time-select-config.model';\nimport {Dayjs} from 'dayjs';\nimport {dayjsRef} from '../common/dayjs/dayjs.ref';\n\nexport type TimeUnit = 'hour' | 'minute' | 'second';\nexport const FIRST_PM_HOUR = 12;\n\n@Injectable({\n providedIn: 'root'\n})\nexport class TimeSelectService {\n readonly DEFAULT_CONFIG: ITimeSelectConfigInternal = {\n hours12Format: 'hh',\n hours24Format: 'HH',\n meridiemFormat: 'A',\n minutesFormat: 'mm',\n minutesInterval: 1,\n secondsFormat: 'ss',\n secondsInterval: 1,\n showSeconds: false,\n showTwentyFourHours: false,\n timeSeparator: ':',\n };\n\n constructor(private readonly utilsService: UtilsService) {\n }\n\n getConfig(config: ITimeSelectConfig): ITimeSelectConfigInternal {\n const timeConfigs = {\n maxTime: this.utilsService.onlyTime(config && config.maxTime),\n minTime: this.utilsService.onlyTime(config && config.minTime)\n };\n\n return <ITimeSelectConfigInternal>{\n ...this.DEFAULT_CONFIG,\n ...this.utilsService.clearUndefined(config),\n ...timeConfigs\n };\n }\n\n getTimeFormat(config: ITimeSelectConfigInternal): string {\n return (config.showTwentyFourHours ? config.hours24Format : config.hours12Format)\n + config.timeSeparator + config.minutesFormat\n + (config.showSeconds ? (config.timeSeparator + config.secondsFormat) : '')\n + (config.showTwentyFourHours ? '' : ' ' + config.meridiemFormat);\n }\n\n getHours(config: ITimeSelectConfigInternal, t: Dayjs | null): string {\n const time = t || dayjsRef();\n return time && time.format(config.showTwentyFourHours ? config.hours24Format : config.hours12Format);\n }\n\n getMinutes(config: ITimeSelectConfigInternal, t: Dayjs | null): string {\n const time = t || dayjsRef();\n return time && time.format(config.minutesFormat);\n }\n\n getSeconds(config: ITimeSelectConfigInternal, t: Dayjs | null): string {\n const time = t || dayjsRef();\n return time && time.format(config.secondsFormat);\n }\n\n getMeridiem(config: ITimeSelectConfigInternal, time: Dayjs): string {\n return time && time.format(config.meridiemFormat);\n }\n\n decrease(config: ITimeSelectConfigInternal, time: Dayjs, unit: TimeUnit): Dayjs {\n let amount: number = 1;\n switch (unit) {\n case 'minute':\n amount = config.minutesInterval;\n break;\n case 'second':\n amount = config.secondsInterval;\n break;\n }\n return time.subtract(amount, unit);\n }\n\n increase(config: ITimeSelectConfigInternal, time: Dayjs, unit: TimeUnit): Dayjs {\n let amount: number = 1;\n switch (unit) {\n case 'minute':\n amount = config.minutesInterval;\n break;\n case 'second':\n amount = config.secondsInterval;\n break;\n }\n return time.add(amount, unit);\n }\n\n toggleMeridiem(time: Dayjs): Dayjs {\n if (time.hour() < FIRST_PM_HOUR) {\n return time.add(12, 'hour');\n } else {\n return time.subtract(12, 'hour');\n }\n }\n\n shouldShowDecrease(config: ITimeSelectConfigInternal, time: Dayjs, unit: TimeUnit): boolean {\n if (!config.min && !config.minTime) {\n return true;\n }\n const newTime = this.decrease(config, time, unit);\n\n return (!config.min || config.min.isSameOrBefore(newTime))\n && (!config.minTime || config.minTime.isSameOrBefore(this.utilsService.onlyTime(newTime)));\n }\n\n shouldShowIncrease(config: ITimeSelectConfigInternal, time: Dayjs, unit: TimeUnit): boolean {\n if (!config.max && !config.maxTime) {\n return true;\n }\n const newTime = this.increase(config, time, unit);\n\n return (!config.max || config.max.isSameOrAfter(newTime))\n && (!config.maxTime || config.maxTime.isSameOrAfter(this.utilsService.onlyTime(newTime)));\n }\n\n shouldShowToggleMeridiem(config: ITimeSelectConfigInternal, time: Dayjs): boolean {\n if (!config.min && !config.max && !config.minTime && !config.maxTime) {\n return true;\n }\n const newTime = this.toggleMeridiem(time);\n return (!config.max || config.max.isSameOrAfter(newTime))\n && (!config.min || config.min.isSameOrBefore(newTime))\n && (!config.maxTime || config.maxTime.isSameOrAfter(this.utilsService.onlyTime(newTime)))\n && (!config.minTime || config.minTime.isSameOrBefore(this.utilsService.onlyTime(newTime)));\n }\n}\n","import {Injectable} from '@angular/core';\n\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {DayCalendarService} from '../day-calendar/day-calendar.service';\nimport {TimeSelectService} from '../time-select/time-select.service';\nimport {IDayTimeCalendarConfig, IDayTimeCalendarConfigInternal} from './day-time-calendar-config.model';\nimport {dayjsRef} from '../common/dayjs/dayjs.ref';\nimport {Dayjs} from 'dayjs';\nimport {IDayCalendarConfigInternal} from '../day-calendar/day-calendar-config.model';\n\nconst DAY_FORMAT = 'YYYYMMDD';\nconst TIME_FORMAT = 'HH:mm:ss';\nconst COMBINED_FORMAT = DAY_FORMAT + TIME_FORMAT;\n\n@Injectable({\n providedIn: 'root'\n})\nexport class DayTimeCalendarService {\n readonly DEFAULT_CONFIG: IDayTimeCalendarConfig = {};\n\n constructor(private utilsService: UtilsService,\n private dayCalendarService: DayCalendarService,\n private timeSelectService: TimeSelectService) {\n }\n\n getConfig(config: IDayTimeCalendarConfig): IDayTimeCalendarConfigInternal {\n const _config = {\n ...this.DEFAULT_CONFIG,\n ...this.timeSelectService.getConfig(config),\n ...this.dayCalendarService.getConfig(config)\n };\n\n this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);\n\n return _config as IDayTimeCalendarConfigInternal;\n }\n\n updateDay(current: Dayjs, day: Dayjs, config: IDayCalendarConfigInternal): Dayjs {\n const time = current ? current : dayjsRef();\n let updated = dayjsRef(day.format(DAY_FORMAT) + time.format(TIME_FORMAT), COMBINED_FORMAT);\n\n if (config.min) {\n const min = config.min;\n updated = min.isAfter(updated) ? min : updated;\n }\n\n if (config.max) {\n const max = config.max;\n updated = max.isBefore(updated) ? max : updated;\n }\n\n return updated;\n }\n\n updateTime(current: Dayjs, time: Dayjs): Dayjs {\n const day = current ? current : dayjsRef();\n\n return dayjsRef(day.format(DAY_FORMAT) + time.format(TIME_FORMAT), COMBINED_FORMAT);\n }\n}\n","import {EventEmitter, Injectable} from '@angular/core';\nimport {IDatePickerConfig, IDatePickerConfigInternal} from './date-picker-config.model';\n\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {IDayCalendarConfig} from '../day-calendar/day-calendar-config.model';\nimport {TimeSelectService} from '../time-select/time-select.service';\nimport {DayTimeCalendarService} from '../day-time-calendar/day-time-calendar.service';\nimport {ITimeSelectConfig} from '../time-select/time-select-config.model';\nimport {CalendarMode} from '../common/types/calendar-mode';\nimport {Dayjs} from 'dayjs';\nimport {IDayTimeCalendarConfig} from '../day-time-calendar/day-time-calendar-config.model';\nimport {ConnectionPositionPair} from '@angular/cdk/overlay';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class DatePickerService {\n readonly onPickerClosed: EventEmitter<null> = new EventEmitter();\n private defaultConfig: IDatePickerConfigInternal = {\n closeOnSelect: true,\n closeOnSelectDelay: 100,\n closeOnEnter: true,\n format: 'DD-MM-YYYY',\n openOnFocus: true,\n openOnClick: true,\n onOpenDelay: 0,\n disableKeypress: false,\n showNearMonthDays: true,\n showWeekNumbers: false,\n enableMonthSelector: true,\n showGoToCurrent: true,\n hideOnOutsideClick: true,\n };\n\n constructor(private readonly utilsService: UtilsService,\n private readonly timeSelectService: TimeSelectService,\n private readonly daytimeCalendarService: DayTimeCalendarService) {\n }\n\n // todo:: add unit tests\n getConfig(config: IDatePickerConfig, mode: CalendarMode = 'daytime'): IDatePickerConfigInternal {\n const _config = <IDatePickerConfigInternal>{\n ...this.defaultConfig,\n format: DatePickerService.getDefaultFormatByMode(mode),\n ...this.utilsService.clearUndefined(config)\n };\n\n this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);\n\n if (config && config.allowMultiSelect && config.closeOnSelect === undefined) {\n _config.closeOnSelect = false;\n }\n\n return _config;\n }\n\n getDayConfigService(pickerConfig: IDatePickerConfig): IDayCalendarConfig {\n return {\n min: pickerConfig.min,\n max: pickerConfig.max,\n isDayDisabledCallback: pickerConfig.isDayDisabledCallback,\n weekDayFormat: pickerConfig.weekDayFormat,\n weekDayFormatter: pickerConfig.weekDayFormatter,\n showNearMonthDays: pickerConfig.showNearMonthDays,\n showWeekNumbers: pickerConfig.showWeekNumbers,\n firstDayOfWeek: pickerConfig.firstDayOfWeek,\n format: pickerConfig.format,\n allowMultiSelect: pickerConfig.allowMultiSelect,\n monthFormat: pickerConfig.monthFormat,\n monthFormatter: pickerConfig.monthFormatter,\n enableMonthSelector: pickerConfig.enableMonthSelector,\n yearFormat: pickerConfig.yearFormat,\n yearFormatter: pickerConfig.yearFormatter,\n dayBtnFormat: pickerConfig.dayBtnFormat,\n dayBtnFormatter: pickerConfig.dayBtnFormatter,\n dayBtnCssClassCallback: pickerConfig.dayBtnCssClassCallback,\n monthBtnFormat: pickerConfig.monthBtnFormat,\n monthBtnFormatter: pickerConfig.monthBtnFormatter,\n monthBtnCssClassCallback: pickerConfig.monthBtnCssClassCallback,\n isMonthDisabledCallback: pickerConfig.isMonthDisabledCallback,\n multipleYearsNavigateBy: pickerConfig.multipleYearsNavigateBy,\n showMultipleYearsNavigation: pickerConfig.showMultipleYearsNavigation,\n returnedValueType: pickerConfig.returnedValueType,\n showGoToCurrent: pickerConfig.showGoToCurrent,\n unSelectOnClick: pickerConfig.unSelectOnClick,\n numOfMonthRows: pickerConfig.numOfMonthRows\n };\n }\n\n getDayTimeConfig(pickerConfig: IDatePickerConfig): IDayTimeCalendarConfig {\n return this.daytimeCalendarService.getConfig(pickerConfig);\n }\n\n getTimeConfig(pickerConfig: IDatePickerConfig): ITimeSelectConfig {\n return this.timeSelectService.getConfig(pickerConfig);\n }\n\n pickerClosed() {\n this.onPickerClosed.emit();\n }\n\n // todo:: add unit tests\n isValidInputDateValue(value: string, config: IDatePickerConfig): boolean {\n value = value ? value : '';\n const datesStrArr: string[] = this.utilsService.datesStringToStringArray(value);\n\n return datesStrArr.every(date => this.utilsService.isDateValid(date, config.format));\n }\n\n // todo:: add unit tests\n convertInputValueToDayjsArray(value: string, config: IDatePickerConfig): Dayjs[] {\n value = value ? value : '';\n const datesStrArr: string[] = this.utilsService.datesStringToStringArray(value);\n\n return this.utilsService.convertToDayjsArray(datesStrArr, config);\n }\n\n getOverlayPosition({drops, opens}: IDatePickerConfig): ConnectionPositionPair[] | undefined {\n if (!drops && !opens) {\n return undefined;\n }\n\n return [{\n originX: opens ? opens === 'left' ? 'start' : 'end' : 'start',\n originY: drops ? drops === 'up' ? 'top' : 'bottom' : 'bottom',\n overlayX: opens ? opens === 'left' ? 'start' : 'end' : 'start',\n overlayY: drops ? drops === 'up' ? 'bottom' : 'top' : 'top',\n }];\n }\n\n private static getDefaultFormatByMode(mode: CalendarMode): string {\n switch (mode) {\n case 'day':\n return 'DD-MM-YYYY';\n case 'daytime':\n return 'DD-MM-YYYY HH:mm:ss';\n case 'time':\n return 'HH:mm:ss';\n case 'month':\n return 'MMM, YYYY';\n }\n }\n}\n","import {Injectable} from '@angular/core';\n\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {IMonth} from './month.model';\nimport {IMonthCalendarConfig, IMonthCalendarConfigInternal} from './month-calendar-config';\nimport {Dayjs} from 'dayjs';\nimport {dayjsRef} from '../common/dayjs/dayjs.ref';\n\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class MonthCalendarService {\n readonly DEFAULT_CONFIG: IMonthCalendarConfigInternal = {\n allowMultiSelect: false,\n yearFormat: 'YYYY',\n format: 'MM-YYYY',\n isNavHeaderBtnClickable: false,\n monthBtnFormat: 'MMM',\n multipleYearsNavigateBy: 10,\n showMultipleYearsNavigation: false,\n unSelectOnClick: true,\n numOfMonthRows: 3\n };\n\n constructor(private utilsService: UtilsService) {\n }\n\n getConfig(config: IMonthCalendarConfig): IMonthCalendarConfigInternal {\n const _config = <IMonthCalendarConfigInternal>{\n ...this.DEFAULT_CONFIG,\n ...this.utilsService.clearUndefined(config)\n };\n\n MonthCalendarService.validateConfig(_config);\n this.utilsService.convertPropsToDayjs(_config, _config.format, ['min', 'max']);\n\n return _config;\n }\n\n generateYear(config: IMonthCalendarConfig, year: Dayjs, selected: Dayjs[] = null): IMonth[][] {\n let index = year.startOf('year');\n\n return this.utilsService.createArray(config.numOfMonthRows).map(() => {\n return this.utilsService.createArray(12 / config.numOfMonthRows).map(() => {\n const date = dayjsRef(index);\n const month = {\n date,\n selected: !!selected.find(s => index.isSame(s, 'month')),\n currentMonth: index.isSame(dayjsRef(), 'month'),\n disabled: this.isMonthDisabled(date, config),\n text: this.getMonthBtnText(config, date)\n };\n\n index = index.add(1, 'month');\n\n return month;\n });\n });\n }\n\n isMonthDisabled(date: Dayjs, config: IMonthCalendarConfig) {\n if (config.isMonthDisabledCallback) {\n return config.isMonthDisabledCallback(date);\n }\n\n if (config.min && date.isBefore(config.min, 'month')) {\n return true;\n }\n\n return !!(config.max && date.isAfter(config.max, 'month'));\n }\n\n shouldShowLeft(min: Dayjs, currentMonthView: Dayjs): boolean {\n return min ? min.isBefore(currentMonthView, 'year') : true;\n }\n\n shouldShowRight(max: Dayjs, currentMonthView: Dayjs): boolean {\n return max ? max.isAfter(currentMonthView, 'year') : true;\n }\n\n getHeaderLabel(config: IMonthCalendarConfig, year: Dayjs): string {\n if (config.yearFormatter) {\n return config.yearFormatter(year);\n }\n\n return year.format(config.yearFormat);\n }\n\n getMonthBtnText(config: IMonthCalendarConfig, month: Dayjs): string {\n if (config.monthBtnFormatter) {\n return config.monthBtnFormatter(month);\n }\n\n return month.format(config.monthBtnFormat);\n }\n\n getMonthBtnCssClass(config: IMonthCalendarConfig, month: Dayjs): string {\n if (config.monthBtnCssClassCallback) {\n return config.monthBtnCssClassCallback(month);\n }\n\n return '';\n }\n\n private static validateConfig(config: IMonthCalendarConfigInternal): void {\n if (config.numOfMonthRows < 1 || config.numOfMonthRows > 12 || !Number.isInteger(12 / config.numOfMonthRows)) {\n throw new Error('numOfMonthRows has to be between 1 - 12 and divide 12 to integer');\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n HostBinding,\n Input,\n Output,\n ViewEncapsulation\n} from '@angular/core';\n\n@Component({\n selector: 'dp-calendar-nav',\n templateUrl: './calendar-nav.component.html',\n styleUrls: ['./calendar-nav.component.less'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class CalendarNavComponent {\n @Input() label: string;\n @Input() isLabelClickable: boolean = false;\n @Input() showLeftNav: boolean = true;\n @Input() showLeftSecondaryNav: boolean = false;\n @Input() showRightNav: boolean = true;\n @Input() showRightSecondaryNav: boolean = false;\n @Input() leftNavDisabled: boolean = false;\n @Input() leftSecondaryNavDisabled: boolean = false;\n @Input() rightNavDisabled: boolean = false;\n @Input() rightSecondaryNavDisabled: boolean = false;\n @Input() showGoToCurrent: boolean = true;\n @HostBinding('class') @Input() theme: string;\n\n @Output() onLeftNav: EventEmitter<null> = new EventEmitter();\n @Output() onLeftSecondaryNav: EventEmitter<null> = new EventEmitter();\n @Output() onRightNav: EventEmitter<null> = new EventEmitter();\n @Output() onRightSecondaryNav: EventEmitter<null> = new EventEmitter();\n @Output() onLabelClick: EventEmitter<null> = new EventEmitter();\n @Output() onGoToCurrent: EventEmitter<null> = new EventEmitter();\n\n leftNavClicked() {\n this.onLeftNav.emit();\n }\n\n leftSecondaryNavClicked() {\n this.onLeftSecondaryNav.emit();\n }\n\n rightNavClicked() {\n this.onRightNav.emit();\n }\n\n rightSecondaryNavClicked() {\n this.onRightSecondaryNav.emit();\n }\n\n labelClicked() {\n this.onLabelClick.emit();\n }\n}\n","<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","import {ECalendarValue} from '../common/types/calendar-value-enum';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChange,\n SimpleChanges,\n ViewEncapsulation\n} from '@angular/core';\nimport {IMonth} from './month.model';\nimport {MonthCalendarService} from './month-calendar.service';\n\nimport {IMonthCalendarConfig, IMonthCalendarConfigInternal} from './month-calendar-config';\nimport {\n ControlValueAccessor,\n UntypedFormControl,\n NG_VALIDATORS,\n NG_VALUE_ACCESSOR,\n ValidationErrors,\n Validator\n} from '@angular/forms';\nimport {CalendarValue} from '../common/types/calendar-value';\nimport {UtilsService} from '../common/services/utils/utils.service';\nimport {DateValidator} from '../common/types/validator.type';\nimport {SingleCalendarValue} from '../common/types/single-calendar-value';\nimport {INavEvent} from '../common/models/navigation-event.model';\nimport {Dayjs} from 'dayjs';\nimport {dayjsRef} from '../common/dayjs/dayjs.ref';\n\n@Component({\n selector: 'dp-month-calendar',\n templateUrl: 'month-calendar.component.html',\n styleUrls: ['month-calendar.component.less'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n MonthCalendarService,\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => MonthCalendarComponent),\n multi: true\n },\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => MonthCalendarComponent),\n multi: true\n }\n ],\n standalone: false\n})\nexport class MonthCalendarComponent implements OnInit, OnChanges, ControlValueAccessor, Validator {\n\n @Input() config: IMonthCalendarConfig;\n @Input() displayDate: Dayjs | string;\n @Input() minDate: Dayjs;\n @Input() maxDate: Dayjs;\n @HostBinding('class') @Input() theme: string;\n @Output() onSelect: EventEmitter<IMonth> = new EventEmitter();\n @Output() onNavHeaderBtnClick: EventEmitter<null> = new EventEmitter();\n @Output() onGoToCurrent: EventEmitter<void> = new EventEmitter();\n @Output() onLeftNav: EventEmitter<INavEvent> = new EventEmitter();\n @Output() onRightNav: EventEmitter<INavEvent> = new EventEmitter();\n @Output() onLeftSecondaryNav: EventEmitter<INavEvent> = new EventEmitter();\n @Output() onRightSecondaryNav: EventEmitter<INavEvent> = new EventEmitter();\n isInited: boolean = false;\n componentConfig: IMonthCalendarConfigInternal;\n yearMonths: IMonth[][];\n inputValue: CalendarValue;\n inputValueType: ECalendarValue;\n validateFn: DateValidator;\n _shouldShowCurrent: boolean = true;\n navLabel: string;\n showLeftNav: boolean;\n showRightNav: boolean;\n showSecondaryLeftNav: boolean;\n showSecondaryRightNav: boolean;\n api = {\n toggleCalendar: this.toggleCalendarMode.bind(this),\n moveCalendarTo: this.moveCalendarTo.bind(this)\n };\n\n constructor(public readonly monthCalendarService: MonthCalendarService,\n public readonly utilsService: UtilsService,\n public readonly cd: ChangeDetectorRef) {\n }\n\n _selected: Dayjs[];\n\n get selected(): Dayjs[] {\n return this._selected;\n }\n\n set selected(selected: Dayjs[]) {\n this._selected = selected;\n this.onChangeCallback(this.processOnChangeCallback(selected));\n }\n\n _currentDateView: Dayjs;\n\n get currentDateView(): Dayjs {\n return this._currentDateView;\n }\n\n set currentDateView(current: Dayjs) {\n this._currentDateView = dayjsRef(current.toDate());\n this.yearMonths = this.monthCalendarService\n .generateYear(this.componentConfig, this._currentDateView, this.selected);\n this.navLabel = this.monthCalendarService.getHeaderLabel(this.componentConfig, this.currentDateView);\n this.showLeftNav = this.monthCalendarService.shouldShowLeft(this.componentConfig.min, this._currentDateView);\n this.showRightNav = this.monthCalendarService.shouldShowRight(this.componentConfig.max, this.currentDateView);\n this.showSecondaryLeftNav = this.componentConfig.showMultipleYearsNavigation && this.showLeftNav;\n this.showSecondaryRightNav = this.componentConfig.showMultipleYearsNavigation && this.showRightNav;\n }\n\n ngOnInit(): void {\n this.isInited = true;\n this.init();\n this.initValidators();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.isInited) {\n const {minDate, maxDate, config} = changes;\n\n this.handleConfigChange(config);\n this.init();\n\n if (minDate || maxDate) {\n this.initValidators();\n }\n this.cd.markForCheck()\n }\n }\n\n init(): void {\n this.componentConfig = this.monthCalendarService.getConfig(this.config);\n this.selected = this.selected || [];\n this.currentDateView = (this.displayDate as Dayjs) ?? this.utilsService\n .getDefaultDisplayDate(\n this.currentDateView,\n this.selected,\n this.componentConfig.allowMultiSelect,\n this.componentConfig.min\n );\n this.inputValueType = this.utilsService.getInputType(this.inputValue, this.componentConfig.allowMultiSelect);\n this._shouldShowCurrent = this.shouldShowCurrent();\n }\n\n writeValue(value: CalendarValue): void {\n this.inputValue = value;\n\n if (value) {\n this.selected = this.utilsService\n .convertToDayjsArray(value, this.componentConfig);\n this.yearMonths = this.monthCalendarService\n .generateYear(this.componentConfig, this.currentDateView, this.selected);\n this.inputValueType = this.utilsService.getInputType(this.inputValue, this.componentConfig.allowMultiSelect);\n } else {\n this.selected = [];\n this.yearMonths = this.monthCalendarService\n .generateYear(this.componentConfig, this.currentDateView, this.selected);\n }\n\n this.cd.markForCheck();\n }\n\n registerOnChange(fn: any): void {\n this.onChangeCallback = fn;\n }\n\n onChangeCallback(_: any): void {\n }\n\n registerOnTouched(fn: any): void {\n }\n\n validate(formControl: UntypedFormControl): ValidationErrors | any {\n if (this.minDate || this.maxDate) {\n return this.validateFn(formControl.value);\n } else {\n return () => null;\n }\n }\n\n processOnChangeCallback(value: Dayjs[]): CalendarValue {\n return this.utilsService.convertFromDayjsArray(\n this.componentConfig.format,\n value,\n this.componentConfig.returnedValueType || this.inputValueType\n );\n }\n\n initValidators(): void {\n this.validateFn = this.validateFn = this.utilsService.createValidator(\n {minDate: this.minDate, maxDate: this.maxDate},\n this.componentConfig.format,\n 'month'\n );\n\n this.onChangeCallback(this.processOnChangeCallback(this.selected));\n }\n\n monthClicked(month: IMonth): void {\n if (month.selected && !this.componentConfig.unSelectOnClick) {\n return;\n }\n\n this.selected = this.utilsService\n .updateSelected(this.componentConfig.allowMultiSelect, this.selected, month, 'month');\n this.yearMonths = this.monthCalendarService\n .generateYear(this.componentConfig, this.currentDateView, this.selected);\n this.onSelect.emit(month);\n }\n\n onLeftNavClick() {\n const from = dayjsRef(this.currentDateView.toDate());\n this.currentDateView = this.currentDateView.subtract(1, 'year');\n const to = dayjsRef(this.currentDateView.toDate());\n this.yearMonths = this.monthCalendarService.generateYear(this.componentConfig, this.currentDateView, this.selected);\n this.onLeftNav.emit({from, to});\n }\n\n onLeftSecondaryNavClick(): void {\n let navigateBy = this.componentConfig.multipleYearsNavigateBy;\n const isOutsideRange = this.componentConfig.min &&\n this.currentDateView.year() - this.componentConfig.min.year() < navigateBy;\n\n if (isOutsideRange) {\n navigateBy = this.currentDateView.year() - this.componentConfig.min.year();\n }\n\n const from = dayjsRef(this.currentDateView.toDate());\n this.currentDateView = this.currentDateView.subtract(navigateBy, 'year');\n const to = dayjsRef(this.currentDateView.toDate());\n this.onLeftSecondaryNav.emit({from, to});\n }\n\n onRightNavClick(): void {\n const from = dayjsRef(this.currentDateView.toDate());\n this.currentDateView = this.currentDateView.add(1, 'year');\n const to = dayjsRef(this.currentDateView.toDate());\n this.onRightNav.emit({from, to});\n }\n\n onRightSecondaryNavClick(): void {\n let navigateBy = this.componentConfig.multipleYearsNavigateBy;\n const isOutsideRange = this.componentConfig.max &&\n this.componentConfig.max.year() - this.currentDateView.year() < navigateBy;\n\n if (isOutsideRange) {\n navigateBy = this.componentConfig.max.year() - this.currentDateView.year();\n }\n\n const from = dayjsRef(this.currentDateView.toDate());\n this.currentDateView = this.currentDateView.add(navigateBy, 'year');\n const to = dayjsRef(this.currentDateView.toDate());\n this.onRightSecondaryNav.emit({from, to});\n }\n\n toggleCalendarMode(): void {\n this.onNavHeaderBtnClick.emit();\n }\n\n getMonthBtnCssClass(month: IMonth): { [klass: string]: boolean } {\n const cssClass: { [klass: string]: boolean } = {\n 'dp-selected': month.selected,\n 'dp-current-month': month.currentMonth\n };\n const customCssClass: string = this.monthCalendarService.getMonthBtnCssClass(this.componentConfig, month.date);\n\n if (customCssClass) {\n cssClass[customCssClass] = true;\n }\n\n return cssClass;\n }\n\n shouldShowCurrent(): boolean {\n return this.utilsService.shouldShowCurrent(\n this.componentConfig.showGoToCurrent,\n 'month',\n this.componentConfig.mi