@praxisui/dialog 8.0.0-beta.9 → 8.0.0-beta.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -212,6 +212,31 @@ this.dialog.openByRegistry(PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, {
212
212
  - In `alertdialog`, focuses the primary action when present
213
213
  - Restores focus on close (service and tag)
214
214
 
215
+ ## Agentic Authoring Contract
216
+
217
+ `@praxisui/dialog` publishes an executable authoring manifest for the
218
+ `praxis-dialog` shell. The manifest governs overlay configuration such as size,
219
+ position, backdrop, close policy, presets, accessibility fields and the child
220
+ host envelope.
221
+
222
+ Dialog authoring intentionally separates shell semantics from child component
223
+ semantics:
224
+
225
+ - shell operations edit `PraxisDialogConfig`
226
+ - size, position and backdrop operations are visual overlay changes
227
+ - close policy edits are explicit, confirmation-gated shell configuration
228
+ - preset operations preserve the merge order `type -> variant -> local config`
229
+ - child host operations resolve component/template ids through governed
230
+ registries
231
+ - child component config edits must be delegated to the child component
232
+ manifest through `childOperation.delegate`
233
+
234
+ This prevents the dialog manifest from becoming an ad hoc facade over table,
235
+ form, page or custom component configuration.
236
+ Each operation declares its editable target, resolver, ambiguity policy,
237
+ preconditions, validators, effects, affected paths and typed
238
+ `submissionImpact`.
239
+
215
240
  ## Theming & Styles
216
241
 
217
242
  - `themeColor: 'light' | 'dark' | 'primary'`
@@ -9,14 +9,14 @@ import * as i3 from '@angular/cdk/a11y';
9
9
  import { A11yModule } from '@angular/cdk/a11y';
10
10
  import * as i4 from '@angular/material/icon';
11
11
  import { MatIconModule } from '@angular/material/icon';
12
- import { PraxisIconDirective, PraxisLayerScaleStyleService, GlobalConfigService, GLOBAL_DIALOG_SERVICE, ComponentMetadataRegistry, GLOBAL_SURFACE_SERVICE, SURFACE_DRAWER_BRIDGE, PraxisSurfaceHostComponent } from '@praxisui/core';
12
+ import { PraxisIconDirective, PraxisLayerScaleStyleService, GlobalConfigService, GLOBAL_DIALOG_SERVICE, ComponentMetadataRegistry, GLOBAL_SURFACE_SERVICE, SurfaceOpenMaterializerService, SURFACE_DRAWER_BRIDGE, PraxisSurfaceHostComponent } from '@praxisui/core';
13
13
  import { Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
14
- import * as i2$1 from '@angular/forms';
14
+ import * as i1$1 from '@angular/forms';
15
15
  import { FormsModule } from '@angular/forms';
16
16
  import { DomSanitizer } from '@angular/platform-browser';
17
- import * as i3$1 from '@angular/material/form-field';
17
+ import * as i2$1 from '@angular/material/form-field';
18
18
  import { MatFormFieldModule } from '@angular/material/form-field';
19
- import * as i4$1 from '@angular/material/input';
19
+ import * as i3$1 from '@angular/material/input';
20
20
  import { MatInputModule } from '@angular/material/input';
21
21
 
22
22
  const PRAXIS_DIALOG_DATA = new InjectionToken('PRAXIS_DIALOG_DATA');
@@ -133,10 +133,10 @@ class PraxisDialogTitleDirective {
133
133
  constructor(templateRef) {
134
134
  this.templateRef = templateRef;
135
135
  }
136
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogTitleDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
137
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.17", type: PraxisDialogTitleDirective, isStandalone: true, selector: "ng-template[praxisDialogTitle]", ngImport: i0 });
136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogTitleDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
137
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: PraxisDialogTitleDirective, isStandalone: true, selector: "ng-template[praxisDialogTitle]", ngImport: i0 });
138
138
  }
139
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogTitleDirective, decorators: [{
139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogTitleDirective, decorators: [{
140
140
  type: Directive,
141
141
  args: [{ selector: 'ng-template[praxisDialogTitle]', standalone: true }]
142
142
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
@@ -146,10 +146,10 @@ class PraxisDialogActionsDirective {
146
146
  constructor(templateRef) {
147
147
  this.templateRef = templateRef;
148
148
  }
149
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogActionsDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
150
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.17", type: PraxisDialogActionsDirective, isStandalone: true, selector: "ng-template[praxisDialogActions]", ngImport: i0 });
149
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogActionsDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
150
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: PraxisDialogActionsDirective, isStandalone: true, selector: "ng-template[praxisDialogActions]", ngImport: i0 });
151
151
  }
152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogActionsDirective, decorators: [{
152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogActionsDirective, decorators: [{
153
153
  type: Directive,
154
154
  args: [{ selector: 'ng-template[praxisDialogActions]', standalone: true }]
155
155
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
@@ -159,10 +159,10 @@ class PraxisDialogContentDirective {
159
159
  constructor(templateRef) {
160
160
  this.templateRef = templateRef;
161
161
  }
162
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
163
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.17", type: PraxisDialogContentDirective, isStandalone: true, selector: "ng-template[praxisDialogContent]", ngImport: i0 });
162
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
163
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: PraxisDialogContentDirective, isStandalone: true, selector: "ng-template[praxisDialogContent]", ngImport: i0 });
164
164
  }
165
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogContentDirective, decorators: [{
165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogContentDirective, decorators: [{
166
166
  type: Directive,
167
167
  args: [{ selector: 'ng-template[praxisDialogContent]', standalone: true }]
168
168
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
@@ -182,6 +182,7 @@ class PraxisDialogComponent {
182
182
  themeColor = 'light';
183
183
  disableClose = false;
184
184
  hasBackdrop = true;
185
+ closeOnBackdropClick = true;
185
186
  overlayMode = false; // true when opened via service/CDK overlay
186
187
  zIndex;
187
188
  panelClass;
@@ -292,6 +293,8 @@ class PraxisDialogComponent {
292
293
  return;
293
294
  if (this.disableClose)
294
295
  return;
296
+ if (!this.closeOnBackdropClick)
297
+ return;
295
298
  // Avoid closing when clicking inside the panel area
296
299
  this.close.emit();
297
300
  }
@@ -487,12 +490,12 @@ class PraxisDialogComponent {
487
490
  return false;
488
491
  }
489
492
  }
490
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
491
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisDialogComponent, isStandalone: true, selector: "praxis-dialog", inputs: { title: "title", actions: "actions", actionsLayout: "actionsLayout", animation: "animation", open: "open", width: "width", height: "height", minWidth: "minWidth", maxWidth: "maxWidth", minHeight: "minHeight", maxHeight: "maxHeight", themeColor: "themeColor", disableClose: "disableClose", hasBackdrop: "hasBackdrop", overlayMode: "overlayMode", zIndex: "zIndex", panelClass: "panelClass", backdropClass: "backdropClass", position: "position", autoFocusedElement: "autoFocusedElement", autoFocus: "autoFocus", restoreFocus: "restoreFocus", id: "id", ariaRole: "ariaRole", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", styles: "styles", titleIcon: "titleIcon" }, outputs: { action: "action", close: "close", opened: "opened", afterClosed: "afterClosed" }, host: { properties: { "class": "this.hostClass", "attr.tabindex": "this.tabindex" } }, queries: [{ propertyName: "titleTpl", first: true, predicate: PraxisDialogTitleDirective, descendants: true, read: PraxisDialogTitleDirective }, { propertyName: "actionsTpl", first: true, predicate: PraxisDialogActionsDirective, descendants: true, read: PraxisDialogActionsDirective }, { propertyName: "contentTpl", first: true, predicate: PraxisDialogContentDirective, descendants: true, read: PraxisDialogContentDirective }], viewQueries: [{ propertyName: "contentHost", first: true, predicate: CdkPortalOutlet, descendants: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "@let _titleId = (id ?? 'praxis-dialog') + '-title';\n\n<ng-template #panelHeader>\n <div class=\"pdx-dialog__title\" @if (titleTpl?.templateRef || title || titleIcon)>\n @if (titleTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"titleTpl!.templateRef\"></ng-container>\n } @else {\n <div class=\"pdx-dialog__title-row\">\n <mat-icon *ngIf=\"titleIcon\" class=\"pdx-dialog__title-icon\" [praxisIcon]=\"titleIcon\" aria-hidden=\"true\"></mat-icon>\n <h2 class=\"pdx-dialog__title-text\" [attr.id]=\"_titleId\">{{ title }}</h2>\n </div>\n }\n </div>\n </ng-template>\n\n<ng-template #panelActions>\n <div class=\"pdx-dialog__actions\" [class.is-stretched]=\"actionsLayout==='stretched'\">\n @if (actionsTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"actionsTpl!.templateRef\"></ng-container>\n } @else {\n @for (a of actions; track a?.id ?? a) {\n <button\n type=\"button\"\n class=\"pdx-dialog__action-btn\"\n [attr.data-testid]=\"a.id || null\"\n [attr.data-role]=\"a.role || null\"\n [attr.data-theme]=\"a.themeColor || null\"\n [attr.data-fill]=\"a.fillMode || null\"\n [ngClass]=\"a.cssClass\"\n (click)=\"onActionClick(a)\"\n [attr.cdkFocusInitial]=\"a.role==='primary' && ariaRole==='alertdialog' ? '' : null\"\n >\n @if (a.icon) {\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n } @else if (a.svgIcon) {\n <mat-icon [svgIcon]=\"a.svgIcon\"></mat-icon>\n }\n {{ a.text }}\n </button>\n }\n }\n </div>\n</ng-template>\n\n@if (overlayMode) {\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n} @else {\n <div class=\"pdx-dialog-overlay\" [class.has-backdrop]=\"hasBackdrop\" [hidden]=\"!isDisplayed\" (click)=\"onBackdrop($event)\" [ngClass]=\"backdropClass\" [style.z-index]=\"zIndex\">\n <div class=\"pdx-dialog-shell\" (click)=\"$event.stopPropagation()\">\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [style.top]=\"position?.top || null\"\n [style.bottom]=\"position?.bottom || null\"\n [style.left]=\"position?.left || null\"\n [style.right]=\"position?.right || null\"\n [class.pdx-has-position]=\"position\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.pdx-dialog-host{--pdx-dialog-bg: var(--md-sys-color-surface);--pdx-dialog-surface: var(--md-sys-color-surface-container-high);--pdx-dialog-border: var(--md-sys-color-outline-variant);--pdx-dialog-title-fg: var(--md-sys-color-on-surface);--pdx-dialog-elevation: var(--mat-elevation-level4)}.pdx-dialog-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:var(--praxis-layer-dialog, 1300);background:transparent}.pdx-dialog-overlay.has-backdrop{background:var(--pdx-dialog-backdrop, rgba(0, 0, 0, .6))}.pdx-dialog-shell{display:contents}.pdx-dialog.pdx-has-position{position:absolute}.pdx-dialog{background:var(--pdx-dialog-container-color, var(--pdx-dialog-surface));color:var(--md-sys-color-on-surface, #111);border:1px solid var(--pdx-dialog-border);border-radius:var(--pdx-dialog-shape, 16px);box-shadow:var(--pdx-dialog-elevation-shadow, var(--pdx-dialog-elevation));max-width:var(--pdx-dialog-max-width, 90vw);max-height:var(--pdx-dialog-max-height, 80vh);display:flex;flex-direction:column;min-width:var(--pdx-dialog-min-width, 280px);outline:0}.pdx-dialog__title{padding:var(--pdx-dialog-headline-padding, 12px 24px 10px);border-bottom:1px solid var(--pdx-dialog-border);color:var(--pdx-dialog-subhead-color, var(--pdx-dialog-title-fg));background:var(--pdx-dialog-title-bg, transparent);flex:0 0 auto}.pdx-dialog__title-row{display:flex;gap:10px}.pdx-dialog__title-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:0 0 24px;font-size:20px;line-height:1;opacity:.87}.pdx-dialog__title-text{margin:0;font-family:var(--pdx-dialog-subhead-font, inherit);font-size:var(--pdx-dialog-subhead-size, 16px);letter-spacing:var(--pdx-dialog-subhead-tracking, normal);font-weight:var(--pdx-dialog-subhead-weight, 600);line-height:1.2}.pdx-dialog__content{padding:var(--pdx-dialog-content-padding, 16px);overflow:auto;flex:1 1 auto;min-height:0;color:var(--pdx-dialog-supporting-text-color, inherit);font-family:var(--pdx-dialog-supporting-text-font, inherit);line-height:var(--pdx-dialog-supporting-text-line-height, 1.4);font-size:var(--pdx-dialog-supporting-text-size, 14px);letter-spacing:var(--pdx-dialog-supporting-text-tracking, normal);font-weight:var(--pdx-dialog-supporting-text-weight, 400)}.pdx-dialog.has-actions .pdx-dialog__content{padding-bottom:var(--pdx-dialog-with-actions-content-padding, var(--pdx-dialog-content-padding, 16px))}.pdx-dialog__actions{display:flex;gap:8px;padding:var(--pdx-dialog-actions-padding, 12px 24px 16px);border-top:1px solid var(--pdx-dialog-border);justify-content:flex-end;align-items:center;background:var(--pdx-dialog-actions-bg, transparent);flex:0 0 auto}.pdx-dialog__actions.is-stretched{justify-content:stretch}.pdx-dialog__actions.is-stretched .pdx-dialog__action-btn{flex:1 1 0;justify-content:center}.pdx-dialog__action-btn{appearance:none;border:1px solid var(--pdx-dialog-border);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-radius:var(--pdx-dialog-action-radius, 8px);padding:var(--pdx-dialog-action-padding, 0 14px);min-height:var(--pdx-dialog-action-min-height, 36px);cursor:pointer;display:inline-flex;align-items:center;gap:8px;line-height:1;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-dialog__action-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-dialog__action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-dialog__action-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid]{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid]:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary-container)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid][data-theme=warn],.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]{background:var(--md-sys-color-error);border-color:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid][data-theme=warn]:hover,.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]:hover{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error-container)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent],.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]{background:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent]:hover,.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]:hover{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary-container)}.pdx-dialog__action-btn[data-fill=outline]{background:transparent;color:var(--md-sys-color-on-surface)}.pdx-dialog__action-btn[data-fill=outline][data-theme=primary],.pdx-dialog__action-btn[data-fill=flat][data-theme=primary]{color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=accent],.pdx-dialog__action-btn[data-fill=flat][data-theme=accent]{color:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=warn],.pdx-dialog__action-btn[data-fill=flat][data-theme=warn]{color:var(--md-sys-color-error);border-color:var(--md-sys-color-error)}.pdx-dialog__action-btn[data-fill=flat]{background:transparent;border-color:transparent;color:var(--md-sys-color-primary)}.pdx-dialog__action-btn .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.pdx-dialog--primary .pdx-dialog__title{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-bottom-color:var(--md-sys-color-outline-variant)}.pdx-dialog--dark{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.pdx-dialog{transform-origin:center;transition-property:transform,opacity;transition-duration:var(--pdx-dialog-anim-duration, .3s);transition-timing-function:var(--pdx-dialog-anim-ease, cubic-bezier(.2, 0, 0, 1))}.pdx-dialog.pdx-anim-fade{opacity:1}.pdx-dialog.pdx-anim-zoom{transform:scale(1)}.pdx-dialog.pdx-anim-translate-up,.pdx-dialog.pdx-anim-translate-down{transform:translateY(0)}.pdx-dialog.pdx-anim-translate-left,.pdx-dialog.pdx-anim-translate-right{transform:translate(0)}.pdx-dialog.pdx-state-opening.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-right{transform:translate(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-right{transform:translate(16px);opacity:0}@media(prefers-reduced-motion:reduce){.pdx-dialog{transition:none!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i2.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
493
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
494
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDialogComponent, isStandalone: true, selector: "praxis-dialog", inputs: { title: "title", actions: "actions", actionsLayout: "actionsLayout", animation: "animation", open: "open", width: "width", height: "height", minWidth: "minWidth", maxWidth: "maxWidth", minHeight: "minHeight", maxHeight: "maxHeight", themeColor: "themeColor", disableClose: "disableClose", hasBackdrop: "hasBackdrop", closeOnBackdropClick: "closeOnBackdropClick", overlayMode: "overlayMode", zIndex: "zIndex", panelClass: "panelClass", backdropClass: "backdropClass", position: "position", autoFocusedElement: "autoFocusedElement", autoFocus: "autoFocus", restoreFocus: "restoreFocus", id: "id", ariaRole: "ariaRole", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", styles: "styles", titleIcon: "titleIcon" }, outputs: { action: "action", close: "close", opened: "opened", afterClosed: "afterClosed" }, host: { properties: { "class": "this.hostClass", "attr.tabindex": "this.tabindex" } }, queries: [{ propertyName: "titleTpl", first: true, predicate: PraxisDialogTitleDirective, descendants: true, read: PraxisDialogTitleDirective }, { propertyName: "actionsTpl", first: true, predicate: PraxisDialogActionsDirective, descendants: true, read: PraxisDialogActionsDirective }, { propertyName: "contentTpl", first: true, predicate: PraxisDialogContentDirective, descendants: true, read: PraxisDialogContentDirective }], viewQueries: [{ propertyName: "contentHost", first: true, predicate: CdkPortalOutlet, descendants: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "@let _titleId = (id ?? 'praxis-dialog') + '-title';\n\n<ng-template #panelHeader>\n @if (titleTpl?.templateRef || title || titleIcon) {\n <div class=\"pdx-dialog__title\">\n @if (titleTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"titleTpl!.templateRef\"></ng-container>\n } @else {\n <div class=\"pdx-dialog__title-row\">\n @if (titleIcon) {\n <mat-icon class=\"pdx-dialog__title-icon\" [praxisIcon]=\"titleIcon\" aria-hidden=\"true\"></mat-icon>\n }\n <h2 class=\"pdx-dialog__title-text\" [attr.id]=\"_titleId\">{{ title }}</h2>\n </div>\n }\n </div>\n }\n</ng-template>\n\n<ng-template #panelActions>\n <div class=\"pdx-dialog__actions\" [class.is-stretched]=\"actionsLayout==='stretched'\">\n @if (actionsTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"actionsTpl!.templateRef\"></ng-container>\n } @else {\n @for (a of actions; track a?.id ?? a) {\n <button\n type=\"button\"\n class=\"pdx-dialog__action-btn\"\n [attr.data-testid]=\"a.id || null\"\n [attr.data-role]=\"a.role || null\"\n [attr.data-theme]=\"a.themeColor || null\"\n [attr.data-fill]=\"a.fillMode || null\"\n [ngClass]=\"a.cssClass\"\n (click)=\"onActionClick(a)\"\n [attr.cdkFocusInitial]=\"a.role==='primary' && ariaRole==='alertdialog' ? '' : null\"\n >\n @if (a.icon) {\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n } @else if (a.svgIcon) {\n <mat-icon [svgIcon]=\"a.svgIcon\"></mat-icon>\n }\n {{ a.text }}\n </button>\n }\n }\n </div>\n</ng-template>\n\n@if (overlayMode) {\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n} @else {\n <div class=\"pdx-dialog-overlay\" [class.has-backdrop]=\"hasBackdrop\" [hidden]=\"!isDisplayed\" (click)=\"onBackdrop($event)\" [ngClass]=\"backdropClass\" [style.z-index]=\"zIndex\">\n <div class=\"pdx-dialog-shell\" (click)=\"$event.stopPropagation()\">\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [style.top]=\"position?.top || null\"\n [style.bottom]=\"position?.bottom || null\"\n [style.left]=\"position?.left || null\"\n [style.right]=\"position?.right || null\"\n [class.pdx-has-position]=\"position\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.pdx-dialog-host{--pdx-dialog-bg: var(--md-sys-color-surface);--pdx-dialog-surface: var(--md-sys-color-surface-container-high);--pdx-dialog-border: var(--md-sys-color-outline-variant);--pdx-dialog-title-fg: var(--md-sys-color-on-surface);--pdx-dialog-elevation: var(--mat-elevation-level4)}.pdx-dialog-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:var(--praxis-layer-dialog, 1300);background:transparent}.pdx-dialog-overlay.has-backdrop{background:var(--pdx-dialog-backdrop, rgba(0, 0, 0, .6))}.pdx-dialog-shell{display:contents}.pdx-dialog.pdx-has-position{position:absolute}.pdx-dialog{background:var(--pdx-dialog-container-color, var(--pdx-dialog-surface));color:var(--md-sys-color-on-surface, #111);border:1px solid var(--pdx-dialog-border);border-radius:var(--pdx-dialog-shape, 16px);box-shadow:var(--pdx-dialog-elevation-shadow, var(--pdx-dialog-elevation));max-width:var(--pdx-dialog-max-width, 90vw);max-height:var(--pdx-dialog-max-height, 80vh);display:flex;flex-direction:column;min-width:var(--pdx-dialog-min-width, 280px);outline:0}.pdx-dialog__title{padding:var(--pdx-dialog-headline-padding, 12px 24px 10px);border-bottom:1px solid var(--pdx-dialog-border);color:var(--pdx-dialog-subhead-color, var(--pdx-dialog-title-fg));background:var(--pdx-dialog-title-bg, transparent);flex:0 0 auto}.pdx-dialog__title-row{display:flex;gap:10px}.pdx-dialog__title-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:0 0 24px;font-size:20px;line-height:1;opacity:.87}.pdx-dialog__title-text{margin:0;font-family:var(--pdx-dialog-subhead-font, inherit);font-size:var(--pdx-dialog-subhead-size, 16px);letter-spacing:var(--pdx-dialog-subhead-tracking, normal);font-weight:var(--pdx-dialog-subhead-weight, 600);line-height:1.2}.pdx-dialog__content{padding:var(--pdx-dialog-content-padding, 16px);overflow:auto;flex:1 1 auto;min-height:0;color:var(--pdx-dialog-supporting-text-color, inherit);font-family:var(--pdx-dialog-supporting-text-font, inherit);line-height:var(--pdx-dialog-supporting-text-line-height, 1.4);font-size:var(--pdx-dialog-supporting-text-size, 14px);letter-spacing:var(--pdx-dialog-supporting-text-tracking, normal);font-weight:var(--pdx-dialog-supporting-text-weight, 400)}.pdx-dialog.has-actions .pdx-dialog__content{padding-bottom:var(--pdx-dialog-with-actions-content-padding, var(--pdx-dialog-content-padding, 16px))}.pdx-dialog__actions{display:flex;gap:8px;padding:var(--pdx-dialog-actions-padding, 12px 24px 16px);border-top:1px solid var(--pdx-dialog-border);justify-content:flex-end;align-items:center;background:var(--pdx-dialog-actions-bg, transparent);flex:0 0 auto}.pdx-dialog__actions.is-stretched{justify-content:stretch}.pdx-dialog__actions.is-stretched .pdx-dialog__action-btn{flex:1 1 0;justify-content:center}.pdx-dialog__action-btn{appearance:none;border:1px solid var(--pdx-dialog-border);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-radius:var(--pdx-dialog-action-radius, 8px);padding:var(--pdx-dialog-action-padding, 0 14px);min-height:var(--pdx-dialog-action-min-height, 36px);cursor:pointer;display:inline-flex;align-items:center;gap:8px;line-height:1;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-dialog__action-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-dialog__action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-dialog__action-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid]{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid]:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary-container)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid][data-theme=warn],.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]{background:var(--md-sys-color-error);border-color:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid][data-theme=warn]:hover,.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]:hover{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error-container)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent],.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]{background:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent]:hover,.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]:hover{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary-container)}.pdx-dialog__action-btn[data-fill=outline]{background:transparent;color:var(--md-sys-color-on-surface)}.pdx-dialog__action-btn[data-fill=outline][data-theme=primary],.pdx-dialog__action-btn[data-fill=flat][data-theme=primary]{color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=accent],.pdx-dialog__action-btn[data-fill=flat][data-theme=accent]{color:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=warn],.pdx-dialog__action-btn[data-fill=flat][data-theme=warn]{color:var(--md-sys-color-error);border-color:var(--md-sys-color-error)}.pdx-dialog__action-btn[data-fill=flat]{background:transparent;border-color:transparent;color:var(--md-sys-color-primary)}.pdx-dialog__action-btn .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.pdx-dialog--primary .pdx-dialog__title{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-bottom-color:var(--md-sys-color-outline-variant)}.pdx-dialog--dark{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.pdx-dialog{transform-origin:center;transition-property:transform,opacity;transition-duration:var(--pdx-dialog-anim-duration, .3s);transition-timing-function:var(--pdx-dialog-anim-ease, cubic-bezier(.2, 0, 0, 1))}.pdx-dialog.pdx-anim-fade{opacity:1}.pdx-dialog.pdx-anim-zoom{transform:scale(1)}.pdx-dialog.pdx-anim-translate-up,.pdx-dialog.pdx-anim-translate-down{transform:translateY(0)}.pdx-dialog.pdx-anim-translate-left,.pdx-dialog.pdx-anim-translate-right{transform:translate(0)}.pdx-dialog.pdx-state-opening.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-right{transform:translate(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-right{transform:translate(16px);opacity:0}@media(prefers-reduced-motion:reduce){.pdx-dialog{transition:none!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i2.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
492
495
  }
493
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialogComponent, decorators: [{
496
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialogComponent, decorators: [{
494
497
  type: Component,
495
- args: [{ selector: 'praxis-dialog', standalone: true, imports: [CommonModule, PortalModule, A11yModule, MatIconModule, PraxisIconDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@let _titleId = (id ?? 'praxis-dialog') + '-title';\n\n<ng-template #panelHeader>\n <div class=\"pdx-dialog__title\" @if (titleTpl?.templateRef || title || titleIcon)>\n @if (titleTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"titleTpl!.templateRef\"></ng-container>\n } @else {\n <div class=\"pdx-dialog__title-row\">\n <mat-icon *ngIf=\"titleIcon\" class=\"pdx-dialog__title-icon\" [praxisIcon]=\"titleIcon\" aria-hidden=\"true\"></mat-icon>\n <h2 class=\"pdx-dialog__title-text\" [attr.id]=\"_titleId\">{{ title }}</h2>\n </div>\n }\n </div>\n </ng-template>\n\n<ng-template #panelActions>\n <div class=\"pdx-dialog__actions\" [class.is-stretched]=\"actionsLayout==='stretched'\">\n @if (actionsTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"actionsTpl!.templateRef\"></ng-container>\n } @else {\n @for (a of actions; track a?.id ?? a) {\n <button\n type=\"button\"\n class=\"pdx-dialog__action-btn\"\n [attr.data-testid]=\"a.id || null\"\n [attr.data-role]=\"a.role || null\"\n [attr.data-theme]=\"a.themeColor || null\"\n [attr.data-fill]=\"a.fillMode || null\"\n [ngClass]=\"a.cssClass\"\n (click)=\"onActionClick(a)\"\n [attr.cdkFocusInitial]=\"a.role==='primary' && ariaRole==='alertdialog' ? '' : null\"\n >\n @if (a.icon) {\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n } @else if (a.svgIcon) {\n <mat-icon [svgIcon]=\"a.svgIcon\"></mat-icon>\n }\n {{ a.text }}\n </button>\n }\n }\n </div>\n</ng-template>\n\n@if (overlayMode) {\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n} @else {\n <div class=\"pdx-dialog-overlay\" [class.has-backdrop]=\"hasBackdrop\" [hidden]=\"!isDisplayed\" (click)=\"onBackdrop($event)\" [ngClass]=\"backdropClass\" [style.z-index]=\"zIndex\">\n <div class=\"pdx-dialog-shell\" (click)=\"$event.stopPropagation()\">\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [style.top]=\"position?.top || null\"\n [style.bottom]=\"position?.bottom || null\"\n [style.left]=\"position?.left || null\"\n [style.right]=\"position?.right || null\"\n [class.pdx-has-position]=\"position\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.pdx-dialog-host{--pdx-dialog-bg: var(--md-sys-color-surface);--pdx-dialog-surface: var(--md-sys-color-surface-container-high);--pdx-dialog-border: var(--md-sys-color-outline-variant);--pdx-dialog-title-fg: var(--md-sys-color-on-surface);--pdx-dialog-elevation: var(--mat-elevation-level4)}.pdx-dialog-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:var(--praxis-layer-dialog, 1300);background:transparent}.pdx-dialog-overlay.has-backdrop{background:var(--pdx-dialog-backdrop, rgba(0, 0, 0, .6))}.pdx-dialog-shell{display:contents}.pdx-dialog.pdx-has-position{position:absolute}.pdx-dialog{background:var(--pdx-dialog-container-color, var(--pdx-dialog-surface));color:var(--md-sys-color-on-surface, #111);border:1px solid var(--pdx-dialog-border);border-radius:var(--pdx-dialog-shape, 16px);box-shadow:var(--pdx-dialog-elevation-shadow, var(--pdx-dialog-elevation));max-width:var(--pdx-dialog-max-width, 90vw);max-height:var(--pdx-dialog-max-height, 80vh);display:flex;flex-direction:column;min-width:var(--pdx-dialog-min-width, 280px);outline:0}.pdx-dialog__title{padding:var(--pdx-dialog-headline-padding, 12px 24px 10px);border-bottom:1px solid var(--pdx-dialog-border);color:var(--pdx-dialog-subhead-color, var(--pdx-dialog-title-fg));background:var(--pdx-dialog-title-bg, transparent);flex:0 0 auto}.pdx-dialog__title-row{display:flex;gap:10px}.pdx-dialog__title-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:0 0 24px;font-size:20px;line-height:1;opacity:.87}.pdx-dialog__title-text{margin:0;font-family:var(--pdx-dialog-subhead-font, inherit);font-size:var(--pdx-dialog-subhead-size, 16px);letter-spacing:var(--pdx-dialog-subhead-tracking, normal);font-weight:var(--pdx-dialog-subhead-weight, 600);line-height:1.2}.pdx-dialog__content{padding:var(--pdx-dialog-content-padding, 16px);overflow:auto;flex:1 1 auto;min-height:0;color:var(--pdx-dialog-supporting-text-color, inherit);font-family:var(--pdx-dialog-supporting-text-font, inherit);line-height:var(--pdx-dialog-supporting-text-line-height, 1.4);font-size:var(--pdx-dialog-supporting-text-size, 14px);letter-spacing:var(--pdx-dialog-supporting-text-tracking, normal);font-weight:var(--pdx-dialog-supporting-text-weight, 400)}.pdx-dialog.has-actions .pdx-dialog__content{padding-bottom:var(--pdx-dialog-with-actions-content-padding, var(--pdx-dialog-content-padding, 16px))}.pdx-dialog__actions{display:flex;gap:8px;padding:var(--pdx-dialog-actions-padding, 12px 24px 16px);border-top:1px solid var(--pdx-dialog-border);justify-content:flex-end;align-items:center;background:var(--pdx-dialog-actions-bg, transparent);flex:0 0 auto}.pdx-dialog__actions.is-stretched{justify-content:stretch}.pdx-dialog__actions.is-stretched .pdx-dialog__action-btn{flex:1 1 0;justify-content:center}.pdx-dialog__action-btn{appearance:none;border:1px solid var(--pdx-dialog-border);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-radius:var(--pdx-dialog-action-radius, 8px);padding:var(--pdx-dialog-action-padding, 0 14px);min-height:var(--pdx-dialog-action-min-height, 36px);cursor:pointer;display:inline-flex;align-items:center;gap:8px;line-height:1;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-dialog__action-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-dialog__action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-dialog__action-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid]{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid]:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary-container)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid][data-theme=warn],.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]{background:var(--md-sys-color-error);border-color:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid][data-theme=warn]:hover,.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]:hover{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error-container)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent],.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]{background:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent]:hover,.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]:hover{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary-container)}.pdx-dialog__action-btn[data-fill=outline]{background:transparent;color:var(--md-sys-color-on-surface)}.pdx-dialog__action-btn[data-fill=outline][data-theme=primary],.pdx-dialog__action-btn[data-fill=flat][data-theme=primary]{color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=accent],.pdx-dialog__action-btn[data-fill=flat][data-theme=accent]{color:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=warn],.pdx-dialog__action-btn[data-fill=flat][data-theme=warn]{color:var(--md-sys-color-error);border-color:var(--md-sys-color-error)}.pdx-dialog__action-btn[data-fill=flat]{background:transparent;border-color:transparent;color:var(--md-sys-color-primary)}.pdx-dialog__action-btn .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.pdx-dialog--primary .pdx-dialog__title{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-bottom-color:var(--md-sys-color-outline-variant)}.pdx-dialog--dark{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.pdx-dialog{transform-origin:center;transition-property:transform,opacity;transition-duration:var(--pdx-dialog-anim-duration, .3s);transition-timing-function:var(--pdx-dialog-anim-ease, cubic-bezier(.2, 0, 0, 1))}.pdx-dialog.pdx-anim-fade{opacity:1}.pdx-dialog.pdx-anim-zoom{transform:scale(1)}.pdx-dialog.pdx-anim-translate-up,.pdx-dialog.pdx-anim-translate-down{transform:translateY(0)}.pdx-dialog.pdx-anim-translate-left,.pdx-dialog.pdx-anim-translate-right{transform:translate(0)}.pdx-dialog.pdx-state-opening.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-right{transform:translate(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-right{transform:translate(16px);opacity:0}@media(prefers-reduced-motion:reduce){.pdx-dialog{transition:none!important}}\n"] }]
498
+ args: [{ selector: 'praxis-dialog', standalone: true, imports: [CommonModule, PortalModule, A11yModule, MatIconModule, PraxisIconDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@let _titleId = (id ?? 'praxis-dialog') + '-title';\n\n<ng-template #panelHeader>\n @if (titleTpl?.templateRef || title || titleIcon) {\n <div class=\"pdx-dialog__title\">\n @if (titleTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"titleTpl!.templateRef\"></ng-container>\n } @else {\n <div class=\"pdx-dialog__title-row\">\n @if (titleIcon) {\n <mat-icon class=\"pdx-dialog__title-icon\" [praxisIcon]=\"titleIcon\" aria-hidden=\"true\"></mat-icon>\n }\n <h2 class=\"pdx-dialog__title-text\" [attr.id]=\"_titleId\">{{ title }}</h2>\n </div>\n }\n </div>\n }\n</ng-template>\n\n<ng-template #panelActions>\n <div class=\"pdx-dialog__actions\" [class.is-stretched]=\"actionsLayout==='stretched'\">\n @if (actionsTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"actionsTpl!.templateRef\"></ng-container>\n } @else {\n @for (a of actions; track a?.id ?? a) {\n <button\n type=\"button\"\n class=\"pdx-dialog__action-btn\"\n [attr.data-testid]=\"a.id || null\"\n [attr.data-role]=\"a.role || null\"\n [attr.data-theme]=\"a.themeColor || null\"\n [attr.data-fill]=\"a.fillMode || null\"\n [ngClass]=\"a.cssClass\"\n (click)=\"onActionClick(a)\"\n [attr.cdkFocusInitial]=\"a.role==='primary' && ariaRole==='alertdialog' ? '' : null\"\n >\n @if (a.icon) {\n <mat-icon [praxisIcon]=\"a.icon\"></mat-icon>\n } @else if (a.svgIcon) {\n <mat-icon [svgIcon]=\"a.svgIcon\"></mat-icon>\n }\n {{ a.text }}\n </button>\n }\n }\n </div>\n</ng-template>\n\n@if (overlayMode) {\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n} @else {\n <div class=\"pdx-dialog-overlay\" [class.has-backdrop]=\"hasBackdrop\" [hidden]=\"!isDisplayed\" (click)=\"onBackdrop($event)\" [ngClass]=\"backdropClass\" [style.z-index]=\"zIndex\">\n <div class=\"pdx-dialog-shell\" (click)=\"$event.stopPropagation()\">\n <div\n #panel\n class=\"pdx-dialog pdx-dialog--{{ themeColor }} pdx-dialog--layout-{{ actionsLayout }}\"\n [attr.role]=\"ariaRole\"\n [attr.id]=\"id || null\"\n [attr.aria-modal]=\"true\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"(ariaLabelledBy || (title ? _titleId : null))\"\n [attr.aria-describedby]=\"ariaDescribedBy || null\"\n (keydown)=\"onKeydown($event)\"\n cdkTrapFocus\n [ngClass]=\"panelNgClass\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n [style.min-width]=\"minWidth\"\n [style.max-width]=\"maxWidth\"\n [style.min-height]=\"minHeight\"\n [style.max-height]=\"maxHeight\"\n [style.top]=\"position?.top || null\"\n [style.bottom]=\"position?.bottom || null\"\n [style.left]=\"position?.left || null\"\n [style.right]=\"position?.right || null\"\n [class.pdx-has-position]=\"position\"\n [class.has-actions]=\"(actions.length||0)>0 || !!actionsTpl?.templateRef\"\n >\n <ng-container [ngTemplateOutlet]=\"panelHeader\"></ng-container>\n <div class=\"pdx-dialog__content\">\n @if (contentTpl?.templateRef) {\n <ng-container [ngTemplateOutlet]=\"contentTpl!.templateRef\"></ng-container>\n } @else {\n <ng-template cdkPortalOutlet></ng-template>\n }\n </div>\n <ng-container [ngTemplateOutlet]=\"panelActions\"></ng-container>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.pdx-dialog-host{--pdx-dialog-bg: var(--md-sys-color-surface);--pdx-dialog-surface: var(--md-sys-color-surface-container-high);--pdx-dialog-border: var(--md-sys-color-outline-variant);--pdx-dialog-title-fg: var(--md-sys-color-on-surface);--pdx-dialog-elevation: var(--mat-elevation-level4)}.pdx-dialog-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:var(--praxis-layer-dialog, 1300);background:transparent}.pdx-dialog-overlay.has-backdrop{background:var(--pdx-dialog-backdrop, rgba(0, 0, 0, .6))}.pdx-dialog-shell{display:contents}.pdx-dialog.pdx-has-position{position:absolute}.pdx-dialog{background:var(--pdx-dialog-container-color, var(--pdx-dialog-surface));color:var(--md-sys-color-on-surface, #111);border:1px solid var(--pdx-dialog-border);border-radius:var(--pdx-dialog-shape, 16px);box-shadow:var(--pdx-dialog-elevation-shadow, var(--pdx-dialog-elevation));max-width:var(--pdx-dialog-max-width, 90vw);max-height:var(--pdx-dialog-max-height, 80vh);display:flex;flex-direction:column;min-width:var(--pdx-dialog-min-width, 280px);outline:0}.pdx-dialog__title{padding:var(--pdx-dialog-headline-padding, 12px 24px 10px);border-bottom:1px solid var(--pdx-dialog-border);color:var(--pdx-dialog-subhead-color, var(--pdx-dialog-title-fg));background:var(--pdx-dialog-title-bg, transparent);flex:0 0 auto}.pdx-dialog__title-row{display:flex;gap:10px}.pdx-dialog__title-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:0 0 24px;font-size:20px;line-height:1;opacity:.87}.pdx-dialog__title-text{margin:0;font-family:var(--pdx-dialog-subhead-font, inherit);font-size:var(--pdx-dialog-subhead-size, 16px);letter-spacing:var(--pdx-dialog-subhead-tracking, normal);font-weight:var(--pdx-dialog-subhead-weight, 600);line-height:1.2}.pdx-dialog__content{padding:var(--pdx-dialog-content-padding, 16px);overflow:auto;flex:1 1 auto;min-height:0;color:var(--pdx-dialog-supporting-text-color, inherit);font-family:var(--pdx-dialog-supporting-text-font, inherit);line-height:var(--pdx-dialog-supporting-text-line-height, 1.4);font-size:var(--pdx-dialog-supporting-text-size, 14px);letter-spacing:var(--pdx-dialog-supporting-text-tracking, normal);font-weight:var(--pdx-dialog-supporting-text-weight, 400)}.pdx-dialog.has-actions .pdx-dialog__content{padding-bottom:var(--pdx-dialog-with-actions-content-padding, var(--pdx-dialog-content-padding, 16px))}.pdx-dialog__actions{display:flex;gap:8px;padding:var(--pdx-dialog-actions-padding, 12px 24px 16px);border-top:1px solid var(--pdx-dialog-border);justify-content:flex-end;align-items:center;background:var(--pdx-dialog-actions-bg, transparent);flex:0 0 auto}.pdx-dialog__actions.is-stretched{justify-content:stretch}.pdx-dialog__actions.is-stretched .pdx-dialog__action-btn{flex:1 1 0;justify-content:center}.pdx-dialog__action-btn{appearance:none;border:1px solid var(--pdx-dialog-border);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);border-radius:var(--pdx-dialog-action-radius, 8px);padding:var(--pdx-dialog-action-padding, 0 14px);min-height:var(--pdx-dialog-action-min-height, 36px);cursor:pointer;display:inline-flex;align-items:center;gap:8px;line-height:1;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-dialog__action-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-dialog__action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-dialog__action-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid]{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-dialog__action-btn[data-role=primary]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid]:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary-container)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]),.pdx-dialog__action-btn[data-fill=solid][data-theme=warn],.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]{background:var(--md-sys-color-error);border-color:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}.pdx-dialog__action-btn[data-role=danger]:not([data-fill]):hover,.pdx-dialog__action-btn[data-fill=solid][data-theme=warn]:hover,.pdx-dialog__action-btn[data-theme=warn][data-fill=solid]:hover{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error-container)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent],.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]{background:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary);color:var(--md-sys-color-on-secondary)}.pdx-dialog__action-btn[data-fill=solid][data-theme=accent]:hover,.pdx-dialog__action-btn[data-theme=accent][data-fill=solid]:hover{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary-container)}.pdx-dialog__action-btn[data-fill=outline]{background:transparent;color:var(--md-sys-color-on-surface)}.pdx-dialog__action-btn[data-fill=outline][data-theme=primary],.pdx-dialog__action-btn[data-fill=flat][data-theme=primary]{color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=accent],.pdx-dialog__action-btn[data-fill=flat][data-theme=accent]{color:var(--md-sys-color-secondary);border-color:var(--md-sys-color-secondary)}.pdx-dialog__action-btn[data-fill=outline][data-theme=warn],.pdx-dialog__action-btn[data-fill=flat][data-theme=warn]{color:var(--md-sys-color-error);border-color:var(--md-sys-color-error)}.pdx-dialog__action-btn[data-fill=flat]{background:transparent;border-color:transparent;color:var(--md-sys-color-primary)}.pdx-dialog__action-btn .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.pdx-dialog--primary .pdx-dialog__title{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-bottom-color:var(--md-sys-color-outline-variant)}.pdx-dialog--dark{background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.pdx-dialog{transform-origin:center;transition-property:transform,opacity;transition-duration:var(--pdx-dialog-anim-duration, .3s);transition-timing-function:var(--pdx-dialog-anim-ease, cubic-bezier(.2, 0, 0, 1))}.pdx-dialog.pdx-anim-fade{opacity:1}.pdx-dialog.pdx-anim-zoom{transform:scale(1)}.pdx-dialog.pdx-anim-translate-up,.pdx-dialog.pdx-anim-translate-down{transform:translateY(0)}.pdx-dialog.pdx-anim-translate-left,.pdx-dialog.pdx-anim-translate-right{transform:translate(0)}.pdx-dialog.pdx-state-opening.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-opening.pdx-anim-translate-right{transform:translate(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-fade{opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-zoom{transform:scale(.96);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-up{transform:translateY(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-down{transform:translateY(16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-left{transform:translate(-16px);opacity:0}.pdx-dialog.pdx-state-closing.pdx-anim-translate-right{transform:translate(16px);opacity:0}@media(prefers-reduced-motion:reduce){.pdx-dialog{transition:none!important}}\n"] }]
496
499
  }], propDecorators: { title: [{
497
500
  type: Input
498
501
  }], actions: [{
@@ -521,6 +524,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
521
524
  type: Input
522
525
  }], hasBackdrop: [{
523
526
  type: Input
527
+ }], closeOnBackdropClick: [{
528
+ type: Input
524
529
  }], overlayMode: [{
525
530
  type: Input
526
531
  }], zIndex: [{
@@ -637,10 +642,10 @@ class DialogOverlayService {
637
642
  }
638
643
  return overlayConfig;
639
644
  }
640
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogOverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
641
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogOverlayService, providedIn: 'root' });
645
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogOverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
646
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogOverlayService, providedIn: 'root' });
642
647
  }
643
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogOverlayService, decorators: [{
648
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogOverlayService, decorators: [{
644
649
  type: Injectable,
645
650
  args: [{ providedIn: 'root' }]
646
651
  }] });
@@ -681,6 +686,8 @@ class PraxisDialog {
681
686
  ref.id = assignedId;
682
687
  const compRef = this.overlay.attachContainer(overlayRef, injector);
683
688
  const container = compRef.instance;
689
+ ref.containerInstance = container;
690
+ ref.containerRef = compRef;
684
691
  // Set inputs before detectChanges so the correct branch/materialization occurs
685
692
  container.overlayMode = true;
686
693
  container.title = config?.title;
@@ -698,6 +705,7 @@ class PraxisDialog {
698
705
  container.styles = config?.styles;
699
706
  container.disableClose = !!config?.disableClose;
700
707
  container.hasBackdrop = config?.hasBackdrop ?? true;
708
+ container.closeOnBackdropClick = config?.closeOnBackdropClick ?? true;
701
709
  container.panelClass = config?.panelClass;
702
710
  container.backdropClass = config?.backdropClass;
703
711
  container.position = config?.position;
@@ -736,7 +744,11 @@ class PraxisDialog {
736
744
  }
737
745
  });
738
746
  // Attach portal content now that the outlet exists
747
+ let contentAttached = false;
739
748
  const doAttach = () => {
749
+ if (contentAttached || !container.contentHost)
750
+ return;
751
+ contentAttached = true;
740
752
  if (content instanceof TemplateRef) {
741
753
  const origin = config?.viewContainerRef ?? null;
742
754
  const portal = new TemplatePortal(content, origin, { $implicit: config?.data });
@@ -758,7 +770,7 @@ class PraxisDialog {
758
770
  }
759
771
  catch { }
760
772
  queueMicrotask(() => {
761
- if (container.contentHost)
773
+ if (overlayRef.hasAttached())
762
774
  doAttach();
763
775
  });
764
776
  }
@@ -852,10 +864,10 @@ class PraxisDialog {
852
864
  getDialogById(id) {
853
865
  return this._openDialogs.find((r) => r.id === id);
854
866
  }
855
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
856
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialog, providedIn: 'root' });
867
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
868
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialog, providedIn: 'root' });
857
869
  }
858
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDialog, decorators: [{
870
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDialog, decorators: [{
859
871
  type: Injectable,
860
872
  args: [{ providedIn: 'root' }]
861
873
  }] });
@@ -876,35 +888,43 @@ class SimpleDialogContentComponent {
876
888
  }
877
889
  catch { }
878
890
  }
879
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SimpleDialogContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
880
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: SimpleDialogContentComponent, isStandalone: true, selector: "praxis-simple-dialog-content", ngImport: i0, template: `
891
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SimpleDialogContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
892
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: SimpleDialogContentComponent, isStandalone: true, selector: "praxis-simple-dialog-content", ngImport: i0, template: `
881
893
  <div class="pdx-simple-dialog">
882
- <p *ngIf="message" class="pdx-simple-dialog__message">{{ message }}</p>
883
- <mat-form-field *ngIf="mode === 'prompt'" appearance="outline" class="pdx-simple-dialog__field">
884
- <mat-label>{{ placeholder || 'Digite um valor' }}</mat-label>
885
- <input matInput [(ngModel)]="value" />
886
- </mat-form-field>
894
+ @if (message) {
895
+ <p class="pdx-simple-dialog__message">{{ message }}</p>
896
+ }
897
+ @if (mode === 'prompt') {
898
+ <mat-form-field appearance="outline" class="pdx-simple-dialog__field">
899
+ <mat-label>{{ placeholder || 'Digite um valor' }}</mat-label>
900
+ <input matInput [(ngModel)]="value" />
901
+ </mat-form-field>
902
+ }
887
903
  </div>
888
- `, isInline: true, styles: [".pdx-simple-dialog{display:grid;gap:12px}.pdx-simple-dialog__message{margin:0}.pdx-simple-dialog__field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
904
+ `, isInline: true, styles: [".pdx-simple-dialog{display:grid;gap:12px}.pdx-simple-dialog__message{margin:0}.pdx-simple-dialog__field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
889
905
  }
890
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SimpleDialogContentComponent, decorators: [{
906
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SimpleDialogContentComponent, decorators: [{
891
907
  type: Component,
892
- args: [{ selector: 'praxis-simple-dialog-content', standalone: true, imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule], template: `
908
+ args: [{ selector: 'praxis-simple-dialog-content', standalone: true, imports: [FormsModule, MatFormFieldModule, MatInputModule], template: `
893
909
  <div class="pdx-simple-dialog">
894
- <p *ngIf="message" class="pdx-simple-dialog__message">{{ message }}</p>
895
- <mat-form-field *ngIf="mode === 'prompt'" appearance="outline" class="pdx-simple-dialog__field">
896
- <mat-label>{{ placeholder || 'Digite um valor' }}</mat-label>
897
- <input matInput [(ngModel)]="value" />
898
- </mat-form-field>
910
+ @if (message) {
911
+ <p class="pdx-simple-dialog__message">{{ message }}</p>
912
+ }
913
+ @if (mode === 'prompt') {
914
+ <mat-form-field appearance="outline" class="pdx-simple-dialog__field">
915
+ <mat-label>{{ placeholder || 'Digite um valor' }}</mat-label>
916
+ <input matInput [(ngModel)]="value" />
917
+ </mat-form-field>
918
+ }
899
919
  </div>
900
- `, styles: [".pdx-simple-dialog{display:grid;gap:12px}.pdx-simple-dialog__message{margin:0}.pdx-simple-dialog__field{width:100%}\n"] }]
920
+ `, styles: [".pdx-simple-dialog{display:grid;gap:12px}.pdx-simple-dialog__message{margin:0}.pdx-simple-dialog__field{width:100%}\n"] }]
901
921
  }], ctorParameters: () => [] });
902
922
  class SimpleHtmlDialogContentComponent {
903
923
  safeHtml;
904
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SimpleHtmlDialogContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
905
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: SimpleHtmlDialogContentComponent, isStandalone: true, selector: "praxis-simple-html-dialog-content", ngImport: i0, template: `<div class="pdx-simple-dialog" [innerHTML]="safeHtml"></div>`, isInline: true });
924
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SimpleHtmlDialogContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
925
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: SimpleHtmlDialogContentComponent, isStandalone: true, selector: "praxis-simple-html-dialog-content", ngImport: i0, template: `<div class="pdx-simple-dialog" [innerHTML]="safeHtml"></div>`, isInline: true });
906
926
  }
907
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SimpleHtmlDialogContentComponent, decorators: [{
927
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SimpleHtmlDialogContentComponent, decorators: [{
908
928
  type: Component,
909
929
  args: [{
910
930
  selector: 'praxis-simple-html-dialog-content',
@@ -988,6 +1008,9 @@ function buildConfig(payload) {
988
1008
  return {
989
1009
  title: payload.title,
990
1010
  message: payload.message,
1011
+ confirmLabel: payload.confirmLabel,
1012
+ cancelLabel: payload.cancelLabel,
1013
+ okLabel: payload.okLabel,
991
1014
  data: payload.data,
992
1015
  width: payload.size?.width ?? payload.width,
993
1016
  height: payload.size?.height ?? payload.height,
@@ -1100,7 +1123,14 @@ function applySurfaceHostInputs(ref, hostInputs) {
1100
1123
  const apply = () => {
1101
1124
  if (!ref.componentInstance)
1102
1125
  return false;
1103
- Object.assign(ref.componentInstance, hostInputs);
1126
+ if (typeof ref.componentRef?.setInput === 'function') {
1127
+ for (const [key, value] of Object.entries(hostInputs)) {
1128
+ ref.componentRef.setInput(key, value);
1129
+ }
1130
+ }
1131
+ else {
1132
+ Object.assign(ref.componentInstance, hostInputs);
1133
+ }
1104
1134
  try {
1105
1135
  ref.componentRef?.changeDetectorRef?.detectChanges();
1106
1136
  }
@@ -1116,37 +1146,39 @@ function providePraxisSurfaceGlobalActions() {
1116
1146
  provide: GLOBAL_SURFACE_SERVICE,
1117
1147
  useFactory: () => {
1118
1148
  const dialog = inject(PraxisDialog);
1149
+ const materializer = inject(SurfaceOpenMaterializerService);
1119
1150
  const surfaceDrawer = inject(SURFACE_DRAWER_BRIDGE, {
1120
1151
  optional: true,
1121
1152
  });
1122
1153
  return {
1123
1154
  open: async (payload, context) => {
1124
- const hostInputs = buildHostInputs(payload, context);
1125
- if (payload.presentation === 'drawer') {
1155
+ const materializedPayload = await materializer.materialize(payload, context);
1156
+ const hostInputs = buildHostInputs(materializedPayload, context);
1157
+ if (materializedPayload.presentation === 'drawer') {
1126
1158
  if (!surfaceDrawer) {
1127
1159
  throw new Error('Drawer surface service not available');
1128
1160
  }
1129
1161
  const ref = surfaceDrawer.open({
1130
- id: `surface:${payload.widget.id}`,
1131
- title: payload.title || payload.widget.id,
1132
- titleIcon: payload.icon,
1133
- subtitle: payload.subtitle,
1134
- width: payload.size?.width,
1135
- minWidth: payload.size?.minWidth,
1136
- maxWidth: payload.size?.maxWidth,
1137
- height: payload.size?.height,
1138
- minHeight: payload.size?.minHeight,
1139
- maxHeight: payload.size?.maxHeight,
1162
+ id: `surface:${materializedPayload.widget.id}`,
1163
+ title: materializedPayload.title || materializedPayload.widget.id,
1164
+ titleIcon: materializedPayload.icon,
1165
+ subtitle: materializedPayload.subtitle,
1166
+ width: materializedPayload.size?.width,
1167
+ minWidth: materializedPayload.size?.minWidth,
1168
+ maxWidth: materializedPayload.size?.maxWidth,
1169
+ height: materializedPayload.size?.height,
1170
+ minHeight: materializedPayload.size?.minHeight,
1171
+ maxHeight: materializedPayload.size?.maxHeight,
1140
1172
  content: {
1141
1173
  component: PraxisSurfaceHostComponent,
1142
- inputs: buildHostInputs(payload, context, {
1174
+ inputs: buildHostInputs(materializedPayload, context, {
1143
1175
  includeSubtitle: false,
1144
1176
  }),
1145
1177
  },
1146
1178
  });
1147
1179
  return ref;
1148
1180
  }
1149
- const ref = dialog.open(PraxisSurfaceHostComponent, buildDialogConfig(payload));
1181
+ const ref = dialog.open(PraxisSurfaceHostComponent, buildDialogConfig(materializedPayload));
1150
1182
  applySurfaceHostInputs(ref, hostInputs);
1151
1183
  return ref;
1152
1184
  },
@@ -1157,8 +1189,8 @@ function providePraxisSurfaceGlobalActions() {
1157
1189
 
1158
1190
  class LongContentDialogExampleComponent {
1159
1191
  items = Array.from({ length: 40 }, (_, idx) => `Example line ${idx + 1}`);
1160
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: LongContentDialogExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1161
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: LongContentDialogExampleComponent, isStandalone: true, selector: "praxis-long-content-dialog-example", ngImport: i0, template: `
1192
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LongContentDialogExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1193
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: LongContentDialogExampleComponent, isStandalone: true, selector: "praxis-long-content-dialog-example", ngImport: i0, template: `
1162
1194
  <div class="pdx-long-content">
1163
1195
  <p>
1164
1196
  This is a long content example to validate scroll behavior inside PraxisDialog.
@@ -1168,17 +1200,19 @@ class LongContentDialogExampleComponent {
1168
1200
  and actions remain visible.
1169
1201
  </p>
1170
1202
  <ul>
1171
- <li *ngFor="let item of items">{{ item }}</li>
1203
+ @for (item of items; track item) {
1204
+ <li>{{ item }}</li>
1205
+ }
1172
1206
  </ul>
1173
1207
  <p>
1174
1208
  End of the long content example.
1175
1209
  </p>
1176
1210
  </div>
1177
- `, isInline: true, styles: [".pdx-long-content{display:grid;gap:12px;color:var(--md-sys-color-on-surface, #111)}.pdx-long-content p{margin:0}.pdx-long-content ul{margin:0;padding-left:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
1211
+ `, isInline: true, styles: [".pdx-long-content{display:grid;gap:12px;color:var(--md-sys-color-on-surface, #111)}.pdx-long-content p{margin:0}.pdx-long-content ul{margin:0;padding-left:20px}\n"] });
1178
1212
  }
1179
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: LongContentDialogExampleComponent, decorators: [{
1213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LongContentDialogExampleComponent, decorators: [{
1180
1214
  type: Component,
1181
- args: [{ selector: 'praxis-long-content-dialog-example', standalone: true, imports: [CommonModule], template: `
1215
+ args: [{ selector: 'praxis-long-content-dialog-example', standalone: true, imports: [], template: `
1182
1216
  <div class="pdx-long-content">
1183
1217
  <p>
1184
1218
  This is a long content example to validate scroll behavior inside PraxisDialog.
@@ -1188,13 +1222,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
1188
1222
  and actions remain visible.
1189
1223
  </p>
1190
1224
  <ul>
1191
- <li *ngFor="let item of items">{{ item }}</li>
1225
+ @for (item of items; track item) {
1226
+ <li>{{ item }}</li>
1227
+ }
1192
1228
  </ul>
1193
1229
  <p>
1194
1230
  End of the long content example.
1195
1231
  </p>
1196
1232
  </div>
1197
- `, styles: [".pdx-long-content{display:grid;gap:12px;color:var(--md-sys-color-on-surface, #111)}.pdx-long-content p{margin:0}.pdx-long-content ul{margin:0;padding-left:20px}\n"] }]
1233
+ `, styles: [".pdx-long-content{display:grid;gap:12px;color:var(--md-sys-color-on-surface, #111)}.pdx-long-content p{margin:0}.pdx-long-content ul{margin:0;padding-left:20px}\n"] }]
1198
1234
  }] });
1199
1235
 
1200
1236
  const PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT = 'praxis.long-content-example';
@@ -1210,8 +1246,411 @@ function providePraxisDialogExamples() {
1210
1246
  };
1211
1247
  }
1212
1248
 
1249
+ const PRAXIS_DIALOG_PORTS = [
1250
+ {
1251
+ id: 'config',
1252
+ label: 'Dialog config',
1253
+ direction: 'input',
1254
+ semanticKind: 'config-fragment',
1255
+ schema: {
1256
+ id: 'PraxisDialogConfig',
1257
+ kind: 'ts-type',
1258
+ ref: 'PraxisDialogConfig',
1259
+ },
1260
+ description: 'Dialog shell configuration for title, actions, dimensions, backdrop, close policy and accessibility.',
1261
+ exposure: { public: true, group: 'config' },
1262
+ },
1263
+ {
1264
+ id: 'close',
1265
+ label: 'Close',
1266
+ direction: 'output',
1267
+ semanticKind: 'event',
1268
+ schema: {
1269
+ id: 'unknown',
1270
+ kind: 'ts-type',
1271
+ ref: 'unknown',
1272
+ },
1273
+ cardinality: 'stream',
1274
+ description: 'Emitted when the dialog shell requests close with an optional result payload.',
1275
+ exposure: { public: true, group: 'events' },
1276
+ },
1277
+ {
1278
+ id: 'action',
1279
+ label: 'Action',
1280
+ direction: 'output',
1281
+ semanticKind: 'event',
1282
+ schema: {
1283
+ id: 'DialogAction',
1284
+ kind: 'ts-type',
1285
+ ref: 'DialogAction',
1286
+ },
1287
+ cardinality: 'stream',
1288
+ description: 'Emitted when a configured dialog action is triggered.',
1289
+ exposure: { public: true, group: 'events' },
1290
+ },
1291
+ ];
1292
+ const PRAXIS_DIALOG_COMPONENT_METADATA = {
1293
+ id: 'praxis-dialog',
1294
+ selector: 'praxis-dialog',
1295
+ component: PraxisDialogComponent,
1296
+ friendlyName: 'Praxis Dialog',
1297
+ description: 'Dialog shell for overlay and embedded authoring, with governed size, position, backdrop, close policy, presets and child host delegation.',
1298
+ icon: 'dialogs',
1299
+ tags: ['dialog', 'overlay', 'shell', 'authoring'],
1300
+ lib: '@praxisui/dialog',
1301
+ inputs: [
1302
+ { name: 'title', type: 'string', label: 'Title', description: 'Dialog title text.' },
1303
+ { name: 'actions', type: 'DialogAction[]', label: 'Actions', description: 'Dialog footer actions and payloads.' },
1304
+ { name: 'actionsLayout', type: 'ActionsLayout', label: 'Actions layout', description: 'Footer action alignment.' },
1305
+ { name: 'width', type: 'string | number', label: 'Width', description: 'Dialog width.' },
1306
+ { name: 'height', type: 'string | number', label: 'Height', description: 'Dialog height.' },
1307
+ { name: 'minWidth', type: 'string | number', label: 'Minimum width', description: 'Minimum dialog width.' },
1308
+ { name: 'maxWidth', type: 'string | number', label: 'Maximum width', description: 'Maximum dialog width.' },
1309
+ { name: 'minHeight', type: 'string | number', label: 'Minimum height', description: 'Minimum dialog height.' },
1310
+ { name: 'maxHeight', type: 'string | number', label: 'Maximum height', description: 'Maximum dialog height.' },
1311
+ { name: 'themeColor', type: 'DialogThemeColor', label: 'Theme color', description: 'Dialog visual theme.' },
1312
+ { name: 'disableClose', type: 'boolean', label: 'Disable close', description: 'Blocks backdrop and Escape close behavior.' },
1313
+ { name: 'hasBackdrop', type: 'boolean', label: 'Backdrop', description: 'Controls whether the dialog renders a backdrop.' },
1314
+ { name: 'closeOnBackdropClick', type: 'boolean', label: 'Close on backdrop click', description: 'Controls backdrop click close policy.' },
1315
+ { name: 'panelClass', type: 'string | string[] | Record<string, boolean>', label: 'Panel class', description: 'Additional CSS class for the dialog panel.' },
1316
+ { name: 'backdropClass', type: 'string | string[] | Record<string, boolean>', label: 'Backdrop class', description: 'Additional CSS class for the backdrop.' },
1317
+ { name: 'position', type: 'PraxisDialogPosition', label: 'Position', description: 'Dialog position offsets.' },
1318
+ { name: 'ariaRole', type: "'dialog' | 'alertdialog'", label: 'ARIA role', description: 'Accessible dialog role.' },
1319
+ { name: 'ariaLabel', type: 'string', label: 'ARIA label', description: 'Accessible label when no visible title is present.' },
1320
+ { name: 'ariaLabelledBy', type: 'string', label: 'ARIA labelled by', description: 'External accessible label id.' },
1321
+ { name: 'ariaDescribedBy', type: 'string', label: 'ARIA described by', description: 'External accessible description id.' },
1322
+ ],
1323
+ outputs: [
1324
+ { name: 'action', type: 'DialogAction', label: 'Action' },
1325
+ { name: 'close', type: 'unknown', label: 'Close' },
1326
+ { name: 'opened', type: 'void', label: 'Opened' },
1327
+ { name: 'afterClosed', type: 'void', label: 'After closed' },
1328
+ ],
1329
+ actions: [
1330
+ {
1331
+ id: 'dialog-open',
1332
+ label: 'Open dialog',
1333
+ icon: 'open_in_new',
1334
+ description: 'Opens a dialog shell with governed config.',
1335
+ scope: 'any',
1336
+ },
1337
+ {
1338
+ id: 'dialog-close',
1339
+ label: 'Close dialog',
1340
+ icon: 'close',
1341
+ description: 'Closes the dialog with an optional payload.',
1342
+ emit: 'close',
1343
+ scope: 'any',
1344
+ },
1345
+ ],
1346
+ ports: PRAXIS_DIALOG_PORTS,
1347
+ };
1348
+ function providePraxisDialogMetadata() {
1349
+ return {
1350
+ provide: ENVIRONMENT_INITIALIZER,
1351
+ multi: true,
1352
+ useFactory: (registry) => () => {
1353
+ registry.register(PRAXIS_DIALOG_COMPONENT_METADATA);
1354
+ },
1355
+ deps: [ComponentMetadataRegistry],
1356
+ };
1357
+ }
1358
+
1359
+ const sizeFieldSchema = {
1360
+ type: 'object',
1361
+ minProperties: 1,
1362
+ properties: {
1363
+ width: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1364
+ height: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1365
+ minWidth: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1366
+ maxWidth: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1367
+ minHeight: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1368
+ maxHeight: { oneOf: [{ type: 'string' }, { type: 'number' }] },
1369
+ },
1370
+ };
1371
+ const positionSchema = {
1372
+ type: 'object',
1373
+ minProperties: 1,
1374
+ properties: {
1375
+ top: { type: 'string' },
1376
+ bottom: { type: 'string' },
1377
+ left: { type: 'string' },
1378
+ right: { type: 'string' },
1379
+ },
1380
+ };
1381
+ const closePolicySchema = {
1382
+ type: 'object',
1383
+ minProperties: 1,
1384
+ properties: {
1385
+ disableClose: { type: 'boolean' },
1386
+ closeOnBackdropClick: { type: 'boolean' },
1387
+ closeOnNavigation: { type: 'boolean' },
1388
+ restoreFocus: { type: 'boolean' },
1389
+ autoFocus: { type: 'boolean' },
1390
+ autoFocusedElement: { type: 'string' },
1391
+ },
1392
+ };
1393
+ const childHostSchema = {
1394
+ type: 'object',
1395
+ required: ['contentType'],
1396
+ properties: {
1397
+ contentType: { enum: ['component', 'template'] },
1398
+ componentId: { type: 'string' },
1399
+ templateId: { type: 'string' },
1400
+ inputs: { type: 'object' },
1401
+ data: {},
1402
+ childManifestComponentId: { type: 'string' },
1403
+ },
1404
+ };
1405
+ const PRAXIS_DIALOG_AUTHORING_MANIFEST = {
1406
+ schemaVersion: '1.0.0',
1407
+ componentId: 'praxis-dialog',
1408
+ ownerPackage: '@praxisui/dialog',
1409
+ configSchemaId: 'PraxisDialogConfig',
1410
+ manifestVersion: '1.0.0',
1411
+ runtimeInputs: [
1412
+ { name: 'config', type: 'PraxisDialogConfig', description: 'Canonical shell configuration consumed by PraxisDialog.open and tag mode.' },
1413
+ { name: 'content', type: 'ComponentType | TemplateRef | DialogContentDescriptor', description: 'Dialog child host content. Child semantics remain owned by the child component manifest.' },
1414
+ { name: 'variant', type: 'string', description: 'Optional global preset variant merged after dialog type presets and before local config.' },
1415
+ { name: 'componentId', type: 'string', description: 'Component metadata or dialog registry id used by global dialog open actions.' },
1416
+ { name: 'inputs', type: 'Record<string, unknown>', description: 'Inputs applied to the child component after opening the dialog.' },
1417
+ ],
1418
+ editableTargets: [
1419
+ { kind: 'dialogShell', resolver: 'praxis-dialog-config-root', description: 'Top-level PraxisDialogConfig shell fields such as title, role, actions and theme.' },
1420
+ { kind: 'size', resolver: 'praxis-dialog-size-fields', description: 'Width, height, min/max size fields on PraxisDialogConfig.' },
1421
+ { kind: 'position', resolver: 'praxis-dialog-position-fields', description: 'Overlay position fields top, bottom, left and right.' },
1422
+ { kind: 'backdrop', resolver: 'praxis-dialog-backdrop-fields', description: 'Backdrop enablement and backdrop class semantics.' },
1423
+ { kind: 'closePolicy', resolver: 'praxis-dialog-close-policy-fields', description: 'disableClose, closeOnBackdropClick, closeOnNavigation, restoreFocus and autofocus behavior.' },
1424
+ { kind: 'preset', resolver: 'praxis-dialog-global-preset-by-type-variant', description: 'Type and variant presets merged through PRAXIS_DIALOG_GLOBAL_PRESETS.' },
1425
+ { kind: 'childHost', resolver: 'praxis-dialog-child-component-or-template-host', description: 'Component/template registry child host and input/data envelope.' },
1426
+ ],
1427
+ operations: [
1428
+ {
1429
+ operationId: 'dialog.shell.set',
1430
+ title: 'Set dialog shell fields',
1431
+ scope: 'global',
1432
+ targetKind: 'dialogShell',
1433
+ target: { kind: 'dialogShell', resolver: 'praxis-dialog-config-root', ambiguityPolicy: 'fail', required: false },
1434
+ inputSchema: {
1435
+ type: 'object',
1436
+ minProperties: 1,
1437
+ properties: {
1438
+ title: { type: 'string' },
1439
+ titleIcon: { type: 'string' },
1440
+ ariaRole: { enum: ['dialog', 'alertdialog'] },
1441
+ ariaLabel: { type: 'string' },
1442
+ ariaLabelledBy: { type: 'string' },
1443
+ ariaDescribedBy: { type: 'string' },
1444
+ themeColor: { enum: ['primary', 'light', 'dark'] },
1445
+ actionsLayout: { enum: ['start', 'center', 'end', 'stretched'] },
1446
+ },
1447
+ },
1448
+ effects: [{ kind: 'merge-object', path: 'config' }],
1449
+ destructive: false,
1450
+ requiresConfirmation: false,
1451
+ validators: ['accessibility-label-preserved', 'aria-role-valid', 'shell-fields-supported', 'dialog-round-trip'],
1452
+ affectedPaths: ['config.title', 'config.titleIcon', 'config.ariaRole', 'config.ariaLabel', 'config.ariaLabelledBy', 'config.ariaDescribedBy', 'config.themeColor', 'config.actionsLayout'],
1453
+ submissionImpact: 'config-only',
1454
+ preconditions: ['config-initialized'],
1455
+ },
1456
+ {
1457
+ operationId: 'dialog.size.set',
1458
+ title: 'Set dialog size',
1459
+ scope: 'layout',
1460
+ targetKind: 'size',
1461
+ target: { kind: 'size', resolver: 'praxis-dialog-size-fields', ambiguityPolicy: 'fail', required: false },
1462
+ inputSchema: sizeFieldSchema,
1463
+ effects: [{ kind: 'merge-object', path: 'config' }],
1464
+ destructive: false,
1465
+ requiresConfirmation: false,
1466
+ validators: ['size-values-safe', 'size-min-max-consistent', 'dialog-round-trip'],
1467
+ affectedPaths: ['config.width', 'config.height', 'config.minWidth', 'config.maxWidth', 'config.minHeight', 'config.maxHeight'],
1468
+ submissionImpact: 'visual-only',
1469
+ preconditions: ['config-initialized'],
1470
+ },
1471
+ {
1472
+ operationId: 'dialog.position.set',
1473
+ title: 'Set dialog position',
1474
+ scope: 'layout',
1475
+ targetKind: 'position',
1476
+ target: { kind: 'position', resolver: 'praxis-dialog-position-fields', ambiguityPolicy: 'fail', required: false },
1477
+ inputSchema: positionSchema,
1478
+ effects: [{ kind: 'set-value', path: 'config.position' }],
1479
+ destructive: false,
1480
+ requiresConfirmation: false,
1481
+ validators: ['position-values-safe', 'position-not-conflicting', 'dialog-round-trip'],
1482
+ affectedPaths: ['config.position'],
1483
+ submissionImpact: 'visual-only',
1484
+ preconditions: ['config-initialized'],
1485
+ },
1486
+ {
1487
+ operationId: 'dialog.backdrop.set',
1488
+ title: 'Set dialog backdrop',
1489
+ scope: 'skin',
1490
+ targetKind: 'backdrop',
1491
+ target: { kind: 'backdrop', resolver: 'praxis-dialog-backdrop-fields', ambiguityPolicy: 'fail', required: false },
1492
+ inputSchema: {
1493
+ type: 'object',
1494
+ minProperties: 1,
1495
+ properties: {
1496
+ hasBackdrop: { type: 'boolean' },
1497
+ backdropClass: { oneOf: [{ type: 'string' }, { type: 'array' }, { type: 'object' }] },
1498
+ },
1499
+ },
1500
+ effects: [{ kind: 'merge-object', path: 'config' }],
1501
+ destructive: false,
1502
+ requiresConfirmation: false,
1503
+ validators: ['backdrop-policy-explicit', 'backdrop-class-safe', 'dialog-round-trip'],
1504
+ affectedPaths: ['config.hasBackdrop', 'config.backdropClass'],
1505
+ submissionImpact: 'visual-only',
1506
+ preconditions: ['config-initialized'],
1507
+ },
1508
+ {
1509
+ operationId: 'dialog.closePolicy.set',
1510
+ title: 'Set dialog close policy',
1511
+ scope: 'accessibility',
1512
+ targetKind: 'closePolicy',
1513
+ target: { kind: 'closePolicy', resolver: 'praxis-dialog-close-policy-fields', ambiguityPolicy: 'fail', required: false },
1514
+ inputSchema: closePolicySchema,
1515
+ effects: [{ kind: 'merge-object', path: 'config' }],
1516
+ destructive: true,
1517
+ requiresConfirmation: true,
1518
+ validators: ['close-policy-explicit', 'unsafe-close-confirmed-when-needed', 'restore-focus-preserved', 'alertdialog-focus-preserved', 'dialog-round-trip'],
1519
+ affectedPaths: ['config.disableClose', 'config.closeOnBackdropClick', 'config.closeOnNavigation', 'config.restoreFocus', 'config.autoFocus', 'config.autoFocusedElement'],
1520
+ submissionImpact: 'config-only',
1521
+ preconditions: ['config-initialized', 'confirmation-collected'],
1522
+ },
1523
+ {
1524
+ operationId: 'dialog.preset.apply',
1525
+ title: 'Apply dialog preset',
1526
+ scope: 'global',
1527
+ targetKind: 'preset',
1528
+ target: { kind: 'preset', resolver: 'praxis-dialog-global-preset-by-type-variant', ambiguityPolicy: 'fail', required: false },
1529
+ inputSchema: {
1530
+ type: 'object',
1531
+ required: ['dialogType'],
1532
+ properties: {
1533
+ dialogType: { enum: ['confirm', 'alert', 'prompt', 'custom'] },
1534
+ variant: { type: 'string' },
1535
+ localConfig: { type: 'object' },
1536
+ },
1537
+ },
1538
+ effects: [{ kind: 'compile-domain-patch', handler: 'dialog-preset-apply', handlerContract: {
1539
+ reads: ['PRAXIS_DIALOG_GLOBAL_PRESETS', 'config', 'variant'],
1540
+ writes: ['config', 'variant'],
1541
+ identityKeys: ['dialogType', 'variant'],
1542
+ inputSchema: { type: 'object', required: ['dialogType'], properties: { dialogType: { enum: ['confirm', 'alert', 'prompt', 'custom'] }, variant: { type: 'string' }, localConfig: { type: 'object' } } },
1543
+ failureModes: ['preset-not-found', 'variant-not-found', 'preset-merge-order-invalid', 'accessibility-regression'],
1544
+ description: 'Applies the canonical merge order type preset -> variant -> local config without mutating child component semantics.',
1545
+ } }],
1546
+ destructive: false,
1547
+ requiresConfirmation: false,
1548
+ validators: ['preset-exists', 'preset-merge-order-preserved', 'accessibility-label-preserved', 'dialog-round-trip'],
1549
+ affectedPaths: ['config', 'variant'],
1550
+ submissionImpact: 'config-only',
1551
+ preconditions: ['config-initialized'],
1552
+ },
1553
+ {
1554
+ operationId: 'childHost.configure',
1555
+ title: 'Configure dialog child host',
1556
+ scope: 'templating',
1557
+ targetKind: 'childHost',
1558
+ target: { kind: 'childHost', resolver: 'praxis-dialog-child-component-or-template-host', ambiguityPolicy: 'fail', required: false },
1559
+ inputSchema: childHostSchema,
1560
+ effects: [{ kind: 'compile-domain-patch', handler: 'dialog-child-host-configure', handlerContract: {
1561
+ reads: ['ComponentMetadataRegistry', 'PRAXIS_DIALOG_CONTENT_REGISTRY', 'PRAXIS_DIALOG_TEMPLATE_REGISTRY', 'content', 'componentId', 'inputs', 'data'],
1562
+ writes: ['content', 'componentId', 'inputs', 'data'],
1563
+ identityKeys: ['componentId', 'templateId'],
1564
+ inputSchema: childHostSchema,
1565
+ failureModes: ['component-not-registered', 'template-not-registered', 'child-inputs-not-serializable', 'child-manifest-required'],
1566
+ description: 'Configures which component/template is hosted in the dialog and serializable host inputs; child config fields remain delegated to the child manifest.',
1567
+ } }],
1568
+ destructive: false,
1569
+ requiresConfirmation: false,
1570
+ validators: ['child-host-registered', 'child-config-delegates-to-child-manifest', 'child-inputs-serializable', 'dialog-round-trip'],
1571
+ affectedPaths: ['content', 'componentId', 'inputs', 'data'],
1572
+ submissionImpact: 'config-only',
1573
+ preconditions: ['config-initialized'],
1574
+ },
1575
+ {
1576
+ operationId: 'childOperation.delegate',
1577
+ title: 'Delegate operation to child manifest',
1578
+ scope: 'templating',
1579
+ targetKind: 'childHost',
1580
+ target: { kind: 'childHost', resolver: 'praxis-dialog-child-component-or-template-host', ambiguityPolicy: 'fail', required: true },
1581
+ inputSchema: {
1582
+ type: 'object',
1583
+ required: ['childManifestComponentId', 'operationId', 'params'],
1584
+ properties: {
1585
+ childManifestComponentId: { type: 'string' },
1586
+ operationId: { type: 'string' },
1587
+ target: { type: 'string' },
1588
+ params: { type: 'object' },
1589
+ },
1590
+ },
1591
+ effects: [{ kind: 'compile-domain-patch', handler: 'dialog-child-operation-delegate', handlerContract: {
1592
+ reads: ['childManifestComponentId', 'operationId', 'params', 'componentRegistry.authoringManifest'],
1593
+ writes: ['inputs', 'data'],
1594
+ identityKeys: ['childManifestComponentId', 'operationId'],
1595
+ inputSchema: { type: 'object', required: ['childManifestComponentId', 'operationId', 'params'], properties: { childManifestComponentId: { type: 'string' }, operationId: { type: 'string' }, target: { type: 'string' }, params: { type: 'object' } } },
1596
+ failureModes: ['child-manifest-not-found', 'child-operation-not-authorized', 'child-operation-validation-failed', 'dialog-shell-child-boundary-violation'],
1597
+ description: 'Delegates child component configuration edits to the child authoring manifest before projecting the validated patch into the dialog child host inputs/data envelope.',
1598
+ } }],
1599
+ destructive: false,
1600
+ requiresConfirmation: false,
1601
+ validators: ['child-manifest-resolvable', 'child-operation-authorized', 'child-config-delegates-to-child-manifest', 'dialog-shell-boundary-preserved'],
1602
+ affectedPaths: ['inputs', 'data'],
1603
+ submissionImpact: 'config-only',
1604
+ preconditions: ['child-host-configured', 'child-manifest-resolved'],
1605
+ },
1606
+ ],
1607
+ validators: [
1608
+ { validatorId: 'accessibility-label-preserved', level: 'error', code: 'DIALOG_ACCESSIBILITY_LABEL_PRESERVED', description: 'Dialog or alertdialog must keep an accessible title or aria label.' },
1609
+ { validatorId: 'aria-role-valid', level: 'error', code: 'DIALOG_ARIA_ROLE_VALID', description: 'ariaRole must be dialog or alertdialog.' },
1610
+ { validatorId: 'shell-fields-supported', level: 'error', code: 'DIALOG_SHELL_FIELDS_SUPPORTED', description: 'Shell edits must target supported PraxisDialogConfig fields.' },
1611
+ { validatorId: 'size-values-safe', level: 'error', code: 'DIALOG_SIZE_VALUES_SAFE', description: 'Size values must be finite numbers or safe CSS size strings.' },
1612
+ { validatorId: 'size-min-max-consistent', level: 'error', code: 'DIALOG_SIZE_MIN_MAX_CONSISTENT', description: 'Minimum sizes must not exceed maximum sizes.' },
1613
+ { validatorId: 'position-values-safe', level: 'error', code: 'DIALOG_POSITION_VALUES_SAFE', description: 'Position values must be safe CSS size strings.' },
1614
+ { validatorId: 'position-not-conflicting', level: 'warning', code: 'DIALOG_POSITION_NOT_CONFLICTING', description: 'Conflicting position pairs should be explicit and intentional.' },
1615
+ { validatorId: 'backdrop-policy-explicit', level: 'error', code: 'DIALOG_BACKDROP_POLICY_EXPLICIT', description: 'Backdrop and backdrop-click behavior must be explicit when edited.' },
1616
+ { validatorId: 'backdrop-class-safe', level: 'error', code: 'DIALOG_BACKDROP_CLASS_SAFE', description: 'Backdrop classes must be serializable safe class values.' },
1617
+ { validatorId: 'close-policy-explicit', level: 'error', code: 'DIALOG_CLOSE_POLICY_EXPLICIT', description: 'Close behavior must explicitly describe ESC, backdrop and navigation semantics.' },
1618
+ { validatorId: 'unsafe-close-confirmed-when-needed', level: 'error', code: 'DIALOG_UNSAFE_CLOSE_CONFIRMED', description: 'Disabling safe close affordances or enabling unsafe dismissal requires confirmation.' },
1619
+ { validatorId: 'restore-focus-preserved', level: 'error', code: 'DIALOG_RESTORE_FOCUS_PRESERVED', description: 'restoreFocus must stay enabled unless intentionally changed with confirmation.' },
1620
+ { validatorId: 'alertdialog-focus-preserved', level: 'error', code: 'DIALOG_ALERTDIALOG_FOCUS_PRESERVED', description: 'alertdialog focus behavior must keep primary action or configured focus target reachable.' },
1621
+ { validatorId: 'preset-exists', level: 'error', code: 'DIALOG_PRESET_EXISTS', description: 'Preset type and variant must exist in PRAXIS_DIALOG_GLOBAL_PRESETS or be host-provided.' },
1622
+ { validatorId: 'preset-merge-order-preserved', level: 'error', code: 'DIALOG_PRESET_MERGE_ORDER_PRESERVED', description: 'Preset merge order must remain type -> variant -> local config.' },
1623
+ { validatorId: 'child-host-registered', level: 'error', code: 'DIALOG_CHILD_HOST_REGISTERED', description: 'Child component/template must resolve through ComponentMetadataRegistry or dialog registries.' },
1624
+ { validatorId: 'child-config-delegates-to-child-manifest', level: 'error', code: 'DIALOG_CHILD_CONFIG_DELEGATES', description: 'Child component config edits must be delegated to the child authoring manifest.' },
1625
+ { validatorId: 'child-inputs-serializable', level: 'error', code: 'DIALOG_CHILD_INPUTS_SERIALIZABLE', description: 'Child inputs/data persisted by authoring must be serializable safe values.' },
1626
+ { validatorId: 'child-manifest-resolvable', level: 'error', code: 'DIALOG_CHILD_MANIFEST_RESOLVABLE', description: 'Delegated child operation must resolve a child component authoring manifest.' },
1627
+ { validatorId: 'child-operation-authorized', level: 'error', code: 'DIALOG_CHILD_OPERATION_AUTHORIZED', description: 'Delegated child operation must be declared by the child manifest.' },
1628
+ { validatorId: 'dialog-shell-boundary-preserved', level: 'error', code: 'DIALOG_SHELL_BOUNDARY_PRESERVED', description: 'Dialog shell operations must not rewrite child component semantics directly.' },
1629
+ { validatorId: 'dialog-round-trip', level: 'error', code: 'DIALOG_ROUND_TRIP', description: 'Service/tag mode must preserve shell config through open, close, afterClosed and host persistence.' },
1630
+ ],
1631
+ roundTripRequirements: [
1632
+ 'PraxisDialogConfig is the canonical shell config; child component config remains owned by the child manifest.',
1633
+ 'Preset application must preserve merge order: type preset, then variant, then local config.',
1634
+ 'Close policy edits must keep accessibility, focus trap, ESC/backdrop behavior and restoreFocus explicit.',
1635
+ 'Dialog host operations must resolve component/template ids through governed registries instead of ad hoc overlays.',
1636
+ ],
1637
+ examples: [
1638
+ { id: 'set-size', request: 'Open this dialog at 860 by 640 pixels.', operationId: 'dialog.size.set', params: { width: '860px', height: '640px' }, isPositive: true },
1639
+ { id: 'set-position', request: 'Anchor the dialog to the right side.', operationId: 'dialog.position.set', params: { right: '24px', top: '64px' }, isPositive: true },
1640
+ { id: 'set-backdrop', request: 'Use a backdrop with the default governed backdrop class.', operationId: 'dialog.backdrop.set', params: { hasBackdrop: true, backdropClass: 'pdx-dialog-backdrop' }, isPositive: true },
1641
+ { id: 'set-close-policy', request: 'Make this destructive confirm require explicit button close.', operationId: 'dialog.closePolicy.set', params: { disableClose: true, closeOnBackdropClick: false, restoreFocus: true }, isPositive: true },
1642
+ { id: 'apply-danger-preset', request: 'Apply the danger confirm preset.', operationId: 'dialog.preset.apply', params: { dialogType: 'confirm', variant: 'danger' }, isPositive: true },
1643
+ { id: 'configure-child-host', request: 'Host the dynamic page component with customization enabled.', operationId: 'childHost.configure', params: { contentType: 'component', componentId: 'praxis-dynamic-page', inputs: { enableCustomization: true } }, isPositive: true },
1644
+ { id: 'delegate-child-config', request: 'Change the table column inside the dialog.', operationId: 'childOperation.delegate', params: { childManifestComponentId: 'praxis-table', operationId: 'column.label.set', params: { field: 'name', label: 'Name' } }, isPositive: true },
1645
+ { id: 'set-shell-label', request: 'Set the dialog title and alertdialog role.', operationId: 'dialog.shell.set', params: { title: 'Delete record', ariaRole: 'alertdialog' }, isPositive: true },
1646
+ { id: 'reject-child-shell-mix', request: 'Directly patch the child table config from the dialog shell manifest.', operationId: 'childOperation.delegate', params: { childManifestComponentId: '', operationId: 'patch-raw-child-config', params: {} }, isPositive: false },
1647
+ { id: 'reject-inaccessible-alert', request: 'Make an alertdialog with no title or aria label.', operationId: 'dialog.shell.set', params: { ariaRole: 'alertdialog', title: '' }, isPositive: false },
1648
+ { id: 'reject-unsafe-close', request: 'Let a destructive dialog close on accidental backdrop click with no confirmation.', operationId: 'dialog.closePolicy.set', params: { closeOnBackdropClick: true, disableClose: false, restoreFocus: false }, isPositive: false },
1649
+ ],
1650
+ };
1651
+
1213
1652
  /**
1214
1653
  * Generated bundle index. Do not edit.
1215
1654
  */
1216
1655
 
1217
- export { LongContentDialogExampleComponent, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisSurfaceGlobalActions };
1656
+ export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisSurfaceGlobalActions };
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@praxisui/dialog",
3
- "version": "8.0.0-beta.9",
3
+ "version": "8.0.0-beta.90",
4
4
  "description": "Dialog helpers and components for Praxis UI with Angular Material integration.",
5
5
  "peerDependencies": {
6
- "@angular/common": "^20.0.0",
7
- "@angular/core": "^20.0.0",
8
- "@angular/cdk": "^20.0.0",
9
- "@angular/forms": "^20.0.0",
10
- "@praxisui/core": "^8.0.0-beta.9"
6
+ "@angular/common": "^21.0.0",
7
+ "@angular/core": "^21.0.0",
8
+ "@angular/cdk": "^21.0.0",
9
+ "@angular/forms": "^21.0.0",
10
+ "@praxisui/core": "^8.0.0-beta.90",
11
+ "@angular/material": "^21.0.0",
12
+ "@angular/platform-browser": "^21.0.0",
13
+ "rxjs": "~7.8.0"
11
14
  },
12
15
  "dependencies": {
13
16
  "tslib": "^2.3.0"
@@ -34,14 +37,15 @@
34
37
  ],
35
38
  "sideEffects": false,
36
39
  "module": "fesm2022/praxisui-dialog.mjs",
37
- "typings": "index.d.ts",
40
+ "typings": "types/praxisui-dialog.d.ts",
38
41
  "exports": {
39
42
  "./package.json": {
40
43
  "default": "./package.json"
41
44
  },
42
45
  ".": {
43
- "types": "./index.d.ts",
46
+ "types": "./types/praxisui-dialog.d.ts",
44
47
  "default": "./fesm2022/praxisui-dialog.mjs"
45
48
  }
46
- }
49
+ },
50
+ "type": "module"
47
51
  }
@@ -3,6 +3,8 @@ import { InjectionToken, TemplateRef, ComponentRef, OnInit, OnChanges, OnDestroy
3
3
  import { OverlayRef } from '@angular/cdk/overlay';
4
4
  import { Observable, Subject } from 'rxjs';
5
5
  import { CdkPortalOutlet } from '@angular/cdk/portal';
6
+ import * as _praxisui_dialog from '@praxisui/dialog';
7
+ import { ComponentDocMeta, ComponentAuthoringManifest } from '@praxisui/core';
6
8
 
7
9
  type ActionsLayout = 'start' | 'center' | 'end' | 'stretched';
8
10
  type DialogThemeColor = 'primary' | 'light' | 'dark';
@@ -213,6 +215,7 @@ declare class PraxisDialogComponent implements OnInit, OnChanges, OnDestroy {
213
215
  themeColor: DialogThemeColor;
214
216
  disableClose: boolean;
215
217
  hasBackdrop: boolean;
218
+ closeOnBackdropClick: boolean;
216
219
  overlayMode: boolean;
217
220
  zIndex?: number;
218
221
  panelClass?: string | string[] | Record<string, boolean>;
@@ -264,7 +267,7 @@ declare class PraxisDialogComponent implements OnInit, OnChanges, OnDestroy {
264
267
  beginCloseAnimation(): Promise<void>;
265
268
  private focusPrimaryAction;
266
269
  static ɵfac: i0.ɵɵFactoryDeclaration<PraxisDialogComponent, never>;
267
- static ɵcmp: i0.ɵɵComponentDeclaration<PraxisDialogComponent, "praxis-dialog", never, { "title": { "alias": "title"; "required": false; }; "actions": { "alias": "actions"; "required": false; }; "actionsLayout": { "alias": "actionsLayout"; "required": false; }; "animation": { "alias": "animation"; "required": false; }; "open": { "alias": "open"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "minWidth": { "alias": "minWidth"; "required": false; }; "maxWidth": { "alias": "maxWidth"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "themeColor": { "alias": "themeColor"; "required": false; }; "disableClose": { "alias": "disableClose"; "required": false; }; "hasBackdrop": { "alias": "hasBackdrop"; "required": false; }; "overlayMode": { "alias": "overlayMode"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "panelClass": { "alias": "panelClass"; "required": false; }; "backdropClass": { "alias": "backdropClass"; "required": false; }; "position": { "alias": "position"; "required": false; }; "autoFocusedElement": { "alias": "autoFocusedElement"; "required": false; }; "autoFocus": { "alias": "autoFocus"; "required": false; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; }; "id": { "alias": "id"; "required": false; }; "ariaRole": { "alias": "ariaRole"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "ariaLabelledBy": { "alias": "ariaLabelledBy"; "required": false; }; "ariaDescribedBy": { "alias": "ariaDescribedBy"; "required": false; }; "styles": { "alias": "styles"; "required": false; }; "titleIcon": { "alias": "titleIcon"; "required": false; }; }, { "action": "action"; "close": "close"; "opened": "opened"; "afterClosed": "afterClosed"; }, ["titleTpl", "actionsTpl", "contentTpl"], never, true, never>;
270
+ static ɵcmp: i0.ɵɵComponentDeclaration<PraxisDialogComponent, "praxis-dialog", never, { "title": { "alias": "title"; "required": false; }; "actions": { "alias": "actions"; "required": false; }; "actionsLayout": { "alias": "actionsLayout"; "required": false; }; "animation": { "alias": "animation"; "required": false; }; "open": { "alias": "open"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "minWidth": { "alias": "minWidth"; "required": false; }; "maxWidth": { "alias": "maxWidth"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "themeColor": { "alias": "themeColor"; "required": false; }; "disableClose": { "alias": "disableClose"; "required": false; }; "hasBackdrop": { "alias": "hasBackdrop"; "required": false; }; "closeOnBackdropClick": { "alias": "closeOnBackdropClick"; "required": false; }; "overlayMode": { "alias": "overlayMode"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "panelClass": { "alias": "panelClass"; "required": false; }; "backdropClass": { "alias": "backdropClass"; "required": false; }; "position": { "alias": "position"; "required": false; }; "autoFocusedElement": { "alias": "autoFocusedElement"; "required": false; }; "autoFocus": { "alias": "autoFocus"; "required": false; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; }; "id": { "alias": "id"; "required": false; }; "ariaRole": { "alias": "ariaRole"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "ariaLabelledBy": { "alias": "ariaLabelledBy"; "required": false; }; "ariaDescribedBy": { "alias": "ariaDescribedBy"; "required": false; }; "styles": { "alias": "styles"; "required": false; }; "titleIcon": { "alias": "titleIcon"; "required": false; }; }, { "action": "action"; "close": "close"; "opened": "opened"; "afterClosed": "afterClosed"; }, ["titleTpl", "actionsTpl", "contentTpl"], never, true, never>;
268
271
  }
269
272
  declare const PraxisDialogDirectives: readonly [];
270
273
 
@@ -329,8 +332,13 @@ declare function providePraxisDialogExamples(): {
329
332
  provide: i0.InjectionToken<readonly (() => void)[]>;
330
333
  multi: boolean;
331
334
  useFactory: (registry: Record<string, any>) => () => void;
332
- deps: i0.InjectionToken<Record<string, ComponentType<any>>>[];
335
+ deps: i0.InjectionToken<Record<string, _praxisui_dialog.ComponentType<any>>>[];
333
336
  };
334
337
 
335
- export { LongContentDialogExampleComponent, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisSurfaceGlobalActions };
338
+ declare const PRAXIS_DIALOG_COMPONENT_METADATA: ComponentDocMeta;
339
+ declare function providePraxisDialogMetadata(): Provider;
340
+
341
+ declare const PRAXIS_DIALOG_AUTHORING_MANIFEST: ComponentAuthoringManifest;
342
+
343
+ export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisSurfaceGlobalActions };
336
344
  export type { ActionsLayout, AnimationDirection, ComponentType, DialogAction, DialogAnimation, DialogAnimationType, DialogContentDescriptor, DialogThemeColor, PraxisAlertConfig, PraxisConfirmConfig, PraxisDialogConfig, PraxisDialogGlobalPresets, PraxisDialogPosition, PraxisDialogStyleConfig, PraxisPromptConfig };