source: trip-planner-front/node_modules/@angular/material/fesm2015/bottom-sheet.js@ ceaed42

Last change on this file since ceaed42 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 24.6 KB
Line 
1import * as i1 from '@angular/cdk/overlay';
2import { OverlayModule, OverlayConfig, Overlay } from '@angular/cdk/overlay';
3import { BasePortalOutlet, CdkPortalOutlet, PortalModule, TemplatePortal, ComponentPortal } from '@angular/cdk/portal';
4import * as i0 from '@angular/core';
5import { InjectionToken, EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, ChangeDetectorRef, Optional, Inject, ViewChild, NgModule, TemplateRef, Injector, InjectFlags, Injectable, SkipSelf } from '@angular/core';
6import { AnimationDurations, AnimationCurves, MatCommonModule } from '@angular/material/core';
7import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
8import { trigger, state, style, transition, animate } from '@angular/animations';
9import { DOCUMENT } from '@angular/common';
10import { FocusTrapFactory } from '@angular/cdk/a11y';
11import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform';
12import { Directionality } from '@angular/cdk/bidi';
13import { Subject, merge, of } from 'rxjs';
14import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
15import { filter, take } from 'rxjs/operators';
16
17/**
18 * @license
19 * Copyright Google LLC All Rights Reserved.
20 *
21 * Use of this source code is governed by an MIT-style license that can be
22 * found in the LICENSE file at https://angular.io/license
23 */
24/** Injection token that can be used to access the data that was passed in to a bottom sheet. */
25const MAT_BOTTOM_SHEET_DATA = new InjectionToken('MatBottomSheetData');
26/**
27 * Configuration used when opening a bottom sheet.
28 */
29class MatBottomSheetConfig {
30 constructor() {
31 /** Data being injected into the child component. */
32 this.data = null;
33 /** Whether the bottom sheet has a backdrop. */
34 this.hasBackdrop = true;
35 /** Whether the user can use escape or clicking outside to close the bottom sheet. */
36 this.disableClose = false;
37 /** Aria label to assign to the bottom sheet element. */
38 this.ariaLabel = null;
39 /**
40 * Whether the bottom sheet should close when the user goes backwards/forwards in history.
41 * Note that this usually doesn't include clicking on links (unless the user is using
42 * the `HashLocationStrategy`).
43 */
44 this.closeOnNavigation = true;
45 // Note that this is disabled by default, because while the a11y recommendations are to focus
46 // the first focusable element, doing so prevents screen readers from reading out the
47 // rest of the bottom sheet content.
48 /** Whether the bottom sheet should focus the first focusable element on open. */
49 this.autoFocus = false;
50 /**
51 * Whether the bottom sheet should restore focus to the
52 * previously-focused element, after it's closed.
53 */
54 this.restoreFocus = true;
55 }
56}
57
58/**
59 * @license
60 * Copyright Google LLC All Rights Reserved.
61 *
62 * Use of this source code is governed by an MIT-style license that can be
63 * found in the LICENSE file at https://angular.io/license
64 */
65/** Animations used by the Material bottom sheet. */
66const matBottomSheetAnimations = {
67 /** Animation that shows and hides a bottom sheet. */
68 bottomSheetState: trigger('state', [
69 state('void, hidden', style({ transform: 'translateY(100%)' })),
70 state('visible', style({ transform: 'translateY(0%)' })),
71 transition('visible => void, visible => hidden', animate(`${AnimationDurations.COMPLEX} ${AnimationCurves.ACCELERATION_CURVE}`)),
72 transition('void => visible', animate(`${AnimationDurations.EXITING} ${AnimationCurves.DECELERATION_CURVE}`)),
73 ])
74};
75
76/**
77 * @license
78 * Copyright Google LLC All Rights Reserved.
79 *
80 * Use of this source code is governed by an MIT-style license that can be
81 * found in the LICENSE file at https://angular.io/license
82 */
83// TODO(crisbeto): consolidate some logic between this, MatDialog and MatSnackBar
84/**
85 * Internal component that wraps user-provided bottom sheet content.
86 * @docs-private
87 */
88class MatBottomSheetContainer extends BasePortalOutlet {
89 constructor(_elementRef, _changeDetectorRef, _focusTrapFactory, breakpointObserver, document,
90 /** The bottom sheet configuration. */
91 bottomSheetConfig) {
92 super();
93 this._elementRef = _elementRef;
94 this._changeDetectorRef = _changeDetectorRef;
95 this._focusTrapFactory = _focusTrapFactory;
96 this.bottomSheetConfig = bottomSheetConfig;
97 /** The state of the bottom sheet animations. */
98 this._animationState = 'void';
99 /** Emits whenever the state of the animation changes. */
100 this._animationStateChanged = new EventEmitter();
101 /** Element that was focused before the bottom sheet was opened. */
102 this._elementFocusedBeforeOpened = null;
103 /**
104 * Attaches a DOM portal to the bottom sheet container.
105 * @deprecated To be turned into a method.
106 * @breaking-change 10.0.0
107 */
108 this.attachDomPortal = (portal) => {
109 this._validatePortalAttached();
110 this._setPanelClass();
111 this._savePreviouslyFocusedElement();
112 return this._portalOutlet.attachDomPortal(portal);
113 };
114 this._document = document;
115 this._breakpointSubscription = breakpointObserver
116 .observe([Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
117 .subscribe(() => {
118 this._toggleClass('mat-bottom-sheet-container-medium', breakpointObserver.isMatched(Breakpoints.Medium));
119 this._toggleClass('mat-bottom-sheet-container-large', breakpointObserver.isMatched(Breakpoints.Large));
120 this._toggleClass('mat-bottom-sheet-container-xlarge', breakpointObserver.isMatched(Breakpoints.XLarge));
121 });
122 }
123 /** Attach a component portal as content to this bottom sheet container. */
124 attachComponentPortal(portal) {
125 this._validatePortalAttached();
126 this._setPanelClass();
127 this._savePreviouslyFocusedElement();
128 return this._portalOutlet.attachComponentPortal(portal);
129 }
130 /** Attach a template portal as content to this bottom sheet container. */
131 attachTemplatePortal(portal) {
132 this._validatePortalAttached();
133 this._setPanelClass();
134 this._savePreviouslyFocusedElement();
135 return this._portalOutlet.attachTemplatePortal(portal);
136 }
137 /** Begin animation of bottom sheet entrance into view. */
138 enter() {
139 if (!this._destroyed) {
140 this._animationState = 'visible';
141 this._changeDetectorRef.detectChanges();
142 }
143 }
144 /** Begin animation of the bottom sheet exiting from view. */
145 exit() {
146 if (!this._destroyed) {
147 this._animationState = 'hidden';
148 this._changeDetectorRef.markForCheck();
149 }
150 }
151 ngOnDestroy() {
152 this._breakpointSubscription.unsubscribe();
153 this._destroyed = true;
154 }
155 _onAnimationDone(event) {
156 if (event.toState === 'hidden') {
157 this._restoreFocus();
158 }
159 else if (event.toState === 'visible') {
160 this._trapFocus();
161 }
162 this._animationStateChanged.emit(event);
163 }
164 _onAnimationStart(event) {
165 this._animationStateChanged.emit(event);
166 }
167 _toggleClass(cssClass, add) {
168 const classList = this._elementRef.nativeElement.classList;
169 add ? classList.add(cssClass) : classList.remove(cssClass);
170 }
171 _validatePortalAttached() {
172 if (this._portalOutlet.hasAttached() && (typeof ngDevMode === 'undefined' || ngDevMode)) {
173 throw Error('Attempting to attach bottom sheet content after content is already attached');
174 }
175 }
176 _setPanelClass() {
177 const element = this._elementRef.nativeElement;
178 const panelClass = this.bottomSheetConfig.panelClass;
179 if (Array.isArray(panelClass)) {
180 // Note that we can't use a spread here, because IE doesn't support multiple arguments.
181 panelClass.forEach(cssClass => element.classList.add(cssClass));
182 }
183 else if (panelClass) {
184 element.classList.add(panelClass);
185 }
186 }
187 /** Moves the focus inside the focus trap. */
188 _trapFocus() {
189 const element = this._elementRef.nativeElement;
190 if (!this._focusTrap) {
191 this._focusTrap = this._focusTrapFactory.create(element);
192 }
193 if (this.bottomSheetConfig.autoFocus) {
194 this._focusTrap.focusInitialElementWhenReady();
195 }
196 else {
197 const activeElement = _getFocusedElementPierceShadowDom();
198 // Otherwise ensure that focus is on the container. It's possible that a different
199 // component tried to move focus while the open animation was running. See:
200 // https://github.com/angular/components/issues/16215. Note that we only want to do this
201 // if the focus isn't inside the bottom sheet already, because it's possible that the
202 // consumer turned off `autoFocus` in order to move focus themselves.
203 if (activeElement !== element && !element.contains(activeElement)) {
204 element.focus();
205 }
206 }
207 }
208 /** Restores focus to the element that was focused before the bottom sheet was opened. */
209 _restoreFocus() {
210 const toFocus = this._elementFocusedBeforeOpened;
211 // We need the extra check, because IE can set the `activeElement` to null in some cases.
212 if (this.bottomSheetConfig.restoreFocus && toFocus && typeof toFocus.focus === 'function') {
213 const activeElement = _getFocusedElementPierceShadowDom();
214 const element = this._elementRef.nativeElement;
215 // Make sure that focus is still inside the bottom sheet or is on the body (usually because a
216 // non-focusable element like the backdrop was clicked) before moving it. It's possible that
217 // the consumer moved it themselves before the animation was done, in which case we shouldn't
218 // do anything.
219 if (!activeElement || activeElement === this._document.body || activeElement === element ||
220 element.contains(activeElement)) {
221 toFocus.focus();
222 }
223 }
224 if (this._focusTrap) {
225 this._focusTrap.destroy();
226 }
227 }
228 /** Saves a reference to the element that was focused before the bottom sheet was opened. */
229 _savePreviouslyFocusedElement() {
230 this._elementFocusedBeforeOpened = _getFocusedElementPierceShadowDom();
231 // The `focus` method isn't available during server-side rendering.
232 if (this._elementRef.nativeElement.focus) {
233 Promise.resolve().then(() => this._elementRef.nativeElement.focus());
234 }
235 }
236}
237MatBottomSheetContainer.decorators = [
238 { type: Component, args: [{
239 selector: 'mat-bottom-sheet-container',
240 template: "<ng-template cdkPortalOutlet></ng-template>\r\n",
241 // In Ivy embedded views will be change detected from their declaration place, rather than where
242 // they were stamped out. This means that we can't have the bottom sheet container be OnPush,
243 // because it might cause the sheets that were opened from a template not to be out of date.
244 // tslint:disable-next-line:validate-decorators
245 changeDetection: ChangeDetectionStrategy.Default,
246 encapsulation: ViewEncapsulation.None,
247 animations: [matBottomSheetAnimations.bottomSheetState],
248 host: {
249 'class': 'mat-bottom-sheet-container',
250 'tabindex': '-1',
251 'role': 'dialog',
252 'aria-modal': 'true',
253 '[attr.aria-label]': 'bottomSheetConfig?.ariaLabel',
254 '[@state]': '_animationState',
255 '(@state.start)': '_onAnimationStart($event)',
256 '(@state.done)': '_onAnimationDone($event)'
257 },
258 styles: [".mat-bottom-sheet-container{padding:8px 16px;min-width:100vw;box-sizing:border-box;display:block;outline:0;max-height:80vh;overflow:auto}.cdk-high-contrast-active .mat-bottom-sheet-container{outline:1px solid}.mat-bottom-sheet-container-xlarge,.mat-bottom-sheet-container-large,.mat-bottom-sheet-container-medium{border-top-left-radius:4px;border-top-right-radius:4px}.mat-bottom-sheet-container-medium{min-width:384px;max-width:calc(100vw - 128px)}.mat-bottom-sheet-container-large{min-width:512px;max-width:calc(100vw - 256px)}.mat-bottom-sheet-container-xlarge{min-width:576px;max-width:calc(100vw - 384px)}\n"]
259 },] }
260];
261MatBottomSheetContainer.ctorParameters = () => [
262 { type: ElementRef },
263 { type: ChangeDetectorRef },
264 { type: FocusTrapFactory },
265 { type: BreakpointObserver },
266 { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] },
267 { type: MatBottomSheetConfig }
268];
269MatBottomSheetContainer.propDecorators = {
270 _portalOutlet: [{ type: ViewChild, args: [CdkPortalOutlet, { static: true },] }]
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 */
280class MatBottomSheetModule {
281}
282MatBottomSheetModule.decorators = [
283 { type: NgModule, args: [{
284 imports: [
285 OverlayModule,
286 MatCommonModule,
287 PortalModule,
288 ],
289 exports: [MatBottomSheetContainer, MatCommonModule],
290 declarations: [MatBottomSheetContainer],
291 entryComponents: [MatBottomSheetContainer],
292 },] }
293];
294
295/**
296 * @license
297 * Copyright Google LLC All Rights Reserved.
298 *
299 * Use of this source code is governed by an MIT-style license that can be
300 * found in the LICENSE file at https://angular.io/license
301 */
302/**
303 * Reference to a bottom sheet dispatched from the bottom sheet service.
304 */
305class MatBottomSheetRef {
306 constructor(containerInstance, _overlayRef) {
307 this._overlayRef = _overlayRef;
308 /** Subject for notifying the user that the bottom sheet has been dismissed. */
309 this._afterDismissed = new Subject();
310 /** Subject for notifying the user that the bottom sheet has opened and appeared. */
311 this._afterOpened = new Subject();
312 this.containerInstance = containerInstance;
313 this.disableClose = containerInstance.bottomSheetConfig.disableClose;
314 // Emit when opening animation completes
315 containerInstance._animationStateChanged.pipe(filter(event => event.phaseName === 'done' && event.toState === 'visible'), take(1))
316 .subscribe(() => {
317 this._afterOpened.next();
318 this._afterOpened.complete();
319 });
320 // Dispose overlay when closing animation is complete
321 containerInstance._animationStateChanged
322 .pipe(filter(event => event.phaseName === 'done' && event.toState === 'hidden'), take(1))
323 .subscribe(() => {
324 clearTimeout(this._closeFallbackTimeout);
325 _overlayRef.dispose();
326 });
327 _overlayRef.detachments().pipe(take(1)).subscribe(() => {
328 this._afterDismissed.next(this._result);
329 this._afterDismissed.complete();
330 });
331 merge(_overlayRef.backdropClick(), _overlayRef.keydownEvents().pipe(filter(event => event.keyCode === ESCAPE))).subscribe(event => {
332 if (!this.disableClose &&
333 (event.type !== 'keydown' || !hasModifierKey(event))) {
334 event.preventDefault();
335 this.dismiss();
336 }
337 });
338 }
339 /**
340 * Dismisses the bottom sheet.
341 * @param result Data to be passed back to the bottom sheet opener.
342 */
343 dismiss(result) {
344 if (!this._afterDismissed.closed) {
345 // Transition the backdrop in parallel to the bottom sheet.
346 this.containerInstance._animationStateChanged.pipe(filter(event => event.phaseName === 'start'), take(1)).subscribe(event => {
347 // The logic that disposes of the overlay depends on the exit animation completing, however
348 // it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback
349 // timeout which will clean everything up if the animation hasn't fired within the specified
350 // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the
351 // vast majority of cases the timeout will have been cleared before it has fired.
352 this._closeFallbackTimeout = setTimeout(() => {
353 this._overlayRef.dispose();
354 }, event.totalTime + 100);
355 this._overlayRef.detachBackdrop();
356 });
357 this._result = result;
358 this.containerInstance.exit();
359 }
360 }
361 /** Gets an observable that is notified when the bottom sheet is finished closing. */
362 afterDismissed() {
363 return this._afterDismissed;
364 }
365 /** Gets an observable that is notified when the bottom sheet has opened and appeared. */
366 afterOpened() {
367 return this._afterOpened;
368 }
369 /**
370 * Gets an observable that emits when the overlay's backdrop has been clicked.
371 */
372 backdropClick() {
373 return this._overlayRef.backdropClick();
374 }
375 /**
376 * Gets an observable that emits when keydown events are targeted on the overlay.
377 */
378 keydownEvents() {
379 return this._overlayRef.keydownEvents();
380 }
381}
382
383/**
384 * @license
385 * Copyright Google LLC All Rights Reserved.
386 *
387 * Use of this source code is governed by an MIT-style license that can be
388 * found in the LICENSE file at https://angular.io/license
389 */
390/** Injection token that can be used to specify default bottom sheet options. */
391const MAT_BOTTOM_SHEET_DEFAULT_OPTIONS = new InjectionToken('mat-bottom-sheet-default-options');
392/**
393 * Service to trigger Material Design bottom sheets.
394 */
395class MatBottomSheet {
396 constructor(_overlay, _injector, _parentBottomSheet, _defaultOptions) {
397 this._overlay = _overlay;
398 this._injector = _injector;
399 this._parentBottomSheet = _parentBottomSheet;
400 this._defaultOptions = _defaultOptions;
401 this._bottomSheetRefAtThisLevel = null;
402 }
403 /** Reference to the currently opened bottom sheet. */
404 get _openedBottomSheetRef() {
405 const parent = this._parentBottomSheet;
406 return parent ? parent._openedBottomSheetRef : this._bottomSheetRefAtThisLevel;
407 }
408 set _openedBottomSheetRef(value) {
409 if (this._parentBottomSheet) {
410 this._parentBottomSheet._openedBottomSheetRef = value;
411 }
412 else {
413 this._bottomSheetRefAtThisLevel = value;
414 }
415 }
416 open(componentOrTemplateRef, config) {
417 const _config = _applyConfigDefaults(this._defaultOptions || new MatBottomSheetConfig(), config);
418 const overlayRef = this._createOverlay(_config);
419 const container = this._attachContainer(overlayRef, _config);
420 const ref = new MatBottomSheetRef(container, overlayRef);
421 if (componentOrTemplateRef instanceof TemplateRef) {
422 container.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, null, {
423 $implicit: _config.data,
424 bottomSheetRef: ref
425 }));
426 }
427 else {
428 const portal = new ComponentPortal(componentOrTemplateRef, undefined, this._createInjector(_config, ref));
429 const contentRef = container.attachComponentPortal(portal);
430 ref.instance = contentRef.instance;
431 }
432 // When the bottom sheet is dismissed, clear the reference to it.
433 ref.afterDismissed().subscribe(() => {
434 // Clear the bottom sheet ref if it hasn't already been replaced by a newer one.
435 if (this._openedBottomSheetRef == ref) {
436 this._openedBottomSheetRef = null;
437 }
438 });
439 if (this._openedBottomSheetRef) {
440 // If a bottom sheet is already in view, dismiss it and enter the
441 // new bottom sheet after exit animation is complete.
442 this._openedBottomSheetRef.afterDismissed().subscribe(() => ref.containerInstance.enter());
443 this._openedBottomSheetRef.dismiss();
444 }
445 else {
446 // If no bottom sheet is in view, enter the new bottom sheet.
447 ref.containerInstance.enter();
448 }
449 this._openedBottomSheetRef = ref;
450 return ref;
451 }
452 /**
453 * Dismisses the currently-visible bottom sheet.
454 * @param result Data to pass to the bottom sheet instance.
455 */
456 dismiss(result) {
457 if (this._openedBottomSheetRef) {
458 this._openedBottomSheetRef.dismiss(result);
459 }
460 }
461 ngOnDestroy() {
462 if (this._bottomSheetRefAtThisLevel) {
463 this._bottomSheetRefAtThisLevel.dismiss();
464 }
465 }
466 /**
467 * Attaches the bottom sheet container component to the overlay.
468 */
469 _attachContainer(overlayRef, config) {
470 const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
471 const injector = Injector.create({
472 parent: userInjector || this._injector,
473 providers: [{ provide: MatBottomSheetConfig, useValue: config }]
474 });
475 const containerPortal = new ComponentPortal(MatBottomSheetContainer, config.viewContainerRef, injector);
476 const containerRef = overlayRef.attach(containerPortal);
477 return containerRef.instance;
478 }
479 /**
480 * Creates a new overlay and places it in the correct location.
481 * @param config The user-specified bottom sheet config.
482 */
483 _createOverlay(config) {
484 const overlayConfig = new OverlayConfig({
485 direction: config.direction,
486 hasBackdrop: config.hasBackdrop,
487 disposeOnNavigation: config.closeOnNavigation,
488 maxWidth: '100%',
489 scrollStrategy: config.scrollStrategy || this._overlay.scrollStrategies.block(),
490 positionStrategy: this._overlay.position().global().centerHorizontally().bottom('0')
491 });
492 if (config.backdropClass) {
493 overlayConfig.backdropClass = config.backdropClass;
494 }
495 return this._overlay.create(overlayConfig);
496 }
497 /**
498 * Creates an injector to be used inside of a bottom sheet component.
499 * @param config Config that was used to create the bottom sheet.
500 * @param bottomSheetRef Reference to the bottom sheet.
501 */
502 _createInjector(config, bottomSheetRef) {
503 const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
504 const providers = [
505 { provide: MatBottomSheetRef, useValue: bottomSheetRef },
506 { provide: MAT_BOTTOM_SHEET_DATA, useValue: config.data }
507 ];
508 if (config.direction && (!userInjector ||
509 !userInjector.get(Directionality, null, InjectFlags.Optional))) {
510 providers.push({
511 provide: Directionality,
512 useValue: { value: config.direction, change: of() }
513 });
514 }
515 return Injector.create({ parent: userInjector || this._injector, providers });
516 }
517}
518MatBottomSheet.ɵprov = i0.ɵɵdefineInjectable({ factory: function MatBottomSheet_Factory() { return new MatBottomSheet(i0.ɵɵinject(i1.Overlay), i0.ɵɵinject(i0.INJECTOR), i0.ɵɵinject(MatBottomSheet, 12), i0.ɵɵinject(MAT_BOTTOM_SHEET_DEFAULT_OPTIONS, 8)); }, token: MatBottomSheet, providedIn: MatBottomSheetModule });
519MatBottomSheet.decorators = [
520 { type: Injectable, args: [{ providedIn: MatBottomSheetModule },] }
521];
522MatBottomSheet.ctorParameters = () => [
523 { type: Overlay },
524 { type: Injector },
525 { type: MatBottomSheet, decorators: [{ type: Optional }, { type: SkipSelf }] },
526 { type: MatBottomSheetConfig, decorators: [{ type: Optional }, { type: Inject, args: [MAT_BOTTOM_SHEET_DEFAULT_OPTIONS,] }] }
527];
528/**
529 * Applies default options to the bottom sheet config.
530 * @param defaults Object containing the default values to which to fall back.
531 * @param config The configuration to which the defaults will be applied.
532 * @returns The new configuration object with defaults applied.
533 */
534function _applyConfigDefaults(defaults, config) {
535 return Object.assign(Object.assign({}, defaults), config);
536}
537
538/**
539 * @license
540 * Copyright Google LLC All Rights Reserved.
541 *
542 * Use of this source code is governed by an MIT-style license that can be
543 * found in the LICENSE file at https://angular.io/license
544 */
545
546/**
547 * Generated bundle index. Do not edit.
548 */
549
550export { MAT_BOTTOM_SHEET_DATA, MAT_BOTTOM_SHEET_DEFAULT_OPTIONS, MatBottomSheet, MatBottomSheetConfig, MatBottomSheetContainer, MatBottomSheetModule, MatBottomSheetRef, matBottomSheetAnimations };
551//# sourceMappingURL=bottom-sheet.js.map
Note: See TracBrowser for help on using the repository browser.