UNPKG

65.1 kBJavaScriptView Raw
1import * as i1 from '@angular/cdk/scrolling';
2import { CdkScrollable, CdkScrollableModule } from '@angular/cdk/scrolling';
3import * as i5 from '@angular/common';
4import { DOCUMENT, CommonModule } from '@angular/common';
5import * as i0 from '@angular/core';
6import { InjectionToken, forwardRef, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, EventEmitter, Optional, Input, Output, ViewChild, QueryList, ContentChildren, ContentChild, NgModule } from '@angular/core';
7import { MatCommonModule } from '@angular/material/core';
8import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
9import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
10import { Subject, fromEvent, merge } from 'rxjs';
11import { filter, map, mapTo, takeUntil, distinctUntilChanged, take, startWith, debounceTime } from 'rxjs/operators';
12import { trigger, state, style, transition, animate } from '@angular/animations';
13import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
14import * as i2 from '@angular/cdk/a11y';
15import * as i3 from '@angular/cdk/platform';
16import * as i4 from '@angular/cdk/bidi';
17
18/**
19 * @license
20 * Copyright Google LLC All Rights Reserved.
21 *
22 * Use of this source code is governed by an MIT-style license that can be
23 * found in the LICENSE file at https://angular.io/license
24 */
25/**
26 * Animations used by the Material drawers.
27 * @docs-private
28 */
29const matDrawerAnimations = {
30 /** Animation that slides a drawer in and out. */
31 transformDrawer: trigger('transform', [
32 // We remove the `transform` here completely, rather than setting it to zero, because:
33 // 1. Having a transform can cause elements with ripples or an animated
34 // transform to shift around in Chrome with an RTL layout (see #10023).
35 // 2. 3d transforms causes text to appear blurry on IE and Edge.
36 state('open, open-instant', style({
37 'transform': 'none',
38 'visibility': 'visible',
39 })),
40 state('void', style({
41 // Avoids the shadow showing up when closed in SSR.
42 'box-shadow': 'none',
43 'visibility': 'hidden',
44 })),
45 transition('void => open-instant', animate('0ms')),
46 transition('void <=> open, open-instant => void', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
47 ]),
48};
49
50/**
51 * Throws an exception when two MatDrawer are matching the same position.
52 * @docs-private
53 */
54function throwMatDuplicatedDrawerError(position) {
55 throw Error(`A drawer was already declared for 'position="${position}"'`);
56}
57/** Configures whether drawers should use auto sizing by default. */
58const MAT_DRAWER_DEFAULT_AUTOSIZE = new InjectionToken('MAT_DRAWER_DEFAULT_AUTOSIZE', {
59 providedIn: 'root',
60 factory: MAT_DRAWER_DEFAULT_AUTOSIZE_FACTORY,
61});
62/**
63 * Used to provide a drawer container to a drawer while avoiding circular references.
64 * @docs-private
65 */
66const MAT_DRAWER_CONTAINER = new InjectionToken('MAT_DRAWER_CONTAINER');
67/** @docs-private */
68function MAT_DRAWER_DEFAULT_AUTOSIZE_FACTORY() {
69 return false;
70}
71class MatDrawerContent extends CdkScrollable {
72 constructor(_changeDetectorRef, _container, elementRef, scrollDispatcher, ngZone) {
73 super(elementRef, scrollDispatcher, ngZone);
74 this._changeDetectorRef = _changeDetectorRef;
75 this._container = _container;
76 }
77 ngAfterContentInit() {
78 this._container._contentMarginChanges.subscribe(() => {
79 this._changeDetectorRef.markForCheck();
80 });
81 }
82}
83MatDrawerContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawerContent, deps: [{ token: i0.ChangeDetectorRef }, { token: forwardRef(() => MatDrawerContainer) }, { token: i0.ElementRef }, { token: i1.ScrollDispatcher }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
84MatDrawerContent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatDrawerContent, selector: "mat-drawer-content", host: { properties: { "style.margin-left.px": "_container._contentMargins.left", "style.margin-right.px": "_container._contentMargins.right" }, classAttribute: "mat-drawer-content" }, providers: [
85 {
86 provide: CdkScrollable,
87 useExisting: MatDrawerContent,
88 },
89 ], usesInheritance: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
90i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawerContent, decorators: [{
91 type: Component,
92 args: [{
93 selector: 'mat-drawer-content',
94 template: '<ng-content></ng-content>',
95 host: {
96 'class': 'mat-drawer-content',
97 '[style.margin-left.px]': '_container._contentMargins.left',
98 '[style.margin-right.px]': '_container._contentMargins.right',
99 },
100 changeDetection: ChangeDetectionStrategy.OnPush,
101 encapsulation: ViewEncapsulation.None,
102 providers: [
103 {
104 provide: CdkScrollable,
105 useExisting: MatDrawerContent,
106 },
107 ],
108 }]
109 }], ctorParameters: function () {
110 return [{ type: i0.ChangeDetectorRef }, { type: MatDrawerContainer, decorators: [{
111 type: Inject,
112 args: [forwardRef(() => MatDrawerContainer)]
113 }] }, { type: i0.ElementRef }, { type: i1.ScrollDispatcher }, { type: i0.NgZone }];
114 } });
115/**
116 * This component corresponds to a drawer that can be opened on the drawer container.
117 */
118class MatDrawer {
119 constructor(_elementRef, _focusTrapFactory, _focusMonitor, _platform, _ngZone, _interactivityChecker, _doc, _container) {
120 this._elementRef = _elementRef;
121 this._focusTrapFactory = _focusTrapFactory;
122 this._focusMonitor = _focusMonitor;
123 this._platform = _platform;
124 this._ngZone = _ngZone;
125 this._interactivityChecker = _interactivityChecker;
126 this._doc = _doc;
127 this._container = _container;
128 this._elementFocusedBeforeDrawerWasOpened = null;
129 /** Whether the drawer is initialized. Used for disabling the initial animation. */
130 this._enableAnimations = false;
131 this._position = 'start';
132 this._mode = 'over';
133 this._disableClose = false;
134 this._opened = false;
135 /** Emits whenever the drawer has started animating. */
136 this._animationStarted = new Subject();
137 /** Emits whenever the drawer is done animating. */
138 this._animationEnd = new Subject();
139 /** Current state of the sidenav animation. */
140 this._animationState = 'void';
141 /** Event emitted when the drawer open state is changed. */
142 this.openedChange =
143 // Note this has to be async in order to avoid some issues with two-bindings (see #8872).
144 new EventEmitter(/* isAsync */ true);
145 /** Event emitted when the drawer has been opened. */
146 this._openedStream = this.openedChange.pipe(filter(o => o), map(() => { }));
147 /** Event emitted when the drawer has started opening. */
148 this.openedStart = this._animationStarted.pipe(filter(e => e.fromState !== e.toState && e.toState.indexOf('open') === 0), mapTo(undefined));
149 /** Event emitted when the drawer has been closed. */
150 this._closedStream = this.openedChange.pipe(filter(o => !o), map(() => { }));
151 /** Event emitted when the drawer has started closing. */
152 this.closedStart = this._animationStarted.pipe(filter(e => e.fromState !== e.toState && e.toState === 'void'), mapTo(undefined));
153 /** Emits when the component is destroyed. */
154 this._destroyed = new Subject();
155 /** Event emitted when the drawer's position changes. */
156 // tslint:disable-next-line:no-output-on-prefix
157 this.onPositionChanged = new EventEmitter();
158 /**
159 * An observable that emits when the drawer mode changes. This is used by the drawer container to
160 * to know when to when the mode changes so it can adapt the margins on the content.
161 */
162 this._modeChanged = new Subject();
163 this.openedChange.subscribe((opened) => {
164 if (opened) {
165 if (this._doc) {
166 this._elementFocusedBeforeDrawerWasOpened = this._doc.activeElement;
167 }
168 this._takeFocus();
169 }
170 else if (this._isFocusWithinDrawer()) {
171 this._restoreFocus(this._openedVia || 'program');
172 }
173 });
174 /**
175 * Listen to `keydown` events outside the zone so that change detection is not run every
176 * time a key is pressed. Instead we re-enter the zone only if the `ESC` key is pressed
177 * and we don't have close disabled.
178 */
179 this._ngZone.runOutsideAngular(() => {
180 fromEvent(this._elementRef.nativeElement, 'keydown')
181 .pipe(filter(event => {
182 return event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event);
183 }), takeUntil(this._destroyed))
184 .subscribe(event => this._ngZone.run(() => {
185 this.close();
186 event.stopPropagation();
187 event.preventDefault();
188 }));
189 });
190 // We need a Subject with distinctUntilChanged, because the `done` event
191 // fires twice on some browsers. See https://github.com/angular/angular/issues/24084
192 this._animationEnd
193 .pipe(distinctUntilChanged((x, y) => {
194 return x.fromState === y.fromState && x.toState === y.toState;
195 }))
196 .subscribe((event) => {
197 const { fromState, toState } = event;
198 if ((toState.indexOf('open') === 0 && fromState === 'void') ||
199 (toState === 'void' && fromState.indexOf('open') === 0)) {
200 this.openedChange.emit(this._opened);
201 }
202 });
203 }
204 /** The side that the drawer is attached to. */
205 get position() {
206 return this._position;
207 }
208 set position(value) {
209 // Make sure we have a valid value.
210 value = value === 'end' ? 'end' : 'start';
211 if (value !== this._position) {
212 // Static inputs in Ivy are set before the element is in the DOM.
213 if (this._isAttached) {
214 this._updatePositionInParent(value);
215 }
216 this._position = value;
217 this.onPositionChanged.emit();
218 }
219 }
220 /** Mode of the drawer; one of 'over', 'push' or 'side'. */
221 get mode() {
222 return this._mode;
223 }
224 set mode(value) {
225 this._mode = value;
226 this._updateFocusTrapState();
227 this._modeChanged.next();
228 }
229 /** Whether the drawer can be closed with the escape key or by clicking on the backdrop. */
230 get disableClose() {
231 return this._disableClose;
232 }
233 set disableClose(value) {
234 this._disableClose = coerceBooleanProperty(value);
235 }
236 /**
237 * Whether the drawer should focus the first focusable element automatically when opened.
238 * Defaults to false in when `mode` is set to `side`, otherwise defaults to `true`. If explicitly
239 * enabled, focus will be moved into the sidenav in `side` mode as well.
240 * @breaking-change 14.0.0 Remove boolean option from autoFocus. Use string or AutoFocusTarget
241 * instead.
242 */
243 get autoFocus() {
244 const value = this._autoFocus;
245 // Note that usually we don't allow autoFocus to be set to `first-tabbable` in `side` mode,
246 // because we don't know how the sidenav is being used, but in some cases it still makes
247 // sense to do it. The consumer can explicitly set `autoFocus`.
248 if (value == null) {
249 if (this.mode === 'side') {
250 return 'dialog';
251 }
252 else {
253 return 'first-tabbable';
254 }
255 }
256 return value;
257 }
258 set autoFocus(value) {
259 if (value === 'true' || value === 'false' || value == null) {
260 value = coerceBooleanProperty(value);
261 }
262 this._autoFocus = value;
263 }
264 /**
265 * Whether the drawer is opened. We overload this because we trigger an event when it
266 * starts or end.
267 */
268 get opened() {
269 return this._opened;
270 }
271 set opened(value) {
272 this.toggle(coerceBooleanProperty(value));
273 }
274 /**
275 * Focuses the provided element. If the element is not focusable, it will add a tabIndex
276 * attribute to forcefully focus it. The attribute is removed after focus is moved.
277 * @param element The element to focus.
278 */
279 _forceFocus(element, options) {
280 if (!this._interactivityChecker.isFocusable(element)) {
281 element.tabIndex = -1;
282 // The tabindex attribute should be removed to avoid navigating to that element again
283 this._ngZone.runOutsideAngular(() => {
284 const callback = () => {
285 element.removeEventListener('blur', callback);
286 element.removeEventListener('mousedown', callback);
287 element.removeAttribute('tabindex');
288 };
289 element.addEventListener('blur', callback);
290 element.addEventListener('mousedown', callback);
291 });
292 }
293 element.focus(options);
294 }
295 /**
296 * Focuses the first element that matches the given selector within the focus trap.
297 * @param selector The CSS selector for the element to set focus to.
298 */
299 _focusByCssSelector(selector, options) {
300 let elementToFocus = this._elementRef.nativeElement.querySelector(selector);
301 if (elementToFocus) {
302 this._forceFocus(elementToFocus, options);
303 }
304 }
305 /**
306 * Moves focus into the drawer. Note that this works even if
307 * the focus trap is disabled in `side` mode.
308 */
309 _takeFocus() {
310 if (!this._focusTrap) {
311 return;
312 }
313 const element = this._elementRef.nativeElement;
314 // When autoFocus is not on the sidenav, if the element cannot be focused or does
315 // not exist, focus the sidenav itself so the keyboard navigation still works.
316 // We need to check that `focus` is a function due to Universal.
317 switch (this.autoFocus) {
318 case false:
319 case 'dialog':
320 return;
321 case true:
322 case 'first-tabbable':
323 this._focusTrap.focusInitialElementWhenReady().then(hasMovedFocus => {
324 if (!hasMovedFocus && typeof this._elementRef.nativeElement.focus === 'function') {
325 element.focus();
326 }
327 });
328 break;
329 case 'first-heading':
330 this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role="heading"]');
331 break;
332 default:
333 this._focusByCssSelector(this.autoFocus);
334 break;
335 }
336 }
337 /**
338 * Restores focus to the element that was originally focused when the drawer opened.
339 * If no element was focused at that time, the focus will be restored to the drawer.
340 */
341 _restoreFocus(focusOrigin) {
342 if (this.autoFocus === 'dialog') {
343 return;
344 }
345 if (this._elementFocusedBeforeDrawerWasOpened) {
346 this._focusMonitor.focusVia(this._elementFocusedBeforeDrawerWasOpened, focusOrigin);
347 }
348 else {
349 this._elementRef.nativeElement.blur();
350 }
351 this._elementFocusedBeforeDrawerWasOpened = null;
352 }
353 /** Whether focus is currently within the drawer. */
354 _isFocusWithinDrawer() {
355 const activeEl = this._doc.activeElement;
356 return !!activeEl && this._elementRef.nativeElement.contains(activeEl);
357 }
358 ngAfterViewInit() {
359 this._isAttached = true;
360 this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
361 this._updateFocusTrapState();
362 // Only update the DOM position when the sidenav is positioned at
363 // the end since we project the sidenav before the content by default.
364 if (this._position === 'end') {
365 this._updatePositionInParent('end');
366 }
367 }
368 ngAfterContentChecked() {
369 // Enable the animations after the lifecycle hooks have run, in order to avoid animating
370 // drawers that are open by default. When we're on the server, we shouldn't enable the
371 // animations, because we don't want the drawer to animate the first time the user sees
372 // the page.
373 if (this._platform.isBrowser) {
374 this._enableAnimations = true;
375 }
376 }
377 ngOnDestroy() {
378 var _a;
379 if (this._focusTrap) {
380 this._focusTrap.destroy();
381 }
382 (_a = this._anchor) === null || _a === void 0 ? void 0 : _a.remove();
383 this._anchor = null;
384 this._animationStarted.complete();
385 this._animationEnd.complete();
386 this._modeChanged.complete();
387 this._destroyed.next();
388 this._destroyed.complete();
389 }
390 /**
391 * Open the drawer.
392 * @param openedVia Whether the drawer was opened by a key press, mouse click or programmatically.
393 * Used for focus management after the sidenav is closed.
394 */
395 open(openedVia) {
396 return this.toggle(true, openedVia);
397 }
398 /** Close the drawer. */
399 close() {
400 return this.toggle(false);
401 }
402 /** Closes the drawer with context that the backdrop was clicked. */
403 _closeViaBackdropClick() {
404 // If the drawer is closed upon a backdrop click, we always want to restore focus. We
405 // don't need to check whether focus is currently in the drawer, as clicking on the
406 // backdrop causes blurs the active element.
407 return this._setOpen(/* isOpen */ false, /* restoreFocus */ true, 'mouse');
408 }
409 /**
410 * Toggle this drawer.
411 * @param isOpen Whether the drawer should be open.
412 * @param openedVia Whether the drawer was opened by a key press, mouse click or programmatically.
413 * Used for focus management after the sidenav is closed.
414 */
415 toggle(isOpen = !this.opened, openedVia) {
416 // If the focus is currently inside the drawer content and we are closing the drawer,
417 // restore the focus to the initially focused element (when the drawer opened).
418 if (isOpen && openedVia) {
419 this._openedVia = openedVia;
420 }
421 const result = this._setOpen(isOpen,
422 /* restoreFocus */ !isOpen && this._isFocusWithinDrawer(), this._openedVia || 'program');
423 if (!isOpen) {
424 this._openedVia = null;
425 }
426 return result;
427 }
428 /**
429 * Toggles the opened state of the drawer.
430 * @param isOpen Whether the drawer should open or close.
431 * @param restoreFocus Whether focus should be restored on close.
432 * @param focusOrigin Origin to use when restoring focus.
433 */
434 _setOpen(isOpen, restoreFocus, focusOrigin) {
435 this._opened = isOpen;
436 if (isOpen) {
437 this._animationState = this._enableAnimations ? 'open' : 'open-instant';
438 }
439 else {
440 this._animationState = 'void';
441 if (restoreFocus) {
442 this._restoreFocus(focusOrigin);
443 }
444 }
445 this._updateFocusTrapState();
446 return new Promise(resolve => {
447 this.openedChange.pipe(take(1)).subscribe(open => resolve(open ? 'open' : 'close'));
448 });
449 }
450 _getWidth() {
451 return this._elementRef.nativeElement ? this._elementRef.nativeElement.offsetWidth || 0 : 0;
452 }
453 /** Updates the enabled state of the focus trap. */
454 _updateFocusTrapState() {
455 if (this._focusTrap) {
456 // The focus trap is only enabled when the drawer is open in any mode other than side.
457 this._focusTrap.enabled = this.opened && this.mode !== 'side';
458 }
459 }
460 /**
461 * Updates the position of the drawer in the DOM. We need to move the element around ourselves
462 * when it's in the `end` position so that it comes after the content and the visual order
463 * matches the tab order. We also need to be able to move it back to `start` if the sidenav
464 * started off as `end` and was changed to `start`.
465 */
466 _updatePositionInParent(newPosition) {
467 const element = this._elementRef.nativeElement;
468 const parent = element.parentNode;
469 if (newPosition === 'end') {
470 if (!this._anchor) {
471 this._anchor = this._doc.createComment('mat-drawer-anchor');
472 parent.insertBefore(this._anchor, element);
473 }
474 parent.appendChild(element);
475 }
476 else if (this._anchor) {
477 this._anchor.parentNode.insertBefore(element, this._anchor);
478 }
479 }
480}
481MatDrawer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawer, deps: [{ token: i0.ElementRef }, { token: i2.FocusTrapFactory }, { token: i2.FocusMonitor }, { token: i3.Platform }, { token: i0.NgZone }, { token: i2.InteractivityChecker }, { token: DOCUMENT, optional: true }, { token: MAT_DRAWER_CONTAINER, optional: true }], target: i0.ɵɵFactoryTarget.Component });
482MatDrawer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatDrawer, selector: "mat-drawer", inputs: { position: "position", mode: "mode", disableClose: "disableClose", autoFocus: "autoFocus", opened: "opened" }, outputs: { openedChange: "openedChange", _openedStream: "opened", openedStart: "openedStart", _closedStream: "closed", closedStart: "closedStart", onPositionChanged: "positionChanged" }, host: { attributes: { "tabIndex": "-1" }, listeners: { "@transform.start": "_animationStarted.next($event)", "@transform.done": "_animationEnd.next($event)" }, properties: { "attr.align": "null", "class.mat-drawer-end": "position === \"end\"", "class.mat-drawer-over": "mode === \"over\"", "class.mat-drawer-push": "mode === \"push\"", "class.mat-drawer-side": "mode === \"side\"", "class.mat-drawer-opened": "opened", "@transform": "_animationState" }, classAttribute: "mat-drawer" }, viewQueries: [{ propertyName: "_content", first: true, predicate: ["content"], descendants: true }], exportAs: ["matDrawer"], ngImport: i0, template: "<div class=\"mat-drawer-inner-container\" cdkScrollable #content>\r\n <ng-content></ng-content>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i1.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }], animations: [matDrawerAnimations.transformDrawer], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
483i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawer, decorators: [{
484 type: Component,
485 args: [{ selector: 'mat-drawer', exportAs: 'matDrawer', animations: [matDrawerAnimations.transformDrawer], host: {
486 'class': 'mat-drawer',
487 // must prevent the browser from aligning text based on value
488 '[attr.align]': 'null',
489 '[class.mat-drawer-end]': 'position === "end"',
490 '[class.mat-drawer-over]': 'mode === "over"',
491 '[class.mat-drawer-push]': 'mode === "push"',
492 '[class.mat-drawer-side]': 'mode === "side"',
493 '[class.mat-drawer-opened]': 'opened',
494 'tabIndex': '-1',
495 '[@transform]': '_animationState',
496 '(@transform.start)': '_animationStarted.next($event)',
497 '(@transform.done)': '_animationEnd.next($event)',
498 }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"mat-drawer-inner-container\" cdkScrollable #content>\r\n <ng-content></ng-content>\r\n</div>\r\n" }]
499 }], ctorParameters: function () {
500 return [{ type: i0.ElementRef }, { type: i2.FocusTrapFactory }, { type: i2.FocusMonitor }, { type: i3.Platform }, { type: i0.NgZone }, { type: i2.InteractivityChecker }, { type: undefined, decorators: [{
501 type: Optional
502 }, {
503 type: Inject,
504 args: [DOCUMENT]
505 }] }, { type: MatDrawerContainer, decorators: [{
506 type: Optional
507 }, {
508 type: Inject,
509 args: [MAT_DRAWER_CONTAINER]
510 }] }];
511 }, propDecorators: { position: [{
512 type: Input
513 }], mode: [{
514 type: Input
515 }], disableClose: [{
516 type: Input
517 }], autoFocus: [{
518 type: Input
519 }], opened: [{
520 type: Input
521 }], openedChange: [{
522 type: Output
523 }], _openedStream: [{
524 type: Output,
525 args: ['opened']
526 }], openedStart: [{
527 type: Output
528 }], _closedStream: [{
529 type: Output,
530 args: ['closed']
531 }], closedStart: [{
532 type: Output
533 }], onPositionChanged: [{
534 type: Output,
535 args: ['positionChanged']
536 }], _content: [{
537 type: ViewChild,
538 args: ['content']
539 }] } });
540/**
541 * `<mat-drawer-container>` component.
542 *
543 * This is the parent component to one or two `<mat-drawer>`s that validates the state internally
544 * and coordinates the backdrop and content styling.
545 */
546class MatDrawerContainer {
547 constructor(_dir, _element, _ngZone, _changeDetectorRef, viewportRuler, defaultAutosize = false, _animationMode) {
548 this._dir = _dir;
549 this._element = _element;
550 this._ngZone = _ngZone;
551 this._changeDetectorRef = _changeDetectorRef;
552 this._animationMode = _animationMode;
553 /** Drawers that belong to this container. */
554 this._drawers = new QueryList();
555 /** Event emitted when the drawer backdrop is clicked. */
556 this.backdropClick = new EventEmitter();
557 /** Emits when the component is destroyed. */
558 this._destroyed = new Subject();
559 /** Emits on every ngDoCheck. Used for debouncing reflows. */
560 this._doCheckSubject = new Subject();
561 /**
562 * Margins to be applied to the content. These are used to push / shrink the drawer content when a
563 * drawer is open. We use margin rather than transform even for push mode because transform breaks
564 * fixed position elements inside of the transformed element.
565 */
566 this._contentMargins = { left: null, right: null };
567 this._contentMarginChanges = new Subject();
568 // If a `Dir` directive exists up the tree, listen direction changes
569 // and update the left/right properties to point to the proper start/end.
570 if (_dir) {
571 _dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => {
572 this._validateDrawers();
573 this.updateContentMargins();
574 });
575 }
576 // Since the minimum width of the sidenav depends on the viewport width,
577 // we need to recompute the margins if the viewport changes.
578 viewportRuler
579 .change()
580 .pipe(takeUntil(this._destroyed))
581 .subscribe(() => this.updateContentMargins());
582 this._autosize = defaultAutosize;
583 }
584 /** The drawer child with the `start` position. */
585 get start() {
586 return this._start;
587 }
588 /** The drawer child with the `end` position. */
589 get end() {
590 return this._end;
591 }
592 /**
593 * Whether to automatically resize the container whenever
594 * the size of any of its drawers changes.
595 *
596 * **Use at your own risk!** Enabling this option can cause layout thrashing by measuring
597 * the drawers on every change detection cycle. Can be configured globally via the
598 * `MAT_DRAWER_DEFAULT_AUTOSIZE` token.
599 */
600 get autosize() {
601 return this._autosize;
602 }
603 set autosize(value) {
604 this._autosize = coerceBooleanProperty(value);
605 }
606 /**
607 * Whether the drawer container should have a backdrop while one of the sidenavs is open.
608 * If explicitly set to `true`, the backdrop will be enabled for drawers in the `side`
609 * mode as well.
610 */
611 get hasBackdrop() {
612 if (this._backdropOverride == null) {
613 return !this._start || this._start.mode !== 'side' || !this._end || this._end.mode !== 'side';
614 }
615 return this._backdropOverride;
616 }
617 set hasBackdrop(value) {
618 this._backdropOverride = value == null ? null : coerceBooleanProperty(value);
619 }
620 /** Reference to the CdkScrollable instance that wraps the scrollable content. */
621 get scrollable() {
622 return this._userContent || this._content;
623 }
624 ngAfterContentInit() {
625 this._allDrawers.changes
626 .pipe(startWith(this._allDrawers), takeUntil(this._destroyed))
627 .subscribe((drawer) => {
628 this._drawers.reset(drawer.filter(item => !item._container || item._container === this));
629 this._drawers.notifyOnChanges();
630 });
631 this._drawers.changes.pipe(startWith(null)).subscribe(() => {
632 this._validateDrawers();
633 this._drawers.forEach((drawer) => {
634 this._watchDrawerToggle(drawer);
635 this._watchDrawerPosition(drawer);
636 this._watchDrawerMode(drawer);
637 });
638 if (!this._drawers.length ||
639 this._isDrawerOpen(this._start) ||
640 this._isDrawerOpen(this._end)) {
641 this.updateContentMargins();
642 }
643 this._changeDetectorRef.markForCheck();
644 });
645 // Avoid hitting the NgZone through the debounce timeout.
646 this._ngZone.runOutsideAngular(() => {
647 this._doCheckSubject
648 .pipe(debounceTime(10), // Arbitrary debounce time, less than a frame at 60fps
649 takeUntil(this._destroyed))
650 .subscribe(() => this.updateContentMargins());
651 });
652 }
653 ngOnDestroy() {
654 this._contentMarginChanges.complete();
655 this._doCheckSubject.complete();
656 this._drawers.destroy();
657 this._destroyed.next();
658 this._destroyed.complete();
659 }
660 /** Calls `open` of both start and end drawers */
661 open() {
662 this._drawers.forEach(drawer => drawer.open());
663 }
664 /** Calls `close` of both start and end drawers */
665 close() {
666 this._drawers.forEach(drawer => drawer.close());
667 }
668 /**
669 * Recalculates and updates the inline styles for the content. Note that this should be used
670 * sparingly, because it causes a reflow.
671 */
672 updateContentMargins() {
673 // 1. For drawers in `over` mode, they don't affect the content.
674 // 2. For drawers in `side` mode they should shrink the content. We do this by adding to the
675 // left margin (for left drawer) or right margin (for right the drawer).
676 // 3. For drawers in `push` mode the should shift the content without resizing it. We do this by
677 // adding to the left or right margin and simultaneously subtracting the same amount of
678 // margin from the other side.
679 let left = 0;
680 let right = 0;
681 if (this._left && this._left.opened) {
682 if (this._left.mode == 'side') {
683 left += this._left._getWidth();
684 }
685 else if (this._left.mode == 'push') {
686 const width = this._left._getWidth();
687 left += width;
688 right -= width;
689 }
690 }
691 if (this._right && this._right.opened) {
692 if (this._right.mode == 'side') {
693 right += this._right._getWidth();
694 }
695 else if (this._right.mode == 'push') {
696 const width = this._right._getWidth();
697 right += width;
698 left -= width;
699 }
700 }
701 // If either `right` or `left` is zero, don't set a style to the element. This
702 // allows users to specify a custom size via CSS class in SSR scenarios where the
703 // measured widths will always be zero. Note that we reset to `null` here, rather
704 // than below, in order to ensure that the types in the `if` below are consistent.
705 left = left || null;
706 right = right || null;
707 if (left !== this._contentMargins.left || right !== this._contentMargins.right) {
708 this._contentMargins = { left, right };
709 // Pull back into the NgZone since in some cases we could be outside. We need to be careful
710 // to do it only when something changed, otherwise we can end up hitting the zone too often.
711 this._ngZone.run(() => this._contentMarginChanges.next(this._contentMargins));
712 }
713 }
714 ngDoCheck() {
715 // If users opted into autosizing, do a check every change detection cycle.
716 if (this._autosize && this._isPushed()) {
717 // Run outside the NgZone, otherwise the debouncer will throw us into an infinite loop.
718 this._ngZone.runOutsideAngular(() => this._doCheckSubject.next());
719 }
720 }
721 /**
722 * Subscribes to drawer events in order to set a class on the main container element when the
723 * drawer is open and the backdrop is visible. This ensures any overflow on the container element
724 * is properly hidden.
725 */
726 _watchDrawerToggle(drawer) {
727 drawer._animationStarted
728 .pipe(filter((event) => event.fromState !== event.toState), takeUntil(this._drawers.changes))
729 .subscribe((event) => {
730 // Set the transition class on the container so that the animations occur. This should not
731 // be set initially because animations should only be triggered via a change in state.
732 if (event.toState !== 'open-instant' && this._animationMode !== 'NoopAnimations') {
733 this._element.nativeElement.classList.add('mat-drawer-transition');
734 }
735 this.updateContentMargins();
736 this._changeDetectorRef.markForCheck();
737 });
738 if (drawer.mode !== 'side') {
739 drawer.openedChange
740 .pipe(takeUntil(this._drawers.changes))
741 .subscribe(() => this._setContainerClass(drawer.opened));
742 }
743 }
744 /**
745 * Subscribes to drawer onPositionChanged event in order to
746 * re-validate drawers when the position changes.
747 */
748 _watchDrawerPosition(drawer) {
749 if (!drawer) {
750 return;
751 }
752 // NOTE: We need to wait for the microtask queue to be empty before validating,
753 // since both drawers may be swapping positions at the same time.
754 drawer.onPositionChanged.pipe(takeUntil(this._drawers.changes)).subscribe(() => {
755 this._ngZone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {
756 this._validateDrawers();
757 });
758 });
759 }
760 /** Subscribes to changes in drawer mode so we can run change detection. */
761 _watchDrawerMode(drawer) {
762 if (drawer) {
763 drawer._modeChanged
764 .pipe(takeUntil(merge(this._drawers.changes, this._destroyed)))
765 .subscribe(() => {
766 this.updateContentMargins();
767 this._changeDetectorRef.markForCheck();
768 });
769 }
770 }
771 /** Toggles the 'mat-drawer-opened' class on the main 'mat-drawer-container' element. */
772 _setContainerClass(isAdd) {
773 const classList = this._element.nativeElement.classList;
774 const className = 'mat-drawer-container-has-open';
775 if (isAdd) {
776 classList.add(className);
777 }
778 else {
779 classList.remove(className);
780 }
781 }
782 /** Validate the state of the drawer children components. */
783 _validateDrawers() {
784 this._start = this._end = null;
785 // Ensure that we have at most one start and one end drawer.
786 this._drawers.forEach(drawer => {
787 if (drawer.position == 'end') {
788 if (this._end != null && (typeof ngDevMode === 'undefined' || ngDevMode)) {
789 throwMatDuplicatedDrawerError('end');
790 }
791 this._end = drawer;
792 }
793 else {
794 if (this._start != null && (typeof ngDevMode === 'undefined' || ngDevMode)) {
795 throwMatDuplicatedDrawerError('start');
796 }
797 this._start = drawer;
798 }
799 });
800 this._right = this._left = null;
801 // Detect if we're LTR or RTL.
802 if (this._dir && this._dir.value === 'rtl') {
803 this._left = this._end;
804 this._right = this._start;
805 }
806 else {
807 this._left = this._start;
808 this._right = this._end;
809 }
810 }
811 /** Whether the container is being pushed to the side by one of the drawers. */
812 _isPushed() {
813 return ((this._isDrawerOpen(this._start) && this._start.mode != 'over') ||
814 (this._isDrawerOpen(this._end) && this._end.mode != 'over'));
815 }
816 _onBackdropClicked() {
817 this.backdropClick.emit();
818 this._closeModalDrawersViaBackdrop();
819 }
820 _closeModalDrawersViaBackdrop() {
821 // Close all open drawers where closing is not disabled and the mode is not `side`.
822 [this._start, this._end]
823 .filter(drawer => drawer && !drawer.disableClose && this._canHaveBackdrop(drawer))
824 .forEach(drawer => drawer._closeViaBackdropClick());
825 }
826 _isShowingBackdrop() {
827 return ((this._isDrawerOpen(this._start) && this._canHaveBackdrop(this._start)) ||
828 (this._isDrawerOpen(this._end) && this._canHaveBackdrop(this._end)));
829 }
830 _canHaveBackdrop(drawer) {
831 return drawer.mode !== 'side' || !!this._backdropOverride;
832 }
833 _isDrawerOpen(drawer) {
834 return drawer != null && drawer.opened;
835 }
836}
837MatDrawerContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawerContainer, deps: [{ token: i4.Directionality, optional: true }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.ViewportRuler }, { token: MAT_DRAWER_DEFAULT_AUTOSIZE }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
838MatDrawerContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatDrawerContainer, selector: "mat-drawer-container", inputs: { autosize: "autosize", hasBackdrop: "hasBackdrop" }, outputs: { backdropClick: "backdropClick" }, host: { properties: { "class.mat-drawer-container-explicit-backdrop": "_backdropOverride" }, classAttribute: "mat-drawer-container" }, providers: [
839 {
840 provide: MAT_DRAWER_CONTAINER,
841 useExisting: MatDrawerContainer,
842 },
843 ], queries: [{ propertyName: "_content", first: true, predicate: MatDrawerContent, descendants: true }, { propertyName: "_allDrawers", predicate: MatDrawer, descendants: true }], viewQueries: [{ propertyName: "_userContent", first: true, predicate: MatDrawerContent, descendants: true }], exportAs: ["matDrawerContainer"], ngImport: i0, template: "<div class=\"mat-drawer-backdrop\" (click)=\"_onBackdropClicked()\" *ngIf=\"hasBackdrop\"\n [class.mat-drawer-shown]=\"_isShowingBackdrop()\"></div>\n\n<ng-content select=\"mat-drawer\"></ng-content>\n\n<ng-content select=\"mat-drawer-content\">\n</ng-content>\n<mat-drawer-content *ngIf=\"!_content\">\n <ng-content></ng-content>\n</mat-drawer-content>\n", styles: [".mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-container-has-open{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:background-color,visibility}.cdk-high-contrast-active .mat-drawer-backdrop{opacity:.5}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%, 0, 0)}.cdk-high-contrast-active .mat-drawer,.cdk-high-contrast-active [dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}.cdk-high-contrast-active [dir=rtl] .mat-drawer,.cdk-high-contrast-active .mat-drawer.mat-drawer-end{border-left:solid 1px currentColor;border-right:none}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer{transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%, 0, 0)}.mat-drawer[style*=\"visibility: hidden\"]{display:none}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MatDrawerContent, selector: "mat-drawer-content" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
844i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatDrawerContainer, decorators: [{
845 type: Component,
846 args: [{ selector: 'mat-drawer-container', exportAs: 'matDrawerContainer', host: {
847 'class': 'mat-drawer-container',
848 '[class.mat-drawer-container-explicit-backdrop]': '_backdropOverride',
849 }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
850 {
851 provide: MAT_DRAWER_CONTAINER,
852 useExisting: MatDrawerContainer,
853 },
854 ], template: "<div class=\"mat-drawer-backdrop\" (click)=\"_onBackdropClicked()\" *ngIf=\"hasBackdrop\"\n [class.mat-drawer-shown]=\"_isShowingBackdrop()\"></div>\n\n<ng-content select=\"mat-drawer\"></ng-content>\n\n<ng-content select=\"mat-drawer-content\">\n</ng-content>\n<mat-drawer-content *ngIf=\"!_content\">\n <ng-content></ng-content>\n</mat-drawer-content>\n", styles: [".mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-container-has-open{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:background-color,visibility}.cdk-high-contrast-active .mat-drawer-backdrop{opacity:.5}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%, 0, 0)}.cdk-high-contrast-active .mat-drawer,.cdk-high-contrast-active [dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}.cdk-high-contrast-active [dir=rtl] .mat-drawer,.cdk-high-contrast-active .mat-drawer.mat-drawer-end{border-left:solid 1px currentColor;border-right:none}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer{transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%, 0, 0)}.mat-drawer[style*=\"visibility: hidden\"]{display:none}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}"] }]
855 }], ctorParameters: function () {
856 return [{ type: i4.Directionality, decorators: [{
857 type: Optional
858 }] }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.ViewportRuler }, { type: undefined, decorators: [{
859 type: Inject,
860 args: [MAT_DRAWER_DEFAULT_AUTOSIZE]
861 }] }, { type: undefined, decorators: [{
862 type: Optional
863 }, {
864 type: Inject,
865 args: [ANIMATION_MODULE_TYPE]
866 }] }];
867 }, propDecorators: { _allDrawers: [{
868 type: ContentChildren,
869 args: [MatDrawer, {
870 // We need to use `descendants: true`, because Ivy will no longer match
871 // indirect descendants if it's left as false.
872 descendants: true,
873 }]
874 }], _content: [{
875 type: ContentChild,
876 args: [MatDrawerContent]
877 }], _userContent: [{
878 type: ViewChild,
879 args: [MatDrawerContent]
880 }], autosize: [{
881 type: Input
882 }], hasBackdrop: [{
883 type: Input
884 }], backdropClick: [{
885 type: Output
886 }] } });
887
888/**
889 * @license
890 * Copyright Google LLC All Rights Reserved.
891 *
892 * Use of this source code is governed by an MIT-style license that can be
893 * found in the LICENSE file at https://angular.io/license
894 */
895class MatSidenavContent extends MatDrawerContent {
896 constructor(changeDetectorRef, container, elementRef, scrollDispatcher, ngZone) {
897 super(changeDetectorRef, container, elementRef, scrollDispatcher, ngZone);
898 }
899}
900MatSidenavContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavContent, deps: [{ token: i0.ChangeDetectorRef }, { token: forwardRef(() => MatSidenavContainer) }, { token: i0.ElementRef }, { token: i1.ScrollDispatcher }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
901MatSidenavContent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatSidenavContent, selector: "mat-sidenav-content", host: { properties: { "style.margin-left.px": "_container._contentMargins.left", "style.margin-right.px": "_container._contentMargins.right" }, classAttribute: "mat-drawer-content mat-sidenav-content" }, providers: [
902 {
903 provide: CdkScrollable,
904 useExisting: MatSidenavContent,
905 },
906 ], usesInheritance: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
907i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavContent, decorators: [{
908 type: Component,
909 args: [{
910 selector: 'mat-sidenav-content',
911 template: '<ng-content></ng-content>',
912 host: {
913 'class': 'mat-drawer-content mat-sidenav-content',
914 '[style.margin-left.px]': '_container._contentMargins.left',
915 '[style.margin-right.px]': '_container._contentMargins.right',
916 },
917 changeDetection: ChangeDetectionStrategy.OnPush,
918 encapsulation: ViewEncapsulation.None,
919 providers: [
920 {
921 provide: CdkScrollable,
922 useExisting: MatSidenavContent,
923 },
924 ],
925 }]
926 }], ctorParameters: function () {
927 return [{ type: i0.ChangeDetectorRef }, { type: MatSidenavContainer, decorators: [{
928 type: Inject,
929 args: [forwardRef(() => MatSidenavContainer)]
930 }] }, { type: i0.ElementRef }, { type: i1.ScrollDispatcher }, { type: i0.NgZone }];
931 } });
932class MatSidenav extends MatDrawer {
933 constructor() {
934 super(...arguments);
935 this._fixedInViewport = false;
936 this._fixedTopGap = 0;
937 this._fixedBottomGap = 0;
938 }
939 /** Whether the sidenav is fixed in the viewport. */
940 get fixedInViewport() {
941 return this._fixedInViewport;
942 }
943 set fixedInViewport(value) {
944 this._fixedInViewport = coerceBooleanProperty(value);
945 }
946 /**
947 * The gap between the top of the sidenav and the top of the viewport when the sidenav is in fixed
948 * mode.
949 */
950 get fixedTopGap() {
951 return this._fixedTopGap;
952 }
953 set fixedTopGap(value) {
954 this._fixedTopGap = coerceNumberProperty(value);
955 }
956 /**
957 * The gap between the bottom of the sidenav and the bottom of the viewport when the sidenav is in
958 * fixed mode.
959 */
960 get fixedBottomGap() {
961 return this._fixedBottomGap;
962 }
963 set fixedBottomGap(value) {
964 this._fixedBottomGap = coerceNumberProperty(value);
965 }
966}
967MatSidenav.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenav, deps: null, target: i0.ɵɵFactoryTarget.Component });
968MatSidenav.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatSidenav, selector: "mat-sidenav", inputs: { fixedInViewport: "fixedInViewport", fixedTopGap: "fixedTopGap", fixedBottomGap: "fixedBottomGap" }, host: { attributes: { "tabIndex": "-1" }, properties: { "attr.align": "null", "class.mat-drawer-end": "position === \"end\"", "class.mat-drawer-over": "mode === \"over\"", "class.mat-drawer-push": "mode === \"push\"", "class.mat-drawer-side": "mode === \"side\"", "class.mat-drawer-opened": "opened", "class.mat-sidenav-fixed": "fixedInViewport", "style.top.px": "fixedInViewport ? fixedTopGap : null", "style.bottom.px": "fixedInViewport ? fixedBottomGap : null" }, classAttribute: "mat-drawer mat-sidenav" }, exportAs: ["matSidenav"], usesInheritance: true, ngImport: i0, template: "<div class=\"mat-drawer-inner-container\" cdkScrollable #content>\r\n <ng-content></ng-content>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i1.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }], animations: [matDrawerAnimations.transformDrawer], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
969i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenav, decorators: [{
970 type: Component,
971 args: [{ selector: 'mat-sidenav', exportAs: 'matSidenav', animations: [matDrawerAnimations.transformDrawer], host: {
972 'class': 'mat-drawer mat-sidenav',
973 'tabIndex': '-1',
974 // must prevent the browser from aligning text based on value
975 '[attr.align]': 'null',
976 '[class.mat-drawer-end]': 'position === "end"',
977 '[class.mat-drawer-over]': 'mode === "over"',
978 '[class.mat-drawer-push]': 'mode === "push"',
979 '[class.mat-drawer-side]': 'mode === "side"',
980 '[class.mat-drawer-opened]': 'opened',
981 '[class.mat-sidenav-fixed]': 'fixedInViewport',
982 '[style.top.px]': 'fixedInViewport ? fixedTopGap : null',
983 '[style.bottom.px]': 'fixedInViewport ? fixedBottomGap : null',
984 }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"mat-drawer-inner-container\" cdkScrollable #content>\r\n <ng-content></ng-content>\r\n</div>\r\n" }]
985 }], propDecorators: { fixedInViewport: [{
986 type: Input
987 }], fixedTopGap: [{
988 type: Input
989 }], fixedBottomGap: [{
990 type: Input
991 }] } });
992class MatSidenavContainer extends MatDrawerContainer {
993}
994MatSidenavContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavContainer, deps: null, target: i0.ɵɵFactoryTarget.Component });
995MatSidenavContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatSidenavContainer, selector: "mat-sidenav-container", host: { properties: { "class.mat-drawer-container-explicit-backdrop": "_backdropOverride" }, classAttribute: "mat-drawer-container mat-sidenav-container" }, providers: [
996 {
997 provide: MAT_DRAWER_CONTAINER,
998 useExisting: MatSidenavContainer,
999 },
1000 ], queries: [{ propertyName: "_content", first: true, predicate: MatSidenavContent, descendants: true }, { propertyName: "_allDrawers", predicate: MatSidenav, descendants: true }], exportAs: ["matSidenavContainer"], usesInheritance: true, ngImport: i0, template: "<div class=\"mat-drawer-backdrop\" (click)=\"_onBackdropClicked()\" *ngIf=\"hasBackdrop\"\n [class.mat-drawer-shown]=\"_isShowingBackdrop()\"></div>\n\n<ng-content select=\"mat-sidenav\"></ng-content>\n\n<ng-content select=\"mat-sidenav-content\">\n</ng-content>\n<mat-sidenav-content *ngIf=\"!_content\">\n <ng-content></ng-content>\n</mat-sidenav-content>\n", styles: [".mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-container-has-open{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:background-color,visibility}.cdk-high-contrast-active .mat-drawer-backdrop{opacity:.5}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%, 0, 0)}.cdk-high-contrast-active .mat-drawer,.cdk-high-contrast-active [dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}.cdk-high-contrast-active [dir=rtl] .mat-drawer,.cdk-high-contrast-active .mat-drawer.mat-drawer-end{border-left:solid 1px currentColor;border-right:none}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer{transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%, 0, 0)}.mat-drawer[style*=\"visibility: hidden\"]{display:none}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MatSidenavContent, selector: "mat-sidenav-content" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1001i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavContainer, decorators: [{
1002 type: Component,
1003 args: [{ selector: 'mat-sidenav-container', exportAs: 'matSidenavContainer', host: {
1004 'class': 'mat-drawer-container mat-sidenav-container',
1005 '[class.mat-drawer-container-explicit-backdrop]': '_backdropOverride',
1006 }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1007 {
1008 provide: MAT_DRAWER_CONTAINER,
1009 useExisting: MatSidenavContainer,
1010 },
1011 ], template: "<div class=\"mat-drawer-backdrop\" (click)=\"_onBackdropClicked()\" *ngIf=\"hasBackdrop\"\n [class.mat-drawer-shown]=\"_isShowingBackdrop()\"></div>\n\n<ng-content select=\"mat-sidenav\"></ng-content>\n\n<ng-content select=\"mat-sidenav-content\">\n</ng-content>\n<mat-sidenav-content *ngIf=\"!_content\">\n <ng-content></ng-content>\n</mat-sidenav-content>\n", styles: [".mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-container-has-open{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:background-color,visibility}.cdk-high-contrast-active .mat-drawer-backdrop{opacity:.5}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:400ms;transition-timing-function:cubic-bezier(0.25, 0.8, 0.25, 1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%, 0, 0)}.cdk-high-contrast-active .mat-drawer,.cdk-high-contrast-active [dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}.cdk-high-contrast-active [dir=rtl] .mat-drawer,.cdk-high-contrast-active .mat-drawer.mat-drawer-end{border-left:solid 1px currentColor;border-right:none}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer{transform:translate3d(100%, 0, 0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%, 0, 0)}.mat-drawer[style*=\"visibility: hidden\"]{display:none}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}"] }]
1012 }], propDecorators: { _allDrawers: [{
1013 type: ContentChildren,
1014 args: [MatSidenav, {
1015 // We need to use `descendants: true`, because Ivy will no longer match
1016 // indirect descendants if it's left as false.
1017 descendants: true,
1018 }]
1019 }], _content: [{
1020 type: ContentChild,
1021 args: [MatSidenavContent]
1022 }] } });
1023
1024/**
1025 * @license
1026 * Copyright Google LLC All Rights Reserved.
1027 *
1028 * Use of this source code is governed by an MIT-style license that can be
1029 * found in the LICENSE file at https://angular.io/license
1030 */
1031class MatSidenavModule {
1032}
1033MatSidenavModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1034MatSidenavModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavModule, declarations: [MatDrawer,
1035 MatDrawerContainer,
1036 MatDrawerContent,
1037 MatSidenav,
1038 MatSidenavContainer,
1039 MatSidenavContent], imports: [CommonModule, MatCommonModule, CdkScrollableModule], exports: [CdkScrollableModule,
1040 MatCommonModule,
1041 MatDrawer,
1042 MatDrawerContainer,
1043 MatDrawerContent,
1044 MatSidenav,
1045 MatSidenavContainer,
1046 MatSidenavContent] });
1047MatSidenavModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavModule, imports: [CommonModule, MatCommonModule, CdkScrollableModule, CdkScrollableModule,
1048 MatCommonModule] });
1049i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatSidenavModule, decorators: [{
1050 type: NgModule,
1051 args: [{
1052 imports: [CommonModule, MatCommonModule, CdkScrollableModule],
1053 exports: [
1054 CdkScrollableModule,
1055 MatCommonModule,
1056 MatDrawer,
1057 MatDrawerContainer,
1058 MatDrawerContent,
1059 MatSidenav,
1060 MatSidenavContainer,
1061 MatSidenavContent,
1062 ],
1063 declarations: [
1064 MatDrawer,
1065 MatDrawerContainer,
1066 MatDrawerContent,
1067 MatSidenav,
1068 MatSidenavContainer,
1069 MatSidenavContent,
1070 ],
1071 }]
1072 }] });
1073
1074/**
1075 * @license
1076 * Copyright Google LLC All Rights Reserved.
1077 *
1078 * Use of this source code is governed by an MIT-style license that can be
1079 * found in the LICENSE file at https://angular.io/license
1080 */
1081
1082/**
1083 * @license
1084 * Copyright Google LLC All Rights Reserved.
1085 *
1086 * Use of this source code is governed by an MIT-style license that can be
1087 * found in the LICENSE file at https://angular.io/license
1088 */
1089
1090/**
1091 * Generated bundle index. Do not edit.
1092 */
1093
1094export { MAT_DRAWER_DEFAULT_AUTOSIZE, MAT_DRAWER_DEFAULT_AUTOSIZE_FACTORY, MatDrawer, MatDrawerContainer, MatDrawerContent, MatSidenav, MatSidenavContainer, MatSidenavContent, MatSidenavModule, matDrawerAnimations, throwMatDuplicatedDrawerError };
1095//# sourceMappingURL=sidenav.mjs.map