UNPKG

@ng-bootstrap/ng-bootstrap

Version:
808 lines (797 loc) 34.2 kB
import * as i0 from '@angular/core'; import { inject, Injectable, ElementRef, NgZone, Injector, ChangeDetectorRef, afterNextRender, Input, ViewEncapsulation, Component, DOCUMENT, EventEmitter, Output, ViewChild, ApplicationRef, EnvironmentInjector, createComponent, TemplateRef, NgModule } from '@angular/core'; import { NgbConfig } from '@ng-bootstrap/ng-bootstrap/config'; import { Subject, of, zip, fromEvent } from 'rxjs'; import { ngbRunTransition, reflow, isDefined, isPromise, isString, getFocusableBoundaryElements, ScrollBar, ngbFocusTrap, ContentRef } from './_ngb-ngbootstrap-utilities.mjs'; import { takeUntil, filter, tap, switchMap, take } from 'rxjs/operators'; /** * A configuration service for the [`NgbModal`](#/components/modal/api#NgbModal) service. * * You can inject this service, typically in your root component, and customize the values of its properties in * order to provide default values for all modals used in the application. * * @since 3.1.0 */ class NgbModalConfig { constructor() { this._ngbConfig = inject(NgbConfig); this.backdrop = true; this.fullscreen = false; this.keyboard = true; this.role = 'dialog'; } get animation() { return this._animation ?? this._ngbConfig.animation; } set animation(animation) { this._animation = animation; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalConfig, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalConfig, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); const BACKDROP_ATTRIBUTES = ['animation', 'backdropClass']; class NgbModalBackdrop { constructor() { this._nativeElement = inject(ElementRef).nativeElement; this._zone = inject(NgZone); this._injector = inject(Injector); this._cdRef = inject(ChangeDetectorRef); } ngOnInit() { afterNextRender({ mixedReadWrite: () => ngbRunTransition(this._zone, this._nativeElement, (element, animation) => { if (animation) { reflow(element); } element.classList.add('show'); }, { animation: this.animation, runningTransition: 'continue' }), }, { injector: this._injector }); } hide() { return ngbRunTransition(this._zone, this._nativeElement, ({ classList }) => classList.remove('show'), { animation: this.animation, runningTransition: 'stop', }); } updateOptions(options) { BACKDROP_ATTRIBUTES.forEach((optionName) => { if (isDefined(options[optionName])) { this[optionName] = options[optionName]; } }); this._cdRef.markForCheck(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalBackdrop, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.4", type: NgbModalBackdrop, isStandalone: true, selector: "ngb-modal-backdrop", inputs: { animation: "animation", backdropClass: "backdropClass" }, host: { properties: { "class": "\"modal-backdrop\" + (backdropClass ? \" \" + backdropClass : \"\")", "class.show": "!animation", "class.fade": "animation" }, styleAttribute: "z-index: 1055" }, ngImport: i0, template: '', isInline: true, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalBackdrop, decorators: [{ type: Component, args: [{ selector: 'ngb-modal-backdrop', encapsulation: ViewEncapsulation.None, template: '', host: { '[class]': '"modal-backdrop" + (backdropClass ? " " + backdropClass : "")', '[class.show]': '!animation', '[class.fade]': 'animation', style: 'z-index: 1055', }, }] }], propDecorators: { animation: [{ type: Input }], backdropClass: [{ type: Input }] } }); /** * A reference to the currently opened (active) modal. * * Instances of this class can be injected into your component passed as modal content. * So you can `.update()`, `.close()` or `.dismiss()` the modal window from your component. */ class NgbActiveModal { /** * Updates options of an opened modal. * * @since 14.2.0 */ update(options) { } /** * Closes the modal with an optional `result` value. * * The `NgbModalRef.result` promise will be resolved with the provided value. */ close(result) { } /** * Dismisses the modal with an optional `reason` value. * * The `NgbModalRef.result` promise will be rejected with the provided value. */ dismiss(reason) { } } /** * A reference to the newly opened modal returned by the `NgbModal.open()` method. */ class NgbModalRef { /** * Updates options of an opened modal. * * @since 14.2.0 */ update(options) { this._windowCmptRef.instance.updateOptions(options); if (this._backdropCmptRef && this._backdropCmptRef.instance) { this._backdropCmptRef.instance.updateOptions(options); } } /** * The instance of a component used for the modal content. * * When a `TemplateRef` is used as the content or when the modal is closed, will return `undefined`. */ get componentInstance() { if (this._contentRef && this._contentRef.componentRef) { return this._contentRef.componentRef.instance; } } /** * The observable that emits when the modal is closed via the `.close()` method. * * It will emit the result passed to the `.close()` method. * * @since 8.0.0 */ get closed() { return this._closed.asObservable().pipe(takeUntil(this._hidden)); } /** * The observable that emits when the modal is dismissed via the `.dismiss()` method. * * It will emit the reason passed to the `.dismissed()` method by the user, or one of the internal * reasons like backdrop click or ESC key press. * * @since 8.0.0 */ get dismissed() { return this._dismissed.asObservable().pipe(takeUntil(this._hidden)); } /** * The observable that emits when both modal window and backdrop are closed and animations were finished. * At this point modal and backdrop elements will be removed from the DOM tree. * * This observable will be completed after emitting. * * @since 8.0.0 */ get hidden() { return this._hidden.asObservable(); } /** * The observable that emits when modal is fully visible and animation was finished. * Modal DOM element is always available synchronously after calling 'modal.open()' service. * * This observable will be completed after emitting. * It will not emit, if modal is closed before open animation is finished. * * @since 8.0.0 */ get shown() { return this._windowCmptRef.instance.shown.asObservable(); } constructor(_windowCmptRef, _contentRef, _backdropCmptRef, _beforeDismiss) { this._windowCmptRef = _windowCmptRef; this._contentRef = _contentRef; this._backdropCmptRef = _backdropCmptRef; this._beforeDismiss = _beforeDismiss; this._closed = new Subject(); this._dismissed = new Subject(); this._hidden = new Subject(); _windowCmptRef.instance.dismissEvent.subscribe((reason) => { this.dismiss(reason); }); this.result = new Promise((resolve, reject) => { this._resolve = resolve; this._reject = reject; }); this.result.then(null, () => { }); } /** * Closes the modal with an optional `result` value. * * The `NgbMobalRef.result` promise will be resolved with the provided value. */ close(result) { if (this._windowCmptRef) { this._closed.next(result); this._resolve(result); this._removeModalElements(); } } _dismiss(reason) { this._dismissed.next(reason); this._reject(reason); this._removeModalElements(); } /** * Dismisses the modal with an optional `reason` value. * * The `NgbModalRef.result` promise will be rejected with the provided value. */ dismiss(reason) { if (this._windowCmptRef) { if (!this._beforeDismiss) { this._dismiss(reason); } else { const dismiss = this._beforeDismiss(); if (isPromise(dismiss)) { dismiss.then((result) => { if (result !== false) { this._dismiss(reason); } }, () => { }); } else if (dismiss !== false) { this._dismiss(reason); } } } } _removeModalElements() { const windowTransition$ = this._windowCmptRef.instance.hide(); const backdropTransition$ = this._backdropCmptRef ? this._backdropCmptRef.instance.hide() : of(undefined); // hiding window windowTransition$.subscribe(() => { const { nativeElement } = this._windowCmptRef.location; nativeElement.parentNode.removeChild(nativeElement); this._windowCmptRef.destroy(); this._contentRef?.viewRef?.destroy(); this._windowCmptRef = null; this._contentRef = null; }); // hiding backdrop backdropTransition$.subscribe(() => { if (this._backdropCmptRef) { const { nativeElement } = this._backdropCmptRef.location; nativeElement.parentNode.removeChild(nativeElement); this._backdropCmptRef.destroy(); this._backdropCmptRef = null; } }); // all done zip(windowTransition$, backdropTransition$).subscribe(() => { this._hidden.next(); this._hidden.complete(); }); } } var ModalDismissReasons; (function (ModalDismissReasons) { ModalDismissReasons[ModalDismissReasons["BACKDROP_CLICK"] = 0] = "BACKDROP_CLICK"; ModalDismissReasons[ModalDismissReasons["ESC"] = 1] = "ESC"; })(ModalDismissReasons || (ModalDismissReasons = {})); const WINDOW_ATTRIBUTES = [ 'animation', 'ariaLabelledBy', 'ariaDescribedBy', 'backdrop', 'centered', 'fullscreen', 'keyboard', 'role', 'scrollable', 'size', 'windowClass', 'modalDialogClass', ]; class NgbModalWindow { constructor() { this._document = inject(DOCUMENT); this._elRef = inject((ElementRef)); this._zone = inject(NgZone); this._injector = inject(Injector); this._cdRef = inject(ChangeDetectorRef); this._closed$ = new Subject(); this._elWithFocus = null; // element that is focused prior to modal opening this.backdrop = true; this.keyboard = true; this.role = 'dialog'; this.dismissEvent = new EventEmitter(); this.shown = new Subject(); this.hidden = new Subject(); } get fullscreenClass() { return this.fullscreen === true ? ' modal-fullscreen' : isString(this.fullscreen) ? ` modal-fullscreen-${this.fullscreen}-down` : ''; } dismiss(reason) { this.dismissEvent.emit(reason); } ngOnInit() { this._elWithFocus = this._document.activeElement; afterNextRender({ mixedReadWrite: () => this._show() }, { injector: this._injector }); } ngOnDestroy() { this._disableEventHandling(); } hide() { const { nativeElement } = this._elRef; const context = { animation: this.animation, runningTransition: 'stop' }; const windowTransition$ = ngbRunTransition(this._zone, nativeElement, () => nativeElement.classList.remove('show'), context); const dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => { }, context); const transitions$ = zip(windowTransition$, dialogTransition$); transitions$.subscribe(() => { this.hidden.next(); this.hidden.complete(); }); this._disableEventHandling(); this._restoreFocus(); return transitions$; } updateOptions(options) { WINDOW_ATTRIBUTES.forEach((optionName) => { if (isDefined(options[optionName])) { this[optionName] = options[optionName]; } }); this._cdRef.markForCheck(); } _show() { const context = { animation: this.animation, runningTransition: 'continue' }; const windowTransition$ = ngbRunTransition(this._zone, this._elRef.nativeElement, (element, animation) => { if (animation) { reflow(element); } element.classList.add('show'); }, context); const dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => { }, context); zip(windowTransition$, dialogTransition$).subscribe(() => { this.shown.next(); this.shown.complete(); }); this._enableEventHandling(); this._setFocus(); } _enableEventHandling() { const { nativeElement } = this._elRef; this._zone.runOutsideAngular(() => { fromEvent(nativeElement, 'keydown') .pipe(takeUntil(this._closed$), filter((e) => e.key === 'Escape')) .subscribe((event) => { if (this.keyboard) { requestAnimationFrame(() => { if (!event.defaultPrevented) { this._zone.run(() => this.dismiss(ModalDismissReasons.ESC)); } }); } else if (this.backdrop === 'static') { this._bumpBackdrop(); } }); // We're listening to 'mousedown' and 'mouseup' to prevent modal from closing when pressing the mouse // inside the modal dialog and releasing it outside let preventClose = false; fromEvent(this._dialogEl.nativeElement, 'mousedown') .pipe(takeUntil(this._closed$), tap(() => (preventClose = false)), switchMap(() => fromEvent(nativeElement, 'mouseup').pipe(takeUntil(this._closed$), take(1))), filter(({ target }) => nativeElement === target)) .subscribe(() => { preventClose = true; }); // We're listening to 'click' to dismiss modal on modal window click, except when: // 1. clicking on modal dialog itself // 2. closing was prevented by mousedown/up handlers // 3. clicking on scrollbar when the viewport is too small and modal doesn't fit (click is not triggered at all) fromEvent(nativeElement, 'click') .pipe(takeUntil(this._closed$)) .subscribe(({ target }) => { if (nativeElement === target) { if (this.backdrop === 'static') { this._bumpBackdrop(); } else if (this.backdrop === true && !preventClose) { this._zone.run(() => this.dismiss(ModalDismissReasons.BACKDROP_CLICK)); } } preventClose = false; }); }); } _disableEventHandling() { this._closed$.next(); } _setFocus() { const { nativeElement } = this._elRef; if (!nativeElement.contains(document.activeElement)) { const autoFocusable = nativeElement.querySelector(`[ngbAutofocus]`); const firstFocusable = getFocusableBoundaryElements(nativeElement)[0]; const elementToFocus = autoFocusable || firstFocusable || nativeElement; elementToFocus.focus(); } } _restoreFocus() { const body = this._document.body; const elWithFocus = this._elWithFocus; let elementToFocus; if (elWithFocus && elWithFocus['focus'] && body.contains(elWithFocus)) { elementToFocus = elWithFocus; } else { elementToFocus = body; } this._zone.runOutsideAngular(() => { setTimeout(() => elementToFocus.focus()); this._elWithFocus = null; }); } _bumpBackdrop() { if (this.backdrop === 'static') { ngbRunTransition(this._zone, this._elRef.nativeElement, ({ classList }) => { classList.add('modal-static'); return () => classList.remove('modal-static'); }, { animation: this.animation, runningTransition: 'continue' }); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalWindow, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.4", type: NgbModalWindow, isStandalone: true, selector: "ngb-modal-window", inputs: { animation: "animation", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", backdrop: "backdrop", centered: "centered", fullscreen: "fullscreen", keyboard: "keyboard", role: "role", scrollable: "scrollable", size: "size", windowClass: "windowClass", modalDialogClass: "modalDialogClass" }, outputs: { dismissEvent: "dismiss" }, host: { attributes: { "tabindex": "-1" }, properties: { "class": "\"modal d-block\" + (windowClass ? \" \" + windowClass : \"\")", "class.fade": "animation", "attr.aria-modal": "true", "attr.aria-labelledby": "ariaLabelledBy", "attr.aria-describedby": "ariaDescribedBy", "attr.role": "role" } }, viewQueries: [{ propertyName: "_dialogEl", first: true, predicate: ["dialog"], descendants: true, static: true }], ngImport: i0, template: ` <div #dialog [class]=" 'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') + fullscreenClass + (scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '') " role="document" > <div class="modal-content"><ng-content /></div> </div> `, isInline: true, styles: ["ngb-modal-window .component-host-scrollable{display:flex;flex-direction:column;overflow:hidden}\n"], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalWindow, decorators: [{ type: Component, args: [{ selector: 'ngb-modal-window', host: { '[class]': '"modal d-block" + (windowClass ? " " + windowClass : "")', '[class.fade]': 'animation', tabindex: '-1', '[attr.aria-modal]': 'true', '[attr.aria-labelledby]': 'ariaLabelledBy', '[attr.aria-describedby]': 'ariaDescribedBy', '[attr.role]': 'role', }, template: ` <div #dialog [class]=" 'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') + fullscreenClass + (scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '') " role="document" > <div class="modal-content"><ng-content /></div> </div> `, encapsulation: ViewEncapsulation.None, styles: ["ngb-modal-window .component-host-scrollable{display:flex;flex-direction:column;overflow:hidden}\n"] }] }], propDecorators: { _dialogEl: [{ type: ViewChild, args: ['dialog', { static: true }] }], animation: [{ type: Input }], ariaLabelledBy: [{ type: Input }], ariaDescribedBy: [{ type: Input }], backdrop: [{ type: Input }], centered: [{ type: Input }], fullscreen: [{ type: Input }], keyboard: [{ type: Input }], role: [{ type: Input }], scrollable: [{ type: Input }], size: [{ type: Input }], windowClass: [{ type: Input }], modalDialogClass: [{ type: Input }], dismissEvent: [{ type: Output, args: ['dismiss'] }] } }); class NgbModalStack { constructor() { this._applicationRef = inject(ApplicationRef); this._injector = inject(Injector); this._environmentInjector = inject(EnvironmentInjector); this._document = inject(DOCUMENT); this._scrollBar = inject(ScrollBar); this._activeWindowCmptHasChanged = new Subject(); this._ariaHiddenValues = new Map(); this._scrollBarRestoreFn = null; this._modalRefs = []; this._windowCmpts = []; this._activeInstances = new EventEmitter(); const ngZone = inject(NgZone); // Trap focus on active WindowCmpt this._activeWindowCmptHasChanged.subscribe(() => { if (this._windowCmpts.length) { const activeWindowCmpt = this._windowCmpts[this._windowCmpts.length - 1]; ngbFocusTrap(ngZone, activeWindowCmpt.location.nativeElement, this._activeWindowCmptHasChanged); this._revertAriaHidden(); this._setAriaHidden(activeWindowCmpt.location.nativeElement); } }); } _restoreScrollBar() { const scrollBarRestoreFn = this._scrollBarRestoreFn; if (scrollBarRestoreFn) { this._scrollBarRestoreFn = null; scrollBarRestoreFn(); } } _hideScrollBar() { if (!this._scrollBarRestoreFn) { this._scrollBarRestoreFn = this._scrollBar.hide(); } } open(contentInjector, content, options) { const containerEl = options.container instanceof HTMLElement ? options.container : isDefined(options.container) ? this._document.querySelector(options.container) : this._document.body; if (!containerEl) { throw new Error(`The specified modal container "${options.container || 'body'}" was not found in the DOM.`); } this._hideScrollBar(); const activeModal = new NgbActiveModal(); contentInjector = options.injector || contentInjector; const environmentInjector = contentInjector.get(EnvironmentInjector, null) || this._environmentInjector; const contentRef = this._getContentRef(contentInjector, environmentInjector, content, activeModal, options); let backdropCmptRef = options.backdrop !== false ? this._attachBackdrop(containerEl) : undefined; let windowCmptRef = this._attachWindowComponent(containerEl, contentRef.nodes); let ngbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss); this._registerModalRef(ngbModalRef); this._registerWindowCmpt(windowCmptRef); // We have to cleanup DOM after the last modal when BOTH 'hidden' was emitted and 'result' promise was resolved: // - with animations OFF, 'hidden' emits synchronously, then 'result' is resolved asynchronously // - with animations ON, 'result' is resolved asynchronously, then 'hidden' emits asynchronously ngbModalRef.hidden.pipe(take(1)).subscribe(() => Promise.resolve(true).then(() => { if (!this._modalRefs.length) { this._document.body.classList.remove('modal-open'); this._restoreScrollBar(); this._revertAriaHidden(); } })); activeModal.close = (result) => { ngbModalRef.close(result); }; activeModal.dismiss = (reason) => { ngbModalRef.dismiss(reason); }; activeModal.update = (options) => { ngbModalRef.update(options); }; ngbModalRef.update(options); if (this._modalRefs.length === 1) { this._document.body.classList.add('modal-open'); } if (backdropCmptRef && backdropCmptRef.instance) { backdropCmptRef.changeDetectorRef.detectChanges(); } windowCmptRef.changeDetectorRef.detectChanges(); return ngbModalRef; } get activeInstances() { return this._activeInstances; } dismissAll(reason) { this._modalRefs.forEach((ngbModalRef) => ngbModalRef.dismiss(reason)); } hasOpenModals() { return this._modalRefs.length > 0; } _attachBackdrop(containerEl) { let backdropCmptRef = createComponent(NgbModalBackdrop, { environmentInjector: this._applicationRef.injector, elementInjector: this._injector, }); this._applicationRef.attachView(backdropCmptRef.hostView); containerEl.appendChild(backdropCmptRef.location.nativeElement); return backdropCmptRef; } _attachWindowComponent(containerEl, projectableNodes) { let windowCmptRef = createComponent(NgbModalWindow, { environmentInjector: this._applicationRef.injector, elementInjector: this._injector, projectableNodes, }); this._applicationRef.attachView(windowCmptRef.hostView); containerEl.appendChild(windowCmptRef.location.nativeElement); return windowCmptRef; } _getContentRef(contentInjector, environmentInjector, content, activeModal, options) { if (!content) { return new ContentRef([]); } else if (content instanceof TemplateRef) { return this._createFromTemplateRef(content, activeModal); } else if (isString(content)) { return this._createFromString(content); } else { return this._createFromComponent(contentInjector, environmentInjector, content, activeModal, options); } } _createFromTemplateRef(templateRef, activeModal) { const context = { $implicit: activeModal, close(result) { activeModal.close(result); }, dismiss(reason) { activeModal.dismiss(reason); }, }; const viewRef = templateRef.createEmbeddedView(context); this._applicationRef.attachView(viewRef); return new ContentRef([viewRef.rootNodes], viewRef); } _createFromString(content) { const component = this._document.createTextNode(`${content}`); return new ContentRef([[component]]); } _createFromComponent(contentInjector, environmentInjector, componentType, context, options) { const elementInjector = Injector.create({ providers: [{ provide: NgbActiveModal, useValue: context }], parent: contentInjector, }); const componentRef = createComponent(componentType, { environmentInjector, elementInjector, }); const componentNativeEl = componentRef.location.nativeElement; if (options.scrollable) { componentNativeEl.classList.add('component-host-scrollable'); } this._applicationRef.attachView(componentRef.hostView); // FIXME: we should here get rid of the component nativeElement // and use `[Array.from(componentNativeEl.childNodes)]` instead and remove the above CSS class. return new ContentRef([[componentNativeEl]], componentRef.hostView, componentRef); } _setAriaHidden(element) { const parent = element.parentElement; if (parent && element !== this._document.body) { Array.from(parent.children).forEach((sibling) => { if (sibling !== element && sibling.nodeName !== 'SCRIPT') { this._ariaHiddenValues.set(sibling, sibling.getAttribute('aria-hidden')); sibling.setAttribute('aria-hidden', 'true'); } }); this._setAriaHidden(parent); } } _revertAriaHidden() { this._ariaHiddenValues.forEach((value, element) => { if (value) { element.setAttribute('aria-hidden', value); } else { element.removeAttribute('aria-hidden'); } }); this._ariaHiddenValues.clear(); } _registerModalRef(ngbModalRef) { const unregisterModalRef = () => { const index = this._modalRefs.indexOf(ngbModalRef); if (index > -1) { this._modalRefs.splice(index, 1); this._activeInstances.emit(this._modalRefs); } }; this._modalRefs.push(ngbModalRef); this._activeInstances.emit(this._modalRefs); ngbModalRef.result.then(unregisterModalRef, unregisterModalRef); } _registerWindowCmpt(ngbWindowCmpt) { this._windowCmpts.push(ngbWindowCmpt); this._activeWindowCmptHasChanged.next(); ngbWindowCmpt.onDestroy(() => { const index = this._windowCmpts.indexOf(ngbWindowCmpt); if (index > -1) { this._windowCmpts.splice(index, 1); this._activeWindowCmptHasChanged.next(); } }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalStack, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalStack, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); /** * A service for opening modal windows. * * Creating a modal is straightforward: create a component or a template and pass it as an argument to * the `.open()` method. */ class NgbModal { constructor() { this._injector = inject(Injector); this._modalStack = inject(NgbModalStack); this._config = inject(NgbModalConfig); } /** * Opens a new modal window with the specified content and supplied options. * * Content can be provided as a `TemplateRef` or a component type. If you pass a component type as content, * then instances of those components can be injected with an instance of the `NgbActiveModal` class. You can then * use `NgbActiveModal` methods to close / dismiss modals from "inside" of your component. * * Also see the [`NgbModalOptions`](#/components/modal/api#NgbModalOptions) for the list of supported options. */ open(content, options = {}) { const combinedOptions = { ...this._config, animation: this._config.animation, ...options }; return this._modalStack.open(this._injector, content, combinedOptions); } /** * Returns an observable that holds the active modal instances. */ get activeInstances() { return this._modalStack.activeInstances; } /** * Dismisses all currently displayed modal windows with the supplied reason. * * @since 3.1.0 */ dismissAll(reason) { this._modalStack.dismissAll(reason); } /** * Indicates if there are currently any open modal windows in the application. * * @since 3.3.0 */ hasOpenModals() { return this._modalStack.hasOpenModals(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModal, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModal, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModal, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class NgbModalModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.4", ngImport: i0, type: NgbModalModule }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalModule, providers: [NgbModal] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.4", ngImport: i0, type: NgbModalModule, decorators: [{ type: NgModule, args: [{ providers: [NgbModal] }] }] }); /** * Generated bundle index. Do not edit. */ export { ModalDismissReasons, NgbActiveModal, NgbModal, NgbModalConfig, NgbModalModule, NgbModalRef }; //# sourceMappingURL=ng-bootstrap-ng-bootstrap-modal.mjs.map