@danielmoncada/angular-datetime-picker
Version:
Angular Date Time Picker
1,047 lines (1,037 loc) • 284 kB
JavaScript
import * as i0 from '@angular/core';
import { Directive, Input, InjectionToken, inject, LOCALE_ID, Optional, Inject, Injectable, EventEmitter, Component, ChangeDetectionStrategy, Output, ViewChild, TemplateRef, SkipSelf, forwardRef, Pipe, NgModule } from '@angular/core';
import * as i3 from '@angular/common';
import { getLocaleFirstDayOfWeek, DOCUMENT, CommonModule } from '@angular/common';
import * as i4 from '@angular/cdk/a11y';
import { A11yModule } from '@angular/cdk/a11y';
import * as i1 from '@angular/cdk/overlay';
import { NoopScrollStrategy, Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
import { Subscription, of, merge, Subject, filter, take as take$1, defer } from 'rxjs';
import * as i2 from '@angular/cdk/portal';
import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, PortalInjector, PortalModule } from '@angular/cdk/portal';
import { ENTER, PAGE_DOWN, PAGE_UP, END, HOME, DOWN_ARROW, UP_ARROW, RIGHT_ARROW, LEFT_ARROW, SPACE, ESCAPE } from '@angular/cdk/keycodes';
import { coerceBooleanProperty, coerceNumberProperty, coerceArray } from '@angular/cdk/coercion';
import { take, debounceTime, startWith, filter as filter$1 } from 'rxjs/operators';
import { trigger, state, style, transition, group, query, animateChild, animate, keyframes } from '@angular/animations';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators } from '@angular/forms';
import * as i1$1 from '@angular/cdk/platform';
import { PlatformModule } from '@angular/cdk/platform';
/**
* date-time-picker-trigger.directive
*/
class OwlDateTimeTriggerDirective {
get disabled() {
return this._disabled === undefined ? this.dtPicker.disabled : !!this._disabled;
}
set disabled(value) {
this._disabled = value;
}
get owlDTTriggerDisabledClass() {
return this.disabled;
}
constructor(changeDetector) {
this.changeDetector = changeDetector;
this.stateChanges = Subscription.EMPTY;
}
ngOnInit() {
}
ngOnChanges(changes) {
if (changes.datepicker) {
this.watchStateChanges();
}
}
ngAfterContentInit() {
this.watchStateChanges();
}
ngOnDestroy() {
this.stateChanges.unsubscribe();
}
handleClickOnHost(event) {
if (this.dtPicker) {
this.dtPicker.open();
event.stopPropagation();
}
}
watchStateChanges() {
this.stateChanges.unsubscribe();
const inputDisabled = this.dtPicker && this.dtPicker.dtInput ?
this.dtPicker.dtInput.disabledChange : of();
const pickerDisabled = this.dtPicker ?
this.dtPicker.disabledChange : of();
this.stateChanges = merge([pickerDisabled, inputDisabled])
.subscribe(() => {
this.changeDetector.markForCheck();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTimeTriggerDirective, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.5", type: OwlDateTimeTriggerDirective, selector: "[owlDateTimeTrigger]", inputs: { dtPicker: ["owlDateTimeTrigger", "dtPicker"], disabled: "disabled" }, host: { listeners: { "click": "handleClickOnHost($event)" }, properties: { "class.owl-dt-trigger-disabled": "owlDTTriggerDisabledClass" } }, usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTimeTriggerDirective, decorators: [{
type: Directive,
args: [{
selector: '[owlDateTimeTrigger]',
standalone: false,
host: {
'(click)': 'handleClickOnHost($event)',
'[class.owl-dt-trigger-disabled]': 'owlDTTriggerDisabledClass'
}
}]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { dtPicker: [{
type: Input,
args: ['owlDateTimeTrigger']
}], disabled: [{
type: Input
}] } });
/**
* date-time-format.class
*/
/** InjectionToken for date time picker that can be used to override default format. */
const OWL_DATE_TIME_FORMATS = new InjectionToken('OWL_DATE_TIME_FORMATS');
/**
* date-time-adapter.class
*/
/** InjectionToken for date time picker that can be used to override default locale code. */
const OWL_DATE_TIME_LOCALE = new InjectionToken('OWL_DATE_TIME_LOCALE', {
providedIn: 'root',
factory: OWL_DATE_TIME_LOCALE_FACTORY
});
/** @docs-private */
function OWL_DATE_TIME_LOCALE_FACTORY() {
return inject(LOCALE_ID);
}
/** Provider for OWL_DATE_TIME_LOCALE injection token. */
const OWL_DATE_TIME_LOCALE_PROVIDER = {
provide: OWL_DATE_TIME_LOCALE,
useExisting: LOCALE_ID
};
class DateTimeAdapter {
constructor() {
/** A stream that emits when the locale changes. */
this._localeChanges = new Subject();
this.firstMonthOfTheYear = 0;
this.firstDayOfTheWeek = 0;
/** total milliseconds in a day. */
this.millisecondsInDay = 86400000;
/** total milliseconds in a minute. */
this.milliseondsInMinute = 60000;
}
get localeChanges() {
return this._localeChanges;
}
/**
* Compare two given dates
* 1 if the first date is after the second,
* -1 if the first date is before the second
* 0 if dates are equal.
* */
compare(first, second) {
if (!this.isValid(first) || !this.isValid(second)) {
throw Error('JSNativeDate: Cannot compare invalid dates.');
}
const dateFirst = this.clone(first);
const dateSecond = this.clone(second);
const diff = this.getTime(dateFirst) - this.getTime(dateSecond);
if (diff < 0) {
return -1;
}
else if (diff > 0) {
return 1;
}
else {
// Return 0 if diff is 0; return NaN if diff is NaN
return diff;
}
}
/**
* Check if two given dates are in the same year
* 1 if the first date's year is after the second,
* -1 if the first date's year is before the second
* 0 if two given dates are in the same year
* */
compareYear(first, second) {
if (!this.isValid(first) || !this.isValid(second)) {
throw Error('JSNativeDate: Cannot compare invalid dates.');
}
const yearLeft = this.getYear(first);
const yearRight = this.getYear(second);
const diff = yearLeft - yearRight;
if (diff < 0) {
return -1;
}
else if (diff > 0) {
return 1;
}
else {
return 0;
}
}
/**
* Attempts to deserialize a value to a valid date object. This is different from parsing in that
* deserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601
* string). The default implementation does not allow any deserialization, it simply checks that
* the given value is already a valid date object or null. The `<mat-datepicker>` will call this
* method on all of it's `@Input()` properties that accept dates. It is therefore possible to
* support passing values from your backend directly to these properties by overriding this method
* to also deserialize the format used by your backend.
*/
deserialize(value) {
if (value == null ||
(this.isDateInstance(value) && this.isValid(value))) {
return value;
}
return this.invalid();
}
/**
* Sets the locale used for all dates.
*/
setLocale(locale) {
this.locale = locale;
this._localeChanges.next(locale);
}
/**
* Get the locale used for all dates.
* */
getLocale() {
return this.locale;
}
/**
* Clamp the given date between min and max dates.
*/
clampDate(date, min, max) {
if (min && this.compare(date, min) < 0) {
return min;
}
if (max && this.compare(date, max) > 0) {
return max;
}
return date;
}
}
/**
* date-time.class
*/
let nextUniqueId = 0;
var DateView;
(function (DateView) {
DateView["MONTH"] = "month";
DateView["YEAR"] = "year";
DateView["MULTI_YEARS"] = "multi-years";
})(DateView || (DateView = {}));
class OwlDateTime {
get showSecondsTimer() {
return this._showSecondsTimer;
}
set showSecondsTimer(val) {
this._showSecondsTimer = coerceBooleanProperty(val);
}
get hour12Timer() {
return this._hour12Timer;
}
set hour12Timer(val) {
this._hour12Timer = coerceBooleanProperty(val);
}
get stepHour() {
return this._stepHour;
}
set stepHour(val) {
this._stepHour = coerceNumberProperty(val, 1);
}
get stepMinute() {
return this._stepMinute;
}
set stepMinute(val) {
this._stepMinute = coerceNumberProperty(val, 1);
}
get stepSecond() {
return this._stepSecond;
}
set stepSecond(val) {
this._stepSecond = coerceNumberProperty(val, 1);
}
get firstDayOfWeek() {
return this._firstDayOfWeek;
}
set firstDayOfWeek(value) {
value = coerceNumberProperty(value);
if (value > 6 || value < 0) {
this._firstDayOfWeek = undefined;
}
else {
this._firstDayOfWeek = value;
}
}
get hideOtherMonths() {
return this._hideOtherMonths;
}
set hideOtherMonths(val) {
this._hideOtherMonths = coerceBooleanProperty(val);
}
get id() {
return this._id;
}
get formatString() {
return this.pickerType === 'both'
? this.dateTimeFormats.fullPickerInput
: this.pickerType === 'calendar'
? this.dateTimeFormats.datePickerInput
: this.dateTimeFormats.timePickerInput;
}
get disabled() {
return false;
}
constructor(dateTimeAdapter, dateTimeFormats) {
this.dateTimeAdapter = dateTimeAdapter;
this.dateTimeFormats = dateTimeFormats;
/**
* Whether to show the second's timer
*/
this._showSecondsTimer = false;
/**
* Whether the timer is in hour12 format
*/
this._hour12Timer = false;
/**
* The view that the calendar should start in.
*/
this.startView = DateView.MONTH;
/**
* Whether to show calendar weeks in the calendar
* */
this.showCalendarWeeks = false;
/**
* Whether to should only the year and multi-year views.
*/
this.yearOnly = false;
/**
* Whether to should only the multi-year view.
*/
this.multiyearOnly = false;
/**
* Hours to change per step
*/
this._stepHour = 1;
/**
* Minutes to change per step
*/
this._stepMinute = 1;
/**
* Seconds to change per step
*/
this._stepSecond = 1;
/**
* Whether to hide dates in other months at the start or end of the current month.
*/
this._hideOtherMonths = false;
/**
* Date Time Checker to check if the give dateTime is selectable
*/
this.dateTimeChecker = (dateTime) => {
return (!!dateTime &&
(!this.dateTimeFilter || this.dateTimeFilter(dateTime)) &&
(!this.minDateTime ||
this.dateTimeAdapter.compare(dateTime, this.minDateTime) >=
0) &&
(!this.maxDateTime ||
this.dateTimeAdapter.compare(dateTime, this.maxDateTime) <= 0));
};
if (!this.dateTimeAdapter) {
throw Error(`OwlDateTimePicker: No provider found for DateTimeAdapter. You must import one of the following ` +
`modules at your application root: OwlNativeDateTimeModule, OwlMomentDateTimeModule, or provide a ` +
`custom implementation.`);
}
if (!this.dateTimeFormats) {
throw Error(`OwlDateTimePicker: No provider found for OWL_DATE_TIME_FORMATS. You must import one of the following ` +
`modules at your application root: OwlNativeDateTimeModule, OwlMomentDateTimeModule, or provide a ` +
`custom implementation.`);
}
this._id = `owl-dt-picker-${nextUniqueId++}`;
}
getValidDate(obj) {
return this.dateTimeAdapter.isDateInstance(obj) &&
this.dateTimeAdapter.isValid(obj)
? obj
: null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTime, deps: [{ token: DateTimeAdapter, optional: true }, { token: OWL_DATE_TIME_FORMATS, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.5", type: OwlDateTime, inputs: { showSecondsTimer: "showSecondsTimer", hour12Timer: "hour12Timer", startView: "startView", showCalendarWeeks: "showCalendarWeeks", yearOnly: "yearOnly", multiyearOnly: "multiyearOnly", stepHour: "stepHour", stepMinute: "stepMinute", stepSecond: "stepSecond", firstDayOfWeek: "firstDayOfWeek", hideOtherMonths: "hideOtherMonths" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTime, decorators: [{
type: Directive
}], ctorParameters: () => [{ type: DateTimeAdapter, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [OWL_DATE_TIME_FORMATS]
}] }], propDecorators: { showSecondsTimer: [{
type: Input
}], hour12Timer: [{
type: Input
}], startView: [{
type: Input
}], showCalendarWeeks: [{
type: Input
}], yearOnly: [{
type: Input
}], multiyearOnly: [{
type: Input
}], stepHour: [{
type: Input
}], stepMinute: [{
type: Input
}], stepSecond: [{
type: Input
}], firstDayOfWeek: [{
type: Input
}], hideOtherMonths: [{
type: Input
}] } });
/**
* date-time-picker-intl.service
*/
class OwlDateTimeIntl {
constructor() {
/**
* Stream that emits whenever the labels here are changed. Use this to notify
* components if the labels have changed after initialization.
*/
this.changes = new Subject();
/** A label for the up second button (used by screen readers). */
this.upSecondLabel = 'Add a second';
/** A label for the down second button (used by screen readers). */
this.downSecondLabel = 'Minus a second';
/** A label for the up minute button (used by screen readers). */
this.upMinuteLabel = 'Add a minute';
/** A label for the down minute button (used by screen readers). */
this.downMinuteLabel = 'Minus a minute';
/** A label for the up hour button (used by screen readers). */
this.upHourLabel = 'Add a hour';
/** A label for the down hour button (used by screen readers). */
this.downHourLabel = 'Minus a hour';
/** A label for the previous month button (used by screen readers). */
this.prevMonthLabel = 'Previous month';
/** A label for the next month button (used by screen readers). */
this.nextMonthLabel = 'Next month';
/** A label for the previous year button (used by screen readers). */
this.prevYearLabel = 'Previous year';
/** A label for the next year button (used by screen readers). */
this.nextYearLabel = 'Next year';
/** A label for the previous multi-year button (used by screen readers). */
this.prevMultiYearLabel = 'Previous 21 years';
/** A label for the next multi-year button (used by screen readers). */
this.nextMultiYearLabel = 'Next 21 years';
/** A label for the 'switch to month view' button (used by screen readers). */
this.switchToMonthViewLabel = 'Change to month view';
/** A label for the 'switch to year view' button (used by screen readers). */
this.switchToMultiYearViewLabel = 'Choose month and year';
/** A label for the cancel button */
this.cancelBtnLabel = 'Cancel';
/** A label for the set button */
this.setBtnLabel = 'Set';
/** A label for the range 'from' in picker info */
this.rangeFromLabel = 'From';
/** A label for the range 'to' in picker info */
this.rangeToLabel = 'To';
/** A label for the hour12 button (AM) */
this.hour12AMLabel = 'AM';
/** A label for the hour12 button (PM) */
this.hour12PMLabel = 'PM';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTimeIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTimeIntl, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlDateTimeIntl, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
/**
* calendar-body.component
*/
class CalendarCell {
constructor(value, displayValue, ariaLabel, enabled, out = false, cellClass = '') {
this.value = value;
this.displayValue = displayValue;
this.ariaLabel = ariaLabel;
this.enabled = enabled;
this.out = out;
this.cellClass = cellClass;
}
}
class OwlCalendarBodyComponent {
get owlDTCalendarBodyClass() {
return true;
}
get isInSingleMode() {
return this.selectMode === 'single';
}
get isInRangeMode() {
return (this.selectMode === 'range' ||
this.selectMode === 'rangeFrom' ||
this.selectMode === 'rangeTo');
}
constructor(elmRef, ngZone) {
this.elmRef = elmRef;
this.ngZone = ngZone;
/**
* The cell number of the active cell in the table.
*/
this.activeCell = 0;
/**
* The number of columns in the table.
* */
this.numCols = 7;
/**
* The ratio (width / height) to use for the cells in the table.
*/
this.cellRatio = 1;
/**
* Emit when a calendar cell is selected
* */
this.select = new EventEmitter();
}
ngOnInit() { }
selectCell(cell) {
this.select.emit(cell);
}
isActiveCell(rowIndex, colIndex) {
const cellNumber = rowIndex * this.numCols + colIndex;
return cellNumber === this.activeCell;
}
/**
* Check if the cell is selected
*/
isSelected(value) {
if (!this.selectedValues || this.selectedValues.length === 0) {
return false;
}
if (this.isInSingleMode) {
return value === this.selectedValues[0];
}
if (this.isInRangeMode) {
const fromValue = this.selectedValues[0];
const toValue = this.selectedValues[1];
return value === fromValue || value === toValue;
}
}
/**
* Check if the cell in the range
* */
isInRange(value) {
if (this.isInRangeMode) {
const fromValue = this.selectedValues[0];
const toValue = this.selectedValues[1];
if (fromValue !== null && toValue !== null) {
return value >= fromValue && value <= toValue;
}
else {
return value === fromValue || value === toValue;
}
}
}
/**
* Check if the cell is the range from
* */
isRangeFrom(value) {
if (this.isInRangeMode) {
const fromValue = this.selectedValues[0];
return fromValue !== null && value === fromValue;
}
}
/**
* Check if the cell is the range to
* */
isRangeTo(value) {
if (this.isInRangeMode) {
const toValue = this.selectedValues[1];
return toValue !== null && value === toValue;
}
}
/**
* Focus to a active cell
* */
focusActiveCell() {
this.ngZone.runOutsideAngular(() => {
this.ngZone.onStable
.asObservable()
.pipe(take(1))
.subscribe(() => {
this.elmRef.nativeElement
.querySelector('.owl-dt-calendar-cell-active')
.focus();
});
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlCalendarBodyComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.5", type: OwlCalendarBodyComponent, selector: "[owl-date-time-calendar-body]", inputs: { activeCell: "activeCell", rows: "rows", numCols: "numCols", cellRatio: "cellRatio", todayValue: "todayValue", selectedValues: "selectedValues", selectMode: "selectMode" }, outputs: { select: "select" }, host: { properties: { "class.owl-dt-calendar-body": "owlDTCalendarBodyClass" } }, exportAs: ["owlDateTimeCalendarBody"], ngImport: i0, template: "<tr *ngFor=\"let row of rows; let rowIndex = index\" role=\"row\">\n <td *ngFor=\"let item of row; let colIndex = index\"\n class=\"owl-dt-calendar-cell {{item.cellClass}}\"\n [tabindex]=\"isActiveCell(rowIndex, colIndex) ? 0 : -1\"\n [class.owl-dt-calendar-cell-active]=\"isActiveCell(rowIndex, colIndex)\"\n [class.owl-dt-calendar-cell-disabled]=\"!item.enabled\"\n [class.owl-dt-calendar-cell-in-range]=\"isInRange(item.value)\"\n [class.owl-dt-calendar-cell-range-from]=\"isRangeFrom(item.value)\"\n [class.owl-dt-calendar-cell-range-to]=\"isRangeTo(item.value)\"\n [attr.aria-label]=\"item.ariaLabel\"\n [attr.aria-disabled]=\"!item.enabled || null\"\n [attr.aria-current]=\"item.value === todayValue ? 'date' : null\"\n [attr.aria-selected]=\"isSelected(item.value)\"\n [style.width.%]=\"100 / numCols\"\n [style.paddingTop.%]=\"50 * cellRatio / numCols\"\n [style.paddingBottom.%]=\"50 * cellRatio / numCols\"\n (click)=\"selectCell(item)\">\n <span class=\"owl-dt-calendar-cell-content\"\n [ngClass]=\"{\n 'owl-dt-calendar-cell-out': item.out,\n 'owl-dt-calendar-cell-today': item.value === todayValue,\n 'owl-dt-calendar-cell-selected': isSelected(item.value)\n }\">\n {{item.displayValue}}\n </span>\n </td>\n</tr>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlCalendarBodyComponent, decorators: [{
type: Component,
args: [{ selector: '[owl-date-time-calendar-body]', exportAs: 'owlDateTimeCalendarBody', host: {
'[class.owl-dt-calendar-body]': 'owlDTCalendarBodyClass'
}, preserveWhitespaces: false, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<tr *ngFor=\"let row of rows; let rowIndex = index\" role=\"row\">\n <td *ngFor=\"let item of row; let colIndex = index\"\n class=\"owl-dt-calendar-cell {{item.cellClass}}\"\n [tabindex]=\"isActiveCell(rowIndex, colIndex) ? 0 : -1\"\n [class.owl-dt-calendar-cell-active]=\"isActiveCell(rowIndex, colIndex)\"\n [class.owl-dt-calendar-cell-disabled]=\"!item.enabled\"\n [class.owl-dt-calendar-cell-in-range]=\"isInRange(item.value)\"\n [class.owl-dt-calendar-cell-range-from]=\"isRangeFrom(item.value)\"\n [class.owl-dt-calendar-cell-range-to]=\"isRangeTo(item.value)\"\n [attr.aria-label]=\"item.ariaLabel\"\n [attr.aria-disabled]=\"!item.enabled || null\"\n [attr.aria-current]=\"item.value === todayValue ? 'date' : null\"\n [attr.aria-selected]=\"isSelected(item.value)\"\n [style.width.%]=\"100 / numCols\"\n [style.paddingTop.%]=\"50 * cellRatio / numCols\"\n [style.paddingBottom.%]=\"50 * cellRatio / numCols\"\n (click)=\"selectCell(item)\">\n <span class=\"owl-dt-calendar-cell-content\"\n [ngClass]=\"{\n 'owl-dt-calendar-cell-out': item.out,\n 'owl-dt-calendar-cell-today': item.value === todayValue,\n 'owl-dt-calendar-cell-selected': isSelected(item.value)\n }\">\n {{item.displayValue}}\n </span>\n </td>\n</tr>\n" }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { activeCell: [{
type: Input
}], rows: [{
type: Input
}], numCols: [{
type: Input
}], cellRatio: [{
type: Input
}], todayValue: [{
type: Input
}], selectedValues: [{
type: Input
}], selectMode: [{
type: Input
}], select: [{
type: Output
}] } });
function defaultOptionsFactory() {
return DefaultOptions.create();
}
function multiYearOptionsFactory(options) {
return options.multiYear;
}
class DefaultOptions {
static create() {
// Always return new instance
return {
multiYear: {
yearRows: 7,
yearsPerRow: 3
}
};
}
}
class OptionsTokens {
static { this.all = new InjectionToken('All options token'); }
static { this.multiYear = new InjectionToken('Grid view options token'); }
}
const optionsProviders = [
{
provide: OptionsTokens.all,
useFactory: defaultOptionsFactory,
},
{
provide: OptionsTokens.multiYear,
useFactory: multiYearOptionsFactory,
deps: [OptionsTokens.all],
},
];
/**
* calendar-multi-year-view.component
*/
class OwlMultiYearViewComponent {
get selectMode() {
return this._selectMode;
}
set selectMode(val) {
this._selectMode = val;
if (this.initiated) {
this.setSelectedYears();
this.cdRef.markForCheck();
}
}
get selected() {
return this._selected;
}
set selected(value) {
const oldSelected = this._selected;
value = this.dateTimeAdapter.deserialize(value);
this._selected = this.getValidDate(value);
if (!this.dateTimeAdapter.isSameDay(oldSelected, this._selected)) {
this.setSelectedYears();
}
}
get selecteds() {
return this._selecteds;
}
set selecteds(values) {
this._selecteds = values.map((v) => {
v = this.dateTimeAdapter.deserialize(v);
return this.getValidDate(v);
});
this.setSelectedYears();
}
get pickerMoment() {
return this._pickerMoment;
}
set pickerMoment(value) {
const oldMoment = this._pickerMoment;
value = this.dateTimeAdapter.deserialize(value);
this._pickerMoment = this.getValidDate(value) || this.dateTimeAdapter.now();
if (oldMoment && this._pickerMoment &&
!this.isSameYearList(oldMoment, this._pickerMoment)) {
this.generateYearList();
}
}
get dateFilter() {
return this._dateFilter;
}
set dateFilter(filter) {
this._dateFilter = filter;
if (this.initiated) {
this.generateYearList();
}
}
get minDate() {
return this._minDate;
}
set minDate(value) {
value = this.dateTimeAdapter.deserialize(value);
this._minDate = this.getValidDate(value);
if (this.initiated) {
this.generateYearList();
}
}
get maxDate() {
return this._maxDate;
}
set maxDate(value) {
value = this.dateTimeAdapter.deserialize(value);
this._maxDate = this.getValidDate(value);
if (this.initiated) {
this.generateYearList();
}
}
get todayYear() {
return this._todayYear;
}
get years() {
return this._years;
}
get selectedYears() {
return this._selectedYears;
}
get isInSingleMode() {
return this.selectMode === 'single';
}
get isInRangeMode() {
return this.selectMode === 'range' || this.selectMode === 'rangeFrom'
|| this.selectMode === 'rangeTo';
}
get activeCell() {
if (this._pickerMoment) {
return this.dateTimeAdapter.getYear(this._pickerMoment) % (this.options.yearsPerRow * this.options.yearRows);
}
}
get tableHeader() {
if (this._years && this._years.length > 0) {
return `${this._years[0][0].displayValue} - ${this._years[this.options.yearRows - 1][this.options.yearsPerRow - 1].displayValue}`;
}
}
get prevButtonLabel() {
return this.pickerIntl.prevMultiYearLabel;
}
get nextButtonLabel() {
return this.pickerIntl.nextMultiYearLabel;
}
get owlDTCalendarView() {
return true;
}
get owlDTCalendarMultiYearView() {
return true;
}
constructor(cdRef, pickerIntl, dateTimeAdapter, options) {
this.cdRef = cdRef;
this.pickerIntl = pickerIntl;
this.dateTimeAdapter = dateTimeAdapter;
this.options = options;
/**
* The select mode of the picker;
* */
this._selectMode = 'single';
this._selecteds = [];
this.initiated = false;
/**
* Callback to invoke when a new month is selected
* */
this.change = new EventEmitter();
/**
* Emits the selected year. This doesn't imply a change on the selected date
* */
this.yearSelected = new EventEmitter();
/** Emits when any date is activated. */
this.pickerMomentChange = new EventEmitter();
/** Emits when use keyboard enter to select a calendar cell */
this.keyboardEnter = new EventEmitter();
}
ngOnInit() {
}
ngAfterContentInit() {
this._todayYear = this.dateTimeAdapter.getYear(this.dateTimeAdapter.now());
this.generateYearList();
this.initiated = true;
}
/**
* Handle a calendarCell selected
*/
selectCalendarCell(cell) {
this.selectYear(cell.value);
}
selectYear(year) {
this.yearSelected.emit(this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1));
const firstDateOfMonth = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.getMonth(this.pickerMoment), 1);
const daysInMonth = this.dateTimeAdapter.getNumDaysInMonth(firstDateOfMonth);
const selected = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.getMonth(this.pickerMoment), Math.min(daysInMonth, this.dateTimeAdapter.getDate(this.pickerMoment)), this.dateTimeAdapter.getHours(this.pickerMoment), this.dateTimeAdapter.getMinutes(this.pickerMoment), this.dateTimeAdapter.getSeconds(this.pickerMoment));
this.change.emit(selected);
}
/**
* Generate the previous year list
* */
prevYearList(event) {
this._pickerMoment = this.dateTimeAdapter.addCalendarYears(this.pickerMoment, -1 * this.options.yearsPerRow * this.options.yearRows);
this.generateYearList();
event.preventDefault();
}
/**
* Generate the next year list
* */
nextYearList(event) {
this._pickerMoment = this.dateTimeAdapter.addCalendarYears(this.pickerMoment, this.options.yearsPerRow * this.options.yearRows);
this.generateYearList();
event.preventDefault();
}
generateYearList() {
this._years = [];
const pickerMomentYear = this.dateTimeAdapter.getYear(this._pickerMoment);
const offset = pickerMomentYear % (this.options.yearsPerRow * this.options.yearRows);
for (let i = 0; i < this.options.yearRows; i++) {
const row = [];
for (let j = 0; j < this.options.yearsPerRow; j++) {
const year = pickerMomentYear - offset + (j + i * this.options.yearsPerRow);
const yearCell = this.createYearCell(year);
row.push(yearCell);
}
this._years.push(row);
}
return;
}
/** Whether the previous period button is enabled. */
previousEnabled() {
if (!this.minDate) {
return true;
}
return !this.minDate || !this.isSameYearList(this._pickerMoment, this.minDate);
}
/** Whether the next period button is enabled. */
nextEnabled() {
return !this.maxDate || !this.isSameYearList(this._pickerMoment, this.maxDate);
}
handleCalendarKeydown(event) {
let moment;
switch (event.keyCode) {
// minus 1 year
case LEFT_ARROW:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, -1);
this.pickerMomentChange.emit(moment);
break;
// add 1 year
case RIGHT_ARROW:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, 1);
this.pickerMomentChange.emit(moment);
break;
// minus 3 years
case UP_ARROW:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, -1 * this.options.yearsPerRow);
this.pickerMomentChange.emit(moment);
break;
// add 3 years
case DOWN_ARROW:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, this.options.yearsPerRow);
this.pickerMomentChange.emit(moment);
break;
// go to the first year of the year page
case HOME:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, -this.dateTimeAdapter.getYear(this._pickerMoment) % (this.options.yearsPerRow * this.options.yearRows));
this.pickerMomentChange.emit(moment);
break;
// go to the last year of the year page
case END:
moment = this.dateTimeAdapter.addCalendarYears(this._pickerMoment, (this.options.yearsPerRow * this.options.yearRows) - this.dateTimeAdapter.getYear(this._pickerMoment) % (this.options.yearsPerRow * this.options.yearRows) - 1);
this.pickerMomentChange.emit(moment);
break;
// minus 1 year page (or 10 year pages)
case PAGE_UP:
moment = this.dateTimeAdapter.addCalendarYears(this.pickerMoment, event.altKey ? -10 * (this.options.yearsPerRow * this.options.yearRows) : -1 * (this.options.yearsPerRow * this.options.yearRows));
this.pickerMomentChange.emit(moment);
break;
// add 1 year page (or 10 year pages)
case PAGE_DOWN:
moment = this.dateTimeAdapter.addCalendarYears(this.pickerMoment, event.altKey ? 10 * (this.options.yearsPerRow * this.options.yearRows) : (this.options.yearsPerRow * this.options.yearRows));
this.pickerMomentChange.emit(moment);
break;
case ENTER:
this.selectYear(this.dateTimeAdapter.getYear(this._pickerMoment));
this.keyboardEnter.emit();
break;
default:
return;
}
this.focusActiveCell();
event.preventDefault();
}
/**
* Creates an CalendarCell for the given year.
*/
createYearCell(year) {
const startDateOfYear = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1);
const ariaLabel = this.dateTimeAdapter.getYearName(startDateOfYear);
const cellClass = 'owl-dt-year-' + year;
return new CalendarCell(year, year.toString(), ariaLabel, this.isYearEnabled(year), false, cellClass);
}
setSelectedYears() {
this._selectedYears = [];
if (this.isInSingleMode && this.selected) {
this._selectedYears[0] = this.dateTimeAdapter.getYear(this.selected);
}
if (this.isInRangeMode && this.selecteds) {
this._selectedYears = this.selecteds.map((selected) => {
if (this.dateTimeAdapter.isValid(selected)) {
return this.dateTimeAdapter.getYear(selected);
}
else {
return null;
}
});
}
}
/** Whether the given year is enabled. */
isYearEnabled(year) {
// disable if the year is greater than maxDate lower than minDate
if (year === undefined || year === null ||
(this.maxDate && year > this.dateTimeAdapter.getYear(this.maxDate)) ||
(this.minDate && year < this.dateTimeAdapter.getYear(this.minDate))) {
return false;
}
// enable if it reaches here and there's no filter defined
if (!this.dateFilter) {
return true;
}
const firstOfYear = this.dateTimeAdapter.createDate(year, this.dateTimeAdapter.firstMonthOfTheYear, 1);
// If any date in the year is enabled count the year as enabled.
for (let date = firstOfYear; this.dateTimeAdapter.getYear(date) === year; date = this.dateTimeAdapter.addCalendarDays(date, 1)) {
if (this.dateFilter(date)) {
return true;
}
}
return false;
}
isSameYearList(date1, date2) {
return Math.floor(this.dateTimeAdapter.getYear(date1) / (this.options.yearsPerRow * this.options.yearRows)) ===
Math.floor(this.dateTimeAdapter.getYear(date2) / (this.options.yearsPerRow * this.options.yearRows));
}
/**
* Get a valid date object
*/
getValidDate(obj) {
return (this.dateTimeAdapter.isDateInstance(obj) && this.dateTimeAdapter.isValid(obj)) ? obj : null;
}
focusActiveCell() {
this.calendarBodyElm.focusActiveCell();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlMultiYearViewComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: OwlDateTimeIntl }, { token: DateTimeAdapter, optional: true }, { token: OptionsTokens.multiYear }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.5", type: OwlMultiYearViewComponent, selector: "owl-date-time-multi-year-view", inputs: { selectMode: "selectMode", selected: "selected", selecteds: "selecteds", pickerMoment: "pickerMoment", dateFilter: "dateFilter", minDate: "minDate", maxDate: "maxDate" }, outputs: { change: "change", yearSelected: "yearSelected", pickerMomentChange: "pickerMomentChange", keyboardEnter: "keyboardEnter" }, host: { properties: { "class.owl-dt-calendar-view": "owlDTCalendarView", "class.owl-dt-calendar-multi-year-view": "owlDTCalendarMultiYearView" } }, viewQueries: [{ propertyName: "calendarBodyElm", first: true, predicate: OwlCalendarBodyComponent, descendants: true, static: true }], ngImport: i0, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Left\"> -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 250.738 250.738\"\n style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\"\n width=\"100%\" height=\"100%\">\n <path style=\"fill-rule: evenodd; clip-rule: evenodd;\" d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n</button>\n<table class=\"owl-dt-calendar-table owl-dt-calendar-multi-year-table\">\n <thead class=\"owl-dt-calendar-header\">\n <tr>\n <th colspan=\"3\">{{tableHeader}}</th>\n </tr>\n </thead>\n <tbody owl-date-time-calendar-body role=\"grid\"\n [rows]=\"years\" [numCols]=\"3\" [cellRatio]=\"3 / 7\"\n [activeCell]=\"activeCell\"\n [todayValue]=\"todayYear\"\n [selectedValues]=\"selectedYears\"\n [selectMode]=\"selectMode\"\n (keydown)=\"handleCalendarKeydown($event)\"\n (select)=\"selectCalendarCell($event)\"></tbody>\n</table>\n<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\n [disabled]=\"!nextEnabled()\" [attr.aria-label]=\"nextButtonLabel\"\n type=\"button\" tabindex=\"0\" (click)=\"nextYearList($event)\">\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Right\"> -->\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n viewBox=\"0 0 250.738 250.738\" style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\">\n <path style=\"fill-rule:evenodd;clip-rule:evenodd;\" d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\n C197.237,120.447,195.534,115.448,191.75,111.689z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n</button>\n", styles: [""], dependencies: [{ kind: "component", type: OwlCalendarBodyComponent, selector: "[owl-date-time-calendar-body]", inputs: ["activeCell", "rows", "numCols", "cellRatio", "todayValue", "selectedValues", "selectMode"], outputs: ["select"], exportAs: ["owlDateTimeCalendarBody"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: OwlMultiYearViewComponent, decorators: [{
type: Component,
args: [{ selector: 'owl-date-time-multi-year-view', host: {
'[class.owl-dt-calendar-view]': 'owlDTCalendarView',
'[class.owl-dt-calendar-multi-year-view]': 'owlDTCalendarMultiYearView'
}, standalone: false, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\n [disabled]=\"!previousEnabled()\" [attr.aria-label]=\"prevButtonLabel\"\n type=\"button\" tabindex=\"0\" (click)=\"prevYearList($event)\">\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Left\"> -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n version=\"1.1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 250.738 250.738\"\n style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\"\n width=\"100%\" height=\"100%\">\n <path style=\"fill-rule: evenodd; clip-rule: evenodd;\" d=\"M96.633,125.369l95.053-94.533c7.101-7.055,7.101-18.492,0-25.546 c-7.1-7.054-18.613-7.054-25.714,0L58.989,111.689c-3.784,3.759-5.487,8.759-5.238,13.68c-0.249,4.922,1.454,9.921,5.238,13.681 l106.983,106.398c7.101,7.055,18.613,7.055,25.714,0c7.101-7.054,7.101-18.491,0-25.544L96.633,125.369z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n</button>\n<table class=\"owl-dt-calendar-table owl-dt-calendar-multi-year-table\">\n <thead class=\"owl-dt-calendar-header\">\n <tr>\n <th colspan=\"3\">{{tableHeader}}</th>\n </tr>\n </thead>\n <tbody owl-date-time-calendar-body role=\"grid\"\n [rows]=\"years\" [numCols]=\"3\" [cellRatio]=\"3 / 7\"\n [activeCell]=\"activeCell\"\n [todayValue]=\"todayYear\"\n [selectedValues]=\"selectedYears\"\n [selectMode]=\"selectMode\"\n (keydown)=\"handleCalendarKeydown($event)\"\n (select)=\"selectCalendarCell($event)\"></tbody>\n</table>\n<button class=\"owl-dt-control-button owl-dt-control-arrow-button\"\n [disabled]=\"!nextEnabled()\" [attr.aria-label]=\"nextButtonLabel\"\n type=\"button\" tabindex=\"0\" (click)=\"nextYearList($event)\">\n <span class=\"owl-dt-control-button-content\" tabindex=\"-1\">\n <!-- <editor-fold desc=\"SVG Arrow Right\"> -->\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n viewBox=\"0 0 250.738 250.738\" style=\"enable-background:new 0 0 250.738 250.738;\" xml:space=\"preserve\">\n <path style=\"fill-rule:evenodd;clip-rule:evenodd;\" d=\"M191.75,111.689L84.766,5.291c-7.1-7.055-18.613-7.055-25.713,0\n c-7.101,7.054-7.101,18.49,0,25.544l95.053,94.534l-95.053,94.533c-7.101,7.054-7.101,18.491,0,25.545\n c7.1,7.054,18.613,7.054,25.713,0L191.75,139.05c3.784-3.759,5.487-8.759,5.238-13.681\n C197.237,120.447,195.534,115.448,191.75,111.689z\"/>\n </svg>\n <!-- </editor-fold> -->\n </span>\n</button>\n" }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: OwlDateTimeIntl }, { type: DateTimeAdapter, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [OptionsTokens.multiYear]
}] }], propDecorators: { selectMode: [{
type: Input
}], selected: [{
type: Input
}], selecteds: [{
type: Input
}], pickerMoment: [{
type: Input
}], dateFilter: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], change: [{
type: Output
}], yearSelected: [{
type: Output
}], pickerMomentChange: [{
type: Output
}], keyboardEnter: [{
type: Output
}], calendarBodyElm: [{
type: ViewChild,
args: [OwlCalendarBodyComponent, { static: true }]
}] } });
/**
* calendar-year-view.component
*/
const MONTHS_PER_YEAR = 12;
const MONTHS_PER_ROW = 3;
class OwlYearViewComponent {
get selectMode() {
return this._selectMode;
}
set selectMode(val) {
this._selectMode = val;
if (this.initiated) {
this.generateMonthList();
this.cdRef.markForCheck();
}
}
get selected() {
return this._selected;
}
set selected(value) {
value = this.dateTimeAdapter.deserialize(value);
this._selected = this.getValidDate(value);
this.setSelectedMonths();
}
get selecteds() {
return this._selecteds;
}
set selecteds(values) {
this._selecteds = [];
for (let i = 0; i < values.length; i++) {
const value = this.dateTimeAdapter.deserialize(values[i]);
this._selecteds.push(this.getValidDate(value));
}
this.setSelectedMonths();
}
get pickerMoment() {
return this._pickerMoment;
}
set pickerMoment(value) {
const oldMoment = this._pickerMoment;
value = this.dateTimeAdapter.deserialize(value);
this._pickerMoment =
this.getValidDate(value) || this.dateTimeAdapter.now();
if (!this.hasSameYear(oldMoment, this._pickerMoment) &&
this.initiated) {
this.generateMonthList();
}
}
get dateFilter() {
return this._dateFilter;
}
set dateFilter(filter) {
this._dateFilter = filter;
if (this.initiated) {
this.generateMonthList();
}
}
get minDate() {
return this._minDate;
}
set minDate(value) {
value = this.dateTimeAdapter.deserialize(value);
this._minDate = this.getValidDate(value);
if (this.initiated) {