import * as i0 from '@angular/core'; import { Directive, PLATFORM_ID, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, SkipSelf, Optional, ViewChild, NgModule, createComponent, Injectable } from '@angular/core'; import { DomHandler } from 'primeng/dom'; import { animation, style, animate, trigger, transition, useAnimation } from '@angular/animations'; import * as i4 from '@angular/common'; import { isPlatformBrowser, DOCUMENT, CommonModule } from '@angular/common'; import * as i3 from 'primeng/api'; import { TranslationKeys, SharedModule } from 'primeng/api'; import * as i5 from 'primeng/focustrap'; import { FocusTrapModule } from 'primeng/focustrap'; import { TimesIcon } from 'primeng/icons/times'; import { WindowMaximizeIcon } from 'primeng/icons/windowmaximize'; import { WindowMinimizeIcon } from 'primeng/icons/windowminimize'; import { UniqueComponentId, ZIndexUtils } from 'primeng/utils'; import { Subject } from 'rxjs'; class DynamicDialogContent { viewContainerRef; constructor(viewContainerRef) { this.viewContainerRef = viewContainerRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: DynamicDialogContent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.7", type: DynamicDialogContent, selector: "[pDynamicDialogContent]", host: { classAttribute: "p-element" }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: DynamicDialogContent, decorators: [{ type: Directive, args: [{ selector: '[pDynamicDialogContent]', host: { class: 'p-element' } }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }] }); /** * Dialogs can be created dynamically with any component as the content using a DialogService. * @group Components */ class DynamicDialogConfig { /** * An object to pass to the component loaded inside the Dialog. * @group Props */ data; /** * Header text of the dialog. * @group Props */ header; /** * Identifies the element (or elements) that labels the element it is applied to. * @group Props */ ariaLabelledBy; /** * Footer text of the dialog. * @group Props */ footer; /** * Width of the dialog. * @group Props */ width; /** * Height of the dialog. * @group Props */ height; /** * Specifies if pressing escape key should hide the dialog. * @group Props */ closeOnEscape; /** * Specifies if autofocus should happen on show. * @group Props */ focusOnShow = true; /** * When enabled, can only focus on elements inside the dialog. * @group Props */ focusTrap = true; /** * Base zIndex value to use in layering. * @group Props */ baseZIndex; /** * Whether to automatically manage layering. * @group Props */ autoZIndex; /** * Specifies if clicking the modal background should hide the dialog. * @group Props */ dismissableMask; /** * Inline style of the component. * @group Props */ rtl; /** * Inline style of the comopnent. * @group Props */ style; /** * Inline style of the content. * @group Props */ contentStyle; /** * Style class of the component. * @group Props */ styleClass; /** * Transition options of the animation. * @group Props */ transitionOptions; /** * Adds a close icon to the header to hide the dialog. * @group Props */ closable; /** * Whether to show the header or not. * @group Props */ showHeader; /** * Defines if background should be blocked when dialog is displayed. * @group Props */ modal; /** * Style class of the mask. * @group Props */ maskStyleClass; /** * Enables resizing of the content. * @group Props */ resizable; /** * Enables dragging to change the position using header. * @group Props */ draggable; /** * Keeps dialog in the viewport. * @group Props */ keepInViewport; /** * Minimum value for the left coordinate of dialog in dragging. * @group Props */ minX; /** * Minimum value for the top coordinate of dialog in dragging. * @group Props */ minY; /** * Whether the dialog can be displayed full screen. * @group Props */ maximizable; /** * Name of the maximize icon. * @group Props */ maximizeIcon; /** * Name of the minimize icon. * @group Props */ minimizeIcon; /** * Position of the dialog, options are "center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left" or "bottom-right". * @group Props */ position; /** * Defines a string that labels the close button for accessibility. * @group Props */ closeAriaLabel; /** * Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]="mydiv" for a div element having #mydiv as variable name). * @group Props */ appendTo; /** * A boolean to determine if it can be duplicate. * @group Props */ duplicate; /** * Object literal to define widths per screen size. * @group Props */ breakpoints; /** * Dialog templates. * @group Props */ templates; } /** * Dynamic Dialog instance. * @group Components */ class DynamicDialogRef { constructor() { } /** * Closes dialog. * @group Method */ close(result) { this._onClose.next(result); setTimeout(() => { this._onClose.complete(); }, 1000); } /** * Destroys the dialog instance. * @group Method */ destroy() { this._onDestroy.next(null); } /** * Callback to invoke on drag start. * @param {MouseEvent} event - Mouse event. * @group Method */ dragStart(event) { this._onDragStart.next(event); } /** * Callback to invoke on drag end. * @param {MouseEvent} event - Mouse event. * @group Method */ dragEnd(event) { this._onDragEnd.next(event); } /** * Callback to invoke on resize start. * @param {MouseEvent} event - Mouse event. * @group Method */ resizeInit(event) { this._onResizeInit.next(event); } /** * Callback to invoke on resize start. * @param {MouseEvent} event - Mouse event. * @group Method */ resizeEnd(event) { this._onResizeEnd.next(event); } /** * Callback to invoke on dialog is maximized. * @param {*} value - Size value. * @group Method */ maximize(value) { this._onMaximize.next(value); } _onClose = new Subject(); /** * Event triggered on dialog is closed. * @group Events */ onClose = this._onClose.asObservable(); _onDestroy = new Subject(); /** * Event triggered on dialog instance is destroyed. * @group Events */ onDestroy = this._onDestroy.asObservable(); _onDragStart = new Subject(); /** * Event triggered on drag start. * @param {MouseEvent} event - Mouse event. * @group Events */ onDragStart = this._onDragStart.asObservable(); _onDragEnd = new Subject(); /** * Event triggered on drag end. * @param {MouseEvent} event - Mouse event. * @group Events */ onDragEnd = this._onDragEnd.asObservable(); _onResizeInit = new Subject(); /** * Event triggered on resize start. * @param {MouseEvent} event - Mouse event. * @group Events */ onResizeInit = this._onResizeInit.asObservable(); _onResizeEnd = new Subject(); /** * Event triggered on resize end. * @param {MouseEvent} event - Mouse event. * @group Events */ onResizeEnd = this._onResizeEnd.asObservable(); _onMaximize = new Subject(); /** * Event triggered on dialog is maximized. * @param {*} value - Size value. * @group Events */ onMaximize = this._onMaximize.asObservable(); /** * Event triggered on child component load. * @param {*} value - Chi. * @group Events */ onChildComponentLoaded = new Subject(); } const showAnimation = animation([style({ transform: '{{transform}}', opacity: 0 }), animate('{{transition}}', style({ transform: 'none', opacity: 1 }))]); const hideAnimation = animation([animate('{{transition}}', style({ transform: '{{transform}}', opacity: 0 }))]); class DynamicDialogComponent { document; platformId; cd; renderer; config; dialogRef; zone; primeNGConfig; parentDialog; visible = true; componentRef; mask; resizing; dragging; maximized; _style = {}; originalStyle; lastPageX; lastPageY; ariaLabelledBy; id = UniqueComponentId(); styleElement; insertionPoint; maskViewChild; contentViewChild; footerViewChild; headerViewChild; childComponentType; container; wrapper; documentKeydownListener; documentEscapeListener; maskClickListener; transformOptions = 'scale(0.7)'; documentResizeListener; documentResizeEndListener; documentDragListener; documentDragEndListener; get minX() { return this.config.minX ? this.config.minX : 0; } get minY() { return this.config.minY ? this.config.minY : 0; } get keepInViewport() { return this.config.keepInViewport; } get maximizable() { return this.config.maximizable; } get maximizeIcon() { return this.config.maximizeIcon; } get minimizeIcon() { return this.config.minimizeIcon; } get style() { return this._style; } get position() { return this.config.position; } get closeAriaLabel() { return this.primeNGConfig.getTranslation(TranslationKeys.ARIA)['close']; } set style(value) { if (value) { this._style = { ...value }; this.originalStyle = value; } } get parent() { const domElements = Array.from(this.document.getElementsByClassName('p-dialog')); if (domElements.length > 1) { return domElements.pop(); } } get parentContent() { const domElements = Array.from(this.document.getElementsByClassName('p-dialog')); if (domElements.length > 0) { const contentElements = domElements[domElements.length - 1].querySelector('.p-dialog-content'); if (contentElements) return Array.isArray(contentElements) ? contentElements[0] : contentElements; } } get header() { return this.config.header; } get data() { return this.config.data; } get breakpoints() { return this.config.breakpoints; } get footerTemplate() { return this.config?.templates?.footer; } get headerTemplate() { return this.config?.templates?.header; } get contentTemplate() { return this.config?.templates?.content; } get minimizeIconTemplate() { return this.config?.templates?.minimizeicon; } get maximizeIconTemplate() { return this.config?.templates?.maximizeicon; } get closeIconTemplate() { return this.config?.templates?.closeicon; } constructor(document, platformId, cd, renderer, config, dialogRef, zone, primeNGConfig, parentDialog) { this.document = document; this.platformId = platformId; this.cd = cd; this.renderer = renderer; this.config = config; this.dialogRef = dialogRef; this.zone = zone; this.primeNGConfig = primeNGConfig; this.parentDialog = parentDialog; } ngOnInit() { if (this.breakpoints) { this.createStyle(); } } createStyle() { if (isPlatformBrowser(this.platformId)) { if (!this.styleElement) { this.styleElement = this.renderer.createElement('style'); this.styleElement.type = 'text/css'; this.renderer.appendChild(this.document.head, this.styleElement); let innerHTML = ''; for (let breakpoint in this.breakpoints) { innerHTML += ` @media screen and (max-width: ${breakpoint}) { .p-dialog[${this.id}]:not(.p-dialog-maximized) { width: ${this.breakpoints[breakpoint]} !important; } } `; } this.renderer.setProperty(this.styleElement, 'innerHTML', innerHTML); } } } destroyStyle() { if (this.styleElement) { this.renderer.removeChild(this.document.head, this.styleElement); this.styleElement = null; } } ngAfterViewInit() { this.loadChildComponent(this.childComponentType); this.ariaLabelledBy = this.getAriaLabelledBy(); this.cd.detectChanges(); } getAriaLabelledBy() { return this.header !== null ? UniqueComponentId() + '_header' : null; } loadChildComponent(componentType) { let viewContainerRef = this.insertionPoint?.viewContainerRef; viewContainerRef?.clear(); this.componentRef = viewContainerRef?.createComponent(componentType); this.dialogRef.onChildComponentLoaded.next(this.componentRef.instance); } moveOnTop() { if (this.config.autoZIndex !== false) { ZIndexUtils.set('modal', this.container, (this.config.baseZIndex || 0) + this.primeNGConfig.zIndex.modal); this.wrapper.style.zIndex = String(parseInt(this.container.style.zIndex, 10) - 1); } } onAnimationStart(event) { switch (event.toState) { case 'visible': this.container = event.element; this.wrapper = this.container.parentElement; this.moveOnTop(); if (this.parent) { this.unbindGlobalListeners(); } this.bindGlobalListeners(); this.container?.setAttribute(this.id, ''); if (this.config.modal !== false) { this.enableModality(); } if (this.config.focusOnShow !== false) { this.focus(); } break; case 'void': if (this.wrapper && this.config.modal !== false) { DomHandler.addClass(this.wrapper, 'p-component-overlay-leave'); } break; } } onAnimationEnd(event) { if (event.toState === 'void') { if (this.parentContent) { this.focus(this.parentContent); } this.onContainerDestroy(); this.dialogRef.destroy(); } } onContainerDestroy() { this.unbindGlobalListeners(); if (this.container && this.config.autoZIndex !== false) { ZIndexUtils.clear(this.container); } if (this.config.modal !== false) { this.disableModality(); } this.container = null; } close() { this.visible = false; this.cd.markForCheck(); } hide() { if (this.dialogRef) { this.dialogRef.close(); } } enableModality() { if (this.config.dismissableMask) { this.maskClickListener = this.renderer.listen(this.wrapper, 'mousedown', (event) => { if (this.wrapper && this.wrapper.isSameNode(event.target)) { this.hide(); } }); } if (this.config.modal !== false) { DomHandler.addClass(this.document.body, 'p-overflow-hidden'); } } disableModality() { if (this.wrapper) { if (this.config.dismissableMask) { this.unbindMaskClickListener(); } if (this.config.modal !== false) { DomHandler.removeClass(this.document.body, 'p-overflow-hidden'); } if (!this.cd.destroyed) { this.cd.detectChanges(); } } } focus(focusParentElement = this.contentViewChild.nativeElement) { let focusable = DomHandler.getFocusableElement(focusParentElement, '[autofocus]'); if (focusable) { this.zone.runOutsideAngular(() => { setTimeout(() => focusable.focus(), 5); }); return; } const focusableElement = DomHandler.getFocusableElement(focusParentElement); if (focusableElement) { this.zone.runOutsideAngular(() => { setTimeout(() => focusableElement.focus(), 5); }); } else if (this.footerViewChild) { // If the content section is empty try to focus on footer this.focus(this.footerViewChild.nativeElement); } else if (!focusableElement && this.headerViewChild) { this.focus(this.headerViewChild.nativeElement); } } maximize() { this.maximized = !this.maximized; if (this.maximized) { DomHandler.addClass(this.document.body, 'p-overflow-hidden'); } else { DomHandler.removeClass(this.document.body, 'p-overflow-hidden'); } this.dialogRef.maximize({ maximized: this.maximized }); } initResize(event) { if (this.config.resizable) { if (!this.documentResizeListener) { this.bindDocumentResizeListeners(); } this.resizing = true; this.lastPageX = event.pageX; this.lastPageY = event.pageY; DomHandler.addClass(this.document.body, 'p-unselectable-text'); this.dialogRef.resizeInit(event); } } onResize(event) { if (this.resizing) { let deltaX = event.pageX - this.lastPageX; let deltaY = event.pageY - this.lastPageY; let containerWidth = DomHandler.getOuterWidth(this.container); let containerHeight = DomHandler.getOuterHeight(this.container); let contentHeight = DomHandler.getOuterHeight(this.contentViewChild.nativeElement); let newWidth = containerWidth + deltaX; let newHeight = containerHeight + deltaY; let minWidth = this.container.style.minWidth; let minHeight = this.container.style.minHeight; let offset = this.container.getBoundingClientRect(); let viewport = DomHandler.getViewport(); let hasBeenDragged = !parseInt(this.container.style.top) || !parseInt(this.container.style.left); if (hasBeenDragged) { newWidth += deltaX; newHeight += deltaY; } if ((!minWidth || newWidth > parseInt(minWidth)) && offset.left + newWidth < viewport.width) { this._style.width = newWidth + 'px'; this.container.style.width = this._style.width; } if ((!minHeight || newHeight > parseInt(minHeight)) && offset.top + newHeight < viewport.height) { this.contentViewChild.nativeElement.style.height = contentHeight + newHeight - containerHeight + 'px'; if (this._style.height) { this._style.height = newHeight + 'px'; this.container.style.height = this._style.height; } } this.lastPageX = event.pageX; this.lastPageY = event.pageY; } } resizeEnd(event) { if (this.resizing) { this.resizing = false; DomHandler.removeClass(this.document.body, 'p-unselectable-text'); this.dialogRef.resizeEnd(event); } } initDrag(event) { if (DomHandler.hasClass(event.target, 'p-dialog-header-icon') || DomHandler.hasClass(event.target.parentElement, 'p-dialog-header-icon')) { return; } if (this.config.draggable) { this.dragging = true; this.lastPageX = event.pageX; this.lastPageY = event.pageY; this.container.style.margin = '0'; DomHandler.addClass(this.document.body, 'p-unselectable-text'); this.dialogRef.dragStart(event); } } onDrag(event) { if (this.dragging) { let containerWidth = DomHandler.getOuterWidth(this.container); let containerHeight = DomHandler.getOuterHeight(this.container); let deltaX = event.pageX - this.lastPageX; let deltaY = event.pageY - this.lastPageY; let offset = this.container.getBoundingClientRect(); let leftPos = offset.left + deltaX; let topPos = offset.top + deltaY; let viewport = DomHandler.getViewport(); this.container.style.position = 'fixed'; if (this.keepInViewport) { if (leftPos >= this.minX && leftPos + containerWidth < viewport.width) { this._style.left = leftPos + 'px'; this.lastPageX = event.pageX; this.container.style.left = leftPos + 'px'; } if (topPos >= this.minY && topPos + containerHeight < viewport.height) { this._style.top = topPos + 'px'; this.lastPageY = event.pageY; this.container.style.top = topPos + 'px'; } } else { this.lastPageX = event.pageX; this.container.style.left = leftPos + 'px'; this.lastPageY = event.pageY; this.container.style.top = topPos + 'px'; } } } endDrag(event) { if (this.dragging) { this.dragging = false; DomHandler.removeClass(this.document.body, 'p-unselectable-text'); this.dialogRef.dragEnd(event); this.cd.detectChanges(); } } resetPosition() { this.container.style.position = ''; this.container.style.left = ''; this.container.style.top = ''; this.container.style.margin = ''; } bindDocumentDragListener() { if (isPlatformBrowser(this.platformId)) { this.zone.runOutsideAngular(() => { this.documentDragListener = this.renderer.listen(this.document, 'mousemove', this.onDrag.bind(this)); }); } } bindDocumentDragEndListener() { if (isPlatformBrowser(this.platformId)) { this.zone.runOutsideAngular(() => { this.documentDragEndListener = this.renderer.listen(this.document, 'mouseup', this.endDrag.bind(this)); }); } } unbindDocumentDragEndListener() { if (this.documentDragEndListener) { this.documentDragEndListener(); this.documentDragListener = null; } } unbindDocumentDragListener() { if (this.documentDragListener) { this.documentDragListener(); this.documentDragListener = null; } } bindDocumentResizeListeners() { if (isPlatformBrowser(this.platformId)) { this.zone.runOutsideAngular(() => { this.documentResizeListener = this.renderer.listen(this.document, 'mousemove', this.onResize.bind(this)); this.documentResizeEndListener = this.renderer.listen(this.document, 'mouseup', this.resizeEnd.bind(this)); }); } } unbindDocumentResizeListeners() { if (this.documentResizeListener && this.documentResizeEndListener) { this.documentResizeListener(); this.documentResizeEndListener(); this.documentResizeListener = null; this.documentResizeEndListener = null; } } bindGlobalListeners() { if (this.config.closeOnEscape !== false) { this.bindDocumentEscapeListener(); } if (this.config.resizable) { this.bindDocumentResizeListeners(); } if (this.config.draggable) { this.bindDocumentDragListener(); this.bindDocumentDragEndListener(); } } unbindGlobalListeners() { this.unbindDocumentEscapeListener(); this.unbindDocumentResizeListeners(); this.unbindDocumentDragListener(); this.unbindDocumentDragEndListener(); } bindDocumentEscapeListener() { const documentTarget = this.maskViewChild ? this.maskViewChild.nativeElement.ownerDocument : 'document'; this.documentEscapeListener = this.renderer.listen(documentTarget, 'keydown', (event) => { if (event.which == 27) { if (parseInt(this.container.style.zIndex) == ZIndexUtils.getCurrent()) { this.hide(); } } }); } unbindDocumentEscapeListener() { if (this.documentEscapeListener) { this.documentEscapeListener(); this.documentEscapeListener = null; } } unbindMaskClickListener() { if (this.maskClickListener) { this.maskClickListener(); this.maskClickListener = null; } } ngOnDestroy() { this.onContainerDestroy(); if (this.componentRef) { this.componentRef.destroy(); } this.destroyStyle(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: DynamicDialogComponent, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: DynamicDialogConfig }, { token: DynamicDialogRef }, { token: i0.NgZone }, { token: i3.PrimeNGConfig }, { token: DynamicDialogComponent, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.7", type: DynamicDialogComponent, selector: "p-dynamicDialog", host: { classAttribute: "p-element" }, viewQueries: [{ propertyName: "insertionPoint", first: true, predicate: DynamicDialogContent, descendants: true }, { propertyName: "maskViewChild", first: true, predicate: ["mask"], descendants: true }, { propertyName: "contentViewChild", first: true, predicate: ["content"], descendants: true }, { propertyName: "footerViewChild", first: true, predicate: ["footer"], descendants: true }, { propertyName: "headerViewChild", first: true, predicate: ["titlebar"], descendants: true }], ngImport: i0, template: `