UNPKG

43.1 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { EventEmitter, Directive, Optional, Inject, ViewChild, Component, ViewEncapsulation, ChangeDetectionStrategy, HostBinding, HostListener, Injector, TemplateRef, InjectFlags, Injectable, SkipSelf, Input, NgModule } from '@angular/core';
3import * as i3 from '@angular/cdk/portal';
4import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, TemplatePortal, PortalModule } from '@angular/cdk/portal';
5import { AnimationDurations, AnimationCurves, MatCommonModule } from '@angular/material/core';
6import { MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA, MAT_DIALOG_DEFAULT_OPTIONS, MatDialogModule } from '@angular/material/dialog';
7import * as i1$1 from '@angular/cdk/overlay';
8import { OverlayConfig } from '@angular/cdk/overlay';
9import * as i1 from '@angular/cdk/a11y';
10import { DOCUMENT } from '@angular/common';
11import { trigger, state, style, transition, animate } from '@angular/animations';
12import { Subject, of } from 'rxjs';
13import { filter, take } from 'rxjs/operators';
14import { Directionality } from '@angular/cdk/bidi';
15import { DialogRef } from '@angular/cdk/dialog';
16
17const tdSideSheetAnimations = {
18 /** Animation that is applied on the side-sheet container by default. */
19 sideSheetContainer: trigger('sideSheetContainer', [
20 state('void, exit', style({ transform: 'translateX(100%)' })),
21 state('enter', style({ transform: 'translateX(0%)', opacity: 1 })),
22 transition('* => enter', animate(`${AnimationDurations.ENTERING} ${AnimationCurves.ACCELERATION_CURVE}`, style({ transform: 'translateX(0)', opacity: 1 }))),
23 transition('* => void, * => exit', animate(`${AnimationDurations.EXITING} ${AnimationCurves.ACCELERATION_CURVE}`, style({ transform: 'translateX(100%)' }))),
24 ]),
25};
26
27var SubPageMode;
28(function (SubPageMode) {
29 SubPageMode["pushed"] = "pushed";
30 SubPageMode["shifted"] = "shifted";
31 SubPageMode["none"] = "none";
32})(SubPageMode || (SubPageMode = {}));
33class CovalentSideSheetConfig extends MatDialogConfig {
34 subPageMode = SubPageMode.pushed;
35}
36
37function _getFocusedElementPierceShadowDom() {
38 let activeElement = typeof document !== 'undefined' && document
39 ? document.activeElement
40 : null;
41 while (activeElement && activeElement.shadowRoot) {
42 const newActiveElement = activeElement.shadowRoot
43 .activeElement;
44 if (newActiveElement === activeElement) {
45 break;
46 }
47 else {
48 activeElement = newActiveElement;
49 }
50 }
51 return activeElement;
52}
53/**
54 * Base class for the `CovalentSideSheetContainer`. The base class does not implement
55 * animations as these are left to implementers of the side-sheet container.
56 */
57class _CovalentSideSheetContainerBase extends BasePortalOutlet {
58 _elementRef;
59 _focusTrapFactory;
60 _changeDetectorRef;
61 _config;
62 _focusMonitor;
63 _document;
64 /** The portal outlet inside of this container into which the side-sheet content will be loaded. */
65 _portalOutlet;
66 /** The class that traps and manages focus within the side-sheet. */
67 _focusTrap;
68 /** Emits when an animation state changes. */
69 _animationStateChanged = new EventEmitter();
70 /** Element that was focused before the side-sheet was opened. Save this to restore upon close. */
71 _elementFocusedBeforeSideSheetWasOpened = null;
72 /**
73 * Type of interaction that led to the side-sheet being closed. This is used to determine
74 * whether the focus style will be applied when returning focus to its original location
75 * after the side-sheet is closed.
76 */
77 _closeInteractionType = null;
78 /** ID of the element that should be considered as the side-sheet's label. */
79 _ariaLabelledBy;
80 /** ID for the container DOM element. */
81 _id;
82 constructor(_elementRef, _focusTrapFactory, _changeDetectorRef, _document,
83 /** The side-sheet configuration. */
84 _config, _focusMonitor) {
85 super();
86 this._elementRef = _elementRef;
87 this._focusTrapFactory = _focusTrapFactory;
88 this._changeDetectorRef = _changeDetectorRef;
89 this._config = _config;
90 this._focusMonitor = _focusMonitor;
91 this._ariaLabelledBy = _config.ariaLabelledBy || null;
92 this._document = _document;
93 }
94 /** Initializes the side-sheet container with the attached content. */
95 _initializeWithAttachedContent() {
96 this._setupFocusTrap();
97 // Save the previously focused element. This element will be re-focused
98 // when the side-sheet closes.
99 this._capturePreviouslyFocusedElement();
100 }
101 /**
102 * Attach a ComponentPortal as content to this side-sheet container.
103 * @param portal Portal to be attached as the side-sheet content.
104 */
105 attachComponentPortal(portal) {
106 return this._portalOutlet.attachComponentPortal(portal);
107 }
108 /**
109 * Attach a TemplatePortal as content to this side-sheet container.
110 * @param portal Portal to be attached as the side-sheet content.
111 */
112 attachTemplatePortal(portal) {
113 return this._portalOutlet.attachTemplatePortal(portal);
114 }
115 /**
116 * Attaches a DOM portal to the side-sheet container.
117 * @param portal Portal to be attached.
118 * @deprecated To be turned into a method.
119 */
120 attachDomPortal = (portal) => {
121 return this._portalOutlet.attachDomPortal(portal);
122 };
123 /** Moves focus back into the side-sheet if it was moved out. */
124 _recaptureFocus() {
125 if (!this._containsFocus()) {
126 this._trapFocus();
127 }
128 }
129 /**
130 * Moves the focus inside the focus trap. When autoFocus is not set to 'side-sheet', if focus
131 * cannot be moved then focus will go to the side-sheet container.
132 */
133 _trapFocus() {
134 const element = this._elementRef.nativeElement;
135 if (!this._config.autoFocus) {
136 if (!this._containsFocus()) {
137 element.focus();
138 }
139 }
140 else {
141 this._focusTrap
142 .focusInitialElementWhenReady()
143 .then((focusedSuccessfully) => {
144 // If we weren't able to find a focusable element in the side-sheet, then focus the side-sheet
145 // container instead.
146 if (!focusedSuccessfully) {
147 this._focusSideSheetContainer();
148 }
149 });
150 }
151 }
152 /** Restores focus to the element that was focused before the side-sheet opened. */
153 _restoreFocus() {
154 const previousElement = this._elementFocusedBeforeSideSheetWasOpened;
155 // We need the extra check, because IE can set the `activeElement` to null in some cases.
156 if (this._config.restoreFocus &&
157 previousElement &&
158 typeof previousElement.focus === 'function') {
159 const activeElement = _getFocusedElementPierceShadowDom();
160 const element = this._elementRef.nativeElement;
161 // Make sure that focus is still inside the side-sheet or is on the body (usually because a
162 // non-focusable element like the backdrop was clicked) before moving it. It's possible that
163 // the consumer moved it themselves before the animation was done, in which case we shouldn't
164 // do anything.
165 if (!activeElement ||
166 activeElement === this._document.body ||
167 activeElement === element ||
168 element.contains(activeElement)) {
169 if (this._focusMonitor) {
170 this._focusMonitor.focusVia(previousElement, this._closeInteractionType);
171 this._closeInteractionType = null;
172 }
173 else {
174 previousElement.focus();
175 }
176 }
177 }
178 if (this._focusTrap) {
179 this._focusTrap.destroy();
180 }
181 }
182 /** Sets up the focus trap. */
183 _setupFocusTrap() {
184 this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
185 }
186 /** Captures the element that was focused before the side-sheet was opened. */
187 _capturePreviouslyFocusedElement() {
188 if (this._document) {
189 this._elementFocusedBeforeSideSheetWasOpened =
190 _getFocusedElementPierceShadowDom();
191 }
192 }
193 /** Focuses the side-sheet container. */
194 _focusSideSheetContainer() {
195 // Note that there is no focus method when rendering on the server.
196 if (this._elementRef.nativeElement.focus) {
197 this._elementRef.nativeElement.focus();
198 }
199 }
200 /** Returns whether focus is inside the side-sheet. */
201 _containsFocus() {
202 const element = this._elementRef.nativeElement;
203 const activeElement = _getFocusedElementPierceShadowDom();
204 return element === activeElement || element.contains(activeElement);
205 }
206 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: _CovalentSideSheetContainerBase, deps: [{ token: i0.ElementRef }, { token: i1.ConfigurableFocusTrapFactory }, { token: i0.ChangeDetectorRef }, { token: DOCUMENT, optional: true }, { token: CovalentSideSheetConfig }, { token: i1.FocusMonitor }], target: i0.ɵɵFactoryTarget.Directive });
207 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: _CovalentSideSheetContainerBase, viewQueries: [{ propertyName: "_portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 });
208}
209i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: _CovalentSideSheetContainerBase, decorators: [{
210 type: Directive
211 }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.ConfigurableFocusTrapFactory }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
212 type: Optional
213 }, {
214 type: Inject,
215 args: [DOCUMENT]
216 }] }, { type: CovalentSideSheetConfig }, { type: i1.FocusMonitor }], propDecorators: { _portalOutlet: [{
217 type: ViewChild,
218 args: [CdkPortalOutlet, { static: true }]
219 }] } });
220/**
221 * Internal component that wraps the generated side-sheet content.
222 * This animation below is the only reason for duplicating most of the Material dialog code
223 */
224class CovalentSideSheetContainerComponent extends _CovalentSideSheetContainerBase {
225 /** State of the side-sheet animation. */
226 _state = 'enter';
227 tdSideSheetContainerClass = true;
228 tabIndex = -1;
229 arialModal = true;
230 idAttr = this._id;
231 roleAttr = this._config.role;
232 arialLabelByAttr = this._config.ariaLabel
233 ? null
234 : this._ariaLabelledBy;
235 arialDescribeByAttr = this._config.ariaDescribedBy || null;
236 arialLabelAttr = this._config.ariaLabel;
237 get sideSheetAnimationState() {
238 return this._state;
239 }
240 onAnimateStart($event) {
241 this._onAnimationStart($event);
242 }
243 onAnimateDone($event) {
244 this._onAnimationDone($event);
245 }
246 /** Callback, invoked whenever an animation on the host completes. */
247 _onAnimationDone({ toState, totalTime }) {
248 if (toState === 'enter') {
249 this._trapFocus();
250 this._animationStateChanged.next({ state: 'opened', totalTime });
251 }
252 else if (toState === 'exit') {
253 this._restoreFocus();
254 this._animationStateChanged.next({ state: 'closed', totalTime });
255 }
256 }
257 /** Callback, invoked when an animation on the host starts. */
258 _onAnimationStart({ toState, totalTime }) {
259 if (toState === 'enter') {
260 this._animationStateChanged.next({ state: 'opening', totalTime });
261 }
262 else if (toState === 'exit' || toState === 'void') {
263 this._animationStateChanged.next({ state: 'closing', totalTime });
264 }
265 }
266 /** Starts the side-sheet exit animation. */
267 _startExitAnimation() {
268 this._state = 'exit';
269 this._changeDetectorRef.markForCheck();
270 }
271 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetContainerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
272 static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetContainerComponent, selector: "td-side-sheet-container", host: { listeners: { "@sideSheetContainer.start": "onAnimateStart($event)", "@sideSheetContainer.done": "onAnimateDone($event)" }, properties: { "class.td-side-sheet-container": "this.tdSideSheetContainerClass", "tabindex": "this.tabIndex", "aria-modal": "this.arialModal", "id": "this.idAttr", "attr.role": "this.roleAttr", "attr.aria-labelledby": "this.arialLabelByAttr", "attr.aria-describedby": "this.arialDescribeByAttr", "attr.aria-label": "this.arialLabelAttr", "@sideSheetContainer": "this.sideSheetAnimationState" } }, usesInheritance: true, ngImport: i0, template: ` <ng-template cdkPortalOutlet></ng-template> `, isInline: true, styles: [".td-side-sheet-container{box-shadow:0 8px 10px -5px #0003,0 16px 24px 2px #00000024,0 6px 30px 5px #0000001f;display:block;padding:24px;box-sizing:border-box;overflow:auto;outline:0;width:100%;height:100%;min-height:inherit;max-height:inherit}.td-side-sheet-wrapper{display:flex;flex-direction:column;height:100%}.td-side-sheet-content{margin:0 -24px;padding:0 24px;overflow:auto;flex:1;-webkit-overflow-scrolling:touch}.td-side-sheet-title{margin:-16px 0 20px;display:flex;align-items:center}.td-side-sheet-actions{padding:8px 0;margin:0 -16px -24px;display:flex;justify-content:space-between;flex-wrap:wrap;align-items:center;box-sizing:content-box}.td-side-sheet-actions[align=end]{justify-content:flex-end}.td-side-sheet-actions[align=center]{justify-content:center}.td-side-sheet-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:8px}[dir=rtl] .td-side-sheet-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:0;margin-right:8px}\n"], dependencies: [{ kind: "directive", type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], animations: [tdSideSheetAnimations.sideSheetContainer], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None });
273}
274i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetContainerComponent, decorators: [{
275 type: Component,
276 args: [{ selector: 'td-side-sheet-container', template: ` <ng-template cdkPortalOutlet></ng-template> `, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, animations: [tdSideSheetAnimations.sideSheetContainer], styles: [".td-side-sheet-container{box-shadow:0 8px 10px -5px #0003,0 16px 24px 2px #00000024,0 6px 30px 5px #0000001f;display:block;padding:24px;box-sizing:border-box;overflow:auto;outline:0;width:100%;height:100%;min-height:inherit;max-height:inherit}.td-side-sheet-wrapper{display:flex;flex-direction:column;height:100%}.td-side-sheet-content{margin:0 -24px;padding:0 24px;overflow:auto;flex:1;-webkit-overflow-scrolling:touch}.td-side-sheet-title{margin:-16px 0 20px;display:flex;align-items:center}.td-side-sheet-actions{padding:8px 0;margin:0 -16px -24px;display:flex;justify-content:space-between;flex-wrap:wrap;align-items:center;box-sizing:content-box}.td-side-sheet-actions[align=end]{justify-content:flex-end}.td-side-sheet-actions[align=center]{justify-content:center}.td-side-sheet-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:8px}[dir=rtl] .td-side-sheet-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:0;margin-right:8px}\n"] }]
277 }], propDecorators: { tdSideSheetContainerClass: [{
278 type: HostBinding,
279 args: ['class.td-side-sheet-container']
280 }], tabIndex: [{
281 type: HostBinding,
282 args: ['tabindex']
283 }], arialModal: [{
284 type: HostBinding,
285 args: ['aria-modal']
286 }], idAttr: [{
287 type: HostBinding,
288 args: ['id']
289 }], roleAttr: [{
290 type: HostBinding,
291 args: ['attr.role']
292 }], arialLabelByAttr: [{
293 type: HostBinding,
294 args: ['attr.aria-labelledby']
295 }], arialDescribeByAttr: [{
296 type: HostBinding,
297 args: ['attr.aria-describedby']
298 }], arialLabelAttr: [{
299 type: HostBinding,
300 args: ['attr.aria-label']
301 }], sideSheetAnimationState: [{
302 type: HostBinding,
303 args: ['@sideSheetContainer']
304 }], onAnimateStart: [{
305 type: HostListener,
306 args: ['@sideSheetContainer.start', ['$event']]
307 }], onAnimateDone: [{
308 type: HostListener,
309 args: ['@sideSheetContainer.done', ['$event']]
310 }] } });
311
312// Counter for unique dialog ids.
313let uniqueId = 0;
314// Create a new side sheet ref to change the id of the ref
315class CovalentSideSheetRef extends MatDialogRef {
316 overlayRef;
317 config;
318 _containerInstance;
319 id;
320 constructor(overlayRef, config, _containerInstance, id = `td-side-sheet-${uniqueId++}`) {
321 const ref = new DialogRef(overlayRef, config);
322 super(ref, config, _containerInstance);
323 this.overlayRef = overlayRef;
324 this.config = config;
325 this._containerInstance = _containerInstance;
326 this.id = id;
327 ref.containerInstance =
328 this._containerInstance;
329 }
330}
331function _closeSideSheetVia(ref, interactionType, result) {
332 // Some mock dialog ref instances in tests do not have the `_containerInstance` property.
333 // For those, we keep the behavior as is and do not deal with the interaction type.
334 if (ref._containerInstance !== undefined) {
335 ref._containerInstance._closeInteractionType = interactionType;
336 }
337 return ref.close(result);
338}
339
340/* tslint:disable */
341class _CovalentSideSheetBase {
342 _overlay;
343 _injector;
344 _defaultOptions;
345 _parentSideSheet;
346 _sideSheetRefConstructor;
347 _sideSheetContainerType;
348 _sideSheetDataToken;
349 _openSideSheetsAtThisLevel = [];
350 _afterAllClosedAtThisLevel = new Subject();
351 _afterOpenedAtThisLevel = new Subject();
352 _animationStateSubscriptions;
353 defaultSidebarConfig = {
354 minWidth: '400px',
355 maxWidth: '100vw',
356 };
357 constructor(_overlay, _injector, _defaultOptions, _parentSideSheet, _sideSheetRefConstructor, _sideSheetContainerType, _sideSheetDataToken) {
358 this._overlay = _overlay;
359 this._injector = _injector;
360 this._defaultOptions = _defaultOptions;
361 this._parentSideSheet = _parentSideSheet;
362 this._sideSheetRefConstructor = _sideSheetRefConstructor;
363 this._sideSheetContainerType = _sideSheetContainerType;
364 this._sideSheetDataToken = _sideSheetDataToken;
365 }
366 /** Keeps track of the currently-open side-sheets. */
367 get openSideSheets() {
368 return this._parentSideSheet
369 ? this._parentSideSheet.openSideSheets
370 : this._openSideSheetsAtThisLevel;
371 }
372 open(componentOrTemplateRef, config) {
373 config = {
374 ...(this._defaultOptions || new CovalentSideSheetConfig()),
375 ...this.defaultSidebarConfig,
376 ...config,
377 };
378 const overlayRef = this._createOverlay(config);
379 const sideSheetContainer = this._attachSideSheetContainer(overlayRef, config);
380 const sideSheetRef = this._attachSideSheetContent(componentOrTemplateRef, sideSheetContainer, overlayRef, config);
381 const prevSideSheetRef = this.openSideSheets.slice(-1)[0];
382 const prevOverlayRef = prevSideSheetRef?.overlayRef;
383 if (prevOverlayRef?.overlayElement &&
384 config.subPageMode !== SubPageMode.none) {
385 prevOverlayRef.overlayElement.style.transition = `${AnimationDurations.COMPLEX} ${AnimationCurves.DECELERATION_CURVE}`;
386 if (config.subPageMode === SubPageMode.pushed) {
387 // Animate previous side sheet to full width
388 prevOverlayRef.overlayElement.style.minWidth = `${window.innerWidth}px`;
389 }
390 else if (config.subPageMode === SubPageMode.shifted) {
391 // Animate previous side sheet to current sidesheet width + 200px
392 prevOverlayRef.overlayElement.style.minWidth = `${sideSheetRef.overlayRef.overlayElement.offsetWidth + 200}px`;
393 }
394 }
395 // Revert the previous side sheet config & size
396 sideSheetRef._containerInstance._animationStateChanged
397 .pipe(filter((event) => event.state === 'closing' && !!(prevSideSheetRef && prevOverlayRef)), take(1))
398 .subscribe(() => {
399 prevOverlayRef.overlayElement.style.transition = `${AnimationDurations.EXITING} ${AnimationCurves.DECELERATION_CURVE}`;
400 prevSideSheetRef.updateSize();
401 });
402 // Add new side sheet to open list
403 this.openSideSheets.push(sideSheetRef);
404 // Remove side sheet ref after closed
405 sideSheetRef
406 .afterClosed()
407 .pipe(take(1))
408 .subscribe(() => this._removeOpenSideSheet(sideSheetRef));
409 // Notify the side-sheet container that the content has been attached.
410 sideSheetContainer._initializeWithAttachedContent();
411 return sideSheetRef;
412 }
413 ngOnDestroy() {
414 // Only close the side-sheets at this level on destroy
415 // since the parent service may still be active.
416 this._closeSideSheets(this._openSideSheetsAtThisLevel);
417 this._afterAllClosedAtThisLevel.complete();
418 this._afterOpenedAtThisLevel.complete();
419 // Clean up any subscriptions to side-sheet that never finished opening.
420 if (this._animationStateSubscriptions) {
421 this._animationStateSubscriptions.unsubscribe();
422 }
423 }
424 /**
425 * Closes all of the currently-open side-sheets.
426 */
427 closeAll() {
428 this._closeSideSheets(this.openSideSheets);
429 }
430 _createOverlay(config) {
431 const overlayConfig = new OverlayConfig({
432 positionStrategy: this._overlay.position().global(),
433 scrollStrategy: this._overlay.scrollStrategies.block(),
434 panelClass: config.panelClass,
435 hasBackdrop: config.hasBackdrop,
436 direction: config.direction,
437 minWidth: config.minWidth,
438 minHeight: config.minHeight,
439 maxWidth: config.maxWidth,
440 });
441 const overlayRef = this._overlay.create(overlayConfig);
442 const positionStrategy = overlayRef.getConfig()
443 .positionStrategy;
444 positionStrategy.right('0px');
445 return overlayRef;
446 }
447 /**
448 * Attaches a container to a side-sheets's already-created overlay.
449 * @param overlay Reference to the side-sheet's underlying overlay.
450 * @param config The side-sheet configuration.
451 * @returns A promise resolving to a ComponentRef for the attached container.
452 */
453 _attachSideSheetContainer(overlay, config) {
454 const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
455 const injector = Injector.create({
456 parent: userInjector || this._injector,
457 providers: [{ provide: CovalentSideSheetConfig, useValue: config }],
458 });
459 const containerPortal = new ComponentPortal(this._sideSheetContainerType, config.viewContainerRef, injector, config.componentFactoryResolver);
460 const containerRef = overlay.attach(containerPortal);
461 return containerRef.instance;
462 }
463 /**
464 * Attaches the user-provided component to the already-created side sheet container.
465 * @param componentOrTemplateRef The type of component being loaded into the side-sheet,
466 * or a TemplateRef to instantiate as the content.
467 * @param dialogContainer Reference to the wrapping side-sheet container.
468 * @param overlayRef Reference to the overlay in which the side-sheet resides.
469 * @param config The side-sheet configuration.
470 * @returns A promise resolving to the CovalentSideSheetRef that should be returned to the user.
471 */
472 _attachSideSheetContent(componentOrTemplateRef, sideSheetContainer, overlayRef, config) {
473 // Create a reference to the side-sheet we're creating in order to give the user a handle
474 // to modify and close it.
475 const sideSheetRef = new this._sideSheetRefConstructor(overlayRef, config, sideSheetContainer, config.id);
476 if (componentOrTemplateRef instanceof TemplateRef) {
477 sideSheetContainer.attachTemplatePortal(
478 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
479 new TemplatePortal(componentOrTemplateRef, null, {
480 $implicit: config.data,
481 sideSheetRef,
482 }));
483 }
484 else {
485 const injector = this._createInjector(config, sideSheetRef, sideSheetContainer);
486 const contentRef = sideSheetContainer.attach(new ComponentPortal(componentOrTemplateRef, config.viewContainerRef, injector));
487 sideSheetRef.componentInstance = contentRef.instance;
488 }
489 sideSheetRef.updateSize(config.width, config.height);
490 return sideSheetRef;
491 }
492 _createInjector(config, sideSheetRef, sideSheetContainer) {
493 const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
494 // The side-sheet container should be provided as the side-sheet container and the side-sheet's
495 // content are created out of the same `ViewContainerRef` and as such, are siblings
496 // for injector purposes. To allow the hierarchy that is expected, the side-sheet
497 // container is explicitly provided in the injector.
498 const providers = [
499 { provide: this._sideSheetContainerType, useValue: sideSheetContainer },
500 { provide: this._sideSheetDataToken, useValue: config.data },
501 { provide: this._sideSheetRefConstructor, useValue: sideSheetRef },
502 ];
503 if (config.direction &&
504 (!userInjector ||
505 !userInjector.get(Directionality, null, InjectFlags.Optional))) {
506 providers.push({
507 provide: Directionality,
508 useValue: { value: config.direction, change: of() },
509 });
510 }
511 return Injector.create({
512 parent: userInjector || this._injector,
513 providers,
514 });
515 }
516 /**
517 * Removes a side sheet from the array of open side sheets.
518 * @param sideSheetRef Side Sheet to be removed.
519 */
520 _removeOpenSideSheet(sideSheetRef) {
521 const index = this.openSideSheets.indexOf(sideSheetRef);
522 if (index > -1) {
523 this.openSideSheets.splice(index, 1);
524 }
525 }
526 /** Closes all of the side-sheet in an array. */
527 _closeSideSheets(sideSheets) {
528 let i = sideSheets.length;
529 while (i--) {
530 sideSheets[i].close();
531 }
532 }
533 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: _CovalentSideSheetBase, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
534 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: _CovalentSideSheetBase, ngImport: i0 });
535}
536i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: _CovalentSideSheetBase, decorators: [{
537 type: Directive
538 }], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }, { type: undefined }, { type: undefined }, { type: i0.Type }, { type: i0.Type }, { type: i0.InjectionToken }] });
539/**
540 * Service to open Covalent Design side-sheet.
541 */
542class CovalentSideSheet extends _CovalentSideSheetBase {
543 constructor(overlay, injector, defaultOptions, parentSideSheet) {
544 super(overlay, injector, defaultOptions, parentSideSheet, CovalentSideSheetRef, CovalentSideSheetContainerComponent, MAT_DIALOG_DATA);
545 }
546 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheet, deps: [{ token: i1$1.Overlay }, { token: i0.Injector }, { token: MAT_DIALOG_DEFAULT_OPTIONS, optional: true }, { token: CovalentSideSheet, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Injectable });
547 static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheet });
548}
549i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheet, decorators: [{
550 type: Injectable
551 }], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }, { type: CovalentSideSheetConfig, decorators: [{
552 type: Optional
553 }, {
554 type: Inject,
555 args: [MAT_DIALOG_DEFAULT_OPTIONS]
556 }] }, { type: CovalentSideSheet, decorators: [{
557 type: Optional
558 }, {
559 type: SkipSelf
560 }] }] });
561
562/* tslint:disable */
563/** Counter used to generate unique IDs for dialog elements. */
564let dialogElementUid = 0;
565/**
566 * Button that will close the current dialog.
567 */
568class CovalentSideSheetCloseDirective {
569 dialogRef;
570 _elementRef;
571 _dialog;
572 /** Screenreader label for the button. */
573 ariaLabel;
574 /** Default to "button" to prevents accidental form submits. */
575 type = 'button';
576 /** Dialog close input. */
577 dialogResult;
578 _CovalentSideSheetClose;
579 onClick($event) {
580 this._onButtonClick($event);
581 }
582 constructor(dialogRef, _elementRef, _dialog) {
583 this.dialogRef = dialogRef;
584 this._elementRef = _elementRef;
585 this._dialog = _dialog;
586 }
587 ngOnInit() {
588 if (!this.dialogRef) {
589 // When this directive is included in a dialog via TemplateRef (rather than being
590 // in a Component), the DialogRef isn't available via injection because embedded
591 // views cannot be given a custom injector. Instead, we look up the DialogRef by
592 // ID. This must occur in `onInit`, as the ID binding for the dialog container won't
593 // be resolved at constructor time.
594 this.dialogRef = getClosestDialog(this._elementRef, this._dialog.openSideSheets);
595 }
596 }
597 ngOnChanges(changes) {
598 const proxiedChange = changes['_CovalentSideSheetClose'] ||
599 changes['_CovalentSideSheetCloseResult'];
600 if (proxiedChange) {
601 this.dialogResult = proxiedChange.currentValue;
602 }
603 }
604 _onButtonClick(event) {
605 // Determinate the focus origin using the click event, because using the FocusMonitor will
606 // result in incorrect origins. Most of the time, close buttons will be auto focused in the
607 // dialog, and therefore clicking the button won't result in a focus change. This means that
608 // the FocusMonitor won't detect any origin change, and will always output `program`.
609 _closeSideSheetVia(this.dialogRef, event.screenX === 0 && event.screenY === 0 ? 'keyboard' : 'mouse', this.dialogResult);
610 }
611 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetCloseDirective, deps: [{ token: CovalentSideSheetRef, optional: true }, { token: i0.ElementRef }, { token: CovalentSideSheet }], target: i0.ɵɵFactoryTarget.Directive });
612 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetCloseDirective, selector: "[td-side-sheet-close], [CovalentSideSheetClose]", inputs: { ariaLabel: ["aria-label", "ariaLabel"], type: "type", dialogResult: ["td-side-sheet-close", "dialogResult"], _CovalentSideSheetClose: ["CovalentSideSheetClose", "_CovalentSideSheetClose"] }, host: { listeners: { "click": "onClick($event)" }, properties: { "attr.arial-label": "this.ariaLabel", "attr.type": "this.type" } }, exportAs: ["CovalentSideSheetClose"], usesOnChanges: true, ngImport: i0 });
613}
614i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetCloseDirective, decorators: [{
615 type: Directive,
616 args: [{
617 selector: '[td-side-sheet-close], [CovalentSideSheetClose]',
618 exportAs: 'CovalentSideSheetClose',
619 }]
620 }], ctorParameters: () => [{ type: CovalentSideSheetRef, decorators: [{
621 type: Optional
622 }] }, { type: i0.ElementRef }, { type: CovalentSideSheet }], propDecorators: { ariaLabel: [{
623 type: HostBinding,
624 args: ['attr.arial-label']
625 }, {
626 type: Input,
627 args: ['aria-label']
628 }], type: [{
629 type: HostBinding,
630 args: ['attr.type']
631 }, {
632 type: Input
633 }], dialogResult: [{
634 type: Input,
635 args: ['td-side-sheet-close']
636 }], _CovalentSideSheetClose: [{
637 type: Input,
638 args: ['CovalentSideSheetClose']
639 }], onClick: [{
640 type: HostListener,
641 args: ['click', ['$event']]
642 }] } });
643/**
644 * Title of a side sheet element. Stays fixed to the top of the side sheet when scrolling.
645 */
646class CovalentSideSheetTitleDirective {
647 _dialogRef;
648 _elementRef;
649 _dialog;
650 /** Unique id for the dialog title. If none is supplied, it will be auto-generated. */
651 id = `td-side-sheet-title-${dialogElementUid++}`;
652 tdSideSheetTitle = true;
653 idAttr = this.id;
654 constructor(
655 // The dialog title directive is always used in combination with a `CovalentSideSheetRef`.
656 // tslint:disable-next-line: lightweight-tokens
657 _dialogRef, _elementRef, _dialog) {
658 this._dialogRef = _dialogRef;
659 this._elementRef = _elementRef;
660 this._dialog = _dialog;
661 }
662 ngOnInit() {
663 if (this._dialogRef) {
664 Promise.resolve().then(() => {
665 const container = this._dialogRef._containerInstance;
666 if (container && !container._ariaLabelledByQueue.includes(this.id)) {
667 container._ariaLabelledByQueue.push(this.id);
668 }
669 });
670 }
671 else {
672 this._dialogRef = getClosestDialog(this._elementRef, this._dialog.openSideSheets);
673 }
674 }
675 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetTitleDirective, deps: [{ token: CovalentSideSheetRef, optional: true }, { token: i0.ElementRef }, { token: CovalentSideSheet }], target: i0.ɵɵFactoryTarget.Directive });
676 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetTitleDirective, selector: "[td-side-sheet-title], [CovalentSideSheetTitle]", inputs: { id: "id" }, host: { properties: { "class.td-side-sheet-title": "this.tdSideSheetTitle", "attr.id": "this.idAttr" } }, exportAs: ["CovalentSideSheetTitle"], ngImport: i0 });
677}
678i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetTitleDirective, decorators: [{
679 type: Directive,
680 args: [{
681 selector: '[td-side-sheet-title], [CovalentSideSheetTitle]',
682 exportAs: 'CovalentSideSheetTitle',
683 }]
684 }], ctorParameters: () => [{ type: CovalentSideSheetRef, decorators: [{
685 type: Optional
686 }] }, { type: i0.ElementRef }, { type: CovalentSideSheet }], propDecorators: { id: [{
687 type: Input
688 }], tdSideSheetTitle: [{
689 type: HostBinding,
690 args: ['class.td-side-sheet-title']
691 }], idAttr: [{
692 type: HostBinding,
693 args: ['attr.id']
694 }] } });
695/**
696 * Scrollable content container of a dialog.
697 */
698class CovalentSideSheetContentDirective {
699 tdSideSheetContent = true;
700 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
701 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetContentDirective, selector: "[td-side-sheet-content], td-side-sheet-content, [CovalentSideSheetContent]", host: { properties: { "class.td-side-sheet-content": "this.tdSideSheetContent" } }, ngImport: i0 });
702}
703i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetContentDirective, decorators: [{
704 type: Directive,
705 args: [{
706 selector: `[td-side-sheet-content], td-side-sheet-content, [CovalentSideSheetContent]`,
707 }]
708 }], propDecorators: { tdSideSheetContent: [{
709 type: HostBinding,
710 args: ['class.td-side-sheet-content']
711 }] } });
712/**
713 * Container for the bottom action buttons in a dialog.
714 * Stays fixed to the bottom when scrolling.
715 */
716class CovalentSideSheetActionsDirective {
717 tdSideSheetActions = true;
718 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetActionsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
719 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetActionsDirective, selector: "[td-side-sheet-actions], td-side-sheet-actions, [CovalentSideSheetActions]", host: { properties: { "class.td-side-sheet-actions": "this.tdSideSheetActions" } }, ngImport: i0 });
720}
721i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetActionsDirective, decorators: [{
722 type: Directive,
723 args: [{
724 selector: `[td-side-sheet-actions], td-side-sheet-actions, [CovalentSideSheetActions]`,
725 }]
726 }], propDecorators: { tdSideSheetActions: [{
727 type: HostBinding,
728 args: ['class.td-side-sheet-actions']
729 }] } });
730/**
731 * Container for the wrapper part of the dialog
732 */
733class CovalentSideSheetWrapperDirective {
734 tdSideSheetWrapper = true;
735 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetWrapperDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
736 static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.1.2", type: CovalentSideSheetWrapperDirective, selector: "[td-side-sheet-wrapper], td-side-sheet-wrapper, [CovalentSideSheetWrapper]", host: { properties: { "class.td-side-sheet-wrapper": "this.tdSideSheetWrapper" } }, ngImport: i0 });
737}
738i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetWrapperDirective, decorators: [{
739 type: Directive,
740 args: [{
741 selector: `[td-side-sheet-wrapper], td-side-sheet-wrapper, [CovalentSideSheetWrapper]`,
742 }]
743 }], propDecorators: { tdSideSheetWrapper: [{
744 type: HostBinding,
745 args: ['class.td-side-sheet-wrapper']
746 }] } });
747/**
748 * Finds the closest CovalentSideSheetRef to an element by looking at the DOM.
749 * @param element Element relative to which to look for a dialog.
750 * @param openDialogs References to the currently-open dialogs.
751 */
752function getClosestDialog(element, openDialogs) {
753 let parent = element.nativeElement.parentElement;
754 while (parent && !parent.classList.contains('td-side-sheet-container')) {
755 parent = parent.parentElement;
756 }
757 return parent
758 ? openDialogs.find((dialog) => dialog.id === parent?.id) ?? openDialogs[0]
759 : openDialogs[0];
760}
761
762class CovalentSideSheetModule {
763 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
764 static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetModule, declarations: [CovalentSideSheetContainerComponent,
765 CovalentSideSheetActionsDirective,
766 CovalentSideSheetCloseDirective,
767 CovalentSideSheetContentDirective,
768 CovalentSideSheetTitleDirective,
769 CovalentSideSheetWrapperDirective], imports: [PortalModule, MatDialogModule, MatCommonModule], exports: [CovalentSideSheetActionsDirective,
770 CovalentSideSheetCloseDirective,
771 CovalentSideSheetContentDirective,
772 CovalentSideSheetTitleDirective,
773 CovalentSideSheetWrapperDirective] });
774 static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetModule, providers: [CovalentSideSheet], imports: [PortalModule, MatDialogModule, MatCommonModule] });
775}
776i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentSideSheetModule, decorators: [{
777 type: NgModule,
778 args: [{
779 declarations: [
780 CovalentSideSheetContainerComponent,
781 CovalentSideSheetActionsDirective,
782 CovalentSideSheetCloseDirective,
783 CovalentSideSheetContentDirective,
784 CovalentSideSheetTitleDirective,
785 CovalentSideSheetWrapperDirective,
786 ],
787 exports: [
788 CovalentSideSheetActionsDirective,
789 CovalentSideSheetCloseDirective,
790 CovalentSideSheetContentDirective,
791 CovalentSideSheetTitleDirective,
792 CovalentSideSheetWrapperDirective,
793 ],
794 imports: [PortalModule, MatDialogModule, MatCommonModule],
795 providers: [CovalentSideSheet],
796 }]
797 }] });
798
799/**
800 * Generated bundle index. Do not edit.
801 */
802
803export { CovalentSideSheet, CovalentSideSheetActionsDirective, CovalentSideSheetCloseDirective, CovalentSideSheetConfig, CovalentSideSheetContentDirective, CovalentSideSheetModule, CovalentSideSheetRef, CovalentSideSheetTitleDirective, CovalentSideSheetWrapperDirective, SubPageMode, _CovalentSideSheetBase, _closeSideSheetVia };
804//# sourceMappingURL=covalent-core-side-sheet.mjs.map
805
\No newline at end of file