primeng
Version:
PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,
1,008 lines (1,006 loc) • 71.4 kB
JavaScript
export * from 'primeng/types/dialog';
import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, input, inject, booleanAttribute, numberAttribute, computed, model, output, viewChild, contentChild, signal, effect, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import { uuid, setAttribute, addStyle, getOuterWidth, getOuterHeight, getViewport, appendChild, removeClass, hasClass } from '@primeuix/utils';
import { OverlayService, TranslationKeys, SharedModule } from 'primeng/api';
import { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';
import * as i1 from 'primeng/bind';
import { Bind } from 'primeng/bind';
import { ButtonDirective } from 'primeng/button';
import { DomHandler, blockBodyScroll, unblockBodyScroll } from 'primeng/dom';
import { FocusTrap } from 'primeng/focustrap';
import { Times } from '@primeicons/angular/times';
import { WindowMaximize } from '@primeicons/angular/window-maximize';
import { WindowMinimize } from '@primeicons/angular/window-minimize';
import * as i2 from 'primeng/motion';
import { MotionModule } from 'primeng/motion';
import { ZIndexUtils } from 'primeng/utils';
import { style } from '@primeuix/styles/dialog';
import { BaseStyle } from 'primeng/base';
/* Position */
const inlineStyles = {
mask: ({ instance }) => {
const position = instance.position();
const modal = instance.modal();
const maskStyle = instance.maskStyle();
return {
position: 'fixed',
height: '100%',
width: '100%',
left: 0,
top: 0,
display: 'flex',
justifyContent: position === 'left' || position === 'topleft' || position === 'bottomleft' ? 'flex-start' : position === 'right' || position === 'topright' || position === 'bottomright' ? 'flex-end' : 'center',
alignItems: position === 'top' || position === 'topleft' || position === 'topright' ? 'flex-start' : position === 'bottom' || position === 'bottomleft' || position === 'bottomright' ? 'flex-end' : 'center',
pointerEvents: modal ? 'auto' : 'none',
...maskStyle
};
},
root: ({ instance }) => {
const style = instance.style();
return {
display: 'flex',
flexDirection: 'column',
pointerEvents: 'auto',
...style
};
}
};
const classes = {
mask: ({ instance }) => {
const positions = ['left', 'right', 'top', 'topleft', 'topright', 'bottom', 'bottomleft', 'bottomright'];
const position = instance.position();
const pos = positions.find((item) => item === position);
return ['p-dialog-mask', { 'p-overlay-mask': instance.modal() }, pos ? `p-dialog-${pos}` : ''];
},
root: ({ instance }) => [
'p-dialog p-component',
{
'p-dialog-maximized': instance.maximizable() && instance.maximized()
}
],
header: 'p-dialog-header',
title: 'p-dialog-title',
resizeHandle: 'p-resizable-handle',
headerActions: 'p-dialog-header-actions',
pcMaximizeButton: 'p-dialog-maximize-button',
pcCloseButton: 'p-dialog-close-button',
content: () => ['p-dialog-content'],
footer: 'p-dialog-footer'
};
class DialogStyle extends BaseStyle {
name = 'dialog';
style = style;
classes = classes;
inlineStyles = inlineStyles;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DialogStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DialogStyle });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DialogStyle, decorators: [{
type: Injectable
}] });
/**
*
* Dialog is a container to display content in an overlay window.
*
* [Live Demo](https://www.primeng.org/dialog)
*
* @module dialogstyle
*
*/
var DialogClasses;
(function (DialogClasses) {
/**
* Class name of the mask element
*/
DialogClasses["mask"] = "p-dialog-mask";
/**
* Class name of the root element
*/
DialogClasses["root"] = "p-dialog";
/**
* Class name of the header element
*/
DialogClasses["header"] = "p-dialog-header";
/**
* Class name of the title element
*/
DialogClasses["title"] = "p-dialog-title";
/**
* Class name of the header actions element
*/
DialogClasses["headerActions"] = "p-dialog-header-actions";
/**
* Class name of the maximize button element
*/
DialogClasses["pcMaximizeButton"] = "p-dialog-maximize-button";
/**
* Class name of the close button element
*/
DialogClasses["pcCloseButton"] = "p-dialog-close-button";
/**
* Class name of the content element
*/
DialogClasses["content"] = "p-dialog-content";
/**
* Class name of the footer element
*/
DialogClasses["footer"] = "p-dialog-footer";
})(DialogClasses || (DialogClasses = {}));
const DIALOG_INSTANCE = new InjectionToken('DIALOG_INSTANCE');
/**
* Dialog is a container to display content in an overlay window.
* @group Components
*/
class Dialog extends BaseComponent {
componentName = 'Dialog';
hostName = input('', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "hostName" }] : /* istanbul ignore next */ []));
$pcDialog = inject(DIALOG_INSTANCE, { optional: true, skipSelf: true }) ?? undefined;
bindDirectiveInstance = inject(Bind, { self: true });
onAfterViewChecked() {
this.bindDirectiveInstance.setAttrs(this.ptm('host'));
}
/**
* Title text of the dialog.
* @group Props
*/
header = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "header" }] : /* istanbul ignore next */ []));
/**
* Enables dragging to change the position using header.
* @group Props
*/
draggable = input(true, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Enables resizing of the content.
* @group Props
*/
resizable = input(true, { ...(ngDevMode ? { debugName: "resizable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Style of the content section.
* @group Props
*/
contentStyle = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "contentStyle" }] : /* istanbul ignore next */ []));
/**
* Style class of the content.
* @group Props
*/
contentStyleClass = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "contentStyleClass" }] : /* istanbul ignore next */ []));
/**
* Defines if background should be blocked when dialog is displayed.
* @group Props
*/
modal = input(false, { ...(ngDevMode ? { debugName: "modal" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Specifies if pressing escape key should hide the dialog.
* @group Props
*/
closeOnEscape = input(true, { ...(ngDevMode ? { debugName: "closeOnEscape" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Specifies if clicking the modal background should hide the dialog.
* @group Props
*/
dismissableMask = input(false, { ...(ngDevMode ? { debugName: "dismissableMask" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* When enabled dialog is displayed in RTL direction.
* @group Props
*/
rtl = input(false, { ...(ngDevMode ? { debugName: "rtl" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Adds a close icon to the header to hide the dialog.
* @group Props
*/
closable = input(true, { ...(ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Object literal to define widths per screen size.
* @group Props
*/
breakpoints = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "breakpoints" }] : /* istanbul ignore next */ []));
/**
* Style class of the component.
* @group Props
*/
styleClass = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "styleClass" }] : /* istanbul ignore next */ []));
/**
* Style class of the mask.
* @group Props
*/
maskStyleClass = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "maskStyleClass" }] : /* istanbul ignore next */ []));
/**
* Style of the mask.
* @group Props
*/
maskStyle = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "maskStyle" }] : /* istanbul ignore next */ []));
/**
* Whether to show the header or not.
* @group Props
*/
showHeader = input(true, { ...(ngDevMode ? { debugName: "showHeader" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Whether background scroll should be blocked when dialog is visible.
* @group Props
*/
blockScroll = input(false, { ...(ngDevMode ? { debugName: "blockScroll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Whether to automatically manage layering.
* @group Props
*/
autoZIndex = input(true, { ...(ngDevMode ? { debugName: "autoZIndex" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Base zIndex value to use in layering.
* @group Props
*/
baseZIndex = input(0, { ...(ngDevMode ? { debugName: "baseZIndex" } : /* istanbul ignore next */ {}), transform: numberAttribute });
/**
* Minimum value for the left coordinate of dialog in dragging.
* @group Props
*/
minX = input(0, { ...(ngDevMode ? { debugName: "minX" } : /* istanbul ignore next */ {}), transform: numberAttribute });
/**
* Minimum value for the top coordinate of dialog in dragging.
* @group Props
*/
minY = input(0, { ...(ngDevMode ? { debugName: "minY" } : /* istanbul ignore next */ {}), transform: numberAttribute });
/**
* When enabled, first focusable element receives focus on show.
* @group Props
*/
focusOnShow = input(true, { ...(ngDevMode ? { debugName: "focusOnShow" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Whether the dialog can be displayed full screen.
* @group Props
*/
maximizable = input(false, { ...(ngDevMode ? { debugName: "maximizable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* Keeps dialog in the viewport.
* @group Props
*/
keepInViewport = input(true, { ...(ngDevMode ? { debugName: "keepInViewport" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* When enabled, can only focus on elements inside the dialog.
* @group Props
*/
focusTrap = input(true, { ...(ngDevMode ? { debugName: "focusTrap" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
/**
* The motion options for the mask.
* @group Props
*/
maskMotionOptions = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maskMotionOptions" }] : /* istanbul ignore next */ []));
computedMaskMotionOptions = computed(() => {
return {
...this.ptm('maskMotion'),
...this.maskMotionOptions()
};
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "computedMaskMotionOptions" }] : /* istanbul ignore next */ []));
maskEnterActiveClass = computed(() => (this.modal() ? 'p-overlay-mask-enter-active' : ''), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maskEnterActiveClass" }] : /* istanbul ignore next */ []));
maskLeaveActiveClass = computed(() => (this.modal() ? 'p-overlay-mask-leave-active' : ''), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maskLeaveActiveClass" }] : /* istanbul ignore next */ []));
/**
* The motion options.
* @group Props
*/
motionOptions = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "motionOptions" }] : /* istanbul ignore next */ []));
computedMotionOptions = computed(() => {
return {
...this.ptm('motion'),
...this.motionOptions()
};
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "computedMotionOptions" }] : /* istanbul ignore next */ []));
/**
* Name of the close icon.
* @group Props
*/
closeIcon = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "closeIcon" }] : /* istanbul ignore next */ []));
/**
* Defines a string that labels the close button for accessibility.
* @group Props
*/
closeAriaLabel = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "closeAriaLabel" }] : /* istanbul ignore next */ []));
/**
* Index of the close button in tabbing order.
* @group Props
*/
closeTabindex = input('0', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "closeTabindex" }] : /* istanbul ignore next */ []));
/**
* Name of the minimize icon.
* @group Props
*/
minimizeIcon = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "minimizeIcon" }] : /* istanbul ignore next */ []));
/**
* Name of the maximize icon.
* @group Props
*/
maximizeIcon = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "maximizeIcon" }] : /* istanbul ignore next */ []));
/**
* Configuration object forwarded to the underlying button.
* @group Props
*/
closeButtonProps = input({
severity: 'secondary',
variant: 'text',
rounded: true
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "closeButtonProps" }] : /* istanbul ignore next */ []));
/**
* Configuration object forwarded to the underlying button.
* @group Props
*/
maximizeButtonProps = input({
severity: 'secondary',
variant: 'text',
rounded: true
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maximizeButtonProps" }] : /* istanbul ignore next */ []));
/**
* Specifies the visibility of the dialog.
* @group Props
*/
visible = model(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
/**
* Inline style of the component.
* @group Props
*/
style = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "style" }] : /* istanbul ignore next */ []));
/**
* Position of the dialog, options are "center", "top", "bottom", "left", "right", "topleft", "topright", "bottomleft" or "bottomright".
* @group Props
*/
position = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "position" }] : /* istanbul ignore next */ []));
/**
* Role attribute of html element.
* @group Emits
*/
role = input('dialog', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
/**
* 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).
* @defaultValue 'self'
* @group Props
*/
appendTo = input(undefined, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
/**
* Callback to invoke when dialog is shown.
* @group Emits
*/
onShow = output();
/**
* Callback to invoke when dialog is hidden.
* @group Emits
*/
onHide = output();
/**
* Callback to invoke when dialog resizing is initiated.
* @param {MouseEvent} event - Mouse event.
* @group Emits
*/
onResizeInit = output();
/**
* Callback to invoke when dialog resizing is completed.
* @param {MouseEvent} event - Mouse event.
* @group Emits
*/
onResizeEnd = output();
/**
* Callback to invoke when dialog dragging is initiated.
* @param {MouseEvent} event - Mouse event.
* @group Emits
*/
onDragStart = output();
/**
* Callback to invoke when dialog dragging is completed.
* @param {DragEvent} event - Drag event.
* @group Emits
*/
onDragEnd = output();
/**
* Callback to invoke when dialog maximized or unmaximized.
* @group Emits
*/
onMaximize = output();
headerViewChild = viewChild('titlebar', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "headerViewChild" }] : /* istanbul ignore next */ []));
contentViewChild = viewChild('content', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "contentViewChild" }] : /* istanbul ignore next */ []));
footerViewChild = viewChild('footer', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "footerViewChild" }] : /* istanbul ignore next */ []));
/**
* Custom header template.
* @group Templates
*/
headerTemplate = contentChild('header', { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom content template.
* @group Templates
*/
contentTemplate = contentChild('content', { ...(ngDevMode ? { debugName: "contentTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom footer template.
* @group Templates
*/
footerTemplate = contentChild('footer', { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom close icon template.
* @group Templates
*/
closeIconTemplate = contentChild('closeicon', { ...(ngDevMode ? { debugName: "closeIconTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom maximize icon template.
* @group Templates
*/
maximizeIconTemplate = contentChild('maximizeicon', { ...(ngDevMode ? { debugName: "maximizeIconTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom minimize icon template.
* @group Templates
*/
minimizeIconTemplate = contentChild('minimizeicon', { ...(ngDevMode ? { debugName: "minimizeIconTemplate" } : /* istanbul ignore next */ {}), descendants: false });
/**
* Custom headless template.
* @group Templates
*/
headlessTemplate = contentChild('headless', { ...(ngDevMode ? { debugName: "headlessTemplate" } : /* istanbul ignore next */ {}), descendants: false });
$appendTo = computed(() => this.appendTo() || this.config.overlayAppendTo(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "$appendTo" }] : /* istanbul ignore next */ []));
renderMask = signal(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "renderMask" }] : /* istanbul ignore next */ []));
renderDialog = signal(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "renderDialog" }] : /* istanbul ignore next */ []));
maskVisible;
container = signal(null, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "container" }] : /* istanbul ignore next */ []));
wrapper;
dragging;
ariaId = uuid('pn_id_') + '_header';
ariaLabelledBy = computed(() => (this.header() !== null ? this.ariaId : null), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ []));
headerTemplateContext = computed(() => ({ ariaLabelledBy: this.ariaLabelledBy() }), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "headerTemplateContext" }] : /* istanbul ignore next */ []));
documentDragListener;
documentDragEndListener;
resizing;
documentResizeListener;
documentResizeEndListener;
documentEscapeListener;
maskClickListener;
lastPageX;
lastPageY;
preventVisibleChangePropagation;
maximized = signal(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maximized" }] : /* istanbul ignore next */ []));
preMaximizeContentHeight;
preMaximizeContainerWidth;
preMaximizeContainerHeight;
preMaximizePageX;
preMaximizePageY;
id = uuid('pn_id_');
_style = {};
originalStyle;
styleElement = null;
_componentStyle = inject(DialogStyle);
overlayService = inject(OverlayService);
zIndexForLayering;
get maximizeLabel() {
return this.translate(TranslationKeys.ARIA, 'maximizeLabel');
}
get minimizeLabel() {
return this.translate(TranslationKeys.ARIA, 'minimizeLabel');
}
maximizeButtonAriaLabel = computed(() => (this.maximized() ? this.minimizeLabel : this.maximizeLabel), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maximizeButtonAriaLabel" }] : /* istanbul ignore next */ []));
maximizeButtonTabindex = computed(() => (this.maximizable() ? '0' : '-1'), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "maximizeButtonTabindex" }] : /* istanbul ignore next */ []));
toggleIcon = computed(() => (this.maximized() ? this.minimizeIcon() : this.maximizeIcon()), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "toggleIcon" }] : /* istanbul ignore next */ []));
showToggleIcon = computed(() => !!this.maximizeIcon() && !this.maximizeIconTemplate() && !this.minimizeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showToggleIcon" }] : /* istanbul ignore next */ []));
showDefaultMaximizeIcon = computed(() => !this.maximizeIcon(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showDefaultMaximizeIcon" }] : /* istanbul ignore next */ []));
showMaximizeSvg = computed(() => !this.maximized() && !this.maximizeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showMaximizeSvg" }] : /* istanbul ignore next */ []));
showMinimizeSvg = computed(() => this.maximized() && !this.minimizeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showMinimizeSvg" }] : /* istanbul ignore next */ []));
showMaximizeIconTemplate = computed(() => !this.maximized() && !!this.maximizeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showMaximizeIconTemplate" }] : /* istanbul ignore next */ []));
showMinimizeIconTemplate = computed(() => this.maximized() && !!this.minimizeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showMinimizeIconTemplate" }] : /* istanbul ignore next */ []));
showDefaultCloseIcon = computed(() => !this.closeIconTemplate(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "showDefaultCloseIcon" }] : /* istanbul ignore next */ []));
scrollBlockerActive = computed(() => this.modal() || this.blockScroll(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "scrollBlockerActive" }] : /* istanbul ignore next */ []));
focusTrapDisabled = computed(() => this.focusTrap() === false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "focusTrapDisabled" }] : /* istanbul ignore next */ []));
constructor() {
super();
effect(() => {
const isVisible = this.visible();
untracked(() => {
if (isVisible && !this.maskVisible) {
this.maskVisible = true;
this.renderMask.set(true);
this.renderDialog.set(true);
}
});
});
}
onInit() {
if (this.breakpoints()) {
this.createStyle();
}
}
_focus(focusParentElement) {
if (focusParentElement) {
let _focusableElements = DomHandler.getFocusableElements(focusParentElement);
if (_focusableElements && _focusableElements.length > 0) {
_focusableElements[0].focus();
return true;
}
}
return false;
}
focus(focusParentElement) {
const element = focusParentElement ?? this.contentViewChild()?.nativeElement;
let focused = this._focus(element);
if (!focused) {
focused = this._focus(this.footerViewChild()?.nativeElement);
if (!focused) {
focused = this._focus(this.headerViewChild()?.nativeElement);
if (!focused) {
this._focus(this.contentViewChild()?.nativeElement);
}
}
}
}
close(event) {
this.visible.set(false);
event.preventDefault();
}
enableModality() {
this.maskClickListener = this.renderer.listen(this.wrapper, 'mousedown', (event) => {
if (this.wrapper && this.wrapper.isSameNode(event.target)) {
if (this.closable() && this.dismissableMask()) {
this.close(event);
}
else if (this.focusTrap()) {
// keep focus within the dialog so the trap is not defeated by a mask click
event.preventDefault();
}
}
});
if (this.modal()) {
blockBodyScroll();
}
}
disableModality() {
if (this.wrapper) {
this.unbindMaskClickListener();
// for nested dialogs w/modal
const scrollBlockers = document.querySelectorAll('[data-p-scrollblocker-active="true"]');
if (this.modal() && scrollBlockers && scrollBlockers.length == 1) {
unblockBodyScroll();
}
if (!this.cd.destroyed) {
this.cd.detectChanges();
}
}
}
maximize() {
this.maximized.update((v) => !v);
if (!this.modal() && !this.blockScroll()) {
if (this.maximized()) {
blockBodyScroll();
}
else {
unblockBodyScroll();
}
}
this.onMaximize.emit({ maximized: this.maximized() });
}
unbindMaskClickListener() {
if (this.maskClickListener) {
this.maskClickListener();
this.maskClickListener = null;
}
}
moveOnTop() {
if (this.autoZIndex()) {
ZIndexUtils.set('modal', this.container(), this.baseZIndex() + this.config.zIndex.modal);
this.wrapper.style.zIndex = String(parseInt(this.container().style.zIndex, 10) - 1);
}
else {
this.zIndexForLayering = ZIndexUtils.generateZIndex('modal', (this.baseZIndex() ?? 0) + this.config.zIndex.modal);
}
}
createStyle() {
if (isPlatformBrowser(this.platformId)) {
if (!this.styleElement && !this.$unstyled()) {
const styleElement = this.renderer.createElement('style');
setAttribute(styleElement, 'nonce', this.config?.csp()?.nonce);
this.renderer.appendChild(this.document.head, 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(styleElement, 'innerHTML', innerHTML);
setAttribute(styleElement, 'nonce', this.config?.csp()?.nonce);
this.styleElement = styleElement;
}
}
}
initDrag(event) {
const target = event.target;
const closestDiv = target.closest('div');
if (closestDiv?.getAttribute('data-pc-section') === 'headeractions') {
return;
}
if (this.draggable()) {
this.dragging = true;
this.lastPageX = event.pageX;
this.lastPageY = event.pageY;
this.container().style.margin = '0';
this.document.body.setAttribute('data-p-unselectable-text', 'true');
!this.$unstyled() && addStyle(this.document.body, { 'user-select': 'none' });
this.onDragStart.emit(event);
}
}
onDrag(event) {
if (this.dragging && this.container()) {
const containerWidth = getOuterWidth(this.container());
const containerHeight = getOuterHeight(this.container());
const deltaX = event.pageX - this.lastPageX;
const deltaY = event.pageY - this.lastPageY;
const offset = this.container().getBoundingClientRect();
const containerComputedStyle = getComputedStyle(this.container());
const leftMargin = parseFloat(containerComputedStyle.marginLeft);
const topMargin = parseFloat(containerComputedStyle.marginTop);
const leftPos = offset.left + deltaX - leftMargin;
const topPos = offset.top + deltaY - topMargin;
const viewport = 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`;
}
this.overlayService.emitParentDrag(this.container());
}
}
endDrag(event) {
if (this.dragging) {
this.dragging = false;
this.document.body.removeAttribute('data-p-unselectable-text');
!this.$unstyled() && (this.document.body.style['user-select'] = '');
this.cd.detectChanges();
this.onDragEnd.emit(event);
}
}
resetPosition() {
this.container().style.position = '';
this.container().style.left = '';
this.container().style.top = '';
this.container().style.margin = '';
}
//backward compatibility
center() {
this.resetPosition();
}
initResize(event) {
if (this.resizable()) {
this.resizing = true;
this.lastPageX = event.pageX;
this.lastPageY = event.pageY;
this.document.body.setAttribute('data-p-unselectable-text', 'true');
!this.$unstyled() && addStyle(this.document.body, { 'user-select': 'none' });
this.onResizeInit.emit(event);
}
}
onResize(event) {
if (this.resizing) {
let deltaX = event.pageX - this.lastPageX;
let deltaY = event.pageY - this.lastPageY;
let containerWidth = getOuterWidth(this.container());
let containerHeight = getOuterHeight(this.container());
let contentHeight = 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 = 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;
this.document.body.removeAttribute('data-p-unselectable-text');
!this.$unstyled() && (this.document.body.style['user-select'] = '');
this.onResizeEnd.emit(event);
}
}
bindGlobalListeners() {
if (this.draggable()) {
this.bindDocumentDragListener();
this.bindDocumentDragEndListener();
}
if (this.resizable()) {
this.bindDocumentResizeListeners();
}
if (this.closeOnEscape() && this.closable()) {
this.bindDocumentEscapeListener();
}
}
unbindGlobalListeners() {
this.unbindDocumentDragListener();
this.unbindDocumentDragEndListener();
this.unbindDocumentResizeListeners();
this.unbindDocumentEscapeListener();
}
bindDocumentDragListener() {
if (!this.documentDragListener) {
this.documentDragListener = this.renderer.listen(this.document.defaultView, 'mousemove', this.onDrag.bind(this));
}
}
unbindDocumentDragListener() {
if (this.documentDragListener) {
this.documentDragListener();
this.documentDragListener = null;
}
}
bindDocumentDragEndListener() {
if (!this.documentDragEndListener) {
this.documentDragEndListener = this.renderer.listen(this.document.defaultView, 'mouseup', this.endDrag.bind(this));
}
}
unbindDocumentDragEndListener() {
if (this.documentDragEndListener) {
this.documentDragEndListener();
this.documentDragEndListener = null;
}
}
bindDocumentResizeListeners() {
if (!this.documentResizeListener && !this.documentResizeEndListener) {
this.documentResizeListener = this.renderer.listen(this.document.defaultView, 'mousemove', this.onResize.bind(this));
this.documentResizeEndListener = this.renderer.listen(this.document.defaultView, 'mouseup', this.resizeEnd.bind(this));
}
}
unbindDocumentResizeListeners() {
if (this.documentResizeListener && this.documentResizeEndListener) {
this.documentResizeListener();
this.documentResizeEndListener();
this.documentResizeListener = null;
this.documentResizeEndListener = null;
}
}
bindDocumentEscapeListener() {
const documentTarget = this.el ? this.el.nativeElement.ownerDocument : this.document;
this.documentEscapeListener = this.renderer.listen(documentTarget, 'keydown', (event) => {
if (event.key == 'Escape') {
const container = this.container();
if (!container) {
return;
}
const currentZIndex = ZIndexUtils.getCurrent();
if (parseInt(container.style.zIndex) == currentZIndex || this.zIndexForLayering == currentZIndex) {
this.close(event);
}
}
});
}
unbindDocumentEscapeListener() {
if (this.documentEscapeListener) {
this.documentEscapeListener();
this.documentEscapeListener = null;
}
}
appendContainer() {
if (this.$appendTo() !== 'self') {
appendChild(this.document.body, this.wrapper);
}
}
restoreAppend() {
if (this.container() && this.$appendTo() !== 'self') {
this.renderer.appendChild(this.el.nativeElement, this.wrapper);
}
}
onBeforeEnter(event) {
this.container.set(event.element);
this.wrapper = this.container()?.parentElement;
this.$attrSelector && this.container()?.setAttribute(this.$attrSelector, '');
this.appendContainer();
this.moveOnTop();
this.bindGlobalListeners();
this.container()?.setAttribute(this.id, '');
if (this.modal()) {
this.enableModality();
}
}
onAfterEnter() {
if (this.focusOnShow()) {
this.focus();
}
this.onShow.emit({});
}
onBeforeLeave() {
if (this.modal()) {
this.maskVisible = false;
}
}
onAfterLeave() {
this.onContainerDestroy();
this.renderDialog.set(false);
if (this.modal()) {
this.renderMask.set(false);
}
else {
this.maskVisible = false;
}
this.onHide.emit({});
}
onMaskAfterLeave() {
if (!this.renderDialog()) {
this.renderMask.set(false);
}
}
onContainerDestroy() {
this.unbindGlobalListeners();
this.dragging = false;
if (this.maximized()) {
removeClass(this.document.body, 'p-overflow-hidden');
this.document.body.style.removeProperty('--px-scrollbar-width');
this.maximized.set(false);
}
if (this.modal()) {
this.disableModality();
}
const remainingScrollBlockers = this.document.querySelectorAll('[data-p-scrollblocker-active="true"]');
if (remainingScrollBlockers.length <= 1 && hasClass(this.document.body, 'p-overflow-hidden')) {
removeClass(this.document.body, 'p-overflow-hidden');
}
if (this.container() && this.autoZIndex()) {
ZIndexUtils.clear(this.container());
}
if (this.zIndexForLayering) {
ZIndexUtils.revertZIndex(this.zIndexForLayering);
}
this.container.set(null);
this.wrapper = null;
this._style = this.originalStyle ? { ...this.originalStyle } : {};
}
destroyStyle() {
if (this.styleElement) {
this.renderer.removeChild(this.document.head, this.styleElement);
this.styleElement = null;
}
}
onDestroy() {
if (this.container()) {
this.restoreAppend();
this.onContainerDestroy();
}
this.destroyStyle();
}
dataP = computed(() => this.cn({
maximized: this.maximized(),
modal: this.modal()
}), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "dataP" }] : /* istanbul ignore next */ []));
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: Dialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: Dialog, isStandalone: true, selector: "p-dialog", inputs: { hostName: { classPropertyName: "hostName", publicName: "hostName", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, contentStyle: { classPropertyName: "contentStyle", publicName: "contentStyle", isSignal: true, isRequired: false, transformFunction: null }, contentStyleClass: { classPropertyName: "contentStyleClass", publicName: "contentStyleClass", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, dismissableMask: { classPropertyName: "dismissableMask", publicName: "dismissableMask", isSignal: true, isRequired: false, transformFunction: null }, rtl: { classPropertyName: "rtl", publicName: "rtl", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, breakpoints: { classPropertyName: "breakpoints", publicName: "breakpoints", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, maskStyleClass: { classPropertyName: "maskStyleClass", publicName: "maskStyleClass", isSignal: true, isRequired: false, transformFunction: null }, maskStyle: { classPropertyName: "maskStyle", publicName: "maskStyle", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, blockScroll: { classPropertyName: "blockScroll", publicName: "blockScroll", isSignal: true, isRequired: false, transformFunction: null }, autoZIndex: { classPropertyName: "autoZIndex", publicName: "autoZIndex", isSignal: true, isRequired: false, transformFunction: null }, baseZIndex: { classPropertyName: "baseZIndex", publicName: "baseZIndex", isSignal: true, isRequired: false, transformFunction: null }, minX: { classPropertyName: "minX", publicName: "minX", isSignal: true, isRequired: false, transformFunction: null }, minY: { classPropertyName: "minY", publicName: "minY", isSignal: true, isRequired: false, transformFunction: null }, focusOnShow: { classPropertyName: "focusOnShow", publicName: "focusOnShow", isSignal: true, isRequired: false, transformFunction: null }, maximizable: { classPropertyName: "maximizable", publicName: "maximizable", isSignal: true, isRequired: false, transformFunction: null }, keepInViewport: { classPropertyName: "keepInViewport", publicName: "keepInViewport", isSignal: true, isRequired: false, transformFunction: null }, focusTrap: { classPropertyName: "focusTrap", publicName: "focusTrap", isSignal: true, isRequired: false, transformFunction: null }, maskMotionOptions: { classPropertyName: "maskMotionOptions", publicName: "maskMotionOptions", isSignal: true, isRequired: false, transformFunction: null }, motionOptions: { classPropertyName: "motionOptions", publicName: "motionOptions", isSignal: true, isRequired: false, transformFunction: null }, closeIcon: { classPropertyName: "closeIcon", publicName: "closeIcon", isSignal: true, isRequired: false, transformFunction: null }, closeAriaLabel: { classPropertyName: "closeAriaLabel", publicName: "closeAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, closeTabindex: { classPropertyName: "closeTabindex", publicName: "closeTabindex", isSignal: true, isRequired: false, transformFunction: null }, minimizeIcon: { classPropertyName: "minimizeIcon", publicName: "minimizeIcon", isSignal: true, isRequired: false, transformFunction: null }, maximizeIcon: { classPropertyName: "maximizeIcon", publicName: "maximizeIcon", isSignal: true, isRequired: false, transformFunction: null }, closeButtonProps: { classPropertyName: "closeButtonProps", publicName: "closeButtonProps", isSignal: true, isRequired: false, transformFunction: null }, maximizeButtonProps: { classPropertyName: "maximizeButtonProps", publicName: "maximizeButtonProps", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", onShow: "onShow", onHide: "onHide", onResizeInit: "onResizeInit", onResizeEnd: "onResizeEnd", onDragStart: "onDragStart", onDragEnd: "onDragEnd", onMaximize: "onMaximize" }, providers: [DialogStyle, { provide: DIALOG_INSTANCE, useExisting: Dialog }, { provide: PARENT_INSTANCE, useExisting: Dialog }], queries: [{ propertyName: "headerTemplate", first: true, predicate: ["header"], isSignal: true }, { propertyName: "contentTemplate", first: true, predicate: ["content"], isSignal: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], isSignal: true }, { propertyName: "closeIconTemplate", first: true, predicate: ["closeicon"], isSignal: true }, { propertyName: "maximizeIconTemplate", first: true, predicate: ["maximizeicon"], isSignal: true }, { propertyName: "minimizeIconTemplate", first: true, predicate: ["minimizeicon"], isSignal: true }, { propertyName: "headlessTemplate", first: true, predicate: ["headless"], isSignal: true }], viewQueries: [{ propertyName: "headerViewChild", first: true, predicate: ["titlebar"], descendants: true, isSignal: true }, { propertyName: "contentViewChild", first: true, predicate: ["content"], descendants: true, isSignal: true }, { propertyName: "footerViewChild", first: true, predicate: ["footer"], descendants: true, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.Bind }], ngImport: i0, template: `
@if (renderMask()) {
<div
[class]="cn(cx('mask'), maskStyleClass())"
[style]="sx('mask')"
[pBind]="ptm('mask')"
[pMotion]="maskVisible"
[pMotionAppear]="true"
[pMotionEnterActiveClass]="maskEnterActiveClass()"
[pMotionLeaveActiveClass]="maskLeaveActiveClass()"
[pMotionOptions]="computedMaskMotionOptions()"
(pMotionOnAfterLeave)="onMaskAfterLeave()"
[attr.data-p-scrollblocker-active]="scrollBlockerActive()"
[attr.data-p]="dataP()"
>
@if (renderDialog()) {
<div
#container
[class]="cn(cx('root'), styleClass())"
[style]="sx('root')"
[pBind]="ptm('root')"
pFocusTrap
[pFocusTrapDisabled]="focusTrapDisabled()"
[pMotion]="visible()"
[pMotionAppear]="true"
[pMotionName]="'p-dialog'"
[pMotionOptions]="computedMotionOptions()"
(pMotionOnBeforeEnter)="onBeforeEnter($event)"
(pMotionOnAfterEnter)="onAfterEnter($event)"
(pMotionOnBeforeLeave)="onBeforeLeave($event)"
(pMotionOnAfterLeave)="onAfterLeave($event)"
[attr.role]="role()"
[attr.aria-labelledby]="ariaLabelledBy()"
[attr.aria-modal]="true"
[attr.data-p]="dataP()"
>
@if (headlessTemplate()) {
<ng-container *ngTemplateOutlet="headlessTemplate()"></ng-container>
} @else {
@if (resizable()) {
<div [class]="cx('resizeHandle')" [pBind]="ptm('resizeHandle')" [style.z-index]="90" (mousedown)="initResize($event)"></div>
}
@if (showHeader()) {
<div #titlebar [class]="cx('header')" [pBind]="ptm('header')" (mousedown)="initDrag($event)">
@if (!headerTemplate()) {
<span [id]="ariaLabelledBy()" [class]="cx('title')" [pBind]="ptm('title')">{{ header() }}</span>
}
<ng-container *ngTemplateOutlet="headerTemplate(); context: headerTemplateContext()"></ng-container>
<div [class]="cx('headerActions')" [pBind]="ptm('headerActions')">
@if (maximizable()) {
<button
type="button"
iconOnly
[pButton]="maximizeButtonProps()"
[class]="cx('pcMaximizeButton')"
[tabindex]="maximizeButtonTabindex()"
[attr.aria-label]="maximizeButtonAriaLabel()"
[attr.data-pc-group-section]="'headericon'"
[pButtonPT]="ptm('pcMaximizeButton')"
[pButtonUnstyled]="unstyled()"
(click)="maximize()"
(keydown.enter)="m