sass-references/angular-material/material/bottom-sheet/bottom-sheet-container.ts

127 lines
3.9 KiB
TypeScript
Raw Normal View History

2024-12-06 10:42:08 +08:00
/**
* @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 {AnimationEvent} from '@angular/animations';
import {CdkDialogContainer} from '@angular/cdk/dialog';
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
OnDestroy,
ViewEncapsulation,
inject,
} from '@angular/core';
import {Subscription} from 'rxjs';
import {matBottomSheetAnimations} from './bottom-sheet-animations';
import {CdkPortalOutlet} from '@angular/cdk/portal';
/**
* Internal component that wraps user-provided bottom sheet content.
* @docs-private
*/
@Component({
selector: 'mat-bottom-sheet-container',
templateUrl: 'bottom-sheet-container.html',
styleUrl: 'bottom-sheet-container.css',
// In Ivy embedded views will be change detected from their declaration place, rather than where
// they were stamped out. This means that we can't have the bottom sheet container be OnPush,
// because it might cause the sheets that were opened from a template not to be out of date.
// tslint:disable-next-line:validate-decorators
changeDetection: ChangeDetectionStrategy.Default,
encapsulation: ViewEncapsulation.None,
animations: [matBottomSheetAnimations.bottomSheetState],
host: {
'class': 'mat-bottom-sheet-container',
'tabindex': '-1',
'[attr.role]': '_config.role',
'[attr.aria-modal]': '_config.ariaModal',
'[attr.aria-label]': '_config.ariaLabel',
'[@state]': '_animationState',
'(@state.start)': '_onAnimationStart($event)',
'(@state.done)': '_onAnimationDone($event)',
},
imports: [CdkPortalOutlet],
})
export class MatBottomSheetContainer extends CdkDialogContainer implements OnDestroy {
private _breakpointSubscription: Subscription;
/** The state of the bottom sheet animations. */
_animationState: 'void' | 'visible' | 'hidden' = 'void';
/** Emits whenever the state of the animation changes. */
_animationStateChanged = new EventEmitter<AnimationEvent>();
/** Whether the component has been destroyed. */
private _destroyed: boolean;
constructor(...args: unknown[]);
constructor() {
super();
const breakpointObserver = inject(BreakpointObserver);
this._breakpointSubscription = breakpointObserver
.observe([Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
.subscribe(() => {
const classList = (this._elementRef.nativeElement as HTMLElement).classList;
classList.toggle(
'mat-bottom-sheet-container-medium',
breakpointObserver.isMatched(Breakpoints.Medium),
);
classList.toggle(
'mat-bottom-sheet-container-large',
breakpointObserver.isMatched(Breakpoints.Large),
);
classList.toggle(
'mat-bottom-sheet-container-xlarge',
breakpointObserver.isMatched(Breakpoints.XLarge),
);
});
}
/** Begin animation of bottom sheet entrance into view. */
enter(): void {
if (!this._destroyed) {
this._animationState = 'visible';
this._changeDetectorRef.markForCheck();
this._changeDetectorRef.detectChanges();
}
}
/** Begin animation of the bottom sheet exiting from view. */
exit(): void {
if (!this._destroyed) {
this._animationState = 'hidden';
this._changeDetectorRef.markForCheck();
}
}
override ngOnDestroy() {
super.ngOnDestroy();
this._breakpointSubscription.unsubscribe();
this._destroyed = true;
}
_onAnimationDone(event: AnimationEvent) {
if (event.toState === 'visible') {
this._trapFocus();
}
this._animationStateChanged.emit(event);
}
_onAnimationStart(event: AnimationEvent) {
this._animationStateChanged.emit(event);
}
protected override _captureInitialFocus(): void {}
}