@praxisui/page-builder 8.0.0-beta.20 → 8.0.0-beta.22

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.
@@ -6,26 +6,26 @@ import * as i2 from '@angular/material/button';
6
6
  import { MatButtonModule } from '@angular/material/button';
7
7
  import * as i1 from '@angular/material/dialog';
8
8
  import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
9
- import * as i4 from '@angular/material/icon';
9
+ import * as i3 from '@angular/material/icon';
10
10
  import { MatIconModule } from '@angular/material/icon';
11
11
  import * as i2$2 from '@praxisui/core';
12
12
  import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, providePraxisI18n, PraxisI18nService, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, deepMerge, generateId, ComponentMetadataRegistry, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
13
13
  export { WidgetShellComponent } from '@praxisui/core';
14
- import * as i3 from '@angular/material/tooltip';
14
+ import * as i3$1 from '@angular/material/tooltip';
15
15
  import { MatTooltipModule } from '@angular/material/tooltip';
16
- import * as i3$1 from '@angular/material/form-field';
16
+ import * as i3$2 from '@angular/material/form-field';
17
17
  import { MatFormFieldModule } from '@angular/material/form-field';
18
- import * as i9 from '@angular/material/input';
18
+ import * as i6 from '@angular/material/input';
19
19
  import { MatInputModule } from '@angular/material/input';
20
20
  import * as i1$1 from '@angular/forms';
21
21
  import { FormsModule, FormGroup, FormArray, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
22
22
  import * as i5 from '@angular/material/checkbox';
23
23
  import { MatCheckboxModule } from '@angular/material/checkbox';
24
- import * as i6 from '@angular/material/divider';
24
+ import * as i6$1 from '@angular/material/divider';
25
25
  import { MatDividerModule } from '@angular/material/divider';
26
- import * as i6$1 from '@angular/material/select';
26
+ import * as i6$2 from '@angular/material/select';
27
27
  import { MatSelectModule } from '@angular/material/select';
28
- import { BehaviorSubject, merge, map, timeout, switchMap, Observable, firstValueFrom, from, concatMap, catchError, of, lastValueFrom } from 'rxjs';
28
+ import { BehaviorSubject, merge, timeout, map, switchMap, Observable, firstValueFrom, from, concatMap, catchError, of, lastValueFrom } from 'rxjs';
29
29
  import { SETTINGS_PANEL_DATA } from '@praxisui/settings-panel';
30
30
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
31
31
  import * as i7 from '@angular/material/tabs';
@@ -55,7 +55,7 @@ class ConfirmDialogComponent {
55
55
  <button mat-button mat-dialog-close>{{ data.cancelLabel || 'Cancelar' }}</button>
56
56
  <button mat-raised-button color="warn" [mat-dialog-close]="true">{{ data.confirmLabel || 'Excluir' }}</button>
57
57
  </div>
58
- `, isInline: true, styles: [":host{color:var(--md-sys-color-on-surface)}.dlg-icon{vertical-align:middle;margin-right:8px;color:var(--md-sys-color-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { 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 });
58
+ `, isInline: true, styles: [":host{color:var(--md-sys-color-on-surface)}.dlg-icon{vertical-align:middle;margin-right:8px;color:var(--md-sys-color-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.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 });
59
59
  }
60
60
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConfirmDialogComponent, decorators: [{
61
61
  type: Component,
@@ -121,7 +121,7 @@ class TileToolbarComponent {
121
121
  <mat-icon [praxisIcon]="'delete'"></mat-icon>
122
122
  </button>
123
123
  </div>
124
- `, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-tile-toolbar{position:absolute;right:6px;top:-18px;display:flex;gap:6px;z-index:5;opacity:0;transition:opacity .12s ease-in-out;pointer-events:auto;background:var(--md-sys-color-surface-container-low);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:999px;padding:4px;box-shadow:var(--mat-elevation-level3)}.pdx-tile-toolbar.always-visible{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
124
+ `, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-tile-toolbar{position:absolute;right:6px;top:-18px;display:flex;gap:6px;z-index:5;opacity:0;transition:opacity .12s ease-in-out;pointer-events:auto;background:var(--md-sys-color-surface-container-low);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:999px;padding:4px;box-shadow:var(--mat-elevation-level3)}.pdx-tile-toolbar.always-visible{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
125
125
  }
126
126
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TileToolbarComponent, decorators: [{
127
127
  type: Component,
@@ -179,6 +179,8 @@ class FloatingToolbarComponent {
179
179
  visible = false;
180
180
  canUndo = false;
181
181
  canRedo = false;
182
+ showSave = true;
183
+ showPreview = true;
182
184
  add = new EventEmitter();
183
185
  undo = new EventEmitter();
184
186
  redo = new EventEmitter();
@@ -186,71 +188,69 @@ class FloatingToolbarComponent {
186
188
  preview = new EventEmitter();
187
189
  save = new EventEmitter();
188
190
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FloatingToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
189
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: FloatingToolbarComponent, isStandalone: true, selector: "praxis-floating-toolbar", inputs: { visible: "visible", canUndo: "canUndo", canRedo: "canRedo" }, outputs: { add: "add", undo: "undo", redo: "redo", settings: "settings", preview: "preview", save: "save" }, ngImport: i0, template: `
191
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: FloatingToolbarComponent, isStandalone: true, selector: "praxis-floating-toolbar", inputs: { visible: "visible", canUndo: "canUndo", canRedo: "canRedo", showSave: "showSave", showPreview: "showPreview" }, outputs: { add: "add", undo: "undo", redo: "redo", settings: "settings", preview: "preview", save: "save" }, ngImport: i0, template: `
190
192
  <div class="pdx-floating-toolbar" *ngIf="visible">
191
- <button mat-fab color="primary" class="pdx-fab" [matTooltip]="'Acoes rapidas'">
192
- <mat-icon [praxisIcon]="'build'"></mat-icon>
193
- </button>
194
193
  <div class="pdx-actions">
195
194
  <button mat-mini-fab color="primary" (click)="add.emit()" [matTooltip]="'Inserir componente'" aria-label="Inserir componente">
196
195
  <mat-icon [praxisIcon]="'add'"></mat-icon>
197
196
  </button>
198
- <button mat-mini-fab color="accent" (click)="save.emit()" [matTooltip]="'Salvar pagina'" aria-label="Salvar pagina">
197
+ <button *ngIf="showSave" mat-mini-fab color="accent" (click)="save.emit()" [matTooltip]="'Salvar pagina'" aria-label="Salvar pagina">
199
198
  <mat-icon [praxisIcon]="'save'"></mat-icon>
200
199
  </button>
201
- <button mat-mini-fab (click)="undo.emit()" [disabled]="!canUndo" [matTooltip]="'Desfazer'" aria-label="Desfazer">
200
+ <button *ngIf="canUndo" mat-mini-fab (click)="undo.emit()" [matTooltip]="'Desfazer'" aria-label="Desfazer">
202
201
  <mat-icon [praxisIcon]="'undo'"></mat-icon>
203
202
  </button>
204
- <button mat-mini-fab (click)="redo.emit()" [disabled]="!canRedo" [matTooltip]="'Refazer'" aria-label="Refazer">
203
+ <button *ngIf="canRedo" mat-mini-fab (click)="redo.emit()" [matTooltip]="'Refazer'" aria-label="Refazer">
205
204
  <mat-icon [praxisIcon]="'redo'"></mat-icon>
206
205
  </button>
207
206
  <button mat-mini-fab (click)="settings.emit()" [matTooltip]="'Configuracoes da pagina'" aria-label="Configuracoes da pagina">
208
207
  <mat-icon [praxisIcon]="'settings'"></mat-icon>
209
208
  </button>
210
- <button mat-mini-fab (click)="preview.emit()" [matTooltip]="'Pre-visualizar'" aria-label="Pre-visualizar">
209
+ <button *ngIf="showPreview" mat-mini-fab (click)="preview.emit()" [matTooltip]="'Pre-visualizar'" aria-label="Pre-visualizar">
211
210
  <mat-icon [praxisIcon]="'visibility'"></mat-icon>
212
211
  </button>
213
212
  <ng-content select="[pdx-toolbar-extra]"></ng-content>
214
213
  </div>
215
214
  </div>
216
- `, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}.pdx-fab{box-shadow:var(--mat-elevation-level4)}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
215
+ `, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
217
216
  }
218
217
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FloatingToolbarComponent, decorators: [{
219
218
  type: Component,
220
219
  args: [{ selector: 'praxis-floating-toolbar', standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule, PraxisIconDirective], template: `
221
220
  <div class="pdx-floating-toolbar" *ngIf="visible">
222
- <button mat-fab color="primary" class="pdx-fab" [matTooltip]="'Acoes rapidas'">
223
- <mat-icon [praxisIcon]="'build'"></mat-icon>
224
- </button>
225
221
  <div class="pdx-actions">
226
222
  <button mat-mini-fab color="primary" (click)="add.emit()" [matTooltip]="'Inserir componente'" aria-label="Inserir componente">
227
223
  <mat-icon [praxisIcon]="'add'"></mat-icon>
228
224
  </button>
229
- <button mat-mini-fab color="accent" (click)="save.emit()" [matTooltip]="'Salvar pagina'" aria-label="Salvar pagina">
225
+ <button *ngIf="showSave" mat-mini-fab color="accent" (click)="save.emit()" [matTooltip]="'Salvar pagina'" aria-label="Salvar pagina">
230
226
  <mat-icon [praxisIcon]="'save'"></mat-icon>
231
227
  </button>
232
- <button mat-mini-fab (click)="undo.emit()" [disabled]="!canUndo" [matTooltip]="'Desfazer'" aria-label="Desfazer">
228
+ <button *ngIf="canUndo" mat-mini-fab (click)="undo.emit()" [matTooltip]="'Desfazer'" aria-label="Desfazer">
233
229
  <mat-icon [praxisIcon]="'undo'"></mat-icon>
234
230
  </button>
235
- <button mat-mini-fab (click)="redo.emit()" [disabled]="!canRedo" [matTooltip]="'Refazer'" aria-label="Refazer">
231
+ <button *ngIf="canRedo" mat-mini-fab (click)="redo.emit()" [matTooltip]="'Refazer'" aria-label="Refazer">
236
232
  <mat-icon [praxisIcon]="'redo'"></mat-icon>
237
233
  </button>
238
234
  <button mat-mini-fab (click)="settings.emit()" [matTooltip]="'Configuracoes da pagina'" aria-label="Configuracoes da pagina">
239
235
  <mat-icon [praxisIcon]="'settings'"></mat-icon>
240
236
  </button>
241
- <button mat-mini-fab (click)="preview.emit()" [matTooltip]="'Pre-visualizar'" aria-label="Pre-visualizar">
237
+ <button *ngIf="showPreview" mat-mini-fab (click)="preview.emit()" [matTooltip]="'Pre-visualizar'" aria-label="Pre-visualizar">
242
238
  <mat-icon [praxisIcon]="'visibility'"></mat-icon>
243
239
  </button>
244
240
  <ng-content select="[pdx-toolbar-extra]"></ng-content>
245
241
  </div>
246
242
  </div>
247
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}.pdx-fab{box-shadow:var(--mat-elevation-level4)}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"] }]
243
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"] }]
248
244
  }], propDecorators: { visible: [{
249
245
  type: Input
250
246
  }], canUndo: [{
251
247
  type: Input
252
248
  }], canRedo: [{
253
249
  type: Input
250
+ }], showSave: [{
251
+ type: Input
252
+ }], showPreview: [{
253
+ type: Input
254
254
  }], add: [{
255
255
  type: Output
256
256
  }], undo: [{
@@ -269,7 +269,7 @@ class ComponentPaletteDialogComponent {
269
269
  dialogRef;
270
270
  registry;
271
271
  data;
272
- query = '';
272
+ query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : []));
273
273
  all = signal([], ...(ngDevMode ? [{ debugName: "all" }] : []));
274
274
  filtered = computed(() => this.applyFilters(), ...(ngDevMode ? [{ debugName: "filtered" }] : []));
275
275
  density = computed(() => {
@@ -314,7 +314,7 @@ class ComponentPaletteDialogComponent {
314
314
  }, ...(ngDevMode ? [{ debugName: "_adjustSizeEffect" }] : []));
315
315
  applyFilters() {
316
316
  const list = (this.all() || []);
317
- const q = (this.query || '').toLowerCase();
317
+ const q = (this.query() || '').toLowerCase();
318
318
  const allowIds = new Set((this.data?.allowedWidgetIds || []).map((s) => s.toLowerCase()));
319
319
  const allowTags = new Set((this.data?.allowedWidgetTags || []).map((s) => s.toLowerCase()));
320
320
  const metadataById = new Map(this.registry.getAll().map((meta) => [meta.id, meta]));
@@ -342,7 +342,8 @@ class ComponentPaletteDialogComponent {
342
342
  title: meta.friendlyName || meta.id,
343
343
  description: meta.description || meta.selector,
344
344
  icon: meta.icon || 'widgets',
345
- searchText: `${meta.id} ${meta.friendlyName || ''} ${meta.description || ''} ${meta.selector || ''}`.toLowerCase(),
345
+ badges: this.buildBadges(meta, false),
346
+ searchText: `${meta.id} ${meta.friendlyName || ''} ${meta.description || ''} ${meta.selector || ''} ${this.buildBadgeSearchText(meta, false)}`.toLowerCase(),
346
347
  };
347
348
  const presets = (meta.insertionPresets ?? []).map((preset) => ({
348
349
  key: `${meta.id}::${preset.id}`,
@@ -351,12 +352,82 @@ class ComponentPaletteDialogComponent {
351
352
  title: `${meta.friendlyName || meta.id} · ${preset.label}`,
352
353
  description: preset.description || meta.description || meta.selector,
353
354
  icon: preset.icon || meta.icon || 'widgets',
354
- searchText: `${meta.id} ${meta.friendlyName || ''} ${preset.label} ${preset.description || ''} ${meta.description || ''}`.toLowerCase(),
355
+ badges: this.buildBadges(meta, true),
356
+ searchText: `${meta.id} ${meta.friendlyName || ''} ${preset.label} ${preset.description || ''} ${meta.description || ''} ${this.buildBadgeSearchText(meta, true)}`.toLowerCase(),
355
357
  inputs: preset.inputs ? JSON.parse(JSON.stringify(preset.inputs)) : undefined,
356
358
  }));
357
359
  return [baseEntry, ...presets];
358
360
  });
359
361
  }
362
+ buildBadges(meta, isPreset) {
363
+ const badges = [];
364
+ const tags = new Set((meta.tags ?? []).map((tag) => tag.toLowerCase()));
365
+ if (meta.configEditor?.component) {
366
+ badges.push({
367
+ label: 'Config editor',
368
+ icon: 'tune',
369
+ tone: 'ready',
370
+ description: 'This component publishes a canonical settings-panel editor for its input contract.',
371
+ });
372
+ }
373
+ if (meta.authoringManifestRef?.componentId) {
374
+ badges.push({
375
+ label: 'AI authoring',
376
+ icon: 'auto_awesome',
377
+ tone: 'ready',
378
+ description: 'This component owner publishes a canonical AI authoring manifest for governed changes.',
379
+ });
380
+ }
381
+ if (meta.ports?.length || meta.actions?.length || meta.commands?.length) {
382
+ badges.push({
383
+ label: 'Governed',
384
+ icon: 'account_tree',
385
+ tone: 'ready',
386
+ description: 'This component exposes semantic ports, actions, or commands for governed composition.',
387
+ });
388
+ }
389
+ if (isPreset) {
390
+ badges.push({
391
+ label: 'Preset',
392
+ icon: 'auto_awesome_motion',
393
+ tone: 'info',
394
+ description: 'This entry inserts a curated preset without changing the component contract.',
395
+ });
396
+ }
397
+ if (this.hasDataSourceInputs(meta) || tags.has('data') || tags.has('analytics')) {
398
+ badges.push({
399
+ label: 'Data source',
400
+ icon: 'database',
401
+ tone: 'info',
402
+ description: 'This component commonly needs schema, API, resource, or dataset context.',
403
+ });
404
+ }
405
+ if (tags.has('deprecated') || tags.has('legacy') || /legacy|legado|deprecated/i.test(meta.description || '')) {
406
+ badges.push({
407
+ label: 'Legacy',
408
+ icon: 'history',
409
+ tone: 'warning',
410
+ description: 'This entry is retained for compatibility and should not be the default for new canonical authoring.',
411
+ });
412
+ }
413
+ if (tags.has('demo') || tags.has('host') || /host-only|host|demo/i.test(`${meta.friendlyName} ${meta.description || ''}`)) {
414
+ badges.push({
415
+ label: 'Host/demo',
416
+ icon: 'science',
417
+ tone: 'neutral',
418
+ description: 'This entry depends on host/demo semantics and may need governance before public reuse.',
419
+ });
420
+ }
421
+ return badges;
422
+ }
423
+ buildBadgeSearchText(meta, isPreset) {
424
+ return this.buildBadges(meta, isPreset)
425
+ .map((badge) => `${badge.label} ${badge.description}`)
426
+ .join(' ');
427
+ }
428
+ hasDataSourceInputs(meta) {
429
+ return (meta.inputs ?? []).some((input) => /resource|schema|api|data(source)?|endpoint|resolver/i.test(input.name));
430
+ }
360
431
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ComponentPaletteDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: i2$2.ComponentMetadataRegistry }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
361
432
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: ComponentPaletteDialogComponent, isStandalone: true, selector: "praxis-component-palette-dialog", ngImport: i0, template: `
362
433
  <h2 mat-dialog-title>
@@ -369,16 +440,25 @@ class ComponentPaletteDialogComponent {
369
440
  </div>
370
441
  </h2>
371
442
  <div mat-dialog-content class="pdx-palette-content">
443
+ <mat-form-field class="pdx-palette-search" appearance="outline">
444
+ <mat-label>Buscar componente</mat-label>
445
+ <mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
446
+ <input
447
+ matInput
448
+ type="search"
449
+ [ngModel]="query()"
450
+ (ngModelChange)="query.set($event)"
451
+ placeholder="Nome, capability ou readiness"
452
+ data-testid="component-palette-search"
453
+ />
454
+ </mat-form-field>
372
455
  <div [class]="'pdx-grid ' + density()" *ngIf="filtered().length; else emptyState">
373
- <div
456
+ <button
374
457
  *ngFor="let entry of filtered(); trackBy: trackById"
375
458
  class="pdx-card mat-elevation-z2"
376
- tabindex="0"
377
- role="button"
459
+ type="button"
378
460
  [attr.aria-label]="'Adicionar ' + entry.title"
379
461
  (click)="select(entry)"
380
- (keydown.enter)="select(entry)"
381
- (keydown.space)="select(entry)"
382
462
  >
383
463
  <div class="pdx-card-icon">
384
464
  <mat-icon [praxisIcon]="entry.icon"></mat-icon>
@@ -386,8 +466,19 @@ class ComponentPaletteDialogComponent {
386
466
  <div class="pdx-card-body">
387
467
  <div class="pdx-card-title">{{ entry.title }}</div>
388
468
  <div class="pdx-card-desc">{{ entry.description }}</div>
469
+ <div class="pdx-card-badges" *ngIf="entry.badges.length">
470
+ <span
471
+ *ngFor="let badge of entry.badges"
472
+ class="pdx-card-badge"
473
+ [class]="'pdx-card-badge ' + badge.tone"
474
+ [title]="badge.description"
475
+ >
476
+ <mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
477
+ {{ badge.label }}
478
+ </span>
479
+ </div>
389
480
  </div>
390
- </div>
481
+ </button>
391
482
  </div>
392
483
 
393
484
  <ng-template #emptyState>
@@ -400,7 +491,7 @@ class ComponentPaletteDialogComponent {
400
491
  <div mat-dialog-actions align="end">
401
492
  <button mat-stroked-button color="primary" mat-dialog-close>Cancelar</button>
402
493
  </div>
403
- `, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;min-height:92px;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
494
+ `, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
404
495
  }
405
496
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ComponentPaletteDialogComponent, decorators: [{
406
497
  type: Component,
@@ -415,16 +506,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
415
506
  </div>
416
507
  </h2>
417
508
  <div mat-dialog-content class="pdx-palette-content">
509
+ <mat-form-field class="pdx-palette-search" appearance="outline">
510
+ <mat-label>Buscar componente</mat-label>
511
+ <mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
512
+ <input
513
+ matInput
514
+ type="search"
515
+ [ngModel]="query()"
516
+ (ngModelChange)="query.set($event)"
517
+ placeholder="Nome, capability ou readiness"
518
+ data-testid="component-palette-search"
519
+ />
520
+ </mat-form-field>
418
521
  <div [class]="'pdx-grid ' + density()" *ngIf="filtered().length; else emptyState">
419
- <div
522
+ <button
420
523
  *ngFor="let entry of filtered(); trackBy: trackById"
421
524
  class="pdx-card mat-elevation-z2"
422
- tabindex="0"
423
- role="button"
525
+ type="button"
424
526
  [attr.aria-label]="'Adicionar ' + entry.title"
425
527
  (click)="select(entry)"
426
- (keydown.enter)="select(entry)"
427
- (keydown.space)="select(entry)"
428
528
  >
429
529
  <div class="pdx-card-icon">
430
530
  <mat-icon [praxisIcon]="entry.icon"></mat-icon>
@@ -432,8 +532,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
432
532
  <div class="pdx-card-body">
433
533
  <div class="pdx-card-title">{{ entry.title }}</div>
434
534
  <div class="pdx-card-desc">{{ entry.description }}</div>
535
+ <div class="pdx-card-badges" *ngIf="entry.badges.length">
536
+ <span
537
+ *ngFor="let badge of entry.badges"
538
+ class="pdx-card-badge"
539
+ [class]="'pdx-card-badge ' + badge.tone"
540
+ [title]="badge.description"
541
+ >
542
+ <mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
543
+ {{ badge.label }}
544
+ </span>
545
+ </div>
435
546
  </div>
436
- </div>
547
+ </button>
437
548
  </div>
438
549
 
439
550
  <ng-template #emptyState>
@@ -446,7 +557,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
446
557
  <div mat-dialog-actions align="end">
447
558
  <button mat-stroked-button color="primary" mat-dialog-close>Cancelar</button>
448
559
  </div>
449
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;min-height:92px;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"] }]
560
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"] }]
450
561
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: i2$2.ComponentMetadataRegistry }, { type: undefined, decorators: [{
451
562
  type: Inject,
452
563
  args: [MAT_DIALOG_DATA]
@@ -1547,7 +1658,7 @@ class WidgetShellEditorComponent {
1547
1658
  <div class="shell-empty">Nenhuma ação configurada.</div>
1548
1659
  </ng-template>
1549
1660
  </div>
1550
- `, isInline: true, styles: [".shell-editor{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.shell-head{display:flex;align-items:center;gap:12px}.shell-title{font-weight:600}.shell-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-section{font-weight:600;margin-top:8px}.shell-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { 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: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1661
+ `, isInline: true, styles: [".shell-editor{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.shell-head{display:flex;align-items:center;gap:12px}.shell-title{font-weight:600}.shell-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-section{font-weight:600;margin-top:8px}.shell-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i6$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1551
1662
  }
1552
1663
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellEditorComponent, decorators: [{
1553
1664
  type: Component,
@@ -2290,6 +2401,18 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2290
2401
  'praxis.pageBuilder.agentic.panelAria': 'AI page authoring',
2291
2402
  'praxis.pageBuilder.agentic.title': 'Praxis semantic copilot',
2292
2403
  'praxis.pageBuilder.agentic.subtitle': 'Author governed decisions with previews, confirmation, and runtime materialization.',
2404
+ 'praxis.pageBuilder.agentic.header.title.page': 'Praxis page copilot',
2405
+ 'praxis.pageBuilder.agentic.header.title.widget': 'Praxis widget copilot',
2406
+ 'praxis.pageBuilder.agentic.header.title.review': 'Praxis review copilot',
2407
+ 'praxis.pageBuilder.agentic.header.title.governed': 'Praxis governed copilot',
2408
+ 'praxis.pageBuilder.agentic.header.subtitle.page': 'Author page-level layout, widgets and governed materialization.',
2409
+ 'praxis.pageBuilder.agentic.header.subtitle.route': 'Authoring page route {route}.',
2410
+ 'praxis.pageBuilder.agentic.header.subtitle.widget': 'Focused on {target}.',
2411
+ 'praxis.pageBuilder.agentic.header.subtitle.review': 'Preview ready for review and persistence.',
2412
+ 'praxis.pageBuilder.agentic.header.subtitle.governed': 'Continue the governed semantic-decision flow.',
2413
+ 'praxis.pageBuilder.agentic.header.mode.page': 'Page',
2414
+ 'praxis.pageBuilder.agentic.header.mode.widget': 'Widget',
2415
+ 'praxis.pageBuilder.agentic.header.mode.governed': 'Governed',
2293
2416
  'praxis.pageBuilder.agentic.close': 'Close',
2294
2417
  'praxis.pageBuilder.agentic.minimize': 'Minimize',
2295
2418
  'praxis.pageBuilder.agentic.dock.aria': 'AI assistant minimized with an active session',
@@ -2343,21 +2466,21 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2343
2466
  'praxis.pageBuilder.agentic.quickReplies.revise': 'I want to adjust',
2344
2467
  'praxis.pageBuilder.agentic.quickReplies.cancel': 'Cancel',
2345
2468
  'praxis.pageBuilder.agentic.quickReplies.payrollExecutiveDashboard': 'Executive dashboard',
2346
- 'praxis.pageBuilder.agentic.quickReplies.payrollDepartmentDrilldown': 'Department drill-down',
2469
+ 'praxis.pageBuilder.agentic.quickReplies.payrollDepartmentDrilldown': 'Category drill-down',
2347
2470
  'praxis.pageBuilder.agentic.quickReplies.payrollDetailTable': 'Detailed table',
2348
2471
  'praxis.pageBuilder.agentic.quickReplies.dashboardSuggestion': 'Dashboard',
2349
2472
  'praxis.pageBuilder.agentic.quickReplies.formSuggestion': 'Form',
2350
2473
  'praxis.pageBuilder.agentic.quickReplies.masterDetailSuggestion': 'Master detail',
2351
2474
  'praxis.pageBuilder.agentic.quickReplies.confirmPromptSuffix': 'Confirmed:',
2352
- 'praxis.pageBuilder.agentic.quickReplies.resourceSelectionPrompt': 'Use {label} ({resourcePath}) as the data source.',
2475
+ 'praxis.pageBuilder.agentic.quickReplies.resourceSelectionPrompt': 'Use {label} as the data source.',
2353
2476
  'praxis.pageBuilder.agentic.attachments.currentPage': 'Current page',
2354
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollExecutiveDashboard': 'Create a payroll dashboard with KPIs, payroll by department, monthly evolution, and a detail table.',
2355
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDepartmentDrilldown': 'Create a payroll dashboard with a department chart that filters a detail table when a bar is selected.',
2356
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDetailTable': 'Create a payroll detail table with filters, formatted currency values, and employee-level columns.',
2477
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollExecutiveDashboard': 'Create an executive dashboard with KPIs, category comparison, temporal evolution, and a detail table.',
2478
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDepartmentDrilldown': 'Create a dashboard with a category chart that filters a detail table when a bar is selected.',
2479
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDetailTable': 'Create a detail table with filters, appropriate value formatting, and relevant columns from the selected resource.',
2357
2480
  'praxis.pageBuilder.agentic.suggestionPrompts.dashboardSuggestion': 'Create a dashboard with KPIs, a chart, and a detail table.',
2358
2481
  'praxis.pageBuilder.agentic.suggestionPrompts.formSuggestion': 'Create a form with only the fields required for the selected business process.',
2359
2482
  'praxis.pageBuilder.agentic.suggestionPrompts.masterDetailSuggestion': 'Create a master-detail page with a summary list and a linked detail area.',
2360
- 'praxis.pageBuilder.agentic.exploratory.payrollOptions': 'For payroll, the best options are: 1. executive dashboard with KPIs and total payroll; 2. department drill-down with chart filtering a detail table; 3. monthly evolution to identify cost trends; 4. detailed table with filters and currency formatting. Choose one option or describe the change you want me to create.',
2483
+ 'praxis.pageBuilder.agentic.exploratory.payrollOptions': 'I can turn the selected source into: 1. an executive dashboard with KPIs; 2. category drill-down with a chart filtering a table; 3. temporal evolution to identify trends; 4. a detail table with filters and formatting. Choose one option or describe what you want me to create.',
2361
2484
  'praxis.pageBuilder.agentic.exploratory.genericOptions': 'I can help you choose before creating. Common options are dashboards for analysis, forms for data entry, master-detail pages for navigation, and tables for operational detail. Choose one option or describe what you want me to create.',
2362
2485
  'praxis.pageBuilder.agentic.exploratory.capability.chart': 'charts',
2363
2486
  'praxis.pageBuilder.agentic.exploratory.capability.table': 'tables',
@@ -2372,8 +2495,12 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2372
2495
  'praxis.pageBuilder.agentic.dragHandleAria': 'Move AI assistant',
2373
2496
  'praxis.pageBuilder.agentic.resizeHandleAria': 'Resize AI assistant',
2374
2497
  'praxis.pageBuilder.agentic.resizeHandleTooltip': 'Resize',
2375
- 'praxis.pageBuilder.agentic.preview': 'Preview',
2498
+ 'praxis.pageBuilder.agentic.preview': 'Generate preview',
2376
2499
  'praxis.pageBuilder.agentic.persist': 'Save',
2500
+ 'praxis.pageBuilder.pageLifecycle.restart': 'Restart page',
2501
+ 'praxis.pageBuilder.pageLifecycle.restartAria': 'Restart current page locally',
2502
+ 'praxis.pageBuilder.pageLifecycle.deleteSaved': 'Delete saved page',
2503
+ 'praxis.pageBuilder.pageLifecycle.deleteSavedAria': 'Delete persisted page and restart',
2377
2504
  'praxis.pageBuilder.agentic.status.resolvingIntent': 'Resolving intent...',
2378
2505
  'praxis.pageBuilder.agentic.status.waitingRevision': 'Refine your prompt and preview again.',
2379
2506
  'praxis.pageBuilder.agentic.status.cancelled': 'Request cancelled.',
@@ -2689,6 +2816,18 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2689
2816
  'praxis.pageBuilder.agentic.panelAria': 'Autoria de página com IA',
2690
2817
  'praxis.pageBuilder.agentic.title': 'Copiloto semântico Praxis',
2691
2818
  'praxis.pageBuilder.agentic.subtitle': 'Autore decisões governadas com prévias, confirmação e materialização runtime.',
2819
+ 'praxis.pageBuilder.agentic.header.title.page': 'Copiloto de página Praxis',
2820
+ 'praxis.pageBuilder.agentic.header.title.widget': 'Copiloto de componente Praxis',
2821
+ 'praxis.pageBuilder.agentic.header.title.review': 'Copiloto de revisão Praxis',
2822
+ 'praxis.pageBuilder.agentic.header.title.governed': 'Copiloto governado Praxis',
2823
+ 'praxis.pageBuilder.agentic.header.subtitle.page': 'Autore layout, widgets e materialização governada no nível da página.',
2824
+ 'praxis.pageBuilder.agentic.header.subtitle.route': 'Autoria da rota {route}.',
2825
+ 'praxis.pageBuilder.agentic.header.subtitle.widget': 'Foco em {target}.',
2826
+ 'praxis.pageBuilder.agentic.header.subtitle.review': 'Prévia pronta para revisão e persistência.',
2827
+ 'praxis.pageBuilder.agentic.header.subtitle.governed': 'Continue o fluxo governado de decisão semântica.',
2828
+ 'praxis.pageBuilder.agentic.header.mode.page': 'Página',
2829
+ 'praxis.pageBuilder.agentic.header.mode.widget': 'Widget',
2830
+ 'praxis.pageBuilder.agentic.header.mode.governed': 'Governado',
2692
2831
  'praxis.pageBuilder.agentic.close': 'Fechar',
2693
2832
  'praxis.pageBuilder.agentic.minimize': 'Minimizar',
2694
2833
  'praxis.pageBuilder.agentic.dock.aria': 'Assistente de IA minimizado com sessão ativa',
@@ -2742,21 +2881,21 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2742
2881
  'praxis.pageBuilder.agentic.quickReplies.revise': 'Quero ajustar',
2743
2882
  'praxis.pageBuilder.agentic.quickReplies.cancel': 'Cancelar',
2744
2883
  'praxis.pageBuilder.agentic.quickReplies.payrollExecutiveDashboard': 'Dashboard executivo',
2745
- 'praxis.pageBuilder.agentic.quickReplies.payrollDepartmentDrilldown': 'Drill-down por departamento',
2884
+ 'praxis.pageBuilder.agentic.quickReplies.payrollDepartmentDrilldown': 'Drill-down por categoria',
2746
2885
  'praxis.pageBuilder.agentic.quickReplies.payrollDetailTable': 'Tabela detalhada',
2747
2886
  'praxis.pageBuilder.agentic.quickReplies.dashboardSuggestion': 'Dashboard',
2748
2887
  'praxis.pageBuilder.agentic.quickReplies.formSuggestion': 'Formulário',
2749
2888
  'praxis.pageBuilder.agentic.quickReplies.masterDetailSuggestion': 'Master detail',
2750
2889
  'praxis.pageBuilder.agentic.quickReplies.confirmPromptSuffix': 'Confirmado:',
2751
- 'praxis.pageBuilder.agentic.quickReplies.resourceSelectionPrompt': 'Usar {label} ({resourcePath}) como fonte de dados.',
2890
+ 'praxis.pageBuilder.agentic.quickReplies.resourceSelectionPrompt': 'Usar {label} como fonte de dados.',
2752
2891
  'praxis.pageBuilder.agentic.attachments.currentPage': 'Página atual',
2753
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollExecutiveDashboard': 'Crie um dashboard de folha de pagamento com KPIs, folha por departamento, evolução mensal e tabela de detalhes.',
2754
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDepartmentDrilldown': 'Crie um dashboard de folha de pagamento com gráfico por departamento que filtre uma tabela detalhada ao selecionar uma barra.',
2755
- 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDetailTable': 'Crie uma tabela detalhada de folha de pagamento com filtros, valores monetários formatados e colunas por funcionário.',
2892
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollExecutiveDashboard': 'Crie um dashboard executivo com KPIs, comparação por categoria, evolução temporal e tabela de detalhes.',
2893
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDepartmentDrilldown': 'Crie um dashboard com gráfico por categoria que filtre uma tabela detalhada ao selecionar uma barra.',
2894
+ 'praxis.pageBuilder.agentic.suggestionPrompts.payrollDetailTable': 'Crie uma tabela detalhada com filtros, formatação adequada dos valores e colunas relevantes do recurso escolhido.',
2756
2895
  'praxis.pageBuilder.agentic.suggestionPrompts.dashboardSuggestion': 'Crie um dashboard com indicadores, gráfico e tabela de detalhes.',
2757
2896
  'praxis.pageBuilder.agentic.suggestionPrompts.formSuggestion': 'Crie um formulário com apenas os campos necessários para o processo de negócio selecionado.',
2758
2897
  'praxis.pageBuilder.agentic.suggestionPrompts.masterDetailSuggestion': 'Crie uma página master-detail com lista resumida e área de detalhes vinculada.',
2759
- 'praxis.pageBuilder.agentic.exploratory.payrollOptions': 'Para folha de pagamento, as melhores opções são: 1. dashboard executivo com KPIs e total da folha; 2. drill-down por departamento com gráfico filtrando uma tabela; 3. evolução mensal para identificar tendência de custo; 4. tabela detalhada com filtros e valores monetários. Escolha uma opção ou descreva o que você quer que eu crie.',
2898
+ 'praxis.pageBuilder.agentic.exploratory.payrollOptions': 'Posso transformar a fonte escolhida em: 1. dashboard executivo com KPIs; 2. drill-down por categoria com gráfico filtrando uma tabela; 3. evolução temporal para identificar tendências; 4. tabela detalhada com filtros e formatação. Escolha uma opção ou descreva o que você quer que eu crie.',
2760
2899
  'praxis.pageBuilder.agentic.exploratory.genericOptions': 'Posso ajudar você a escolher antes de criar. As opções mais comuns são dashboards para análise, formulários para entrada de dados, páginas master-detail para navegação e tabelas para detalhe operacional. Escolha uma opção ou descreva o que você quer que eu crie.',
2761
2900
  'praxis.pageBuilder.agentic.exploratory.capability.chart': 'gráficos',
2762
2901
  'praxis.pageBuilder.agentic.exploratory.capability.table': 'tabelas',
@@ -2771,8 +2910,12 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2771
2910
  'praxis.pageBuilder.agentic.dragHandleAria': 'Mover assistente de IA',
2772
2911
  'praxis.pageBuilder.agentic.resizeHandleAria': 'Redimensionar assistente de IA',
2773
2912
  'praxis.pageBuilder.agentic.resizeHandleTooltip': 'Redimensionar',
2774
- 'praxis.pageBuilder.agentic.preview': 'Pré-visualizar',
2913
+ 'praxis.pageBuilder.agentic.preview': 'Gerar prévia',
2775
2914
  'praxis.pageBuilder.agentic.persist': 'Salvar',
2915
+ 'praxis.pageBuilder.pageLifecycle.restart': 'Recomeçar tela',
2916
+ 'praxis.pageBuilder.pageLifecycle.restartAria': 'Recomeçar a tela atual apenas localmente',
2917
+ 'praxis.pageBuilder.pageLifecycle.deleteSaved': 'Excluir página salva',
2918
+ 'praxis.pageBuilder.pageLifecycle.deleteSavedAria': 'Excluir página persistida e recomeçar',
2776
2919
  'praxis.pageBuilder.agentic.status.resolvingIntent': 'Resolvendo intenção...',
2777
2920
  'praxis.pageBuilder.agentic.status.waitingRevision': 'Ajuste o prompt e pré-visualize novamente.',
2778
2921
  'praxis.pageBuilder.agentic.status.cancelled': 'Solicitação cancelada.',
@@ -2843,6 +2986,7 @@ function resolvePraxisPageBuilderText(i18n, key, fallback) {
2843
2986
  }
2844
2987
 
2845
2988
  const CONNECTION_EDITOR_STATE_NODE_ID = '__page_state__';
2989
+ const CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID = '__global_actions__';
2846
2990
  function deriveConnectionEditorGraph(page, options = {}) {
2847
2991
  const stateNodeTitle = options.stateNodeTitle ?? 'Page state';
2848
2992
  const fallbackStatePath = options.fallbackStatePath ?? 'selection.value';
@@ -2899,7 +3043,28 @@ function deriveConnectionEditorGraph(page, options = {}) {
2899
3043
  inputs: [],
2900
3044
  states: (statePaths.length ? statePaths : [fallbackStatePath]).slice(0, 6).map((path) => statePort(path)),
2901
3045
  };
2902
- const allNodes = [stateNode, ...nodes];
3046
+ const actionIds = Array.from(new Set(links
3047
+ .filter((link) => link.to.kind === 'global-action')
3048
+ .map((link) => link.to.kind === 'global-action' ? link.to.ref.actionId.trim() : '')
3049
+ .filter(Boolean)));
3050
+ const globalActionNode = actionIds.length
3051
+ ? {
3052
+ id: CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID,
3053
+ title: 'Global actions',
3054
+ subtitle: 'GlobalActionService',
3055
+ icon: 'bolt',
3056
+ x: center.x,
3057
+ y: center.y + radiusY + 104,
3058
+ outputs: [],
3059
+ inputs: actionIds.map((actionId) => globalActionPort(actionId)),
3060
+ states: [],
3061
+ }
3062
+ : null;
3063
+ const allNodes = [
3064
+ stateNode,
3065
+ ...nodes,
3066
+ ...(globalActionNode ? [globalActionNode] : []),
3067
+ ];
2903
3068
  for (const node of allNodes) {
2904
3069
  for (const port of [...node.outputs, ...node.inputs, ...node.states]) {
2905
3070
  portById.set(port.id, port);
@@ -2974,6 +3139,8 @@ function canConnectPorts(source, target) {
2974
3139
  return false;
2975
3140
  }
2976
3141
  function inferConnectionIntent(source, target) {
3142
+ if (target.endpoint.kind === 'global-action')
3143
+ return 'command-dispatch';
2977
3144
  if (target.kind === 'state')
2978
3145
  return 'state-write';
2979
3146
  if (source.kind === 'state')
@@ -3098,6 +3265,18 @@ function statePort(path) {
3098
3265
  },
3099
3266
  };
3100
3267
  }
3268
+ function globalActionPort(actionId) {
3269
+ return {
3270
+ id: `action-${portId(actionId)}`,
3271
+ nodeId: CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID,
3272
+ label: actionId,
3273
+ kind: 'input',
3274
+ endpoint: {
3275
+ kind: 'global-action',
3276
+ ref: { actionId },
3277
+ },
3278
+ };
3279
+ }
3101
3280
  function ensureEndpointPort(endpoint, nodes, portById, portByEndpointKey) {
3102
3281
  const key = endpointKey(endpoint);
3103
3282
  if (portByEndpointKey.has(key))
@@ -3115,6 +3294,20 @@ function ensureEndpointPort(endpoint, nodes, portById, portByEndpointKey) {
3115
3294
  portByEndpointKey.set(key, port);
3116
3295
  return;
3117
3296
  }
3297
+ if (endpoint.kind === 'global-action') {
3298
+ const node = nodes.find((candidate) => candidate.id === CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID);
3299
+ if (!node)
3300
+ return;
3301
+ const actionId = endpoint.ref.actionId.trim();
3302
+ if (!actionId)
3303
+ return;
3304
+ const port = globalActionPort(actionId);
3305
+ if (!node.inputs.some((candidate) => candidate.id === port.id))
3306
+ node.inputs.push(port);
3307
+ portById.set(port.id, port);
3308
+ portByEndpointKey.set(key, port);
3309
+ return;
3310
+ }
3118
3311
  const node = nodes.find((candidate) => candidate.id === endpoint.ref.widget);
3119
3312
  if (!node)
3120
3313
  return;
@@ -3129,6 +3322,12 @@ function endpointLabel(endpoint) {
3129
3322
  if (endpoint.kind === 'state') {
3130
3323
  return { nodeId: CONNECTION_EDITOR_STATE_NODE_ID, label: endpoint.ref.path };
3131
3324
  }
3325
+ if (endpoint.kind === 'global-action') {
3326
+ return {
3327
+ nodeId: CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID,
3328
+ label: endpoint.ref.actionId,
3329
+ };
3330
+ }
3132
3331
  return {
3133
3332
  nodeId: endpoint.ref.widget,
3134
3333
  label: endpoint.ref.nestedPath?.length
@@ -3140,6 +3339,9 @@ function endpointKey(endpoint) {
3140
3339
  if (endpoint.kind === 'state') {
3141
3340
  return `state:${endpoint.ref.layer ?? 'values'}:${endpoint.ref.path}`;
3142
3341
  }
3342
+ if (endpoint.kind === 'global-action') {
3343
+ return `global-action:${endpoint.ref.actionId}`;
3344
+ }
3143
3345
  const nested = endpoint.ref.nestedPath?.length
3144
3346
  ? endpoint.ref.nestedPath.map(formatPathSegment).join('/')
3145
3347
  : '';
@@ -3164,6 +3366,24 @@ function diagnosticsForEndpoint(endpoint, side, wasDeclared, resolvedPort, nodes
3164
3366
  }
3165
3367
  return diagnostics;
3166
3368
  }
3369
+ if (endpoint.kind === 'global-action') {
3370
+ if (!endpoint.ref.actionId.trim()) {
3371
+ diagnostics.push({
3372
+ code: 'endpoint-unresolved',
3373
+ severity: 'error',
3374
+ endpoint: side,
3375
+ });
3376
+ return diagnostics;
3377
+ }
3378
+ if (!resolvedPort) {
3379
+ diagnostics.push({
3380
+ code: 'endpoint-unresolved',
3381
+ severity: 'error',
3382
+ endpoint: side,
3383
+ });
3384
+ }
3385
+ return diagnostics;
3386
+ }
3167
3387
  const nodeExists = nodes.some((node) => node.id === endpoint.ref.widget);
3168
3388
  if (!nodeExists) {
3169
3389
  diagnostics.push({
@@ -8490,7 +8710,7 @@ class DynamicPageConfigEditorComponent {
8490
8710
  <mat-tab label="Estado da Pagina"><mat-form-field appearance="outline" class="wide"><mat-label>State (JSON)</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
8491
8711
  </mat-tab-group>
8492
8712
  </div>
8493
- `, isInline: true, styles: [".editor,.panel{display:grid;gap:16px}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid #d8e0ea;border-radius:16px;background:#fbfcfe}.wide{grid-column:1/-1}.hint{color:#5b6472;font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8713
+ `, isInline: true, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8494
8714
  }
8495
8715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageConfigEditorComponent, decorators: [{
8496
8716
  type: Component,
@@ -8515,7 +8735,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
8515
8735
  <mat-tab label="Estado da Pagina"><mat-form-field appearance="outline" class="wide"><mat-label>State (JSON)</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
8516
8736
  </mat-tab-group>
8517
8737
  </div>
8518
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".editor,.panel{display:grid;gap:16px}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid #d8e0ea;border-radius:16px;background:#fbfcfe}.wide{grid-column:1/-1}.hint{color:#5b6472;font-size:12px}\n"] }]
8738
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"] }]
8519
8739
  }], ctorParameters: () => [], propDecorators: { page: [{
8520
8740
  type: Input
8521
8741
  }], layout: [{
@@ -9995,7 +10215,7 @@ class PageConfigEditorComponent {
9995
10215
  </div>
9996
10216
  }
9997
10217
  </div>
9998
- `, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10218
+ `, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9999
10219
  }
10000
10220
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PageConfigEditorComponent, decorators: [{
10001
10221
  type: Component,
@@ -10644,15 +10864,14 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
10644
10864
  'praxis-dynamic-page-builder',
10645
10865
  ],
10646
10866
  notes: [
10647
- 'page segue o modelo canonico WidgetPageDefinition (widgets, composition.links, context e state opcional).',
10867
+ 'page segue o modelo canonico WidgetPageDefinition (widgets, composition.links, context e state opcional); composition.links tambem pode despachar actions globais via to.kind = global-action.',
10648
10868
  'Conteudo editorial rico deve ser modelado como widget praxis-rich-content com definition.inputs.document: RichContentDocument, nao como DSL local do page-builder.',
10649
10869
  'Quando definition.id = praxis-rich-content em uma pagina dinamica, definition.inputs.document continua sendo o contrato persistido; hostCapabilities e mediado em runtime pelo host praxis-dynamic-page e nao deve ser serializado no JSON da pagina.',
10650
- 'Edicao visual de inputs de widget deve usar ComponentDocMeta.configEditor publicado pela lib dona do componente; nao criar editor local no page-builder para semantica de outro pacote.',
10870
+ 'Edicao visual de inputs de widget deve usar ComponentDocMeta.configEditor ou ComponentDocMeta.authoringManifestRef publicado pela lib dona do componente; nao criar editor local no page-builder para semantica de outro pacote.',
10651
10871
  'Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.',
10652
10872
  'Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.',
10653
10873
  'Para criacao agentic de paginas, o preview pode trazer uiCompositionPlan como plano intermediario validavel; o page-builder compila esse plano para WidgetPageDefinition antes de aplicar.',
10654
10874
  'UiCompositionPlan usa widgets[].componentId e bindings declarativos. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.',
10655
- 'Nested component ports usam endpoint component-port com nestedPath. O owner em ref.widget, bindings[].from.widget ou bindings[].to.widget continua sendo o widget top-level; a porta real do filho fica em port/direction e o caminho ate o filho fica em nestedPath.',
10656
10875
  'Nested component ports usam endpoint component-port com nestedPath. O owner em ref.widget ou bindings[].*.widget continua sendo o widget top-level; a porta real do filho fica em port/direction e o caminho ate o filho fica em nestedPath.',
10657
10876
  'Nao gere links nested via owner.widgetEvent, bindingPath profundo, page.connections ou wrappers host-specific. widgetEvent e bridge legada/avancada, nao contrato principal de authoring.',
10658
10877
  'Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.',
@@ -10672,7 +10891,10 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
10672
10891
  { path: 'uiCompositionPlan.bindings', category: 'connections', valueKind: 'array', description: 'Bindings declarativos que serao compilados para page.composition.links.' },
10673
10892
  { path: 'uiCompositionPlan.bindings[].id', category: 'connections', valueKind: 'string', description: 'Identificador estavel do binding planejado.' },
10674
10893
  { path: 'uiCompositionPlan.bindings[].from', category: 'connections', valueKind: 'object', description: 'Endpoint de origem: component-port ou state.' },
10675
- { path: 'uiCompositionPlan.bindings[].to', category: 'connections', valueKind: 'object', description: 'Endpoint de destino: component-port ou state.' },
10894
+ { path: 'uiCompositionPlan.bindings[].to', category: 'connections', valueKind: 'object', description: 'Endpoint de destino: component-port, state ou global-action.' },
10895
+ { path: 'uiCompositionPlan.bindings[].to.[actionId]', category: 'connections', valueKind: 'string', description: 'ID da action global quando uiCompositionPlan.bindings[].to.kind = global-action.' },
10896
+ { path: 'uiCompositionPlan.bindings[].to.payload', category: 'connections', valueKind: 'object', description: 'Payload literal opcional para destino global-action planejado.' },
10897
+ { path: 'uiCompositionPlan.bindings[].to.payloadExpr', category: 'connections', valueKind: 'string', description: 'Path de payload opcional para destino global-action planejado.' },
10676
10898
  { path: 'uiCompositionPlan.bindings[].from.nestedPath', category: 'connections', valueKind: 'array', description: 'Caminho estruturado para porta nested de origem. Use apenas com endpoint component-port; o owner top-level continua em from.widget.' },
10677
10899
  { path: 'uiCompositionPlan.bindings[].to.nestedPath', category: 'connections', valueKind: 'array', description: 'Caminho estruturado para porta nested de destino. Use apenas com endpoint component-port; o owner top-level continua em to.widget.' },
10678
10900
  { path: 'uiCompositionPlan.bindings[].from.nestedPath[].kind', category: 'connections', valueKind: 'string', description: 'Tipo do segmento nested de origem, como tab, nav, link, expansion, panel ou widget. O ultimo segmento deve ser widget.' },
@@ -10730,12 +10952,20 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
10730
10952
  { path: 'ComponentDocMeta.configEditor', category: 'widgets', valueKind: 'object', description: 'Editor canonico de inputs publicado pela lib dona do componente e aberto pelo settings-panel do host.' },
10731
10953
  { path: 'ComponentDocMeta.configEditor.component', category: 'widgets', valueKind: 'object', description: 'Componente standalone que implementa SettingsValueProvider para editar definition.inputs.' },
10732
10954
  { path: 'ComponentDocMeta.configEditor.title', category: 'widgets', valueKind: 'string', description: 'Titulo opcional usado pelo host ao abrir o editor de inputs do componente.' },
10955
+ { path: 'ComponentDocMeta.authoringManifestRef', category: 'widgets', valueKind: 'object', description: 'Referencia canonica para o manifesto executavel de authoring por IA publicado pela lib dona do componente.' },
10956
+ { path: 'ComponentDocMeta.authoringManifestRef.componentId', category: 'widgets', valueKind: 'string', description: 'ID do componente no registry/backend de manifestos de authoring.' },
10957
+ { path: 'ComponentDocMeta.authoringManifestRef.source', category: 'widgets', valueKind: 'string', description: 'Simbolo, modulo ou registry id estavel do manifesto usado para delegar edicoes governadas.' },
10733
10958
  { path: 'page.composition', category: 'connections', valueKind: 'object', description: 'Envelope canonico da composicao persistida.' },
10734
10959
  { path: 'page.composition.version', category: 'connections', valueKind: 'string', description: 'Versao do envelope de composicao.' },
10735
- { path: 'page.composition.links', category: 'connections', valueKind: 'array', description: 'Links canonicos entre widgets e estado.' },
10960
+ { path: 'page.composition.links', category: 'connections', valueKind: 'array', description: 'Links canonicos entre widgets, estado e actions globais.' },
10736
10961
  { path: 'page.composition.links[].id', category: 'connections', valueKind: 'string', description: 'Identificador estavel do link.' },
10737
10962
  { path: 'page.composition.links[].from', category: 'connections', valueKind: 'object', description: 'Endpoint de origem do link.' },
10738
10963
  { path: 'page.composition.links[].to', category: 'connections', valueKind: 'object', description: 'Endpoint de destino do link.' },
10964
+ { path: 'page.composition.links[].to.kind', category: 'connections', valueKind: 'string', description: 'Tipo do endpoint de destino, incluindo global-action para command-dispatch declarativo.' },
10965
+ { path: 'page.composition.links[].to.ref.[actionId]', category: 'connections', valueKind: 'string', description: 'ID da action global quando page.composition.links[].to.kind = global-action.' },
10966
+ { path: 'page.composition.links[].to.ref.payload', category: 'connections', valueKind: 'object', description: 'Payload estruturado opcional da action global persistida; quando omitido, o valor transformado do link segue como delivery value.' },
10967
+ { path: 'page.composition.links[].to.ref.payloadExpr', category: 'connections', valueKind: 'expression', description: 'Escape avancado explicito de payload da action global persistida.' },
10968
+ { path: 'page.composition.links[].to.ref.meta', category: 'connections', valueKind: 'object', description: 'Metadados opcionais do GlobalActionRef persistido, sem criar executor paralelo.' },
10739
10969
  { path: 'page.composition.links[].from.ref.nestedPath', category: 'connections', valueKind: 'array', description: 'NestedPath canonico em endpoint component-port de origem persistido. Omita para top-level; nao serialize nestedPath: [].' },
10740
10970
  { path: 'page.composition.links[].from.ref.nestedPath[].key', category: 'connections', valueKind: 'string', description: 'Chave estavel do widget filho no segmento terminal widget de origem. Obrigatoria para endpoint nested persistido.', critical: true },
10741
10971
  { path: 'page.composition.links[].to.ref.nestedPath', category: 'connections', valueKind: 'array', description: 'NestedPath canonico em endpoint component-port de destino persistido. Omita para top-level; nao serialize nestedPath: [].' },
@@ -10902,7 +11132,9 @@ function providePageBuilderWidgetAiCatalogs() {
10902
11132
  };
10903
11133
  }
10904
11134
 
11135
+ const DEFAULT_AGENTIC_AUTHORING_REQUEST_TIMEOUT_MS = 15000;
10905
11136
  const DEFAULT_TURN_STREAM_START_TIMEOUT_MS = 10000;
11137
+ const DEFAULT_TURN_STREAM_TIMEOUT_MS = 60000;
10906
11138
  const PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS = new InjectionToken('PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS');
10907
11139
  class PageBuilderAgenticAuthoringService {
10908
11140
  http = inject(HttpClient);
@@ -10912,16 +11144,16 @@ class PageBuilderAgenticAuthoringService {
10912
11144
  baseUrl = (this.options?.baseUrl || '/api/praxis/config/ai/authoring').replace(/\/$/, '');
10913
11145
  headersFactory = this.options?.headersFactory || (() => ({}));
10914
11146
  getComponentCapabilities() {
10915
- return this.http.get(`${this.baseUrl}/component-capabilities`, { headers: this.buildHeaders() });
11147
+ return this.http.get(`${this.baseUrl}/component-capabilities`, { headers: this.buildHeaders() }).pipe(timeout({ first: this.requestTimeoutMs() }));
10916
11148
  }
10917
11149
  previewPage(request) {
10918
- return this.http.post(`${this.baseUrl}/page-preview`, request, { headers: this.buildHeaders() });
11150
+ return this.http.post(`${this.baseUrl}/page-preview`, request, { headers: this.buildHeaders() }).pipe(timeout({ first: this.requestTimeoutMs() }));
10919
11151
  }
10920
11152
  resolveIntent(request) {
10921
- return this.http.post(`${this.baseUrl}/intent-resolution`, request, { headers: this.buildHeaders() }).pipe(map((result) => this.normalizeIntentResolutionResult(result)));
11153
+ return this.http.post(`${this.baseUrl}/intent-resolution`, request, { headers: this.buildHeaders() }).pipe(timeout({ first: this.requestTimeoutMs() }), map((result) => this.normalizeIntentResolutionResult(result)));
10922
11154
  }
10923
11155
  searchResourceCandidates(request) {
10924
- return this.http.post(`${this.baseUrl}/resource-candidates`, request, { headers: this.buildHeaders() });
11156
+ return this.http.post(`${this.baseUrl}/resource-candidates`, request, { headers: this.buildHeaders() }).pipe(timeout({ first: this.requestTimeoutMs() }));
10925
11157
  }
10926
11158
  streamTurn(request) {
10927
11159
  return this.http.post(`${this.baseUrl}/turn/stream/start`, request, { headers: this.buildHeaders(), withCredentials: true }).pipe(timeout({ first: this.streamStartTimeoutMs() }), switchMap((start) => this.connectTurnStream(start)));
@@ -10961,11 +11193,19 @@ class PageBuilderAgenticAuthoringService {
10961
11193
  const probeUrl = this.buildStreamProbeUrl(start);
10962
11194
  let source = null;
10963
11195
  let closed = false;
11196
+ let streamTimeout = null;
10964
11197
  let connectionErrorTimer = null;
10965
11198
  const connectionErrorGraceMs = Math.max(0, this.options?.streamConnectionErrorGraceMs ?? 1500);
11199
+ const streamTimeoutMs = this.streamTurnTimeoutMs();
10966
11200
  let probeAbort = typeof AbortController !== 'undefined'
10967
11201
  ? new AbortController()
10968
11202
  : null;
11203
+ const clearStreamTimeout = () => {
11204
+ if (streamTimeout) {
11205
+ clearTimeout(streamTimeout);
11206
+ streamTimeout = null;
11207
+ }
11208
+ };
10969
11209
  const clearConnectionErrorTimer = () => {
10970
11210
  if (connectionErrorTimer) {
10971
11211
  clearTimeout(connectionErrorTimer);
@@ -10977,9 +11217,21 @@ class PageBuilderAgenticAuthoringService {
10977
11217
  return;
10978
11218
  }
10979
11219
  closed = true;
11220
+ clearStreamTimeout();
10980
11221
  clearConnectionErrorTimer();
10981
11222
  source?.close();
10982
11223
  };
11224
+ streamTimeout = setTimeout(() => {
11225
+ if (closed) {
11226
+ return;
11227
+ }
11228
+ observer.error({
11229
+ name: 'TimeoutError',
11230
+ code: 'agentic-authoring-timeout',
11231
+ message: `Agentic authoring turn timed out after ${streamTimeoutMs}ms.`,
11232
+ });
11233
+ closeSource();
11234
+ }, streamTimeoutMs);
10983
11235
  const failConnection = (event) => {
10984
11236
  if (closed) {
10985
11237
  return;
@@ -11043,6 +11295,7 @@ class PageBuilderAgenticAuthoringService {
11043
11295
  return;
11044
11296
  }
11045
11297
  closed = true;
11298
+ clearStreamTimeout();
11046
11299
  observer.error(this.streamConnectionError(error));
11047
11300
  });
11048
11301
  return () => {
@@ -11052,6 +11305,7 @@ class PageBuilderAgenticAuthoringService {
11052
11305
  return;
11053
11306
  }
11054
11307
  closed = true;
11308
+ clearStreamTimeout();
11055
11309
  clearConnectionErrorTimer();
11056
11310
  };
11057
11311
  });
@@ -11059,6 +11313,12 @@ class PageBuilderAgenticAuthoringService {
11059
11313
  streamStartTimeoutMs() {
11060
11314
  return Math.max(1, this.options?.streamStartTimeoutMs ?? DEFAULT_TURN_STREAM_START_TIMEOUT_MS);
11061
11315
  }
11316
+ streamTurnTimeoutMs() {
11317
+ return Math.max(1, this.options?.streamTurnTimeoutMs ?? DEFAULT_TURN_STREAM_TIMEOUT_MS);
11318
+ }
11319
+ requestTimeoutMs() {
11320
+ return Math.max(1, this.options?.requestTimeoutMs ?? DEFAULT_AGENTIC_AUTHORING_REQUEST_TIMEOUT_MS);
11321
+ }
11062
11322
  streamConnectionError(cause) {
11063
11323
  return {
11064
11324
  praxisAgenticTurnStreamConnectionError: true,
@@ -11177,16 +11437,84 @@ const widgetSchema = {
11177
11437
  canvasItem: { type: 'object' },
11178
11438
  },
11179
11439
  };
11440
+ const linkIntentValues = [
11441
+ 'event-propagation',
11442
+ 'state-write',
11443
+ 'state-read',
11444
+ 'command-dispatch',
11445
+ 'selection-sync',
11446
+ 'data-projection',
11447
+ 'status-propagation',
11448
+ ];
11449
+ const componentPortEndpointSchema = {
11450
+ type: 'object',
11451
+ required: ['kind', 'ref'],
11452
+ additionalProperties: false,
11453
+ properties: {
11454
+ kind: { enum: ['component-port'] },
11455
+ ref: {
11456
+ type: 'object',
11457
+ required: ['widget', 'port', 'direction'],
11458
+ additionalProperties: false,
11459
+ properties: {
11460
+ widget: { type: 'string' },
11461
+ port: { type: 'string' },
11462
+ direction: { enum: ['input', 'output'] },
11463
+ bindingPath: { type: 'string' },
11464
+ nestedPath: { type: 'array' },
11465
+ },
11466
+ },
11467
+ },
11468
+ };
11469
+ const stateEndpointSchema = {
11470
+ type: 'object',
11471
+ required: ['kind', 'ref'],
11472
+ additionalProperties: false,
11473
+ properties: {
11474
+ kind: { enum: ['state'] },
11475
+ ref: {
11476
+ type: 'object',
11477
+ required: ['path'],
11478
+ additionalProperties: false,
11479
+ properties: {
11480
+ path: { type: 'string' },
11481
+ layer: { enum: ['values', 'derived', 'transient'] },
11482
+ },
11483
+ },
11484
+ },
11485
+ };
11486
+ const globalActionEndpointSchema = {
11487
+ type: 'object',
11488
+ required: ['kind', 'ref'],
11489
+ additionalProperties: false,
11490
+ properties: {
11491
+ kind: { enum: ['global-action'] },
11492
+ ref: {
11493
+ type: 'object',
11494
+ required: ['actionId'],
11495
+ additionalProperties: false,
11496
+ properties: {
11497
+ actionId: { type: 'string' },
11498
+ payload: { type: 'object' },
11499
+ payloadExpr: { type: 'string' },
11500
+ meta: { type: 'object' },
11501
+ },
11502
+ },
11503
+ },
11504
+ };
11180
11505
  const compositionLinkSchema = {
11181
11506
  type: 'object',
11182
- required: ['linkId', 'from', 'to'],
11507
+ required: ['id', 'from', 'to', 'intent'],
11508
+ additionalProperties: false,
11183
11509
  properties: {
11184
- linkId: { type: 'string' },
11185
- from: { type: 'object' },
11186
- to: { type: 'object' },
11510
+ id: { type: 'string' },
11511
+ from: { oneOf: [componentPortEndpointSchema, stateEndpointSchema] },
11512
+ to: { oneOf: [componentPortEndpointSchema, stateEndpointSchema, globalActionEndpointSchema] },
11513
+ intent: { enum: linkIntentValues },
11187
11514
  condition: { type: 'object' },
11188
11515
  transform: { type: 'object' },
11189
11516
  policy: { type: 'object' },
11517
+ metadata: { type: 'object' },
11190
11518
  },
11191
11519
  };
11192
11520
  const childOperationSchema = {
@@ -11358,7 +11686,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11358
11686
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-composition-link-add', handlerContract: {
11359
11687
  reads: ['WidgetPageDefinition.composition.links', 'WidgetPageDefinition.widgets', 'PAGE_BUILDER_AI_CAPABILITIES'],
11360
11688
  writes: ['page.composition.links[]'],
11361
- identityKeys: ['linkId'],
11689
+ identityKeys: ['id'],
11362
11690
  inputSchema: compositionLinkSchema,
11363
11691
  failureModes: ['link-id-duplicate', 'endpoint-not-found', 'nested-path-invalid', 'json-logic-invalid'],
11364
11692
  description: 'Adds canonical declarative wiring in page.composition.links, including component-port nestedPath endpoints.',
@@ -11374,13 +11702,13 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11374
11702
  scope: 'dataBinding',
11375
11703
  targetKind: 'compositionLink',
11376
11704
  target: { kind: 'compositionLink', resolver: 'composition-link-by-id', ambiguityPolicy: 'fail', required: true },
11377
- inputSchema: { type: 'object', required: ['linkId'], properties: { linkId: { type: 'string' }, confirmed: { type: 'boolean' } } },
11705
+ inputSchema: { type: 'object', required: ['id'], properties: { id: { type: 'string' }, confirmed: { type: 'boolean' } } },
11378
11706
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-composition-link-remove', handlerContract: {
11379
11707
  reads: ['WidgetPageDefinition.composition.links'],
11380
11708
  writes: ['page.composition.links[]'],
11381
- identityKeys: ['linkId'],
11709
+ identityKeys: ['id'],
11382
11710
  failureModes: ['composition-link-not-found', 'destructive-removal-not-confirmed'],
11383
- description: 'Removes a canonical composition link by stable linkId.',
11711
+ description: 'Removes a canonical composition link by stable id.',
11384
11712
  } }],
11385
11713
  destructive: true,
11386
11714
  requiresConfirmation: true,
@@ -11399,7 +11727,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11399
11727
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-ui-composition-plan-compile', handlerContract: {
11400
11728
  reads: ['UiCompositionPlan', 'compileUiCompositionPlan', 'PAGE_BUILDER_WIDGET_AI_CATALOGS', 'ComponentDocMeta.configEditor'],
11401
11729
  writes: ['compiledFormPatch.patch.page'],
11402
- identityKeys: ['uiCompositionPlan.id', 'widgetKey', 'linkId'],
11730
+ identityKeys: ['uiCompositionPlan.id', 'widgetKey', 'uiCompositionPlan.bindings[].id'],
11403
11731
  failureModes: ['ui-composition-plan-invalid', 'widget-catalog-missing', 'compiled-page-invalid', 'child-config-editor-missing'],
11404
11732
  description: 'Compiles the agentic intermediate UiCompositionPlan into a renderable WidgetPageDefinition patch.page.',
11405
11733
  } }],
@@ -11597,7 +11925,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11597
11925
  request: 'When department-list selection changes, filter employees-table by department id.',
11598
11926
  operationId: 'composition.link.add',
11599
11927
  target: 'department-selection-to-employees',
11600
- params: { linkId: 'department-selection-to-employees', from: { widget: 'department-list', port: 'selection' }, to: { widget: 'employees-table', port: 'filter' } },
11928
+ params: { id: 'department-selection-to-employees', from: { widget: 'department-list', port: 'selection' }, to: { widget: 'employees-table', port: 'filter' }, intent: 'selection-sync' },
11601
11929
  isPositive: true,
11602
11930
  },
11603
11931
  {
@@ -11605,7 +11933,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11605
11933
  request: 'Remove the old payroll-filter-link composition link.',
11606
11934
  operationId: 'composition.link.remove',
11607
11935
  target: 'payroll-filter-link',
11608
- params: { linkId: 'payroll-filter-link', confirmed: true },
11936
+ params: { id: 'payroll-filter-link', confirmed: true },
11609
11937
  isPositive: true,
11610
11938
  },
11611
11939
  {
@@ -11661,7 +11989,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11661
11989
  request: 'Create the widget link under the old connections collection.',
11662
11990
  operationId: 'composition.link.add',
11663
11991
  target: 'legacy-connection',
11664
- params: { linkId: 'legacy-connection', collection: 'connections' },
11992
+ params: { id: 'legacy-connection', collection: 'connections' },
11665
11993
  isPositive: false,
11666
11994
  },
11667
11995
  ],
@@ -11734,8 +12062,8 @@ function validateUiCompositionPlan(plan) {
11734
12062
  }
11735
12063
  }
11736
12064
  for (const [index, binding] of (plan.bindings ?? []).entries()) {
11737
- validateEndpoint(binding.from, widgetKeys, diagnostics, `bindings.${index}.from`);
11738
- validateEndpoint(binding.to, widgetKeys, diagnostics, `bindings.${index}.to`);
12065
+ validateEndpoint(binding.from, widgetKeys, diagnostics, `bindings.${index}.from`, false);
12066
+ validateEndpoint(binding.to, widgetKeys, diagnostics, `bindings.${index}.to`, true);
11739
12067
  if (!binding.id?.trim()) {
11740
12068
  diagnostics.push({
11741
12069
  code: 'binding-id-required',
@@ -11760,7 +12088,7 @@ function validateCanvas(canvas, widgetKeys, diagnostics) {
11760
12088
  }
11761
12089
  }
11762
12090
  }
11763
- function validateEndpoint(endpoint, widgetKeys, diagnostics, path) {
12091
+ function validateEndpoint(endpoint, widgetKeys, diagnostics, path, allowGlobalAction) {
11764
12092
  if (!endpoint || typeof endpoint !== 'object') {
11765
12093
  diagnostics.push({
11766
12094
  code: 'endpoint-required',
@@ -11797,9 +12125,36 @@ function validateEndpoint(endpoint, widgetKeys, diagnostics, path) {
11797
12125
  }
11798
12126
  return;
11799
12127
  }
12128
+ if (endpoint.kind === 'global-action') {
12129
+ if (!allowGlobalAction) {
12130
+ diagnostics.push({
12131
+ code: 'endpoint-global-action-source-unsupported',
12132
+ message: 'Global-action endpoints are supported only as binding targets.',
12133
+ path: `${path}.kind`,
12134
+ });
12135
+ return;
12136
+ }
12137
+ if (!endpoint.actionId?.trim()) {
12138
+ diagnostics.push({
12139
+ code: 'endpoint-global-action-id-required',
12140
+ message: 'Global-action target must declare an actionId.',
12141
+ path: `${path}.actionId`,
12142
+ });
12143
+ }
12144
+ if (endpoint.payloadExpr !== undefined && typeof endpoint.payloadExpr !== 'string') {
12145
+ diagnostics.push({
12146
+ code: 'endpoint-global-action-payload-expr-invalid',
12147
+ message: 'Global-action payloadExpr must be a string expression path.',
12148
+ path: `${path}.payloadExpr`,
12149
+ });
12150
+ }
12151
+ return;
12152
+ }
11800
12153
  diagnostics.push({
11801
12154
  code: 'endpoint-kind-unsupported',
11802
- message: 'Endpoint kind must be "component-port" or "state".',
12155
+ message: allowGlobalAction
12156
+ ? 'Endpoint kind must be "component-port", "state" or "global-action".'
12157
+ : 'Endpoint kind must be "component-port" or "state".',
11803
12158
  path: `${path}.kind`,
11804
12159
  });
11805
12160
  }
@@ -11851,6 +12206,17 @@ function toCompositionEndpoint(endpoint) {
11851
12206
  },
11852
12207
  };
11853
12208
  }
12209
+ if (endpoint.kind === 'global-action') {
12210
+ return {
12211
+ kind: 'global-action',
12212
+ ref: {
12213
+ actionId: endpoint.actionId,
12214
+ ...(endpoint.payload !== undefined ? { payload: clone(endpoint.payload) } : {}),
12215
+ ...(endpoint.payloadExpr !== undefined ? { payloadExpr: endpoint.payloadExpr } : {}),
12216
+ ...(endpoint.meta !== undefined ? { meta: clone(endpoint.meta) } : {}),
12217
+ },
12218
+ };
12219
+ }
11854
12220
  return {
11855
12221
  kind: 'state',
11856
12222
  ref: {
@@ -12383,6 +12749,9 @@ class PageBuilderAiAdapter {
12383
12749
  this.nestedPathKey(endpoint.ref.nestedPath),
12384
12750
  ].filter((part) => part !== '').join('::');
12385
12751
  }
12752
+ if (endpoint.kind === 'global-action') {
12753
+ return endpoint.ref.actionId ? `global-action:${endpoint.ref.actionId}` : null;
12754
+ }
12386
12755
  return endpoint.ref.path ? `state:${endpoint.ref.path}::${endpoint.ref.layer || 'values'}` : null;
12387
12756
  }
12388
12757
  nestedPathKey(nestedPath) {
@@ -12488,7 +12857,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
12488
12857
  ?? (intentClarification
12489
12858
  ? this.buildPendingClarificationForNextTurn(request, this.resolveEffectivePrompt(intentResolution, prompt), intentClarification)
12490
12859
  : routeRequiredClarification);
12491
- if (!this.hasPendingClarificationQuestion(pendingClarification) && quickReplies.length === 0) {
12860
+ const shouldAutoGenerateGuidedPreview = this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) && !this.hasPendingClarificationQuestion(pendingClarification);
12861
+ const mustPauseForClarification = (!this.isExecutableIntent(intentResolution) && !shouldAutoGenerateGuidedPreview)
12862
+ || this.hasPendingClarificationQuestion(pendingClarification);
12863
+ if (mustPauseForClarification && !this.hasPendingClarificationQuestion(pendingClarification) && quickReplies.length === 0) {
12492
12864
  return {
12493
12865
  state: 'success',
12494
12866
  phase: 'summarize',
@@ -12498,21 +12870,38 @@ class PageBuilderAgenticAuthoringTurnFlow {
12498
12870
  statusText: '',
12499
12871
  errorText: '',
12500
12872
  preview: null,
12873
+ pendingClarification: null,
12874
+ diagnostics: { intentResolution },
12875
+ };
12876
+ }
12877
+ if (mustPauseForClarification && !this.hasPendingClarificationQuestion(pendingClarification)) {
12878
+ return {
12879
+ state: 'clarification',
12880
+ phase: 'clarify',
12881
+ assistantMessage: intentAssistantMessage,
12882
+ quickReplies,
12883
+ canApply: false,
12884
+ statusText: '',
12885
+ errorText: '',
12886
+ preview: null,
12887
+ pendingClarification: null,
12888
+ diagnostics: { intentResolution },
12889
+ };
12890
+ }
12891
+ if (mustPauseForClarification) {
12892
+ return {
12893
+ state: 'clarification',
12894
+ phase: 'clarify',
12895
+ assistantMessage: intentAssistantMessage,
12896
+ quickReplies,
12897
+ canApply: false,
12898
+ statusText: '',
12899
+ errorText: '',
12900
+ preview: null,
12901
+ pendingClarification,
12501
12902
  diagnostics: { intentResolution },
12502
12903
  };
12503
12904
  }
12504
- return {
12505
- state: 'clarification',
12506
- phase: 'clarify',
12507
- assistantMessage: intentAssistantMessage,
12508
- quickReplies,
12509
- canApply: false,
12510
- statusText: '',
12511
- errorText: '',
12512
- preview: null,
12513
- pendingClarification,
12514
- diagnostics: { intentResolution },
12515
- };
12516
12905
  }
12517
12906
  const clarification = this.resolveIntentClarification(intentResolution);
12518
12907
  if (clarification) {
@@ -12608,7 +12997,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
12608
12997
  }
12609
12998
  }
12610
12999
  submitWithTurnStream(request, prompt) {
12611
- return from(this.buildTurnStreamRequest(request, prompt)).pipe(concatMap((streamRequest) => this.service.streamTurn(streamRequest)), concatMap((event) => from(this.toTurnResultFromStreamEvent(event))), catchError((error) => {
13000
+ return from(this.buildTurnStreamRequest(request, prompt)).pipe(concatMap((streamRequest) => this.service.streamTurn(streamRequest)), concatMap((event) => from(this.toTurnResultFromStreamEvent(event, request, prompt))), catchError((error) => {
12612
13001
  if (this.shouldFailClosedFromTurnStreamError(request, prompt, error)) {
12613
13002
  return of(this.toGovernedRouteFailClosedResult(request, prompt, error));
12614
13003
  }
@@ -12647,10 +13036,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
12647
13036
  ...this.buildAuthoringContext(request),
12648
13037
  };
12649
13038
  }
12650
- async toTurnResultFromStreamEvent(event) {
13039
+ async toTurnResultFromStreamEvent(event, request, prompt) {
12651
13040
  const payload = this.toJsonObject(event.payload) ?? {};
12652
13041
  if (event.type === 'result') {
12653
- return this.toResultTurnFromStreamPayload(payload);
13042
+ return this.toResultTurnFromStreamPayload(payload, request, prompt);
12654
13043
  }
12655
13044
  if (event.type === 'error') {
12656
13045
  const message = this.describeStreamError(payload);
@@ -12688,7 +13077,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
12688
13077
  preview: null,
12689
13078
  };
12690
13079
  }
12691
- async toResultTurnFromStreamPayload(payload) {
13080
+ async toResultTurnFromStreamPayload(payload, request, prompt) {
12692
13081
  const intentResolution = this.normalizeIntentResolutionResult(payload['intentResolution']);
12693
13082
  const preview = payload['preview'];
12694
13083
  if (!intentResolution) {
@@ -12706,13 +13095,28 @@ class PageBuilderAgenticAuthoringTurnFlow {
12706
13095
  const assistantMessage = this.readString(payload, 'assistantMessage')
12707
13096
  || this.resolveIntentAssistantMessage(intentResolution)
12708
13097
  || (preview ? this.context.describePreviewStatus(preview) : '');
12709
- const quickReplies = Array.isArray(payload['quickReplies'])
12710
- ? this.toShellQuickReplies(payload['quickReplies'])
12711
- : [];
13098
+ const rawQuickReplies = Array.isArray(payload['quickReplies'])
13099
+ ? payload['quickReplies']
13100
+ : intentResolution.quickReplies ?? [];
13101
+ const quickReplies = this.toShellQuickReplies(rawQuickReplies);
12712
13102
  const canApply = payload['canApply'] === true && !!preview?.valid;
13103
+ if (canApply
13104
+ && request
13105
+ && prompt
13106
+ && this.shouldRegenerateStreamPreview(intentResolution, preview)) {
13107
+ return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
13108
+ }
12713
13109
  if (!canApply) {
12714
13110
  const pendingClarification = this.toShellPendingClarification(intentResolution?.pendingClarification)
12715
13111
  ?? this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, assistantMessage));
13112
+ if (!pendingClarification
13113
+ && (this.isExecutableIntent(intentResolution)
13114
+ || (!!prompt && this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt)))
13115
+ && !this.hasBlockingResourceQuickReply(quickReplies)
13116
+ && request
13117
+ && prompt) {
13118
+ return this.completeExecutableStreamPreview(request, prompt, intentResolution, preview);
13119
+ }
12716
13120
  const requiresChoice = quickReplies.length > 0;
12717
13121
  return {
12718
13122
  state: pendingClarification || requiresChoice ? 'clarification' : 'success',
@@ -12755,6 +13159,103 @@ class PageBuilderAgenticAuthoringTurnFlow {
12755
13159
  diagnostics: { intentResolution, preview },
12756
13160
  };
12757
13161
  }
13162
+ hasBlockingResourceQuickReply(quickReplies) {
13163
+ return quickReplies.some((reply) => {
13164
+ const kind = (reply.kind || '').trim().toLowerCase();
13165
+ if (['cancel', 'revise'].includes(kind)) {
13166
+ return false;
13167
+ }
13168
+ const contextHints = this.toJsonObject(reply.contextHints);
13169
+ return !!this.readString(contextHints, 'resourcePath');
13170
+ });
13171
+ }
13172
+ async completeExecutableStreamPreview(request, prompt, intentResolution, streamPreview) {
13173
+ try {
13174
+ const authoringContext = this.buildAuthoringContext(request);
13175
+ const componentCapabilities = await this.context.loadComponentCapabilities();
13176
+ const selectedWidgetKey = this.context.selectedWidgetKey();
13177
+ const reusableStreamPreview = streamPreview?.valid
13178
+ && !this.shouldRegenerateStreamPreview(intentResolution, streamPreview);
13179
+ const preview = reusableStreamPreview
13180
+ ? streamPreview
13181
+ : await firstValueFrom(this.service.previewPage({
13182
+ userPrompt: prompt,
13183
+ provider: this.context.provider(),
13184
+ model: this.context.model(),
13185
+ apiKey: this.context.apiKey(),
13186
+ currentPage: this.context.currentPage(),
13187
+ selectedWidgetKey,
13188
+ intentResolution,
13189
+ componentCapabilities,
13190
+ ...authoringContext,
13191
+ }));
13192
+ if (!preview.valid) {
13193
+ const message = this.context.describePreviewFailure(preview);
13194
+ return {
13195
+ state: 'error',
13196
+ phase: 'preview',
13197
+ assistantMessage: message,
13198
+ canApply: false,
13199
+ statusText: '',
13200
+ errorText: message,
13201
+ preview: null,
13202
+ diagnostics: { intentResolution, preview },
13203
+ };
13204
+ }
13205
+ const applied = await this.context.applyLocalPreview(preview);
13206
+ if (!applied.success) {
13207
+ const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
13208
+ return {
13209
+ state: 'error',
13210
+ phase: 'preview',
13211
+ assistantMessage: message,
13212
+ canApply: false,
13213
+ statusText: '',
13214
+ errorText: message,
13215
+ preview: null,
13216
+ diagnostics: { intentResolution, preview },
13217
+ };
13218
+ }
13219
+ const status = this.context.describePreviewStatus(preview);
13220
+ const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
13221
+ return {
13222
+ state: 'review',
13223
+ phase: 'review',
13224
+ assistantMessage: status,
13225
+ quickReplies: [],
13226
+ canApply: true,
13227
+ statusText,
13228
+ errorText: '',
13229
+ preview,
13230
+ diagnostics: { intentResolution, preview },
13231
+ };
13232
+ }
13233
+ catch (error) {
13234
+ const message = this.context.describeError(error);
13235
+ return {
13236
+ state: 'error',
13237
+ phase: 'preview',
13238
+ assistantMessage: message,
13239
+ canApply: false,
13240
+ statusText: '',
13241
+ errorText: message,
13242
+ preview: null,
13243
+ diagnostics: { intentResolution, streamPreview },
13244
+ };
13245
+ }
13246
+ }
13247
+ shouldRegenerateStreamPreview(intentResolution, preview) {
13248
+ if (!preview?.valid) {
13249
+ return false;
13250
+ }
13251
+ if (intentResolution.artifactKind !== 'dashboard') {
13252
+ return false;
13253
+ }
13254
+ if (preview.uiCompositionPlan) {
13255
+ return false;
13256
+ }
13257
+ return true;
13258
+ }
12758
13259
  phaseForStreamPayload(payload) {
12759
13260
  const phase = this.readString(payload, 'phase');
12760
13261
  if (phase === 'intent.resolve')
@@ -13182,14 +13683,80 @@ class PageBuilderAgenticAuthoringTurnFlow {
13182
13683
  isExecutableIntent(intentResolution) {
13183
13684
  const operationKind = intentResolution.operationKind;
13184
13685
  const artifactKind = intentResolution.artifactKind;
13686
+ const allowsMaterializedArtifactOperation = operationKind === 'create'
13687
+ || operationKind === 'modify'
13688
+ || operationKind === 'remove';
13185
13689
  return !!intentResolution.valid
13186
13690
  && intentResolution.gate?.status === 'eligible'
13187
13691
  && !!intentResolution.selectedCandidate
13188
- && (artifactKind === 'form'
13189
- || artifactKind === 'dashboard'
13190
- || artifactKind === 'table'
13191
- || this.isExecutablePageCompositionIntent(intentResolution))
13192
- && (operationKind === 'create' || operationKind === 'modify' || operationKind === 'remove' || operationKind === 'compose');
13692
+ && ((allowsMaterializedArtifactOperation
13693
+ && (artifactKind === 'form'
13694
+ || artifactKind === 'dashboard'
13695
+ || artifactKind === 'table'))
13696
+ || this.isExecutablePageCompositionIntent(intentResolution));
13697
+ }
13698
+ shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) {
13699
+ if (!this.isGuidedPreviewIntent(intentResolution)) {
13700
+ return false;
13701
+ }
13702
+ if (this.hasBlockingResourceQuickReply(quickReplies)) {
13703
+ return false;
13704
+ }
13705
+ return this.isExplicitPreviewCreationPrompt(prompt);
13706
+ }
13707
+ isGuidedPreviewIntent(intentResolution) {
13708
+ if (!intentResolution.valid || intentResolution.gate?.status !== 'eligible' || !intentResolution.selectedCandidate) {
13709
+ return false;
13710
+ }
13711
+ if (this.isExecutableIntent(intentResolution)) {
13712
+ return true;
13713
+ }
13714
+ const artifactKind = intentResolution.artifactKind;
13715
+ return (artifactKind === 'dashboard' || artifactKind === 'page' || artifactKind === 'table' || artifactKind === 'form')
13716
+ && (intentResolution.operationKind === 'compose' || intentResolution.operationKind === 'explore');
13717
+ }
13718
+ isExplicitPreviewCreationPrompt(prompt) {
13719
+ const normalized = prompt
13720
+ .normalize('NFD')
13721
+ .replace(/[\u0300-\u036f]/g, '')
13722
+ .toLowerCase();
13723
+ const asksHow = [
13724
+ 'como posso',
13725
+ 'quais opcoes',
13726
+ 'quais componentes',
13727
+ 'me oriente',
13728
+ 'explique',
13729
+ 'compare alternativas',
13730
+ ].some((term) => normalized.includes(term));
13731
+ if (asksHow) {
13732
+ return false;
13733
+ }
13734
+ const action = [
13735
+ 'crie',
13736
+ 'criar',
13737
+ 'monte',
13738
+ 'montar',
13739
+ 'gere',
13740
+ 'gerar',
13741
+ 'construa',
13742
+ 'adicione',
13743
+ 'adicionar',
13744
+ 'faca',
13745
+ ].some((term) => normalized.includes(term));
13746
+ const artifact = [
13747
+ 'preview',
13748
+ 'pre visualizacao',
13749
+ 'pre-visualizacao',
13750
+ 'dashboard',
13751
+ 'painel',
13752
+ 'grafico',
13753
+ 'graficos',
13754
+ 'tela',
13755
+ 'pagina',
13756
+ 'componente',
13757
+ 'componentes',
13758
+ ].some((term) => normalized.includes(term));
13759
+ return action && artifact;
13193
13760
  }
13194
13761
  isExecutablePageCompositionIntent(intentResolution) {
13195
13762
  return intentResolution.artifactKind === 'page'
@@ -13557,10 +14124,17 @@ class DynamicPageBuilderComponent {
13557
14124
  agenticAuthoringIncludeLlmDiagnostics = false;
13558
14125
  agenticAuthoringEnableStreaming = false;
13559
14126
  agenticAuthoringContextHints;
14127
+ showPageLifecycleActions = false;
14128
+ canDeleteSavedPage = false;
14129
+ pageLifecycleBusy = false;
14130
+ pageLifecycleResetRevision = null;
13560
14131
  pageChange = new EventEmitter();
13561
14132
  agenticAuthoringApplied = new EventEmitter();
13562
14133
  agenticAuthoringSharedRuleHandoff = new EventEmitter();
14134
+ pageRestart = new EventEmitter();
14135
+ savedPageDeleteRequested = new EventEmitter();
13563
14136
  currentPage = signal({ widgets: [] }, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
14137
+ hasPageWidgets = computed(() => (this.currentPage().widgets || []).length > 0, ...(ngDevMode ? [{ debugName: "hasPageWidgets" }] : []));
13564
14138
  connectionsViewerOpen = signal(false, ...(ngDevMode ? [{ debugName: "connectionsViewerOpen" }] : []));
13565
14139
  agenticAuthoringOpen = signal(false, ...(ngDevMode ? [{ debugName: "agenticAuthoringOpen" }] : []));
13566
14140
  agenticAuthoringPrompt = signal('', ...(ngDevMode ? [{ debugName: "agenticAuthoringPrompt" }] : []));
@@ -13591,6 +14165,8 @@ class DynamicPageBuilderComponent {
13591
14165
  sharedRuleCockpitCollapsed = signal(false, ...(ngDevMode ? [{ debugName: "sharedRuleCockpitCollapsed" }] : []));
13592
14166
  projectKnowledgeCockpitCollapsed = signal(true, ...(ngDevMode ? [{ debugName: "projectKnowledgeCockpitCollapsed" }] : []));
13593
14167
  agenticAuthoringEditingMessageId = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringEditingMessageId" }] : []));
14168
+ selectedWidgetKey = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetKey" }] : []));
14169
+ agenticAuthoringWidgetContextKey = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringWidgetContextKey" }] : []));
13594
14170
  agenticAuthoringPanelLayout = signal({
13595
14171
  left: 16,
13596
14172
  top: 16,
@@ -13617,6 +14193,9 @@ class DynamicPageBuilderComponent {
13617
14193
  if (changes['page']) {
13618
14194
  this.currentPage.set(this.parsePage(this.page) || { widgets: [] });
13619
14195
  }
14196
+ if (changes['pageLifecycleResetRevision'] && !changes['pageLifecycleResetRevision'].isFirstChange()) {
14197
+ this.resetAgenticAuthoringSessionState();
14198
+ }
13620
14199
  }
13621
14200
  showSettings() {
13622
14201
  return !!this.enableCustomization && !this.previewMode;
@@ -13624,13 +14203,21 @@ class DynamicPageBuilderComponent {
13624
14203
  onRuntimePageChange(next) {
13625
14204
  const cloned = this.clonePage(next);
13626
14205
  this.currentPage.set(cloned);
14206
+ this.clearSelectedWidgetIfMissing(cloned);
13627
14207
  this.pageChange.emit(cloned);
13628
14208
  }
13629
14209
  onConnectionEditorPageChange(next) {
13630
14210
  const cloned = this.clonePage(next);
13631
14211
  this.currentPage.set(cloned);
14212
+ this.clearSelectedWidgetIfMissing(cloned);
13632
14213
  this.pageChange.emit(cloned);
13633
14214
  }
14215
+ onRuntimeWidgetSelectionChange(widgetKey) {
14216
+ this.selectedWidgetKey.set(widgetKey);
14217
+ if (this.agenticAuthoringWidgetContextKey()) {
14218
+ this.agenticAuthoringWidgetContextKey.set(widgetKey);
14219
+ }
14220
+ }
13634
14221
  togglePreview() {
13635
14222
  this.previewMode = !this.previewMode;
13636
14223
  if (this.previewMode) {
@@ -13638,6 +14225,7 @@ class DynamicPageBuilderComponent {
13638
14225
  this.agenticAuthoringLlmDiagnostics.set(null);
13639
14226
  this.sharedRuleCockpitCollapsed.set(true);
13640
14227
  this.projectKnowledgeCockpitCollapsed.set(true);
14228
+ this.selectedWidgetKey.set(null);
13641
14229
  }
13642
14230
  }
13643
14231
  toggleAgenticAuthoringLlmDiagnostics() {
@@ -13723,6 +14311,9 @@ class DynamicPageBuilderComponent {
13723
14311
  this.minimizeAgenticAuthoring();
13724
14312
  return;
13725
14313
  }
14314
+ if (!this.agenticAuthoringMinimized()) {
14315
+ this.agenticAuthoringWidgetContextKey.set(null);
14316
+ }
13726
14317
  this.openAgenticAuthoring();
13727
14318
  }
13728
14319
  openAgenticAuthoring() {
@@ -13730,6 +14321,11 @@ class DynamicPageBuilderComponent {
13730
14321
  this.agenticAuthoringError.set('');
13731
14322
  this.syncAgenticAuthoringSession('active');
13732
14323
  }
14324
+ openAgenticAuthoringForWidget(widgetKey) {
14325
+ this.selectedWidgetKey.set(widgetKey);
14326
+ this.agenticAuthoringWidgetContextKey.set(widgetKey);
14327
+ this.openAgenticAuthoring();
14328
+ }
13733
14329
  openAgenticAuthoringFromSession(session) {
13734
14330
  if (session.id !== this.resolveAgenticAuthoringSessionId())
13735
14331
  return;
@@ -13748,15 +14344,67 @@ class DynamicPageBuilderComponent {
13748
14344
  && !this.agenticAuthoringOpen()
13749
14345
  && this.hasAgenticAuthoringSession();
13750
14346
  }
14347
+ agenticAuthoringMinimized() {
14348
+ return this.showAgenticAuthoringDock();
14349
+ }
14350
+ agenticAuthoringToggleLabel() {
14351
+ if (this.agenticAuthoringOpen()) {
14352
+ return this.tx('agentic.toggle.minimize', 'Minimize Praxis copilot');
14353
+ }
14354
+ if (this.agenticAuthoringMinimized()) {
14355
+ return this.tx('agentic.dock.openTooltip', 'Reopen Praxis copilot');
14356
+ }
14357
+ return this.tx('agentic.toggle', 'Create with AI');
14358
+ }
14359
+ agenticAuthoringHeaderTitle() {
14360
+ if (this.agenticAuthoringSharedRuleHandoffState()) {
14361
+ return this.tx('agentic.header.title.governed', 'Praxis governed copilot');
14362
+ }
14363
+ if (this.agenticAuthoringPreviewResult()?.valid) {
14364
+ return this.tx('agentic.header.title.review', 'Praxis review copilot');
14365
+ }
14366
+ if (this.resolveSelectedWidgetKey()) {
14367
+ return this.tx('agentic.header.title.widget', 'Praxis widget copilot');
14368
+ }
14369
+ return this.tx('agentic.header.title.page', 'Praxis page copilot');
14370
+ }
14371
+ agenticAuthoringHeaderSubtitle() {
14372
+ const selectedWidgetLabel = this.resolveSelectedWidgetLabel();
14373
+ if (this.agenticAuthoringSharedRuleHandoffState()) {
14374
+ return this.tx('agentic.header.subtitle.governed', 'Continue the governed semantic-decision flow.');
14375
+ }
14376
+ if (this.agenticAuthoringPreviewResult()?.valid) {
14377
+ return this.tx('agentic.header.subtitle.review', 'Preview ready for review and persistence.');
14378
+ }
14379
+ if (selectedWidgetLabel) {
14380
+ return this.tx('agentic.header.subtitle.widget', 'Focused on {target}.')
14381
+ .replace('{target}', selectedWidgetLabel);
14382
+ }
14383
+ const routePath = this.pageIdentity?.routePath?.trim();
14384
+ if (routePath) {
14385
+ return this.tx('agentic.header.subtitle.route', 'Authoring page route {route}.')
14386
+ .replace('{route}', routePath);
14387
+ }
14388
+ return this.tx('agentic.header.subtitle.page', 'Author page-level layout, widgets and governed materialization.');
14389
+ }
14390
+ agenticAuthoringHeaderModeLabel() {
14391
+ if (this.agenticAuthoringSharedRuleHandoffState()) {
14392
+ return this.tx('agentic.header.mode.governed', 'Governed');
14393
+ }
14394
+ if (this.resolveSelectedWidgetKey()) {
14395
+ return this.tx('agentic.header.mode.widget', 'Widget');
14396
+ }
14397
+ return this.tx('agentic.header.mode.page', 'Page');
14398
+ }
13751
14399
  agenticAuthoringShellLabels() {
13752
14400
  return {
13753
- title: this.tx('agentic.title', 'Praxis semantic copilot'),
13754
- subtitle: this.tx('agentic.subtitle', 'Author governed decisions with previews, confirmation and runtime materialization.'),
14401
+ title: this.agenticAuthoringHeaderTitle(),
14402
+ subtitle: this.agenticAuthoringHeaderSubtitle(),
13755
14403
  close: this.tx('agentic.minimize', 'Minimize'),
13756
14404
  prompt: this.tx('agentic.promptLabel', 'Message'),
13757
14405
  promptPlaceholder: this.tx('agentic.promptPlaceholder', 'Describe the page, dashboard, form or change you need.'),
13758
14406
  emptyConversation: this.tx('agentic.emptyConversation', 'Tell me what you want to create or change. I will ask follow-up questions before applying the preview.'),
13759
- submit: this.tx('agentic.preview', 'Preview'),
14407
+ submit: this.tx('agentic.preview', 'Generate preview'),
13760
14408
  apply: this.tx('agentic.persist', 'Save'),
13761
14409
  conversationAria: this.tx('agentic.conversationAria', 'AI conversation'),
13762
14410
  quickRepliesAria: this.tx('agentic.quickRepliesAria', 'Quick replies'),
@@ -13768,7 +14416,7 @@ class DynamicPageBuilderComponent {
13768
14416
  removeAttachment: this.tx('agentic.removeAttachment', 'Remove attachment'),
13769
14417
  editMessage: this.tx('agentic.editMessage', 'Edit'),
13770
14418
  resendMessage: this.tx('agentic.resendMessage', 'Resend'),
13771
- modeAgenticAuthoring: this.tx('agentic.mode.agenticAuthoring', 'Authoring'),
14419
+ modeAgenticAuthoring: this.agenticAuthoringHeaderModeLabel(),
13772
14420
  modeConfig: this.tx('agentic.mode.config', 'Configuration'),
13773
14421
  modeChat: this.tx('agentic.mode.chat', 'Chat'),
13774
14422
  modeDiagnostic: this.tx('agentic.mode.diagnostic', 'Diagnostic'),
@@ -13784,6 +14432,20 @@ class DynamicPageBuilderComponent {
13784
14432
  stateError: this.tx('agentic.state.error', 'Error'),
13785
14433
  };
13786
14434
  }
14435
+ agenticAuthoringSubmitAction() {
14436
+ const label = this.tx('agentic.preview', 'Generate preview');
14437
+ return {
14438
+ id: 'submit',
14439
+ kind: 'submit-prompt',
14440
+ label,
14441
+ ariaLabel: label,
14442
+ icon: 'send',
14443
+ iconOnly: true,
14444
+ tone: 'primary',
14445
+ requiresPrompt: true,
14446
+ testId: 'page-builder-agentic-preview',
14447
+ };
14448
+ }
13787
14449
  agenticAuthoringDockIcon() {
13788
14450
  const state = this.agenticAuthoringShellState();
13789
14451
  if (state === 'error')
@@ -13852,6 +14514,30 @@ class DynamicPageBuilderComponent {
13852
14514
  || !!this.agenticAuthoringStatus().trim()
13853
14515
  || this.agenticAuthoringBusy();
13854
14516
  }
14517
+ resetAgenticAuthoringSessionState() {
14518
+ this.agenticTurnController = undefined;
14519
+ this.sharedRuleHandoffRevision += 1;
14520
+ this.agenticAuthoringBusy.set(false);
14521
+ this.agenticAuthoringPrompt.set('');
14522
+ this.agenticAuthoringStatus.set('');
14523
+ this.agenticAuthoringError.set('');
14524
+ this.agenticAuthoringPreviewResult.set(null);
14525
+ this.agenticAuthoringConversation.set([]);
14526
+ this.agenticAuthoringQuickReplies.set([]);
14527
+ this.agenticAuthoringAttachments.set([]);
14528
+ this.agenticAuthoringSharedRuleHandoffState.set(null);
14529
+ this.agenticAuthoringLlmDiagnostics.set(null);
14530
+ this.agenticAuthoringEditingMessageId.set(null);
14531
+ this.selectedWidgetKey.set(null);
14532
+ this.agenticAuthoringWidgetContextKey.set(null);
14533
+ this.connectionsViewerOpen.set(false);
14534
+ this.clearSharedRuleCockpitState();
14535
+ this.clearProjectKnowledgeCockpitState();
14536
+ this.assistantSessions.removeSession(this.resolveAgenticAuthoringSessionId());
14537
+ if (this.agenticAuthoringOpen()) {
14538
+ this.syncAgenticAuthoringSession('active');
14539
+ }
14540
+ }
13855
14541
  syncAgenticAuthoringSession(visibility = null) {
13856
14542
  if (!this.enableAgenticAuthoring || !this.enableCustomization)
13857
14543
  return;
@@ -13861,7 +14547,7 @@ class DynamicPageBuilderComponent {
13861
14547
  id: this.resolveAgenticAuthoringSessionId(),
13862
14548
  ownerId: this.componentInstanceId || this.pageIdentity?.routePath || 'page-builder',
13863
14549
  ownerType: 'page-builder',
13864
- title: this.tx('agentic.session.title', 'Praxis semantic copilot'),
14550
+ title: this.agenticAuthoringHeaderTitle(),
13865
14551
  summary: this.agenticAuthoringDockSummary(),
13866
14552
  mode: 'agentic-authoring',
13867
14553
  state: this.agenticAuthoringShellState(),
@@ -14021,16 +14707,17 @@ class DynamicPageBuilderComponent {
14021
14707
  }
14022
14708
  const selectedWidgetKey = this.resolveSelectedWidgetKey();
14023
14709
  if (selectedWidgetKey) {
14710
+ const selectedWidget = this.resolveWidgetByKey(selectedWidgetKey);
14024
14711
  items.push({
14025
14712
  id: 'selection',
14026
14713
  kind: 'selection',
14027
14714
  label: this.tx('agentic.context.selection', 'Selection'),
14028
- value: selectedWidgetKey,
14715
+ value: this.describeSelectedWidgetContext(selectedWidget, selectedWidgetKey),
14029
14716
  icon: 'select_all',
14030
14717
  });
14031
14718
  }
14032
14719
  const governedDomainContext = this.resolveGovernedDomainContextSummary(this.agenticAuthoringLlmDiagnostics());
14033
- if (governedDomainContext) {
14720
+ if (governedDomainContext && this.shouldShowGovernedDomainContext(governedDomainContext)) {
14034
14721
  items.push({
14035
14722
  id: 'governed-domain-context',
14036
14723
  kind: 'custom',
@@ -14216,7 +14903,7 @@ class DynamicPageBuilderComponent {
14216
14903
  this.agenticAuthoringEditingMessageId.set(null);
14217
14904
  const contextHints = reply.contextHints ? { ...reply.contextHints } : undefined;
14218
14905
  const visiblePrompt = this.agenticQuickReplyVisiblePrompt(reply, contextHints);
14219
- const submittedPrompt = (reply.prompt || '').trim() || visiblePrompt;
14906
+ const submittedPrompt = this.agenticQuickReplySubmittedPrompt(reply, contextHints, visiblePrompt, this.ensureAgenticTurnController().snapshot().pendingClarification);
14220
14907
  if (this.promoteSharedRuleHandoffFromQuickReply(reply, contextHints, visiblePrompt)) {
14221
14908
  return;
14222
14909
  }
@@ -14232,12 +14919,14 @@ class DynamicPageBuilderComponent {
14232
14919
  try {
14233
14920
  const controller = this.ensureAgenticTurnController();
14234
14921
  const actionKind = controller.snapshot().state === 'clarification'
14922
+ && !this.isGovernedConfirmationQuickReply(reply, contextHints)
14235
14923
  ? 'clarify'
14236
14924
  : replyKind || 'quick-reply';
14237
14925
  await this.consumeAgenticTurn(controller.submitPrompt(submittedPrompt, {
14238
14926
  kind: actionKind,
14239
14927
  id: reply.id,
14240
14928
  value: reply.prompt,
14929
+ displayPrompt: visiblePrompt,
14241
14930
  contextHints,
14242
14931
  }));
14243
14932
  }
@@ -14252,18 +14941,110 @@ class DynamicPageBuilderComponent {
14252
14941
  }
14253
14942
  }
14254
14943
  agenticQuickReplyVisiblePrompt(reply, contextHints) {
14944
+ const prompt = (reply.prompt || '').trim();
14945
+ if (this.isGovernedConfirmationQuickReply(reply, contextHints)) {
14946
+ return (reply.label || prompt || this.tx('agentic.quickReplies.confirm', 'Confirm')).trim();
14947
+ }
14255
14948
  if (!this.isResourceQuickReply(reply, contextHints)) {
14256
- return reply.prompt;
14949
+ return prompt;
14950
+ }
14951
+ if (this.isHumanSafeResourceQuickReplyPrompt(prompt, contextHints)) {
14952
+ return prompt;
14257
14953
  }
14258
14954
  const label = (reply.label || this.describeResourceContext(contextHints) || reply.prompt).trim();
14259
- const resourcePath = String(contextHints?.['resourcePath'] || '').trim();
14260
- return this.tx('agentic.quickReplies.resourceSelectionPrompt', 'Use {label} ({resourcePath}) as the data source.')
14955
+ return this.tx('agentic.quickReplies.resourceSelectionPrompt', 'Usar {label} como fonte de dados.')
14261
14956
  .replace('{label}', label)
14262
- .replace('{resourcePath}', resourcePath);
14957
+ .replace('{resourcePath}', '');
14958
+ }
14959
+ agenticQuickReplySubmittedPrompt(reply, contextHints, visiblePrompt, pendingClarification) {
14960
+ const prompt = (reply.prompt || '').trim();
14961
+ if (this.isGovernedConfirmationQuickReply(reply, contextHints)) {
14962
+ if (prompt
14963
+ && !this.isGenericDataSourceQuickReplyPrompt(prompt)
14964
+ && !this.isGenericGovernedConfirmationQuickReplyPrompt(prompt)) {
14965
+ return prompt;
14966
+ }
14967
+ return this.agenticQuickReplyGovernedConfirmationPrompt(contextHints, visiblePrompt);
14968
+ }
14969
+ if (!this.isResourceQuickReply(reply, contextHints)) {
14970
+ if (this.isConfirmationQuickReply(reply)) {
14971
+ return this.agenticQuickReplyClarificationConfirmationPrompt(pendingClarification, prompt || visiblePrompt);
14972
+ }
14973
+ return prompt || visiblePrompt;
14974
+ }
14975
+ if (this.isGenericDataSourceQuickReplyPrompt(prompt) && this.isConfirmationQuickReply(reply)) {
14976
+ return this.agenticQuickReplyGovernedConfirmationPrompt(contextHints, visiblePrompt);
14977
+ }
14978
+ return this.isHumanSafeResourceQuickReplyPrompt(prompt, contextHints)
14979
+ ? prompt
14980
+ : visiblePrompt;
14981
+ }
14982
+ agenticQuickReplyClarificationConfirmationPrompt(pendingClarification, confirmationText) {
14983
+ const sourcePrompt = (pendingClarification?.sourcePrompt || '').trim();
14984
+ const confirmation = confirmationText.trim();
14985
+ if (!sourcePrompt || !confirmation) {
14986
+ return confirmation || sourcePrompt;
14987
+ }
14988
+ if (sourcePrompt === confirmation) {
14989
+ return sourcePrompt;
14990
+ }
14991
+ return `${sourcePrompt}\n\nConfirmed: ${confirmation}`;
14992
+ }
14993
+ isHumanSafeResourceQuickReplyPrompt(prompt, contextHints) {
14994
+ const trimmed = prompt.trim();
14995
+ if (!trimmed)
14996
+ return false;
14997
+ const resourcePath = String(contextHints?.['resourcePath'] || '').trim();
14998
+ if (resourcePath && trimmed.includes(resourcePath))
14999
+ return false;
15000
+ if (/\bConfirmed\s*:/i.test(trimmed))
15001
+ return false;
15002
+ return !/\/api\/[A-Za-z0-9_./:-]+/.test(trimmed)
15003
+ && !/\bresourcePath\b/i.test(trimmed)
15004
+ && !/\bas the data source\b/i.test(trimmed);
15005
+ }
15006
+ isGenericDataSourceQuickReplyPrompt(prompt) {
15007
+ return /\bas the data source\b/i.test(prompt)
15008
+ || /\bcomo fonte de dados\b/i.test(prompt);
15009
+ }
15010
+ isGenericGovernedConfirmationQuickReplyPrompt(prompt) {
15011
+ return /^gerar\s+pr[eé]via\s+governada\.?$/i.test(prompt.trim())
15012
+ || /^generate\s+governed\s+preview\.?$/i.test(prompt.trim());
15013
+ }
15014
+ agenticQuickReplyGovernedConfirmationPrompt(contextHints, visiblePrompt) {
15015
+ const artifactKind = typeof contextHints?.['artifactKind'] === 'string'
15016
+ ? contextHints['artifactKind'].trim()
15017
+ : 'dashboard';
15018
+ const resourcePath = typeof contextHints?.['resourcePath'] === 'string'
15019
+ ? contextHints['resourcePath'].trim()
15020
+ : '';
15021
+ const submitUrl = typeof contextHints?.['submitUrl'] === 'string'
15022
+ ? contextHints['submitUrl'].trim()
15023
+ : '';
15024
+ const artifactLabel = artifactKind || 'dashboard';
15025
+ if (resourcePath) {
15026
+ const operation = submitUrl && submitUrl !== resourcePath
15027
+ ? ` via ${submitUrl}`
15028
+ : '';
15029
+ return `Crie um ${artifactLabel} governado\n\nConfirmed: usar ${resourcePath}${operation}`;
15030
+ }
15031
+ return visiblePrompt;
14263
15032
  }
14264
15033
  isResourceQuickReply(reply, contextHints) {
14265
- return reply.kind === 'suggestion'
14266
- && typeof contextHints?.['resourcePath'] === 'string'
15034
+ return this.hasResourceContextHint(contextHints)
15035
+ && !['cancel', 'revise'].includes((reply.kind || '').trim().toLowerCase());
15036
+ }
15037
+ isGovernedConfirmationQuickReply(reply, contextHints) {
15038
+ return this.isConfirmationQuickReply(reply)
15039
+ && this.hasResourceContextHint(contextHints);
15040
+ }
15041
+ isConfirmationQuickReply(reply) {
15042
+ const kind = (reply.kind || '').trim().toLowerCase();
15043
+ const id = (reply.id || '').trim().toLowerCase();
15044
+ return kind === 'confirm' || id === 'confirm' || id.startsWith('confirm-');
15045
+ }
15046
+ hasResourceContextHint(contextHints) {
15047
+ return typeof contextHints?.['resourcePath'] === 'string'
14267
15048
  && !!String(contextHints['resourcePath']).trim();
14268
15049
  }
14269
15050
  describeResourceContext(contextHints) {
@@ -14334,6 +15115,37 @@ class DynamicPageBuilderComponent {
14334
15115
  this.agenticAuthoringBusy.set(false);
14335
15116
  }
14336
15117
  }
15118
+ async retryAgenticAuthoring() {
15119
+ if (this.agenticAuthoringBusy())
15120
+ return;
15121
+ this.agenticAuthoringEditingMessageId.set(null);
15122
+ this.agenticAuthoringBusy.set(true);
15123
+ this.agenticAuthoringStatus.set(this.tx('agentic.status.resolvingIntent', 'Resolving intent...'));
15124
+ this.agenticAuthoringError.set('');
15125
+ try {
15126
+ await this.consumeAgenticTurn(this.ensureAgenticTurnController().retry());
15127
+ }
15128
+ catch (error) {
15129
+ this.agenticAuthoringStatus.set('');
15130
+ const errorMessage = this.describeAgenticError(error);
15131
+ this.agenticAuthoringError.set(errorMessage);
15132
+ this.appendAgenticMessage('error', errorMessage);
15133
+ }
15134
+ finally {
15135
+ this.agenticAuthoringBusy.set(false);
15136
+ }
15137
+ }
15138
+ async cancelAgenticAuthoring() {
15139
+ if (this.agenticAuthoringBusy())
15140
+ return;
15141
+ this.agenticAuthoringEditingMessageId.set(null);
15142
+ this.agenticAuthoringPrompt.set('');
15143
+ this.agenticAuthoringPreviewResult.set(null);
15144
+ this.agenticAuthoringSharedRuleHandoffState.set(null);
15145
+ this.clearSharedRuleCockpitState();
15146
+ this.clearProjectKnowledgeCockpitState();
15147
+ await this.consumeAgenticTurn(this.ensureAgenticTurnController().cancel());
15148
+ }
14337
15149
  async persistAgenticAuthoring() {
14338
15150
  const preview = this.agenticAuthoringPreviewResult();
14339
15151
  if (!preview || this.agenticAuthoringBusy())
@@ -15425,6 +16237,12 @@ class DynamicPageBuilderComponent {
15425
16237
  promptBlockLength: promptBlock.length,
15426
16238
  };
15427
16239
  }
16240
+ shouldShowGovernedDomainContext(summary) {
16241
+ if (summary.resolutionStatus !== 'not_requested') {
16242
+ return true;
16243
+ }
16244
+ return !!summary.resourceKey || !!summary.query || summary.promptBlockLength > 0;
16245
+ }
15428
16246
  trimmedString(value) {
15429
16247
  return typeof value === 'string' && value.trim() ? value.trim() : null;
15430
16248
  }
@@ -15449,7 +16267,7 @@ class DynamicPageBuilderComponent {
15449
16267
  focusCanvasWidget(widgetKey) {
15450
16268
  if (!widgetKey)
15451
16269
  return;
15452
- this.runtime?.selectCanvasWidget(widgetKey);
16270
+ this.runtime?.selectWidget(widgetKey);
15453
16271
  }
15454
16272
  parsePage(input) {
15455
16273
  if (!input)
@@ -15467,6 +16285,16 @@ class DynamicPageBuilderComponent {
15467
16285
  clonePage(page) {
15468
16286
  return JSON.parse(JSON.stringify(page));
15469
16287
  }
16288
+ clearSelectedWidgetIfMissing(page) {
16289
+ const selected = this.selectedWidgetKey();
16290
+ if (selected && !(page.widgets || []).some((widget) => widget.key === selected)) {
16291
+ this.selectedWidgetKey.set(null);
16292
+ }
16293
+ const agenticTarget = this.agenticAuthoringWidgetContextKey();
16294
+ if (agenticTarget && !(page.widgets || []).some((widget) => widget.key === agenticTarget)) {
16295
+ this.agenticAuthoringWidgetContextKey.set(null);
16296
+ }
16297
+ }
15470
16298
  defaultInputsFor(type, presetInputs) {
15471
16299
  const metadata = this.componentMetadata.get(type);
15472
16300
  const inputs = {};
@@ -15493,16 +16321,39 @@ class DynamicPageBuilderComponent {
15493
16321
  return null;
15494
16322
  }
15495
16323
  resolveSelectedWidgetKey() {
15496
- const runtime = this.runtime;
15497
- if (!runtime)
15498
- return null;
15499
- for (const widget of this.currentPage().widgets ?? []) {
15500
- if (widget?.key && runtime.isCanvasWidgetSelected(widget.key)) {
15501
- return widget.key;
15502
- }
16324
+ const selected = this.agenticAuthoringWidgetContextKey();
16325
+ if (selected && this.resolveWidgetByKey(selected)) {
16326
+ return selected;
15503
16327
  }
15504
16328
  return null;
15505
16329
  }
16330
+ resolveWidgetByKey(widgetKey) {
16331
+ return (this.currentPage().widgets ?? []).find((widget) => widget.key === widgetKey);
16332
+ }
16333
+ resolveSelectedWidgetLabel() {
16334
+ const selectedWidgetKey = this.resolveSelectedWidgetKey();
16335
+ if (!selectedWidgetKey)
16336
+ return null;
16337
+ return this.describeSelectedWidgetContext(this.resolveWidgetByKey(selectedWidgetKey), selectedWidgetKey);
16338
+ }
16339
+ describeSelectedWidgetContext(widget, fallbackKey) {
16340
+ if (!widget) {
16341
+ return fallbackKey;
16342
+ }
16343
+ const componentId = widget.definition?.id || '';
16344
+ const label = this.resolveWidgetDisplayName(widget);
16345
+ return componentId && componentId !== label
16346
+ ? `${label} · ${componentId}`
16347
+ : label || fallbackKey;
16348
+ }
16349
+ resolveWidgetDisplayName(widget) {
16350
+ const shellTitle = String(widget.shell?.title || '').trim();
16351
+ if (shellTitle)
16352
+ return shellTitle;
16353
+ const componentId = widget.definition?.id || '';
16354
+ const metadata = componentId ? this.componentMetadata.get(componentId) : undefined;
16355
+ return metadata?.friendlyName || componentId || widget.key;
16356
+ }
15506
16357
  formatAgenticFailures(failureCodes) {
15507
16358
  const codes = (failureCodes ?? []).filter((code) => !!code);
15508
16359
  if (codes.length === 0) {
@@ -15557,6 +16408,9 @@ class DynamicPageBuilderComponent {
15557
16408
  ]);
15558
16409
  }
15559
16410
  describeAgenticError(error) {
16411
+ if (error?.name === 'TimeoutError') {
16412
+ return this.tx('agentic.errors.streamTimeout', 'The assistant took too long to finish this request. Try again with a narrower request or review the active context.');
16413
+ }
15560
16414
  if (typeof error?.error?.message === 'string' && error.error.message.trim()) {
15561
16415
  return error.error.message.trim();
15562
16416
  }
@@ -15581,7 +16435,7 @@ class DynamicPageBuilderComponent {
15581
16435
  return resolvePraxisPageBuilderText(this.i18n, key, fallback);
15582
16436
  }
15583
16437
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, deps: [{ token: i1.MatDialog }, { token: SETTINGS_PANEL_BRIDGE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
15584
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints" }, outputs: { pageChange: "pageChange", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff" }, providers: [
16438
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
15585
16439
  providePraxisPageBuilderI18n(),
15586
16440
  { provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
15587
16441
  ], viewQueries: [{ propertyName: "runtime", first: true, predicate: ["runtime"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
@@ -15597,7 +16451,10 @@ class DynamicPageBuilderComponent {
15597
16451
  [pageIdentity]="pageIdentity"
15598
16452
  [componentInstanceId]="componentInstanceId"
15599
16453
  [pageEditorComponent]="pageEditorComponent"
16454
+ [showWidgetAssistantButton]="enableAgenticAuthoring"
15600
16455
  (pageChange)="onRuntimePageChange($event)"
16456
+ (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
16457
+ (widgetAssistantRequested)="openAgenticAuthoringForWidget($event)"
15601
16458
  />
15602
16459
 
15603
16460
  <praxis-connection-editor
@@ -15626,8 +16483,9 @@ class DynamicPageBuilderComponent {
15626
16483
  [errorText]="agenticAuthoringError()"
15627
16484
  [busy]="agenticAuthoringBusy()"
15628
16485
  [canApply]="!!agenticAuthoringPreviewResult()?.valid"
15629
- [enableFileAttachments]="true"
15630
- attachmentAccept="image/*,application/json,text/plain,application/pdf"
16486
+ [primaryAction]="agenticAuthoringSubmitAction()"
16487
+ [showAttachAction]="false"
16488
+ [enablePastedAttachments]="false"
15631
16489
  [layout]="agenticAuthoringPanelLayout()"
15632
16490
  [minWidth]="320"
15633
16491
  [minHeight]="280"
@@ -15635,10 +16493,10 @@ class DynamicPageBuilderComponent {
15635
16493
  (promptChange)="agenticAuthoringPrompt.set($event)"
15636
16494
  (submitPrompt)="agenticAuthoringPrompt.set($event); previewAgenticAuthoring()"
15637
16495
  (apply)="persistAgenticAuthoring()"
16496
+ (retryTurn)="retryAgenticAuthoring()"
16497
+ (cancelTurn)="cancelAgenticAuthoring()"
15638
16498
  (quickReply)="submitAgenticQuickReply($event)"
15639
16499
  (attach)="attachAgenticContext()"
15640
- (attachmentsPasted)="addAgenticAttachments($event)"
15641
- (attachmentsSelected)="addAgenticAttachments($event)"
15642
16500
  (removeAttachment)="removeAgenticAttachment($event)"
15643
16501
  (editMessage)="editAgenticMessage($event)"
15644
16502
  (resendMessage)="resendAgenticMessage($event)"
@@ -15920,28 +16778,57 @@ class DynamicPageBuilderComponent {
15920
16778
  [visible]="showSettings()"
15921
16779
  [canUndo]="false"
15922
16780
  [canRedo]="false"
16781
+ [showSave]="autoPersist && hasPageWidgets()"
16782
+ [showPreview]="hasPageWidgets()"
15923
16783
  (add)="onAddComponent()"
15924
16784
  (settings)="openPageSettings()"
15925
16785
  (save)="saveCurrentPage()"
15926
16786
  (preview)="togglePreview()"
15927
16787
  >
16788
+ <button
16789
+ *ngIf="showPageLifecycleActions && hasPageWidgets()"
16790
+ pdx-toolbar-extra
16791
+ mat-mini-fab
16792
+ type="button"
16793
+ [attr.data-testid]="'page-builder-restart-page'"
16794
+ [disabled]="pageLifecycleBusy"
16795
+ [matTooltip]="tx('pageLifecycle.restart', 'Restart page')"
16796
+ [attr.aria-label]="tx('pageLifecycle.restartAria', 'Restart current page locally')"
16797
+ (click)="pageRestart.emit()"
16798
+ >
16799
+ <mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
16800
+ </button>
16801
+ <button
16802
+ *ngIf="showPageLifecycleActions && canDeleteSavedPage"
16803
+ pdx-toolbar-extra
16804
+ mat-mini-fab
16805
+ color="warn"
16806
+ type="button"
16807
+ [attr.data-testid]="'page-builder-delete-saved-page'"
16808
+ [disabled]="pageLifecycleBusy"
16809
+ [matTooltip]="tx('pageLifecycle.deleteSaved', 'Delete saved page')"
16810
+ [attr.aria-label]="tx('pageLifecycle.deleteSavedAria', 'Delete persisted page and restart')"
16811
+ (click)="savedPageDeleteRequested.emit()"
16812
+ >
16813
+ <mat-icon [praxisIcon]="'delete'"></mat-icon>
16814
+ </button>
15928
16815
  <button
15929
16816
  *ngIf="enableAgenticAuthoring"
15930
16817
  pdx-toolbar-extra
15931
16818
  mat-mini-fab
15932
16819
  type="button"
16820
+ class="builder-shell__agentic-toggle"
16821
+ [class.builder-shell__agentic-toggle--open]="agenticAuthoringOpen()"
16822
+ [class.builder-shell__agentic-toggle--minimized]="agenticAuthoringMinimized()"
15933
16823
  [attr.data-testid]="'page-builder-agentic-toggle'"
15934
- [matTooltip]="agenticAuthoringOpen()
15935
- ? tx('agentic.toggle.minimize', 'Minimize Praxis copilot')
15936
- : tx('agentic.toggle', 'Create with AI')"
15937
- [attr.aria-label]="agenticAuthoringOpen()
15938
- ? tx('agentic.toggle.minimize', 'Minimize Praxis copilot')
15939
- : tx('agentic.toggle', 'Create with AI')"
16824
+ [matTooltip]="agenticAuthoringToggleLabel()"
16825
+ [attr.aria-label]="agenticAuthoringToggleLabel()"
15940
16826
  (click)="toggleAgenticAuthoring()"
15941
16827
  >
15942
16828
  <mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
15943
16829
  </button>
15944
16830
  <button
16831
+ *ngIf="hasPageWidgets()"
15945
16832
  pdx-toolbar-extra
15946
16833
  mat-mini-fab
15947
16834
  type="button"
@@ -15954,7 +16841,7 @@ class DynamicPageBuilderComponent {
15954
16841
  </button>
15955
16842
  </praxis-floating-toolbar>
15956
16843
  </div>
15957
- `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId"], outputs: ["pageChange", "widgetEvent", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "busy", "canSubmit", "canApply", "submitOnEnter", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "layoutChange"] }] });
16844
+ `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "layoutChange"] }] });
15958
16845
  }
15959
16846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
15960
16847
  type: Component,
@@ -15984,7 +16871,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15984
16871
  [pageIdentity]="pageIdentity"
15985
16872
  [componentInstanceId]="componentInstanceId"
15986
16873
  [pageEditorComponent]="pageEditorComponent"
16874
+ [showWidgetAssistantButton]="enableAgenticAuthoring"
15987
16875
  (pageChange)="onRuntimePageChange($event)"
16876
+ (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
16877
+ (widgetAssistantRequested)="openAgenticAuthoringForWidget($event)"
15988
16878
  />
15989
16879
 
15990
16880
  <praxis-connection-editor
@@ -16013,8 +16903,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16013
16903
  [errorText]="agenticAuthoringError()"
16014
16904
  [busy]="agenticAuthoringBusy()"
16015
16905
  [canApply]="!!agenticAuthoringPreviewResult()?.valid"
16016
- [enableFileAttachments]="true"
16017
- attachmentAccept="image/*,application/json,text/plain,application/pdf"
16906
+ [primaryAction]="agenticAuthoringSubmitAction()"
16907
+ [showAttachAction]="false"
16908
+ [enablePastedAttachments]="false"
16018
16909
  [layout]="agenticAuthoringPanelLayout()"
16019
16910
  [minWidth]="320"
16020
16911
  [minHeight]="280"
@@ -16022,10 +16913,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16022
16913
  (promptChange)="agenticAuthoringPrompt.set($event)"
16023
16914
  (submitPrompt)="agenticAuthoringPrompt.set($event); previewAgenticAuthoring()"
16024
16915
  (apply)="persistAgenticAuthoring()"
16916
+ (retryTurn)="retryAgenticAuthoring()"
16917
+ (cancelTurn)="cancelAgenticAuthoring()"
16025
16918
  (quickReply)="submitAgenticQuickReply($event)"
16026
16919
  (attach)="attachAgenticContext()"
16027
- (attachmentsPasted)="addAgenticAttachments($event)"
16028
- (attachmentsSelected)="addAgenticAttachments($event)"
16029
16920
  (removeAttachment)="removeAgenticAttachment($event)"
16030
16921
  (editMessage)="editAgenticMessage($event)"
16031
16922
  (resendMessage)="resendAgenticMessage($event)"
@@ -16307,28 +17198,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16307
17198
  [visible]="showSettings()"
16308
17199
  [canUndo]="false"
16309
17200
  [canRedo]="false"
17201
+ [showSave]="autoPersist && hasPageWidgets()"
17202
+ [showPreview]="hasPageWidgets()"
16310
17203
  (add)="onAddComponent()"
16311
17204
  (settings)="openPageSettings()"
16312
17205
  (save)="saveCurrentPage()"
16313
17206
  (preview)="togglePreview()"
16314
17207
  >
17208
+ <button
17209
+ *ngIf="showPageLifecycleActions && hasPageWidgets()"
17210
+ pdx-toolbar-extra
17211
+ mat-mini-fab
17212
+ type="button"
17213
+ [attr.data-testid]="'page-builder-restart-page'"
17214
+ [disabled]="pageLifecycleBusy"
17215
+ [matTooltip]="tx('pageLifecycle.restart', 'Restart page')"
17216
+ [attr.aria-label]="tx('pageLifecycle.restartAria', 'Restart current page locally')"
17217
+ (click)="pageRestart.emit()"
17218
+ >
17219
+ <mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
17220
+ </button>
17221
+ <button
17222
+ *ngIf="showPageLifecycleActions && canDeleteSavedPage"
17223
+ pdx-toolbar-extra
17224
+ mat-mini-fab
17225
+ color="warn"
17226
+ type="button"
17227
+ [attr.data-testid]="'page-builder-delete-saved-page'"
17228
+ [disabled]="pageLifecycleBusy"
17229
+ [matTooltip]="tx('pageLifecycle.deleteSaved', 'Delete saved page')"
17230
+ [attr.aria-label]="tx('pageLifecycle.deleteSavedAria', 'Delete persisted page and restart')"
17231
+ (click)="savedPageDeleteRequested.emit()"
17232
+ >
17233
+ <mat-icon [praxisIcon]="'delete'"></mat-icon>
17234
+ </button>
16315
17235
  <button
16316
17236
  *ngIf="enableAgenticAuthoring"
16317
17237
  pdx-toolbar-extra
16318
17238
  mat-mini-fab
16319
17239
  type="button"
17240
+ class="builder-shell__agentic-toggle"
17241
+ [class.builder-shell__agentic-toggle--open]="agenticAuthoringOpen()"
17242
+ [class.builder-shell__agentic-toggle--minimized]="agenticAuthoringMinimized()"
16320
17243
  [attr.data-testid]="'page-builder-agentic-toggle'"
16321
- [matTooltip]="agenticAuthoringOpen()
16322
- ? tx('agentic.toggle.minimize', 'Minimize Praxis copilot')
16323
- : tx('agentic.toggle', 'Create with AI')"
16324
- [attr.aria-label]="agenticAuthoringOpen()
16325
- ? tx('agentic.toggle.minimize', 'Minimize Praxis copilot')
16326
- : tx('agentic.toggle', 'Create with AI')"
17244
+ [matTooltip]="agenticAuthoringToggleLabel()"
17245
+ [attr.aria-label]="agenticAuthoringToggleLabel()"
16327
17246
  (click)="toggleAgenticAuthoring()"
16328
17247
  >
16329
17248
  <mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
16330
17249
  </button>
16331
17250
  <button
17251
+ *ngIf="hasPageWidgets()"
16332
17252
  pdx-toolbar-extra
16333
17253
  mat-mini-fab
16334
17254
  type="button"
@@ -16341,7 +17261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16341
17261
  </button>
16342
17262
  </praxis-floating-toolbar>
16343
17263
  </div>
16344
- `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
17264
+ `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
16345
17265
  }], ctorParameters: () => [{ type: i1.MatDialog }, { type: undefined, decorators: [{
16346
17266
  type: Optional
16347
17267
  }, {
@@ -16388,12 +17308,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16388
17308
  type: Input
16389
17309
  }], agenticAuthoringContextHints: [{
16390
17310
  type: Input
17311
+ }], showPageLifecycleActions: [{
17312
+ type: Input
17313
+ }], canDeleteSavedPage: [{
17314
+ type: Input
17315
+ }], pageLifecycleBusy: [{
17316
+ type: Input
17317
+ }], pageLifecycleResetRevision: [{
17318
+ type: Input
16391
17319
  }], pageChange: [{
16392
17320
  type: Output
16393
17321
  }], agenticAuthoringApplied: [{
16394
17322
  type: Output
16395
17323
  }], agenticAuthoringSharedRuleHandoff: [{
16396
17324
  type: Output
17325
+ }], pageRestart: [{
17326
+ type: Output
17327
+ }], savedPageDeleteRequested: [{
17328
+ type: Output
16397
17329
  }] } });
16398
17330
 
16399
17331
  /*
@@ -16405,4 +17337,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16405
17337
  * Generated bundle index. Do not edit.
16406
17338
  */
16407
17339
 
16408
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, registerWidgetAiCatalog, registerWidgetAiCatalogs };
17340
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };