/
githubmirror
/
components
Обзор
Документация
Войти
/
githubmirror
/
components
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/material/datepicker/date-selection-model.ts
237 строк
7 KB
Kristiyan Kostadinov
refactor(material/datepicker): fix strict property initialization errors
16 дек 2025, 18:38
16 дек 2025, 18:38
4382f74
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import {FactoryProvider, Injectable, OnDestroy, inject} from '@angular/core'; import {DateAdapter} from '../core'; import {Observable, Subject} from 'rxjs'; /** A class representing a range of dates. */ export class DateRange<D> { /** * Ensures that objects with a `start` and `end` property can't be assigned to a variable that * expects a `DateRange` */ // tslint:disable-next-line:no-unused-variable private _disableStructuralEquivalency!: never; constructor( /** The start date of the range. */ readonly start: D | null, /** The end date of the range. */ readonly end: D | null, ) {} } /** * Conditionally picks the date type, if a DateRange is passed in. * @docs-private */ export type ExtractDateTypeFromSelection<T> = T extends DateRange<infer D> ? D : NonNullable<T>; /** * Event emitted by the date selection model when its selection changes. * @docs-private */ export interface DateSelectionModelChange<S> { /** New value for the selection. */ selection: S; /** Object that triggered the change. */ source: unknown; /** Previous value */ oldValue?: S; } /** * A selection model containing a date selection. * @docs-private */ @Injectable() export abstract class MatDateSelectionModel< S, D = ExtractDateTypeFromSelection<S>, > implements OnDestroy { private readonly _selectionChanged = new Subject<DateSelectionModelChange<S>>(); /** Emits when the selection has changed. */ selectionChanged: Observable<DateSelectionModelChange<S>> = this._selectionChanged; protected constructor( /** The current selection. */ readonly selection: S, protected _adapter: DateAdapter<D>, ) { this.selection = selection; } /** * Updates the current selection in the model. * @param value New selection that should be assigned. * @param source Object that triggered the selection change. */ updateSelection(value: S, source: unknown) { const oldValue = (this as {selection: S}).selection; (this as {selection: S}).selection = value; this._selectionChanged.next({selection: value, source, oldValue}); } ngOnDestroy() { this._selectionChanged.complete(); } protected _isValidDateInstance(date: D): boolean { return this._adapter.isDateInstance(date) && this._adapter.isValid(date); } /** Adds a date to the current selection. */ abstract add(date: D | null): void; /** Checks whether the current selection is valid. */ abstract isValid(): boolean; /** Checks whether the current selection is complete. */ abstract isComplete(): boolean; /** Clones the selection model. */ abstract clone(): MatDateSelectionModel<S, D>; } /** * A selection model that contains a single date. * @docs-private */ @Injectable() export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D | null, D> { constructor(adapter: DateAdapter<D>) { super(null, adapter); } /** * Adds a date to the current selection. In the case of a single date selection, the added date * simply overwrites the previous selection */ add(date: D | null) { super.updateSelection(date, this); } /** Checks whether the current selection is valid. */ isValid(): boolean { return this.selection != null && this._isValidDateInstance(this.selection); } /** * Checks whether the current selection is complete. In the case of a single date selection, this * is true if the current selection is not null. */ isComplete() { return this.selection != null; } /** Clones the selection model. */ clone() { const clone = new MatSingleDateSelectionModel<D>(this._adapter); clone.updateSelection(this.selection, this); return clone; } } /** * A selection model that contains a date range. * @docs-private */ @Injectable() export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<DateRange<D>, D> { constructor(adapter: DateAdapter<D>) { super(new DateRange<D>(null, null), adapter); } /** * Adds a date to the current selection. In the case of a date range selection, the added date * fills in the next `null` value in the range. If both the start and the end already have a date, * the selection is reset so that the given date is the new `start` and the `end` is null. */ add(date: D | null): void { let {start, end} = this.selection; if (start == null) { start = date; } else if (end == null) { end = date; } else { start = date; end = null; } super.updateSelection(new DateRange<D>(start, end), this); } /** Checks whether the current selection is valid. */ isValid(): boolean { const {start, end} = this.selection; // Empty ranges are valid. if (start == null && end == null) { return true; } // Complete ranges are only valid if both dates are valid and the start is before the end. if (start != null && end != null) { return ( this._isValidDateInstance(start) && this._isValidDateInstance(end) && this._adapter.compareDate(start, end) <= 0 ); } // Partial ranges are valid if the start/end is valid. return ( (start == null || this._isValidDateInstance(start)) && (end == null || this._isValidDateInstance(end)) ); } /** * Checks whether the current selection is complete. In the case of a date range selection, this * is true if the current selection has a non-null `start` and `end`. */ isComplete(): boolean { return this.selection.start != null && this.selection.end != null; } /** Clones the selection model. */ clone() { const clone = new MatRangeDateSelectionModel<D>(this._adapter); clone.updateSelection(this.selection, this); return clone; } } /** * Used to provide a single selection model to a component. * @docs-private */ export const MAT_SINGLE_DATE_SELECTION_MODEL_PROVIDER: FactoryProvider = { provide: MatDateSelectionModel, useFactory: () => { const parent = inject(MatDateSelectionModel, {optional: true, skipSelf: true}); return parent || new MatSingleDateSelectionModel(inject(DateAdapter)); }, }; /** * Used to provide a range selection model to a component. * @docs-private */ export const MAT_RANGE_DATE_SELECTION_MODEL_PROVIDER: FactoryProvider = { provide: MatDateSelectionModel, useFactory: () => { const parent = inject(MatDateSelectionModel, {optional: true, skipSelf: true}); return parent || new MatRangeDateSelectionModel(inject(DateAdapter)); }, };