sass-references/angular-material/material/datepicker/datepicker-toggle.ts

144 lines
4.4 KiB
TypeScript

/**
* @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 {
AfterContentInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChild,
Directive,
Input,
OnChanges,
OnDestroy,
SimpleChanges,
ViewEncapsulation,
ViewChild,
booleanAttribute,
inject,
HostAttributeToken,
} from '@angular/core';
import {MatButton, MatIconButton} from '@angular/material/button';
import {merge, Observable, of as observableOf, Subscription} from 'rxjs';
import {MatDatepickerIntl} from './datepicker-intl';
import {MatDatepickerControl, MatDatepickerPanel} from './datepicker-base';
/** Can be used to override the icon of a `matDatepickerToggle`. */
@Directive({
selector: '[matDatepickerToggleIcon]',
})
export class MatDatepickerToggleIcon {}
@Component({
selector: 'mat-datepicker-toggle',
templateUrl: 'datepicker-toggle.html',
styleUrl: 'datepicker-toggle.css',
host: {
'class': 'mat-datepicker-toggle',
'[attr.tabindex]': 'null',
'[class.mat-datepicker-toggle-active]': 'datepicker && datepicker.opened',
'[class.mat-accent]': 'datepicker && datepicker.color === "accent"',
'[class.mat-warn]': 'datepicker && datepicker.color === "warn"',
// Used by the test harness to tie this toggle to its datepicker.
'[attr.data-mat-calendar]': 'datepicker ? datepicker.id : null',
// Bind the `click` on the host, rather than the inner `button`, so that we can call
// `stopPropagation` on it without affecting the user's `click` handlers. We need to stop
// it so that the input doesn't get focused automatically by the form field (See #21836).
'(click)': '_open($event)',
},
exportAs: 'matDatepickerToggle',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [MatIconButton],
})
export class MatDatepickerToggle<D> implements AfterContentInit, OnChanges, OnDestroy {
_intl = inject(MatDatepickerIntl);
private _changeDetectorRef = inject(ChangeDetectorRef);
private _stateChanges = Subscription.EMPTY;
/** Datepicker instance that the button will toggle. */
@Input('for') datepicker: MatDatepickerPanel<MatDatepickerControl<any>, D>;
/** Tabindex for the toggle. */
@Input() tabIndex: number | null;
/** Screen-reader label for the button. */
@Input('aria-label') ariaLabel: string;
/** Whether the toggle button is disabled. */
@Input({transform: booleanAttribute})
get disabled(): boolean {
if (this._disabled === undefined && this.datepicker) {
return this.datepicker.disabled;
}
return !!this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
private _disabled: boolean;
/** Whether ripples on the toggle should be disabled. */
@Input() disableRipple: boolean;
/** Custom icon set by the consumer. */
@ContentChild(MatDatepickerToggleIcon) _customIcon: MatDatepickerToggleIcon;
/** Underlying button element. */
@ViewChild('button') _button: MatButton;
constructor(...args: unknown[]);
constructor() {
const defaultTabIndex = inject(new HostAttributeToken('tabindex'), {optional: true});
const parsedTabIndex = Number(defaultTabIndex);
this.tabIndex = parsedTabIndex || parsedTabIndex === 0 ? parsedTabIndex : null;
}
ngOnChanges(changes: SimpleChanges) {
if (changes['datepicker']) {
this._watchStateChanges();
}
}
ngOnDestroy() {
this._stateChanges.unsubscribe();
}
ngAfterContentInit() {
this._watchStateChanges();
}
_open(event: Event): void {
if (this.datepicker && !this.disabled) {
this.datepicker.open();
event.stopPropagation();
}
}
private _watchStateChanges() {
const datepickerStateChanged = this.datepicker ? this.datepicker.stateChanges : observableOf();
const inputStateChanged =
this.datepicker && this.datepicker.datepickerInput
? this.datepicker.datepickerInput.stateChanges
: observableOf();
const datepickerToggled = this.datepicker
? merge(this.datepicker.openedStream, this.datepicker.closedStream)
: observableOf();
this._stateChanges.unsubscribe();
this._stateChanges = merge(
this._intl.changes,
datepickerStateChanged as Observable<void>,
inputStateChanged,
datepickerToggled,
).subscribe(() => this._changeDetectorRef.markForCheck());
}
}