@bimeister/pupakit.forms
Version:
PupaKit Forms
1 lines • 555 kB
Source Map (JSON)
{"version":3,"file":"bimeister-pupakit.forms.mjs","sources":["../../src/components/control-text/components/control-text/control-text.component.ts","../../src/components/control-text/components/control-text/control-text.component.html","../../src/components/control-text/control-text.module.ts","../../src/declarations/constants/day-in-ms.const.ts","../../src/declarations/enums/day-of-week.enum.ts","../../src/declarations/functions/is-date.function.ts","../../src/declarations/functions/date-clear-time.function.ts","../../src/declarations/functions/get-days-in-month.function.ts","../../src/declarations/functions/sanitize-date.function.ts","../../src/declarations/functions/get-range-end-date.function.ts","../../src/declarations/functions/get-range-start-date.function.ts","../../src/components/date-time-picker/services/date-picker-state.service.ts","../../src/components/date-time-picker/components/date-picker-years/date-picker-years.component.ts","../../src/components/date-time-picker/components/date-picker-years/date-picker-years.component.html","../../src/components/date-time-picker/components/date-picker-months/date-picker-months.component.ts","../../src/components/date-time-picker/components/date-picker-months/date-picker-months.component.html","../../src/components/date-time-picker/components/date-picker-simple/date-picker-simple.component.ts","../../src/components/date-time-picker/components/date-picker-simple/date-picker-simple.component.html","../../src/components/date-time-picker/components/date-picker-double/date-picker-double.component.ts","../../src/components/date-time-picker/components/date-picker-double/date-picker-double.component.html","../../src/components/date-time-picker/services/time-picker-state.service.ts","../../src/components/date-time-picker/components/time-picker-digits/time-picker-digits.component.ts","../../src/components/date-time-picker/components/time-picker-digits/time-picker-digits.component.html","../../src/components/date-time-picker/components/time-picker-simple/time-picker-simple.component.ts","../../src/components/date-time-picker/components/time-picker-simple/time-picker-simple.component.html","../../src/components/date-time-picker/components/date-picker-simple-time/date-picker-simple-time.component.ts","../../src/components/date-time-picker/components/date-picker-simple-time/date-picker-simple-time.component.html","../../src/components/date-time-picker/components/date-picker/date-picker.component.ts","../../src/components/date-time-picker/components/date-picker/date-picker.component.html","../../src/components/date-time-picker/components/time-picker/time-picker.component.ts","../../src/components/date-time-picker/components/time-picker/time-picker.component.html","../../src/components/date-time-picker/date-time-picker.module.ts","../../src/components/day-selector/services/day-selector-state.service.ts","../../src/declarations/constants/default-day-selector-config.const.ts","../../src/declarations/tokens/day-selector-config.token.ts","../../src/components/day-selector/services/locale-day-formatter.service.ts","../../src/components/day-selector/components/day-selector-item/day-selector-item.component.ts","../../src/components/day-selector/components/day-selector-item/day-selector-item.component.html","../../src/components/day-selector/components/day-selector/day-selector.component.ts","../../src/components/day-selector/components/day-selector/day-selector.component.html","../../src/components/day-selector/day-selector.module.ts","../../src/components/droppable/components/droppable/droppable.component.ts","../../src/components/droppable/components/droppable/droppable.component.html","../../src/components/droppable/declarations/classes/abstract/droppable-content.abstract.ts","../../src/components/droppable/components/droppable-content/droppable-content.component.ts","../../src/components/droppable/components/droppable-content/droppable-content.component.html","../../src/components/droppable/components/droppable-legacy/droppable-legacy.component.ts","../../src/components/droppable/components/droppable-legacy/droppable-legacy.component.html","../../src/components/droppable/components/droppable-native-content/droppable-native-content.component.ts","../../src/components/droppable/components/droppable-native-content/droppable-native-content.component.html","../../src/components/droppable/components/droppable-trigger/droppable-trigger.component.ts","../../src/components/droppable/components/droppable-trigger/droppable-trigger.component.html","../../src/components/droppable/droppable.module.ts","../../src/components/form-layout/components/form-layout/form-layout.component.ts","../../src/components/form-layout/components/form-layout/form-layout.component.html","../../src/components/form-layout/components/form-elements-group/form-elements-group.component.ts","../../src/components/form-layout/components/form-elements-group/form-elements-group.component.html","../../src/components/form-layout/components/form-element/form-element.component.ts","../../src/components/form-layout/components/form-element/form-element.component.html","../../src/components/form-layout/form-layout.module.ts","../../src/declarations/classes/input-date-time-helper.class.ts","../../src/declarations/functions/is-form-control-valid-status.function.ts","../../src/declarations/classes/abstract/input-base-control-value-accessor.abstract.ts","../../src/declarations/classes/abstract/input-base.abstract.ts","../../src/declarations/classes/abstract/input-date-time-base.abstract.ts","../../src/components/input/components/input-date-range-double/input-date-range-double.component.ts","../../src/components/input/components/input-date-range-double/input-date-range-double.component.html","../../src/components/input/components/input-date-range/input-date-range.component.ts","../../src/components/input/components/input-date-range/input-date-range.component.html","../../src/components/input/components/input-date-time-seconds/input-date-time-seconds.component.ts","../../src/components/input/components/input-date-time-seconds/input-date-time-seconds.component.html","../../src/components/input/components/input-date-time/input-date-time.component.ts","../../src/components/input/components/input-date-time/input-date-time.component.html","../../src/components/input/components/input-date/input-date.component.ts","../../src/components/input/components/input-date/input-date.component.html","../../src/components/input/components/input-number/input-number.component.ts","../../src/components/input/components/input-number/input-number.component.html","../../src/components/input/components/input-password/input-password.component.ts","../../src/components/input/components/input-password/input-password.component.html","../../src/components/input/components/input-text/input-text.component.ts","../../src/components/input/components/input-text/input-text.component.html","../../src/components/input/components/input-time/input-time.component.ts","../../src/components/input/components/input-time/input-time.component.html","../../src/components/input/input.module.ts","../../src/components/label/components/label/label.component.ts","../../src/components/label/components/label/label.component.html","../../src/components/label/label.module.ts","../../src/components/radio-group/services/radio-group.service.ts","../../src/components/radio-group/components/radio-control/radio-control.component.ts","../../src/components/radio-group/components/radio-control/radio-control.component.html","../../src/components/radio-group/components/radio-group/radio-group.component.ts","../../src/components/radio-group/components/radio-group/radio-group.component.html","../../src/components/radio-group/radio-group.module.ts","../../src/components/rating/components/rating/rating.component.ts","../../src/components/rating/components/rating/rating.component.html","../../src/components/rating/rating.module.ts","../../src/components/search-field/components/search-field/search-field.component.ts","../../src/components/search-field/components/search-field/search-field.component.html","../../src/components/search-field/search-field.module.ts","../../src/components/select/components/select-dropdown-footer/select-dropdown-footer.component.ts","../../src/components/select/components/select-dropdown-footer/select-dropdown-footer.component.html","../../src/components/select/components/select-dropdown-header/select-dropdown-header.component.ts","../../src/components/select/components/select-dropdown-header/select-dropdown-header.component.html","../../src/declarations/classes/abstract/select-dropdown-base.abstract.ts","../../src/components/select/services/select-state.service.ts","../../src/components/select/components/select-dropdown/select-dropdown.component.ts","../../src/components/select/components/select-dropdown/select-dropdown.component.html","../../src/components/select/components/select-option-icon/select-option-icon.component.ts","../../src/components/select/components/select-option-icon/select-option-icon.component.html","../../src/declarations/classes/abstract/select-option-base.abstract.ts","../../src/components/select/components/select-option/select-option.component.ts","../../src/components/select/components/select-option/select-option.component.html","../../src/declarations/classes/abstract/select-options-container-base.abstract.ts","../../src/components/select/components/select-options-container/select-options-container.component.ts","../../src/components/select/components/select-options-container/select-options-container.component.html","../../src/declarations/classes/abstract/select-trigger-base.abstract.ts","../../src/components/select/components/select-trigger-extra-case/select-trigger-extra-case.component.ts","../../src/components/select/components/select-trigger-extra-case/select-trigger-extra-case.component.html","../../src/components/select/components/select-trigger-input/select-trigger-input.component.ts","../../src/components/select/components/select-trigger-input/select-trigger-input.component.html","../../src/components/select/components/select-trigger-tag/select-trigger-tag.component.ts","../../src/components/select/components/select-trigger-tag/select-trigger-tag.component.html","../../src/components/select/directives/select-trigger-tag-template.directive.ts","../../src/components/select/components/select-trigger-tags/select-trigger-tags.component.ts","../../src/components/select/components/select-trigger-tags/select-trigger-tags.component.html","../../src/components/select/components/select-trigger/select-trigger.component.ts","../../src/components/select/components/select-trigger/select-trigger.component.html","../../src/declarations/classes/abstract/select-base.abstract.ts","../../src/components/select/components/select/select.component.ts","../../src/components/select/components/select/select.component.html","../../src/components/select/select.module.ts","../../src/components/switcher/components/switcher/switcher.component.ts","../../src/components/switcher/components/switcher/switcher.component.html","../../src/components/switcher/switcher.module.ts","../../src/declarations/classes/abstract/textarea-base.abstract.ts","../../src/components/textarea/components/textarea-inline/textarea-inline.component.ts","../../src/components/textarea/components/textarea-inline/textarea-inline.component.html","../../src/components/textarea/components/textarea/textarea.component.ts","../../src/components/textarea/components/textarea/textarea.component.html","../../src/components/textarea/textarea.module.ts","../../src/forms.module.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\n\n@Component({\n selector: 'pupa-control-text',\n templateUrl: './control-text.component.html',\n styleUrls: ['./control-text.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n})\nexport class ControlTextComponent {\n @Input() public isError: boolean = false;\n}\n","<p class=\"control-text\" [class.control-text_error]=\"isError\">\n <ng-content></ng-content>\n</p>\n","import { NgModule } from '@angular/core';\nimport { ControlTextComponent } from './components/control-text/control-text.component';\n\n@NgModule({\n declarations: [ControlTextComponent],\n imports: [],\n exports: [ControlTextComponent],\n})\nexport class PupaControlTextModule {}\n","export const dayInMs: number = 86400000;\n","export enum DayOfWeek {\n Sunday,\n Monday,\n Tuesday,\n Wednesday,\n Thursday,\n Friday,\n Saturday,\n}\n","export function isDate(date: unknown): boolean {\n return !Number.isNaN(Date.parse(String(date)));\n}\n","import { isNil } from '@bimeister/utilities';\nimport { isDate } from './is-date.function';\n\nexport function dateClearTime(date: Date): Date {\n if (isNil(date) || !isDate(date)) {\n return date;\n }\n const sanitizedDate: Date = date;\n sanitizedDate.setHours(0, 0, 0, 0);\n return sanitizedDate;\n}\n","import { dateClearTime } from './date-clear-time.function';\n\nexport function getDaysInMonth(date: Date): number {\n // https://habr.com/ru/post/177059/\n const maxDaysInMonth: number = 33;\n return maxDaysInMonth - dateClearTime(new Date(date.getFullYear(), date.getMonth(), maxDaysInMonth)).getDate();\n}\n","export function sanitizeDate(date: Date): Date {\n return new Date(Date.parse(String(date)));\n}\n","import { isNil } from '@bimeister/utilities';\n\nexport function getRangeEndDate(range: Date[]): Date {\n if (!Array.isArray(range)) {\n return undefined;\n }\n const rangeEndDateIndex: number = range.findIndex(\n (rangeItem: Date, rangeItemIndex: number, rangeItemOrigin: [Date, Date]) => {\n const nextItem: Date = rangeItemOrigin[rangeItemIndex + 1];\n const previousItem: Date = rangeItemOrigin[rangeItemIndex - 1];\n\n if (isNil(rangeItem)) {\n return false;\n }\n\n if (isNil(previousItem)) {\n return rangeItem.valueOf() > nextItem.valueOf();\n }\n return rangeItem.valueOf() > previousItem.valueOf();\n }\n );\n if (Object.is(rangeEndDateIndex, -1)) {\n return range[0];\n }\n return range[rangeEndDateIndex];\n}\n","import { isNil } from '@bimeister/utilities';\n\nexport function getRangeStartDate(range: Date[]): Date {\n if (!Array.isArray(range)) {\n return undefined;\n }\n const rangeStartDateIndex: number = range.findIndex(\n (rangeItem: Date, rangeItemIndex: number, rangeItemOrigin: [Date, Date]) => {\n const nextItem: Date = rangeItemOrigin[rangeItemIndex + 1];\n const previousItem: Date = rangeItemOrigin[rangeItemIndex - 1];\n\n if (isNil(rangeItem)) {\n return false;\n }\n\n if (isNil(previousItem)) {\n return rangeItem.valueOf() < nextItem.valueOf();\n }\n return rangeItem.valueOf() < previousItem.valueOf();\n }\n );\n if (Object.is(rangeStartDateIndex, -1)) {\n return range[0];\n }\n return range[rangeStartDateIndex];\n}\n","import { Injectable } from '@angular/core';\nimport { filterFalsy, filterNotNil, isNil, shareReplayWithRefCount } from '@bimeister/utilities';\nimport { BehaviorSubject, combineLatest, NEVER, Observable } from 'rxjs';\nimport { filter, map, switchMap, take } from 'rxjs/operators';\nimport { dateClearTime } from '../../../declarations/functions/date-clear-time.function';\nimport { getRangeEndDate } from '../../../declarations/functions/get-range-end-date.function';\nimport { getRangeStartDate } from '../../../declarations/functions/get-range-start-date.function';\nimport { DatePickerPreviewMode } from '../../../declarations/types/date-picker-preview-mode.type';\nimport { DatePickerSelectionMode } from '../../../declarations/types/date-picker-selection-mode.type';\n\nconst WEEK_DAY_NAMES: string[] = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС'];\nconst INVALID_RANGE_SIZE: number = 2;\nconst VALID_RANGE_SIZE: number = 2;\n\nconst DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME: Date = dateClearTime(new Date());\n\n@Injectable({ providedIn: 'any' })\nexport class DatePickerStateService {\n public readonly weekDayNames: string[] = WEEK_DAY_NAMES;\n public readonly currentDate: Date = DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME;\n\n public readonly hours$: BehaviorSubject<number> = new BehaviorSubject<number>(null);\n public readonly minutes$: BehaviorSubject<number> = new BehaviorSubject<number>(null);\n public readonly seconds$: BehaviorSubject<number> = new BehaviorSubject<number>(null);\n\n public readonly isBackDating$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);\n public readonly availableEndDate$: BehaviorSubject<Date | number> = new BehaviorSubject<Date | number>(Infinity);\n\n public readonly selectionMode$: BehaviorSubject<DatePickerSelectionMode> =\n new BehaviorSubject<DatePickerSelectionMode>('range');\n\n public readonly previewMode$: BehaviorSubject<DatePickerPreviewMode> = new BehaviorSubject<DatePickerPreviewMode>(\n 'simple'\n );\n\n public readonly withSeconds$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);\n\n public readonly selectedDate$: BehaviorSubject<Date> = new BehaviorSubject<Date>(null);\n public readonly selectedRange$: BehaviorSubject<Date[]> = new BehaviorSubject<Date[]>([]);\n\n public readonly isSelectionModeDate$: Observable<boolean> = this.selectionMode$.pipe(\n map((selectionMode: DatePickerSelectionMode) => selectionMode === 'date'),\n shareReplayWithRefCount()\n );\n\n public readonly hoveredDate$: BehaviorSubject<Date> = new BehaviorSubject<Date>(null);\n\n public readonly hoveredRange$: Observable<Date[]> = combineLatest([this.selectedRange$, this.hoveredDate$]).pipe(\n filter((aggregatedDates: [Date[], Date]) => {\n const selectedRange: Date[] = aggregatedDates[0];\n return !Object.is(selectedRange.length, INVALID_RANGE_SIZE);\n }),\n map((aggregatedDates: [Date[], Date]) => {\n const selectedRange: Date[] = aggregatedDates[0];\n if (Object.is(selectedRange.length, 0)) {\n return [];\n }\n const selectedDateFromRange: Date = selectedRange[selectedRange.length - 1];\n const hoveredDate: Date = aggregatedDates[1];\n return [selectedDateFromRange, hoveredDate];\n }),\n shareReplayWithRefCount()\n );\n\n public processDateSelection(date: Date): void {\n this.isSelectionModeDate$\n .pipe(\n filterNotNil(),\n take(1),\n switchMap((isSelectionModeDate: boolean) => {\n if (isSelectionModeDate) {\n this.selectedDate$.next(date);\n return NEVER;\n }\n\n return this.selectedRange$;\n }),\n take(1),\n map((alreadySelectedDates: Date[]) =>\n Object.is(alreadySelectedDates.length, 1) ? [alreadySelectedDates[alreadySelectedDates.length - 1]] : []\n )\n )\n .subscribe((alreadySelectedDates: Date[]) => this.selectedRange$.next([...alreadySelectedDates, date]));\n }\n\n public processDateHover(date: Date): void {\n this.isSelectionModeDate$.pipe(filterNotNil(), take(1), filterFalsy()).subscribe(() => {\n this.hoveredDate$.next(date);\n });\n }\n\n public isSameDate(dateA: Date, dateB: Date): boolean {\n return !isNil(dateA) && !isNil(dateB) && Object.is(dateA.valueOf(), dateB.valueOf());\n }\n\n public dateIsInDateRange(date: Date, dateRange: Date[]): boolean {\n if (isNil(date) || !Array.isArray(dateRange) || Object.is(dateRange.length, 0)) {\n return false;\n }\n const uniqueRangeItemsMs: Set<number> = new Set<number>(\n dateRange.filter((rangeItem: Date) => !isNil(rangeItem)).map((rangeItem: Date) => rangeItem.valueOf())\n );\n const rangeIsInvalid: boolean = !Object.is(uniqueRangeItemsMs.size, VALID_RANGE_SIZE);\n if (rangeIsInvalid) {\n return false;\n }\n const rangeStartDate: Date = getRangeStartDate(dateRange);\n const rangeEndDate: Date = getRangeEndDate(dateRange);\n const rangeStartDateMs: number = rangeStartDate.valueOf();\n const rangeEndDateMs: number = rangeEndDate.valueOf();\n const dateToTestMs: number = date.valueOf();\n\n return rangeStartDateMs < dateToTestMs && rangeEndDateMs > dateToTestMs;\n }\n\n public dateIsInDateArray(date: Date, dateArray: Date[]): boolean {\n if (isNil(date) || !Array.isArray(dateArray) || Object.is(dateArray.length, 0)) {\n return false;\n }\n return dateArray.some((dateFromRange: Date) => this.isSameDate(dateFromRange, date));\n }\n\n public dateIsRangeStartDate(date: Date, dateRange: Date[]): boolean {\n if (isNil(date) || !Array.isArray(dateRange) || Object.is(dateRange.length, 0)) {\n return false;\n }\n const uniqueRangeItemsMs: Set<number> = new Set<number>(\n dateRange.filter((rangeItem: Date) => !isNil(rangeItem)).map((rangeItem: Date) => rangeItem.valueOf())\n );\n const rangeIsInvalid: boolean = !Object.is(uniqueRangeItemsMs.size, VALID_RANGE_SIZE);\n if (rangeIsInvalid) {\n return false;\n }\n const rangeStartDate: Date = getRangeStartDate(dateRange);\n return this.isSameDate(rangeStartDate, date);\n }\n\n public dateIsRangeEndDate(date: Date, dateRange: Date[]): boolean {\n if (isNil(date) || !Array.isArray(dateRange) || Object.is(dateRange.length, 0)) {\n return false;\n }\n const uniqueRangeItemsMs: Set<number> = new Set<number>(\n dateRange.filter((rangeItem: Date) => !isNil(rangeItem)).map((rangeItem: Date) => rangeItem.valueOf())\n );\n const rangeIsInvalid: boolean = !Object.is(uniqueRangeItemsMs.size, VALID_RANGE_SIZE);\n if (rangeIsInvalid) {\n return false;\n }\n const rangeEndDate: Date = getRangeEndDate(dateRange);\n return this.isSameDate(rangeEndDate, date);\n }\n\n public dateIsNotAvailable(date: Date, isBackDating: boolean, availableEndDate: Date | number): boolean {\n return (!isBackDating && date < DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME) || date > availableEndDate;\n }\n\n public isDateStartInHoveredAndSelectedRange(date: Date, hoveredRange: Date[], selectedRange: Date[]): boolean {\n return this.dateIsRangeStartDate(date, hoveredRange) || this.dateIsRangeStartDate(date, selectedRange);\n }\n\n public isDateEndInHoveredAndSelectedRange(date: Date, hoveredRange: Date[], selectedRange: Date[]): boolean {\n return this.dateIsRangeEndDate(date, hoveredRange) || this.dateIsRangeEndDate(date, selectedRange);\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ComponentChange, ComponentChanges } from '@bimeister/pupakit.common';\nimport { isNil } from '@bimeister/utilities';\nimport { BehaviorSubject } from 'rxjs';\nimport { dateClearTime } from '../../../../declarations/functions/date-clear-time.function';\n\nconst DEFAULT_YEAR: number = dateClearTime(new Date()).getFullYear();\nconst YEARS_IN_SECTION: number = 30;\nconst DEFAULT_YEARS: number[] = Array(YEARS_IN_SECTION)\n .fill(0)\n .map((_year: number, index: number) => DEFAULT_YEAR + index);\n\n@Component({\n selector: 'pupa-date-picker-years',\n templateUrl: './date-picker-years.component.html',\n styleUrls: ['./date-picker-years.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DatePickerYearsComponent implements OnChanges {\n @Input() public readonly years: number[] = DEFAULT_YEARS;\n public readonly years$: BehaviorSubject<number[]> = new BehaviorSubject<number[]>(DEFAULT_YEARS);\n\n public readonly currentYear: number = DEFAULT_YEAR;\n\n @Output() private readonly selectedYear: EventEmitter<number> = new EventEmitter<number>();\n\n public ngOnChanges(changes: ComponentChanges<this>): void {\n this.processYearsChange(changes?.years);\n }\n\n public selectYear(year: number): void {\n this.selectedYear.emit(year);\n }\n\n private processYearsChange(change: ComponentChange<this, number[]>): void {\n const updatedValue: number[] | undefined = change?.currentValue;\n\n if (isNil(updatedValue)) {\n return;\n }\n this.years$.next(updatedValue);\n }\n}\n","<div class=\"year\" *ngFor=\"let year of years$ | async\" [class.current]=\"year === currentYear\" (click)=\"selectYear(year)\">\n {{ year }}\n</div>\n","import { ChangeDetectionStrategy, Component, EventEmitter, Output, ViewEncapsulation } from '@angular/core';\nimport { dateClearTime } from '../../../../declarations/functions/date-clear-time.function';\n\nconst DEFAULT_MONTH: number = dateClearTime(new Date()).getMonth();\nconst MONTH_COUNT: number = 12;\n\n@Component({\n selector: 'pupa-date-picker-months',\n templateUrl: './date-picker-months.component.html',\n styleUrls: ['./date-picker-months.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DatePickerMonthsComponent {\n public readonly currentMonth: number = DEFAULT_MONTH;\n\n public readonly months: Date[] = Array(MONTH_COUNT)\n .fill(new Date())\n .map((date: Date, index: number) => {\n date.setMonth(index, 1);\n return dateClearTime(new Date(date));\n });\n\n @Output() private readonly selectedMonth: EventEmitter<number> = new EventEmitter<number>();\n\n public selectMonth(month: number): void {\n this.selectedMonth.emit(month);\n }\n}\n","<div class=\"month\" *ngFor=\"let month of months; let index = index\" (click)=\"selectMonth(index)\">\n {{ month | date : 'LLLL' | titlecase }}\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ComponentChange, ComponentChanges } from '@bimeister/pupakit.common';\nimport { filterFalsy, isNil } from '@bimeister/utilities';\nimport { BehaviorSubject, combineLatest, Observable } from 'rxjs';\nimport { distinctUntilChanged, filter, map, switchMap, take, withLatestFrom } from 'rxjs/operators';\nimport { dayInMs } from '../../../../declarations/constants/day-in-ms.const';\nimport { DayOfWeek } from '../../../../declarations/enums/day-of-week.enum';\nimport { dateClearTime } from '../../../../declarations/functions/date-clear-time.function';\nimport { getDaysInMonth } from '../../../../declarations/functions/get-days-in-month.function';\nimport { isDate } from '../../../../declarations/functions/is-date.function';\nimport { sanitizeDate } from '../../../../declarations/functions/sanitize-date.function';\nimport { DatePickerStateService } from '../../services/date-picker-state.service';\nimport { DatePickerPreviewMode } from '../../../../declarations/types/date-picker-preview-mode.type';\n\nconst DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME: Date = dateClearTime(new Date());\nconst YEARS_IN_SECTION: number = 30;\nconst YEARS_START_OFFSET: number = 19;\n\nconst MIN_DAYS_MONTH: number = 28;\n\nenum DatePickerState {\n Years,\n Months,\n Days,\n}\n\n@Component({\n selector: 'pupa-date-picker-simple',\n templateUrl: './date-picker-simple.component.html',\n styleUrls: ['./date-picker-simple.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DatePickerSimpleComponent implements OnChanges {\n @Input() public readonly baseDate: Date = DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME;\n public readonly baseDate$: BehaviorSubject<Date> = new BehaviorSubject<Date>(DEFAULT_CURRENT_DATE_WITH_CLEARED_TIME);\n\n @Input() public readonly isLeftDoubleDatePicker: boolean = false;\n public readonly isLeftDoubleDatePicker$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);\n\n @Input() public readonly isRightDoubleDatePicker: boolean = false;\n public readonly isRightDoubleDatePicker$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);\n\n @Input() public readonly needAddedWeek: boolean = false;\n public readonly needAddedWeek$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);\n\n @Output() public readonly nextMonthClicked: EventEmitter<void> = new EventEmitter<void>();\n @Output() public readonly previousMonthClicked: EventEmitter<void> = new EventEmitter<void>();\n\n public readonly weekDayNames: string[] = this.datePickerStateService.weekDayNames;\n\n public readonly datePickerPreviewMode: typeof DatePickerState = DatePickerState;\n public readonly datePickerPreviewMode$: BehaviorSubject<DatePickerState> = new BehaviorSubject<DatePickerState>(\n DatePickerState.Days\n );\n\n public readonly previewMode$: BehaviorSubject<DatePickerPreviewMode> = this.datePickerStateService.previewMode$;\n\n public readonly selectedDate$: BehaviorSubject<Date> = this.datePickerStateService.selectedDate$;\n public readonly selectedRange$: BehaviorSubject<Date[]> = this.datePickerStateService.selectedRange$;\n\n public readonly isSelectionModeDate$: Observable<boolean> = this.datePickerStateService.isSelectionModeDate$;\n public readonly isDatePickerDoubleModeEnabled$: Observable<boolean> = combineLatest([\n this.isLeftDoubleDatePicker$,\n this.isRightDoubleDatePicker$,\n ]).pipe(\n map(([isLeftDoubleDatePicker, isRightDoubleDatePicker]: [boolean, boolean]) =>\n [isLeftDoubleDatePicker, isRightDoubleDatePicker].includes(true)\n )\n );\n\n public readonly hoveredDate$: BehaviorSubject<Date> = this.datePickerStateService.hoveredDate$;\n public readonly hoveredRange$: Observable<Date[]> = this.datePickerStateService.hoveredRange$;\n\n public readonly isBackDating$: BehaviorSubject<boolean> = this.datePickerStateService.isBackDating$;\n public readonly availableEndDate$: BehaviorSubject<Date | number> = this.datePickerStateService.availableEndDate$;\n\n public readonly primarySectionStartDate$: Observable<Date> = this.baseDate$.pipe(\n distinctUntilChanged(),\n filter((baseDate: Date) => isDate(baseDate)),\n map((baseDate: Date) => {\n const baseMonthDay: number = baseDate.getDate();\n const baseDateMs: number = baseDate.valueOf();\n return baseDateMs - (baseMonthDay - 1) * dayInMs;\n }),\n map((sectionStartDateMs: number) => dateClearTime(new Date(sectionStartDateMs)))\n );\n\n public readonly baseYear$: Observable<number> = this.primarySectionStartDate$.pipe(\n distinctUntilChanged(),\n map((primarySectionStartDate: Date) => primarySectionStartDate.getFullYear())\n );\n\n public readonly primarySectionEndDate$: Observable<Date> = this.baseDate$.pipe(\n distinctUntilChanged(),\n filter((baseDate: Date) => isDate(baseDate)),\n map((baseDate: Date) => {\n const baseMonthDay: number = baseDate.getDate();\n const baseDateMs: number = baseDate.valueOf();\n const daysInMonth: number = getDaysInMonth(baseDate);\n\n return Object.is(baseMonthDay, daysInMonth) ? baseDateMs : baseDateMs + (daysInMonth - baseMonthDay) * dayInMs;\n }),\n map((sectionStartDateMs: number) => dateClearTime(new Date(sectionStartDateMs)))\n );\n\n public readonly primarySectionDates$: Observable<Date[]> = this.primarySectionStartDate$.pipe(\n distinctUntilChanged(),\n map((sectionStartDate: Date) => {\n const daysInMonth: number = getDaysInMonth(sectionStartDate);\n const sectionStartDateMs: number = sectionStartDate.valueOf();\n return new Array(daysInMonth)\n .fill(sectionStartDateMs)\n .map((startDateMs: number, dayInMonth: number) => startDateMs + dayInMonth * dayInMs);\n }),\n map((sectionDatesMs: number[]) => sectionDatesMs.map((dateMs: number) => dateClearTime(new Date(dateMs))))\n );\n\n public readonly primarySectionLeftOffsetDates$: Observable<Date[]> = this.primarySectionStartDate$.pipe(\n distinctUntilChanged(),\n map((sectionStartDate: Date) => {\n const sectionStartDateMs: number = sectionStartDate.valueOf();\n const lastDayOfPreviousMonthMs: number = sectionStartDateMs - dayInMs;\n return dateClearTime(new Date(lastDayOfPreviousMonthMs));\n }),\n map((previousMonthLastDate: Date) => {\n const previousMonthLastDateDayOfWeek: DayOfWeek = previousMonthLastDate.getDay();\n if (previousMonthLastDateDayOfWeek === DayOfWeek.Sunday) {\n return [];\n }\n const previousMonthLastDateMs: number = previousMonthLastDate.valueOf();\n const visibleDaysCount: number = previousMonthLastDateDayOfWeek;\n return new Array(visibleDaysCount)\n .fill(previousMonthLastDateMs)\n .map((lastMonthDateMs: number, multiplier: number) => lastMonthDateMs - multiplier * dayInMs);\n }),\n map((previousMonthDatesMs: number[]) => [...previousMonthDatesMs].reverse()),\n map((reversedPreviousMonthDatesMs: number[]) =>\n reversedPreviousMonthDatesMs.map((dateMs: number) => dateClearTime(new Date(dateMs)))\n )\n );\n\n public readonly primarySectionRightOffsetDates$: Observable<Date[]> = this.needAddedWeek$.pipe(\n switchMap((needAddedWeek: boolean) =>\n this.primarySectionEndDate$.pipe(\n distinctUntilChanged(),\n map((sectionEndDate: Date) => {\n const currentSectionDate: Date = new Date(sectionEndDate);\n const month: number = currentSectionDate.getMonth() + 1;\n currentSectionDate.setDate(1);\n currentSectionDate.setMonth(month);\n\n return [sectionEndDate, dateClearTime(new Date(currentSectionDate))];\n }),\n withLatestFrom(this.previewMode$),\n map(([[currentSectionEndDate, nextMonthFirstDate], previewMode]: [[Date, Date], DatePickerPreviewMode]) => {\n const nextMonthFirstDateDayOfWeek: DayOfWeek = nextMonthFirstDate.getDay();\n const nextMonthFirstDateMs: number = nextMonthFirstDate.valueOf();\n\n const currentDaysInMonth: number = getDaysInMonth(currentSectionEndDate);\n const currentMonthIsSmall: boolean = currentDaysInMonth === MIN_DAYS_MONTH;\n const currentMonthPreviewModeIsDouble: boolean = previewMode === 'double';\n const nextMonthFirstDateDayIsMonday: boolean = nextMonthFirstDateDayOfWeek === DayOfWeek.Monday;\n const nextMonthFirstDateDayIsSunday: boolean = nextMonthFirstDateDayOfWeek === DayOfWeek.Sunday;\n\n const currentMonthIsSmallAndInDouble: boolean = currentMonthIsSmall && currentMonthPreviewModeIsDouble;\n\n if (nextMonthFirstDateDayIsMonday && !currentMonthIsSmallAndInDouble) {\n return [];\n }\n const visibleDaysCount: number = nextMonthFirstDateDayIsSunday ? 1 : 8 - nextMonthFirstDateDayOfWeek;\n\n const resultDaysCount: number = needAddedWeek ? visibleDaysCount + 7 : visibleDaysCount;\n\n return new Array(resultDaysCount)\n .fill(nextMonthFirstDateMs)\n .map((lastMonthDateMs: number, multiplier: number) => lastMonthDateMs + multiplier * dayInMs);\n }),\n map((reversedPreviousMonthDatesMs: number[]) =>\n reversedPreviousMonthDatesMs.map((dateMs: number) => dateClearTime(new Date(dateMs)))\n )\n )\n )\n );\n\n public readonly primarySectionYears$: Observable<number[]> = this.primarySectionStartDate$.pipe(\n distinctUntilChanged(),\n map((sectionStartDate: Date) => sectionStartDate.getFullYear()),\n map((currentYear: number) => {\n const startYearInSection: number =\n Math.floor(currentYear / YEARS_IN_SECTION) * YEARS_IN_SECTION - YEARS_START_OFFSET;\n\n const resultStartYearInSection: number =\n startYearInSection + YEARS_IN_SECTION > currentYear ? startYearInSection : currentYear;\n\n return Array(YEARS_IN_SECTION)\n .fill(0)\n .map((_year: number, index: number) => resultStartYearInSection + index);\n })\n );\n\n public readonly primarySectionYearsStartYear$: Observable<number> = this.primarySectionYears$.pipe(\n map((years: number[]) => years[0])\n );\n public readonly primarySectionYearsEndYear$: Observable<number> = this.primarySectionYears$.pipe(\n map((years: number[]) => years[years.length - 1])\n );\n\n constructor(private readonly datePickerStateService: DatePickerStateService) {}\n\n public ngOnChanges(changes: ComponentChanges<this>): void {\n this.processBaseDateChange(changes?.baseDate);\n this.processIsLeftDoubleDatePickerChange(changes?.isLeftDoubleDatePicker);\n this.processIsRightDoubleDatePickerChange(changes?.isRightDoubleDatePicker);\n this.processNeedAddedWeekChange(changes?.needAddedWeek);\n }\n\n public switchToPreviousMonth(): void {\n this.baseDate$\n .pipe(\n take(1),\n map((currentBaseDate: Date) => {\n const month: number = currentBaseDate.getMonth() - 1;\n currentBaseDate.setMonth(month, 1);\n return currentBaseDate;\n }),\n map((newBaseDateMs: Date) => dateClearTime(new Date(newBaseDateMs)))\n )\n .subscribe((newBaseDate: Date) => {\n this.baseDate$.next(newBaseDate);\n this.previousMonthClicked.emit();\n });\n }\n\n public switchToNextMonth(): void {\n this.baseDate$\n .pipe(\n take(1),\n map((currentBaseDate: Date) => {\n const month: number = currentBaseDate.getMonth() + 1;\n currentBaseDate.setMonth(month, 1);\n return currentBaseDate;\n }),\n map((newBaseDateMs: Date) => dateClearTime(new Date(newBaseDateMs)))\n )\n .subscribe((newBaseDate: Date) => {\n this.baseDate$.next(newBaseDate);\n this.nextMonthClicked.emit();\n });\n }\n\n public switchToNextYear(): void {\n this.baseYear$.pipe(take(1)).subscribe((year: number) => this.switchToYear(year + 1));\n }\n\n public switchToPreviousYear(): void {\n this.baseYear$.pipe(take(1)).subscribe((year: number) => this.switchToYear(year - 1));\n }\n\n public switchToYear(year: number): void {\n this.baseDate$\n .pipe(\n take(1),\n map((currentBaseDate: Date) => dateClearTime(new Date(currentBaseDate.setFullYear(year))))\n )\n .subscribe((newBaseDate: Date) => {\n this.datePickerPreviewMode$.next(DatePickerState.Months);\n this.baseDate$.next(newBaseDate);\n });\n }\n\n public switchToMonth(month: number): void {\n this.baseDate$\n .pipe(\n take(1),\n map((currentBaseDate: Date) => dateClearTime(new Date(currentBaseDate.setMonth(month, 1))))\n )\n .subscribe((newBaseDate: Date) => {\n this.datePickerPreviewMode$.next(DatePickerState.Days);\n this.baseDate$.next(newBaseDate);\n });\n }\n\n public switchToPreviousYearsPeriod(): void {\n this.primarySectionYearsStartYear$\n .pipe(\n take(1),\n switchMap((primarySectionYearsStartYear: number) => {\n const nextSectionYearsStartYear: number = primarySectionYearsStartYear - YEARS_IN_SECTION;\n\n return this.baseDate$.pipe(\n take(1),\n map((currentBaseDate: Date) =>\n dateClearTime(new Date(currentBaseDate.setFullYear(nextSectionYearsStartYear)))\n )\n );\n })\n )\n .subscribe((newBaseDate: Date) => {\n this.baseDate$.next(newBaseDate);\n });\n }\n\n public switchToNextYearsPeriod(): void {\n this.primarySectionYearsStartYear$\n .pipe(\n take(1),\n switchMap((primarySectionYearsStartYear: number) => {\n const nextSectionYearsStartYear: number = primarySectionYearsStartYear + YEARS_IN_SECTION;\n\n return this.baseDate$.pipe(\n take(1),\n map((currentBaseDate: Date) =>\n dateClearTime(new Date(currentBaseDate.setFullYear(nextSectionYearsStartYear)))\n )\n );\n })\n )\n .subscribe((newBaseDate: Date) => {\n this.baseDate$.next(newBaseDate);\n });\n }\n\n public switchDatePickerPreviewMode(mode: DatePickerState): void {\n this.isDatePickerDoubleModeEnabled$\n .pipe(take(1), filterFalsy())\n .subscribe(() => this.datePickerPreviewMode$.next(mode));\n }\n\n public processDateSelection(date: Date): void {\n this.datePickerStateService.processDateSelection(date);\n }\n\n public processDateHover(date: Date): void {\n this.datePickerStateService.processDateHover(date);\n }\n\n public isSameDate(dateA: Date, dateB: Date): boolean {\n return this.datePickerStateService.isSameDate(dateA, dateB);\n }\n\n public dateIsInDateRange(date: Date, dateRange: Date[]): boolean {\n return this.datePickerStateService.dateIsInDateRange(date, dateRange);\n }\n\n public dateIsInDateArray(date: Date, dateArray: Date[]): boolean {\n return this.datePickerStateService.dateIsInDateArray(date, dateArray);\n }\n\n public dateIsRangeStartDate(date: Date, dateRange: Date[]): boolean {\n return this.datePickerStateService.dateIsRangeStartDate(date, dateRange);\n }\n\n public dateIsRangeEndDate(date: Date, dateRange: Date[]): boolean {\n return this.datePickerStateService.dateIsRangeEndDate(date, dateRange);\n }\n\n public dateIsNotAvailable(date: Date, isBackDating: boolean, availableEndDate: Date | number): boolean {\n return this.datePickerStateService.dateIsNotAvailable(date, isBackDating, availableEndDate);\n }\n\n public isDateStartInHoveredAndSelectedRange(date: Date, hoveredRange: Date[], selectedRange: Date[]): boolean {\n return this.datePickerStateService.isDateStartInHoveredAndSelectedRange(date, hoveredRange, selectedRange);\n }\n\n public isDateEndInHoveredAndSelectedRange(date: Date, hoveredRange: Date[], selectedRange: Date[]): boolean {\n return this.datePickerStateService.isDateEndInHoveredAndSelectedRange(date, hoveredRange, selectedRange);\n }\n\n private processBaseDateChange(change: ComponentChange<this, Date>): void {\n const updatedValue: Date | undefined = change?.currentValue;\n\n if (isNil(updatedValue) || !isDate(updatedValue)) {\n return;\n }\n const sanitizedDate: Date = sanitizeDate(updatedValue);\n const sanitizedDateWithClearedTime: Date = dateClearTime(sanitizedDate);\n this.baseDate$.next(sanitizedDateWithClearedTime);\n }\n\n private processIsLeftDoubleDatePickerChange(change: ComponentChange<this, boolean>): void {\n const updatedValue: boolean | undefined = change?.currentValue;\n\n if (isNil(updatedValue)) {\n return;\n }\n this.isLeftDoubleDatePicker$.next(updatedValue);\n }\n\n private processIsRightDoubleDatePickerChange(change: ComponentChange<this, boolean>): void {\n const updatedValue: boolean | undefined = change?.currentValue;\n\n if (isNil(updatedValue)) {\n return;\n }\n this.isRightDoubleDatePicker$.next(updatedValue);\n }\n\n private processNeedAddedWeekChange(change: ComponentChange<this, boolean>): void {\n const updatedValue: boolean | undefined = change?.currentValue;\n\n if (isNil(updatedValue)) {\n return;\n }\n this.needAddedWeek$.next(updatedValue);\n }\n}\n","<ng-container [ngSwitch]=\"datePickerPreviewMode$ | async\">\n <ng-container *ngSwitchCase=\"datePickerPreviewMode.Years\" [ngTemplateOutlet]=\"yearsTemplate\"></ng-container>\n <ng-container *ngSwitchCase=\"datePickerPreviewMode.Months\" [ngTemplateOutlet]=\"monthsTemplate\"></ng-container>\n <ng-container *ngSwitchDefault [ngTemplateOutlet]=\"datesTemplate\"></ng-container>\n</ng-container>\n\n<ng-template #datesTemplate>\n <ng-container [ngTemplateOutlet]=\"headerDatesTemplate\"></ng-container>\n\n <div class=\"date-picker__week-days\">\n <span class=\"week-day\" *ngFor=\"let dayName of weekDayNames\">\n {{ dayName }}\n </span>\n </div>\n\n <div class=\"date-picker__wrapper\">\n <ng-container\n [ngTemplateOutlet]=\"dateButton\"\n [ngTemplateOutletContext]=\"{\n dateOrigin: primarySectionLeftOffsetDates$ | async,\n disabled: true\n }\"\n ></ng-container>\n\n <ng-container\n [ngTemplateOutlet]=\"dateButton\"\n [ngTemplateOutletContext]=\"{\n dateOrigin: primarySectionDates$ | async,\n disabled: false\n }\"\n ></ng-container>\n\n <ng-container\n [ngTemplateOutlet]=\"dateButton\"\n [ngTemplateOutletContext]=\"{\n dateOrigin: primarySectionRightOffsetDates$ | async,\n disabled: true\n }\"\n ></ng-container>\n </div>\n</ng-template>\n\n<ng-template #yearsTemplate>\n <ng-container [ngTemplateOutlet]=\"headerYearsTemplate\"></ng-container>\n <div class=\"date-picker__wrapper\">\n <pupa-date-picker-years\n [years]=\"primarySectionYears$ | async\"\n (selectedYear)=\"switchToYear($event)\"\n ></pupa-date-picker-years>\n </div>\n</ng-template>\n\n<ng-template #monthsTemplate>\n <ng-container [ngTemplateOutlet]=\"headerMonthsTemplate\"></ng-container>\n <div class=\"date-picker__wrapper\">\n <pupa-date-picker-months (selectedMonth)=\"switchToMonth($event)\"></pupa-date-picker-months>\n </div>\n</ng-template>\n\n<ng-template #dateButton let-dateOrigin=\"dateOrigin\" let-disabled=\"disabled\">\n <div\n class=\"date-wrapper\"\n *ngFor=\"let date of dateOrigin; index as index; last as last; first as first\"\n [class.date-wrapper__disabled]=\"\n disabled || dateIsNotAvailable(date, isBackDating$ | async, availableEndDate$ | async)\n \"\n [class.date-wrapper__range]=\"\n !disabled &&\n !(isSelectionModeDate$ | async) &&\n (dateIsInDateRange(date, selectedRange$ | async) || dateIsInDateRange(date, hoveredRange$ | async))\n \"\n [class.date-wrapper__first]=\"!disabled && first\"\n [class.date-wrapper__last]=\"!disabled && last\"\n >\n <div\n class=\"date\"\n [class.date__range-start]=\"\n isDateStartInHoveredAndSelectedRange(date, hoveredRange$ | async, selectedRange$ | async)\n \"\n [class.date__range-end]=\"isDateEndInHoveredAndSelectedRange(date, hoveredRange$ | async, selectedRange$ | async)\"\n (mouseover)=\"processDateHover(date)\"\n (click)=\"processDateSelection(date)\"\n >\n <div\n class=\"date-inner\"\n [class.date-inner__selected]=\"\n (isSelectionModeDate$ | async)\n ? isSameDate(date, selectedDate$ | async)\n : dateIsInDateArray(date, selectedRange$ | async)\n \"\n [class.date-inner__disabled]=\"\n disabled || dateIsNotAvailable(date, isBackDating$ | async, availableEndDate$ | async)\n \"\n >\n {{ date | date : 'd' }}\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #headerDatesTemplate>\n <div class=\"date-picker__header\">\n <button\n class=\"arrow-button\"\n [class.not-showing]=\"isRightDoubleDatePicker$ | async\"\n (click)=\"switchToPreviousMonth()\"\n >\n <pupa-icon name=\"ios-arrow-back\"></pupa-icon>\n </button>\n <span class=\"title\">\n <div\n class=\"title__month\"\n [class.disable-hover]=\"isDatePickerDoubleModeEnabled$ | async\"\n (click)=\"switchDatePickerPreviewMode(datePickerPreviewMode.Months)\"\n >\n {{ primarySectionStartDate$ | async | date : 'LLLL' | titlecase }}\n </div>\n \n <div\n class=\"title__year\"\n [class.disable-hover]=\"isDatePickerDoubleModeEnabled$ | async\"\n (click)=\"switchDatePickerPreviewMode(datePickerPreviewMode.Years)\"\n >\n {{ primarySectionStartDate$ | async | date : 'yyy' | titlecase }}\n </div>\n </span>\n <button class=\"arrow-button\" [class.not-showing]=\"isLeftDoubleDatePicker$ | async\" (click)=\"switchToNextMonth()\">\n <pupa-icon name=\"ios-arrow-forward\"></pupa-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #headerYearsTemplate>\n <div class=\"date-picker__header\">\n <button class=\"arrow-button\" (click)=\"switchToPreviousYearsPeriod()\">\n <pupa-icon name=\"ios-arrow-back\"></pupa-icon>\n </button>\n <span class=\"title selected\">\n <div class=\"title__year\">\n {{ primarySectionYearsStartYear$ | async }}\n </div>\n - \n <div class=\"title__year\">\n {{ primarySectionYearsEndYear$ | async }}\n </div>\n </span>\n <button class=\"arrow-button\" (click)=\"switchToNextYearsPeriod()\">\n <pupa-icon name=\"ios-arrow-forward\"></pupa-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #headerMonthsTemplate>\n <div class=\"date-picker__header\">\n <button class=\"arrow-button\" (click)=\"switchToPreviousYear()\">\n <pupa-icon name=\"ios-arrow-back\"></pupa-icon>\n </button>\n <span class=\"title selected\">\n <div class=\"title__year\">\n {{ baseYear$ | async }}\n </div>\n </span>\n <button class=\"arrow-button\" (click)=\"switchToNextYear()\">\n <pupa-icon name=\"ios-arrow-forward\"></pupa-icon>\n </button>\n </div>\n</ng-template>\n","import { ChangeDetectionStrategy, Component, Input, OnChanges, ViewEncapsulation } from '@angular/core';\nimport { ComponentChange, ComponentChanges } from '@bimeister/pupakit.common';\nimport { isNil } from '@bimeister/utilities';\nimport { BehaviorSubject, Observable, of } from 'rxjs';\nimport { distinctUntilChanged, filter, map, switchMap, take } from 'rxjs/operators';\nimport { dayInMs } from '../../../../declarations/constants/day-in-ms.const';\nimport { DayOfWeek } from '../../../../declarations/enums/day-of-week.enum';\nimport { dateClearTime } from '../../../../declarations/functions/date-clear-time.function';\nimport { getDaysInMonth } from '../../../../declarations/functions/get-days-in-month.function';\nimport { isDate } from '../../../../declarations/functions/is-date.function';\nimport { sanitizeDate } from '../../../../declarations/functions/sanitize-date.functio