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.

126 lines (125 loc) 5.84 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Directive, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; import { Subscription } from 'rxjs'; import { intersects, isSameRange, resourcesMatch } from '../utils'; import { SchedulerComponent } from '../../scheduler.component'; import { distinctUntilChanged, filter } from 'rxjs/operators'; import { isChanged } from '@progress/kendo-angular-common'; import * as i0 from "@angular/core"; import * as i1 from "../../scheduler.component"; /** * A directive which manages the in-memory selection state of the Scheduler slots * ([see example]({% slug slotselection_scheduler %}#toc-built-in-directive)). */ export class SlotSelectableDirective { scheduler; cdr; /** * The currently selected slot range. */ slotSelection; /** * Fires when the currently selected slot range has changed through user interaction. */ slotSelectionChange = new EventEmitter(); /** * @hidden * The resources of the cell where the selection started. * When dragging over the slots of a different resource in grouped mode, the ongoing selection will not be affected. */ selectionOriginResources; selectedRange = null; slotSelectionChangeSource = new EventEmitter(); subscriptions = new Subscription(); constructor(scheduler, cdr) { this.scheduler = scheduler; this.cdr = cdr; this.scheduler.selectable = true; this.subscriptions.add(this.slotSelectionChangeSource .pipe(distinctUntilChanged(isSameRange)).subscribe((v) => { this.slotSelectionChange.emit(v); })); const start$ = this.scheduler.slotDragStart; const drag$ = this.scheduler.slotDrag; const end$ = this.scheduler.slotDragEnd; const startSource = start$.pipe(filter(e => !e.isDefaultPrevented())); this.subscriptions.add(startSource.subscribe(e => this.initDragSelect(e))); this.subscriptions.add(drag$.subscribe(e => this.onDrag(e))); this.subscriptions.add(end$.subscribe(() => this.onRelease())); } ngOnInit() { this.scheduler.isSlotSelected = this.isSlotSelected.bind(this); } ngOnChanges(changes) { if (isChanged("slotSelection", changes, false)) { const defaults = { isAllDay: false, resources: this.scheduler?.resources ? this.scheduler.resources.reduce((result, resource) => { result.push(...resource.data); return result; }, []) : [] }; this.selectedRange = Object.assign(defaults, changes['slotSelection'].currentValue); this.cdr.markForCheck(); } } ngOnDestroy() { this.subscriptions.unsubscribe(); } isSlotSelected({ start, end, isAllDay, resources }) { if (!start || !end || !this.selectedRange) { return false; } const match = resourcesMatch(this.selectedRange.resources, resources); if (!match) { return false; // Limit selection to the grouped resource where the drag started. } return this.selectedRange && isAllDay === this.selectedRange.isAllDay && this.isInRange(start, end); } initDragSelect({ start, end, isAllDay, resources }) { this.selectionOriginResources = resources.slice(); this.selectedRange = { start, end, isAllDay, resources: resources.slice() }; this.cdr.markForCheck(); } onDrag({ start, end, resources }) { const match = resourcesMatch(this.selectionOriginResources, resources); if (!match) { return; // Don't change selection when dragging over a different grouped resource's cells. } this.selectedRange.start = start; this.selectedRange.end = end; this.cdr.markForCheck(); } onRelease() { this.selectionOriginResources = null; if (this.selectedRange) { this.slotSelectionChangeSource.emit(this.selectedRange); } } /** * @hidden * Checks if the selected range contains a local date range. */ isInRange(start, end) { if (!this.selectedRange) { return; } return intersects(start, end, this.selectedRange.start, this.selectedRange.end); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SlotSelectableDirective, deps: [{ token: i1.SchedulerComponent }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SlotSelectableDirective, isStandalone: true, selector: "[kendoSchedulerSlotSelectable]", inputs: { slotSelection: "slotSelection" }, outputs: { slotSelectionChange: "slotSelectionChange" }, usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SlotSelectableDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoSchedulerSlotSelectable]', standalone: true }] }], ctorParameters: function () { return [{ type: i1.SchedulerComponent }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { slotSelection: [{ type: Input }], slotSelectionChange: [{ type: Output }] } });