ngx-bootstrap
Version:
Angular Bootstrap
893 lines (882 loc) • 35.9 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, Component, EventEmitter, Optional, Inject, HostListener, Directive, Input, Output, NgModule } from '@angular/core';
import * as i1 from 'ngx-bootstrap/component-loader';
import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
import { Utils, document, window as window$1 } from 'ngx-bootstrap/utils';
import { FocusTrapDirective, FocusTrapModule } from 'ngx-bootstrap/focus-trap';
import { PositioningService } from 'ngx-bootstrap/positioning';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
class BsModalRef {
constructor() {
/**
* Hides the modal
*/
this.hide = () => void 0;
/**
* Sets new class to modal window
*/
this.setClass = () => void 0;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalRef, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalRef, providedIn: 'platform' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalRef, decorators: [{
type: Injectable,
args: [{ providedIn: 'platform' }]
}] });
class ModalBackdropOptions {
constructor(options) {
this.animate = true;
Object.assign(this, options);
}
}
class ModalOptions {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalOptions, providedIn: 'platform' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalOptions, decorators: [{
type: Injectable,
args: [{ providedIn: 'platform' }]
}] });
const modalConfigDefaults = {
backdrop: true,
keyboard: true,
focus: true,
show: false,
ignoreBackdropClick: false,
class: '',
animated: true,
initialState: {},
closeInterceptor: void 0
};
const MODAL_CONFIG_DEFAULT_OVERRIDE = new InjectionToken('override-default-config');
const CLASS_NAME = {
SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
BACKDROP: 'modal-backdrop',
OPEN: 'modal-open',
FADE: 'fade',
IN: 'in',
SHOW: 'show'
};
const SELECTOR = {
DIALOG: '.modal-dialog',
DATA_TOGGLE: '[data-toggle="modal"]',
DATA_DISMISS: '[data-dismiss="modal"]',
FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
};
const TRANSITION_DURATIONS = {
MODAL: 300,
BACKDROP: 150
};
const DISMISS_REASONS = {
BACKRDOP: 'backdrop-click',
ESC: 'esc',
BACK: 'browser-back-navigation-clicked'
};
/** This component will be added as background layout for modals if enabled */
class ModalBackdropComponent {
get isAnimated() {
return this._isAnimated;
}
set isAnimated(value) {
this._isAnimated = value;
}
get isShown() {
return this._isShown;
}
set isShown(value) {
this._isShown = value;
if (value) {
this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
}
else {
this.renderer.removeClass(this.element.nativeElement, `${CLASS_NAME.SHOW}`);
}
}
constructor(element, renderer) {
this._isAnimated = false;
this._isShown = false;
this.element = element;
this.renderer = renderer;
}
ngOnInit() {
if (this.isAnimated) {
this.renderer.addClass(this.element.nativeElement, `${CLASS_NAME.FADE}`);
Utils.reflow(this.element.nativeElement);
}
this.isShown = true;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalBackdropComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.1", type: ModalBackdropComponent, isStandalone: true, selector: "bs-modal-backdrop", host: { classAttribute: "modal-backdrop" }, ngImport: i0, template: ' ', isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalBackdropComponent, decorators: [{
type: Component,
args: [{
selector: 'bs-modal-backdrop',
template: ' ',
host: { class: CLASS_NAME.BACKDROP },
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }] });
let currentId = 1;
class BsModalService {
constructor(rendererFactory, clf, modalDefaultOption) {
this.clf = clf;
this.modalDefaultOption = modalDefaultOption;
this.onShow = new EventEmitter();
this.onShown = new EventEmitter();
this.onHide = new EventEmitter();
this.onHidden = new EventEmitter();
this.isBodyOverflowing = false;
this.originalBodyPadding = 0;
this.scrollbarWidth = 0;
this.modalsCount = 0;
this.lastHiddenId = null;
this.loaders = [];
this._focusEl = null;
this._backdropLoader = this.clf.createLoader();
this._renderer = rendererFactory.createRenderer(null, null);
this.config = modalDefaultOption ?
(Object.assign({}, modalConfigDefaults, modalDefaultOption)) :
modalConfigDefaults;
}
/** Shows a modal */
show(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
content, config) {
this._focusEl = document.activeElement;
this.modalsCount++;
this.lastHiddenId = null;
this._createLoaders();
// must be different per every show() call
const id = config?.id || currentId++;
this.config = this.modalDefaultOption ?
Object.assign({}, modalConfigDefaults, this.modalDefaultOption, config) :
Object.assign({}, modalConfigDefaults, config);
this.config.id = id;
this._showBackdrop();
this.lastDismissReason = void 0;
return this._showModal(content);
}
hide(id) {
if (this.lastHiddenId === id) {
return;
}
this.lastHiddenId = id;
if (this.modalsCount === 1 || id == null) {
this._hideBackdrop();
this.resetScrollbar();
}
this.modalsCount = this.modalsCount >= 1 && id != null ? this.modalsCount - 1 : 0;
setTimeout(() => {
this._hideModal(id);
this.removeLoaders(id);
}, this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0);
if (this._focusEl) {
this._focusEl.focus();
}
}
_showBackdrop() {
const isBackdropEnabled = this.config.backdrop === true || this.config.backdrop === 'static';
const isBackdropInDOM = !this.backdropRef || !this.backdropRef.instance.isShown;
if (this.modalsCount === 1) {
this.removeBackdrop();
if (isBackdropEnabled && isBackdropInDOM) {
this._backdropLoader
.attach(ModalBackdropComponent)
.to('body')
.show({ isAnimated: this.config.animated });
this.backdropRef = this._backdropLoader._componentRef;
}
}
}
_hideBackdrop() {
if (!this.backdropRef) {
return;
}
this.backdropRef.instance.isShown = false;
const duration = this.config.animated ? TRANSITION_DURATIONS.BACKDROP : 0;
setTimeout(() => this.removeBackdrop(), duration);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_showModal(content) {
const modalLoader = this.loaders[this.loaders.length - 1];
if (this.config && this.config.providers) {
for (const provider of this.config.providers) {
modalLoader.provide(provider);
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const bsModalRef = new BsModalRef();
const modalContainerRef = modalLoader
.provide({ provide: ModalOptions, useValue: this.config })
.provide({ provide: BsModalRef, useValue: bsModalRef })
.attach(ModalContainerComponent)
.to('body');
bsModalRef.hide = () => modalContainerRef.instance?.hide();
bsModalRef.setClass = (newClass) => {
if (modalContainerRef.instance) {
modalContainerRef.instance.config.class = newClass;
}
};
bsModalRef.onHidden = new EventEmitter();
bsModalRef.onHide = new EventEmitter();
this.copyEvent(modalLoader.onBeforeHide, bsModalRef.onHide);
this.copyEvent(modalLoader.onHidden, bsModalRef.onHidden);
// call 'show' method after assign setClass in bsModalRef.
// it makes modal component's bsModalRef available to call setClass method
modalContainerRef.show({
content,
isAnimated: this.config.animated,
initialState: this.config.initialState,
bsModalService: this,
id: this.config.id
});
if (modalContainerRef.instance) {
modalContainerRef.instance.level = this.getModalsCount();
bsModalRef.content = modalLoader.getInnerComponent();
bsModalRef.id = modalContainerRef.instance.config?.id;
}
return bsModalRef;
}
_hideModal(id) {
if (id != null) {
const indexToRemove = this.loaders.findIndex(loader => loader.instance?.config.id === id);
const modalLoader = this.loaders[indexToRemove];
if (modalLoader) {
modalLoader.hide(id);
}
}
else {
this.loaders.forEach((loader) => {
if (loader.instance) {
loader.hide(loader.instance.config.id);
}
});
}
}
getModalsCount() {
return this.modalsCount;
}
setDismissReason(reason) {
this.lastDismissReason = reason;
}
removeBackdrop() {
this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
this._renderer.setStyle(document.body, 'overflow-y', '');
this._backdropLoader.hide();
this.backdropRef = void 0;
}
/** Checks if the body is overflowing and sets scrollbar width */
/** @internal */
checkScrollbar() {
this.isBodyOverflowing = document.body.clientWidth < window.innerWidth;
this.scrollbarWidth = this.getScrollbarWidth();
}
setScrollbar() {
if (!document) {
return;
}
this.originalBodyPadding = parseInt(window
.getComputedStyle(document.body)
.getPropertyValue('padding-right') || '0', 10);
if (this.isBodyOverflowing) {
document.body.style.paddingRight = `${this.originalBodyPadding +
this.scrollbarWidth}px`;
}
}
resetScrollbar() {
document.body.style.paddingRight = `${this.originalBodyPadding}px`;
}
// thx d.walsh
getScrollbarWidth() {
const scrollDiv = this._renderer.createElement('div');
this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);
this._renderer.appendChild(document.body, scrollDiv);
const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
this._renderer.removeChild(document.body, scrollDiv);
return scrollbarWidth;
}
_createLoaders() {
const loader = this.clf.createLoader();
this.copyEvent(loader.onBeforeShow, this.onShow);
this.copyEvent(loader.onShown, this.onShown);
this.copyEvent(loader.onBeforeHide, this.onHide);
this.copyEvent(loader.onHidden, this.onHidden);
this.loaders.push(loader);
}
removeLoaders(id) {
if (id != null) {
const indexToRemove = this.loaders.findIndex(loader => loader.instance?.config.id === id);
if (indexToRemove >= 0) {
this.loaders.splice(indexToRemove, 1);
this.loaders.forEach((loader, i) => {
if (loader.instance) {
loader.instance.level = i + 1;
}
});
}
}
else {
this.loaders.splice(0, this.loaders.length);
}
}
copyEvent(from, to) {
from.subscribe((data) => {
to.emit(this.lastDismissReason || data);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalService, deps: [{ token: i0.RendererFactory2 }, { token: i1.ComponentLoaderFactory }, { token: MODAL_CONFIG_DEFAULT_OVERRIDE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalService, providedIn: 'platform' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: BsModalService, decorators: [{
type: Injectable,
args: [{ providedIn: 'platform' }]
}], ctorParameters: () => [{ type: i0.RendererFactory2 }, { type: i1.ComponentLoaderFactory }, { type: ModalOptions, decorators: [{
type: Optional
}, {
type: Inject,
args: [MODAL_CONFIG_DEFAULT_OVERRIDE]
}] }] });
class ModalContainerComponent {
constructor(options, _element, _renderer) {
this._element = _element;
this._renderer = _renderer;
this.isShown = false;
this.isAnimated = false;
this._focusEl = null;
this.isModalHiding = false;
this.clickStartedInContent = false;
this.config = Object.assign({}, options);
}
ngOnInit() {
this._focusEl = document.activeElement;
if (this.isAnimated) {
this._renderer.addClass(this._element.nativeElement, CLASS_NAME.FADE);
}
this._renderer.setStyle(this._element.nativeElement, 'display', 'block');
setTimeout(() => {
this.isShown = true;
this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);
}, this.isAnimated ? TRANSITION_DURATIONS.BACKDROP : 0);
if (document && document.body) {
if (this.bsModalService && this.bsModalService.getModalsCount() === 1) {
this.bsModalService.checkScrollbar();
this.bsModalService.setScrollbar();
}
this._renderer.addClass(document.body, CLASS_NAME.OPEN);
this._renderer.setStyle(document.body, 'overflow-y', 'hidden');
}
if (this._element.nativeElement) {
this._element.nativeElement.focus();
}
}
onClickStarted(event) {
this.clickStartedInContent = event.target !== this._element.nativeElement;
}
onClickStop(event) {
const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;
if (this.config.ignoreBackdropClick ||
this.config.backdrop === 'static' ||
!clickedInBackdrop) {
this.clickStartedInContent = false;
return;
}
this.bsModalService?.setDismissReason(DISMISS_REASONS.BACKRDOP);
this.hide();
}
onPopState() {
this.bsModalService?.setDismissReason(DISMISS_REASONS.BACK);
this.hide();
}
onEsc(event) {
if (!this.isShown) {
return;
}
if (event.keyCode === 27 || event.key === 'Escape') {
event.preventDefault();
}
if (this.config.keyboard &&
this.level === this.bsModalService?.getModalsCount()) {
this.bsModalService?.setDismissReason(DISMISS_REASONS.ESC);
this.hide();
}
}
ngOnDestroy() {
if (this.isShown) {
this._hide();
}
}
hide() {
if (this.isModalHiding) {
return;
}
if (this.config.closeInterceptor) {
this.config.closeInterceptor().then(() => this._hide(), () => undefined);
return;
}
this._hide();
}
_hide() {
this.isModalHiding = true;
this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);
setTimeout(() => {
this.isShown = false;
this.bsModalService?.hide(this.config.id);
if (document &&
document.body &&
this.bsModalService?.getModalsCount() === 0) {
this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
this._renderer.setStyle(document.body, 'overflow-y', '');
}
this.bsModalService?.hide(this.config.id);
this.isModalHiding = false;
if (this._focusEl) {
this._focusEl.focus();
}
}, this.isAnimated ? TRANSITION_DURATIONS.MODAL : 0);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalContainerComponent, deps: [{ token: ModalOptions }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.1", type: ModalContainerComponent, isStandalone: true, selector: "modal-container", host: { attributes: { "role": "dialog", "tabindex": "-1" }, listeners: { "mousedown": "onClickStarted($event)", "click": "onClickStop($event)", "window:popstate": "onPopState()", "window:keydown.esc": "onEsc($event)" }, properties: { "attr.aria-modal": "true", "attr.aria-labelledby": "config.ariaLabelledBy", "attr.aria-describedby": "config.ariaDescribedby" }, classAttribute: "modal" }, providers: [BsModalService], ngImport: i0, template: `
<div [class]="'modal-dialog' + (config.class ? ' ' + config.class : '')"
role="document"
focusTrap>
<div class="modal-content">
<ng-content></ng-content>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: FocusTrapDirective, selector: "[focusTrap]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["focusTrap"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalContainerComponent, decorators: [{
type: Component,
args: [{
selector: 'modal-container',
template: `
<div [class]="'modal-dialog' + (config.class ? ' ' + config.class : '')"
role="document"
focusTrap>
<div class="modal-content">
<ng-content></ng-content>
</div>
</div>
`,
host: {
class: 'modal',
role: 'dialog',
tabindex: '-1',
'[attr.aria-modal]': 'true',
'[attr.aria-labelledby]': 'config.ariaLabelledBy',
'[attr.aria-describedby]': 'config.ariaDescribedby'
},
standalone: true,
imports: [FocusTrapDirective],
providers: [BsModalService]
}]
}], ctorParameters: () => [{ type: ModalOptions }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { onClickStarted: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], onClickStop: [{
type: HostListener,
args: ['click', ['$event']]
}], onPopState: [{
type: HostListener,
args: ['window:popstate']
}], onEsc: [{
type: HostListener,
args: ['window:keydown.esc', ['$event']]
}] } });
// todo: should we support enforce focus in?
// todo: in original bs there are was a way to prevent modal from showing
// todo: original modal had resize events
const TRANSITION_DURATION = 300;
const BACKDROP_TRANSITION_DURATION = 150;
/** Mark any code with directive to show it's content in modal */
class ModalDirective {
/** allows to set modal configuration via element property */
set config(conf) {
this._config = this.getConfig(conf);
}
get config() {
return this._config;
}
get isShown() {
return this._isShown;
}
constructor(_element, _viewContainerRef, _renderer, clf, modalDefaultOption) {
this._element = _element;
this._renderer = _renderer;
/** This event fires immediately when the `show` instance method is called. */
this.onShow = new EventEmitter();
/** This event is fired when the modal has been made visible to the user
* (will wait for CSS transitions to complete)
*/
this.onShown = new EventEmitter();
/** This event is fired immediately when
* the hide instance method has been called.
*/
this.onHide = new EventEmitter();
/** This event is fired when the modal has finished being
* hidden from the user (will wait for CSS transitions to complete).
*/
this.onHidden = new EventEmitter();
this._isShown = false;
this.isBodyOverflowing = false;
this.originalBodyPadding = 0;
this.scrollbarWidth = 0;
this.timerHideModal = 0;
this.timerRmBackDrop = 0;
this.isNested = false;
this.clickStartedInContent = false;
this._focusEl = null;
this._backdrop = clf.createLoader(_element, _viewContainerRef, _renderer);
this._config = modalDefaultOption || modalConfigDefaults;
}
onClickStarted(event) {
this.clickStartedInContent = event.target !== this._element.nativeElement;
}
onClickStop(event) {
const clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;
if (this.config.ignoreBackdropClick ||
this.config.backdrop === 'static' ||
!clickedInBackdrop) {
this.clickStartedInContent = false;
return;
}
this.dismissReason = DISMISS_REASONS.BACKRDOP;
this.hide(event);
}
// todo: consider preventing default and stopping propagation
onEsc(event) {
if (!this._isShown) {
return;
}
if (event.keyCode === 27 || event.key === 'Escape') {
event.preventDefault();
}
if (this.config.keyboard) {
this.dismissReason = DISMISS_REASONS.ESC;
this.hide();
}
}
ngOnDestroy() {
if (this._isShown) {
this._isShown = false;
this.hideModal();
this._backdrop.dispose();
}
}
ngOnInit() {
this._config = this._config || this.getConfig();
setTimeout(() => {
if (this._config.show) {
this.show();
}
}, 0);
}
/* Public methods */
/** Allows to manually toggle modal visibility */
toggle() {
return this._isShown ? this.hide() : this.show();
}
/** Allows to manually open modal */
show() {
this.dismissReason = void 0;
this.onShow.emit(this);
if (this._isShown) {
return;
}
clearTimeout(this.timerHideModal);
clearTimeout(this.timerRmBackDrop);
this._isShown = true;
this.checkScrollbar();
this.setScrollbar();
if (document && document.body) {
if (document.body.classList.contains(CLASS_NAME.OPEN)) {
this.isNested = true;
}
else {
this._renderer.addClass(document.body, CLASS_NAME.OPEN);
this._renderer.setStyle(document.body, 'overflow-y', 'hidden');
}
}
this.showBackdrop(() => {
this.showElement();
});
}
/** Check if we can close the modal */
hide(event) {
if (!this._isShown) {
return;
}
if (event) {
event.preventDefault();
}
if (this.config.closeInterceptor) {
this.config.closeInterceptor().then(() => this._hide(), () => undefined);
return;
}
this._hide();
}
/** Private methods @internal */
/**
* Manually close modal
* @internal
*/
_hide() {
this.onHide.emit(this);
window$1.clearTimeout(this.timerHideModal);
window$1.clearTimeout(this.timerRmBackDrop);
this._isShown = false;
this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);
if (this._config.animated) {
this.timerHideModal = window$1.setTimeout(() => this.hideModal(), TRANSITION_DURATION);
}
else {
this.hideModal();
}
if (this._focusEl) {
this._focusEl.focus();
}
}
getConfig(config) {
return Object.assign({}, this._config, config);
}
/**
* Show dialog
* @internal
*/
showElement() {
// todo: replace this with component loader usage
if (!this._element.nativeElement.parentNode ||
this._element.nativeElement.parentNode.nodeType !== Node.ELEMENT_NODE) {
// don't move modals dom position
if (document && document.body) {
document.body.appendChild(this._element.nativeElement);
}
}
this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'false');
this._renderer.setAttribute(this._element.nativeElement, 'aria-modal', 'true');
this._renderer.setStyle(this._element.nativeElement, 'display', 'block');
this._renderer.setProperty(this._element.nativeElement, 'scrollTop', 0);
if (this._config.animated) {
Utils.reflow(this._element.nativeElement);
}
this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);
const transitionComplete = () => {
if (this._config.focus) {
this._element.nativeElement.focus();
}
this.onShown.emit(this);
};
if (this._config.animated) {
setTimeout(transitionComplete, TRANSITION_DURATION);
}
else {
transitionComplete();
}
}
/** @internal */
hideModal() {
this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'true');
this._renderer.setStyle(this._element.nativeElement, 'display', 'none');
this.showBackdrop(() => {
if (!this.isNested) {
if (document && document.body) {
this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
this._renderer.setStyle(document.body, 'overflow-y', '');
}
this.resetScrollbar();
}
this.resetAdjustments();
this.focusOtherModal();
this.onHidden.emit(this);
});
}
// todo: original show was calling a callback when done, but we can use
// promise
/** @internal */
showBackdrop(callback) {
if (this._isShown &&
this.config.backdrop &&
(!this.backdrop || !this.backdrop.instance.isShown)) {
this.removeBackdrop();
this._backdrop
.attach(ModalBackdropComponent)
.to('body')
.show({ isAnimated: this._config.animated });
this.backdrop = this._backdrop._componentRef;
if (!callback) {
return;
}
if (!this._config.animated) {
callback();
return;
}
setTimeout(callback, BACKDROP_TRANSITION_DURATION);
}
else if (!this._isShown && this.backdrop) {
this.backdrop.instance.isShown = false;
const callbackRemove = () => {
this.removeBackdrop();
if (callback) {
callback();
}
};
if (this.backdrop.instance.isAnimated) {
this.timerRmBackDrop = window$1.setTimeout(callbackRemove, BACKDROP_TRANSITION_DURATION);
}
else {
callbackRemove();
}
}
else if (callback) {
callback();
}
}
/** @internal */
removeBackdrop() {
this._backdrop.hide();
}
/** Events tricks */
// no need for it
// protected setEscapeEvent():void {
// if (this._isShown && this._config.keyboard) {
// $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
// if (event.which === 27) {
// this.hide()
// }
// })
//
// } else if (!this._isShown) {
// $(this._element).off(Event.KEYDOWN_DISMISS)
// }
// }
// protected setResizeEvent():void {
// console.log(this.renderer.listenGlobal('', Event.RESIZE));
// if (this._isShown) {
// $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
// } else {
// $(window).off(Event.RESIZE)
// }
// }
focusOtherModal() {
if (this._element.nativeElement.parentElement == null) {
return;
}
const otherOpenedModals = this._element.nativeElement.parentElement.querySelectorAll('.in[bsModal]');
if (!otherOpenedModals.length) {
return;
}
otherOpenedModals[otherOpenedModals.length - 1].focus();
}
/** @internal */
resetAdjustments() {
this._renderer.setStyle(this._element.nativeElement, 'paddingLeft', '');
this._renderer.setStyle(this._element.nativeElement, 'paddingRight', '');
}
/** Scroll bar tricks */
/** @internal */
checkScrollbar() {
this.isBodyOverflowing = document.body.clientWidth < window$1.innerWidth;
this.scrollbarWidth = this.getScrollbarWidth();
}
setScrollbar() {
if (!document) {
return;
}
this.originalBodyPadding = parseInt(window$1
.getComputedStyle(document.body)
.getPropertyValue('padding-right') || 0, 10);
if (this.isBodyOverflowing) {
document.body.style.paddingRight = `${this.originalBodyPadding +
this.scrollbarWidth}px`;
}
}
resetScrollbar() {
document.body.style.paddingRight = `${this.originalBodyPadding}px`;
}
// thx d.walsh
getScrollbarWidth() {
const scrollDiv = this._renderer.createElement('div');
this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);
this._renderer.appendChild(document.body, scrollDiv);
const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
this._renderer.removeChild(document.body, scrollDiv);
return scrollbarWidth;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalDirective, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i1.ComponentLoaderFactory }, { token: MODAL_CONFIG_DEFAULT_OVERRIDE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.1", type: ModalDirective, isStandalone: true, selector: "[bsModal]", inputs: { config: "config", closeInterceptor: "closeInterceptor" }, outputs: { onShow: "onShow", onShown: "onShown", onHide: "onHide", onHidden: "onHidden" }, host: { listeners: { "mousedown": "onClickStarted($event)", "mouseup": "onClickStop($event)", "keydown.esc": "onEsc($event)" } }, exportAs: ["bs-modal"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalDirective, decorators: [{
type: Directive,
args: [{
selector: '[bsModal]',
exportAs: 'bs-modal',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i1.ComponentLoaderFactory }, { type: ModalOptions, decorators: [{
type: Optional
}, {
type: Inject,
args: [MODAL_CONFIG_DEFAULT_OVERRIDE]
}] }], propDecorators: { config: [{
type: Input
}], closeInterceptor: [{
type: Input
}], onShow: [{
type: Output
}], onShown: [{
type: Output
}], onHide: [{
type: Output
}], onHidden: [{
type: Output
}], onClickStarted: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], onClickStop: [{
type: HostListener,
args: ['mouseup', ['$event']]
}], onEsc: [{
type: HostListener,
args: ['keydown.esc', ['$event']]
}] } });
class ModalModule {
// @deprecated method not required anymore, will be deleted in v19.0.0
static forRoot() {
return {
ngModule: ModalModule,
providers: [BsModalService, ComponentLoaderFactory, PositioningService]
};
}
// @deprecated method not required anymore, will be deleted in v19.0.0
static forChild() {
return {
ngModule: ModalModule,
providers: [BsModalService, ComponentLoaderFactory, PositioningService]
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.1", ngImport: i0, type: ModalModule, imports: [FocusTrapModule,
ModalBackdropComponent,
ModalDirective,
ModalContainerComponent], exports: [ModalBackdropComponent, ModalDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalModule, imports: [FocusTrapModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: ModalModule, decorators: [{
type: NgModule,
args: [{
imports: [
FocusTrapModule,
ModalBackdropComponent,
ModalDirective,
ModalContainerComponent
],
exports: [ModalBackdropComponent, ModalDirective]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { BsModalRef, BsModalService, MODAL_CONFIG_DEFAULT_OVERRIDE, ModalBackdropComponent, ModalBackdropOptions, ModalContainerComponent, ModalDirective, ModalModule, ModalOptions };
//# sourceMappingURL=ngx-bootstrap-modal.mjs.map