UNPKG

@progress/kendo-angular-scheduler

Version:

Kendo UI Scheduler Angular - Outlook or Google-style angular scheduler calendar. Full-featured and customizable embedded scheduling from the creator developers trust for professional UI components.

381 lines (376 loc) 15.2 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { ChangeDetectionStrategy, Component, HostBinding, Input, ChangeDetectorRef, ViewChild } from '@angular/core'; import { PopupService } from '@progress/kendo-angular-popup'; import { LocalizationService } from '@progress/kendo-angular-l10n'; import { ToolbarService } from './toolbar.service'; import { CalendarComponent, CalendarCustomMessagesComponent } from '@progress/kendo-angular-dateinputs'; import { ViewContextService } from '../views/view-context.service'; import { isDocumentAvailable } from '@progress/kendo-angular-common'; import { caretAltRightIcon, caretAltLeftIcon, calendarIcon } from '@progress/kendo-svg-icons'; import { AsyncPipe } from '@angular/common'; import { FocusableDirective } from '../navigation/focusable.directive'; import { ButtonComponent } from '@progress/kendo-angular-buttons'; import * as i0 from "@angular/core"; import * as i1 from "@progress/kendo-angular-popup"; import * as i2 from "./toolbar.service"; import * as i3 from "@progress/kendo-angular-l10n"; import * as i4 from "../views/view-context.service"; const iconsMap = { caretAltLeftIcon, caretAltRightIcon, calendarIcon }; /** * A toolbar component which contains the controls for date navigation * ([see example]({% slug toolbar_scheduler %}#toc-including-the-built-in-components)). * * To render the **Previous**, **Today**, **Next**, and **Date picker** * buttons, include the component in the * [toolbar template]({% slug api_scheduler_toolbartemplatedirective %}). */ export class ToolbarNavigationComponent { popupService; toolbarService; localization; cd; viewContext; set calendar(calendar) { if (calendar) { calendar.focus(); } } hostClass = true; /** * @hidden */ min; /** * @hidden */ max; /** * @hidden */ get todayText() { return this.localization.get('today'); } /** * Sets the [`activeView`]({% slug api_dateinputs_calendarcomponent %}#toc-activeview) of the Calendar in the navigation component. * * @default month */ activeView = 'month'; /** * Sets the [`bottomView`]({% slug api_dateinputs_calendarcomponent %}#toc-bottomview) of the Calendar in the navigation component. * * @default month */ bottomView = 'month'; /** * @hidden */ get calendarTodayText() { return this.localization.get('calendarToday'); } /** * @hidden */ get nextText() { return this.localization.get('nextTitle'); } /** * @hidden */ get previousText() { return this.localization.get('previousTitle'); } /** * @hidden */ get ctx() { return this.toolbarService.context; } /** * @hidden */ dateRangeText = { short: '', long: '', current: '' }; /** * @hidden */ svgIcon(name) { return iconsMap[name]; } popupRef; subs; isMouseDown = false; constructor(popupService, toolbarService, localization, cd, viewContext) { this.popupService = popupService; this.toolbarService = toolbarService; this.localization = localization; this.cd = cd; this.viewContext = viewContext; this.subs = this.localization.changes.subscribe(() => { cd.markForCheck(); }); } /** * @hidden */ onBlur() { this.isMouseDown ? null : this.closePopup(); } /** * @hidden */ onMouseDown() { this.isMouseDown = true; } ngOnInit() { if (!isDocumentAvailable()) { return; } this.subs.add(this.ctx.dateRange.subscribe(res => { this.dateRangeText.short = res?.shortText; this.dateRangeText.long = res?.text; this.setDateRangeText(); })); this.subs.add(this.viewContext.resize.subscribe(() => { this.setDateRangeText(); })); } ngOnDestroy() { this.subs.unsubscribe(); this.closePopup(); } /** * @hidden */ toggleSelectedDate(anchor, template) { if (this.popupRef) { this.closePopup(); } else { const popupSettings = { anchor: anchor, content: template }; if (this.localization.rtl) { popupSettings.popupClass = 'k-rtl'; } this.popupRef = this.popupService.open(popupSettings); } this.isMouseDown = false; return false; } /** * @hidden */ selectDate(value) { this.closePopup(); this.toolbarService.navigate({ type: 'select-date', date: value }); } /** * @hidden */ prevClick() { this.toolbarService.navigate({ type: 'prev' }); return false; } /** * @hidden */ nextClick() { this.toolbarService.navigate({ type: 'next' }); return false; } /** * @hidden */ todayClick() { this.toolbarService.navigate({ type: 'today' }); return false; } closePopup() { if (this.popupRef) { this.popupRef.close(); this.popupRef = null; } } setDateRangeText() { const isDesktop = window.matchMedia('(min-width: 1024px)').matches; this.dateRangeText.current = isDesktop ? this.dateRangeText.long : this.dateRangeText.short; this.cd.detectChanges(); } get arrowIcons() { return !this.localization.rtl ? ['caret-alt-left', 'caret-alt-right'] : ['caret-alt-right', 'caret-alt-left']; } get arrowSVGIcons() { return !this.localization.rtl ? ['caretAltLeftIcon', 'caretAltRightIcon'] : ['caretAltRightIcon', 'caretAltLeftIcon']; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolbarNavigationComponent, deps: [{ token: i1.PopupService }, { token: i2.ToolbarService }, { token: i3.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i4.ViewContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ToolbarNavigationComponent, isStandalone: true, selector: "[kendoSchedulerToolbarNavigation]", inputs: { min: "min", max: "max", activeView: "activeView", bottomView: "bottomView" }, host: { properties: { "class.k-toolbar-group": "this.hostClass" } }, providers: [ PopupService ], viewQueries: [{ propertyName: "calendar", first: true, predicate: ["calendar"], descendants: true }], ngImport: i0, template: ` <span class="k-scheduler-navigation k-button-group k-button-group-solid" role="group"> <button kendoButton (click)="todayClick()" class="k-nav-today" [attr.title]="todayText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> {{todayText}} </button> <button kendoButton (click)="prevClick()" class="k-nav-prev" [icon]="arrowIcons[0]" [svgIcon]="svgIcon(arrowSVGIcons[0])" [attr.title]="previousText" [attr.aria-label]="previousText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> </button> <button kendoButton (click)="nextClick()" type="button" class="k-nav-next" [icon]="arrowIcons[1]" [svgIcon]="svgIcon(arrowSVGIcons[1])" [attr.title]="nextText" [attr.aria-label]="nextText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> </button> </span> <button #anchor kendoButton type="button" icon="calendar" [svgIcon]="svgIcon('calendarIcon')" fillMode="flat" (mousedown)="onMouseDown()" (mouseup)="toggleSelectedDate({ nativeElement: anchor.element }, template)" (keydown.enter)="toggleSelectedDate({ nativeElement: anchor.element }, template)" (keydown.alt.arrowdown)="toggleSelectedDate({ nativeElement: anchor.element }, template)" role="button" class="k-nav-current" [attr.aria-live]="'polite'" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> <span>{{ dateRangeText?.current }}</span> </button> <ng-template #template> <kendo-calendar #calendar (blur)="onBlur()" [activeView]="activeView" [bottomView]="bottomView" (keydown.escape)="toggleSelectedDate({ nativeElement: anchor }, template); anchor.focus();" (valueChange)="selectDate($event)" [value]="ctx.selectedDate | async" [min]="min" [max]="max"> <kendo-calendar-messages [today]="calendarTodayText"> </kendo-calendar-messages> </kendo-calendar> </ng-template> `, isInline: true, dependencies: [{ kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: FocusableDirective, selector: "[kendoSchedulerFocusIndex]", inputs: ["kendoSchedulerFocusIndex", "containerType"] }, { kind: "component", type: CalendarComponent, selector: "kendo-calendar", inputs: ["showOtherMonthDays", "id", "focusedDate", "min", "max", "rangeValidation", "weekDaysFormat", "footer", "selection", "allowReverse", "value", "disabled", "tabindex", "tabIndex", "disabledDates", "navigation", "activeView", "bottomView", "topView", "type", "animateNavigation", "weekNumber", "cellTemplate", "monthCellTemplate", "yearCellTemplate", "decadeCellTemplate", "centuryCellTemplate", "weekNumberTemplate", "headerTitleTemplate", "headerTemplate", "footerTemplate", "navigationItemTemplate", "size", "activeRangeEnd"], outputs: ["activeViewChange", "navigate", "activeViewDateChange", "blur", "focus", "valueChange"], exportAs: ["kendo-calendar"] }, { kind: "component", type: CalendarCustomMessagesComponent, selector: "kendo-calendar-messages" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolbarNavigationComponent, decorators: [{ type: Component, args: [{ // eslint-disable-next-line @angular-eslint/component-selector selector: '[kendoSchedulerToolbarNavigation]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ PopupService ], template: ` <span class="k-scheduler-navigation k-button-group k-button-group-solid" role="group"> <button kendoButton (click)="todayClick()" class="k-nav-today" [attr.title]="todayText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> {{todayText}} </button> <button kendoButton (click)="prevClick()" class="k-nav-prev" [icon]="arrowIcons[0]" [svgIcon]="svgIcon(arrowSVGIcons[0])" [attr.title]="previousText" [attr.aria-label]="previousText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> </button> <button kendoButton (click)="nextClick()" type="button" class="k-nav-next" [icon]="arrowIcons[1]" [svgIcon]="svgIcon(arrowSVGIcons[1])" [attr.title]="nextText" [attr.aria-label]="nextText" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> </button> </span> <button #anchor kendoButton type="button" icon="calendar" [svgIcon]="svgIcon('calendarIcon')" fillMode="flat" (mousedown)="onMouseDown()" (mouseup)="toggleSelectedDate({ nativeElement: anchor.element }, template)" (keydown.enter)="toggleSelectedDate({ nativeElement: anchor.element }, template)" (keydown.alt.arrowdown)="toggleSelectedDate({ nativeElement: anchor.element }, template)" role="button" class="k-nav-current" [attr.aria-live]="'polite'" [kendoSchedulerFocusIndex]="0" containerType="toolbar"> <span>{{ dateRangeText?.current }}</span> </button> <ng-template #template> <kendo-calendar #calendar (blur)="onBlur()" [activeView]="activeView" [bottomView]="bottomView" (keydown.escape)="toggleSelectedDate({ nativeElement: anchor }, template); anchor.focus();" (valueChange)="selectDate($event)" [value]="ctx.selectedDate | async" [min]="min" [max]="max"> <kendo-calendar-messages [today]="calendarTodayText"> </kendo-calendar-messages> </kendo-calendar> </ng-template> `, standalone: true, imports: [ButtonComponent, FocusableDirective, CalendarComponent, CalendarCustomMessagesComponent, AsyncPipe] }] }], ctorParameters: function () { return [{ type: i1.PopupService }, { type: i2.ToolbarService }, { type: i3.LocalizationService }, { type: i0.ChangeDetectorRef }, { type: i4.ViewContextService }]; }, propDecorators: { calendar: [{ type: ViewChild, args: ['calendar', { static: false }] }], hostClass: [{ type: HostBinding, args: ['class.k-toolbar-group'] }], min: [{ type: Input }], max: [{ type: Input }], activeView: [{ type: Input }], bottomView: [{ type: Input }] } });