104 lines
3.1 KiB
TypeScript
104 lines
3.1 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 {
|
|
Directive,
|
|
Input,
|
|
ContentChildren,
|
|
QueryList,
|
|
AfterContentInit,
|
|
OnDestroy,
|
|
booleanAttribute,
|
|
} from '@angular/core';
|
|
import {CdkAccordion} from '@angular/cdk/accordion';
|
|
import {FocusKeyManager} from '@angular/cdk/a11y';
|
|
import {startWith} from 'rxjs/operators';
|
|
import {
|
|
MAT_ACCORDION,
|
|
MatAccordionBase,
|
|
MatAccordionDisplayMode,
|
|
MatAccordionTogglePosition,
|
|
} from './accordion-base';
|
|
import {MatExpansionPanelHeader} from './expansion-panel-header';
|
|
|
|
/**
|
|
* Directive for a Material Design Accordion.
|
|
*/
|
|
@Directive({
|
|
selector: 'mat-accordion',
|
|
exportAs: 'matAccordion',
|
|
providers: [
|
|
{
|
|
provide: MAT_ACCORDION,
|
|
useExisting: MatAccordion,
|
|
},
|
|
],
|
|
host: {
|
|
class: 'mat-accordion',
|
|
// Class binding which is only used by the test harness as there is no other
|
|
// way for the harness to detect if multiple panel support is enabled.
|
|
'[class.mat-accordion-multi]': 'this.multi',
|
|
},
|
|
})
|
|
export class MatAccordion
|
|
extends CdkAccordion
|
|
implements MatAccordionBase, AfterContentInit, OnDestroy
|
|
{
|
|
private _keyManager: FocusKeyManager<MatExpansionPanelHeader>;
|
|
|
|
/** Headers belonging to this accordion. */
|
|
private _ownHeaders = new QueryList<MatExpansionPanelHeader>();
|
|
|
|
/** All headers inside the accordion. Includes headers inside nested accordions. */
|
|
@ContentChildren(MatExpansionPanelHeader, {descendants: true})
|
|
_headers: QueryList<MatExpansionPanelHeader>;
|
|
|
|
/** Whether the expansion indicator should be hidden. */
|
|
@Input({transform: booleanAttribute})
|
|
hideToggle: boolean = false;
|
|
|
|
/**
|
|
* Display mode used for all expansion panels in the accordion. Currently two display
|
|
* modes exist:
|
|
* default - a gutter-like spacing is placed around any expanded panel, placing the expanded
|
|
* panel at a different elevation from the rest of the accordion.
|
|
* flat - no spacing is placed around expanded panels, showing all panels at the same
|
|
* elevation.
|
|
*/
|
|
@Input() displayMode: MatAccordionDisplayMode = 'default';
|
|
|
|
/** The position of the expansion indicator. */
|
|
@Input() togglePosition: MatAccordionTogglePosition = 'after';
|
|
|
|
ngAfterContentInit() {
|
|
this._headers.changes
|
|
.pipe(startWith(this._headers))
|
|
.subscribe((headers: QueryList<MatExpansionPanelHeader>) => {
|
|
this._ownHeaders.reset(headers.filter(header => header.panel.accordion === this));
|
|
this._ownHeaders.notifyOnChanges();
|
|
});
|
|
|
|
this._keyManager = new FocusKeyManager(this._ownHeaders).withWrap().withHomeAndEnd();
|
|
}
|
|
|
|
/** Handles keyboard events coming in from the panel headers. */
|
|
_handleHeaderKeydown(event: KeyboardEvent) {
|
|
this._keyManager.onKeydown(event);
|
|
}
|
|
|
|
_handleHeaderFocus(header: MatExpansionPanelHeader) {
|
|
this._keyManager.updateActiveItem(header);
|
|
}
|
|
|
|
override ngOnDestroy() {
|
|
super.ngOnDestroy();
|
|
this._keyManager?.destroy();
|
|
this._ownHeaders.destroy();
|
|
}
|
|
}
|