igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1 lines • 192 kB
Source Map (JSON)
{"version":3,"file":"igniteui-angular-date-picker.mjs","sources":["../../../projects/igniteui-angular/date-picker/src/date-picker/picker-base.directive.ts","../../../projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area.component.ts","../../../projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area-component.html","../../../projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.ts","../../../projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.html","../../../projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.ts","../../../projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.html","../../../projects/igniteui-angular/date-picker/src/date-picker/public_api.ts","../../../projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker-inputs.common.ts","../../../projects/igniteui-angular/input-group/src/input-group/input-group.component.html","../../../projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.ts","../../../projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.html","../../../projects/igniteui-angular/date-picker/src/date-range-picker/public_api.ts","../../../projects/igniteui-angular/date-picker/src/date-picker/date-picker.module.ts","../../../projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.module.ts","../../../projects/igniteui-angular/date-picker/src/igniteui-angular-date-picker.ts"],"sourcesContent":["import {\n AfterContentChecked,\n AfterViewInit, booleanAttribute, ContentChildren, Directive, ElementRef, EventEmitter,\n inject,\n Input, LOCALE_ID, OnDestroy, Output, QueryList, ViewChild\n} from '@angular/core';\nimport { getLocaleFirstDayOfWeek } from \"@angular/common\";\n\nimport { merge, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { IGX_INPUT_GROUP_TYPE, IgxInputGroupComponent, IgxInputGroupType, IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group';\nimport { DateRange, EditorProvider, IBaseCancelableBrowserEventArgs, IBaseEventArgs, IgxOverlayOutletDirective, IgxPickerClearComponent, IgxPickerToggleComponent, IToggleView, OverlaySettings, PickerHeaderOrientation, PickerInteractionMode, WEEKDAYS } from 'igniteui-angular/core';\n\n@Directive()\nexport abstract class PickerBaseDirective implements IToggleView, EditorProvider, AfterViewInit, AfterContentChecked, OnDestroy {\n public element = inject(ElementRef);\n protected _localeId = inject<string>(LOCALE_ID);\n protected _inputGroupType = inject<IgxInputGroupType>(IGX_INPUT_GROUP_TYPE, { optional: true });\n \n /**\n * The editor's input mask.\n *\n * @remarks\n * Also used as a placeholder when none is provided.\n *\n * @example\n * ```html\n * <igx-date-picker inputFormat=\"dd/MM/yy\"></igx-date-picker>\n * ```\n */\n @Input()\n public inputFormat: string;\n\n /**\n * The format used to display the picker's value when it's not being edited.\n *\n * @remarks\n * Uses Angular's DatePipe.\n *\n * @example\n * ```html\n * <igx-date-picker displayFormat=\"EE/M/yy\"></igx-date-picker>\n * ```\n *\n */\n @Input()\n public displayFormat: string;\n\n /**\n * Sets the `placeholder` of the picker's input.\n *\n * @example\n * ```html\n * <igx-date-picker [placeholder]=\"'Choose your date'\"></igx-date-picker>\n * ```\n */\n @Input()\n public placeholder = '';\n\n /**\n * Can be `dropdown` with editable input field or `dialog` with readonly input field.\n *\n * @remarks\n * Default mode is `dropdown`\n *\n * @example\n * ```html\n * <igx-date-picker mode=\"dialog\"></igx-date-picker>\n * ```\n */\n @Input()\n public mode: PickerInteractionMode = PickerInteractionMode.DropDown;\n\n /**\n * Gets/Sets the orientation of the `IgxDatePickerComponent` header.\n *\n * @example\n * ```html\n * <igx-date-picker headerOrientation=\"vertical\"></igx-date-picker>\n * ```\n */\n @Input()\n public headerOrientation: PickerHeaderOrientation = PickerHeaderOrientation.Horizontal;\n\n /**\n * Gets/Sets whether the header is hidden in dialog mode.\n *\n * @example\n * ```html\n * <igx-date-picker mode=\"dialog\" [hideHeader]=\"true\"></igx-date-picker>\n * ```\n */\n @Input({ transform: booleanAttribute })\n public hideHeader = false;\n\n /**\n * Overlay settings used to display the pop-up element.\n *\n * @example\n * ```html\n * <igx-date-picker [overlaySettings]=\"customOverlaySettings\"></igx-date-picker>\n * ```\n */\n @Input()\n public overlaySettings: OverlaySettings;\n\n /**\n * Enables or disables the picker.\n *\n * @example\n * ```html\n * <igx-date-picker [disabled]=\"'true'\"></igx-date-picker>\n * ```\n */\n @Input({ transform: booleanAttribute })\n public disabled = false;\n\n /**\n * @example\n * ```html\n * <igx-date-picker locale=\"jp\"></igx-date-picker>\n * ```\n */\n /**\n * Gets the `locale` of the date-picker.\n * If not set, defaults to applciation's locale..\n */\n @Input()\n public get locale(): string {\n return this._locale;\n }\n\n /**\n * Sets the `locale` of the date-picker.\n * Expects a valid BCP 47 language tag.\n */\n public set locale(value: string) {\n this._locale = value;\n // if value is invalid, set it back to _localeId\n try {\n getLocaleFirstDayOfWeek(this._locale);\n } catch (e) {\n this._locale = this._localeId;\n }\n }\n\n /**\n * Gets the start day of the week.\n * Can return a numeric or an enum representation of the week day.\n * If not set, defaults to the first day of the week for the application locale.\n */\n @Input()\n public get weekStart(): WEEKDAYS | number {\n return this._weekStart ?? getLocaleFirstDayOfWeek(this._locale);\n }\n\n /**\n * Sets the start day of the week.\n * Can be assigned to a numeric value or to `WEEKDAYS` enum value.\n */\n public set weekStart(value: WEEKDAYS | number) {\n this._weekStart = value;\n }\n\n /**\n * The container used for the pop-up element.\n *\n * @example\n * ```html\n * <div igxOverlayOutlet #outlet=\"overlay-outlet\"></div>\n * <!-- ... -->\n * <igx-date-picker [outlet]=\"outlet\"></igx-date-picker>\n * <!-- ... -->\n * ```\n */\n @Input()\n public outlet: IgxOverlayOutletDirective | ElementRef;\n\n /**\n * Determines how the picker's input will be styled.\n *\n * @remarks\n * Default is `box`.\n *\n * @example\n * ```html\n * <igx-date-picker [type]=\"'line'\"></igx-date-picker>\n * ```\n */\n @Input()\n public set type(val: IgxInputGroupType) {\n this._type = val;\n }\n public get type(): IgxInputGroupType {\n return this._type || this._inputGroupType;\n }\n\n /**\n * Gets/Sets the default template editor's tabindex.\n *\n * @example\n * ```html\n * <igx-date-picker [tabIndex]=\"1\"></igx-date-picker>\n * ```\n */\n @Input()\n public tabIndex: number | string;\n\n /**\n * Emitted when the calendar has started opening, cancelable.\n *\n * @example\n * ```html\n * <igx-date-picker (opening)=\"handleOpening($event)\"></igx-date-picker>\n * ```\n */\n @Output()\n public opening = new EventEmitter<IBaseCancelableBrowserEventArgs>();\n\n /**\n * Emitted after the calendar has opened.\n *\n * @example\n * ```html\n * <igx-date-picker (opened)=\"handleOpened($event)\"></igx-date-picker>\n * ```\n */\n @Output()\n public opened = new EventEmitter<IBaseEventArgs>();\n\n /**\n * Emitted when the calendar has started closing, cancelable.\n *\n * @example\n * ```html\n * <igx-date-picker (closing)=\"handleClosing($event)\"></igx-date-picker>\n * ```\n */\n @Output()\n public closing = new EventEmitter<IBaseCancelableBrowserEventArgs>();\n\n /**\n * Emitted after the calendar has closed.\n *\n * @example\n * ```html\n * <igx-date-picker (closed)=\"handleClosed($event)\"></igx-date-picker>\n * ```\n */\n @Output()\n public closed = new EventEmitter<IBaseEventArgs>();\n\n /** @hidden @internal */\n @ContentChildren(IgxPickerToggleComponent, { descendants: true })\n public toggleComponents: QueryList<IgxPickerToggleComponent>;\n\n /** @hidden @internal */\n @ContentChildren(IgxPickerClearComponent, { descendants: true })\n public clearComponents: QueryList<IgxPickerClearComponent>;\n\n @ContentChildren(IgxPrefixDirective, { descendants: true })\n protected prefixes: QueryList<IgxPrefixDirective>;\n\n @ContentChildren(IgxSuffixDirective, { descendants: true })\n protected suffixes: QueryList<IgxSuffixDirective>;\n\n @ViewChild(IgxInputGroupComponent)\n protected inputGroup: IgxInputGroupComponent;\n\n protected _locale: string;\n protected _collapsed = true;\n protected _type: IgxInputGroupType;\n protected _minValue: Date | string;\n protected _maxValue: Date | string;\n protected _weekStart: WEEKDAYS | number;\n protected abstract get toggleContainer(): HTMLElement | undefined;\n\n /**\n * Gets the picker's pop-up state.\n *\n * @example\n * ```typescript\n * const state = this.picker.collapsed;\n * ```\n */\n public get collapsed(): boolean {\n return this._collapsed;\n }\n\n /** @hidden @internal */\n public get isDropdown(): boolean {\n return this.mode === PickerInteractionMode.DropDown;\n }\n\n /**\n * Returns if there's focus within the picker's element OR popup container\n * @hidden @internal\n */\n public get isFocused(): boolean {\n const document = this.element.nativeElement?.getRootNode() as Document | ShadowRoot;\n if (!document?.activeElement) return false;\n\n return this.element.nativeElement.contains(document.activeElement)\n || !this.collapsed && this.toggleContainer.contains(document.activeElement);\n }\n\n protected _destroy$ = new Subject<void>();\n\n // D.P. EventEmitter<string | Date | DateRange | null> throws on strict checks for more restrictive overrides\n // w/ TS2416 Type 'string | Date ...' not assignable to type 'DateRange' due to observer method check\n public abstract valueChange: EventEmitter<any>;\n\n constructor() {\n this.locale = this.locale || this._localeId;\n }\n\n /** @hidden @internal */\n public ngAfterViewInit(): void {\n this.subToIconsClicked(this.toggleComponents, () => this.toggle());\n this.subToIconsClicked(this.clearComponents, () => this.clear());\n }\n\n /** @hidden @internal */\n public ngAfterContentChecked(): void {\n if (this.inputGroup && this.prefixes?.length > 0) {\n this.inputGroup.prefixes = this.prefixes;\n }\n\n if (this.inputGroup && this.suffixes?.length > 0) {\n this.inputGroup.suffixes = this.suffixes;\n }\n }\n\n /** @hidden @internal */\n public ngOnDestroy(): void {\n this._destroy$.next();\n this._destroy$.complete();\n }\n\n /** Subscribes to the click events of toggle/clear icons in a query */\n private subToIconsClicked(\n components: QueryList<IgxPickerToggleComponent | IgxPickerClearComponent>,\n handler: () => void\n ): void {\n const subscribeToClick = componentList => {\n componentList.forEach(component => {\n component.clicked\n .pipe(takeUntil(merge(componentList.changes, this._destroy$)))\n .subscribe(handler);\n });\n };\n\n subscribeToClick(components);\n\n components.changes.pipe(takeUntil(this._destroy$))\n .subscribe(() => subscribeToClick(components));\n }\n\n public abstract select(value: Date | DateRange | string): void;\n public abstract open(settings?: OverlaySettings): void;\n public abstract toggle(settings?: OverlaySettings): void;\n public abstract close(): void;\n public abstract clear(): void;\n public abstract getEditElement(): HTMLInputElement;\n}\n","import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy } from '@angular/core';\nimport { IgxChipComponent } from 'igniteui-angular/chips';\nimport { CalendarDay, CustomDateRange, DateRange, DateRangePickerResourceStringsEN, IDateRangePickerResourceStrings } from 'igniteui-angular/core';\n\n\ntype PredefinedRangeKey = 'last7Days' | 'currentMonth' | 'last30Days' | 'yearToDate';\n\n@Component({\n selector: 'igx-predefined-ranges-area',\n standalone: true,\n imports: [IgxChipComponent],\n templateUrl: './predefined-ranges-area-component.html',\n styles: [`\n :host { display:block; }\n .igx-predefined-ranges {\n display:flex; flex-wrap:wrap; gap:.5rem; padding:.5rem .75rem;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class IgxPredefinedRangesAreaComponent {\n @Input() public usePredefinedRanges = false;\n @Input() public customRanges: CustomDateRange[] = [];\n @Input() public resourceStrings: IDateRangePickerResourceStrings = DateRangePickerResourceStringsEN as any;\n\n @Output() public rangeSelect = new EventEmitter<DateRange>();\n\n public get ranges(): CustomDateRange[] {\n const base = this.usePredefinedRanges ? this.getPredefinedRanges() : [];\n return [...base, ...(this.customRanges ?? [])];\n }\n\n public trackByLabel = (i: number, r: CustomDateRange) => r.label;\n\n public onSelect(range: DateRange) {\n this.rangeSelect.emit(range);\n }\n\n private getLabel(rs: any, shortKey: string, prefixedKey: string, fallback: string): string {\n return rs?.[shortKey] ?? rs?.[prefixedKey] ?? fallback;\n }\n\n private getPredefinedRanges(): CustomDateRange[] {\n const today = CalendarDay.today;\n const rs: any = this.resourceStrings ?? {};\n\n const labels = {\n last7Days: this.getLabel(rs, 'last7Days', 'igx_date_range_picker_last7Days', 'Last 7 Days'),\n currentMonth: this.getLabel(rs, 'currentMonth', 'igx_date_range_picker_currentMonth', 'Current Month'),\n last30Days: this.getLabel(rs, 'last30Days', 'igx_date_range_picker_last30Days', 'Last 30 Days'),\n yearToDate: this.getLabel(rs, 'yearToDate', 'igx_date_range_picker_yearToDate', 'Year to Date')\n };\n\n const startOfMonth = new Date(today.native.getFullYear(), today.native.getMonth(), 1);\n const endOfMonth = new Date(today.native.getFullYear(), today.native.getMonth() + 1, 0);\n const startOfYear = new Date(today.native.getFullYear(), 0, 1);\n\n const predefinedRanges: { key: PredefinedRangeKey; get: () => { start: Date; end: Date } }[] = [\n { key: 'last7Days', get: () => ({ start: today.add('day', -7).native, end: today.native }) },\n { key: 'currentMonth', get: () => ({ start: startOfMonth, end: endOfMonth }) },\n { key: 'last30Days', get: () => ({ start: today.add('day', -29).native, end: today.native }) },\n { key: 'yearToDate', get: () => ({ start: startOfYear, end: today.native }) },\n ];\n\n return predefinedRanges.map(range => ({\n label: labels[range.key],\n dateRange: range.get()\n }));\n }\n}\n","<div class=\"igx-predefined-ranges\" role=\"group\" aria-label=\"Predefined ranges\">\n @for (r of ranges; track r.label) {\n <igx-chip (click)=\"onSelect(r.dateRange)\">\n {{ r.label }}\n </igx-chip>\n }\n</div>\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n Component,\n ViewChild,\n Output, EventEmitter,\n HostListener,\n HostBinding\n} from '@angular/core';\nimport { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives';\nimport { IgxCalendarComponent } from 'igniteui-angular/calendar';\nimport { IgxDividerDirective } from 'igniteui-angular/directives';\nimport { IBaseEventArgs, DateRange, CustomDateRange, PickerInteractionMode, IDateRangePickerResourceStrings, IgxPickerActionsDirective } from 'igniteui-angular/core';\nimport { IgxPredefinedRangesAreaComponent } from '../../date-range-picker/predefined-ranges/predefined-ranges-area.component';\n\n/** @hidden */\n@Component({\n selector: 'igx-calendar-container',\n styles: [':host {display: block;}'],\n templateUrl: 'calendar-container.component.html',\n imports: [\n IgxButtonDirective,\n IgxRippleDirective,\n IgxCalendarComponent,\n NgTemplateOutlet,\n IgxDividerDirective,\n IgxPredefinedRangesAreaComponent\n ]\n})\nexport class IgxCalendarContainerComponent {\n @ViewChild(IgxCalendarComponent, { static: true })\n public calendar: IgxCalendarComponent;\n\n @Output()\n public calendarClose = new EventEmitter<IBaseEventArgs>();\n\n @Output()\n public calendarCancel = new EventEmitter<IBaseEventArgs>();\n\n @Output()\n public todaySelection = new EventEmitter<IBaseEventArgs>();\n\n @Output()\n public rangeSelected = new EventEmitter<DateRange>();\n\n\n @HostBinding('class.igx-date-picker')\n public styleClass = 'igx-date-picker';\n\n @HostBinding('class.igx-date-picker--dropdown')\n public get dropdownCSS(): boolean {\n return this.mode === PickerInteractionMode.DropDown;\n }\n\n public usePredefinedRanges = false;\n public customRanges: CustomDateRange[] = [];\n public resourceStrings!: IDateRangePickerResourceStrings;\n public vertical = false;\n public closeButtonLabel: string;\n public cancelButtonLabel: string;\n public todayButtonLabel: string;\n public mode: PickerInteractionMode = PickerInteractionMode.DropDown;\n public pickerActions: IgxPickerActionsDirective;\n\n @HostListener('keydown.alt.arrowup', ['$event'])\n public onEscape(event) {\n event.preventDefault();\n this.calendarClose.emit();\n }\n\n public get isReadonly() {\n return this.mode === PickerInteractionMode.Dialog;\n }\n}\n\n/** @hidden */\n\n","<ng-template #defaultPickerActions>\n @if (closeButtonLabel || cancelButtonLabel || todayButtonLabel) {\n <div class=\"igx-date-picker__buttons\">\n @if (cancelButtonLabel) {\n <button\n #cancelButton type=\"button\"\n igxButton=\"flat\" igxRipple\n (click)=\"calendarCancel.emit({ owner: this})\"\n >\n {{ cancelButtonLabel }}\n </button>\n }\n @if (closeButtonLabel) {\n <button\n #closeButton\n type=\"button\"\n igxButton=\"flat\"\n igxRipple\n (click)=\"calendarClose.emit({ owner: this})\"\n >\n {{ closeButtonLabel }}\n </button>\n }\n @if (todayButtonLabel) {\n <button\n #todayButton\n type=\"button\"\n igxButton=\"flat\"\n igxRipple\n (click)=\"todaySelection.emit({ owner: this })\"\n >\n {{ todayButtonLabel }}\n </button>\n }\n </div>\n }\n</ng-template>\n\n<igx-calendar></igx-calendar>\n @if( usePredefinedRanges || (customRanges?.length || 0) > 0 ){\n <igx-predefined-ranges-area\n [usePredefinedRanges]=\"usePredefinedRanges\"\n [customRanges]=\"customRanges\"\n [resourceStrings]=\"resourceStrings\"\n (rangeSelect)=\"rangeSelected.emit($event)\">\n </igx-predefined-ranges-area>\n }\n@if (pickerActions?.template || (closeButtonLabel || todayButtonLabel)) {\n <igx-divider></igx-divider>\n}\n@if (pickerActions?.template || (closeButtonLabel || cancelButtonLabel || todayButtonLabel)) {\n <div class=\"igx-date-picker__actions\">\n <ng-container\n *ngTemplateOutlet=\"\n pickerActions?.template || defaultPickerActions;\n context: { $implicit: calendar }\n \"\n >\n </ng-container>\n </div>\n}\n","import {\n AfterViewChecked,\n AfterViewInit,\n AfterContentChecked,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ElementRef,\n EventEmitter,\n HostBinding,\n HostListener,\n Injector,\n Input,\n OnDestroy,\n OnInit,\n Output,\n PipeTransform,\n Renderer2,\n ViewChild,\n ViewContainerRef,\n booleanAttribute,\n inject\n} from '@angular/core';\nimport {\n AbstractControl,\n ControlValueAccessor,\n NgControl,\n NG_VALIDATORS,\n NG_VALUE_ACCESSOR,\n ValidationErrors,\n Validator\n} from '@angular/forms';\nimport {\n IgxCalendarComponent, IgxCalendarHeaderTemplateDirective, IgxCalendarHeaderTitleTemplateDirective, IgxCalendarSubheaderTemplateDirective,\n IFormattingViews, IFormattingOptions\n} from 'igniteui-angular/calendar';\nimport {\n IgxLabelDirective, IgxInputState, IgxInputGroupComponent, IgxPrefixDirective, IgxInputDirective, IgxSuffixDirective,\n IgxReadOnlyInputDirective\n} from 'igniteui-angular/input-group';\nimport { fromEvent, Subscription, noop, MonoTypeOperatorFunction } from 'rxjs';\nimport { filter, takeUntil } from 'rxjs/operators';\n\nimport { IgxDateTimeEditorDirective, IgxTextSelectionDirective } from 'igniteui-angular/directives';\nimport {\n AbsoluteScrollStrategy,\n AutoPositionStrategy,\n IgxOverlayService,\n OverlayCancelableEventArgs,\n OverlayEventArgs,\n OverlaySettings,\n IgxPickerActionsDirective,\n DatePickerResourceStringsEN,\n IDatePickerResourceStrings,\n DateRangeDescriptor,\n DateRangeType,\n IBaseCancelableBrowserEventArgs,\n isDate,\n PlatformUtil,\n getCurrentResourceStrings,\n PickerCalendarOrientation,\n DateTimeUtil,\n DatePartDeltas,\n DatePart,\n isDateInRanges,\n IgxOverlayOutletDirective\n} from 'igniteui-angular/core';\nimport { IDatePickerValidationFailedEventArgs } from './date-picker.common';\nimport { IgxIconComponent } from 'igniteui-angular/icon';\nimport { fadeIn, fadeOut } from 'igniteui-angular/animations';\nimport { PickerBaseDirective } from './picker-base.directive';\nimport { IgxCalendarContainerComponent } from './calendar-container/calendar-container.component';\n\nlet NEXT_ID = 0;\n\n/**\n * Date Picker displays a popup calendar that lets users select a single date.\n *\n * @igxModule IgxDatePickerModule\n * @igxTheme igx-calendar-theme, igx-icon-theme\n * @igxGroup Scheduling\n * @igxKeywords datepicker, calendar, schedule, date\n * @example\n * ```html\n * <igx-date-picker [(ngModel)]=\"selectedDate\"></igx-date-picker>\n * ```\n */\n@Component({\n providers: [\n { provide: NG_VALUE_ACCESSOR, useExisting: IgxDatePickerComponent, multi: true },\n { provide: NG_VALIDATORS, useExisting: IgxDatePickerComponent, multi: true }\n ],\n selector: 'igx-date-picker',\n templateUrl: 'date-picker.component.html',\n styles: [':host { display: block; }'],\n imports: [\n IgxInputGroupComponent,\n IgxPrefixDirective,\n IgxIconComponent,\n IgxInputDirective,\n IgxReadOnlyInputDirective,\n IgxDateTimeEditorDirective,\n IgxTextSelectionDirective,\n IgxSuffixDirective\n ]\n})\nexport class IgxDatePickerComponent extends PickerBaseDirective implements ControlValueAccessor, Validator,\n OnInit, AfterViewInit, OnDestroy, AfterViewChecked, AfterContentChecked {\n private _overlayService = inject<IgxOverlayService>(IgxOverlayService);\n private _injector = inject(Injector);\n private _renderer = inject(Renderer2);\n private platform = inject(PlatformUtil);\n private cdr = inject(ChangeDetectorRef);\n\n\n /**\n * Gets/Sets whether the inactive dates will be hidden.\n *\n * @remarks\n * Applies to dates that are out of the current month.\n * Default value is `false`.\n * @example\n * ```html\n * <igx-date-picker [hideOutsideDays]=\"true\"></igx-date-picker>\n * ```\n * @example\n * ```typescript\n * let hideOutsideDays = this.datePicker.hideOutsideDays;\n * ```\n */\n @Input({ transform: booleanAttribute })\n public hideOutsideDays: boolean;\n\n /**\n * Gets/Sets the number of month views displayed.\n *\n * @remarks\n * Default value is `1`.\n *\n * @example\n * ```html\n * <igx-date-picker [displayMonthsCount]=\"2\"></igx-date-picker>\n * ```\n * @example\n * ```typescript\n * let monthViewsDisplayed = this.datePicker.displayMonthsCount;\n * ```\n */\n @Input()\n public displayMonthsCount = 1;\n\n /**\n * Gets/Sets the orientation of the multiple months displayed in the picker's calendar's days view.\n *\n * @example\n * <igx-date-picker orientation=\"vertical\"></igx-date-picker>\n */\n @Input()\n public orientation: PickerCalendarOrientation = PickerCalendarOrientation.Horizontal;\n\n /**\n * Show/hide week numbers\n *\n * @example\n * ```html\n * <igx-date-picker [showWeekNumbers]=\"true\"></igx-date-picker>\n * ``\n */\n @Input({ transform: booleanAttribute })\n public showWeekNumbers: boolean;\n\n\n /**\n * Gets/Sets the date which is shown in the calendar picker and is highlighted.\n * By default it is the current date, or the value of the picker, if set.\n */\n @Input()\n public get activeDate(): Date {\n const today = new Date(new Date().setHours(0, 0, 0, 0));\n const dateValue = DateTimeUtil.isValidDate(this._dateValue) ? new Date(this._dateValue.setHours(0, 0, 0, 0)) : null;\n return this._activeDate ?? dateValue ?? this._calendar?.activeDate ?? today;\n }\n\n public set activeDate(value: Date) {\n this._activeDate = value;\n }\n\n /**\n * Gets/Sets a custom formatter function on the selected or passed date.\n *\n * @example\n * ```html\n * <igx-date-picker [value]=\"date\" [formatter]=\"formatter\"></igx-date-picker>\n * ```\n */\n @Input()\n public formatter: (val: Date) => string;\n\n /**\n * Gets/Sets the today button's label.\n *\n * @example\n * ```html\n * <igx-date-picker todayButtonLabel=\"Today\"></igx-date-picker>\n * ```\n */\n @Input()\n public todayButtonLabel: string;\n\n /**\n * Gets/Sets the cancel button's label.\n *\n * @example\n * ```html\n * <igx-date-picker cancelButtonLabel=\"Cancel\"></igx-date-picker>\n * ```\n */\n @Input()\n public cancelButtonLabel: string;\n\n /**\n * Specify if the currently spun date segment should loop over.\n *\n * @example\n * ```html\n * <igx-date-picker [spinLoop]=\"false\"></igx-date-picker>\n * ```\n */\n @Input({ transform: booleanAttribute })\n public spinLoop = true;\n\n /**\n * Delta values used to increment or decrement each editor date part on spin actions.\n * All values default to `1`.\n *\n * @example\n * ```html\n * <igx-date-picker [spinDelta]=\"{ date: 5, month: 2 }\"></igx-date-picker>\n * ```\n */\n @Input()\n public spinDelta: Pick<DatePartDeltas, 'date' | 'month' | 'year'>;\n\n /**\n * Gets/Sets the container used for the popup element.\n *\n * @remarks\n * `outlet` is an instance of `IgxOverlayOutletDirective` or an `ElementRef`.\n * @example\n * ```html\n * <div igxOverlayOutlet #outlet=\"overlay-outlet\"></div>\n * //..\n * <igx-date-picker [outlet]=\"outlet\"></igx-date-picker>\n * //..\n * ```\n */\n @Input()\n public override outlet: IgxOverlayOutletDirective | ElementRef;\n\n /**\n * Gets/Sets the value of `id` attribute.\n *\n * @remarks If not provided it will be automatically generated.\n * @example\n * ```html\n * <igx-date-picker [id]=\"'igx-date-picker-3'\" cancelButtonLabel=\"cancel\" todayButtonLabel=\"today\"></igx-date-picker>\n * ```\n */\n @Input()\n @HostBinding('attr.id')\n public id = `igx-date-picker-${NEXT_ID++}`;\n\n //#region calendar members\n\n /**\n * Gets/Sets the format views of the `IgxDatePickerComponent`.\n *\n * @example\n * ```typescript\n * let formatViews = this.datePicker.formatViews;\n * this.datePicker.formatViews = {day:false, month: false, year:false};\n * ```\n */\n @Input()\n public formatViews: IFormattingViews;\n\n /**\n * Gets/Sets the disabled dates descriptors.\n *\n * @example\n * ```typescript\n * let disabledDates = this.datepicker.disabledDates;\n * this.datePicker.disabledDates = [ {type: DateRangeType.Weekends}, ...];\n * ```\n */\n @Input()\n public get disabledDates(): DateRangeDescriptor[] {\n return this._disabledDates;\n }\n public set disabledDates(value: DateRangeDescriptor[]) {\n this._disabledDates = value;\n this._onValidatorChange();\n }\n\n /**\n * Gets/Sets the special dates descriptors.\n *\n * @example\n * ```typescript\n * let specialDates = this.datepicker.specialDates;\n * this.datePicker.specialDates = [ {type: DateRangeType.Weekends}, ... ];\n * ```\n */\n @Input()\n public get specialDates(): DateRangeDescriptor[] {\n return this._specialDates;\n }\n public set specialDates(value: DateRangeDescriptor[]) {\n this._specialDates = value;\n }\n\n\n /**\n * Gets/Sets the format options of the `IgxDatePickerComponent`.\n *\n * @example\n * ```typescript\n * this.datePicker.calendarFormat = {day: \"numeric\", month: \"long\", weekday: \"long\", year: \"numeric\"};\n * ```\n */\n @Input()\n public calendarFormat: IFormattingOptions;\n\n //#endregion\n\n /**\n * Gets/Sets the selected date.\n *\n * @example\n * ```html\n * <igx-date-picker [value]=\"date\"></igx-date-picker>\n * ```\n */\n @Input()\n public get value(): Date | string {\n return this._value;\n }\n public set value(date: Date | string) {\n this._value = date;\n this.setDateValue(date);\n if (this.dateTimeEditor.value !== date) {\n this.dateTimeEditor.value = this._dateValue;\n }\n this.valueChange.emit(this.dateValue);\n this._onChangeCallback(this.dateValue);\n }\n\n /**\n * The minimum value the picker will accept.\n *\n * @example\n * <igx-date-picker [minValue]=\"minDate\"></igx-date-picker>\n */\n @Input()\n public set minValue(value: Date | string) {\n this._minValue = value;\n this._onValidatorChange();\n }\n\n public get minValue(): Date | string {\n return this._minValue;\n }\n\n /**\n * The maximum value the picker will accept.\n *\n * @example\n * <igx-date-picker [maxValue]=\"maxDate\"></igx-date-picker>\n */\n @Input()\n public set maxValue(value: Date | string) {\n this._maxValue = value;\n this._onValidatorChange();\n }\n\n public get maxValue(): Date | string {\n return this._maxValue;\n }\n\n /**\n * Gets/Sets the resource strings for the picker's default toggle icon.\n * By default it uses EN resources.\n */\n @Input()\n public resourceStrings: IDatePickerResourceStrings;\n\n /** @hidden @internal */\n @Input({ transform: booleanAttribute })\n public readOnly = false;\n\n /**\n * Emitted when the picker's value changes.\n *\n * @remarks\n * Used for `two-way` bindings.\n *\n * @example\n * ```html\n * <igx-date-picker [(value)]=\"date\"></igx-date-picker>\n * ```\n */\n @Output()\n public valueChange = new EventEmitter<Date>();\n\n /**\n * Emitted when the user types/spins invalid date in the date-picker editor.\n *\n * @example\n * ```html\n * <igx-date-picker (validationFailed)=\"onValidationFailed($event)\"></igx-date-picker>\n * ```\n */\n @Output()\n public validationFailed = new EventEmitter<IDatePickerValidationFailedEventArgs>();\n\n /** @hidden @internal */\n @ContentChild(IgxLabelDirective)\n public label: IgxLabelDirective;\n\n @ContentChild(IgxCalendarHeaderTitleTemplateDirective)\n private headerTitleTemplate: IgxCalendarHeaderTitleTemplateDirective;\n\n @ContentChild(IgxCalendarHeaderTemplateDirective)\n private headerTemplate: IgxCalendarHeaderTemplateDirective;\n\n @ViewChild(IgxDateTimeEditorDirective, { static: true })\n private dateTimeEditor: IgxDateTimeEditorDirective;\n\n @ViewChild(IgxInputGroupComponent, { read: ViewContainerRef })\n private viewContainerRef: ViewContainerRef;\n\n @ViewChild(IgxLabelDirective)\n private labelDirective: IgxLabelDirective;\n\n @ViewChild(IgxInputDirective)\n private inputDirective: IgxInputDirective;\n\n @ContentChild(IgxCalendarSubheaderTemplateDirective)\n private subheaderTemplate: IgxCalendarSubheaderTemplateDirective;\n\n @ContentChild(IgxPickerActionsDirective)\n private pickerActions: IgxPickerActionsDirective;\n\n private get dialogOverlaySettings(): OverlaySettings {\n return Object.assign({}, this._dialogOverlaySettings, this.overlaySettings);\n }\n\n private get dropDownOverlaySettings(): OverlaySettings {\n return Object.assign({}, this._dropDownOverlaySettings, this.overlaySettings);\n }\n\n private get inputGroupElement(): HTMLElement {\n return this.inputGroup?.element.nativeElement;\n }\n\n private get dateValue(): Date {\n return this._dateValue;\n }\n\n private get pickerFormatViews(): IFormattingViews {\n return Object.assign({}, this._defFormatViews, this.formatViews);\n }\n\n private get pickerCalendarFormat(): IFormattingOptions {\n return Object.assign({}, this._calendarFormat, this.calendarFormat);\n }\n\n /** @hidden @internal */\n public displayValue: PipeTransform = { transform: (date: Date) => this.formatter(date) };\n\n private _resourceStrings = getCurrentResourceStrings(DatePickerResourceStringsEN);\n private _dateValue: Date;\n private _overlayId: string;\n private _value: Date | string;\n private _ngControl: NgControl = null;\n private _statusChanges$: Subscription;\n private _calendar: IgxCalendarComponent;\n private _calendarContainer?: HTMLElement;\n private _specialDates: DateRangeDescriptor[] = null;\n private _disabledDates: DateRangeDescriptor[] = null;\n private _activeDate: Date = null;\n private _overlaySubFilter:\n [MonoTypeOperatorFunction<OverlayEventArgs>,\n MonoTypeOperatorFunction<OverlayEventArgs | OverlayCancelableEventArgs>] = [\n filter(x => x.id === this._overlayId),\n takeUntil(this._destroy$)\n ];\n private _dropDownOverlaySettings: OverlaySettings = {\n target: this.inputGroupElement,\n closeOnOutsideClick: true,\n modal: false,\n closeOnEscape: true,\n scrollStrategy: new AbsoluteScrollStrategy(),\n positionStrategy: new AutoPositionStrategy({\n openAnimation: fadeIn,\n closeAnimation: fadeOut\n })\n };\n private _dialogOverlaySettings: OverlaySettings = {\n closeOnOutsideClick: true,\n modal: true,\n closeOnEscape: true\n };\n private _calendarFormat: IFormattingOptions = {\n day: 'numeric',\n month: 'short',\n weekday: 'short',\n year: 'numeric'\n };\n private _defFormatViews: IFormattingViews = {\n day: false,\n month: true,\n year: false\n };\n private _onChangeCallback: (_: Date) => void = noop;\n private _onTouchedCallback: () => void = noop;\n private _onValidatorChange: () => void = noop;\n\n constructor() {\n super();\n this.locale = this.locale || this._localeId;\n }\n\n /** @hidden @internal */\n public get required(): boolean {\n if (this._ngControl && this._ngControl.control && this._ngControl.control.validator) {\n // Run the validation with empty object to check if required is enabled.\n const error = this._ngControl.control.validator({} as AbstractControl);\n return error && error.required;\n }\n\n return false;\n }\n\n /** @hidden @internal */\n public get pickerResourceStrings(): IDatePickerResourceStrings {\n return Object.assign({}, this._resourceStrings, this.resourceStrings);\n }\n\n protected override get toggleContainer(): HTMLElement | undefined {\n return this._calendarContainer;\n }\n\n /** @hidden @internal */\n @HostListener('keydown', ['$event'])\n public onKeyDown(event: KeyboardEvent) {\n switch (event.key) {\n case this.platform.KEYMAP.ARROW_UP:\n if (event.altKey) {\n this.close();\n }\n break;\n case this.platform.KEYMAP.ARROW_DOWN:\n if (event.altKey) {\n this.open();\n }\n break;\n case this.platform.KEYMAP.SPACE:\n event.preventDefault();\n this.open();\n break;\n }\n }\n\n /**\n * Opens the picker's dropdown or dialog.\n *\n * @example\n * ```html\n * <igx-date-picker #picker></igx-date-picker>\n *\n * <button type=\"button\" igxButton (click)=\"picker.open()\">Open Dialog</button>\n * ```\n */\n public open(settings?: OverlaySettings): void {\n if (!this.collapsed || this.disabled || this.readOnly) {\n return;\n }\n\n const overlaySettings = Object.assign({}, this.isDropdown\n ? this.dropDownOverlaySettings\n : this.dialogOverlaySettings\n , settings);\n\n if (this.isDropdown && this.inputGroupElement) {\n overlaySettings.target = this.inputGroupElement;\n }\n if (this.outlet) {\n overlaySettings.outlet = this.outlet;\n }\n this._overlayId = this._overlayService\n .attach(IgxCalendarContainerComponent, this.viewContainerRef, overlaySettings);\n this._overlayService.show(this._overlayId);\n }\n\n /**\n * Toggles the picker's dropdown or dialog\n *\n * @example\n * ```html\n * <igx-date-picker #picker></igx-date-picker>\n *\n * <button type=\"button\" igxButton (click)=\"picker.toggle()\">Toggle Dialog</button>\n * ```\n */\n public toggle(settings?: OverlaySettings): void {\n if (this.collapsed) {\n this.open(settings);\n } else {\n this.close();\n }\n }\n\n /**\n * Closes the picker's dropdown or dialog.\n *\n * @example\n * ```html\n * <igx-date-picker #picker></igx-date-picker>\n *\n * <button type=\"button\" igxButton (click)=\"picker.close()\">Close Dialog</button>\n * ```\n */\n public close(): void {\n if (!this.collapsed) {\n this._overlayService.hide(this._overlayId);\n }\n }\n\n /**\n * Selects a date.\n *\n * @remarks Updates the value in the input field.\n *\n * @example\n * ```typescript\n * this.datePicker.select(date);\n * ```\n * @param date passed date that has to be set to the calendar.\n */\n public select(value: Date): void {\n this.value = value;\n }\n\n /**\n * Selects today's date and closes the picker.\n *\n * @example\n * ```html\n * <igx-date-picker #picker></igx-date-picker>\n *\n * <button type=\"button\" igxButton (click)=\"picker.selectToday()\">Select Today</button>\n * ```\n * */\n public selectToday(): void {\n const today = new Date();\n today.setHours(0);\n today.setMinutes(0);\n today.setSeconds(0);\n today.setMilliseconds(0);\n this.select(today);\n this.close();\n }\n\n /**\n * Clears the input field and the picker's value.\n *\n * @example\n * ```typescript\n * this.datePicker.clear();\n * ```\n */\n public clear(): void {\n if (!this.disabled || !this.readOnly) {\n this._calendar?.deselectDate();\n this.dateTimeEditor.clear();\n }\n }\n\n /**\n * Increment a specified `DatePart`.\n *\n * @param datePart The optional DatePart to increment. Defaults to Date.\n * @param delta The optional delta to increment by. Overrides `spinDelta`.\n * @example\n * ```typescript\n * this.datePicker.increment(DatePart.Date);\n * ```\n */\n public increment(datePart?: DatePart, delta?: number): void {\n this.dateTimeEditor.increment(datePart, delta);\n }\n\n /**\n * Decrement a specified `DatePart`\n *\n * @param datePart The optional DatePart to decrement. Defaults to Date.\n * @param delta The optional delta to decrement by. Overrides `spinDelta`.\n * @example\n * ```typescript\n * this.datePicker.decrement(DatePart.Date);\n * ```\n */\n public decrement(datePart?: DatePart, delta?: number): void {\n this.dateTimeEditor.decrement(datePart, delta);\n }\n\n //#region Control Value Accessor\n /** @hidden @internal */\n public writeValue(value: Date | string) {\n this._value = value;\n this.setDateValue(value);\n if (this.dateTimeEditor.value !== value) {\n this.dateTimeEditor.value = this._dateValue;\n }\n }\n\n /** @hidden @internal */\n public registerOnChange(fn: any) {\n this._onChangeCallback = fn;\n }\n\n /** @hidden @internal */\n public registerOnTouched(fn: any) {\n this._onTouchedCallback = fn;\n }\n\n /** @hidden @internal */\n public setDisabledState?(isDisabled: boolean): void {\n this.disabled = isDisabled;\n }\n //#endregion\n\n //#region Validator\n /** @hidden @internal */\n public registerOnValidatorChange(fn: any) {\n this._onValidatorChange = fn;\n }\n\n /** @hidden @internal */\n public validate(control: AbstractControl): ValidationErrors | null {\n if (!control.value) {\n return null;\n }\n // InvalidDate handling\n if (isDate(control.value) && !DateTimeUtil.isValidDate(control.value)) {\n return { value: true };\n }\n\n const errors = {};\n const value = DateTimeUtil.isValidDate(control.value) ? control.value : DateTimeUtil.parseIsoDate(control.value);\n if (value && this.disabledDates && isDateInRanges(value, this.disabledDates)) {\n Object.assign(errors, { dateIsDisabled: true });\n }\n Object.assign(errors, DateTimeUtil.validateMinMax(value, this.minValue, this.maxValue, false));\n\n return Object.keys(errors).length > 0 ? errors : null;\n }\n //#endregion\n\n /** @hidden @internal */\n public ngOnInit(): void {\n this._ngControl = this._injector.get<NgControl>(NgControl, null);\n\n this.locale = this.locale || this._localeId;\n }\n\n /** @hidden @internal */\n public override ngAfterViewInit() {\n super.ngAfterViewInit();\n this.subscribeToClick();\n this.subscribeToOverlayEvents();\n this.subscribeToDateEditorEvents();\n\n this._dropDownOverlaySettings.excludeFromOutsideClick = [this.inputGroup.element.nativeElement];\n\n fromEvent(this.inputDirective.nativeElement, 'blur')\n .pipe(takeUntil(this._destroy$))\n .subscribe(() => {\n if (this.collapsed) {\n this._onTouchedCallback();\n this.updateValidity();\n }\n });\n\n if (this._ngControl) {\n this._statusChanges$ =\n this._ngControl.statusChanges.subscribe(this.onStatusChanged.bind(this));\n if (this._ngControl.control.validator) {\n this.inputGroup.isRequired = this.required;\n this.cdr.detectChanges();\n }\n }\n }\n\n /** @hidden @internal */\n public ngAfterViewChecked() {\n if (this.labelDirective) {\n this._renderer.setAttribute(this.inputDirective.nativeElement, 'aria-labelledby', this.labelDirective.id);\n }\n }\n\n /** @hidden @internal */\n public override ngOnDestroy(): void {\n super.ngOnDestroy();\n if (this._statusChanges$) {\n this._statusChanges$.unsubscribe();\n }\n if (this._overlayId) {\n this._overlayService.detach(this._overlayId);\n delete this._overlayId;\n }\n }\n\n /** @hidden @internal */\n public getEditElement(): HTMLInputElement {\n return this.inputDirective.nativeElement;\n }\n\n private subscribeToClick() {\n fromEvent(this.getEditElement(), 'click')\n .pipe(takeUntil(this._destroy$))\n .subscribe(() => {\n if (!this.isDropdown) {\n this.toggle();\n }\n });\n }\n\n private setDateValue(value: Date | string) {\n if (isDate(value) && isNaN(value.getTime())) {\n this._dateValue = value;\n return;\n }\n this._dateValue = DateTimeUtil.isValidDate(value) ? value : DateTimeUtil.parseIsoDate(value);\n if (this._calendar) {\n this._calendar.selectDate(this._dateValue);\n this._calendar.activeDate = this.activeDate;\n this._calendar.viewDate = this.activeDate;\n this.cdr.detectChanges();\n }\n }\n\n private updateValidity() {\n // B.P. 18 May 2021: IgxDatePicker does not reset its state upon resetForm #9526\n if (this._ngControl && !this.disabled && this.isTouchedOrDirty) {\n if (this.hasValidators && this.inputGroup.isFocused) {\n this.inputDirective.valid = this._ngControl.valid ? IgxInputState.VALID : IgxInputState.INVALID;\n } else {\n this.inputDirective.valid = this._ngControl.valid ? IgxInputState.INITIAL : IgxInputState.INVALID;\n }\n } else {\n this.inputDirective.valid = IgxInputState.INITIAL;\n }\n }\n\n private get isTouchedOrDirty(): boolean {\n return (this._ngControl.control.touched || this._ngControl.control.dirty);\n }\n\n private get hasValidators(): boolean {\n return (!!this._ngControl.control.validator || !!this._ngControl.control.asyncValidator);\n }\n\n private onStatusChanged = () => {\n this.disabled = this._ngControl.disabled;\n this.updateValidity();\n this.inputGroup.isRequired = this.required;\n };\n\n private handleSelection(date: Date): void {\n if (this.dateValue && DateTimeUtil.isValidDate(this.dateValue)) {\n date.setHours(this.dateValue.getHours());\n date.setMinutes(this.dateValue.getMinutes());\n date.setSeconds(this.dateValue.getSeconds());\n date.setMilliseconds(this.dateValue.getMilliseconds());\n }\n this.value = date;\n if (this._calendar) {\n this._calendar.activeDate = this.activeDate;\n this._calendar.viewDate = this.activeDate;\n }\n this.close();\n }\n\n private subscribeToDateEditorEvents(): void {\n this.dateTimeEditor.valueChange.pipe(\n takeUntil(this._destroy$)).subscribe(val => {\n this.value = val;\n });\n this.dateTimeEditor.validationFailed.pipe(\n takeUntil(this._destroy$)).subscribe((event) => {\n this.validationFailed.emit({\n owner: this,\n prevValue: event.oldValue,\n currentValue: this.value\n });\n });\n }\n\n private subscribeToOverlayEvents() {\n this._overlayService.opening.pipe(...this._overlaySubFilter).subscribe((e: OverlayCancelableEventArgs) => {\n const args: IBaseCancelableBrowserEventArgs = { owner: this, event: e.event, cancel: e.cancel };\n this.opening.emit(args);\n e.cancel = args.cancel;\n if (args.cancel) {\n this._overlayService.detach(this._overlayId);\n return;\n }\n\n this._initializeCalendarContainer(e.componentRef.instance);\n this._calendarContainer = e.componentRef.location.nativeElement;\n this._collapsed = false;\n });\n\n this._overlayService.opened.pipe(...this._overlaySubFilter).subscribe(() => {\n this.opened.emit({ owner: this });\n\n this._calendar.wrapper?.nativeElement?.focus();\n });\n\n