UNPKG

@progress/kendo-angular-dateinputs

Version:

Kendo UI for Angular Date Inputs Package - Everything you need to add date selection functionality to apps (DatePicker, TimePicker, DateInput, DateRangePicker, DateTimePicker, Calendar, and MultiViewCalendar).

226 lines (225 loc) 8.74 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Injectable, Renderer2, Optional } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { EMPTY_SELECTIONRANGE } from '../calendar/models/selection-range.interface'; import { isEqual } from '@progress/kendo-date-math'; import { attributeNames } from '../common/utils'; import * as i0 from "@angular/core"; const isActive = (cmp) => (cmp && cmp.isActive) || false; const hasActiveContent = (popup) => popup && popup.hasActiveContent(); /** * A service that handles the communication between the components that are placed inside the DateRangeComponent. * For example, the start and end `DateInput` and `DateRangePopup` components. */ export class DateRangeService { renderer; /** * An Observable instance that notifies when the `activeRangeEnd` state is changed. */ activeRangeEnd$ = new BehaviorSubject(null); /** * An Observable instance that notifies when the `focusedDate` is changed. */ focusedDate$ = new BehaviorSubject(null); /** * An Observable instance that notifies when the end `DateInput` component is changed. * For example, when a new end `DateInput` is attached or when the old one is detached. */ endInput$ = new BehaviorSubject(null); /** * An Observable instance that notifies when the start `DateInput` component is changed. * For example, when a new start `DateInput` is attached or the old one is detached. */ startInput$ = new BehaviorSubject(null); /** * An Observable instance that notifies when the `DateRangePopup` component is changed. */ dateRangePopup$ = new BehaviorSubject(null); /** * An Observable instance that notifies when the state of the selection range is changed. */ range$ = new BehaviorSubject(EMPTY_SELECTIONRANGE); /** * Gets the current `activeRangeEnd` value. */ get activeRangeEnd() { return this.activeRangeEnd$.value; } /** * Gets the current `focusedDate` value. */ get focusedDate() { return this.focusedDate$.value; } /** * Gets the `min` range value. * The `min` value is extracted from the `start` DateInput value or the `min` value of the Calendar. */ get min() { return (this.startInput$.value || {}).min || null; } /** * Gets the `max` range value. * The `max` value is extracted from the `end` DateInput value or the `max` value of the Calendar. */ get max() { return (this.endInput$.value || {}).max || null; } /** * Gets the current `selectionRange` value. */ get selectionRange() { return this.range$.value; } /** * @hidden * Gets the start input element. */ get inputStartElement() { return this.startInput$.value.inputElement; } /** * @hidden * Gets the end input element. */ get inputEndElement() { return this.endInput$.value.inputElement; } /** @hidden */ constructor(renderer) { this.renderer = renderer; } /** * Activates the registered `DateRangePopup` component. * The method opens the popup and focuses the calendar. */ activatePopup() { const dateRangePopup = this.dateRangePopup$.value; if (!dateRangePopup) { return; } if (this.startInput$.value) { this.renderer.setAttribute(this.inputStartElement, attributeNames.ariaControls, dateRangePopup.popupUID); this.renderer.setAttribute(this.inputStartElement, attributeNames.ariaExpanded, 'true'); this.renderer.setAttribute(this.inputEndElement, attributeNames.ariaControls, dateRangePopup.popupUID); this.renderer.setAttribute(this.inputEndElement, attributeNames.ariaExpanded, 'true'); } dateRangePopup.activate(); } /** * Deactivates the registered `DateRangePopup` component. * The method closes the popup. */ deactivatePopup() { const dateRangePopup = this.dateRangePopup$.value; if (this.startInput$.value) { this.renderer.removeAttribute(this.inputStartElement, attributeNames.ariaControls); this.renderer.setAttribute(this.inputStartElement, attributeNames.ariaExpanded, 'false'); this.renderer.removeAttribute(this.inputStartElement, attributeNames.ariaActiveDescendant); this.renderer.removeAttribute(this.inputEndElement, attributeNames.ariaControls); this.renderer.setAttribute(this.inputEndElement, attributeNames.ariaExpanded, 'false'); this.renderer.removeAttribute(this.inputEndElement, attributeNames.ariaActiveDescendant); } if (!(dateRangePopup && dateRangePopup.show)) { return; } dateRangePopup.show = false; } /** * @hidden */ setActiveDescendent(id) { this.renderer.setAttribute(this.inputStartElement, attributeNames.ariaActiveDescendant, id); this.renderer.setAttribute(this.inputEndElement, attributeNames.ariaActiveDescendant, id); } /** * @hidden * * Deactivates the registered `DateRangePopup` component and fires the `cancel` event. * The method closes the popup. */ cancelPopup() { const dateRangePopup = this.dateRangePopup$.value; if (!(dateRangePopup && dateRangePopup.show)) { return; } dateRangePopup.cancelPopup(); } /** * Completes all observables to mitigate possible memory leaks. * Calls the method when a component that uses it is destroyed. */ destroy() { this.activeRangeEnd$.complete(); this.dateRangePopup$.complete(); this.focusedDate$.complete(); this.endInput$.complete(); this.startInput$.complete(); this.range$.complete(); } /** * Returns `true` when an active component that is placed inside the `DateRangeComponent` is detected. * For example, the opened popup or the focused DateInput. * * @returns `true` if an active component is present. */ hasActiveComponent() { const popup = this.dateRangePopup$.value; const isPopup = isActive(popup); const isStart = isActive(this.startInput$.value); const isEnd = isActive(this.endInput$.value); return isPopup || isStart || isEnd || hasActiveContent(popup) || false; } /** * Registers a new start `DateInput` component. Notifies all `startInput$` listeners. */ registerStartInput(startInput) { this.startInput$.next(startInput); } /** * Registers a new end `DateInput` component. Notifies all `endInput$` listeners. */ registerEndInput(endInput) { this.endInput$.next(endInput); } /** * Registers a new `DateRangePopup` component. Notifies all `dateRangePopup$` listeners. */ registerPopup(dateRangePopup) { this.dateRangePopup$.next(dateRangePopup); } /** * Updates the `activeRangeEnd` value. Notifies all `activeRangeEnd$` listeners. */ setActiveRangeEnd(activeRange) { if (!activeRange || this.activeRangeEnd === activeRange) { return; } this.activeRangeEnd$.next(activeRange); } /** * Updates the focused date. Notifies all `focusedDate$` listeners. */ setFocusedDate(value) { if (isEqual(this.focusedDate$.value, value)) { return; } this.focusedDate$.next(value); } /** * Updates the selection range. Notifies all `range$` listeners. */ setRange(range = EMPTY_SELECTIONRANGE) { this.range$.next(range); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DateRangeService, deps: [{ token: i0.Renderer2, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DateRangeService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DateRangeService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i0.Renderer2, decorators: [{ type: Optional }] }]; } });