UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

1 lines 98.2 kB
{"version":3,"file":"ng-zorro-antd-modal.mjs","sources":["../../components/modal/modal-types.ts","../../components/modal/modal-config.ts","../../components/modal/modal-animations.ts","../../components/modal/utils.ts","../../components/modal/modal-container.directive.ts","../../components/modal/modal-close.component.ts","../../components/modal/modal-confirm-container.component.ts","../../components/modal/modal-title.component.ts","../../components/modal/modal-footer.component.ts","../../components/modal/modal-container.component.ts","../../components/modal/modal-ref.ts","../../components/modal/modal.service.ts","../../components/modal/modal-content.directive.ts","../../components/modal/modal-footer.directive.ts","../../components/modal/modal-title.directive.ts","../../components/modal/modal.component.ts","../../components/modal/modal.module.ts","../../components/modal/modal-legacy-api.ts","../../components/modal/public-api.ts","../../components/modal/ng-zorro-antd-modal.ts"],"sourcesContent":["/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { Direction } from '@angular/cdk/bidi';\nimport { EventEmitter, TemplateRef, Type, ViewContainerRef } from '@angular/core';\n\nimport { NzButtonShape, NzButtonSize, NzButtonType } from 'ng-zorro-antd/button';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\n\nexport type OnClickCallback<T> = (instance: T) => (false | void | {}) | Promise<false | void | {}>;\n\nexport type ModalTypes = 'default' | 'confirm'; // Different modal styles we have supported\n\nexport type ConfirmType = 'confirm' | 'info' | 'success' | 'error' | 'warning'; // Subtypes of Confirm Modal\n\nexport interface StyleObjectLike {\n [key: string]: string;\n}\n\nconst noopFun = () => void 0;\n\nexport class ModalOptions<T = NzSafeAny, R = NzSafeAny> {\n nzCentered?: boolean = false;\n nzClosable?: boolean = true;\n nzOkLoading?: boolean = false;\n nzOkDisabled?: boolean = false;\n nzCancelDisabled?: boolean = false;\n nzCancelLoading?: boolean = false;\n nzNoAnimation?: boolean = false;\n nzAutofocus?: 'ok' | 'cancel' | 'auto' | null = 'auto';\n nzMask?: boolean;\n nzMaskClosable?: boolean;\n nzKeyboard?: boolean = true;\n nzZIndex?: number = 1000;\n nzWidth?: number | string = 520;\n nzCloseIcon?: string | TemplateRef<void> = 'close';\n nzOkType?: NzButtonType = 'primary';\n nzOkDanger?: boolean = false;\n nzModalType?: ModalTypes = 'default';\n nzOnCancel?: EventEmitter<T> | OnClickCallback<T> = noopFun;\n nzOnOk?: EventEmitter<T> | OnClickCallback<T> = noopFun;\n nzComponentParams?: Partial<T>;\n nzMaskStyle?: StyleObjectLike;\n nzBodyStyle?: StyleObjectLike;\n nzWrapClassName?: string;\n nzClassName?: string;\n nzStyle?: object;\n nzTitle?: string | TemplateRef<{}>;\n nzFooter?: string | TemplateRef<{}> | Array<ModalButtonOptions<T>> | null; // Default Modal ONLY\n nzCancelText?: string | null;\n nzOkText?: string | null;\n nzContent?: string | TemplateRef<NzSafeAny> | Type<T>;\n nzCloseOnNavigation?: boolean;\n nzViewContainerRef?: ViewContainerRef;\n // Template use only\n nzAfterOpen?: EventEmitter<void>;\n nzAfterClose?: EventEmitter<R>;\n\n // Confirm\n nzIconType?: string = 'question-circle';\n nzDirection?: Direction;\n}\n\nexport interface ModalButtonOptions<T = NzSafeAny> {\n label: string;\n type?: NzButtonType;\n danger?: boolean;\n shape?: NzButtonShape;\n ghost?: boolean;\n size?: NzButtonSize;\n autoLoading?: boolean; // Default: true, indicate whether show loading automatically while onClick returned a Promise\n\n // [NOTE] \"componentInstance\" will refer to the component's instance when using Component\n show?: boolean | ((this: ModalButtonOptions<T>, contentComponentInstance?: T) => boolean);\n loading?: boolean | ((this: ModalButtonOptions<T>, contentComponentInstance?: T) => boolean); // This prop CAN'T use with autoLoading=true\n disabled?: boolean | ((this: ModalButtonOptions<T>, contentComponentInstance?: T) => boolean);\n onClick?(this: ModalButtonOptions<T>, contentComponentInstance?: T): NzSafeAny | Promise<NzSafeAny>;\n [key: string]: NzSafeAny;\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { NzConfigKey } from 'ng-zorro-antd/core/config';\n\nexport const ZOOM_CLASS_NAME_MAP = {\n enter: 'ant-zoom-enter',\n enterActive: 'ant-zoom-enter-active',\n leave: 'ant-zoom-leave',\n leaveActive: 'ant-zoom-leave-active'\n};\n\nexport const FADE_CLASS_NAME_MAP = {\n enter: 'ant-fade-enter',\n enterActive: 'ant-fade-enter-active',\n leave: 'ant-fade-leave',\n leaveActive: 'ant-fade-leave-active'\n};\n\nexport const MODAL_MASK_CLASS_NAME = 'ant-modal-mask';\nexport const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'modal';\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { animate, AnimationTriggerMetadata, state, style, transition, trigger } from '@angular/animations';\n\nexport const nzModalAnimations: {\n readonly modalContainer: AnimationTriggerMetadata;\n} = {\n modalContainer: trigger('modalContainer', [\n state('void, exit', style({})),\n state('enter', style({})),\n transition('* => enter', animate('.24s', style({}))),\n transition('* => void, * => exit', animate('.2s', style({})))\n ])\n};\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { ModalOptions } from './modal-types';\n\nexport function applyConfigDefaults(config: ModalOptions, defaultOptions: ModalOptions): ModalOptions {\n return { ...defaultOptions, ...config };\n}\n\nexport function getValueWithConfig<T>(\n userValue: T | undefined,\n configValue: T | undefined,\n defaultValue: T\n): T | undefined {\n return typeof userValue === 'undefined'\n ? typeof configValue === 'undefined'\n ? defaultValue\n : configValue\n : userValue;\n}\n\n/**\n * Assign the params into the content component instance.\n *\n * @deprecated Should use dependency injection to get the params for user\n * @breaking-change 14.0.0\n */\nexport function setContentInstanceParams<T>(instance: T, params: Partial<T> | undefined): void {\n Object.assign(instance, params);\n}\n\nexport function getConfigFromComponent<T extends ModalOptions>(component: T): ModalOptions {\n const {\n nzCentered,\n nzMask,\n nzMaskClosable,\n nzClosable,\n nzOkLoading,\n nzOkDisabled,\n nzCancelDisabled,\n nzCancelLoading,\n nzKeyboard,\n nzNoAnimation,\n nzContent,\n nzComponentParams,\n nzFooter,\n nzZIndex,\n nzWidth,\n nzWrapClassName,\n nzClassName,\n nzStyle,\n nzTitle,\n nzCloseIcon,\n nzMaskStyle,\n nzBodyStyle,\n nzOkText,\n nzCancelText,\n nzOkType,\n nzOkDanger,\n nzIconType,\n nzModalType,\n nzOnOk,\n nzOnCancel,\n nzAfterOpen,\n nzAfterClose,\n nzCloseOnNavigation,\n nzAutofocus\n } = component;\n return {\n nzCentered,\n nzMask,\n nzMaskClosable,\n nzClosable,\n nzOkLoading,\n nzOkDisabled,\n nzCancelDisabled,\n nzCancelLoading,\n nzKeyboard,\n nzNoAnimation,\n nzContent,\n nzComponentParams,\n nzFooter,\n nzZIndex,\n nzWidth,\n nzWrapClassName,\n nzClassName,\n nzStyle,\n nzTitle,\n nzCloseIcon,\n nzMaskStyle,\n nzBodyStyle,\n nzOkText,\n nzCancelText,\n nzOkType,\n nzOkDanger,\n nzIconType,\n nzModalType,\n nzOnOk,\n nzOnCancel,\n nzAfterOpen,\n nzAfterClose,\n nzCloseOnNavigation,\n nzAutofocus\n };\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { AnimationEvent } from '@angular/animations';\nimport { FocusTrap, FocusTrapFactory } from '@angular/cdk/a11y';\nimport { Direction } from '@angular/cdk/bidi';\nimport { OverlayRef } from '@angular/cdk/overlay';\nimport { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport {\n ChangeDetectorRef,\n ComponentRef,\n Directive,\n ElementRef,\n EmbeddedViewRef,\n EventEmitter,\n NgZone,\n OnDestroy,\n Renderer2\n} from '@angular/core';\nimport { fromEvent, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport { NzConfigService } from 'ng-zorro-antd/core/config';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { getElementOffset, isNotNil } from 'ng-zorro-antd/core/util';\n\nimport { FADE_CLASS_NAME_MAP, MODAL_MASK_CLASS_NAME, NZ_CONFIG_MODULE_NAME, ZOOM_CLASS_NAME_MAP } from './modal-config';\nimport { NzModalRef } from './modal-ref';\nimport { ModalOptions } from './modal-types';\nimport { getValueWithConfig } from './utils';\n\nexport function throwNzModalContentAlreadyAttachedError(): never {\n throw Error('Attempting to attach modal content after content is already attached');\n}\n\n@Directive()\nexport class BaseModalContainerComponent extends BasePortalOutlet implements OnDestroy {\n portalOutlet!: CdkPortalOutlet;\n modalElementRef!: ElementRef<HTMLDivElement>;\n\n animationStateChanged = new EventEmitter<AnimationEvent>();\n containerClick = new EventEmitter<void>();\n cancelTriggered = new EventEmitter<void>();\n okTriggered = new EventEmitter<void>();\n\n state: 'void' | 'enter' | 'exit' = 'enter';\n document: Document;\n modalRef!: NzModalRef;\n isStringContent: boolean = false;\n dir: Direction = 'ltr';\n private elementFocusedBeforeModalWasOpened: HTMLElement | null = null;\n private focusTrap!: FocusTrap;\n private mouseDown = false;\n private oldMaskStyle: { [key: string]: string } | null = null;\n protected destroy$ = new Subject();\n\n get showMask(): boolean {\n const defaultConfig: NzSafeAny = this.nzConfigService.getConfigForComponent(NZ_CONFIG_MODULE_NAME) || {};\n\n return !!getValueWithConfig<boolean>(this.config.nzMask, defaultConfig.nzMask, true);\n }\n\n get maskClosable(): boolean {\n const defaultConfig: NzSafeAny = this.nzConfigService.getConfigForComponent(NZ_CONFIG_MODULE_NAME) || {};\n\n return !!getValueWithConfig<boolean>(this.config.nzMaskClosable, defaultConfig.nzMaskClosable, true);\n }\n\n constructor(\n protected ngZone: NgZone,\n protected host: ElementRef<HTMLElement>,\n protected focusTrapFactory: FocusTrapFactory,\n public cdr: ChangeDetectorRef,\n protected render: Renderer2,\n protected overlayRef: OverlayRef,\n protected nzConfigService: NzConfigService,\n public config: ModalOptions,\n document?: NzSafeAny,\n protected animationType?: string\n ) {\n super();\n this.document = document;\n this.dir = overlayRef.getDirection();\n this.isStringContent = typeof config.nzContent === 'string';\n this.nzConfigService\n .getConfigChangeEventForComponent(NZ_CONFIG_MODULE_NAME)\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n this.updateMaskClassname();\n });\n }\n\n onContainerClick(e: MouseEvent): void {\n if (e.target === e.currentTarget && !this.mouseDown && this.showMask && this.maskClosable) {\n this.containerClick.emit();\n }\n }\n\n onCloseClick(): void {\n this.cancelTriggered.emit();\n }\n\n onOkClick(): void {\n this.okTriggered.emit();\n }\n\n attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {\n if (this.portalOutlet.hasAttached()) {\n throwNzModalContentAlreadyAttachedError();\n }\n this.savePreviouslyFocusedElement();\n this.setZIndexForBackdrop();\n return this.portalOutlet.attachComponentPortal(portal);\n }\n\n attachTemplatePortal<C>(portal: TemplatePortal<C>): EmbeddedViewRef<C> {\n if (this.portalOutlet.hasAttached()) {\n throwNzModalContentAlreadyAttachedError();\n }\n this.savePreviouslyFocusedElement();\n this.setZIndexForBackdrop();\n return this.portalOutlet.attachTemplatePortal(portal);\n }\n\n attachStringContent(): void {\n this.savePreviouslyFocusedElement();\n this.setZIndexForBackdrop();\n }\n\n getNativeElement(): HTMLElement {\n return this.host.nativeElement;\n }\n\n private animationDisabled(): boolean {\n return this.config.nzNoAnimation || this.animationType === 'NoopAnimations';\n }\n\n private setModalTransformOrigin(): void {\n const modalElement = this.modalElementRef.nativeElement;\n if (this.elementFocusedBeforeModalWasOpened as HTMLElement) {\n const previouslyDOMRect = this.elementFocusedBeforeModalWasOpened!.getBoundingClientRect();\n const lastPosition = getElementOffset(this.elementFocusedBeforeModalWasOpened!);\n const x = lastPosition.left + previouslyDOMRect.width / 2;\n const y = lastPosition.top + previouslyDOMRect.height / 2;\n const transformOrigin = `${x - modalElement.offsetLeft}px ${y - modalElement.offsetTop}px 0px`;\n this.render.setStyle(modalElement, 'transform-origin', transformOrigin);\n }\n }\n\n private savePreviouslyFocusedElement(): void {\n if (!this.focusTrap) {\n this.focusTrap = this.focusTrapFactory.create(this.host.nativeElement);\n }\n\n if (this.document) {\n this.elementFocusedBeforeModalWasOpened = this.document.activeElement as HTMLElement;\n if (this.host.nativeElement.focus) {\n this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.host.nativeElement.focus()));\n }\n }\n }\n\n private trapFocus(): void {\n const element = this.host.nativeElement;\n\n if (this.config.nzAutofocus) {\n this.focusTrap.focusInitialElementWhenReady();\n } else {\n const activeElement = this.document.activeElement;\n if (activeElement !== element && !element.contains(activeElement)) {\n element.focus();\n }\n }\n }\n\n private restoreFocus(): void {\n const toFocus = this.elementFocusedBeforeModalWasOpened as HTMLElement;\n\n // We need the extra check, because IE can set the `activeElement` to null in some cases.\n if (toFocus && typeof toFocus.focus === 'function') {\n const activeElement = this.document.activeElement as Element;\n const element = this.host.nativeElement;\n\n if (\n !activeElement ||\n activeElement === this.document.body ||\n activeElement === element ||\n element.contains(activeElement)\n ) {\n toFocus.focus();\n }\n }\n\n if (this.focusTrap) {\n this.focusTrap.destroy();\n }\n }\n\n private setEnterAnimationClass(): void {\n if (this.animationDisabled()) {\n return;\n }\n // Make sure to set the `TransformOrigin` style before set the modelElement's class names\n this.setModalTransformOrigin();\n const modalElement = this.modalElementRef.nativeElement;\n const backdropElement = this.overlayRef.backdropElement;\n modalElement.classList.add(ZOOM_CLASS_NAME_MAP.enter);\n modalElement.classList.add(ZOOM_CLASS_NAME_MAP.enterActive);\n if (backdropElement) {\n backdropElement.classList.add(FADE_CLASS_NAME_MAP.enter);\n backdropElement.classList.add(FADE_CLASS_NAME_MAP.enterActive);\n }\n }\n\n private setExitAnimationClass(): void {\n const modalElement = this.modalElementRef.nativeElement;\n\n modalElement.classList.add(ZOOM_CLASS_NAME_MAP.leave);\n modalElement.classList.add(ZOOM_CLASS_NAME_MAP.leaveActive);\n\n this.setMaskExitAnimationClass();\n }\n\n private setMaskExitAnimationClass(force: boolean = false): void {\n const backdropElement = this.overlayRef.backdropElement;\n if (backdropElement) {\n if (this.animationDisabled() || force) {\n // https://github.com/angular/components/issues/18645\n backdropElement.classList.remove(MODAL_MASK_CLASS_NAME);\n return;\n }\n backdropElement.classList.add(FADE_CLASS_NAME_MAP.leave);\n backdropElement.classList.add(FADE_CLASS_NAME_MAP.leaveActive);\n }\n }\n\n private cleanAnimationClass(): void {\n if (this.animationDisabled()) {\n return;\n }\n const backdropElement = this.overlayRef.backdropElement;\n const modalElement = this.modalElementRef.nativeElement;\n if (backdropElement) {\n backdropElement.classList.remove(FADE_CLASS_NAME_MAP.enter);\n backdropElement.classList.remove(FADE_CLASS_NAME_MAP.enterActive);\n }\n modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.enter);\n modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.enterActive);\n modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.leave);\n modalElement.classList.remove(ZOOM_CLASS_NAME_MAP.leaveActive);\n }\n\n private setZIndexForBackdrop(): void {\n const backdropElement = this.overlayRef.backdropElement;\n if (backdropElement) {\n if (isNotNil(this.config.nzZIndex)) {\n this.render.setStyle(backdropElement, 'z-index', this.config.nzZIndex);\n }\n }\n }\n\n bindBackdropStyle(): void {\n const backdropElement = this.overlayRef.backdropElement;\n if (backdropElement) {\n if (this.oldMaskStyle) {\n const styles = this.oldMaskStyle as { [key: string]: string };\n Object.keys(styles).forEach(key => {\n this.render.removeStyle(backdropElement, key);\n });\n this.oldMaskStyle = null;\n }\n\n this.setZIndexForBackdrop();\n\n if (typeof this.config.nzMaskStyle === 'object' && Object.keys(this.config.nzMaskStyle).length) {\n const styles: { [key: string]: string } = { ...this.config.nzMaskStyle };\n Object.keys(styles).forEach(key => {\n this.render.setStyle(backdropElement, key, styles[key]);\n });\n this.oldMaskStyle = styles;\n }\n }\n }\n\n updateMaskClassname(): void {\n const backdropElement = this.overlayRef.backdropElement;\n if (backdropElement) {\n if (this.showMask) {\n backdropElement.classList.add(MODAL_MASK_CLASS_NAME);\n } else {\n backdropElement.classList.remove(MODAL_MASK_CLASS_NAME);\n }\n }\n }\n\n onAnimationDone(event: AnimationEvent): void {\n if (event.toState === 'enter') {\n this.trapFocus();\n } else if (event.toState === 'exit') {\n this.restoreFocus();\n }\n this.cleanAnimationClass();\n this.animationStateChanged.emit(event);\n }\n\n onAnimationStart(event: AnimationEvent): void {\n if (event.toState === 'enter') {\n this.setEnterAnimationClass();\n this.bindBackdropStyle();\n } else if (event.toState === 'exit') {\n this.setExitAnimationClass();\n }\n this.animationStateChanged.emit(event);\n }\n\n startExitAnimation(): void {\n this.state = 'exit';\n this.cdr.markForCheck();\n }\n\n ngOnDestroy(): void {\n this.setMaskExitAnimationClass(true);\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n protected setupMouseListeners(modalContainer: ElementRef<HTMLElement>): void {\n this.ngZone.runOutsideAngular(() => {\n fromEvent(this.host.nativeElement, 'mouseup')\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.mouseDown) {\n setTimeout(() => {\n this.mouseDown = false;\n });\n }\n });\n\n fromEvent(modalContainer.nativeElement, 'mousedown')\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n this.mouseDown = true;\n });\n });\n }\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { ModalOptions } from './modal-types';\n\n@Component({\n selector: 'button[nz-modal-close]',\n exportAs: 'NzModalCloseBuiltin',\n template: `\n <span class=\"ant-modal-close-x\">\n <ng-container *nzStringTemplateOutlet=\"config.nzCloseIcon; let closeIcon\">\n <i nz-icon [nzType]=\"closeIcon\" class=\"ant-modal-close-icon\"></i>\n </ng-container>\n </span>\n `,\n host: {\n class: 'ant-modal-close',\n 'aria-label': 'Close'\n },\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class NzModalCloseComponent {\n constructor(public config: ModalOptions) {}\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { FocusTrapFactory } from '@angular/cdk/a11y';\nimport { OverlayRef } from '@angular/cdk/overlay';\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Inject,\n NgZone,\n OnInit,\n Optional,\n Output,\n Renderer2,\n ViewChild\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\nimport { takeUntil } from 'rxjs/operators';\n\nimport { NzConfigService } from 'ng-zorro-antd/core/config';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { NzI18nService, NzModalI18nInterface } from 'ng-zorro-antd/i18n';\n\nimport { nzModalAnimations } from './modal-animations';\nimport { BaseModalContainerComponent } from './modal-container.directive';\nimport { ModalOptions } from './modal-types';\n\n@Component({\n selector: 'nz-modal-confirm-container',\n exportAs: 'nzModalConfirmContainer',\n template: `\n <div\n #modalElement\n role=\"document\"\n class=\"ant-modal\"\n [ngClass]=\"config.nzClassName!\"\n [ngStyle]=\"config.nzStyle!\"\n [style.width]=\"config?.nzWidth! | nzToCssUnit\"\n >\n <div class=\"ant-modal-content\">\n <button *ngIf=\"config.nzClosable\" nz-modal-close (click)=\"onCloseClick()\"></button>\n <div class=\"ant-modal-body\" [ngStyle]=\"config.nzBodyStyle!\">\n <div class=\"ant-modal-confirm-body-wrapper\">\n <div class=\"ant-modal-confirm-body\">\n <i nz-icon [nzType]=\"config.nzIconType!\"></i>\n <span class=\"ant-modal-confirm-title\">\n <ng-container *nzStringTemplateOutlet=\"config.nzTitle\">\n <span [innerHTML]=\"config.nzTitle\"></span>\n </ng-container>\n </span>\n <div class=\"ant-modal-confirm-content\">\n <ng-template cdkPortalOutlet></ng-template>\n <div *ngIf=\"isStringContent\" [innerHTML]=\"config.nzContent\"></div>\n </div>\n </div>\n <div class=\"ant-modal-confirm-btns\">\n <button\n *ngIf=\"config.nzCancelText !== null\"\n [attr.cdkFocusInitial]=\"config.nzAutofocus === 'cancel' || null\"\n nz-button\n (click)=\"onCancel()\"\n [nzLoading]=\"!!config.nzCancelLoading\"\n [disabled]=\"config.nzCancelDisabled\"\n >\n {{ config.nzCancelText || locale.cancelText }}\n </button>\n <button\n *ngIf=\"config.nzOkText !== null\"\n [attr.cdkFocusInitial]=\"config.nzAutofocus === 'ok' || null\"\n nz-button\n [nzType]=\"config.nzOkType!\"\n (click)=\"onOk()\"\n [nzLoading]=\"!!config.nzOkLoading\"\n [disabled]=\"config.nzOkDisabled\"\n [nzDanger]=\"config.nzOkDanger\"\n >\n {{ config.nzOkText || locale.okText }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n `,\n animations: [nzModalAnimations.modalContainer],\n // Using OnPush for modal caused footer can not to detect changes. we can fix it when 8.x.\n changeDetection: ChangeDetectionStrategy.Default,\n host: {\n tabindex: '-1',\n role: 'dialog',\n '[class]': 'config.nzWrapClassName ? \"ant-modal-wrap \" + config.nzWrapClassName : \"ant-modal-wrap\"',\n '[class.ant-modal-wrap-rtl]': `dir === 'rtl'`,\n '[class.ant-modal-centered]': 'config.nzCentered',\n '[style.zIndex]': 'config.nzZIndex',\n '[@.disabled]': 'config.nzNoAnimation',\n '[@modalContainer]': 'state',\n '(@modalContainer.start)': 'onAnimationStart($event)',\n '(@modalContainer.done)': 'onAnimationDone($event)',\n '(click)': 'onContainerClick($event)'\n }\n})\nexport class NzModalConfirmContainerComponent extends BaseModalContainerComponent implements OnInit {\n @ViewChild(CdkPortalOutlet, { static: true }) override portalOutlet!: CdkPortalOutlet;\n @ViewChild('modalElement', { static: true }) override modalElementRef!: ElementRef<HTMLDivElement>;\n @Output() override readonly cancelTriggered = new EventEmitter<void>();\n @Output() override readonly okTriggered = new EventEmitter<void>();\n locale!: NzModalI18nInterface;\n\n constructor(\n ngZone: NgZone,\n private i18n: NzI18nService,\n host: ElementRef<HTMLElement>,\n focusTrapFactory: FocusTrapFactory,\n cdr: ChangeDetectorRef,\n render: Renderer2,\n overlayRef: OverlayRef,\n nzConfigService: NzConfigService,\n public override config: ModalOptions,\n @Optional() @Inject(DOCUMENT) document: NzSafeAny,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string\n ) {\n super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);\n\n this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {\n this.locale = this.i18n.getLocaleData('Modal');\n });\n }\n\n ngOnInit(): void {\n this.setupMouseListeners(this.modalElementRef);\n }\n\n onCancel(): void {\n this.cancelTriggered.emit();\n }\n\n onOk(): void {\n this.okTriggered.emit();\n }\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { ModalOptions } from './modal-types';\n\n@Component({\n selector: 'div[nz-modal-title]',\n exportAs: 'NzModalTitleBuiltin',\n template: `\n <div class=\"ant-modal-title\">\n <ng-container *nzStringTemplateOutlet=\"config.nzTitle\">\n <div [innerHTML]=\"config.nzTitle\"></div>\n </ng-container>\n </div>\n `,\n host: {\n class: 'ant-modal-header'\n },\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class NzModalTitleComponent {\n constructor(public config: ModalOptions) {}\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport { isPromise } from 'ng-zorro-antd/core/util';\nimport { NzI18nService, NzModalI18nInterface } from 'ng-zorro-antd/i18n';\n\nimport { NzModalRef } from './modal-ref';\nimport { ModalButtonOptions, ModalOptions } from './modal-types';\n\n@Component({\n selector: 'div[nz-modal-footer]',\n exportAs: 'NzModalFooterBuiltin',\n template: `\n <ng-container *ngIf=\"config.nzFooter; else defaultFooterButtons\">\n <ng-container\n *nzStringTemplateOutlet=\"config.nzFooter; context: { $implicit: config.nzComponentParams, modalRef: modalRef }\"\n >\n <div *ngIf=\"!buttonsFooter\" [innerHTML]=\"config.nzFooter\"></div>\n <ng-container *ngIf=\"buttonsFooter\">\n <button\n *ngFor=\"let button of buttons\"\n nz-button\n (click)=\"onButtonClick(button)\"\n [hidden]=\"!getButtonCallableProp(button, 'show')\"\n [nzLoading]=\"getButtonCallableProp(button, 'loading')\"\n [disabled]=\"getButtonCallableProp(button, 'disabled')\"\n [nzType]=\"button.type!\"\n [nzDanger]=\"button.danger\"\n [nzShape]=\"button.shape!\"\n [nzSize]=\"button.size!\"\n [nzGhost]=\"button.ghost!\"\n >\n {{ button.label }}\n </button>\n </ng-container>\n </ng-container>\n </ng-container>\n <ng-template #defaultFooterButtons>\n <button\n *ngIf=\"config.nzCancelText !== null\"\n [attr.cdkFocusInitial]=\"config.nzAutofocus === 'cancel' || null\"\n nz-button\n (click)=\"onCancel()\"\n [nzLoading]=\"!!config.nzCancelLoading\"\n [disabled]=\"config.nzCancelDisabled\"\n >\n {{ config.nzCancelText || locale.cancelText }}\n </button>\n <button\n *ngIf=\"config.nzOkText !== null\"\n [attr.cdkFocusInitial]=\"config.nzAutofocus === 'ok' || null\"\n nz-button\n [nzType]=\"config.nzOkType!\"\n [nzDanger]=\"config.nzOkDanger\"\n (click)=\"onOk()\"\n [nzLoading]=\"!!config.nzOkLoading\"\n [disabled]=\"config.nzOkDisabled\"\n >\n {{ config.nzOkText || locale.okText }}\n </button>\n </ng-template>\n `,\n host: {\n class: 'ant-modal-footer'\n },\n changeDetection: ChangeDetectionStrategy.Default\n})\nexport class NzModalFooterComponent implements OnDestroy {\n buttonsFooter = false;\n buttons: ModalButtonOptions[] = [];\n locale!: NzModalI18nInterface;\n @Output() readonly cancelTriggered = new EventEmitter<void>();\n @Output() readonly okTriggered = new EventEmitter<void>();\n @Input() modalRef!: NzModalRef;\n private destroy$ = new Subject<void>();\n\n constructor(private i18n: NzI18nService, public config: ModalOptions) {\n if (Array.isArray(config.nzFooter)) {\n this.buttonsFooter = true;\n this.buttons = (config.nzFooter as ModalButtonOptions[]).map(mergeDefaultOption);\n }\n this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {\n this.locale = this.i18n.getLocaleData('Modal');\n });\n }\n\n onCancel(): void {\n this.cancelTriggered.emit();\n }\n\n onOk(): void {\n this.okTriggered.emit();\n }\n\n /**\n * Returns the value of the specified key.\n * If it is a function, run and return the return value of the function.\n */\n getButtonCallableProp(options: ModalButtonOptions, prop: keyof ModalButtonOptions): boolean {\n const value = options[prop];\n const componentInstance = this.modalRef.getContentComponent();\n return typeof value === 'function' ? value.apply(options, componentInstance && [componentInstance]) : value;\n }\n\n /**\n * Run function based on the type and set its `loading` prop if needed.\n */\n onButtonClick(options: ModalButtonOptions): void {\n const loading = this.getButtonCallableProp(options, 'loading');\n if (!loading) {\n const result = this.getButtonCallableProp(options, 'onClick');\n if (options.autoLoading && isPromise(result)) {\n options.loading = true;\n result\n .then(() => (options.loading = false))\n .catch(e => {\n options.loading = false;\n throw e;\n });\n }\n }\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n}\n\nfunction mergeDefaultOption(options: ModalButtonOptions): ModalButtonOptions {\n return {\n type: null,\n size: 'default',\n autoLoading: true,\n show: true,\n loading: false,\n disabled: false,\n ...options\n };\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { FocusTrapFactory } from '@angular/cdk/a11y';\nimport { OverlayRef } from '@angular/cdk/overlay';\nimport { CdkPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Inject,\n NgZone,\n OnInit,\n Optional,\n Renderer2,\n ViewChild\n} from '@angular/core';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\n\nimport { NzConfigService } from 'ng-zorro-antd/core/config';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\n\nimport { nzModalAnimations } from './modal-animations';\nimport { BaseModalContainerComponent } from './modal-container.directive';\nimport { ModalOptions } from './modal-types';\n\n@Component({\n selector: 'nz-modal-container',\n exportAs: 'nzModalContainer',\n template: `\n <div\n #modalElement\n role=\"document\"\n class=\"ant-modal\"\n [ngClass]=\"config.nzClassName!\"\n [ngStyle]=\"config.nzStyle!\"\n [style.width]=\"config?.nzWidth! | nzToCssUnit\"\n >\n <div class=\"ant-modal-content\">\n <button *ngIf=\"config.nzClosable\" nz-modal-close (click)=\"onCloseClick()\"></button>\n <div *ngIf=\"config.nzTitle\" nz-modal-title></div>\n <div class=\"ant-modal-body\" [ngStyle]=\"config.nzBodyStyle!\">\n <ng-template cdkPortalOutlet></ng-template>\n <div *ngIf=\"isStringContent\" [innerHTML]=\"config.nzContent\"></div>\n </div>\n <div\n *ngIf=\"config.nzFooter !== null\"\n nz-modal-footer\n [modalRef]=\"modalRef\"\n (cancelTriggered)=\"onCloseClick()\"\n (okTriggered)=\"onOkClick()\"\n ></div>\n </div>\n </div>\n `,\n animations: [nzModalAnimations.modalContainer],\n // Using OnPush for modal caused footer can not to detect changes. we can fix it when 8.x.\n changeDetection: ChangeDetectionStrategy.Default,\n host: {\n tabindex: '-1',\n role: 'dialog',\n '[class]': 'config.nzWrapClassName ? \"ant-modal-wrap \" + config.nzWrapClassName : \"ant-modal-wrap\"',\n '[class.ant-modal-wrap-rtl]': `dir === 'rtl'`,\n '[class.ant-modal-centered]': 'config.nzCentered',\n '[style.zIndex]': 'config.nzZIndex',\n '[@.disabled]': 'config.nzNoAnimation',\n '[@modalContainer]': 'state',\n '(@modalContainer.start)': 'onAnimationStart($event)',\n '(@modalContainer.done)': 'onAnimationDone($event)',\n '(click)': 'onContainerClick($event)'\n }\n})\nexport class NzModalContainerComponent extends BaseModalContainerComponent implements OnInit {\n @ViewChild(CdkPortalOutlet, { static: true }) override portalOutlet!: CdkPortalOutlet;\n @ViewChild('modalElement', { static: true }) override modalElementRef!: ElementRef<HTMLDivElement>;\n constructor(\n ngZone: NgZone,\n host: ElementRef<HTMLElement>,\n focusTrapFactory: FocusTrapFactory,\n cdr: ChangeDetectorRef,\n render: Renderer2,\n overlayRef: OverlayRef,\n nzConfigService: NzConfigService,\n public override config: ModalOptions,\n @Optional() @Inject(DOCUMENT) document: NzSafeAny,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string\n ) {\n super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);\n }\n\n ngOnInit(): void {\n this.setupMouseListeners(this.modalElementRef);\n }\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';\nimport { OverlayRef } from '@angular/cdk/overlay';\nimport { EventEmitter } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { filter, take, takeUntil } from 'rxjs/operators';\n\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { isPromise } from 'ng-zorro-antd/core/util';\n\nimport { BaseModalContainerComponent } from './modal-container.directive';\nimport { NzModalLegacyAPI } from './modal-legacy-api';\nimport { ModalOptions } from './modal-types';\n\nexport const enum NzModalState {\n OPEN,\n CLOSING,\n CLOSED\n}\n\nexport const enum NzTriggerAction {\n CANCEL = 'cancel',\n OK = 'ok'\n}\n\nexport class NzModalRef<T = NzSafeAny, R = NzSafeAny> implements NzModalLegacyAPI<T, R> {\n componentInstance: T | null = null;\n result?: R;\n state: NzModalState = NzModalState.OPEN;\n afterClose: Subject<R> = new Subject();\n afterOpen: Subject<void> = new Subject();\n\n private closeTimeout?: number;\n\n private destroy$ = new Subject<void>();\n\n constructor(\n private overlayRef: OverlayRef,\n private config: ModalOptions,\n public containerInstance: BaseModalContainerComponent\n ) {\n containerInstance.animationStateChanged\n .pipe(\n filter(event => event.phaseName === 'done' && event.toState === 'enter'),\n take(1)\n )\n .subscribe(() => {\n this.afterOpen.next();\n this.afterOpen.complete();\n if (config.nzAfterOpen instanceof EventEmitter) {\n config.nzAfterOpen.emit();\n }\n });\n\n containerInstance.animationStateChanged\n .pipe(\n filter(event => event.phaseName === 'done' && event.toState === 'exit'),\n take(1)\n )\n .subscribe(() => {\n clearTimeout(this.closeTimeout);\n this._finishDialogClose();\n });\n\n containerInstance.containerClick.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => {\n const cancelable = !this.config.nzCancelLoading && !this.config.nzOkLoading;\n if (cancelable) {\n this.trigger(NzTriggerAction.CANCEL);\n }\n });\n\n overlayRef\n .keydownEvents()\n .pipe(\n filter(\n event =>\n (this.config.nzKeyboard as boolean) &&\n !this.config.nzCancelLoading &&\n !this.config.nzOkLoading &&\n event.keyCode === ESCAPE &&\n !hasModifierKey(event)\n )\n )\n .subscribe(event => {\n event.preventDefault();\n this.trigger(NzTriggerAction.CANCEL);\n });\n\n containerInstance.cancelTriggered\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => this.trigger(NzTriggerAction.CANCEL));\n\n containerInstance.okTriggered.pipe(takeUntil(this.destroy$)).subscribe(() => this.trigger(NzTriggerAction.OK));\n\n overlayRef.detachments().subscribe(() => {\n this.afterClose.next(this.result);\n this.afterClose.complete();\n if (config.nzAfterClose instanceof EventEmitter) {\n config.nzAfterClose.emit(this.result);\n }\n this.componentInstance = null;\n this.overlayRef.dispose();\n });\n }\n\n getContentComponent(): T {\n return this.componentInstance as T;\n }\n\n getElement(): HTMLElement {\n return this.containerInstance.getNativeElement();\n }\n\n destroy(result?: R): void {\n this.close(result);\n }\n\n triggerOk(): Promise<void> {\n return this.trigger(NzTriggerAction.OK);\n }\n\n triggerCancel(): Promise<void> {\n return this.trigger(NzTriggerAction.CANCEL);\n }\n\n close(result?: R): void {\n if (this.state !== NzModalState.OPEN) {\n return;\n }\n this.result = result;\n this.containerInstance.animationStateChanged\n .pipe(\n filter(event => event.phaseName === 'start'),\n take(1)\n )\n .subscribe(event => {\n this.overlayRef.detachBackdrop();\n this.closeTimeout = setTimeout(() => {\n this._finishDialogClose();\n }, event.totalTime + 100);\n });\n\n this.containerInstance.startExitAnimation();\n this.state = NzModalState.CLOSING;\n }\n\n updateConfig(config: ModalOptions): void {\n Object.assign(this.config, config);\n this.containerInstance.bindBackdropStyle();\n this.containerInstance.cdr.markForCheck();\n }\n\n getState(): NzModalState {\n return this.state;\n }\n\n getConfig(): ModalOptions {\n return this.config;\n }\n\n getBackdropElement(): HTMLElement | null {\n return this.overlayRef.backdropElement;\n }\n\n private async trigger(action: NzTriggerAction): Promise<void> {\n const trigger = { ok: this.config.nzOnOk, cancel: this.config.nzOnCancel }[action];\n const loadingKey = { ok: 'nzOkLoading', cancel: 'nzCancelLoading' }[action] as 'nzOkLoading' | 'nzCancelLoading';\n const loading = this.config[loadingKey];\n if (loading) {\n return;\n }\n if (trigger instanceof EventEmitter) {\n trigger.emit(this.getContentComponent());\n } else if (typeof trigger === 'function') {\n const result = trigger(this.getContentComponent());\n if (isPromise(result)) {\n this.config[loadingKey] = true;\n let doClose: boolean | void | {} = false;\n try {\n doClose = await result;\n } finally {\n this.config[loadingKey] = false;\n this.closeWhitResult(doClose);\n }\n } else {\n this.closeWhitResult(result);\n }\n }\n }\n\n private closeWhitResult(result: NzSafeAny): void {\n if (result !== false) {\n this.close(result);\n }\n }\n\n _finishDialogClose(): void {\n this.state = NzModalState.CLOSED;\n this.overlayRef.dispose();\n this.destroy$.next();\n }\n}\n","/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { ComponentType, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport { Injectable, Injector, OnDestroy, Optional, SkipSelf, TemplateRef } from '@angular/core';\nimport { defer, Observable, Subject } from 'rxjs';\nimport { startWith } from 'rxjs/operators';\n\nimport { NzConfigService } from 'ng-zorro-antd/core/config';\nimport { warn } from 'ng-zorro-antd/core/logger';\nimport { IndexableObject, NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { isNotNil } from 'ng-zorro-antd/core/util';\n\nimport { MODAL_MASK_CLASS_NAME, NZ_CONFIG_MODULE_NAME } from './modal-config';\nimport { NzModalConfirmContainerComponent } from './modal-confirm-container.component';\nimport { NzModalContainerComponent } from './modal-container.component';\nimport { BaseModalContainerComponent } from './modal-container.directive';\nimport { NzModalRef } from './modal-ref';\nimport { ConfirmType, ModalOptions } from './modal-types';\nimport { applyConfigDefaults, getValueWithConfig, setContentInstanceParams } from './utils';\n\ntype ContentType<T> = ComponentType<T> | TemplateRef<T> | string;\n\n@Injectable()\nexport class NzModalService implements OnDestroy {\n private openModalsAtThisLevel: NzModalRef[] = [];\n private readonly afterAllClosedAtThisLevel = new Subject<void>();\n\n get openModals(): NzModalRef[] {\n return this.parentModal ? this.parentModal.openModals : this.openModalsAtThisLevel;\n }\n\n get _afterAllClosed(): Subject<void> {\n const parent = this.parentModal;\n return parent ? parent._afterAllClosed : this.afterAllClosedAtThisLevel;\n }\n\n readonly afterAllClose: Observable<void> = defer(() =>\n this.openModals.length ? this._afterAllClosed : this._afterAllClosed.pipe(startWith(undefined))\n ) as Observable<void>;\n\n constructor(\n private overlay: Overlay,\n private injector: Injector,\n private nzConfigService: NzConfigService,\n @Optional() @SkipSelf() private parentModal: NzModalService,\n @Optional() private directionality: Directionality\n ) {}\n\n create<T, R = NzSafeAny>(config: ModalOptions<T, R>): NzModalRef<T, R> {\n return this.open<T, R>(config.nzContent as ComponentType<T>, config);\n }\n\n closeAll(): void {\n this.closeModals(this.openModals);\n }\n\n confirm<T>(options: ModalOptions<T> = {}, confirmType: ConfirmType = 'confirm'): NzModalRef<T> {\n if ('nzFooter' in options) {\n warn(`The Confirm-Modal doesn't support \"nzFooter\", this property will be ignored.`);\n }\n if (!('nzWidth' in options)) {\n options.nzWidth = 416;\n }\n if (!('nzMaskClosable' in options)) {\n options.nzMaskClosable = false;\n }\n\n options.nzModalType = 'confirm';\n options.nzClassName = `ant-modal-confirm ant-modal-confirm-${confirmType} ${options.nzClassName || ''}`;\n return this.create(options);\n }\n\n info<T>(options: ModalOptions<T> = {}): NzModalRef<T> {\n return this.confirmFactory(options, 'info');\n }\n\n success<T>(options: ModalOptions<T> = {}): NzModalRef<T> {\n return this.confirmFactory(options, 'success');\n }\n\n error<T>(options: ModalOptions<T> = {}): NzModalRef<T> {\n return this.confirmFactory(options, 'error');\n }\n\n warning<T>(options: ModalOptions<T> = {}): NzModalRef<T> {\n return this.confirmFactory(options, 'warning');\n }\n\n private open<T, R>(componentOrTemplateRef: ContentType<T>, config?: ModalOptions): NzModalRef<T, R> {\n const configMerged = applyConfigDefaults(config || {}, new ModalOptions());\n const overlayRef = this.createOverlay(configMerged);\n const modalContainer = this.attachModalContainer(overlayRef, configMerged);\n const modalRef = this.attachModalContent<T, R>(componentOrTemplateRef, modalContainer, overlayRef, configMerged);\n modalContainer.modalRef = modalRef;\n\n this.openModals.push(modalRef);\n modalRef.afterClose.subscribe(() => this.removeOpenModal(modalRef));\n\n return modalRef;\n }\n\n private removeOpenModal(modalRef: NzModalRef): void {\n const index = this.openModals.indexOf(modalRef);\n if (index > -1) {\n this.openModals.splice(index, 1);\n\n if (!this.openModals.length) {\n this._afterAllClosed.next();\n }\n }\n }\n\n private closeModals(dialogs: NzModalRef[]): void {\n let i = dialogs.length;\n while (i--) {\n dialogs[i].close();\n if (!this.openModals.length) {\n this._afterAllClosed.next();\n }\n }\n }\n\n private createOverlay(config: ModalOptions): OverlayRef {\n const globalConfig: NzSafeAny = this.nzConfigService.getConfigForComponent(NZ_CONFIG_MODULE_NAME) || {};\n const overlayConfig = new OverlayConfig({\n hasBackdrop: true,\n scrollStrategy: this.overlay.scrollStrategies.block(),\n positionStrategy: this.overlay.position().global(),\n disposeOnNavigation: getValueWithConfig(config.nzCloseOnNavigation, globalConfig.nzCloseOnNavigation, true),\n direction: getValueWithConfig(config.nzDirection, globalConfig.nzDirection, this.directionality.value)\n });\n if (getValueWithConfig(config.nzMask, globalConfig.nzMask, true)) {\n overlayConfig.backdropClass = MODAL_MASK_CLASS_NAME;\n }\n\n return this.overlay.create(overlayConfig);\n }\n\n private attachModalContainer(overlayRef: OverlayRef, config: ModalOptions): BaseModalContainerComponent {\n const userInjector = config && config.nzViewContainerRef && config.nzViewContainerRef.injector;\n const injector = Injector.create({\n parent: userInjector || this.injector,\n providers: [\n { provide: OverlayRef, useValue: overlayRef },\n { provide: ModalOptions, useValue: config }\n ]\n });\n\n const ContainerComponent =\n config.nzModalType === 'confirm'\n ? // If the mode is `confirm`, use `NzModalConfirmContainerComponent`\n NzModalConfirmContainerComponent\n : // If the mode is not `confirm`, use `NzModalContainerComponent`\n NzModalContainerComponent;\n\n const containerPortal = new ComponentPortal<BaseModalContainerComponent>(\n ContainerComponent,\n config.nzViewContainerRef,\n injector\n );\n const containerRef = overlayRef.attach<BaseModalContainerComponent>(containerPortal);\n\n return containerRef.instance;\n }\n\n private attachModalContent<T, R>(\n componentOrTemplateRef: ContentType<T>,\n modalContainer: BaseModalContainerComponent,\n overlayRef: OverlayRef,\n config: ModalOptions<T>\n ): NzModalRef<T, R> {\n const modalRef = new NzModalRef<T, R>(overlayRef, config, modalContainer);\n\n if (componentOrTemplateRef instanceof TemplateRef) {\n modalContainer.attachTemplatePortal(\n new TemplatePortal<T>(componentOrTemplateRef, null!, {\n $implicit: config.nzComponentParams,\n modalRef\n } as NzSafeAny)\n );\n } else if (isNotNil(componentOrTemplateRef) && typeof componentOrTemplateRef !== 'string') {\n const injector = this.createInjector<T, R>(modalRef, config);\n const contentRef = modalContainer.attachComponentPortal<T>(\n new ComponentPortal(componentOrTemplateRef, config.nzViewContainerRef, injector)\n );\n setContentInstanceParams<T>(contentRef.instance, config.nzComponentParams);\n modalRef.componentInstance = contentRef.instance;\n } else {\n modalContainer.attachStringContent();\n }\n return modalRef;\n }\n\n private createInjector<T, R>(modalRef: NzModalRef<T, R>, config: ModalOptions<T>): Injector {\n const userInjector = config && config.nzViewContainerRef && config.nzViewContainerRef.injector;\n\n return Injector.create({\n parent: userInjector || this.injector,\n providers: [{ provide: NzModalRef, useValue: modalRef }]\n });\n }\n\n private confirmFactory<T>(options: ModalOptions<T> = {}, confirmType: ConfirmType): NzModalRef<T> {\n const iconMap: IndexableObject = {\n info: 'info-circle',\n success: 'check-circl