@ng-bootstrap/ng-bootstrap
Version:
Angular powered Bootstrap
643 lines (635 loc) • 72.3 kB
JavaScript
import { fromEvent, merge } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, DestroyRef, Directive, ElementRef, EventEmitter, forwardRef, inject, Injector, Input, NgZone, Output, TemplateRef, ViewChild, ViewEncapsulation, } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgTemplateOutlet } from '@angular/common';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgbCalendar } from './ngb-calendar';
import { NgbDate } from './ngb-date';
import { NgbDatepickerService } from './datepicker-service';
import { NavigationEvent } from './datepicker-view-model';
import { NgbDatepickerConfig } from './datepicker-config';
import { NgbDateAdapter } from './adapters/ngb-date-adapter';
import { NgbDatepickerI18n } from './datepicker-i18n';
import { NgbDatepickerKeyboardService } from './datepicker-keyboard-service';
import { isChangedDate, isChangedMonth } from './datepicker-tools';
import { NgbDatepickerDayView } from './datepicker-day-view';
import { NgbDatepickerNavigation } from './datepicker-navigation';
import * as i0 from "@angular/core";
/**
* A directive that marks the content template that customizes the way datepicker months are displayed
*
* @since 5.3.0
*/
export class NgbDatepickerContent {
constructor() {
this.templateRef = inject(TemplateRef);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepickerContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0", type: NgbDatepickerContent, isStandalone: true, selector: "ng-template[ngbDatepickerContent]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepickerContent, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[ngbDatepickerContent]', standalone: true }]
}] });
/**
* A component that renders one month including all the days, weekdays and week numbers. Can be used inside
* the `<ng-template ngbDatepickerMonths></ng-template>` when you want to customize months layout.
*
* For a usage example, see [custom month layout demo](#/components/datepicker/examples#custommonth)
*
* @since 5.3.0
*/
export class NgbDatepickerMonth {
constructor() {
this._keyboardService = inject(NgbDatepickerKeyboardService);
this._service = inject(NgbDatepickerService);
this.i18n = inject(NgbDatepickerI18n);
this.datepicker = inject(NgbDatepicker);
}
/**
* The first date of month to be rendered.
*
* This month must one of the months present in the
* [datepicker state](#/components/datepicker/api#NgbDatepickerState).
*/
set month(month) {
this.viewModel = this._service.getMonth(month);
}
onKeyDown(event) {
this._keyboardService.processKey(event, this.datepicker);
}
doSelect(day) {
if (!day.context.disabled && !day.hidden) {
this.datepicker.onDateSelect(day.date);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepickerMonth, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: NgbDatepickerMonth, isStandalone: true, selector: "ngb-datepicker-month", inputs: { month: "month" }, host: { attributes: { "role": "grid" }, listeners: { "keydown": "onKeyDown($event)" } }, ngImport: i0, template: `
@if (viewModel.weekdays.length > 0) {
<div class="ngb-dp-week ngb-dp-weekdays" role="row">
@if (datepicker.showWeekNumbers) {
<div class="ngb-dp-weekday ngb-dp-showweek small">{{ i18n.getWeekLabel() }}</div>
}
@for (weekday of viewModel.weekdays; track weekday) {
<div class="ngb-dp-weekday small" role="columnheader">{{ weekday }}</div>
}
</div>
}
@for (week of viewModel.weeks; track week) {
@if (!week.collapsed) {
<div class="ngb-dp-week" role="row">
@if (datepicker.showWeekNumbers) {
<div class="ngb-dp-week-number small text-muted">{{ i18n.getWeekNumerals(week.number) }}</div>
}
@for (day of week.days; track day) {
<div
(click)="doSelect(day); $event.preventDefault()"
class="ngb-dp-day"
role="gridcell"
[class.disabled]="day.context.disabled"
[tabindex]="day.tabindex"
[class.hidden]="day.hidden"
[class.ngb-dp-today]="day.context.today"
[attr.aria-label]="day.ariaLabel"
>
@if (!day.hidden) {
<ng-template [ngTemplateOutlet]="datepicker.dayTemplate" [ngTemplateOutletContext]="day.context" />
}
</div>
}
</div>
}
}
`, isInline: true, styles: ["ngb-datepicker-month{display:block}.ngb-dp-weekday,.ngb-dp-week-number{line-height:2rem;text-align:center;font-style:italic}.ngb-dp-weekday{color:var(--bs-info)}.ngb-dp-week{border-radius:.25rem;display:flex}.ngb-dp-weekdays{border-bottom:1px solid var(--bs-border-color);border-radius:0;background-color:var(--bs-tertiary-bg)}.ngb-dp-day,.ngb-dp-weekday,.ngb-dp-week-number{width:2rem;height:2rem}.ngb-dp-day{cursor:pointer}.ngb-dp-day.disabled,.ngb-dp-day.hidden{cursor:default;pointer-events:none}.ngb-dp-day[tabindex=\"0\"]{z-index:1}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepickerMonth, decorators: [{
type: Component,
args: [{ selector: 'ngb-datepicker-month', standalone: true, imports: [NgTemplateOutlet], host: {
role: 'grid',
'(keydown)': 'onKeyDown($event)',
}, encapsulation: ViewEncapsulation.None, template: `
@if (viewModel.weekdays.length > 0) {
<div class="ngb-dp-week ngb-dp-weekdays" role="row">
@if (datepicker.showWeekNumbers) {
<div class="ngb-dp-weekday ngb-dp-showweek small">{{ i18n.getWeekLabel() }}</div>
}
@for (weekday of viewModel.weekdays; track weekday) {
<div class="ngb-dp-weekday small" role="columnheader">{{ weekday }}</div>
}
</div>
}
@for (week of viewModel.weeks; track week) {
@if (!week.collapsed) {
<div class="ngb-dp-week" role="row">
@if (datepicker.showWeekNumbers) {
<div class="ngb-dp-week-number small text-muted">{{ i18n.getWeekNumerals(week.number) }}</div>
}
@for (day of week.days; track day) {
<div
(click)="doSelect(day); $event.preventDefault()"
class="ngb-dp-day"
role="gridcell"
[class.disabled]="day.context.disabled"
[tabindex]="day.tabindex"
[class.hidden]="day.hidden"
[class.ngb-dp-today]="day.context.today"
[attr.aria-label]="day.ariaLabel"
>
@if (!day.hidden) {
<ng-template [ngTemplateOutlet]="datepicker.dayTemplate" [ngTemplateOutletContext]="day.context" />
}
</div>
}
</div>
}
}
`, styles: ["ngb-datepicker-month{display:block}.ngb-dp-weekday,.ngb-dp-week-number{line-height:2rem;text-align:center;font-style:italic}.ngb-dp-weekday{color:var(--bs-info)}.ngb-dp-week{border-radius:.25rem;display:flex}.ngb-dp-weekdays{border-bottom:1px solid var(--bs-border-color);border-radius:0;background-color:var(--bs-tertiary-bg)}.ngb-dp-day,.ngb-dp-weekday,.ngb-dp-week-number{width:2rem;height:2rem}.ngb-dp-day{cursor:pointer}.ngb-dp-day.disabled,.ngb-dp-day.hidden{cursor:default;pointer-events:none}.ngb-dp-day[tabindex=\"0\"]{z-index:1}\n"] }]
}], propDecorators: { month: [{
type: Input
}] } });
/**
* A highly configurable component that helps you with selecting calendar dates.
*
* `NgbDatepicker` is meant to be displayed inline on a page or put inside a popup.
*/
export class NgbDatepicker {
constructor() {
this.injector = inject(Injector);
this._service = inject(NgbDatepickerService);
this._calendar = inject(NgbCalendar);
this._i18n = inject(NgbDatepickerI18n);
this._config = inject(NgbDatepickerConfig);
this._nativeElement = inject(ElementRef).nativeElement;
this._ngbDateAdapter = inject((NgbDateAdapter));
this._ngZone = inject(NgZone);
this._destroyRef = inject(DestroyRef);
this._controlValue = null;
this._publicState = {};
/**
* The reference to a custom template for the day.
*
* Allows to completely override the way a day 'cell' in the calendar is displayed.
*
* See [`DayTemplateContext`](#/components/datepicker/api#DayTemplateContext) for the data you get inside.
*/
this.dayTemplate = this._config.dayTemplate;
/**
* The callback to pass any arbitrary data to the template cell via the
* [`DayTemplateContext`](#/components/datepicker/api#DayTemplateContext)'s `data` parameter.
*
* `current` is the month that is currently displayed by the datepicker.
*
* @since 3.3.0
*/
this.dayTemplateData = this._config.dayTemplateData;
/**
* The number of months to display.
*/
this.displayMonths = this._config.displayMonths;
/**
* The first day of the week.
*
* With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun.
*/
this.firstDayOfWeek = this._config.firstDayOfWeek;
/**
* The reference to the custom template for the datepicker footer.
*
* @since 3.3.0
*/
this.footerTemplate = this._config.footerTemplate;
/**
* The callback to mark some dates as disabled.
*
* It is called for each new date when navigating to a different month.
*
* `current` is the month that is currently displayed by the datepicker.
*/
this.markDisabled = this._config.markDisabled;
/**
* The latest date that can be displayed or selected.
*
* If not provided, 'year' select box will display 10 years after the current month.
*/
this.maxDate = this._config.maxDate;
/**
* The earliest date that can be displayed or selected.
*
* If not provided, 'year' select box will display 10 years before the current month.
*/
this.minDate = this._config.minDate;
/**
* Navigation type.
*
* * `"select"` - select boxes for month and navigation arrows
* * `"arrows"` - only navigation arrows
* * `"none"` - no navigation visible at all
*/
this.navigation = this._config.navigation;
/**
* The way of displaying days that don't belong to the current month.
*
* * `"visible"` - days are visible
* * `"hidden"` - days are hidden, white space preserved
* * `"collapsed"` - days are collapsed, so the datepicker height might change between months
*
* For the 2+ months view, days in between months are never shown.
*/
this.outsideDays = this._config.outsideDays;
/**
* If `true`, week numbers will be displayed.
*/
this.showWeekNumbers = this._config.showWeekNumbers;
/**
* The date to open calendar with.
*
* With the default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date is provided, calendar will open with current month.
*
* You could use `navigateTo(date)` method as an alternative.
*/
this.startDate = this._config.startDate;
/**
* The way weekdays should be displayed.
*
* * `true` - weekdays are displayed using default width
* * `false` - weekdays are not displayed
* * `TranslationWidth` - weekdays are displayed using specified width
*
* @since 9.1.0
*/
this.weekdays = this._config.weekdays;
/**
* An event emitted right before the navigation happens and displayed month changes.
*
* See [`NgbDatepickerNavigateEvent`](#/components/datepicker/api#NgbDatepickerNavigateEvent) for the payload info.
*/
this.navigate = new EventEmitter();
/**
* An event emitted when user selects a date using keyboard or mouse.
*
* The payload of the event is currently selected `NgbDate`.
*
* @since 5.2.0
*/
this.dateSelect = new EventEmitter();
this.onChange = (_) => { };
this.onTouched = () => { };
const cd = inject(ChangeDetectorRef);
this._service.dateSelect$.pipe(takeUntilDestroyed()).subscribe((date) => {
this.dateSelect.emit(date);
});
this._service.model$.pipe(takeUntilDestroyed()).subscribe((model) => {
const newDate = model.firstDate;
const oldDate = this.model ? this.model.firstDate : null;
// update public state
this._publicState = {
maxDate: model.maxDate,
minDate: model.minDate,
firstDate: model.firstDate,
lastDate: model.lastDate,
focusedDate: model.focusDate,
months: model.months.map((viewModel) => viewModel.firstDate),
};
let navigationPrevented = false;
// emitting navigation event if the first month changes
if (!newDate.equals(oldDate)) {
this.navigate.emit({
current: oldDate ? { year: oldDate.year, month: oldDate.month } : null,
next: { year: newDate.year, month: newDate.month },
preventDefault: () => (navigationPrevented = true),
});
// can't prevent the very first navigation
if (navigationPrevented && oldDate !== null) {
this._service.open(oldDate);
return;
}
}
const newSelectedDate = model.selectedDate;
const newFocusedDate = model.focusDate;
const oldFocusedDate = this.model ? this.model.focusDate : null;
this.model = model;
// handling selection change
if (isChangedDate(newSelectedDate, this._controlValue)) {
this._controlValue = newSelectedDate;
this.onTouched();
this.onChange(this._ngbDateAdapter.toModel(newSelectedDate));
}
// handling focus change
if (isChangedDate(newFocusedDate, oldFocusedDate) && oldFocusedDate && model.focusVisible) {
this.focus();
}
cd.markForCheck();
});
}
/**
* Returns the readonly public state of the datepicker
*
* @since 5.2.0
*/
get state() {
return this._publicState;
}
/**
* Returns the calendar service used in the specific datepicker instance.
*
* @since 5.3.0
*/
get calendar() {
return this._calendar;
}
/**
* Returns the i18n service used in the specific datepicker instance.
*
* @since 14.2.0
*/
get i18n() {
return this._i18n;
}
/**
* Focuses on given date.
*/
focusDate(date) {
this._service.focus(NgbDate.from(date));
}
/**
* Selects focused date.
*/
focusSelect() {
this._service.focusSelect();
}
focus() {
this._ngZone.onStable
.asObservable()
.pipe(take(1))
.subscribe(() => this._nativeElement.querySelector('div.ngb-dp-day[tabindex="0"]')?.focus());
}
/**
* Navigates to the provided date.
*
* With the default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided calendar will open current month.
*
* Use the `[startDate]` input as an alternative.
*/
navigateTo(date) {
this._service.open(NgbDate.from(date ? (date.day ? date : { ...date, day: 1 }) : null));
}
ngAfterViewInit() {
this._ngZone.runOutsideAngular(() => {
const focusIns$ = fromEvent(this._contentEl.nativeElement, 'focusin');
const focusOuts$ = fromEvent(this._contentEl.nativeElement, 'focusout');
// we're changing 'focusVisible' only when entering or leaving months view
// and ignoring all focus events where both 'target' and 'related' target are day cells
merge(focusIns$, focusOuts$)
.pipe(filter((focusEvent) => {
const target = focusEvent.target;
const relatedTarget = focusEvent.relatedTarget;
return !(target?.classList.contains('ngb-dp-day') &&
relatedTarget?.classList.contains('ngb-dp-day') &&
this._nativeElement.contains(target) &&
this._nativeElement.contains(relatedTarget));
}), takeUntilDestroyed(this._destroyRef))
.subscribe(({ type }) => this._ngZone.run(() => this._service.set({ focusVisible: type === 'focusin' })));
});
}
ngOnInit() {
if (this.model === undefined) {
const inputs = {};
[
'dayTemplateData',
'displayMonths',
'markDisabled',
'firstDayOfWeek',
'navigation',
'minDate',
'maxDate',
'outsideDays',
'weekdays',
].forEach((name) => (inputs[name] = this[name]));
this._service.set(inputs);
this.navigateTo(this.startDate);
}
if (!this.dayTemplate) {
this.dayTemplate = this._defaultDayTemplate;
}
}
ngOnChanges(changes) {
const inputs = {};
[
'dayTemplateData',
'displayMonths',
'markDisabled',
'firstDayOfWeek',
'navigation',
'minDate',
'maxDate',
'outsideDays',
'weekdays',
]
.filter((name) => name in changes)
.forEach((name) => (inputs[name] = this[name]));
this._service.set(inputs);
if ('startDate' in changes) {
const { currentValue, previousValue } = changes.startDate;
if (isChangedMonth(previousValue, currentValue)) {
this.navigateTo(this.startDate);
}
}
}
onDateSelect(date) {
this._service.focus(date);
this._service.select(date, { emitEvent: true });
}
onNavigateDateSelect(date) {
this._service.open(date);
}
onNavigateEvent(event) {
switch (event) {
case NavigationEvent.PREV:
this._service.open(this._calendar.getPrev(this.model.firstDate, 'm', 1));
break;
case NavigationEvent.NEXT:
this._service.open(this._calendar.getNext(this.model.firstDate, 'm', 1));
break;
}
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(disabled) {
this._service.set({ disabled });
}
writeValue(value) {
this._controlValue = NgbDate.from(this._ngbDateAdapter.fromModel(value));
this._service.select(this._controlValue);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: NgbDatepicker, isStandalone: true, selector: "ngb-datepicker", inputs: { contentTemplate: "contentTemplate", dayTemplate: "dayTemplate", dayTemplateData: "dayTemplateData", displayMonths: "displayMonths", firstDayOfWeek: "firstDayOfWeek", footerTemplate: "footerTemplate", markDisabled: "markDisabled", maxDate: "maxDate", minDate: "minDate", navigation: "navigation", outsideDays: "outsideDays", showWeekNumbers: "showWeekNumbers", startDate: "startDate", weekdays: "weekdays" }, outputs: { navigate: "navigate", dateSelect: "dateSelect" }, host: { properties: { "class.disabled": "model.disabled" } }, providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbDatepicker), multi: true },
NgbDatepickerService,
], queries: [{ propertyName: "contentTemplateFromContent", first: true, predicate: NgbDatepickerContent, descendants: true, static: true }], viewQueries: [{ propertyName: "_defaultDayTemplate", first: true, predicate: ["defaultDayTemplate"], descendants: true, static: true }, { propertyName: "_contentEl", first: true, predicate: ["content"], descendants: true, static: true }], exportAs: ["ngbDatepicker"], usesOnChanges: true, ngImport: i0, template: `
<ng-template
#defaultDayTemplate
let-date="date"
let-currentMonth="currentMonth"
let-selected="selected"
let-disabled="disabled"
let-focused="focused"
>
<div
ngbDatepickerDayView
[date]="date"
[currentMonth]="currentMonth"
[selected]="selected"
[disabled]="disabled"
[focused]="focused"
>
</div>
</ng-template>
<ng-template #defaultContentTemplate>
@for (month of model.months; track month; let i = $index) {
<div class="ngb-dp-month">
@if (navigation === 'none' || (displayMonths > 1 && navigation === 'select')) {
<div class="ngb-dp-month-name">
{{ i18n.getMonthLabel(month.firstDate) }}
</div>
}
<ngb-datepicker-month [month]="month.firstDate" />
</div>
}
</ng-template>
<div class="ngb-dp-header">
@if (navigation !== 'none') {
<ngb-datepicker-navigation
[date]="model.firstDate!"
[months]="model.months"
[disabled]="model.disabled"
[showSelect]="model.navigation === 'select'"
[prevDisabled]="model.prevDisabled"
[nextDisabled]="model.nextDisabled"
[selectBoxes]="model.selectBoxes"
(navigate)="onNavigateEvent($event)"
(select)="onNavigateDateSelect($event)"
/>
}
</div>
<div class="ngb-dp-content" [class.ngb-dp-months]="!contentTemplate" #content>
<ng-template
[ngTemplateOutlet]="contentTemplate || contentTemplateFromContent?.templateRef || defaultContentTemplate"
[ngTemplateOutletContext]="{ $implicit: this }"
[ngTemplateOutletInjector]="injector"
/>
</div>
<ng-template [ngTemplateOutlet]="footerTemplate" />
`, isInline: true, styles: ["ngb-datepicker{border:1px solid var(--bs-border-color);border-radius:.25rem;display:inline-block}ngb-datepicker-month{pointer-events:auto}ngb-datepicker.dropdown-menu{padding:0}ngb-datepicker.disabled .ngb-dp-weekday,ngb-datepicker.disabled .ngb-dp-week-number,ngb-datepicker.disabled .ngb-dp-month-name{color:var(--bs-text-muted)}.ngb-dp-body{z-index:1055}.ngb-dp-header{border-bottom:0;border-radius:.25rem .25rem 0 0;padding-top:.25rem;background-color:var(--bs-tertiary-bg)}.ngb-dp-months{display:flex}.ngb-dp-month{pointer-events:none}.ngb-dp-month-name{font-size:larger;height:2rem;line-height:2rem;text-align:center;background-color:var(--bs-tertiary-bg)}.ngb-dp-month+.ngb-dp-month .ngb-dp-month-name,.ngb-dp-month+.ngb-dp-month .ngb-dp-week{padding-left:1rem}.ngb-dp-month:last-child .ngb-dp-week{padding-right:.25rem}.ngb-dp-month:first-child .ngb-dp-week{padding-left:.25rem}.ngb-dp-month .ngb-dp-week:last-child{padding-bottom:.25rem}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgbDatepickerDayView, selector: "[ngbDatepickerDayView]", inputs: ["currentMonth", "date", "disabled", "focused", "selected"] }, { kind: "component", type: NgbDatepickerMonth, selector: "ngb-datepicker-month", inputs: ["month"] }, { kind: "component", type: NgbDatepickerNavigation, selector: "ngb-datepicker-navigation", inputs: ["date", "disabled", "months", "showSelect", "prevDisabled", "nextDisabled", "selectBoxes"], outputs: ["navigate", "select"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbDatepicker, decorators: [{
type: Component,
args: [{ exportAs: 'ngbDatepicker', selector: 'ngb-datepicker', standalone: true, imports: [NgTemplateOutlet, NgbDatepickerDayView, NgbDatepickerMonth, NgbDatepickerNavigation], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
'[class.disabled]': 'model.disabled',
}, template: `
<ng-template
#defaultDayTemplate
let-date="date"
let-currentMonth="currentMonth"
let-selected="selected"
let-disabled="disabled"
let-focused="focused"
>
<div
ngbDatepickerDayView
[date]="date"
[currentMonth]="currentMonth"
[selected]="selected"
[disabled]="disabled"
[focused]="focused"
>
</div>
</ng-template>
<ng-template #defaultContentTemplate>
@for (month of model.months; track month; let i = $index) {
<div class="ngb-dp-month">
@if (navigation === 'none' || (displayMonths > 1 && navigation === 'select')) {
<div class="ngb-dp-month-name">
{{ i18n.getMonthLabel(month.firstDate) }}
</div>
}
<ngb-datepicker-month [month]="month.firstDate" />
</div>
}
</ng-template>
<div class="ngb-dp-header">
@if (navigation !== 'none') {
<ngb-datepicker-navigation
[date]="model.firstDate!"
[months]="model.months"
[disabled]="model.disabled"
[showSelect]="model.navigation === 'select'"
[prevDisabled]="model.prevDisabled"
[nextDisabled]="model.nextDisabled"
[selectBoxes]="model.selectBoxes"
(navigate)="onNavigateEvent($event)"
(select)="onNavigateDateSelect($event)"
/>
}
</div>
<div class="ngb-dp-content" [class.ngb-dp-months]="!contentTemplate" #content>
<ng-template
[ngTemplateOutlet]="contentTemplate || contentTemplateFromContent?.templateRef || defaultContentTemplate"
[ngTemplateOutletContext]="{ $implicit: this }"
[ngTemplateOutletInjector]="injector"
/>
</div>
<ng-template [ngTemplateOutlet]="footerTemplate" />
`, providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbDatepicker), multi: true },
NgbDatepickerService,
], styles: ["ngb-datepicker{border:1px solid var(--bs-border-color);border-radius:.25rem;display:inline-block}ngb-datepicker-month{pointer-events:auto}ngb-datepicker.dropdown-menu{padding:0}ngb-datepicker.disabled .ngb-dp-weekday,ngb-datepicker.disabled .ngb-dp-week-number,ngb-datepicker.disabled .ngb-dp-month-name{color:var(--bs-text-muted)}.ngb-dp-body{z-index:1055}.ngb-dp-header{border-bottom:0;border-radius:.25rem .25rem 0 0;padding-top:.25rem;background-color:var(--bs-tertiary-bg)}.ngb-dp-months{display:flex}.ngb-dp-month{pointer-events:none}.ngb-dp-month-name{font-size:larger;height:2rem;line-height:2rem;text-align:center;background-color:var(--bs-tertiary-bg)}.ngb-dp-month+.ngb-dp-month .ngb-dp-month-name,.ngb-dp-month+.ngb-dp-month .ngb-dp-week{padding-left:1rem}.ngb-dp-month:last-child .ngb-dp-week{padding-right:.25rem}.ngb-dp-month:first-child .ngb-dp-week{padding-left:.25rem}.ngb-dp-month .ngb-dp-week:last-child{padding-bottom:.25rem}\n"] }]
}], ctorParameters: () => [], propDecorators: { _defaultDayTemplate: [{
type: ViewChild,
args: ['defaultDayTemplate', { static: true }]
}], _contentEl: [{
type: ViewChild,
args: ['content', { static: true }]
}], contentTemplate: [{
type: Input
}], contentTemplateFromContent: [{
type: ContentChild,
args: [NgbDatepickerContent, { static: true }]
}], dayTemplate: [{
type: Input
}], dayTemplateData: [{
type: Input
}], displayMonths: [{
type: Input
}], firstDayOfWeek: [{
type: Input
}], footerTemplate: [{
type: Input
}], markDisabled: [{
type: Input
}], maxDate: [{
type: Input
}], minDate: [{
type: Input
}], navigation: [{
type: Input
}], outsideDays: [{
type: Input
}], showWeekNumbers: [{
type: Input
}], startDate: [{
type: Input
}], weekdays: [{
type: Input
}], navigate: [{
type: Output
}], dateSelect: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kYXRlcGlja2VyL2RhdGVwaWNrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBRU4sdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLFVBQVUsRUFDVixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLFFBQVEsRUFDUixLQUFLLEVBQ0wsTUFBTSxFQUdOLE1BQU0sRUFFTixXQUFXLEVBQ1gsU0FBUyxFQUNULGlCQUFpQixHQUNqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFaEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDckMsT0FBTyxFQUEyQixvQkFBb0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JGLE9BQU8sRUFBcUQsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFN0csT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3RELE9BQU8sRUFB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bnQiOlsiaW1wb3J0IHsgZnJvbUV2ZW50LCBtZXJnZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcblx0QWZ0ZXJWaWV3SW5pdCxcblx0Q2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG5cdENoYW5nZURldGVjdG9yUmVmLFxuXHRDb21wb25lbnQsXG5cdENvbnRlbnRDaGlsZCxcblx0RGVzdHJveVJlZixcblx0RGlyZWN0aXZlLFxuXHRFbGVtZW50UmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGZvcndhcmRSZWYsXG5cdGluamVjdCxcblx0SW5qZWN0b3IsXG5cdElucHV0LFxuXHROZ1pvbmUsXG5cdE9uQ2hhbmdlcyxcblx0T25Jbml0LFxuXHRPdXRwdXQsXG5cdFNpbXBsZUNoYW5nZXMsXG5cdFRlbXBsYXRlUmVmLFxuXHRWaWV3Q2hpbGQsXG5cdFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IE5nVGVtcGxhdGVPdXRsZXQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuXG5pbXBvcnQgeyBOZ2JDYWxlbmRhciB9IGZyb20gJy4vbmdiLWNhbGVuZGFyJztcbmltcG9ydCB7IE5nYkRhdGUgfSBmcm9tICcuL25nYi1kYXRlJztcbmltcG9ydCB7IERhdGVwaWNrZXJTZXJ2aWNlSW5wdXRzLCBOZ2JEYXRlcGlja2VyU2VydmljZSB9IGZyb20gJy4vZGF0ZXBpY2tlci1zZXJ2aWNlJztcbmltcG9ydCB7IERhdGVwaWNrZXJWaWV3TW9kZWwsIERheVZpZXdNb2RlbCwgTW9udGhWaWV3TW9kZWwsIE5hdmlnYXRpb25FdmVudCB9IGZyb20gJy4vZGF0ZXBpY2tlci12aWV3LW1vZGVsJztcbmltcG9ydCB7IERheVRlbXBsYXRlQ29udGV4dCB9IGZyb20gJy4vZGF0ZXBpY2tlci1kYXktdGVtcGxhdGUtY29udGV4dCc7XG5pbXBvcnQgeyBOZ2JEYXRlcGlja2VyQ29uZmlnIH0gZnJvbSAnLi9kYXRlcGlja2VyLWNvbmZpZyc7XG5pbXBvcnQgeyBOZ2JEYXRlQWRhcHRlciB9IGZyb20gJy4vYWRhcHRlcnMvbmdiLWRhdGUtYWRhcHRlcic7XG5pbXBvcnQgeyBOZ2JEYXRlU3RydWN0IH0gZnJvbSAnLi9uZ2ItZGF0ZS1zdHJ1Y3QnO1xuaW1wb3J0IHsgTmdiRGF0ZXBpY2tlckkxOG4gfSBmcm9tICcuL2RhdGVwaWNrZXItaTE4bic7XG5pbXBvcnQgeyBOZ2JEYXRlcGlja2VyS2V5Ym9hcmRTZXJ2aWNlIH0gZnJvbSAnLi9kYXRlcGlja2VyLWtleWJvYXJkLXNlcnZpY2UnO1xuaW1wb3J0IHsgaXNDaGFuZ2VkRGF0ZSwgaXNDaGFuZ2VkTW9udGggfSBmcm9tICcuL2RhdGVwaWNrZXItdG9vbHMnO1xuaW1wb3J0IHsgTmdiRGF0ZXBpY2tlckRheVZpZXcgfSBmcm9tICcuL2RhdGVwaWNrZXItZGF5LXZpZXcnO1xuaW1wb3J0IHsgTmdiRGF0ZXBpY2tlck5hdmlnYXRpb24gfSBmcm9tICcuL2RhdGVwaWNrZXItbmF2aWdhdGlvbic7XG5pbXBvcnQgeyBDb250ZW50VGVtcGxhdGVDb250ZXh0IH0gZnJvbSAnLi9kYXRlcGlja2VyLWNvbnRlbnQtdGVtcGxhdGUtY29udGV4dCc7XG5cbi8qKlxuICogQW4gZXZlbnQgZW1pdHRlZCByaWdodCBiZWZvcmUgdGhlIG5hdmlnYXRpb24gaGFwcGVucyBhbmQgdGhlIG1vbnRoIGRpc3BsYXllZCBieSB0aGUgZGF0ZXBpY2tlciBjaGFuZ2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5nYkRhdGVwaWNrZXJOYXZpZ2F0ZUV2ZW50IHtcblx0LyoqXG5cdCAqIFRoZSBjdXJyZW50bHkgZGlzcGxheWVkIG1vbnRoLlxuXHQgKi9cblx0Y3VycmVudDogeyB5ZWFyOiBudW1iZXI7IG1vbnRoOiBudW1iZXIgfSB8IG51bGw7XG5cblx0LyoqXG5cdCAqIFRoZSBtb250aCB3ZSdyZSBuYXZpZ2F0aW5nIHRvLlxuXHQgKi9cblx0bmV4dDogeyB5ZWFyOiBudW1iZXI7IG1vbnRoOiBudW1iZXIgfTtcblxuXHQvKipcblx0ICogQ2FsbGluZyB0aGlzIGZ1bmN0aW9uIHdpbGwgcHJldmVudCBuYXZpZ2F0aW9uIGZyb20gaGFwcGVuaW5nLlxuXHQgKlxuXHQgKiBAc2luY2UgNC4xLjBcblx0ICovXG5cdHByZXZlbnREZWZhdWx0OiAoKSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIEFuIGludGVyZmFjZSB0aGF0IHJlcHJlc2VudHMgdGhlIHJlYWRvbmx5IHB1YmxpYyBzdGF0ZSBvZiB0aGUgZGF0ZXBpY2tlci5cbiAqXG4gKiBBY2Nlc3NpYmxlIHZpYSB0aGUgYGRhdGVwaWNrZXIuc3RhdGVgIGdldHRlclxuICpcbiAqIEBzaW5jZSA1LjIuMFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5nYkRhdGVwaWNrZXJTdGF0ZSB7XG5cdC8qKlxuXHQgKiBUaGUgZWFybGllc3QgZGF0ZSB0aGF0IGNhbiBiZSBkaXNwbGF5ZWQgb3Igc2VsZWN0ZWRcblx0ICovXG5cdHJlYWRvbmx5IG1pbkRhdGU6IE5nYkRhdGUgfCBudWxsO1xuXG5cdC8qKlxuXHQgKiBUaGUgbGF0ZXN0IGRhdGUgdGhhdCBjYW4gYmUgZGlzcGxheWVkIG9yIHNlbGVjdGVkXG5cdCAqL1xuXHRyZWFkb25seSBtYXhEYXRlOiBOZ2JEYXRlIHwgbnVsbDtcblxuXHQvKipcblx0ICogVGhlIGZpcnN0IHZpc2libGUgZGF0ZSBvZiBjdXJyZW50bHkgZGlzcGxheWVkIG1vbnRoc1xuXHQgKi9cblx0cmVhZG9ubHkgZmlyc3REYXRlOiBOZ2JEYXRlO1xuXG5cdC8qKlxuXHQgKiBUaGUgbGFzdCB2aXNpYmxlIGRhdGUgb2YgY3VycmVudGx5IGRpc3BsYXllZCBtb250aHNcblx0ICovXG5cdHJlYWRvbmx5IGxhc3REYXRlOiBOZ2JEYXRlO1xuXG5cdC8qKlxuXHQgKiBUaGUgZGF0ZSBjdXJyZW50bHkgZm9jdXNlZCBieSB0aGUgZGF0ZXBpY2tlclxuXHQgKi9cblx0cmVhZG9ubHkgZm9jdXNlZERhdGU6IE5nYkRhdGU7XG5cblx0LyoqXG5cdCAqIEZpcnN0IGRhdGVzIG9mIG1vbnRocyBjdXJyZW50bHkgZGlzcGxheWVkIGJ5IHRoZSBkYXRlcGlja2VyXG5cdCAqXG5cdCAqIEBzaW5jZSA1LjMuMFxuXHQgKi9cblx0cmVhZG9ubHkgbW9udGhzOiBOZ2JEYXRlW107XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgdGhhdCBtYXJrcyB0aGUgY29udGVudCB0ZW1wbGF0ZSB0aGF0IGN1c3RvbWl6ZXMgdGhlIHdheSBkYXRlcGlja2VyIG1vbnRocyBhcmUgZGlzcGxheWVkXG4gKlxuICogQHNpbmNlIDUuMy4wXG4gKi9cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ25nLXRlbXBsYXRlW25nYkRhdGVwaWNrZXJDb250ZW50XScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBOZ2JEYXRlcGlja2VyQ29udGVudCB7XG5cdHRlbXBsYXRlUmVmID0gaW5qZWN0KFRlbXBsYXRlUmVmKTtcbn1cblxuLyoqXG4gKiBBIGNvbXBvbmVudCB0aGF0IHJlbmRlcnMgb25lIG1vbnRoIGluY2x1ZGluZyBhbGwgdGhlIGRheXMsIHdlZWtkYXlzIGFuZCB3ZWVrIG51bWJlcnMuIENhbiBiZSB1c2VkIGluc2lkZVxuICogdGhlIGA8bmctdGVtcGxhdGUgbmdiRGF0ZXBpY2tlck1vbnRocz48L25nLXRlbXBsYXRlPmAgd2hlbiB5b3Ugd2FudCB0byBjdXN0b21pemUgbW9udGhzIGxheW91dC5cbiAqXG4gKiBGb3IgYSB1c2FnZSBleGFtcGxlLCBzZWUgW2N1c3RvbSBtb250aCBsYXlvdXQgZGVtb10oIy9jb21wb25lbnRzL2RhdGVwaWNrZXIvZXhhbXBsZXMjY3VzdG9tbW9udGgpXG4gKlxuICogQHNpbmNlIDUuMy4wXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ25nYi1kYXRlcGlja2VyLW1vbnRoJyxcblx0c3RhbmRhbG9uZTogdHJ1ZSxcblx0aW1wb3J0czogW05nVGVtcGxhdGVPdXRsZXRdLFxuXHRob3N0OiB7XG5cdFx0cm9sZTogJ2dyaWQnLFxuXHRcdCcoa2V5ZG93biknOiAnb25LZXlEb3duKCRldmVudCknLFxuXHR9LFxuXHRlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuXHRzdHlsZVVybDogJy4vZGF0ZXBpY2tlci1tb250aC5zY3NzJyxcblx0dGVtcGxhdGU6IGBcblx0XHRAaWYgKHZpZXdNb2RlbC53ZWVrZGF5cy5sZW5ndGggPiAwKSB7XG5cdFx0XHQ8ZGl2IGNsYXNzPVwibmdiLWRwLXdlZWsgbmdiLWRwLXdlZWtkYXlzXCIgcm9sZT1cInJvd1wiPlxuXHRcdFx0XHRAaWYgKGRhdGVwaWNrZXIuc2hvd1dlZWtOdW1iZXJzKSB7XG5cdFx0XHRcdFx0PGRpdiBjbGFzcz1cIm5nYi1kcC13ZWVrZGF5IG5nYi1kcC1zaG93d2VlayBzbWFsbFwiPnt7IGkxOG4uZ2V0V2Vla0xhYmVsKCkgfX08L2Rpdj5cblx0XHRcdFx0fVxuXHRcdFx0XHRAZm9yICh3ZWVrZGF5IG9mIHZpZXdNb2RlbC53ZWVrZGF5czsgdHJhY2sgd2Vla2RheSkge1xuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJuZ2ItZHAtd2Vla2RheSBzbWFsbFwiIHJvbGU9XCJjb2x1bW5oZWFkZXJcIj57eyB3ZWVrZGF5IH19PC9kaXY+XG5cdFx0XHRcdH1cblx0XHRcdDwvZGl2PlxuXHRcdH1cblx0XHRAZm9yICh3ZWVrIG9mIHZpZXdNb2RlbC53ZWVrczsgdHJhY2sgd2Vlaykge1xuXHRcdFx0QGlmICghd2Vlay5jb2xsYXBzZWQpIHtcblx0XHRcdFx0PGRpdiBjbGFzcz1cIm5nYi