UNPKG

ngx-bootstrap

Version:
1 lines 307 kB
{"version":3,"file":"ngx-bootstrap-datepicker.mjs","sources":["../../../../src/datepicker/bs-datepicker.config.ts","../../../../src/datepicker/datepicker-animations.ts","../../../../src/datepicker/base/bs-datepicker-container.ts","../../../../src/datepicker/reducer/bs-datepicker.actions.ts","../../../../src/datepicker/bs-locale.service.ts","../../../../src/datepicker/reducer/bs-datepicker.effects.ts","../../../../src/datepicker/reducer/_defaults.ts","../../../../src/datepicker/reducer/bs-datepicker.state.ts","../../../../src/datepicker/utils/bs-calendar-utils.ts","../../../../src/datepicker/utils/matrix-utils.ts","../../../../src/datepicker/engine/calc-days-calendar.ts","../../../../src/datepicker/engine/format-days-calendar.ts","../../../../src/datepicker/engine/flag-days-calendar.ts","../../../../src/datepicker/engine/view-mode.ts","../../../../src/datepicker/engine/format-months-calendar.ts","../../../../src/datepicker/engine/flag-months-calendar.ts","../../../../src/datepicker/engine/format-years-calendar.ts","../../../../src/datepicker/engine/flag-years-calendar.ts","../../../../src/datepicker/utils/copy-time-utils.ts","../../../../src/datepicker/reducer/bs-datepicker.reducer.ts","../../../../src/datepicker/reducer/bs-datepicker.store.ts","../../../../src/datepicker/themes/bs/bs-custom-dates-view.component.ts","../../../../src/datepicker/models/index.ts","../../../../src/datepicker/themes/bs/bs-current-date-view.component.ts","../../../../src/datepicker/themes/bs/bs-timepicker-view.component.ts","../../../../src/datepicker/themes/bs/bs-calendar-layout.component.ts","../../../../src/datepicker/themes/bs/bs-datepicker-day-decorator.directive.ts","../../../../src/datepicker/themes/bs/bs-datepicker-navigation-view.component.ts","../../../../src/datepicker/themes/bs/bs-days-calendar-view.component.ts","../../../../src/datepicker/themes/bs/bs-months-calendar-view.component.ts","../../../../src/datepicker/themes/bs/bs-years-calendar-view.component.ts","../../../../src/datepicker/themes/bs/bs-datepicker-container.component.ts","../../../../src/datepicker/themes/bs/bs-datepicker-view.html","../../../../src/datepicker/bs-datepicker.component.ts","../../../../src/datepicker/bs-datepicker-inline.config.ts","../../../../src/datepicker/themes/bs/bs-datepicker-inline-container.component.ts","../../../../src/datepicker/bs-datepicker-inline.component.ts","../../../../src/datepicker/bs-daterangepicker-inline.config.ts","../../../../src/datepicker/themes/bs/bs-daterangepicker-container.component.ts","../../../../src/datepicker/themes/bs/bs-daterangepicker-inline-container.component.ts","../../../../src/datepicker/bs-daterangepicker-inline.component.ts","../../../../src/datepicker/bs-datepicker-input.directive.ts","../../../../src/datepicker/bs-daterangepicker.config.ts","../../../../src/datepicker/bs-daterangepicker.component.ts","../../../../src/datepicker/bs-daterangepicker-input.directive.ts","../../../../src/datepicker/bs-datepicker.module.ts","../../../../src/datepicker/ngx-bootstrap-datepicker.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport {\n DatepickerRenderOptions,\n BsDatepickerViewMode,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText\n} from './models';\nimport { BsCustomDates } from './themes/bs/bs-custom-dates-view.component';\n\n\n/**\n * For date range picker there are `BsDaterangepickerConfig` which inherits all properties,\n * except `displayMonths`, for range picker it default to `2`\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class BsDatepickerConfig implements DatepickerRenderOptions {\n /** sets use adaptive position */\n adaptivePosition = false;\n /** sets use UTC date time format */\n useUtc = false;\n /** turn on/off animation */\n isAnimated = false;\n value?: Date | Date[];\n isDisabled?: boolean;\n /**\n * Default min date for all date/range pickers\n */\n minDate?: Date;\n /**\n * Default max date for all date/range pickers\n */\n maxDate?: Date;\n /**\n * The view that the datepicker should start in\n */\n startView: BsDatepickerViewMode = 'day';\n /**\n * Default date custom classes for all date/range pickers\n */\n dateCustomClasses?: DatepickerDateCustomClasses[];\n /**\n * Default tooltip text for all date/range pickers\n */\n dateTooltipTexts?: DatepickerDateTooltipText[];\n /**\n * Disable specific days, e.g. [0,6] will disable all Saturdays and Sundays\n */\n daysDisabled?: number[];\n /**\n * Disable specific dates\n */\n datesDisabled?: Date[];\n /**\n * Show one months for special cases (only for dateRangePicker)\n * 1. maxDate is equal to today's date\n * 2. minDate's month is equal to maxDate's month\n */\n displayOneMonthRange?: boolean;\n /**\n * Enable specific dates\n */\n datesEnabled?: Date[];\n /**\n * Makes dates from other months active\n */\n selectFromOtherMonth?: boolean;\n\n /**\n * Allows select first date of the week by click on week number\n */\n selectWeek?: boolean;\n\n /**\n * Allows select daterange as first and last day of week by click on week number (dateRangePicker only)\n */\n selectWeekDateRange?: boolean;\n\n /**\n * Shows previous and current month, instead of current and next (dateRangePicker only)\n */\n showPreviousMonth?: boolean;\n\n /**\n * Prevents change to next month for right calendar in two calendars view (dateRangePicker only)\n */\n preventChangeToNextMonth?: boolean;\n\n /**\n * Add class to current day\n */\n customTodayClass?: string;\n\n /**\n * Default mode for all date pickers\n */\n minMode?: BsDatepickerViewMode;\n\n /**\n * If true, returns focus to the datepicker / daterangepicker input after date selection\n */\n returnFocusToInput = false;\n\n /** CSS class which will be applied to datepicker container,\n * usually used to set color theme\n */\n containerClass = 'theme-green';\n\n // DatepickerRenderOptions\n displayMonths = 1;\n /**\n * Allows to hide week numbers in datepicker\n */\n showWeekNumbers = true;\n\n dateInputFormat = 'L';\n // range picker\n rangeSeparator = ' - ';\n /**\n * Date format for date range input field\n */\n rangeInputFormat = 'L';\n\n /**\n * Predefined ranges\n */\n ranges?: BsCustomDates[];\n\n /**\n * Max Date Range in days\n */\n maxDateRange?: number;\n\n // DatepickerFormatOptions\n monthTitle = 'MMMM';\n yearTitle = 'YYYY';\n dayLabel = 'D';\n monthLabel = 'MMMM';\n yearLabel = 'YYYY';\n weekNumbers = 'w';\n\n /**\n * Shows 'today' button\n */\n showTodayButton = false;\n\n /**\n * Shows clear button\n */\n showClearButton = false;\n\n /**\n * Positioning of 'today' button\n */\n todayPosition = 'center';\n\n /**\n * Positioning of 'clear' button\n */\n clearPosition = 'right';\n\n /**\n * Label for 'today' button\n */\n todayButtonLabel = 'Today';\n\n /**\n * Label for 'clear' button\n */\n clearButtonLabel = 'Clear';\n\n /**\n * Label for 'custom range' button\n */\n customRangeButtonLabel = 'Custom Range';\n\n /**\n * Shows timepicker under datepicker\n */\n withTimepicker = false;\n /**\n * Set current hours, minutes, seconds and milliseconds for bsValue\n */\n initCurrentTime?: boolean;\n /**\n * Set allowed positions of container.\n */\n allowedPositions = ['top', 'bottom'];\n /**\n * Set rule for datepicker closing. If value is true datepicker closes only if date is changed, if user changes only time datepicker doesn't close. It is available only if property withTimepicker is set true\n * */\n keepDatepickerOpened = false;\n /**\n * Allows keep invalid dates in range. Can be used with minDate, maxDate\n * */\n keepDatesOutOfRules = false;\n}\n","import {\n animate,\n style,\n AnimationTriggerMetadata,\n state,\n transition,\n trigger\n} from '@angular/animations';\n\nexport const DATEPICKER_ANIMATION_TIMING = '220ms cubic-bezier(0, 0, 0.2, 1)';\n\nexport const datepickerAnimation: AnimationTriggerMetadata =\n trigger('datepickerAnimation', [\n state('animated-down', style({ height: '*', overflow: 'hidden'})),\n transition('* => animated-down', [\n style({ height: 0, overflow: 'hidden' }),\n animate(DATEPICKER_ANIMATION_TIMING)\n ]),\n state('animated-up', style({ height: '*', overflow: 'hidden'})),\n transition('* => animated-up', [\n style({ height: '*', overflow: 'hidden' }),\n animate(DATEPICKER_ANIMATION_TIMING)\n ]),\n transition('* => unanimated', animate('0s'))\n ]);\n","// datepicker container component\nimport { BsCustomDates } from '../themes/bs/bs-custom-dates-view.component';\nimport { BsDatepickerEffects } from '../reducer/bs-datepicker.effects';\nimport { Observable, Subscription } from 'rxjs';\nimport {\n BsDatepickerViewMode,\n BsNavigationEvent,\n CalendarCellViewModel,\n CellHoverEvent,\n DatepickerRenderOptions,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText,\n DaysCalendarViewModel,\n DayViewModel,\n MonthsCalendarViewModel,\n WeekViewModel,\n YearsCalendarViewModel\n} from '../models';\n\nexport abstract class BsDatepickerAbstractComponent {\n containerClass = '';\n isOtherMonthsActive?: boolean;\n showTodayBtn?: boolean;\n todayBtnLbl?: string;\n todayPos?: string;\n showClearBtn?: boolean;\n clearBtnLbl?: string;\n clearPos?: string;\n\n _effects?: BsDatepickerEffects;\n customRanges: BsCustomDates[] = [];\n customRangeBtnLbl?: string;\n chosenRange: Date[] = [];\n\n multipleCalendars?: boolean;\n\n isRangePicker?: boolean;\n withTimepicker?: boolean;\n\n set minDate(value: Date|undefined) {\n this._effects?.setMinDate(value);\n }\n\n set maxDate(value: Date|undefined) {\n this._effects?.setMaxDate(value);\n }\n set daysDisabled(value: number[]|undefined) {\n this._effects?.setDaysDisabled(value);\n }\n set datesDisabled(value: Date[]|undefined) {\n this._effects?.setDatesDisabled(value);\n }\n\n set datesEnabled(value: Date[]|undefined) {\n this._effects?.setDatesEnabled(value);\n }\n\n set isDisabled(value: boolean|undefined) {\n this._effects?.setDisabled(value);\n }\n\n set dateCustomClasses(value: DatepickerDateCustomClasses[]|undefined) {\n this._effects?.setDateCustomClasses(value);\n }\n\n set dateTooltipTexts(value: DatepickerDateTooltipText[]|undefined) {\n this._effects?.setDateTooltipTexts(value);\n }\n\n viewMode?: Observable<BsDatepickerViewMode|undefined>;\n monthsCalendar?: Observable<MonthsCalendarViewModel[]|undefined>;\n yearsCalendar?: Observable<YearsCalendarViewModel[]|undefined>;\n options$!: Observable<DatepickerRenderOptions|undefined>;\n\n _daysCalendar$!: Observable<DaysCalendarViewModel[]|undefined>;\n _daysCalendarSub = new Subscription();\n\n set daysCalendar$(value: Observable<DaysCalendarViewModel[]|undefined>) {\n this._daysCalendar$ = value;\n this._daysCalendarSub.unsubscribe();\n this._daysCalendarSub.add(this._daysCalendar$.subscribe(value => {\n this.multipleCalendars = !!value && value.length > 1;\n }));\n }\n\n get daysCalendar$(): Observable<DaysCalendarViewModel[]|undefined> {\n return this._daysCalendar$;\n }\n\n selectedTime?: Observable<Date[]|undefined>;\n selectedTimeSub = new Subscription();\n\n // todo: valorkin fix\n // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function\n setViewMode(event: BsDatepickerViewMode): void {}\n\n // eslint-disable-next-line\n navigateTo(event: BsNavigationEvent): void {}\n\n // eslint-disable-next-line\n dayHoverHandler(event: CellHoverEvent): void {}\n\n // eslint-disable-next-line\n weekHoverHandler(event: WeekViewModel): void {}\n\n // eslint-disable-next-line\n monthHoverHandler(event: CellHoverEvent): void {}\n\n // eslint-disable-next-line\n yearHoverHandler(event: CellHoverEvent): void {}\n\n // eslint-disable-next-line\n timeSelectHandler(date: Date, index: number): void {}\n\n // eslint-disable-next-line\n daySelectHandler(day: DayViewModel): void {}\n\n // eslint-disable-next-line\n monthSelectHandler(event: CalendarCellViewModel): void {}\n\n // eslint-disable-next-line\n yearSelectHandler(event: CalendarCellViewModel): void {}\n\n // eslint-disable-next-line\n setRangeOnCalendar(dates: BsCustomDates): void {}\n\n // eslint-disable-next-line\n setToday(): void {}\n\n // eslint-disable-next-line\n clearDate(): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _stopPropagation(event: any): void {\n event.stopPropagation();\n }\n}\n","import { Injectable } from '@angular/core';\nimport { TimeUnit } from 'ngx-bootstrap/chronos';\nimport { Action } from 'ngx-bootstrap/mini-ngrx';\nimport {\n BsDatepickerViewMode,\n BsViewNavigationEvent,\n CellHoverEvent,\n DatepickerRenderOptions,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText\n} from '../models';\n\n@Injectable({providedIn: 'platform'})\nexport class BsDatepickerActions {\n static readonly CALCULATE = '[datepicker] calculate dates matrix';\n static readonly FORMAT = '[datepicker] format datepicker values';\n static readonly FLAG = '[datepicker] set flags';\n static readonly SELECT = '[datepicker] select date';\n static readonly NAVIGATE_OFFSET = '[datepicker] shift view date';\n static readonly NAVIGATE_TO = '[datepicker] change view date';\n static readonly SET_OPTIONS = '[datepicker] update render options';\n static readonly HOVER = '[datepicker] hover date';\n static readonly CHANGE_VIEWMODE = '[datepicker] switch view mode';\n\n static readonly SET_MIN_DATE = '[datepicker] set min date';\n static readonly SET_MAX_DATE = '[datepicker] set max date';\n static readonly SET_DAYSDISABLED = '[datepicker] set days disabled';\n static readonly SET_DATESDISABLED = '[datepicker] set dates disabled';\n static readonly SET_DATESENABLED = '[datepicker] set dates enabled';\n static readonly SET_IS_DISABLED = '[datepicker] set is disabled';\n static readonly SET_DATE_CUSTOM_CLASSES = '[datepicker] set date custom classes';\n static readonly SET_DATE_TOOLTIP_TEXTS = '[datepicker] set date tooltip texts';\n static readonly SET_LOCALE = '[datepicker] set datepicker locale';\n static readonly SELECT_TIME = '[datepicker] select time';\n\n static readonly SELECT_RANGE = '[daterangepicker] select dates range';\n\n calculate(): Action {\n return { type: BsDatepickerActions.CALCULATE };\n }\n\n format(): Action {\n return { type: BsDatepickerActions.FORMAT };\n }\n\n flag(): Action {\n return { type: BsDatepickerActions.FLAG };\n }\n\n select(date?: Date): Action {\n return {\n type: BsDatepickerActions.SELECT,\n payload: date\n };\n }\n\n selectTime(date: Date, index: number): Action {\n return {\n type: BsDatepickerActions.SELECT_TIME,\n payload: { date, index },\n };\n }\n\n changeViewMode(event: BsDatepickerViewMode): Action {\n return {\n type: BsDatepickerActions.CHANGE_VIEWMODE,\n payload: event\n };\n }\n\n navigateTo(event: BsViewNavigationEvent): Action {\n return {\n type: BsDatepickerActions.NAVIGATE_TO,\n payload: event\n };\n }\n\n navigateStep(step?: TimeUnit): Action {\n return {\n type: BsDatepickerActions.NAVIGATE_OFFSET,\n payload: step\n };\n }\n\n setOptions(options: DatepickerRenderOptions): Action {\n return {\n type: BsDatepickerActions.SET_OPTIONS,\n payload: options\n };\n }\n\n // date range picker\n selectRange(value?: (Date|undefined)[] | undefined): Action {\n return {\n type: BsDatepickerActions.SELECT_RANGE,\n payload: value\n };\n }\n\n hoverDay(event: CellHoverEvent): Action {\n return {\n type: BsDatepickerActions.HOVER,\n payload: event.isHovered ? event.cell.date : null\n };\n }\n\n minDate(date?: Date): Action {\n return {\n type: BsDatepickerActions.SET_MIN_DATE,\n payload: date\n };\n }\n\n maxDate(date?: Date): Action {\n return {\n type: BsDatepickerActions.SET_MAX_DATE,\n payload: date\n };\n }\n\n daysDisabled(days?: number[]): Action {\n return {\n type: BsDatepickerActions.SET_DAYSDISABLED,\n payload: days\n };\n }\n\n datesDisabled(dates?: Date[]): Action {\n return {\n type: BsDatepickerActions.SET_DATESDISABLED,\n payload: dates\n };\n }\n\n datesEnabled(dates?: Date[]): Action {\n return {\n type: BsDatepickerActions.SET_DATESENABLED,\n payload: dates\n };\n }\n\n isDisabled(value?: boolean): Action {\n return {\n type: BsDatepickerActions.SET_IS_DISABLED,\n payload: value\n };\n }\n\n setDateCustomClasses(value?: DatepickerDateCustomClasses[]): Action {\n return {\n type: BsDatepickerActions.SET_DATE_CUSTOM_CLASSES,\n payload: value\n };\n }\n\n setDateTooltipTexts(value?: DatepickerDateTooltipText[]): Action {\n return {\n type: BsDatepickerActions.SET_DATE_TOOLTIP_TEXTS,\n payload: value\n };\n }\n\n setLocale(locale: string): Action {\n return {\n type: BsDatepickerActions.SET_LOCALE,\n payload: locale\n };\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\n@Injectable({providedIn: 'platform'})\nexport class BsLocaleService {\n private _defaultLocale = 'en';\n private _locale = new BehaviorSubject<string>(this._defaultLocale);\n private _localeChange: Observable<string> = this._locale.asObservable();\n\n get locale(): BehaviorSubject<string> {\n return this._locale;\n }\n\n get localeChange(): Observable<string> {\n return this._localeChange;\n }\n\n get currentLocale(): string {\n return this._locale.getValue();\n }\n\n use(locale: string): void {\n if (locale === this.currentLocale) {\n return;\n }\n\n this._locale.next(locale);\n }\n}\n","import { Injectable } from '@angular/core';\n\nimport { combineLatest, Observable, Subscription } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nimport { BsDatepickerAbstractComponent } from '../base/bs-datepicker-container';\nimport { BsDatepickerConfig } from '../bs-datepicker.config';\nimport { BsLocaleService } from '../bs-locale.service';\n\nimport {\n BsDatepickerViewMode,\n BsNavigationEvent,\n CellHoverEvent,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText,\n DatepickerRenderOptions,\n DaysCalendarViewModel,\n DayViewModel,\n MonthsCalendarViewModel,\n YearsCalendarViewModel\n} from '../models';\nimport { BsDatepickerActions } from './bs-datepicker.actions';\nimport { BsDatepickerStore } from './bs-datepicker.store';\n\n\n@Injectable({providedIn: 'platform'})\nexport class BsDatepickerEffects {\n viewMode?: Observable<BsDatepickerViewMode>;\n daysCalendar?: Observable<DaysCalendarViewModel[]>;\n monthsCalendar?: Observable<MonthsCalendarViewModel[]>;\n yearsCalendar?: Observable<YearsCalendarViewModel[]>;\n options?: Observable<DatepickerRenderOptions>;\n\n private _store?: BsDatepickerStore;\n private _subs: Subscription[] = [];\n\n constructor(private _actions: BsDatepickerActions,\n private _localeService: BsLocaleService) {\n }\n\n init(_bsDatepickerStore: BsDatepickerStore): BsDatepickerEffects {\n this._store = _bsDatepickerStore;\n\n return this;\n }\n\n /** setters */\n\n setValue(value?: Date): void {\n this._store?.dispatch(this._actions.select(value));\n }\n\n setRangeValue(value?: (Date|undefined)[] | undefined): void {\n this._store?.dispatch(this._actions.selectRange(value));\n }\n\n setMinDate(value?: Date): BsDatepickerEffects {\n this._store?.dispatch(this._actions.minDate(value));\n\n return this;\n }\n\n setMaxDate(value?: Date): BsDatepickerEffects {\n this._store?.dispatch(this._actions.maxDate(value));\n\n return this;\n }\n\n setDaysDisabled(value?: number[]): BsDatepickerEffects {\n this._store?.dispatch(this._actions.daysDisabled(value));\n\n return this;\n }\n\n setDatesDisabled(value?: Date[]): BsDatepickerEffects {\n this._store?.dispatch(this._actions.datesDisabled(value));\n\n return this;\n }\n\n setDatesEnabled(value?: Date[]): BsDatepickerEffects {\n this._store?.dispatch(this._actions.datesEnabled(value));\n\n return this;\n }\n\n setDisabled(value?: boolean): BsDatepickerEffects {\n this._store?.dispatch(this._actions.isDisabled(value));\n\n return this;\n }\n\n setDateCustomClasses(value?: DatepickerDateCustomClasses[]): BsDatepickerEffects {\n this._store?.dispatch(this._actions.setDateCustomClasses(value));\n\n return this;\n }\n\n setDateTooltipTexts(value?: DatepickerDateTooltipText[]): BsDatepickerEffects {\n this._store?.dispatch(this._actions.setDateTooltipTexts(value));\n\n return this;\n }\n\n /* Set rendering options */\n setOptions(_config: BsDatepickerConfig): BsDatepickerEffects {\n const _options = Object.assign({ locale: this._localeService.currentLocale }, _config);\n this._store?.dispatch(this._actions.setOptions(_options));\n\n return this;\n }\n\n /** view to mode bindings */\n setBindings(container: BsDatepickerAbstractComponent): BsDatepickerEffects {\n if (!this._store) {\n return this;\n }\n\n container.selectedTime = this._store.select(state => state.selectedTime)\n .pipe(filter(times => !!times));\n\n container.daysCalendar$ = this._store.select(state => state.flaggedMonths)\n .pipe(filter(months => !!months));\n\n // month calendar\n container.monthsCalendar = this._store.select(state => state.flaggedMonthsCalendar)\n .pipe(filter(months => !!months));\n\n // year calendar\n container.yearsCalendar = this._store.select(state => state.yearsCalendarFlagged)\n .pipe(filter(years => !!years));\n\n container.viewMode = this._store.select(state => state.view?.mode);\n\n container.options$ = combineLatest([\n this._store.select(state => state.showWeekNumbers),\n this._store.select(state => state.displayMonths)\n ])\n .pipe(map((latest) => ({\n showWeekNumbers: latest[0],\n displayMonths: latest[1]\n })\n ));\n\n return this;\n }\n\n /** event handlers */\n setEventHandlers(container: BsDatepickerAbstractComponent): BsDatepickerEffects {\n container.setViewMode = (event: BsDatepickerViewMode): void => {\n this._store?.dispatch(this._actions.changeViewMode(event));\n };\n\n container.navigateTo = (event: BsNavigationEvent): void => {\n this._store?.dispatch(this._actions.navigateStep(event.step));\n };\n\n container.dayHoverHandler = (event: CellHoverEvent): void => {\n const _cell = event.cell as DayViewModel;\n if (_cell.isOtherMonth || _cell.isDisabled) {\n return;\n }\n\n this._store?.dispatch(this._actions.hoverDay(event));\n _cell.isHovered = event.isHovered;\n };\n\n container.monthHoverHandler = (event: CellHoverEvent): void => {\n event.cell.isHovered = event.isHovered;\n };\n\n container.yearHoverHandler = (event: CellHoverEvent): void => {\n event.cell.isHovered = event.isHovered;\n };\n\n return this;\n }\n\n registerDatepickerSideEffects(): BsDatepickerEffects {\n if (!this._store) {\n return this;\n }\n\n this._subs.push(\n this._store.select(state => state.view).subscribe(() => {\n this._store?.dispatch(this._actions.calculate());\n })\n );\n\n // format calendar values on month model change\n this._subs.push(\n this._store\n .select(state => state.monthsModel)\n .pipe(\n filter(monthModel => !!monthModel)\n )\n .subscribe(() => this._store?.dispatch(this._actions.format()))\n );\n\n // flag day values\n this._subs.push(\n this._store\n .select(state => state.formattedMonths)\n .pipe(\n filter(month => !!month)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // flag day values\n this._subs.push(\n this._store\n .select(state => state.selectedDate)\n .pipe(\n filter(selectedDate => !!selectedDate)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // flag for date range picker\n this._subs.push(\n this._store\n .select(state => state.selectedRange)\n .pipe(\n filter(selectedRange => !!selectedRange)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // monthsCalendar\n this._subs.push(\n this._store\n .select(state => state.monthsCalendar)\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // years calendar\n this._subs.push(\n this._store\n .select(state => state.yearsCalendarModel)\n .pipe(\n filter(state => !!state)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // on hover\n this._subs.push(\n this._store\n .select(state => state.hoveredDate)\n .pipe(\n filter(hoveredDate => !!hoveredDate)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // date custom classes\n this._subs.push(\n this._store\n .select(state => state.dateCustomClasses)\n .pipe(\n filter(dateCustomClasses => !!dateCustomClasses)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // date tooltip texts\n this._subs.push(\n this._store\n .select(state => state.dateTooltipTexts)\n .pipe(\n filter(dateTooltipTexts => !!dateTooltipTexts)\n )\n .subscribe(() => this._store?.dispatch(this._actions.flag()))\n );\n\n // on locale change\n this._subs.push(\n this._localeService.localeChange\n .subscribe(locale => this._store?.dispatch(this._actions.setLocale(locale)))\n );\n\n return this;\n }\n\n destroy(): void {\n for (const sub of this._subs) {\n sub.unsubscribe();\n }\n }\n}\n","import {\n MonthViewOptions\n} from '../models';\n\nexport const defaultMonthOptions: MonthViewOptions = {\n width: 7,\n height: 6\n};\n\nexport const dayInMilliseconds = 24 * 60 * 60 * 1000;\n","import {\n BsDatepickerViewMode,\n DatepickerFormatOptions,\n DatepickerRenderOptions,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText,\n DaysCalendarModel,\n DaysCalendarViewModel,\n MonthsCalendarViewModel,\n MonthViewOptions,\n YearsCalendarViewModel\n} from '../models';\nimport { defaultMonthOptions } from './_defaults';\nimport { BsDatepickerConfig } from '../bs-datepicker.config';\n\nexport interface BsDatepickerViewState {\n date: Date;\n mode: BsDatepickerViewMode;\n}\n\nexport class BsDatepickerState\n implements DatepickerRenderOptions, DatepickerFormatOptions {\n // date picker\n selectedDate?: Date;\n // daterange picker\n selectedRange?: Date[];\n // time picker\n selectedTime?: Date[];\n\n // initial date of calendar, today by default\n view?: BsDatepickerViewState;\n\n isDisabled?: boolean;\n // bounds\n minDate?: Date;\n maxDate?: Date;\n daysDisabled?: number[];\n datesDisabled?: Date[];\n datesEnabled?: Date[];\n minMode?: BsDatepickerViewMode;\n dateCustomClasses?: DatepickerDateCustomClasses[];\n dateTooltipTexts?: DatepickerDateTooltipText[];\n\n hoveredDate?: Date;\n hoveredMonth?: Date;\n hoveredYear?: Date;\n\n // days calendar\n monthsModel?: DaysCalendarModel[];\n formattedMonths?: DaysCalendarViewModel[];\n flaggedMonths?: DaysCalendarViewModel[];\n selectFromOtherMonth?: boolean;\n showPreviousMonth?: boolean; // dateRangePicker only;\n preventChangeToNextMonth?: boolean; // dateRangePicker only;\n displayOneMonthRange?: boolean; // dateRangePicker only;\n\n // months calendar\n monthsCalendar?: MonthsCalendarViewModel[];\n flaggedMonthsCalendar?: MonthsCalendarViewModel[];\n\n // years calendar\n yearsCalendarModel?: YearsCalendarViewModel[];\n yearsCalendarFlagged?: YearsCalendarViewModel[];\n\n // options\n monthViewOptions?: MonthViewOptions;\n\n // DatepickerRenderOptions\n showWeekNumbers = true;\n displayMonths = 1;\n\n // DatepickerFormatOptions\n locale?: string;\n\n monthTitle?: string;\n yearTitle?: string;\n\n dayLabel?: string;\n monthLabel?: string;\n yearLabel?: string;\n\n weekNumbers?: string;\n}\n\nconst _initialView: BsDatepickerViewState = { date: new Date(), mode: 'day' };\n\nexport const initialDatepickerState: BsDatepickerState = Object.assign(\n new BsDatepickerConfig(),\n {\n locale: 'en',\n view: _initialView,\n selectedRange: [],\n selectedTime: [],\n monthViewOptions: defaultMonthOptions\n }\n);\n","import {\n getDay,\n isFirstDayOfWeek,\n isAfter,\n isBefore,\n shiftDate,\n endOf,\n startOf,\n isArray,\n isSame\n} from 'ngx-bootstrap/chronos';\nimport { BsDatepickerState } from '../reducer/bs-datepicker.state';\nimport { BsCustomDates } from '../themes/bs/bs-custom-dates-view.component';\n\nexport function getStartingDayOfCalendar(date: Date,\n options: { firstDayOfWeek?: number }): Date {\n if (isFirstDayOfWeek(date, options.firstDayOfWeek)) {\n return date;\n }\n\n const weekDay = getDay(date);\n const offset = calculateDateOffset(weekDay, options.firstDayOfWeek);\n\n return shiftDate(date, {day: -offset});\n}\n\nexport function calculateDateOffset(weekday: number, startingDayOffset?: number): number {\n const _startingDayOffset = Number(startingDayOffset);\n if (isNaN(_startingDayOffset)) {\n return 0;\n }\n\n if (_startingDayOffset === 0) {\n return weekday;\n }\n\n const offset = weekday - _startingDayOffset % 7;\n\n return offset < 0 ? offset + 7 : offset;\n}\n\nexport function isMonthDisabled(date: Date, min?: Date, max?: Date): boolean {\n const minBound = min && isBefore(endOf(date, 'month'), min, 'day');\n const maxBound = max && isAfter(startOf(date, 'month'), max, 'day');\n\n return minBound || maxBound || false;\n}\n\nexport function isYearDisabled(date: Date, min?: Date, max?: Date): boolean {\n const minBound = min && isBefore(endOf(date, 'year'), min, 'day');\n const maxBound = max && isAfter(startOf(date, 'year'), max, 'day');\n\n return minBound || maxBound || false;\n}\n\nexport function isDisabledDate(date?: Date, datesDisabled?: Date[], unit?: 'year' | 'date' | 'month'): boolean {\n if (!datesDisabled || !isArray(datesDisabled) || !datesDisabled.length) {\n return false;\n }\n\n if (unit && unit === 'year' && !datesDisabled[0].getDate()) {\n return datesDisabled.some((dateDisabled: Date) => isSame(date, dateDisabled, 'year'));\n }\n\n return datesDisabled.some((dateDisabled: Date) => isSame(date, dateDisabled, 'date'));\n}\n\nexport function isEnabledDate(date?: Date, datesEnabled?: Date[], unit?: 'year' | 'date' | 'month'): boolean {\n if (!datesEnabled || !isArray(datesEnabled) || !datesEnabled.length) {\n return false;\n }\n\n return !datesEnabled.some((enabledDate: Date) => isSame(date, enabledDate, unit || 'date'));\n}\n\nexport function getYearsCalendarInitialDate(state: BsDatepickerState, calendarIndex = 0): Date | undefined {\n const model = state && state.yearsCalendarModel && state.yearsCalendarModel[calendarIndex];\n\n return model?.years[0] && model.years[0][0] && model.years[0][0].date;\n}\n\nexport function checkRangesWithMaxDate(ranges?: BsCustomDates[], maxDate?: Date): BsCustomDates[] | undefined {\n if (!ranges) return ranges;\n if (!maxDate) return ranges;\n if (!ranges.length && !ranges[0].value) return ranges;\n\n ranges.forEach((item: BsCustomDates) => {\n if (!item || !item.value) return ranges;\n if (item.value instanceof Date) return ranges;\n if (!(item.value instanceof Array && item.value.length) ) return ranges;\n item.value = compareDateWithMaxDateHelper(item.value, maxDate);\n return ranges;\n });\n return ranges;\n}\n\nexport function checkBsValue(date?: Array<Date> | Date | (Date | undefined)[], maxDate?: Date): Array<Date> | Date | (Date|undefined)[] | undefined {\n if (!date) return date;\n if (!maxDate) return date;\n if (date instanceof Array && !date.length) return date;\n if (date instanceof Date) return date;\n return compareDateWithMaxDateHelper(date, maxDate);\n}\n\nfunction compareDateWithMaxDateHelper <T>(date: T, maxDate: Date): T | Date[] {\n if (date instanceof Array) {\n const editedValues = date.map(item => {\n if (!item) return item;\n if (isAfter(item, maxDate, 'date')) item = maxDate;\n return item;\n });\n return editedValues;\n }\n return date;\n}\n\nexport function setCurrentTimeOnDateSelect(value?: Date): Date | undefined {\n if (!value) return value;\n\n return setCurrentTimeHelper(value);\n}\n\nexport function setDateRangesCurrentTimeOnDateSelect(value?: (Date|undefined)[]): (Date|undefined)[] | undefined {\n if (!value?.length) return value;\n\n value.map((date) => {\n if (!date) {\n return date;\n }\n return setCurrentTimeHelper(date);\n });\n\n return value;\n}\n\nfunction setCurrentTimeHelper(date: Date): Date {\n const now = new Date();\n date.setMilliseconds(now.getMilliseconds());\n date.setSeconds(now.getSeconds());\n date.setMinutes(now.getMinutes());\n date.setHours(now.getHours());\n return date;\n}\n","import { TimeUnit, shiftDate } from 'ngx-bootstrap/chronos';\n\nexport type CreateMatrixCb<T> = (date: Date) => T;\n\nexport interface MatrixOptions {\n height: number;\n width: number;\n initialDate: Date;\n shift: TimeUnit;\n}\n\nexport function createMatrix<T>(\n options: MatrixOptions,\n fn: CreateMatrixCb<T>\n): T[][] {\n let prevValue = options.initialDate;\n const matrix: T[][] = new Array(options.height);\n for (let i = 0; i < options.height; i++) {\n matrix[i] = new Array(options.width);\n for (let j = 0; j < options.width; j++) {\n matrix[i][j] = fn(prevValue);\n prevValue = shiftDate(prevValue, options.shift);\n }\n }\n\n return matrix;\n}\n","// user and model input should handle parsing and validating input values\nimport { getFirstDayOfMonth } from 'ngx-bootstrap/chronos';\n// should accept some options\n// todo: split out formatting\nimport { DaysCalendarModel, MonthViewOptions } from '../models';\nimport { getStartingDayOfCalendar } from '../utils/bs-calendar-utils';\nimport { createMatrix, MatrixOptions } from '../utils/matrix-utils';\n\nexport function calcDaysCalendar(\n startingDate: Date,\n options: MonthViewOptions\n): DaysCalendarModel {\n const firstDay = getFirstDayOfMonth(startingDate);\n const initialDate = getStartingDayOfCalendar(firstDay, options);\n\n // todo test\n const matrixOptions: MatrixOptions = {\n width: options.width || 0,\n height: options.height || 0,\n initialDate,\n shift: { day: 1 }\n };\n const daysMatrix = createMatrix<Date>(matrixOptions, date => date);\n\n return {\n daysMatrix,\n month: firstDay\n };\n}\n","import {\n DatepickerFormatOptions,\n DaysCalendarModel,\n DaysCalendarViewModel\n} from '../models';\nimport { formatDate, getLocale } from 'ngx-bootstrap/chronos';\n\nexport function formatDaysCalendar(daysCalendar: DaysCalendarModel,\n formatOptions: DatepickerFormatOptions,\n monthIndex: number): DaysCalendarViewModel {\n return {\n month: daysCalendar.month,\n monthTitle: formatDate(\n daysCalendar.month,\n formatOptions.monthTitle,\n formatOptions.locale\n ),\n yearTitle: formatDate(\n daysCalendar.month,\n formatOptions.yearTitle,\n formatOptions.locale\n ),\n weekNumbers: getWeekNumbers(\n daysCalendar.daysMatrix,\n formatOptions.weekNumbers,\n formatOptions.locale\n ),\n weekdays: getShiftedWeekdays(formatOptions.locale),\n weeks: daysCalendar.daysMatrix.map((week: Date[], weekIndex: number) => ({\n days: week.map((date: Date, dayIndex: number) => ({\n date,\n label: formatDate(date, formatOptions.dayLabel, formatOptions.locale),\n monthIndex,\n weekIndex,\n dayIndex\n }))\n })),\n hideLeftArrow: false,\n hideRightArrow: false,\n disableLeftArrow: false,\n disableRightArrow: false\n };\n}\n\nexport function getWeekNumbers(daysMatrix: Date[][],\n format?: string,\n locale?: string): string[] {\n return daysMatrix.map(\n (days: Date[]) => (days[0] ? formatDate(days[0], format, locale) : '')\n );\n}\n\nexport function getShiftedWeekdays(locale?: string): string[] {\n const _locale = getLocale(locale);\n const weekdays = _locale.weekdaysShort() as string[];\n const firstDayOfWeek = _locale.firstDayOfWeek();\n\n return [...weekdays.slice(firstDayOfWeek), ...weekdays.slice(0, firstDayOfWeek)];\n}\n","import {\n DaysCalendarViewModel,\n DayViewModel,\n WeekViewModel,\n DatepickerDateCustomClasses,\n DatepickerDateTooltipText\n} from '../models';\n\nimport {\n isAfter,\n isBefore,\n isDisabledDay,\n isSameDay,\n isSameMonth,\n shiftDate\n} from 'ngx-bootstrap/chronos';\n\nimport { isMonthDisabled, isDisabledDate, isEnabledDate } from '../utils/bs-calendar-utils';\n\nexport interface FlagDaysCalendarOptions {\n isDisabled: boolean;\n minDate: Date;\n maxDate: Date;\n daysDisabled: number[];\n datesDisabled: Date[];\n datesEnabled: Date[];\n hoveredDate: Date;\n selectedDate: Date;\n selectedRange: Date[];\n displayMonths: number;\n monthIndex: number;\n dateCustomClasses: DatepickerDateCustomClasses[];\n dateTooltipTexts: DatepickerDateTooltipText[];\n}\n\nexport function flagDaysCalendar(\n formattedMonth: DaysCalendarViewModel,\n options: Partial<FlagDaysCalendarOptions>\n): DaysCalendarViewModel {\n formattedMonth.weeks.forEach((week: WeekViewModel) => {\n week.days.forEach((day: DayViewModel, dayIndex: number) => {\n // datepicker\n const isOtherMonth = !isSameMonth(day.date, formattedMonth.month);\n\n const isHovered =\n !isOtherMonth && isSameDay(day.date, options.hoveredDate);\n // date range picker\n const isSelectionStart =\n !isOtherMonth &&\n options.selectedRange &&\n isSameDay(day.date, options.selectedRange[0]);\n const isSelectionEnd =\n !isOtherMonth &&\n options.selectedRange &&\n isSameDay(day.date, options.selectedRange[1]);\n\n const isSelected =\n (!isOtherMonth && isSameDay(day.date, options.selectedDate)) ||\n isSelectionStart ||\n isSelectionEnd;\n\n const isInRange =\n !isOtherMonth &&\n options.selectedRange &&\n isDateInRange(day.date, options.selectedRange, options.hoveredDate);\n\n const isDisabled =\n options.isDisabled ||\n isBefore(day.date, options.minDate, 'day') ||\n isAfter(day.date, options.maxDate, 'day') ||\n isDisabledDay(day.date, options.daysDisabled) ||\n isDisabledDate(day.date, options.datesDisabled) ||\n isEnabledDate(day.date, options.datesEnabled);\n\n const currentDate = new Date();\n const isToday = !isOtherMonth && isSameDay(day.date, currentDate);\n\n const customClasses = options.dateCustomClasses && options.dateCustomClasses\n .map(dcc => isSameDay(day.date, dcc.date) ? dcc.classes : [])\n .reduce((previousValue, currentValue) => previousValue.concat(currentValue), [])\n .join(' ')\n || '';\n\n const tooltipText = options.dateTooltipTexts && options.dateTooltipTexts\n .map(tt => isSameDay(day.date, tt.date) ? tt.tooltipText : '')\n .reduce((previousValue, currentValue) => {\n previousValue.push(currentValue);\n return previousValue;\n }, [] as string[])\n .join(' ')\n || '';\n\n // decide update or not\n const newDay = Object.assign({}, day, {\n isOtherMonth,\n isHovered,\n isSelected,\n isSelectionStart,\n isSelectionEnd,\n isInRange,\n isDisabled,\n isToday,\n customClasses,\n tooltipText\n });\n\n if (\n day.isOtherMonth !== newDay.isOtherMonth ||\n day.isHovered !== newDay.isHovered ||\n day.isSelected !== newDay.isSelected ||\n day.isSelectionStart !== newDay.isSelectionStart ||\n day.isSelectionEnd !== newDay.isSelectionEnd ||\n day.isDisabled !== newDay.isDisabled ||\n day.isInRange !== newDay.isInRange ||\n day.customClasses !== newDay.customClasses ||\n day.tooltipText !== newDay.tooltipText\n ) {\n week.days[dayIndex] = newDay;\n }\n });\n });\n\n // todo: add check for linked calendars\n formattedMonth.hideLeftArrow =\n options.isDisabled ||\n (!!options.monthIndex && options.monthIndex > 0 && options.monthIndex !== options.displayMonths);\n formattedMonth.hideRightArrow =\n options.isDisabled ||\n ((!!options.monthIndex || options.monthIndex === 0) && !!options.displayMonths && options.monthIndex < options.displayMonths &&\n options.monthIndex + 1 !== options.displayMonths);\n\n formattedMonth.disableLeftArrow = isMonthDisabled(\n shiftDate(formattedMonth.month, { month: -1 }),\n options.minDate,\n options.maxDate\n );\n formattedMonth.disableRightArrow = isMonthDisabled(\n shiftDate(formattedMonth.month, { month: 1 }),\n options.minDate,\n options.maxDate\n );\n return formattedMonth;\n}\n\nfunction isDateInRange(\n date: Date,\n selectedRange?: Date[],\n hoveredDate?: Date\n): boolean {\n if (!date || !selectedRange || !selectedRange[0]) {\n return false;\n }\n\n if (selectedRange[1]) {\n return date > selectedRange[0] && date <= selectedRange[1];\n }\n\n if (hoveredDate) {\n return date > selectedRange[0] && date <= hoveredDate;\n }\n\n return false;\n}\n","import { BsDatepickerViewMode } from '../models';\n\nexport function canSwitchMode(mode: BsDatepickerViewMode, minMode?: BsDatepickerViewMode): boolean {\n return minMode ? mode >= minMode : true;\n}\n","import {\n DatepickerFormatOptions,\n MonthsCalendarViewModel,\n CalendarCellViewModel\n} from '../models';\nimport { startOf, formatDate } from 'ngx-bootstrap/chronos';\nimport { createMatrix } from '../utils/matrix-utils';\n\nconst height = 4;\nconst width = 3;\nconst shift = { month: 1 };\n\nexport function formatMonthsCalendar(\n viewDate: Date,\n formatOptions: DatepickerFormatOptions\n): MonthsCalendarViewModel {\n const initialDate = startOf(viewDate, 'year');\n const matrixOptions = { width, height, initialDate, shift };\n const monthMatrix = createMatrix<\n CalendarCellViewModel\n >(matrixOptions, date => ({\n date,\n label: formatDate(date, formatOptions.monthLabel, formatOptions.locale)\n }));\n\n return {\n months: monthMatrix,\n monthTitle: '',\n yearTitle: formatDate(\n viewDate,\n formatOptions.yearTitle,\n formatOptions.locale\n ),\n hideRightArrow: false,\n hideLeftArrow: false,\n disableRightArrow: false,\n disableLeftArrow: false\n };\n}\n","import { isSameMonth, shiftDate } from 'ngx-bootstrap/chronos';\nimport {\n MonthsCalendarViewModel,\n CalendarCellViewModel\n} from '../models';\nimport { isDisabledDate, isEnabledDate, isMonthDisabled, isYearDisabled } from '../utils/bs-calendar-utils';\n\nexport interface FlagMonthCalendarOptions {\n isDisabled: boolean;\n minDate: Date;\n maxDate: Date;\n hoveredMonth: Date;\n selectedDate: Date;\n selectedRange: Date[];\n datesDisabled: Date[];\n datesEnabled: Date[];\n displayMonths: number;\n monthIndex: number;\n}\n\nexport function flagMonthsCalendar(\n monthCalendar: MonthsCalendarViewModel,\n options: Partial<FlagMonthCalendarOptions>\n): MonthsCalendarViewModel {\n monthCalendar.months.forEach(\n (months: CalendarCellViewModel[], rowIndex: number) => {\n months.forEach((month: CalendarCellViewModel, monthIndex: number) => {\n let isSelected: boolean;\n const isHovered = isSameMonth(month.date, options.hoveredMonth);\n const isDisabled =\n options.isDisabled ||\n isDisabledDate(month.date, options.datesDisabled) ||\n isEnabledDate(month.date, options.datesEnabled, 'month') ||\n isMonthDisabled(month.date, options.minDate, options.maxDate);\n\n if (!options.selectedDate && options.selectedRange) {\n isSelected = isSameMonth(month.date, options.selectedRange[0]);\n if (!isSelected) {\n isSelected = isSameMonth(month.date, options.selectedRange[1]);\n }\n } else {\n isSelected = isSameMonth(month.date, options.selectedDate);\n }\n const newMonth = Object.assign(/*{},*/ month, {\n isHovered,\n isDisabled,\n isSelected\n });\n if (\n month.isHovered !== newMonth.isHovered ||\n month.isDisabled !== newMonth.isDisabled ||\n month.isSelected !== newMonth.isSelected\n ) {\n monthCalendar.months[rowIndex][monthIndex] = newMonth;\n }\n });\n }\n );\n\n // todo: add check for linked calendars\n monthCalendar.hideLeftArrow =\n !!options.monthIndex && options.monthIndex > 0 && options.monthIndex !== options.displayMonths;\n\n monthCalendar.hideRightArrow =\n (!!options.monthIndex || options.monthIndex === 0 )\n && (!!options.displayMonths || options.displayMonths === 0)\n && options.monthIndex < options.displayMonths\n && options.monthIndex + 1 !== options.displayMonths;\n\n monthCalendar.disableLeftArrow = isYearDisabled(\n shiftDate(monthCalendar.months[0][0].date, { year: -1 }),\n options.minDate,\n options.maxDate\n );\n monthCalendar.disableRightArrow = isYearDisabled(\n shiftDate(monthCalendar.months[0][0].date, { year: 1 }),\n options.minDate,\n options.maxDate\n );\n\n return monthCalendar;\n}\n","import {\n DatepickerFormatOptions,\n YearsCalendarViewModel,\n CalendarCellViewModel\n} from '../models';\nimport { shiftDate, formatDate } from 'ngx-bootstrap/chronos';\nimport { createMatrix } from '../utils/matrix-utils';\n\nconst height = 4;\nconst width = 4;\nexport const yearsPerCalendar = height * width;\nexport const initialYearShift = (Math.floor(yearsPerCalendar / 2) - 1) * -1;\nconst shift = { year: 1 };\n\nexport function formatYearsCalendar(\n viewDate: Date,\n formatOptions: DatepickerFormatOptions,\n previousInitialDate?: Date\n): YearsCalendarViewModel {\n const initialDate = calculateInitialDate(viewDate, previousInitialDate);\n const matrixOptions = { width, height, initialDate, shift };\n const yearsMatrix = createMatrix<\n CalendarCellViewModel\n >(matrixOptions, date => ({\n date,\n label: formatDate(date, formatOptions.yearLabel, formatOptions.locale)\n }));\n const yearTitle = formatYearRangeTitle(yearsMatrix, formatOptions);\n\n return {\n years: yearsMatrix,\n monthTitle: '',\n yearTitle,\n hideLeftArrow: false,\n hideRightArrow: false,\n disableLeftArrow: false,\n disableRightArrow: false\n };\n}\n\nfunction calculateInitialDate(viewDate: Date, previousInitialDate?: Date): Date {\n if (previousInitialDate\n && viewDate.getFullYear() >= previousInitialDate.getFullYear()\n && viewDate.getFullYear() < previousInitialDate.getFullYear() + yearsPerCalendar) {\n return previousInitialDate;\n }\n\n return shiftDate(viewDate, { year: initialYearShift });\n}\n\nfunction formatYearRangeTitle(\n yearsMatrix: CalendarCellViewModel[][],\n formatOptions: DatepickerFormatOptions\n): string {\n const from = formatDate(\n yearsMatrix[0][0].date,\n formatOptions.yearTitle,\n formatOptions.locale\n );\n const to = formatDate(\n yearsMatrix[height - 1][width - 1].date,\n formatOptions.yearTitle,\n formatOptions.locale\n );\n\n return `${from} - ${to}`;\n}\n","import { isSameYear, shiftDate } from 'ngx-bootstrap/chronos';\nimport { YearsCalendarViewModel, CalendarCellViewModel } from '../models';\nimport { isDisabledDate, isEnabledDate, isYearDisabled } from '../utils/bs-calendar-utils';\n\nexport interface FlagYearsCalendarOptions {\n isDisabled: boolean;\n minDate: Date;\n maxDate: Date;\n hoveredYear: Date;\n selectedDate: Date;\n selectedRange: Date[];\n datesDisabled: Date[];\n datesEnabled: Date[];\n displayMonths: number;\n yearIndex: number;\n}\n\nexport function flagYearsCalendar(\n yearsCalendar: YearsCalendarViewModel,\n options: Partial<FlagYearsCalendarOptions>\n): YearsCalendarViewModel {\n yearsCalendar.years.forEach(\n (years: CalendarCellViewModel[], rowIndex: number) => {\n years.forEach((year: CalendarCellViewModel, yearIndex: number) => {\n let isSelected: boolean;\n const isHovered = isSameYear(year.date, options.hoveredYear);\n const isDisabled =\n options.isDisabled ||\n isDisabledDate(year.date, options.datesDisabled, 'year') ||\n isEnabledDate(year.date, options.datesEnabled, 'year') ||\n isYearDisabled(year.date, options.minDate, options.maxDate);\n\n if (!options.selectedDate && options.selectedRange) {\n isSelected = isSameYear(year.date, options.selectedRange[0]);\n if (!isSelected) {\n isSelected = isSameYear(year.date, options.selectedRange[1]);\n }\n } else {\n isSelected = isSameYear(year.date, options.selectedDate);\n }\n\n const newMonth = Object.assign(/*{},*/ year, { isHovered, isDisabled, isSelected });\n if (\n