UNPKG

30.5 kBJavaScriptView Raw
1import { Injectable, InjectionToken, Component, ElementRef, Renderer2, HostListener, EventEmitter, Directive, ViewContainerRef, Optional, Inject, Input, Output, RendererFactory2, NgModule } from '@angular/core';
2import { isBs3, Utils, document as document$1, window as window$1 } from 'ngx-bootstrap/utils';
3import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
4import { PositioningService } from 'ngx-bootstrap/positioning';
5import { FocusTrapModule } from 'ngx-bootstrap/focus-trap';
6
7// eslint-disable-next-line @typescript-eslint/no-explicit-any
8class BsModalRef {
9 constructor() {
10 /**
11 * Hides the modal
12 */
13 this.hide = () => void 0;
14 /**
15 * Sets new class to modal window
16 */
17 this.setClass = () => void 0;
18 }
19}
20BsModalRef.decorators = [
21 { type: Injectable }
22];
23
24class ModalBackdropOptions {
25 constructor(options) {
26 this.animate = true;
27 Object.assign(this, options);
28 }
29}
30
31class ModalOptions {
32}
33ModalOptions.decorators = [
34 { type: Injectable }
35];
36const modalConfigDefaults = {
37 backdrop: true,
38 keyboard: true,
39 focus: true,
40 show: false,
41 ignoreBackdropClick: false,
42 class: '',
43 animated: true,
44 initialState: {},
45 closeInterceptor: void 0
46};
47const MODAL_CONFIG_DEFAULT_OVERRIDE = new InjectionToken('override-default-config');
48const CLASS_NAME = {
49 SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
50 BACKDROP: 'modal-backdrop',
51 OPEN: 'modal-open',
52 FADE: 'fade',
53 IN: 'in',
54 SHOW: 'show' // bs4
55};
56const SELECTOR = {
57 DIALOG: '.modal-dialog',
58 DATA_TOGGLE: '[data-toggle="modal"]',
59 DATA_DISMISS: '[data-dismiss="modal"]',
60 FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
61};
62const TRANSITION_DURATIONS = {
63 MODAL: 300,
64 BACKDROP: 150
65};
66const DISMISS_REASONS = {
67 BACKRDOP: 'backdrop-click',
68 ESC: 'esc',
69 BACK: 'browser-back-navigation-clicked'
70};
71
72class ModalContainerComponent {
73 constructor(options, _element, _renderer) {
74 this._element = _element;
75 this._renderer = _renderer;
76 this.isShown = false;
77 this.isAnimated = false;
78 this.isModalHiding = false;
79 this.clickStartedInContent = false;
80 this.config = Object.assign({}, options);
81 }
82 ngOnInit() {
83 if (this.isAnimated) {
84 this._renderer.addClass(this._element.nativeElement, CLASS_NAME.FADE);
85 }
86 this._renderer.setStyle(this._element.nativeElement, 'display', 'block');
87 setTimeout(() => {
88 this.isShown = true;
89 this._renderer.addClass(this._element.nativeElement, isBs3() ? CLASS_NAME.IN : CLASS_NAME.SHOW);
90 }, this.isAnimated ? TRANSITION_DURATIONS.BACKDROP : 0);
91 if (document && document.body) {
92 if (this.bsModalService && this.bsModalService.getModalsCount() === 1) {
93 this.bsModalService.checkScrollbar();
94 this.bsModalService.setScrollbar();
95 }
96 this._renderer.addClass(document.body, CLASS_NAME.OPEN);
97 this._renderer.setStyle(document.body, 'overflow-y', 'hidden');
98 }
99 if (this._element.nativeElement) {
100 this._element.nativeElement.focus();
101 }
102 }
103 onClickStarted(event) {
104 this.clickStartedInContent = event.target !== this._element.nativeElement;
105 }
106 onClickStop(event) {
107 var _a;
108 const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;
109 if (this.config.ignoreBackdropClick ||
110 this.config.backdrop === 'static' ||
111 !clickedInBackdrop) {
112 this.clickStartedInContent = false;
113 return;
114 }
115 (_a = this.bsModalService) === null || _a === void 0 ? void 0 : _a.setDismissReason(DISMISS_REASONS.BACKRDOP);
116 this.hide();
117 }
118 onPopState() {
119 var _a;
120 (_a = this.bsModalService) === null || _a === void 0 ? void 0 : _a.setDismissReason(DISMISS_REASONS.BACK);
121 this.hide();
122 }
123 onEsc(event) {
124 var _a, _b;
125 if (!this.isShown) {
126 return;
127 }
128 if (event.keyCode === 27 || event.key === 'Escape') {
129 event.preventDefault();
130 }
131 if (this.config.keyboard &&
132 this.level === ((_a = this.bsModalService) === null || _a === void 0 ? void 0 : _a.getModalsCount())) {
133 (_b = this.bsModalService) === null || _b === void 0 ? void 0 : _b.setDismissReason(DISMISS_REASONS.ESC);
134 this.hide();
135 }
136 }
137 ngOnDestroy() {
138 if (this.isShown) {
139 this._hide();
140 }
141 }
142 hide() {
143 if (this.isModalHiding || !this.isShown) {
144 return;
145 }
146 if (this.config.closeInterceptor) {
147 this.config.closeInterceptor().then(() => this._hide(), () => undefined);
148 return;
149 }
150 this._hide();
151 }
152 _hide() {
153 this.isModalHiding = true;
154 this._renderer.removeClass(this._element.nativeElement, isBs3() ? CLASS_NAME.IN : CLASS_NAME.SHOW);
155 setTimeout(() => {
156 var _a, _b;
157 this.isShown = false;
158 if (document &&
159 document.body &&
160 ((_a = this.bsModalService) === null || _a === void 0 ? void 0 : _a.getModalsCount()) === 1) {
161 this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
162 this._renderer.setStyle(document.body, 'overflow-y', '');
163 }
164 (_b = this.bsModalService) === null || _b === void 0 ? void 0 : _b.hide(this.config.id);
165 this.isModalHiding = false;
166 }, this.isAnimated ? TRANSITION_DURATIONS.MODAL : 0);
167 }
168}
169ModalContainerComponent.decorators = [
170 { type: Component, args: [{
171 selector: 'modal-container',
172 template: `
173 <div [class]="'modal-dialog' + (config.class ? ' ' + config.class : '')"
174 role="document"
175 focusTrap>
176 <div class="modal-content">
177 <ng-content></ng-content>
178 </div>
179 </div>
180 `,
181 // eslint-disable-next-line @angular-eslint/no-host-metadata-property
182 host: {
183 class: 'modal',
184 role: 'dialog',
185 tabindex: '-1',
186 '[attr.aria-modal]': 'true',
187 '[attr.aria-labelledby]': 'config.ariaLabelledBy',
188 '[attr.aria-describedby]': 'config.ariaDescribedby'
189 }
190 },] }
191];
192ModalContainerComponent.ctorParameters = () => [
193 { type: ModalOptions },
194 { type: ElementRef },
195 { type: Renderer2 }
196];
197ModalContainerComponent.propDecorators = {
198 onClickStarted: [{ type: HostListener, args: ['mousedown', ['$event'],] }],
199 onClickStop: [{ type: HostListener, args: ['click', ['$event'],] }],
200 onPopState: [{ type: HostListener, args: ['window:popstate',] }],
201 onEsc: [{ type: HostListener, args: ['window:keydown.esc', ['$event'],] }]
202};
203
204/** This component will be added as background layout for modals if enabled */
205class ModalBackdropComponent {
206 constructor(element, renderer) {
207 this._isAnimated = false;
208 this._isShown = false;
209 this.element = element;
210 this.renderer = renderer;
211 }
212 get isAnimated() {
213 return this._isAnimated;
214 }
215 set isAnimated(value) {
216 this._isAnimated = value;
217 }
218 get isShown() {
219 return this._isShown;
220 }
221 set isShown(value) {
222 this._isShown = value;
223 if (value) {
224 this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.IN}`);
225 }
226 else {
227 this.renderer.removeClass(this.element.nativeElement, `${CLASS_NAME.IN}`);
228 }
229 if (!isBs3()) {
230 if (value) {
231 this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
232 }
233 else {
234 this.renderer.removeClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
235 }
236 }
237 }
238 ngOnInit() {
239 if (this.isAnimated) {
240 this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.FADE}`);
241 Utils.reflow(this.element.nativeElement);
242 }
243 this.isShown = true;
244 }
245}
246ModalBackdropComponent.decorators = [
247 { type: Component, args: [{
248 selector: 'bs-modal-backdrop',
249 template: ' ',
250 // eslint-disable-next-line @angular-eslint/no-host-metadata-property
251 host: { class: CLASS_NAME.BACKDROP }
252 },] }
253];
254ModalBackdropComponent.ctorParameters = () => [
255 { type: ElementRef },
256 { type: Renderer2 }
257];
258
259// todo: should we support enforce focus in?
260const TRANSITION_DURATION = 300;
261const BACKDROP_TRANSITION_DURATION = 150;
262/** Mark any code with directive to show it's content in modal */
263class ModalDirective {
264 constructor(_element, _viewContainerRef, _renderer, clf, modalDefaultOption) {
265 this._element = _element;
266 this._renderer = _renderer;
267 /** This event fires immediately when the `show` instance method is called. */
268 this.onShow = new EventEmitter();
269 /** This event is fired when the modal has been made visible to the user
270 * (will wait for CSS transitions to complete)
271 */
272 this.onShown = new EventEmitter();
273 /** This event is fired immediately when
274 * the hide instance method has been called.
275 */
276 this.onHide = new EventEmitter();
277 /** This event is fired when the modal has finished being
278 * hidden from the user (will wait for CSS transitions to complete).
279 */
280 this.onHidden = new EventEmitter();
281 this._isShown = false;
282 this.isBodyOverflowing = false;
283 this.originalBodyPadding = 0;
284 this.scrollbarWidth = 0;
285 this.timerHideModal = 0;
286 this.timerRmBackDrop = 0;
287 this.isNested = false;
288 this.clickStartedInContent = false;
289 this._backdrop = clf.createLoader(_element, _viewContainerRef, _renderer);
290 this._config = modalDefaultOption || modalConfigDefaults;
291 }
292 /** allows to set modal configuration via element property */
293 set config(conf) {
294 this._config = this.getConfig(conf);
295 }
296 get config() {
297 return this._config;
298 }
299 get isShown() {
300 return this._isShown;
301 }
302 onClickStarted(event) {
303 this.clickStartedInContent = event.target !== this._element.nativeElement;
304 }
305 onClickStop(event) {
306 const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;
307 if (this.config.ignoreBackdropClick ||
308 this.config.backdrop === 'static' ||
309 !clickedInBackdrop) {
310 this.clickStartedInContent = false;
311 return;
312 }
313 this.dismissReason = DISMISS_REASONS.BACKRDOP;
314 this.hide(event);
315 }
316 // todo: consider preventing default and stopping propagation
317 onEsc(event) {
318 if (!this._isShown) {
319 return;
320 }
321 if (event.keyCode === 27 || event.key === 'Escape') {
322 event.preventDefault();
323 }
324 if (this.config.keyboard) {
325 this.dismissReason = DISMISS_REASONS.ESC;
326 this.hide();
327 }
328 }
329 ngOnDestroy() {
330 if (this._isShown) {
331 this._isShown = false;
332 this.hideModal();
333 this._backdrop.dispose();
334 }
335 }
336 ngOnInit() {
337 this._config = this._config || this.getConfig();
338 setTimeout(() => {
339 if (this._config.show) {
340 this.show();
341 }
342 }, 0);
343 }
344 /* Public methods */
345 /** Allows to manually toggle modal visibility */
346 toggle() {
347 return this._isShown ? this.hide() : this.show();
348 }
349 /** Allows to manually open modal */
350 show() {
351 this.dismissReason = void 0;
352 this.onShow.emit(this);
353 if (this._isShown) {
354 return;
355 }
356 clearTimeout(this.timerHideModal);
357 clearTimeout(this.timerRmBackDrop);
358 this._isShown = true;
359 this.checkScrollbar();
360 this.setScrollbar();
361 if (document$1 && document$1.body) {
362 if (document$1.body.classList.contains(CLASS_NAME.OPEN)) {
363 this.isNested = true;
364 }
365 else {
366 this._renderer.addClass(document$1.body, CLASS_NAME.OPEN);
367 this._renderer.setStyle(document$1.body, 'overflow-y', 'hidden');
368 }
369 }
370 this.showBackdrop(() => {
371 this.showElement();
372 });
373 }
374 /** Check if we can close the modal */
375 hide(event) {
376 if (!this._isShown) {
377 return;
378 }
379 if (event) {
380 event.preventDefault();
381 }
382 if (this.config.closeInterceptor) {
383 this.config.closeInterceptor().then(() => this._hide(), () => undefined);
384 return;
385 }
386 this._hide();
387 }
388 /** Private methods @internal */
389 /**
390 * Manually close modal
391 * @internal
392 */
393 _hide() {
394 this.onHide.emit(this);
395 window$1.clearTimeout(this.timerHideModal);
396 window$1.clearTimeout(this.timerRmBackDrop);
397 this._isShown = false;
398 this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.IN);
399 if (!isBs3()) {
400 this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);
401 }
402 // this._addClassIn = false;
403 if (this._config.animated) {
404 this.timerHideModal = window$1.setTimeout(() => this.hideModal(), TRANSITION_DURATION);
405 }
406 else {
407 this.hideModal();
408 }
409 }
410 getConfig(config) {
411 return Object.assign({}, this._config, config);
412 }
413 /**
414 * Show dialog
415 * @internal
416 */
417 showElement() {
418 // todo: replace this with component loader usage
419 if (!this._element.nativeElement.parentNode ||
420 this._element.nativeElement.parentNode.nodeType !== Node.ELEMENT_NODE) {
421 // don't move modals dom position
422 if (document$1 && document$1.body) {
423 document$1.body.appendChild(this._element.nativeElement);
424 }
425 }
426 this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'false');
427 this._renderer.setAttribute(this._element.nativeElement, 'aria-modal', 'true');
428 this._renderer.setStyle(this._element.nativeElement, 'display', 'block');
429 this._renderer.setProperty(this._element.nativeElement, 'scrollTop', 0);
430 if (this._config.animated) {
431 Utils.reflow(this._element.nativeElement);
432 }
433 // this._addClassIn = true;
434 this._renderer.addClass(this._element.nativeElement, CLASS_NAME.IN);
435 if (!isBs3()) {
436 this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);
437 }
438 const transitionComplete = () => {
439 if (this._config.focus) {
440 this._element.nativeElement.focus();
441 }
442 this.onShown.emit(this);
443 };
444 if (this._config.animated) {
445 setTimeout(transitionComplete, TRANSITION_DURATION);
446 }
447 else {
448 transitionComplete();
449 }
450 }
451 /** @internal */
452 hideModal() {
453 this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'true');
454 this._renderer.setStyle(this._element.nativeElement, 'display', 'none');
455 this.showBackdrop(() => {
456 if (!this.isNested) {
457 if (document$1 && document$1.body) {
458 this._renderer.removeClass(document$1.body, CLASS_NAME.OPEN);
459 this._renderer.setStyle(document$1.body, 'overflow-y', '');
460 }
461 this.resetScrollbar();
462 }
463 this.resetAdjustments();
464 this.focusOtherModal();
465 this.onHidden.emit(this);
466 });
467 }
468 // todo: original show was calling a callback when done, but we can use
469 // promise
470 /** @internal */
471 showBackdrop(callback) {
472 if (this._isShown &&
473 this.config.backdrop &&
474 (!this.backdrop || !this.backdrop.instance.isShown)) {
475 this.removeBackdrop();
476 this._backdrop
477 .attach(ModalBackdropComponent)
478 .to('body')
479 .show({ isAnimated: this._config.animated });
480 this.backdrop = this._backdrop._componentRef;
481 if (!callback) {
482 return;
483 }
484 if (!this._config.animated) {
485 callback();
486 return;
487 }
488 setTimeout(callback, BACKDROP_TRANSITION_DURATION);
489 }
490 else if (!this._isShown && this.backdrop) {
491 this.backdrop.instance.isShown = false;
492 const callbackRemove = () => {
493 this.removeBackdrop();
494 if (callback) {
495 callback();
496 }
497 };
498 if (this.backdrop.instance.isAnimated) {
499 this.timerRmBackDrop = window$1.setTimeout(callbackRemove, BACKDROP_TRANSITION_DURATION);
500 }
501 else {
502 callbackRemove();
503 }
504 }
505 else if (callback) {
506 callback();
507 }
508 }
509 /** @internal */
510 removeBackdrop() {
511 this._backdrop.hide();
512 }
513 /** Events tricks */
514 // no need for it
515 // protected setEscapeEvent():void {
516 // if (this._isShown && this._config.keyboard) {
517 // $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
518 // if (event.which === 27) {
519 // this.hide()
520 // }
521 // })
522 //
523 // } else if (!this._isShown) {
524 // $(this._element).off(Event.KEYDOWN_DISMISS)
525 // }
526 // }
527 // protected setResizeEvent():void {
528 // console.log(this.renderer.listenGlobal('', Event.RESIZE));
529 // if (this._isShown) {
530 // $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
531 // } else {
532 // $(window).off(Event.RESIZE)
533 // }
534 // }
535 focusOtherModal() {
536 if (this._element.nativeElement.parentElement == null) {
537 return;
538 }
539 const otherOpenedModals = this._element.nativeElement.parentElement.querySelectorAll('.in[bsModal]');
540 if (!otherOpenedModals.length) {
541 return;
542 }
543 otherOpenedModals[otherOpenedModals.length - 1].focus();
544 }
545 /** @internal */
546 resetAdjustments() {
547 this._renderer.setStyle(this._element.nativeElement, 'paddingLeft', '');
548 this._renderer.setStyle(this._element.nativeElement, 'paddingRight', '');
549 }
550 /** Scroll bar tricks */
551 /** @internal */
552 checkScrollbar() {
553 this.isBodyOverflowing = document$1.body.clientWidth < window$1.innerWidth;
554 this.scrollbarWidth = this.getScrollbarWidth();
555 }
556 setScrollbar() {
557 if (!document$1) {
558 return;
559 }
560 this.originalBodyPadding = parseInt(window$1
561 .getComputedStyle(document$1.body)
562 .getPropertyValue('padding-right') || 0, 10);
563 if (this.isBodyOverflowing) {
564 document$1.body.style.paddingRight = `${this.originalBodyPadding +
565 this.scrollbarWidth}px`;
566 }
567 }
568 resetScrollbar() {
569 document$1.body.style.paddingRight = `${this.originalBodyPadding}px`;
570 }
571 // thx d.walsh
572 getScrollbarWidth() {
573 const scrollDiv = this._renderer.createElement('div');
574 this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);
575 this._renderer.appendChild(document$1.body, scrollDiv);
576 const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
577 this._renderer.removeChild(document$1.body, scrollDiv);
578 return scrollbarWidth;
579 }
580}
581ModalDirective.decorators = [
582 { type: Directive, args: [{
583 selector: '[bsModal]',
584 exportAs: 'bs-modal'
585 },] }
586];
587ModalDirective.ctorParameters = () => [
588 { type: ElementRef },
589 { type: ViewContainerRef },
590 { type: Renderer2 },
591 { type: ComponentLoaderFactory },
592 { type: ModalOptions, decorators: [{ type: Optional }, { type: Inject, args: [MODAL_CONFIG_DEFAULT_OVERRIDE,] }] }
593];
594ModalDirective.propDecorators = {
595 config: [{ type: Input }],
596 closeInterceptor: [{ type: Input }],
597 onShow: [{ type: Output }],
598 onShown: [{ type: Output }],
599 onHide: [{ type: Output }],
600 onHidden: [{ type: Output }],
601 onClickStarted: [{ type: HostListener, args: ['mousedown', ['$event'],] }],
602 onClickStop: [{ type: HostListener, args: ['mouseup', ['$event'],] }],
603 onEsc: [{ type: HostListener, args: ['keydown.esc', ['$event'],] }]
604};
605
606class BsModalService {
607 constructor(rendererFactory, clf, modalDefaultOption) {
608 this.clf = clf;
609 this.modalDefaultOption = modalDefaultOption;
610 this.onShow = new EventEmitter();
611 this.onShown = new EventEmitter();
612 this.onHide = new EventEmitter();
613 this.onHidden = new EventEmitter();
614 this.isBodyOverflowing = false;
615 this.originalBodyPadding = 0;
616 this.scrollbarWidth = 0;
617 this.modalsCount = 0;
618 this.loaders = [];
619 this._backdropLoader = this.clf.createLoader();
620 this._renderer = rendererFactory.createRenderer(null, null);
621 this.config = modalDefaultOption ?
622 (Object.assign({}, modalConfigDefaults, modalDefaultOption)) :
623 modalConfigDefaults;
624 }
625 /** Shows a modal */
626 show(
627 // eslint-disable-next-line @typescript-eslint/no-explicit-any
628 content, config) {
629 this.modalsCount++;
630 this._createLoaders();
631 // must be different per every show() call
632 const id = (config === null || config === void 0 ? void 0 : config.id) || (new Date()).getUTCMilliseconds();
633 this.config = this.modalDefaultOption ?
634 Object.assign({}, modalConfigDefaults, this.modalDefaultOption, config) :
635 Object.assign({}, modalConfigDefaults, config);
636 this.config.id = id;
637 this._showBackdrop();
638 this.lastDismissReason = void 0;
639 return this._showModal(content);
640 }
641 hide(id) {
642 if (this.modalsCount === 1 || id == null) {
643 this._hideBackdrop();
644 this.resetScrollbar();
645 }
646 this.modalsCount = this.modalsCount >= 1 && id != null ? this.modalsCount - 1 : 0;
647 setTimeout(() => {
648 this._hideModal(id);
649 this.removeLoaders(id);
650 }, this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0);
651 }
652 _showBackdrop() {
653 const isBackdropEnabled = this.config.backdrop === true || this.config.backdrop === 'static';
654 const isBackdropInDOM = !this.backdropRef || !this.backdropRef.instance.isShown;
655 if (this.modalsCount === 1) {
656 this.removeBackdrop();
657 if (isBackdropEnabled && isBackdropInDOM) {
658 this._backdropLoader
659 .attach(ModalBackdropComponent)
660 .to('body')
661 .show({ isAnimated: this.config.animated });
662 this.backdropRef = this._backdropLoader._componentRef;
663 }
664 }
665 }
666 _hideBackdrop() {
667 if (!this.backdropRef) {
668 return;
669 }
670 this.backdropRef.instance.isShown = false;
671 const duration = this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0;
672 setTimeout(() => this.removeBackdrop(), duration);
673 }
674 // eslint-disable-next-line @typescript-eslint/no-explicit-any
675 _showModal(content) {
676 var _a;
677 const modalLoader = this.loaders[this.loaders.length - 1];
678 if (this.config && this.config.providers) {
679 for (const provider of this.config.providers) {
680 modalLoader.provide(provider);
681 }
682 }
683 // eslint-disable-next-line @typescript-eslint/no-explicit-any
684 const bsModalRef = new BsModalRef();
685 const modalContainerRef = modalLoader
686 .provide({ provide: ModalOptions, useValue: this.config })
687 .provide({ provide: BsModalRef, useValue: bsModalRef })
688 .attach(ModalContainerComponent)
689 .to('body');
690 bsModalRef.hide = () => { var _a; return (_a = modalContainerRef.instance) === null || _a === void 0 ? void 0 : _a.hide(); };
691 bsModalRef.setClass = (newClass) => {
692 if (modalContainerRef.instance) {
693 modalContainerRef.instance.config.class = newClass;
694 }
695 };
696 bsModalRef.onHidden = new EventEmitter();
697 bsModalRef.onHide = new EventEmitter();
698 this.copyEvent(modalLoader.onBeforeHide, bsModalRef.onHide);
699 this.copyEvent(modalLoader.onHidden, bsModalRef.onHidden);
700 // call 'show' method after assign setClass in bsModalRef.
701 // it makes modal component's bsModalRef available to call setClass method
702 modalContainerRef.show({
703 content,
704 isAnimated: this.config.animated,
705 initialState: this.config.initialState,
706 bsModalService: this,
707 id: this.config.id
708 });
709 if (modalContainerRef.instance) {
710 modalContainerRef.instance.level = this.getModalsCount();
711 bsModalRef.content = modalLoader.getInnerComponent();
712 bsModalRef.id = (_a = modalContainerRef.instance.config) === null || _a === void 0 ? void 0 : _a.id;
713 }
714 return bsModalRef;
715 }
716 _hideModal(id) {
717 if (id != null) {
718 const indexToRemove = this.loaders.findIndex(loader => { var _a; return ((_a = loader.instance) === null || _a === void 0 ? void 0 : _a.config.id) === id; });
719 const modalLoader = this.loaders[indexToRemove];
720 if (modalLoader) {
721 modalLoader.hide(id);
722 }
723 }
724 else {
725 this.loaders.forEach((loader) => {
726 if (loader.instance) {
727 loader.hide(loader.instance.config.id);
728 }
729 });
730 }
731 }
732 getModalsCount() {
733 return this.modalsCount;
734 }
735 setDismissReason(reason) {
736 this.lastDismissReason = reason;
737 }
738 removeBackdrop() {
739 this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
740 this._renderer.setStyle(document.body, 'overflow-y', '');
741 this._backdropLoader.hide();
742 this.backdropRef = void 0;
743 }
744 /** Checks if the body is overflowing and sets scrollbar width */
745 /** @internal */
746 checkScrollbar() {
747 this.isBodyOverflowing = document.body.clientWidth < window.innerWidth;
748 this.scrollbarWidth = this.getScrollbarWidth();
749 }
750 setScrollbar() {
751 if (!document) {
752 return;
753 }
754 this.originalBodyPadding = parseInt(window
755 .getComputedStyle(document.body)
756 .getPropertyValue('padding-right') || '0', 10);
757 if (this.isBodyOverflowing) {
758 document.body.style.paddingRight = `${this.originalBodyPadding +
759 this.scrollbarWidth}px`;
760 }
761 }
762 resetScrollbar() {
763 document.body.style.paddingRight = `${this.originalBodyPadding}px`;
764 }
765 // thx d.walsh
766 getScrollbarWidth() {
767 const scrollDiv = this._renderer.createElement('div');
768 this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);
769 this._renderer.appendChild(document.body, scrollDiv);
770 const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
771 this._renderer.removeChild(document.body, scrollDiv);
772 return scrollbarWidth;
773 }
774 _createLoaders() {
775 const loader = this.clf.createLoader();
776 this.copyEvent(loader.onBeforeShow, this.onShow);
777 this.copyEvent(loader.onShown, this.onShown);
778 this.copyEvent(loader.onBeforeHide, this.onHide);
779 this.copyEvent(loader.onHidden, this.onHidden);
780 this.loaders.push(loader);
781 }
782 removeLoaders(id) {
783 if (id != null) {
784 const indexToRemove = this.loaders.findIndex(loader => { var _a; return ((_a = loader.instance) === null || _a === void 0 ? void 0 : _a.config.id) === id; });
785 if (indexToRemove >= 0) {
786 this.loaders.splice(indexToRemove, 1);
787 this.loaders.forEach((loader, i) => {
788 if (loader.instance) {
789 loader.instance.level = i + 1;
790 }
791 });
792 }
793 }
794 else {
795 this.loaders.splice(0, this.loaders.length);
796 }
797 }
798 copyEvent(from, to) {
799 from.subscribe((data) => {
800 to.emit(this.lastDismissReason || data);
801 });
802 }
803}
804BsModalService.decorators = [
805 { type: Injectable }
806];
807BsModalService.ctorParameters = () => [
808 { type: RendererFactory2 },
809 { type: ComponentLoaderFactory },
810 { type: ModalOptions, decorators: [{ type: Optional }, { type: Inject, args: [MODAL_CONFIG_DEFAULT_OVERRIDE,] }] }
811];
812
813const focusTrapModule = FocusTrapModule.forRoot();
814class ModalModule {
815 static forRoot() {
816 return {
817 ngModule: ModalModule,
818 providers: [BsModalService, ComponentLoaderFactory, PositioningService]
819 };
820 }
821 static forChild() {
822 return {
823 ngModule: ModalModule,
824 providers: [BsModalService, ComponentLoaderFactory, PositioningService]
825 };
826 }
827}
828ModalModule.decorators = [
829 { type: NgModule, args: [{
830 imports: [FocusTrapModule],
831 declarations: [
832 ModalBackdropComponent,
833 ModalDirective,
834 ModalContainerComponent
835 ],
836 exports: [ModalBackdropComponent, ModalDirective],
837 entryComponents: [ModalBackdropComponent, ModalContainerComponent]
838 },] }
839];
840
841/**
842 * Generated bundle index. Do not edit.
843 */
844
845export { BsModalRef, BsModalService, MODAL_CONFIG_DEFAULT_OVERRIDE, ModalBackdropComponent, ModalBackdropOptions, ModalContainerComponent, ModalDirective, ModalModule, ModalOptions, CLASS_NAME as ɵa };
846//# sourceMappingURL=ngx-bootstrap-modal.js.map