[6a3a178] | 1 | import { CdkAccordionItem, CdkAccordion, CdkAccordionModule } from '@angular/cdk/accordion';
|
---|
| 2 | import { TemplatePortal, PortalModule } from '@angular/cdk/portal';
|
---|
| 3 | import { DOCUMENT, CommonModule } from '@angular/common';
|
---|
| 4 | import { InjectionToken, Directive, TemplateRef, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, Optional, SkipSelf, Inject, ChangeDetectorRef, ViewContainerRef, Input, Output, ContentChild, ViewChild, Host, ElementRef, Attribute, QueryList, ContentChildren, NgModule } from '@angular/core';
|
---|
| 5 | import { mixinTabIndex, MatCommonModule } from '@angular/material/core';
|
---|
| 6 | import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
---|
| 7 | import { FocusMonitor, FocusKeyManager } from '@angular/cdk/a11y';
|
---|
| 8 | import { distinctUntilChanged, startWith, filter, take } from 'rxjs/operators';
|
---|
| 9 | import { ENTER, hasModifierKey, SPACE } from '@angular/cdk/keycodes';
|
---|
| 10 | import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
|
---|
| 11 | import { Subject, Subscription, EMPTY, merge } from 'rxjs';
|
---|
| 12 | import { trigger, state, style, transition, animate } from '@angular/animations';
|
---|
| 13 | import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
|
---|
| 14 |
|
---|
| 15 | /**
|
---|
| 16 | * @license
|
---|
| 17 | * Copyright Google LLC All Rights Reserved.
|
---|
| 18 | *
|
---|
| 19 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 20 | * found in the LICENSE file at https://angular.io/license
|
---|
| 21 | */
|
---|
| 22 | /**
|
---|
| 23 | * Token used to provide a `MatAccordion` to `MatExpansionPanel`.
|
---|
| 24 | * Used primarily to avoid circular imports between `MatAccordion` and `MatExpansionPanel`.
|
---|
| 25 | */
|
---|
| 26 | const MAT_ACCORDION = new InjectionToken('MAT_ACCORDION');
|
---|
| 27 |
|
---|
| 28 | /**
|
---|
| 29 | * @license
|
---|
| 30 | * Copyright Google LLC All Rights Reserved.
|
---|
| 31 | *
|
---|
| 32 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 33 | * found in the LICENSE file at https://angular.io/license
|
---|
| 34 | */
|
---|
| 35 | /** Time and timing curve for expansion panel animations. */
|
---|
| 36 | // Note: Keep this in sync with the Sass variable for the panel header animation.
|
---|
| 37 | const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,1)';
|
---|
| 38 | /**
|
---|
| 39 | * Animations used by the Material expansion panel.
|
---|
| 40 | *
|
---|
| 41 | * A bug in angular animation's `state` when ViewContainers are moved using ViewContainerRef.move()
|
---|
| 42 | * causes the animation state of moved components to become `void` upon exit, and not update again
|
---|
| 43 | * upon reentry into the DOM. This can lead a to situation for the expansion panel where the state
|
---|
| 44 | * of the panel is `expanded` or `collapsed` but the animation state is `void`.
|
---|
| 45 | *
|
---|
| 46 | * To correctly handle animating to the next state, we animate between `void` and `collapsed` which
|
---|
| 47 | * are defined to have the same styles. Since angular animates from the current styles to the
|
---|
| 48 | * destination state's style definition, in situations where we are moving from `void`'s styles to
|
---|
| 49 | * `collapsed` this acts a noop since no style values change.
|
---|
| 50 | *
|
---|
| 51 | * In the case where angular's animation state is out of sync with the expansion panel's state, the
|
---|
| 52 | * expansion panel being `expanded` and angular animations being `void`, the animation from the
|
---|
| 53 | * `expanded`'s effective styles (though in a `void` animation state) to the collapsed state will
|
---|
| 54 | * occur as expected.
|
---|
| 55 | *
|
---|
| 56 | * Angular Bug: https://github.com/angular/angular/issues/18847
|
---|
| 57 | *
|
---|
| 58 | * @docs-private
|
---|
| 59 | */
|
---|
| 60 | const matExpansionAnimations = {
|
---|
| 61 | /** Animation that rotates the indicator arrow. */
|
---|
| 62 | indicatorRotate: trigger('indicatorRotate', [
|
---|
| 63 | state('collapsed, void', style({ transform: 'rotate(0deg)' })),
|
---|
| 64 | state('expanded', style({ transform: 'rotate(180deg)' })),
|
---|
| 65 | transition('expanded <=> collapsed, void => collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
|
---|
| 66 | ]),
|
---|
| 67 | /** Animation that expands and collapses the panel content. */
|
---|
| 68 | bodyExpansion: trigger('bodyExpansion', [
|
---|
| 69 | state('collapsed, void', style({ height: '0px', visibility: 'hidden' })),
|
---|
| 70 | state('expanded', style({ height: '*', visibility: 'visible' })),
|
---|
| 71 | transition('expanded <=> collapsed, void => collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
|
---|
| 72 | ])
|
---|
| 73 | };
|
---|
| 74 |
|
---|
| 75 | /**
|
---|
| 76 | * @license
|
---|
| 77 | * Copyright Google LLC All Rights Reserved.
|
---|
| 78 | *
|
---|
| 79 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 80 | * found in the LICENSE file at https://angular.io/license
|
---|
| 81 | */
|
---|
| 82 | /**
|
---|
| 83 | * Expansion panel content that will be rendered lazily
|
---|
| 84 | * after the panel is opened for the first time.
|
---|
| 85 | */
|
---|
| 86 | class MatExpansionPanelContent {
|
---|
| 87 | constructor(_template) {
|
---|
| 88 | this._template = _template;
|
---|
| 89 | }
|
---|
| 90 | }
|
---|
| 91 | MatExpansionPanelContent.decorators = [
|
---|
| 92 | { type: Directive, args: [{
|
---|
| 93 | selector: 'ng-template[matExpansionPanelContent]'
|
---|
| 94 | },] }
|
---|
| 95 | ];
|
---|
| 96 | MatExpansionPanelContent.ctorParameters = () => [
|
---|
| 97 | { type: TemplateRef }
|
---|
| 98 | ];
|
---|
| 99 |
|
---|
| 100 | /**
|
---|
| 101 | * @license
|
---|
| 102 | * Copyright Google LLC All Rights Reserved.
|
---|
| 103 | *
|
---|
| 104 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 105 | * found in the LICENSE file at https://angular.io/license
|
---|
| 106 | */
|
---|
| 107 | /** Counter for generating unique element ids. */
|
---|
| 108 | let uniqueId = 0;
|
---|
| 109 | /**
|
---|
| 110 | * Injection token that can be used to configure the default
|
---|
| 111 | * options for the expansion panel component.
|
---|
| 112 | */
|
---|
| 113 | const MAT_EXPANSION_PANEL_DEFAULT_OPTIONS = new InjectionToken('MAT_EXPANSION_PANEL_DEFAULT_OPTIONS');
|
---|
| 114 | const ɵ0 = undefined;
|
---|
| 115 | /**
|
---|
| 116 | * This component can be used as a single element to show expandable content, or as one of
|
---|
| 117 | * multiple children of an element with the MatAccordion directive attached.
|
---|
| 118 | */
|
---|
| 119 | class MatExpansionPanel extends CdkAccordionItem {
|
---|
| 120 | constructor(accordion, _changeDetectorRef, _uniqueSelectionDispatcher, _viewContainerRef, _document, _animationMode, defaultOptions) {
|
---|
| 121 | super(accordion, _changeDetectorRef, _uniqueSelectionDispatcher);
|
---|
| 122 | this._viewContainerRef = _viewContainerRef;
|
---|
| 123 | this._animationMode = _animationMode;
|
---|
| 124 | this._hideToggle = false;
|
---|
| 125 | /** An event emitted after the body's expansion animation happens. */
|
---|
| 126 | this.afterExpand = new EventEmitter();
|
---|
| 127 | /** An event emitted after the body's collapse animation happens. */
|
---|
| 128 | this.afterCollapse = new EventEmitter();
|
---|
| 129 | /** Stream that emits for changes in `@Input` properties. */
|
---|
| 130 | this._inputChanges = new Subject();
|
---|
| 131 | /** ID for the associated header element. Used for a11y labelling. */
|
---|
| 132 | this._headerId = `mat-expansion-panel-header-${uniqueId++}`;
|
---|
| 133 | /** Stream of body animation done events. */
|
---|
| 134 | this._bodyAnimationDone = new Subject();
|
---|
| 135 | this.accordion = accordion;
|
---|
| 136 | this._document = _document;
|
---|
| 137 | // We need a Subject with distinctUntilChanged, because the `done` event
|
---|
| 138 | // fires twice on some browsers. See https://github.com/angular/angular/issues/24084
|
---|
| 139 | this._bodyAnimationDone.pipe(distinctUntilChanged((x, y) => {
|
---|
| 140 | return x.fromState === y.fromState && x.toState === y.toState;
|
---|
| 141 | })).subscribe(event => {
|
---|
| 142 | if (event.fromState !== 'void') {
|
---|
| 143 | if (event.toState === 'expanded') {
|
---|
| 144 | this.afterExpand.emit();
|
---|
| 145 | }
|
---|
| 146 | else if (event.toState === 'collapsed') {
|
---|
| 147 | this.afterCollapse.emit();
|
---|
| 148 | }
|
---|
| 149 | }
|
---|
| 150 | });
|
---|
| 151 | if (defaultOptions) {
|
---|
| 152 | this.hideToggle = defaultOptions.hideToggle;
|
---|
| 153 | }
|
---|
| 154 | }
|
---|
| 155 | /** Whether the toggle indicator should be hidden. */
|
---|
| 156 | get hideToggle() {
|
---|
| 157 | return this._hideToggle || (this.accordion && this.accordion.hideToggle);
|
---|
| 158 | }
|
---|
| 159 | set hideToggle(value) {
|
---|
| 160 | this._hideToggle = coerceBooleanProperty(value);
|
---|
| 161 | }
|
---|
| 162 | /** The position of the expansion indicator. */
|
---|
| 163 | get togglePosition() {
|
---|
| 164 | return this._togglePosition || (this.accordion && this.accordion.togglePosition);
|
---|
| 165 | }
|
---|
| 166 | set togglePosition(value) {
|
---|
| 167 | this._togglePosition = value;
|
---|
| 168 | }
|
---|
| 169 | /** Determines whether the expansion panel should have spacing between it and its siblings. */
|
---|
| 170 | _hasSpacing() {
|
---|
| 171 | if (this.accordion) {
|
---|
| 172 | return this.expanded && this.accordion.displayMode === 'default';
|
---|
| 173 | }
|
---|
| 174 | return false;
|
---|
| 175 | }
|
---|
| 176 | /** Gets the expanded state string. */
|
---|
| 177 | _getExpandedState() {
|
---|
| 178 | return this.expanded ? 'expanded' : 'collapsed';
|
---|
| 179 | }
|
---|
| 180 | /** Toggles the expanded state of the expansion panel. */
|
---|
| 181 | toggle() {
|
---|
| 182 | this.expanded = !this.expanded;
|
---|
| 183 | }
|
---|
| 184 | /** Sets the expanded state of the expansion panel to false. */
|
---|
| 185 | close() {
|
---|
| 186 | this.expanded = false;
|
---|
| 187 | }
|
---|
| 188 | /** Sets the expanded state of the expansion panel to true. */
|
---|
| 189 | open() {
|
---|
| 190 | this.expanded = true;
|
---|
| 191 | }
|
---|
| 192 | ngAfterContentInit() {
|
---|
| 193 | if (this._lazyContent) {
|
---|
| 194 | // Render the content as soon as the panel becomes open.
|
---|
| 195 | this.opened.pipe(startWith(null), filter(() => this.expanded && !this._portal), take(1)).subscribe(() => {
|
---|
| 196 | this._portal = new TemplatePortal(this._lazyContent._template, this._viewContainerRef);
|
---|
| 197 | });
|
---|
| 198 | }
|
---|
| 199 | }
|
---|
| 200 | ngOnChanges(changes) {
|
---|
| 201 | this._inputChanges.next(changes);
|
---|
| 202 | }
|
---|
| 203 | ngOnDestroy() {
|
---|
| 204 | super.ngOnDestroy();
|
---|
| 205 | this._bodyAnimationDone.complete();
|
---|
| 206 | this._inputChanges.complete();
|
---|
| 207 | }
|
---|
| 208 | /** Checks whether the expansion panel's content contains the currently-focused element. */
|
---|
| 209 | _containsFocus() {
|
---|
| 210 | if (this._body) {
|
---|
| 211 | const focusedElement = this._document.activeElement;
|
---|
| 212 | const bodyElement = this._body.nativeElement;
|
---|
| 213 | return focusedElement === bodyElement || bodyElement.contains(focusedElement);
|
---|
| 214 | }
|
---|
| 215 | return false;
|
---|
| 216 | }
|
---|
| 217 | }
|
---|
| 218 | MatExpansionPanel.decorators = [
|
---|
| 219 | { type: Component, args: [{
|
---|
| 220 | selector: 'mat-expansion-panel',
|
---|
| 221 | exportAs: 'matExpansionPanel',
|
---|
| 222 | template: "<ng-content select=\"mat-expansion-panel-header\"></ng-content>\n<div class=\"mat-expansion-panel-content\"\n role=\"region\"\n [@bodyExpansion]=\"_getExpandedState()\"\n (@bodyExpansion.done)=\"_bodyAnimationDone.next($event)\"\n [attr.aria-labelledby]=\"_headerId\"\n [id]=\"id\"\n #body>\n <div class=\"mat-expansion-panel-body\">\n <ng-content></ng-content>\n <ng-template [cdkPortalOutlet]=\"_portal\"></ng-template>\n </div>\n <ng-content select=\"mat-action-row\"></ng-content>\n</div>\n",
|
---|
| 223 | encapsulation: ViewEncapsulation.None,
|
---|
| 224 | changeDetection: ChangeDetectionStrategy.OnPush,
|
---|
| 225 | inputs: ['disabled', 'expanded'],
|
---|
| 226 | outputs: ['opened', 'closed', 'expandedChange'],
|
---|
| 227 | animations: [matExpansionAnimations.bodyExpansion],
|
---|
| 228 | providers: [
|
---|
| 229 | // Provide MatAccordion as undefined to prevent nested expansion panels from registering
|
---|
| 230 | // to the same accordion.
|
---|
| 231 | { provide: MAT_ACCORDION, useValue: ɵ0 },
|
---|
| 232 | ],
|
---|
| 233 | host: {
|
---|
| 234 | 'class': 'mat-expansion-panel',
|
---|
| 235 | '[class.mat-expanded]': 'expanded',
|
---|
| 236 | '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
|
---|
| 237 | '[class.mat-expansion-panel-spacing]': '_hasSpacing()',
|
---|
| 238 | },
|
---|
| 239 | styles: [".mat-expansion-panel{box-sizing:content-box;display:block;margin:0;border-radius:4px;overflow:hidden;transition:margin 225ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);position:relative}.mat-accordion .mat-expansion-panel:not(.mat-expanded),.mat-accordion .mat-expansion-panel:not(.mat-expansion-panel-spacing){border-radius:0}.mat-accordion .mat-expansion-panel:first-of-type{border-top-right-radius:4px;border-top-left-radius:4px}.mat-accordion .mat-expansion-panel:last-of-type{border-bottom-right-radius:4px;border-bottom-left-radius:4px}.cdk-high-contrast-active .mat-expansion-panel{outline:solid 1px}.mat-expansion-panel.ng-animate-disabled,.ng-animate-disabled .mat-expansion-panel,.mat-expansion-panel._mat-animation-noopable{transition:none}.mat-expansion-panel-content{display:flex;flex-direction:column;overflow:visible}.mat-expansion-panel-body{padding:0 24px 16px}.mat-expansion-panel-spacing{margin:16px 0}.mat-accordion>.mat-expansion-panel-spacing:first-child,.mat-accordion>*:first-child:not(.mat-expansion-panel) .mat-expansion-panel-spacing{margin-top:0}.mat-accordion>.mat-expansion-panel-spacing:last-child,.mat-accordion>*:last-child:not(.mat-expansion-panel) .mat-expansion-panel-spacing{margin-bottom:0}.mat-action-row{border-top-style:solid;border-top-width:1px;display:flex;flex-direction:row;justify-content:flex-end;padding:16px 8px 16px 24px}.mat-action-row button.mat-button-base,.mat-action-row button.mat-mdc-button-base{margin-left:8px}[dir=rtl] .mat-action-row button.mat-button-base,[dir=rtl] .mat-action-row button.mat-mdc-button-base{margin-left:0;margin-right:8px}\n"]
|
---|
| 240 | },] }
|
---|
| 241 | ];
|
---|
| 242 | MatExpansionPanel.ctorParameters = () => [
|
---|
| 243 | { type: undefined, decorators: [{ type: Optional }, { type: SkipSelf }, { type: Inject, args: [MAT_ACCORDION,] }] },
|
---|
| 244 | { type: ChangeDetectorRef },
|
---|
| 245 | { type: UniqueSelectionDispatcher },
|
---|
| 246 | { type: ViewContainerRef },
|
---|
| 247 | { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
|
---|
| 248 | { type: String, decorators: [{ type: Optional }, { type: Inject, args: [ANIMATION_MODULE_TYPE,] }] },
|
---|
| 249 | { type: undefined, decorators: [{ type: Inject, args: [MAT_EXPANSION_PANEL_DEFAULT_OPTIONS,] }, { type: Optional }] }
|
---|
| 250 | ];
|
---|
| 251 | MatExpansionPanel.propDecorators = {
|
---|
| 252 | hideToggle: [{ type: Input }],
|
---|
| 253 | togglePosition: [{ type: Input }],
|
---|
| 254 | afterExpand: [{ type: Output }],
|
---|
| 255 | afterCollapse: [{ type: Output }],
|
---|
| 256 | _lazyContent: [{ type: ContentChild, args: [MatExpansionPanelContent,] }],
|
---|
| 257 | _body: [{ type: ViewChild, args: ['body',] }]
|
---|
| 258 | };
|
---|
| 259 | /**
|
---|
| 260 | * Actions of a `<mat-expansion-panel>`.
|
---|
| 261 | */
|
---|
| 262 | class MatExpansionPanelActionRow {
|
---|
| 263 | }
|
---|
| 264 | MatExpansionPanelActionRow.decorators = [
|
---|
| 265 | { type: Directive, args: [{
|
---|
| 266 | selector: 'mat-action-row',
|
---|
| 267 | host: {
|
---|
| 268 | class: 'mat-action-row'
|
---|
| 269 | }
|
---|
| 270 | },] }
|
---|
| 271 | ];
|
---|
| 272 |
|
---|
| 273 | /**
|
---|
| 274 | * @license
|
---|
| 275 | * Copyright Google LLC All Rights Reserved.
|
---|
| 276 | *
|
---|
| 277 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 278 | * found in the LICENSE file at https://angular.io/license
|
---|
| 279 | */
|
---|
| 280 | // Boilerplate for applying mixins to MatExpansionPanelHeader.
|
---|
| 281 | /** @docs-private */
|
---|
| 282 | class MatExpansionPanelHeaderBase {
|
---|
| 283 | }
|
---|
| 284 | const _MatExpansionPanelHeaderMixinBase = mixinTabIndex(MatExpansionPanelHeaderBase);
|
---|
| 285 | /**
|
---|
| 286 | * Header element of a `<mat-expansion-panel>`.
|
---|
| 287 | */
|
---|
| 288 | class MatExpansionPanelHeader extends _MatExpansionPanelHeaderMixinBase {
|
---|
| 289 | constructor(panel, _element, _focusMonitor, _changeDetectorRef, defaultOptions, _animationMode, tabIndex) {
|
---|
| 290 | super();
|
---|
| 291 | this.panel = panel;
|
---|
| 292 | this._element = _element;
|
---|
| 293 | this._focusMonitor = _focusMonitor;
|
---|
| 294 | this._changeDetectorRef = _changeDetectorRef;
|
---|
| 295 | this._animationMode = _animationMode;
|
---|
| 296 | this._parentChangeSubscription = Subscription.EMPTY;
|
---|
| 297 | const accordionHideToggleChange = panel.accordion ?
|
---|
| 298 | panel.accordion._stateChanges.pipe(filter(changes => !!(changes['hideToggle'] || changes['togglePosition']))) :
|
---|
| 299 | EMPTY;
|
---|
| 300 | this.tabIndex = parseInt(tabIndex || '') || 0;
|
---|
| 301 | // Since the toggle state depends on an @Input on the panel, we
|
---|
| 302 | // need to subscribe and trigger change detection manually.
|
---|
| 303 | this._parentChangeSubscription =
|
---|
| 304 | merge(panel.opened, panel.closed, accordionHideToggleChange, panel._inputChanges.pipe(filter(changes => {
|
---|
| 305 | return !!(changes['hideToggle'] ||
|
---|
| 306 | changes['disabled'] ||
|
---|
| 307 | changes['togglePosition']);
|
---|
| 308 | })))
|
---|
| 309 | .subscribe(() => this._changeDetectorRef.markForCheck());
|
---|
| 310 | // Avoids focus being lost if the panel contained the focused element and was closed.
|
---|
| 311 | panel.closed
|
---|
| 312 | .pipe(filter(() => panel._containsFocus()))
|
---|
| 313 | .subscribe(() => _focusMonitor.focusVia(_element, 'program'));
|
---|
| 314 | if (defaultOptions) {
|
---|
| 315 | this.expandedHeight = defaultOptions.expandedHeight;
|
---|
| 316 | this.collapsedHeight = defaultOptions.collapsedHeight;
|
---|
| 317 | }
|
---|
| 318 | }
|
---|
| 319 | /**
|
---|
| 320 | * Whether the associated panel is disabled. Implemented as a part of `FocusableOption`.
|
---|
| 321 | * @docs-private
|
---|
| 322 | */
|
---|
| 323 | get disabled() {
|
---|
| 324 | return this.panel.disabled;
|
---|
| 325 | }
|
---|
| 326 | /** Toggles the expanded state of the panel. */
|
---|
| 327 | _toggle() {
|
---|
| 328 | if (!this.disabled) {
|
---|
| 329 | this.panel.toggle();
|
---|
| 330 | }
|
---|
| 331 | }
|
---|
| 332 | /** Gets whether the panel is expanded. */
|
---|
| 333 | _isExpanded() {
|
---|
| 334 | return this.panel.expanded;
|
---|
| 335 | }
|
---|
| 336 | /** Gets the expanded state string of the panel. */
|
---|
| 337 | _getExpandedState() {
|
---|
| 338 | return this.panel._getExpandedState();
|
---|
| 339 | }
|
---|
| 340 | /** Gets the panel id. */
|
---|
| 341 | _getPanelId() {
|
---|
| 342 | return this.panel.id;
|
---|
| 343 | }
|
---|
| 344 | /** Gets the toggle position for the header. */
|
---|
| 345 | _getTogglePosition() {
|
---|
| 346 | return this.panel.togglePosition;
|
---|
| 347 | }
|
---|
| 348 | /** Gets whether the expand indicator should be shown. */
|
---|
| 349 | _showToggle() {
|
---|
| 350 | return !this.panel.hideToggle && !this.panel.disabled;
|
---|
| 351 | }
|
---|
| 352 | /**
|
---|
| 353 | * Gets the current height of the header. Null if no custom height has been
|
---|
| 354 | * specified, and if the default height from the stylesheet should be used.
|
---|
| 355 | */
|
---|
| 356 | _getHeaderHeight() {
|
---|
| 357 | const isExpanded = this._isExpanded();
|
---|
| 358 | if (isExpanded && this.expandedHeight) {
|
---|
| 359 | return this.expandedHeight;
|
---|
| 360 | }
|
---|
| 361 | else if (!isExpanded && this.collapsedHeight) {
|
---|
| 362 | return this.collapsedHeight;
|
---|
| 363 | }
|
---|
| 364 | return null;
|
---|
| 365 | }
|
---|
| 366 | /** Handle keydown event calling to toggle() if appropriate. */
|
---|
| 367 | _keydown(event) {
|
---|
| 368 | switch (event.keyCode) {
|
---|
| 369 | // Toggle for space and enter keys.
|
---|
| 370 | case SPACE:
|
---|
| 371 | case ENTER:
|
---|
| 372 | if (!hasModifierKey(event)) {
|
---|
| 373 | event.preventDefault();
|
---|
| 374 | this._toggle();
|
---|
| 375 | }
|
---|
| 376 | break;
|
---|
| 377 | default:
|
---|
| 378 | if (this.panel.accordion) {
|
---|
| 379 | this.panel.accordion._handleHeaderKeydown(event);
|
---|
| 380 | }
|
---|
| 381 | return;
|
---|
| 382 | }
|
---|
| 383 | }
|
---|
| 384 | /**
|
---|
| 385 | * Focuses the panel header. Implemented as a part of `FocusableOption`.
|
---|
| 386 | * @param origin Origin of the action that triggered the focus.
|
---|
| 387 | * @docs-private
|
---|
| 388 | */
|
---|
| 389 | focus(origin, options) {
|
---|
| 390 | if (origin) {
|
---|
| 391 | this._focusMonitor.focusVia(this._element, origin, options);
|
---|
| 392 | }
|
---|
| 393 | else {
|
---|
| 394 | this._element.nativeElement.focus(options);
|
---|
| 395 | }
|
---|
| 396 | }
|
---|
| 397 | ngAfterViewInit() {
|
---|
| 398 | this._focusMonitor.monitor(this._element).subscribe(origin => {
|
---|
| 399 | if (origin && this.panel.accordion) {
|
---|
| 400 | this.panel.accordion._handleHeaderFocus(this);
|
---|
| 401 | }
|
---|
| 402 | });
|
---|
| 403 | }
|
---|
| 404 | ngOnDestroy() {
|
---|
| 405 | this._parentChangeSubscription.unsubscribe();
|
---|
| 406 | this._focusMonitor.stopMonitoring(this._element);
|
---|
| 407 | }
|
---|
| 408 | }
|
---|
| 409 | MatExpansionPanelHeader.decorators = [
|
---|
| 410 | { type: Component, args: [{
|
---|
| 411 | selector: 'mat-expansion-panel-header',
|
---|
| 412 | template: "<span class=\"mat-content\">\n <ng-content select=\"mat-panel-title\"></ng-content>\n <ng-content select=\"mat-panel-description\"></ng-content>\n <ng-content></ng-content>\n</span>\n<span [@indicatorRotate]=\"_getExpandedState()\" *ngIf=\"_showToggle()\"\n class=\"mat-expansion-indicator\"></span>\n",
|
---|
| 413 | encapsulation: ViewEncapsulation.None,
|
---|
| 414 | changeDetection: ChangeDetectionStrategy.OnPush,
|
---|
| 415 | inputs: ['tabIndex'],
|
---|
| 416 | animations: [
|
---|
| 417 | matExpansionAnimations.indicatorRotate,
|
---|
| 418 | ],
|
---|
| 419 | host: {
|
---|
| 420 | 'class': 'mat-expansion-panel-header mat-focus-indicator',
|
---|
| 421 | 'role': 'button',
|
---|
| 422 | '[attr.id]': 'panel._headerId',
|
---|
| 423 | '[attr.tabindex]': 'tabIndex',
|
---|
| 424 | '[attr.aria-controls]': '_getPanelId()',
|
---|
| 425 | '[attr.aria-expanded]': '_isExpanded()',
|
---|
| 426 | '[attr.aria-disabled]': 'panel.disabled',
|
---|
| 427 | '[class.mat-expanded]': '_isExpanded()',
|
---|
| 428 | '[class.mat-expansion-toggle-indicator-after]': `_getTogglePosition() === 'after'`,
|
---|
| 429 | '[class.mat-expansion-toggle-indicator-before]': `_getTogglePosition() === 'before'`,
|
---|
| 430 | '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
|
---|
| 431 | '[style.height]': '_getHeaderHeight()',
|
---|
| 432 | '(click)': '_toggle()',
|
---|
| 433 | '(keydown)': '_keydown($event)',
|
---|
| 434 | },
|
---|
| 435 | styles: [".mat-expansion-panel-header{display:flex;flex-direction:row;align-items:center;padding:0 24px;border-radius:inherit;transition:height 225ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-expansion-panel-header._mat-animation-noopable{transition:none}.mat-expansion-panel-header:focus,.mat-expansion-panel-header:hover{outline:none}.mat-expansion-panel-header.mat-expanded:focus,.mat-expansion-panel-header.mat-expanded:hover{background:inherit}.mat-expansion-panel-header:not([aria-disabled=true]){cursor:pointer}.mat-expansion-panel-header.mat-expansion-toggle-indicator-before{flex-direction:row-reverse}.mat-expansion-panel-header.mat-expansion-toggle-indicator-before .mat-expansion-indicator{margin:0 16px 0 0}[dir=rtl] .mat-expansion-panel-header.mat-expansion-toggle-indicator-before .mat-expansion-indicator{margin:0 0 0 16px}.mat-content{display:flex;flex:1;flex-direction:row;overflow:hidden}.mat-expansion-panel-header-title,.mat-expansion-panel-header-description{display:flex;flex-grow:1;margin-right:16px}[dir=rtl] .mat-expansion-panel-header-title,[dir=rtl] .mat-expansion-panel-header-description{margin-right:0;margin-left:16px}.mat-expansion-panel-header-description{flex-grow:2}.mat-expansion-indicator::after{border-style:solid;border-width:0 2px 2px 0;content:\"\";display:inline-block;padding:3px;transform:rotate(45deg);vertical-align:middle}.cdk-high-contrast-active .mat-expansion-panel .mat-expansion-panel-header.cdk-keyboard-focused:not([aria-disabled=true])::before,.cdk-high-contrast-active .mat-expansion-panel .mat-expansion-panel-header.cdk-program-focused:not([aria-disabled=true])::before,.cdk-high-contrast-active .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover:not([aria-disabled=true])::before{top:0;left:0;right:0;bottom:0;position:absolute;box-sizing:border-box;pointer-events:none;border:3px solid;border-radius:4px;content:\"\"}.cdk-high-contrast-active .mat-expansion-panel-content{border-top:1px solid;border-top-left-radius:0;border-top-right-radius:0}\n"]
|
---|
| 436 | },] }
|
---|
| 437 | ];
|
---|
| 438 | MatExpansionPanelHeader.ctorParameters = () => [
|
---|
| 439 | { type: MatExpansionPanel, decorators: [{ type: Host }] },
|
---|
| 440 | { type: ElementRef },
|
---|
| 441 | { type: FocusMonitor },
|
---|
| 442 | { type: ChangeDetectorRef },
|
---|
| 443 | { type: undefined, decorators: [{ type: Inject, args: [MAT_EXPANSION_PANEL_DEFAULT_OPTIONS,] }, { type: Optional }] },
|
---|
| 444 | { type: String, decorators: [{ type: Optional }, { type: Inject, args: [ANIMATION_MODULE_TYPE,] }] },
|
---|
| 445 | { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] }
|
---|
| 446 | ];
|
---|
| 447 | MatExpansionPanelHeader.propDecorators = {
|
---|
| 448 | expandedHeight: [{ type: Input }],
|
---|
| 449 | collapsedHeight: [{ type: Input }]
|
---|
| 450 | };
|
---|
| 451 | /**
|
---|
| 452 | * Description element of a `<mat-expansion-panel-header>`.
|
---|
| 453 | */
|
---|
| 454 | class MatExpansionPanelDescription {
|
---|
| 455 | }
|
---|
| 456 | MatExpansionPanelDescription.decorators = [
|
---|
| 457 | { type: Directive, args: [{
|
---|
| 458 | selector: 'mat-panel-description',
|
---|
| 459 | host: {
|
---|
| 460 | class: 'mat-expansion-panel-header-description'
|
---|
| 461 | }
|
---|
| 462 | },] }
|
---|
| 463 | ];
|
---|
| 464 | /**
|
---|
| 465 | * Title element of a `<mat-expansion-panel-header>`.
|
---|
| 466 | */
|
---|
| 467 | class MatExpansionPanelTitle {
|
---|
| 468 | }
|
---|
| 469 | MatExpansionPanelTitle.decorators = [
|
---|
| 470 | { type: Directive, args: [{
|
---|
| 471 | selector: 'mat-panel-title',
|
---|
| 472 | host: {
|
---|
| 473 | class: 'mat-expansion-panel-header-title'
|
---|
| 474 | }
|
---|
| 475 | },] }
|
---|
| 476 | ];
|
---|
| 477 |
|
---|
| 478 | /**
|
---|
| 479 | * @license
|
---|
| 480 | * Copyright Google LLC All Rights Reserved.
|
---|
| 481 | *
|
---|
| 482 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 483 | * found in the LICENSE file at https://angular.io/license
|
---|
| 484 | */
|
---|
| 485 | /**
|
---|
| 486 | * Directive for a Material Design Accordion.
|
---|
| 487 | */
|
---|
| 488 | class MatAccordion extends CdkAccordion {
|
---|
| 489 | constructor() {
|
---|
| 490 | super(...arguments);
|
---|
| 491 | /** Headers belonging to this accordion. */
|
---|
| 492 | this._ownHeaders = new QueryList();
|
---|
| 493 | this._hideToggle = false;
|
---|
| 494 | /**
|
---|
| 495 | * Display mode used for all expansion panels in the accordion. Currently two display
|
---|
| 496 | * modes exist:
|
---|
| 497 | * default - a gutter-like spacing is placed around any expanded panel, placing the expanded
|
---|
| 498 | * panel at a different elevation from the rest of the accordion.
|
---|
| 499 | * flat - no spacing is placed around expanded panels, showing all panels at the same
|
---|
| 500 | * elevation.
|
---|
| 501 | */
|
---|
| 502 | this.displayMode = 'default';
|
---|
| 503 | /** The position of the expansion indicator. */
|
---|
| 504 | this.togglePosition = 'after';
|
---|
| 505 | }
|
---|
| 506 | /** Whether the expansion indicator should be hidden. */
|
---|
| 507 | get hideToggle() { return this._hideToggle; }
|
---|
| 508 | set hideToggle(show) { this._hideToggle = coerceBooleanProperty(show); }
|
---|
| 509 | ngAfterContentInit() {
|
---|
| 510 | this._headers.changes
|
---|
| 511 | .pipe(startWith(this._headers))
|
---|
| 512 | .subscribe((headers) => {
|
---|
| 513 | this._ownHeaders.reset(headers.filter(header => header.panel.accordion === this));
|
---|
| 514 | this._ownHeaders.notifyOnChanges();
|
---|
| 515 | });
|
---|
| 516 | this._keyManager = new FocusKeyManager(this._ownHeaders).withWrap().withHomeAndEnd();
|
---|
| 517 | }
|
---|
| 518 | /** Handles keyboard events coming in from the panel headers. */
|
---|
| 519 | _handleHeaderKeydown(event) {
|
---|
| 520 | this._keyManager.onKeydown(event);
|
---|
| 521 | }
|
---|
| 522 | _handleHeaderFocus(header) {
|
---|
| 523 | this._keyManager.updateActiveItem(header);
|
---|
| 524 | }
|
---|
| 525 | ngOnDestroy() {
|
---|
| 526 | super.ngOnDestroy();
|
---|
| 527 | this._ownHeaders.destroy();
|
---|
| 528 | }
|
---|
| 529 | }
|
---|
| 530 | MatAccordion.decorators = [
|
---|
| 531 | { type: Directive, args: [{
|
---|
| 532 | selector: 'mat-accordion',
|
---|
| 533 | exportAs: 'matAccordion',
|
---|
| 534 | inputs: ['multi'],
|
---|
| 535 | providers: [{
|
---|
| 536 | provide: MAT_ACCORDION,
|
---|
| 537 | useExisting: MatAccordion
|
---|
| 538 | }],
|
---|
| 539 | host: {
|
---|
| 540 | class: 'mat-accordion',
|
---|
| 541 | // Class binding which is only used by the test harness as there is no other
|
---|
| 542 | // way for the harness to detect if multiple panel support is enabled.
|
---|
| 543 | '[class.mat-accordion-multi]': 'this.multi',
|
---|
| 544 | }
|
---|
| 545 | },] }
|
---|
| 546 | ];
|
---|
| 547 | MatAccordion.propDecorators = {
|
---|
| 548 | _headers: [{ type: ContentChildren, args: [MatExpansionPanelHeader, { descendants: true },] }],
|
---|
| 549 | hideToggle: [{ type: Input }],
|
---|
| 550 | displayMode: [{ type: Input }],
|
---|
| 551 | togglePosition: [{ type: Input }]
|
---|
| 552 | };
|
---|
| 553 |
|
---|
| 554 | /**
|
---|
| 555 | * @license
|
---|
| 556 | * Copyright Google LLC All Rights Reserved.
|
---|
| 557 | *
|
---|
| 558 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 559 | * found in the LICENSE file at https://angular.io/license
|
---|
| 560 | */
|
---|
| 561 | class MatExpansionModule {
|
---|
| 562 | }
|
---|
| 563 | MatExpansionModule.decorators = [
|
---|
| 564 | { type: NgModule, args: [{
|
---|
| 565 | imports: [CommonModule, MatCommonModule, CdkAccordionModule, PortalModule],
|
---|
| 566 | exports: [
|
---|
| 567 | MatAccordion,
|
---|
| 568 | MatExpansionPanel,
|
---|
| 569 | MatExpansionPanelActionRow,
|
---|
| 570 | MatExpansionPanelHeader,
|
---|
| 571 | MatExpansionPanelTitle,
|
---|
| 572 | MatExpansionPanelDescription,
|
---|
| 573 | MatExpansionPanelContent,
|
---|
| 574 | ],
|
---|
| 575 | declarations: [
|
---|
| 576 | MatAccordion,
|
---|
| 577 | MatExpansionPanel,
|
---|
| 578 | MatExpansionPanelActionRow,
|
---|
| 579 | MatExpansionPanelHeader,
|
---|
| 580 | MatExpansionPanelTitle,
|
---|
| 581 | MatExpansionPanelDescription,
|
---|
| 582 | MatExpansionPanelContent,
|
---|
| 583 | ],
|
---|
| 584 | },] }
|
---|
| 585 | ];
|
---|
| 586 |
|
---|
| 587 | /**
|
---|
| 588 | * @license
|
---|
| 589 | * Copyright Google LLC All Rights Reserved.
|
---|
| 590 | *
|
---|
| 591 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 592 | * found in the LICENSE file at https://angular.io/license
|
---|
| 593 | */
|
---|
| 594 |
|
---|
| 595 | /**
|
---|
| 596 | * Generated bundle index. Do not edit.
|
---|
| 597 | */
|
---|
| 598 |
|
---|
| 599 | export { EXPANSION_PANEL_ANIMATION_TIMING, MAT_ACCORDION, MAT_EXPANSION_PANEL_DEFAULT_OPTIONS, MatAccordion, MatExpansionModule, MatExpansionPanel, MatExpansionPanelActionRow, MatExpansionPanelContent, MatExpansionPanelDescription, MatExpansionPanelHeader, MatExpansionPanelTitle, matExpansionAnimations, ɵ0 };
|
---|
| 600 | //# sourceMappingURL=expansion.js.map
|
---|