@praxisui/page-builder 10.0.0-rc.6 → 10.0.0-rc.8

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Inject, ChangeDetectionStrategy, Component, EventEmitter, Output, Input, inject, ElementRef, signal, computed, effect, Optional, input, output, Injector, viewChild, afterNextRender, afterEveryRender, ViewChild, InjectionToken, ENVIRONMENT_INITIALIZER, Injectable, isSignal, ChangeDetectorRef } from '@angular/core';
2
+ import { Inject, ChangeDetectionStrategy, Component, EventEmitter, Output, Input, inject, ElementRef, signal, computed, effect, Optional, input, output, Injector, viewChild, afterNextRender, afterEveryRender, ViewChild, InjectionToken, ENVIRONMENT_INITIALIZER, Injectable, isSignal } from '@angular/core';
3
3
  import * as i2 from '@angular/material/button';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i1 from '@angular/material/dialog';
@@ -7,7 +7,7 @@ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
7
7
  import * as i2$1 from '@angular/material/icon';
8
8
  import { MatIconModule } from '@angular/material/icon';
9
9
  import * as i2$2 from '@praxisui/core';
10
- import { PraxisIconDirective, providePraxisI18n, BUILTIN_WIDGET_SHELL_PRESETS, SETTINGS_EDITOR_SECTIONS_HOSTED, PraxisI18nService, getWidgetShellActionIdError, WidgetShellComponent, SettingsSectionTabsComponent, PraxisIconButtonComponent, GLOBAL_ACTION_CATALOG, ComponentMetadataRegistry, CompositionValidatorService, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, BUILTIN_PAGE_LAYOUT_PRESETS, resolveWidgetPageLayoutPreset, BUILTIN_PAGE_THEME_PRESETS, prepareCanvasArrangement, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, validateCanvasArrangement, PraxisJsonLogicService, NestedWidgetConfigAccessor, canonicalJsonSha256, ResourceDiscoveryService, ComponentRuntimeProfileService, buildApiUrl, deepMerge, generateId, ObservabilityDashboardService, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR, CONFIG_STORAGE, ASYNC_CONFIG_STORAGE } from '@praxisui/core';
10
+ import { PraxisIconDirective, providePraxisI18n, BUILTIN_WIDGET_SHELL_PRESETS, SETTINGS_EDITOR_SECTIONS_HOSTED, PraxisI18nService, getWidgetShellActionIdError, WidgetShellComponent, SettingsSectionTabsComponent, PraxisIconButtonComponent, GLOBAL_ACTION_CATALOG, ComponentMetadataRegistry, CompositionValidatorService, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, BUILTIN_PAGE_LAYOUT_PRESETS, resolveWidgetPageLayoutPreset, BUILTIN_PAGE_THEME_PRESETS, prepareCanvasArrangement, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, validateCanvasArrangement, PraxisJsonLogicService, NestedWidgetConfigAccessor, canonicalJsonSha256, ResourceDiscoveryService, ComponentRuntimeProfileService, buildApiUrl, deepMerge, generateId, ObservabilityDashboardService, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
11
11
  import * as i3 from '@angular/material/tooltip';
12
12
  import { MatTooltipModule } from '@angular/material/tooltip';
13
13
  import * as i4 from '@angular/material/form-field';
@@ -32,7 +32,6 @@ import * as i8 from '@angular/material/tabs';
32
32
  import { MatTabsModule } from '@angular/material/tabs';
33
33
  import { HttpClient, HttpHeaders } from '@angular/common/http';
34
34
  import { AgenticAuthoringTurnClientService, withAuthoringScopePolicyContextHints, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
35
- import { Router, ActivatedRoute } from '@angular/router';
36
35
 
37
36
  const PLACEHOLDER = 1;
38
37
 
@@ -17622,8 +17621,9 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
17622
17621
  componentId: 'praxis-page-builder',
17623
17622
  ownerPackage: '@praxisui/page-builder',
17624
17623
  configSchemaId: 'WidgetPageDefinition',
17625
- manifestVersion: '1.5.0',
17624
+ manifestVersion: '1.5.1',
17626
17625
  runtimeInputs: [
17626
+ { name: 'autoPersist', type: 'boolean', description: 'Host-only opt-in Core persistence for manual pages. Disabled for agentic authoring and authoringDocument; never use to persist an AI preview.' },
17627
17627
  { name: 'page', type: 'WidgetPageDefinition', description: 'Canonical renderable page document consumed by praxis-dynamic-page.' },
17628
17628
  { name: 'pageIdentity', type: 'PageIdentity | null', description: 'Persistence identity for ui_user_config save/apply flows; not persisted inside page.' },
17629
17629
  { name: 'enableCustomization', type: 'boolean', description: 'Enables page-builder authoring chrome around the runtime page.' },
@@ -26051,7 +26051,8 @@ class DynamicPageBuilderComponent {
26051
26051
  page;
26052
26052
  context = null;
26053
26053
  strictValidation = true;
26054
- autoPersist = true;
26054
+ /** Opt in to Core persistence; hosts managing their own documents leave this disabled. */
26055
+ autoPersist = false;
26055
26056
  enableCustomization = false;
26056
26057
  authoringCapabilities;
26057
26058
  showSettingsButton = true;
@@ -26078,6 +26079,8 @@ class DynamicPageBuilderComponent {
26078
26079
  canDeleteSavedPage = false;
26079
26080
  pageLifecycleBusy = false;
26080
26081
  pageLifecycleResetRevision = null;
26082
+ persistenceChange = output();
26083
+ runtimePersistenceStatus = 'idle';
26081
26084
  pageChange = new EventEmitter();
26082
26085
  /** Emits only explicit visual authoring operations, never runtime state changes. */
26083
26086
  pageAuthoringChange = output();
@@ -26194,7 +26197,7 @@ class DynamicPageBuilderComponent {
26194
26197
  this.persistedUiCompositionAuthoringSource.set(null);
26195
26198
  this.agenticAuthoringLastEtag.set(null);
26196
26199
  }
26197
- else if (changes['page'] && !this.authoringDocument) {
26200
+ else if ((changes['page'] || changes['pageIdentity'] || changes['componentInstanceId']) && !this.authoringDocument) {
26198
26201
  const parsed = this.parsePage(this.page) || { widgets: [] };
26199
26202
  this.currentPage.set(parsed);
26200
26203
  this.lastRuntimePageChangeFingerprint = JSON.stringify(parsed);
@@ -26324,13 +26327,36 @@ class DynamicPageBuilderComponent {
26324
26327
  }
26325
26328
  return this.tx('builderMode.presentation', 'Presentation');
26326
26329
  }
26330
+ /** Governed documents and agentic previews retain their explicit host/apply lifecycle. */
26331
+ runtimeAutoPersist() {
26332
+ return this.autoPersist && !this.authoringDocument && !this.enableAgenticAuthoring;
26333
+ }
26334
+ /** Explicitly discard the local draft and reload the current identity's saved page. */
26335
+ reloadPersistedPage(defaultPage) {
26336
+ if (this.runtimeAutoPersist())
26337
+ this.runtime?.reloadPersistedPage(defaultPage);
26338
+ }
26339
+ /** Clear the current identity's saved document after storage acknowledgement. */
26340
+ resetPersistedPage(defaultPage) {
26341
+ if (!this.runtimeAutoPersist())
26342
+ return;
26343
+ this.runtime?.resetPersistedPage(defaultPage);
26344
+ }
26345
+ onRuntimePersistenceChange(state) {
26346
+ this.runtimePersistenceStatus = state.status;
26347
+ this.persistenceChange.emit(state);
26348
+ }
26327
26349
  onRuntimePageChange(next) {
26328
- const canonical = this.toCanonicalPageFromRuntime(next);
26350
+ // Core load/reset emits an authoritative persisted document, not our edit-mode projection.
26351
+ const hydrating = this.runtimeAutoPersist()
26352
+ && (this.runtimePersistenceStatus === 'loading' || this.runtimePersistenceStatus === 'resetting');
26353
+ const canonical = hydrating ? this.clonePage(next) : this.toCanonicalPageFromRuntime(next);
26329
26354
  const fingerprint = JSON.stringify(canonical);
26330
26355
  if (fingerprint === this.lastRuntimePageChangeFingerprint) {
26331
26356
  return;
26332
26357
  }
26333
26358
  this.lastRuntimePageChangeFingerprint = fingerprint;
26359
+ this.currentPage.set(canonical);
26334
26360
  this.pageChange.emit(canonical);
26335
26361
  }
26336
26362
  onRuntimePageAuthoringChange(next) {
@@ -26533,6 +26559,12 @@ class DynamicPageBuilderComponent {
26533
26559
  this.connectionsViewerOpen.set(false);
26534
26560
  this.runtime?.openPageSettings();
26535
26561
  }
26562
+ /** Retries the current persisted draft, including an intentionally empty page. */
26563
+ retryPersistedPage() {
26564
+ if (!this.runtimeAutoPersist() || !this.isAuthoringCapabilityEnabled('save'))
26565
+ return;
26566
+ this.runtime?.persistCurrentPage(this.clonePage(this.currentPage()));
26567
+ }
26536
26568
  saveCurrentPage() {
26537
26569
  if (!this.isAuthoringCapabilityEnabled('save'))
26538
26570
  return;
@@ -26543,6 +26575,8 @@ class DynamicPageBuilderComponent {
26543
26575
  const cloned = this.clonePage(this.currentPage());
26544
26576
  this.currentPage.set(cloned);
26545
26577
  this.pageChange.emit(cloned);
26578
+ if (this.runtimeAutoPersist())
26579
+ this.runtime?.persistCurrentPage(cloned);
26546
26580
  this.pageSaveRequested.emit(this.clonePage(cloned));
26547
26581
  }
26548
26582
  canSaveCurrentPage() {
@@ -30025,7 +30059,7 @@ class DynamicPageBuilderComponent {
30025
30059
  return resolvePraxisPageBuilderText(this.i18n, key, fallback);
30026
30060
  }
30027
30061
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageBuilderComponent, deps: [{ token: i1.MatDialog }, { token: SETTINGS_PANEL_BRIDGE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
30028
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", authoringCapabilities: "authoringCapabilities", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", componentPaletteAllowedWidgetIds: "componentPaletteAllowedWidgetIds", componentPaletteAllowedWidgetTags: "componentPaletteAllowedWidgetTags", componentPaletteAllowedPresetIds: "componentPaletteAllowedPresetIds", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringVoiceInputMode: "agenticAuthoringVoiceInputMode", agenticAuthoringContextHints: "agenticAuthoringContextHints", authoringDocument: "authoringDocument", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", pageAuthoringChange: "pageAuthoringChange", widgetEvent: "widgetEvent", pageSaveRequested: "pageSaveRequested", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
30062
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", authoringCapabilities: "authoringCapabilities", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", componentPaletteAllowedWidgetIds: "componentPaletteAllowedWidgetIds", componentPaletteAllowedWidgetTags: "componentPaletteAllowedWidgetTags", componentPaletteAllowedPresetIds: "componentPaletteAllowedPresetIds", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringVoiceInputMode: "agenticAuthoringVoiceInputMode", agenticAuthoringContextHints: "agenticAuthoringContextHints", authoringDocument: "authoringDocument", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { persistenceChange: "persistenceChange", pageChange: "pageChange", pageAuthoringChange: "pageAuthoringChange", widgetEvent: "widgetEvent", pageSaveRequested: "pageSaveRequested", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
30029
30063
  providePraxisPageBuilderI18n(),
30030
30064
  { provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
30031
30065
  ], viewQueries: [{ propertyName: "runtime", first: true, predicate: ["runtime"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
@@ -30100,7 +30134,7 @@ class DynamicPageBuilderComponent {
30100
30134
  [page]="runtimePage()"
30101
30135
  [context]="context"
30102
30136
  [strictValidation]="strictValidation"
30103
- [autoPersist]="false"
30137
+ [autoPersist]="runtimeAutoPersist()"
30104
30138
  [enableCustomization]="showSettings()"
30105
30139
  [authoringCapabilities]="runtimeAuthoringCapabilities()"
30106
30140
  [showPageSettingsButton]="false"
@@ -30109,6 +30143,7 @@ class DynamicPageBuilderComponent {
30109
30143
  [pageEditorComponent]="pageEditorComponent"
30110
30144
  [showWidgetAssistantButton]="canUseAgenticAuthoring()"
30111
30145
  (pageChange)="onRuntimePageChange($event)"
30146
+ (persistenceChange)="onRuntimePersistenceChange($event)"
30112
30147
  (pageAuthoringChange)="onRuntimePageAuthoringChange($event)"
30113
30148
  (widgetEvent)="onRuntimeWidgetEvent($event)"
30114
30149
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
@@ -30597,7 +30632,7 @@ class DynamicPageBuilderComponent {
30597
30632
  }
30598
30633
  </praxis-floating-toolbar>
30599
30634
  </div>
30600
- `, 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%;box-sizing:border-box}.builder-shell--bottom-toolbar{padding-block-end:calc(80px + env(safe-area-inset-bottom,0px))}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-authoring-lineage-alert{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;margin:0 0 14px;padding:12px 14px;border:1px solid var(--md-sys-color-error, #b3261e);border-radius:10px;background:var(--md-sys-color-error-container, #f9dedc);color:var(--md-sys-color-on-error-container, #410e0b)}.builder-authoring-lineage-alert strong{display:block}.builder-authoring-lineage-alert p{margin:4px 0 0}.builder-authoring-lineage-alert ul{margin:8px 0 0;padding-inline-start:20px}@media(forced-colors:active){.builder-authoring-lineage-alert{border:2px solid CanvasText;background:Canvas;color:CanvasText}}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.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 color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 84%,transparent);color:var(--md-sys-color-primary);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}.agentic-diagnostics-panel__health{display:grid;gap:8px;margin-bottom:12px}.agentic-diagnostics-panel__health h3,.agentic-diagnostics-panel__health p{margin:0}.agentic-diagnostics-panel__health h3{font-size:13px}.agentic-diagnostics-panel__health p{color:#4b5563;font-size:11px}.agentic-diagnostics-panel__metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0}.agentic-diagnostics-panel__metrics div{padding:8px;border-radius:8px;background:#f3f4f6}.agentic-diagnostics-panel__metrics dt{color:#4b5563;font-size:10px}.agentic-diagnostics-panel__metrics dd{margin:3px 0 0;font-size:14px;font-weight:700}.agentic-diagnostics-panel__health-table{width:100%;border-collapse:collapse;font-size:10px}.agentic-diagnostics-panel__health-table caption{margin-bottom:4px;text-align:left;font-weight:700}.agentic-diagnostics-panel__health-table th,.agentic-diagnostics-panel__health-table td{padding:5px 4px;border-bottom:1px solid #e5e7eb;text-align:left}.agentic-diagnostics-panel__raw summary{margin-bottom:8px;cursor:pointer;font-size:11px;font-weight:700}@media(max-width:520px){.agentic-diagnostics-panel__metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.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}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.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 color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface-container-high) 76%),color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container) 82%));color:var(--md-sys-color-on-surface);box-shadow:0 18px 46px color-mix(in srgb,var(--md-sys-color-shadow, #000) 24%,transparent);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:var(--md-sys-color-on-surface-variant);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 74%,transparent);color:var(--md-sys-color-primary);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:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:var(--md-sys-color-error);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:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 72%,transparent)}.shared-rule-cockpit__facts dt{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:var(--md-sys-color-on-surface);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 58%,transparent)}.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:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:var(--md-sys-color-on-surface-variant);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 color-mix(in srgb,var(--md-sys-color-outline-variant) 52%,transparent);border-radius:11px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent)}.shared-rule-cockpit__projection[data-status=ready]{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 24%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 32%,var(--md-sys-color-surface-container-low) 68%)}.shared-rule-cockpit__projection span{color:var(--md-sys-color-primary);font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:var(--md-sys-color-on-surface-variant);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 color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 76%,transparent)}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:var(--md-sys-color-primary);font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:var(--md-sys-color-on-surface);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:var(--md-sys-color-on-surface-variant);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:color-mix(in srgb,var(--md-sys-color-secondary-container) 42%,transparent);color:var(--md-sys-color-on-secondary-container);font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 64%,transparent)}@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: 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: i2$1.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", "authoringCapabilities", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "pageAuthoringChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "showAdd", "showSettings", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "addLabel", "saveLabel", "undoLabel", "redoLabel", "settingsLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
30635
+ `, 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%;box-sizing:border-box}.builder-shell--bottom-toolbar{padding-block-end:calc(80px + env(safe-area-inset-bottom,0px))}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-authoring-lineage-alert{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;margin:0 0 14px;padding:12px 14px;border:1px solid var(--md-sys-color-error, #b3261e);border-radius:10px;background:var(--md-sys-color-error-container, #f9dedc);color:var(--md-sys-color-on-error-container, #410e0b)}.builder-authoring-lineage-alert strong{display:block}.builder-authoring-lineage-alert p{margin:4px 0 0}.builder-authoring-lineage-alert ul{margin:8px 0 0;padding-inline-start:20px}@media(forced-colors:active){.builder-authoring-lineage-alert{border:2px solid CanvasText;background:Canvas;color:CanvasText}}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.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 color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 84%,transparent);color:var(--md-sys-color-primary);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}.agentic-diagnostics-panel__health{display:grid;gap:8px;margin-bottom:12px}.agentic-diagnostics-panel__health h3,.agentic-diagnostics-panel__health p{margin:0}.agentic-diagnostics-panel__health h3{font-size:13px}.agentic-diagnostics-panel__health p{color:#4b5563;font-size:11px}.agentic-diagnostics-panel__metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0}.agentic-diagnostics-panel__metrics div{padding:8px;border-radius:8px;background:#f3f4f6}.agentic-diagnostics-panel__metrics dt{color:#4b5563;font-size:10px}.agentic-diagnostics-panel__metrics dd{margin:3px 0 0;font-size:14px;font-weight:700}.agentic-diagnostics-panel__health-table{width:100%;border-collapse:collapse;font-size:10px}.agentic-diagnostics-panel__health-table caption{margin-bottom:4px;text-align:left;font-weight:700}.agentic-diagnostics-panel__health-table th,.agentic-diagnostics-panel__health-table td{padding:5px 4px;border-bottom:1px solid #e5e7eb;text-align:left}.agentic-diagnostics-panel__raw summary{margin-bottom:8px;cursor:pointer;font-size:11px;font-weight:700}@media(max-width:520px){.agentic-diagnostics-panel__metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.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}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.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 color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface-container-high) 76%),color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container) 82%));color:var(--md-sys-color-on-surface);box-shadow:0 18px 46px color-mix(in srgb,var(--md-sys-color-shadow, #000) 24%,transparent);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:var(--md-sys-color-on-surface-variant);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 74%,transparent);color:var(--md-sys-color-primary);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:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:var(--md-sys-color-error);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:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 72%,transparent)}.shared-rule-cockpit__facts dt{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:var(--md-sys-color-on-surface);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 58%,transparent)}.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:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:var(--md-sys-color-on-surface-variant);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 color-mix(in srgb,var(--md-sys-color-outline-variant) 52%,transparent);border-radius:11px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent)}.shared-rule-cockpit__projection[data-status=ready]{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 24%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 32%,var(--md-sys-color-surface-container-low) 68%)}.shared-rule-cockpit__projection span{color:var(--md-sys-color-primary);font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:var(--md-sys-color-on-surface-variant);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 color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 76%,transparent)}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:var(--md-sys-color-primary);font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:var(--md-sys-color-on-surface);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:var(--md-sys-color-on-surface-variant);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:color-mix(in srgb,var(--md-sys-color-secondary-container) 42%,transparent);color:var(--md-sys-color-on-secondary-container);font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 64%,transparent)}@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: 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: i2$1.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", "authoringCapabilities", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "persistenceChange", "pageAuthoringChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "showAdd", "showSettings", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "addLabel", "saveLabel", "undoLabel", "redoLabel", "settingsLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
30601
30636
  }
30602
30637
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
30603
30638
  type: Component,
@@ -30685,7 +30720,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
30685
30720
  [page]="runtimePage()"
30686
30721
  [context]="context"
30687
30722
  [strictValidation]="strictValidation"
30688
- [autoPersist]="false"
30723
+ [autoPersist]="runtimeAutoPersist()"
30689
30724
  [enableCustomization]="showSettings()"
30690
30725
  [authoringCapabilities]="runtimeAuthoringCapabilities()"
30691
30726
  [showPageSettingsButton]="false"
@@ -30694,6 +30729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
30694
30729
  [pageEditorComponent]="pageEditorComponent"
30695
30730
  [showWidgetAssistantButton]="canUseAgenticAuthoring()"
30696
30731
  (pageChange)="onRuntimePageChange($event)"
30732
+ (persistenceChange)="onRuntimePersistenceChange($event)"
30697
30733
  (pageAuthoringChange)="onRuntimePageAuthoringChange($event)"
30698
30734
  (widgetEvent)="onRuntimeWidgetEvent($event)"
30699
30735
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
@@ -31249,7 +31285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31249
31285
  type: Input
31250
31286
  }], pageLifecycleResetRevision: [{
31251
31287
  type: Input
31252
- }], pageChange: [{
31288
+ }], persistenceChange: [{ type: i0.Output, args: ["persistenceChange"] }], pageChange: [{
31253
31289
  type: Output
31254
31290
  }], pageAuthoringChange: [{ type: i0.Output, args: ["pageAuthoringChange"] }], widgetEvent: [{
31255
31291
  type: Output
@@ -31274,7 +31310,11 @@ const PRAXIS_PAGE_BUILDER_COMPONENT_METADATA = {
31274
31310
  description: 'Page builder using the canonical praxis-dynamic-page runtime.',
31275
31311
  tags: ['widget', 'page-builder', 'configurable'],
31276
31312
  lib: '@praxisui/page-builder',
31313
+ inputs: [
31314
+ { name: 'autoPersist', type: 'boolean', description: 'Opt-in Core persistence for manual pages; defaults to false. Disabled for authoringDocument and agentic authoring.' },
31315
+ ],
31277
31316
  outputs: [
31317
+ { name: 'persistenceChange', type: 'WidgetPagePersistenceState', description: 'Core persistence lifecycle and safe failure category; saved requires storage acknowledgement.' },
31278
31318
  {
31279
31319
  name: 'pageChange',
31280
31320
  type: 'WidgetPageDefinition',
@@ -31370,542 +31410,6 @@ function providePraxisPageBuilderWidgets(widgets) {
31370
31410
  return providers;
31371
31411
  }
31372
31412
 
31373
- /**
31374
- * Praxis UI Platform — Zero-Code Canonical Smart Dashboard Page
31375
- *
31376
- * Componente governado de página inteira que orquestra automaticamente a experiência
31377
- * completa de um dashboard corporativo baseado no Praxis Page Builder.
31378
- *
31379
- * Suporta nativamente:
31380
- * - Toolbar executiva de governança e telemetria de layout
31381
- * - Alternância entre modo de visualização e modo de customização de widgets
31382
- * - Persistência transparente de layout por persona/usuário (CONFIG_STORAGE / ASYNC_CONFIG_STORAGE)
31383
- * - Auto-healing entre layout de fábrica e layout salvo
31384
- * - Restauração segura para layout de fábrica
31385
- * - Orquestração reativa de eventos de navegação de widgets
31386
- *
31387
- * Pode ser utilizado diretamente como alvo de rotas do Angular:
31388
- * ```typescript
31389
- * {
31390
- * path: '',
31391
- * component: PraxisDashboardPage,
31392
- * data: {
31393
- * pageKey: 'hq-dashboard',
31394
- * defaultDefinition: DASHBOARD_PAGE_DEFINITION,
31395
- * title: 'HQ TACTICAL OPERATIONAL MATRIX',
31396
- * badge: 'Praxis Page Builder · Canvas Governed',
31397
- * }
31398
- * }
31399
- * ```
31400
- */
31401
- class PraxisDashboardPage {
31402
- router = inject(Router, { optional: true });
31403
- route = inject(ActivatedRoute, { optional: true });
31404
- configStorage = inject(CONFIG_STORAGE, { optional: true });
31405
- asyncConfigStorage = inject(ASYNC_CONFIG_STORAGE, { optional: true });
31406
- cdr = inject(ChangeDetectorRef);
31407
- /** Chave identificadora do dashboard para fins de persistência (ex: 'hq-dashboard') */
31408
- pageKey;
31409
- /** Definição de layout padrão governada de fábrica */
31410
- defaultDefinition;
31411
- /** Contexto dinâmico de dados / expressões injetado nos widgets */
31412
- context;
31413
- /** Título principal exibido na toolbar de governança */
31414
- title;
31415
- /** Subtítulo descritivo */
31416
- subtitle;
31417
- /** Texto da badge de governança */
31418
- badge;
31419
- /** Habilitar/desabilitar exibição da toolbar superior de governança */
31420
- showHeader = true;
31421
- /** Permitir que o usuário acione o modo de customização */
31422
- enableCustomization;
31423
- /** Exibir o botão de engrenagem / configurações de widget quando em edição */
31424
- showSettingsButton;
31425
- /** Escopar o layout salvo por persona / usuário logado */
31426
- personaScoped;
31427
- /** Sobrescrita explícita da chave de armazenamento */
31428
- storageKey;
31429
- /** Notificação de alteração no layout da página */
31430
- pageChange = new EventEmitter();
31431
- /** Eventos emitidos por ações interativas de widgets */
31432
- widgetEvent = new EventEmitter();
31433
- /** Notificação de alteração no status de customização (edição ativa) */
31434
- customizingChange = new EventEmitter();
31435
- /** Notificação de layout restaurado para os padrões de fábrica */
31436
- layoutReset = new EventEmitter();
31437
- // Sinais de estado interno
31438
- isCustomizing = signal(false, ...(ngDevMode ? [{ debugName: "isCustomizing" }] : /* istanbul ignore next */ []));
31439
- isLayoutCustomized = signal(false, ...(ngDevMode ? [{ debugName: "isLayoutCustomized" }] : /* istanbul ignore next */ []));
31440
- lastSavedAt = signal(null, ...(ngDevMode ? [{ debugName: "lastSavedAt" }] : /* istanbul ignore next */ []));
31441
- effectivePageDefinition = signal({ widgets: [] }, ...(ngDevMode ? [{ debugName: "effectivePageDefinition" }] : /* istanbul ignore next */ []));
31442
- // Resolução computada de inputs com fallback para rota Angular
31443
- effectivePageKey = computed(() => {
31444
- return this.pageKey || this.route?.snapshot?.data?.['pageKey'] || 'default-dashboard';
31445
- }, ...(ngDevMode ? [{ debugName: "effectivePageKey" }] : /* istanbul ignore next */ []));
31446
- effectiveDefaultDefinition = computed(() => {
31447
- if (this.defaultDefinition)
31448
- return this.defaultDefinition;
31449
- const fromRoute = this.route?.snapshot?.data?.['defaultDefinition'];
31450
- if (fromRoute)
31451
- return fromRoute;
31452
- return { widgets: [] };
31453
- }, ...(ngDevMode ? [{ debugName: "effectiveDefaultDefinition" }] : /* istanbul ignore next */ []));
31454
- effectiveContext = computed(() => {
31455
- if (this.context !== undefined)
31456
- return this.context;
31457
- return this.route?.snapshot?.data?.['context'] || null;
31458
- }, ...(ngDevMode ? [{ debugName: "effectiveContext" }] : /* istanbul ignore next */ []));
31459
- effectiveTitle = computed(() => {
31460
- return this.title || this.route?.snapshot?.data?.['title'] || 'HQ TACTICAL OPERATIONAL MATRIX';
31461
- }, ...(ngDevMode ? [{ debugName: "effectiveTitle" }] : /* istanbul ignore next */ []));
31462
- effectiveBadge = computed(() => {
31463
- if (this.badge !== undefined)
31464
- return this.badge;
31465
- return this.route?.snapshot?.data?.['badge'] ?? 'Praxis Page Builder 10.0 · Canvas Governed';
31466
- }, ...(ngDevMode ? [{ debugName: "effectiveBadge" }] : /* istanbul ignore next */ []));
31467
- effectiveEnableCustomization = computed(() => {
31468
- if (this.enableCustomization !== undefined)
31469
- return this.enableCustomization;
31470
- const fromRoute = this.route?.snapshot?.data?.['enableCustomization'];
31471
- return fromRoute !== undefined ? fromRoute : true;
31472
- }, ...(ngDevMode ? [{ debugName: "effectiveEnableCustomization" }] : /* istanbul ignore next */ []));
31473
- effectiveShowSettingsButton = computed(() => {
31474
- if (this.showSettingsButton !== undefined)
31475
- return this.showSettingsButton;
31476
- const fromRoute = this.route?.snapshot?.data?.['showSettingsButton'];
31477
- return fromRoute !== undefined ? fromRoute : true;
31478
- }, ...(ngDevMode ? [{ debugName: "effectiveShowSettingsButton" }] : /* istanbul ignore next */ []));
31479
- effectivePersonaScoped = computed(() => {
31480
- if (this.personaScoped !== undefined)
31481
- return this.personaScoped;
31482
- const fromRoute = this.route?.snapshot?.data?.['personaScoped'];
31483
- return fromRoute !== undefined ? fromRoute : true;
31484
- }, ...(ngDevMode ? [{ debugName: "effectivePersonaScoped" }] : /* istanbul ignore next */ []));
31485
- effectiveStorageKey = computed(() => {
31486
- if (this.storageKey)
31487
- return this.storageKey;
31488
- const fromRoute = this.route?.snapshot?.data?.['storageKey'];
31489
- if (fromRoute)
31490
- return fromRoute;
31491
- return `dynamic-page:${this.effectivePageKey()}`;
31492
- }, ...(ngDevMode ? [{ debugName: "effectiveStorageKey" }] : /* istanbul ignore next */ []));
31493
- ngOnInit() {
31494
- this.effectivePageDefinition.set(this.effectiveDefaultDefinition());
31495
- this.loadEffectiveLayout();
31496
- if (typeof window !== 'undefined') {
31497
- window.addEventListener('praxis:identity-switch', this.onIdentitySwitch);
31498
- window.PAX_SAVE_DASHBOARD_LAYOUT = (def) => this.onPageChange(def);
31499
- window.PAX_RELOAD_DASHBOARD_LAYOUT = () => this.loadEffectiveLayout();
31500
- }
31501
- }
31502
- ngOnDestroy() {
31503
- if (typeof window !== 'undefined') {
31504
- window.removeEventListener('praxis:identity-switch', this.onIdentitySwitch);
31505
- delete window.PAX_SAVE_DASHBOARD_LAYOUT;
31506
- delete window.PAX_RELOAD_DASHBOARD_LAYOUT;
31507
- }
31508
- }
31509
- toggleCustomization() {
31510
- const nextState = !this.isCustomizing();
31511
- this.isCustomizing.set(nextState);
31512
- this.customizingChange.emit(nextState);
31513
- }
31514
- resetToFactoryLayout() {
31515
- const key = this.resolveActiveScopedKey();
31516
- if (typeof localStorage !== 'undefined') {
31517
- try {
31518
- localStorage.removeItem(key);
31519
- }
31520
- catch { }
31521
- }
31522
- if (this.asyncConfigStorage) {
31523
- this.asyncConfigStorage.clearConfig(this.effectiveStorageKey()).pipe(take(1)).subscribe({
31524
- next: () => { },
31525
- error: () => { },
31526
- });
31527
- }
31528
- const factoryDef = this.effectiveDefaultDefinition();
31529
- this.effectivePageDefinition.set(factoryDef);
31530
- this.isLayoutCustomized.set(false);
31531
- this.lastSavedAt.set(null);
31532
- this.layoutReset.emit();
31533
- this.pageChange.emit(factoryDef);
31534
- this.cdr.markForCheck();
31535
- }
31536
- onPageChange(newDef) {
31537
- if (!newDef?.widgets)
31538
- return;
31539
- this.effectivePageDefinition.set(newDef);
31540
- this.isLayoutCustomized.set(true);
31541
- const now = new Date();
31542
- const timeStr = now.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
31543
- this.lastSavedAt.set(timeStr);
31544
- const key = this.resolveActiveScopedKey();
31545
- if (typeof localStorage !== 'undefined') {
31546
- try {
31547
- localStorage.setItem(key, JSON.stringify(newDef));
31548
- }
31549
- catch { }
31550
- }
31551
- if (this.asyncConfigStorage) {
31552
- this.asyncConfigStorage.saveConfig(this.effectiveStorageKey(), newDef).pipe(take(1)).subscribe({
31553
- next: () => { },
31554
- error: (err) => console.warn('[PraxisDashboardPage] Falha ao persistir layout remoto:', err),
31555
- });
31556
- }
31557
- this.pageChange.emit(newDef);
31558
- this.cdr.markForCheck();
31559
- }
31560
- handleWidgetEvent(envelope) {
31561
- this.widgetEvent.emit(envelope);
31562
- // Orquestração automática de navegação se o evento for de navegação
31563
- const envAny = envelope;
31564
- const isNavigate = envelope?.output === 'navigate' ||
31565
- envAny?.['type'] === 'navigate' ||
31566
- envAny?.['action'] === 'navigate';
31567
- if (isNavigate) {
31568
- const payload = envelope.payload;
31569
- const targetUrl = (payload?.['url'] || payload?.['path'] || payload?.['route']);
31570
- if (targetUrl && this.router) {
31571
- this.router.navigateByUrl(targetUrl);
31572
- }
31573
- }
31574
- }
31575
- onIdentitySwitch = () => {
31576
- this.isLayoutCustomized.set(false);
31577
- this.effectivePageDefinition.set(this.effectiveDefaultDefinition());
31578
- this.loadEffectiveLayout();
31579
- };
31580
- resolveActiveScopedKey() {
31581
- const baseKey = this.effectiveStorageKey();
31582
- if (!this.effectivePersonaScoped()) {
31583
- return baseKey;
31584
- }
31585
- let personaId = 'default';
31586
- if (typeof window !== 'undefined') {
31587
- try {
31588
- const storedPersona = localStorage.getItem('praxis:auth:current-persona');
31589
- if (storedPersona) {
31590
- const parsed = JSON.parse(storedPersona);
31591
- if (parsed?.id)
31592
- personaId = parsed.id;
31593
- }
31594
- else if (window.__praxis_current_persona_id) {
31595
- personaId = window.__praxis_current_persona_id;
31596
- }
31597
- }
31598
- catch { }
31599
- }
31600
- return `${baseKey}:${personaId}`;
31601
- }
31602
- loadEffectiveLayout() {
31603
- const scopedKey = this.resolveActiveScopedKey();
31604
- const factoryDef = this.effectiveDefaultDefinition();
31605
- // 1. Renderização imediata a partir do cache local da persona
31606
- let stored = null;
31607
- if (typeof localStorage !== 'undefined') {
31608
- try {
31609
- const raw = localStorage.getItem(scopedKey);
31610
- if (raw)
31611
- stored = JSON.parse(raw);
31612
- }
31613
- catch { }
31614
- }
31615
- if (stored && stored.widgets && stored.widgets.length > 0) {
31616
- this.isLayoutCustomized.set(true);
31617
- this.effectivePageDefinition.set(this.mergeWithFactoryDefaults(stored, factoryDef));
31618
- }
31619
- else {
31620
- this.isLayoutCustomized.set(false);
31621
- this.effectivePageDefinition.set(factoryDef);
31622
- }
31623
- // 2. Sincronização assíncrona com backend (praxis-config-starter)
31624
- if (this.asyncConfigStorage) {
31625
- this.asyncConfigStorage
31626
- .loadConfig(this.effectiveStorageKey())
31627
- .pipe(take(1))
31628
- .subscribe({
31629
- next: (remote) => {
31630
- if (remote && remote.widgets && remote.widgets.length > 0) {
31631
- this.isLayoutCustomized.set(true);
31632
- const healed = this.mergeWithFactoryDefaults(remote, factoryDef);
31633
- this.effectivePageDefinition.set(healed);
31634
- if (typeof localStorage !== 'undefined') {
31635
- try {
31636
- localStorage.setItem(scopedKey, JSON.stringify(healed));
31637
- }
31638
- catch { }
31639
- }
31640
- }
31641
- else {
31642
- this.isLayoutCustomized.set(false);
31643
- this.effectivePageDefinition.set(factoryDef);
31644
- if (typeof localStorage !== 'undefined') {
31645
- try {
31646
- localStorage.removeItem(scopedKey);
31647
- }
31648
- catch { }
31649
- }
31650
- }
31651
- this.cdr.markForCheck();
31652
- },
31653
- error: (err) => {
31654
- console.warn('[PraxisDashboardPage] Não foi possível carregar config remota:', err);
31655
- },
31656
- });
31657
- }
31658
- this.cdr.markForCheck();
31659
- }
31660
- mergeWithFactoryDefaults(stored, factory) {
31661
- if (!stored?.widgets?.length)
31662
- return factory;
31663
- if (!factory?.widgets?.length)
31664
- return stored;
31665
- const factoryMap = new Map(factory.widgets.map((w) => [w.key, w]));
31666
- const mergedWidgets = stored.widgets.map((w) => {
31667
- const defaultWidget = factoryMap.get(w.key);
31668
- if (!defaultWidget)
31669
- return w;
31670
- const wAny = w;
31671
- const hasGrid = defaultWidget['grid'] || wAny['grid'];
31672
- return {
31673
- ...defaultWidget,
31674
- ...w,
31675
- ...(hasGrid ? { grid: { ...(defaultWidget['grid'] || {}), ...(wAny['grid'] || {}) } } : {}),
31676
- };
31677
- });
31678
- // Anexa widgets recém-adicionados na fábrica que a versão customizada ainda não conhecia
31679
- const storedKeys = new Set(stored.widgets.map((w) => w.key));
31680
- for (const fw of factory.widgets) {
31681
- if (!storedKeys.has(fw.key)) {
31682
- mergedWidgets.push(fw);
31683
- }
31684
- }
31685
- return {
31686
- ...factory,
31687
- ...stored,
31688
- widgets: mergedWidgets,
31689
- };
31690
- }
31691
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDashboardPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
31692
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDashboardPage, isStandalone: true, selector: "praxis-dashboard-page", inputs: { pageKey: "pageKey", defaultDefinition: "defaultDefinition", context: "context", title: "title", subtitle: "subtitle", badge: "badge", showHeader: "showHeader", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", personaScoped: "personaScoped", storageKey: "storageKey" }, outputs: { pageChange: "pageChange", widgetEvent: "widgetEvent", customizingChange: "customizingChange", layoutReset: "layoutReset" }, ngImport: i0, template: `
31693
- <div class="praxis-dashboard-page dashboard-page-wrapper">
31694
- <!-- Toolbar de Governança do Dashboard -->
31695
- @if (showHeader) {
31696
- <header class="dashboard-toolbar" data-testid="dashboard-governance-toolbar">
31697
- <div class="toolbar-brand">
31698
- <div class="status-indicator">
31699
- <span class="dot-pulse"></span>
31700
- <span class="status-label">{{ effectiveTitle() }}</span>
31701
- </div>
31702
-
31703
- @if (effectiveBadge(); as badgeText) {
31704
- <span class="governance-badge">
31705
- <span class="material-symbols-outlined">dashboard_customize</span>
31706
- {{ badgeText }}
31707
- </span>
31708
- }
31709
-
31710
- <!-- Layout Persistence Status Badge -->
31711
- @if (isLayoutCustomized()) {
31712
- <div
31713
- class="layout-persistence-badge customized"
31714
- data-testid="dashboard-layout-status"
31715
- title="Layout customizado persistido para esta persona"
31716
- >
31717
- <span class="pulse-indicator-amber"></span>
31718
- <span>Layout Customizado (Persistido)</span>
31719
- @if (lastSavedAt(); as saved) {
31720
- <span class="saved-time">· salvo às {{ saved }}</span>
31721
- }
31722
- </div>
31723
- } @else {
31724
- <div
31725
- class="layout-persistence-badge governed"
31726
- data-testid="dashboard-layout-status"
31727
- title="Layout padrão governado de fábrica"
31728
- >
31729
- <span class="pulse-indicator-cyan"></span>
31730
- <span>Layout de Fábrica (Governança)</span>
31731
- </div>
31732
- }
31733
- </div>
31734
-
31735
- <div class="toolbar-actions">
31736
- <ng-content select="[dashboard-toolbar-actions]"></ng-content>
31737
-
31738
- @if (isCustomizing() && isLayoutCustomized()) {
31739
- <button
31740
- type="button"
31741
- class="reset-layout-btn"
31742
- data-testid="reset-layout-btn"
31743
- (click)="resetToFactoryLayout()"
31744
- title="Reverter para o layout padrão de fábrica e descartar customizações desta persona"
31745
- >
31746
- <span class="material-symbols-outlined">restart_alt</span>
31747
- <span>Restaurar Fábrica</span>
31748
- </button>
31749
- }
31750
-
31751
- @if (effectiveEnableCustomization()) {
31752
- <button
31753
- type="button"
31754
- class="customize-toggle-btn"
31755
- data-testid="toggle-customization-btn"
31756
- [class.active]="isCustomizing()"
31757
- (click)="toggleCustomization()"
31758
- [title]="isCustomizing() ? 'Concluir customização de layout' : 'Alternar modo de customização de layout e widgets'"
31759
- >
31760
- <span class="material-symbols-outlined">
31761
- {{ isCustomizing() ? 'visibility' : 'dashboard_customize' }}
31762
- </span>
31763
- <span>{{ isCustomizing() ? 'Concluir Edição' : 'Customizar Layout' }}</span>
31764
- </button>
31765
- }
31766
- </div>
31767
- </header>
31768
- }
31769
-
31770
- <!-- Canvas Oficial Page Builder -->
31771
- <main class="dashboard-canvas-container">
31772
- <praxis-dynamic-page-builder
31773
- [page]="effectivePageDefinition()"
31774
- [context]="effectiveContext()"
31775
- [enableCustomization]="isCustomizing()"
31776
- [showSettingsButton]="isCustomizing() && effectiveShowSettingsButton()"
31777
- (pageChange)="onPageChange($event)"
31778
- (widgetEvent)="handleWidgetEvent($event)"
31779
- />
31780
- </main>
31781
- </div>
31782
- `, isInline: true, styles: [":host{display:block;width:100%}.praxis-dashboard-page{display:flex;flex-direction:column;gap:16px;max-width:1540px;margin:0 auto;width:100%}.dashboard-toolbar{display:flex;justify-content:space-between;align-items:center;padding:10px 18px;border-radius:14px;background:color-mix(in oklab,var(--card, #161b22) 60%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--border, rgba(255, 255, 255, .1));gap:16px;flex-wrap:wrap}.toolbar-brand{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.status-indicator{display:inline-flex;align-items:center;gap:8px;padding:3px 10px;border-radius:9999px;background:color-mix(in oklab,var(--ready, #238636) 12%,transparent);border:1px solid color-mix(in oklab,var(--ready, #238636) 28%,transparent);color:var(--ready, #3fb950);font-size:.68rem;font-weight:700;letter-spacing:.08em}.dot-pulse{width:6px;height:6px;border-radius:50%;background-color:var(--ready, #3fb950);box-shadow:0 0 8px var(--ready, #3fb950);animation:praxis-pulse-glow 2s infinite ease-in-out}@keyframes praxis-pulse-glow{0%,to{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.85)}}.governance-badge{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;color:var(--muted-foreground, #8b949e);font-weight:600}.governance-badge span{font-size:15px;color:var(--cobalt, #58a6ff)}.layout-persistence-badge{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:9999px;font-size:.7rem;font-weight:600;letter-spacing:.04em}.layout-persistence-badge.customized{background:color-mix(in oklab,var(--warning, #d29922) 15%,transparent);border:1px solid color-mix(in oklab,var(--warning, #d29922) 35%,transparent);color:var(--warning, #e3b341)}.layout-persistence-badge.governed{background:color-mix(in oklab,var(--cobalt, #58a6ff) 12%,transparent);border:1px solid color-mix(in oklab,var(--cobalt, #58a6ff) 30%,transparent);color:var(--cobalt, #58a6ff)}.layout-persistence-badge .saved-time{font-size:.65rem;opacity:.8}.pulse-indicator-amber{width:6px;height:6px;border-radius:50%;background-color:var(--warning, #d29922);box-shadow:0 0 6px var(--warning, #d29922)}.pulse-indicator-cyan{width:6px;height:6px;border-radius:50%;background-color:var(--cobalt, #58a6ff);box-shadow:0 0 6px var(--cobalt, #58a6ff)}.toolbar-actions{display:flex;align-items:center;gap:10px}.reset-layout-btn{display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 14px;border-radius:10px;font-size:.78rem;font-weight:600;cursor:pointer;border:1px solid color-mix(in oklab,var(--destructive, #f85149) 35%,transparent);background:color-mix(in oklab,var(--destructive, #f85149) 10%,transparent);color:var(--destructive, #f85149);transition:all .2s cubic-bezier(.16,1,.3,1)}.reset-layout-btn:hover{background:var(--destructive, #f85149);color:#fff;border-color:var(--destructive, #f85149);transform:translateY(-1px)}.reset-layout-btn span{font-size:16px}.customize-toggle-btn{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 16px;border-radius:10px;font-size:.8rem;font-weight:600;cursor:pointer;border:1px solid var(--border, rgba(255, 255, 255, .15));background:color-mix(in oklab,var(--card, #161b22) 80%,transparent);color:var(--foreground, #c9d1d9);transition:all .2s cubic-bezier(.16,1,.3,1)}.customize-toggle-btn:hover{border-color:var(--primary, #58a6ff);color:var(--primary, #58a6ff);transform:translateY(-1px)}.customize-toggle-btn.active{background:var(--primary, #1f6feb);color:var(--primary-foreground, #fff);border-color:var(--primary, #1f6feb);box-shadow:0 0 16px color-mix(in oklab,var(--primary, #1f6feb) 40%,transparent)}.customize-toggle-btn span{font-size:18px}.dashboard-canvas-container{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DynamicPageBuilderComponent, selector: "praxis-dynamic-page-builder", inputs: ["page", "context", "strictValidation", "autoPersist", "enableCustomization", "authoringCapabilities", "showSettingsButton", "pageIdentity", "componentInstanceId", "pageEditorComponent", "componentPaletteAllowedWidgetIds", "componentPaletteAllowedWidgetTags", "componentPaletteAllowedPresetIds", "enableAgenticAuthoring", "agenticAuthoringProvider", "agenticAuthoringModel", "agenticAuthoringApiKey", "agenticAuthoringComponentId", "agenticAuthoringScope", "agenticAuthoringEtag", "agenticAuthoringIncludeLlmDiagnostics", "agenticAuthoringEnableStreaming", "agenticAuthoringVoiceInputMode", "agenticAuthoringContextHints", "authoringDocument", "showPageLifecycleActions", "canDeleteSavedPage", "pageLifecycleBusy", "pageLifecycleResetRevision"], outputs: ["pageChange", "pageAuthoringChange", "widgetEvent", "pageSaveRequested", "agenticAuthoringApplied", "agenticAuthoringSharedRuleHandoff", "pageRestart", "savedPageDeleteRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
31783
- }
31784
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDashboardPage, decorators: [{
31785
- type: Component,
31786
- args: [{ selector: 'praxis-dashboard-page', standalone: true, imports: [CommonModule, DynamicPageBuilderComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
31787
- <div class="praxis-dashboard-page dashboard-page-wrapper">
31788
- <!-- Toolbar de Governança do Dashboard -->
31789
- @if (showHeader) {
31790
- <header class="dashboard-toolbar" data-testid="dashboard-governance-toolbar">
31791
- <div class="toolbar-brand">
31792
- <div class="status-indicator">
31793
- <span class="dot-pulse"></span>
31794
- <span class="status-label">{{ effectiveTitle() }}</span>
31795
- </div>
31796
-
31797
- @if (effectiveBadge(); as badgeText) {
31798
- <span class="governance-badge">
31799
- <span class="material-symbols-outlined">dashboard_customize</span>
31800
- {{ badgeText }}
31801
- </span>
31802
- }
31803
-
31804
- <!-- Layout Persistence Status Badge -->
31805
- @if (isLayoutCustomized()) {
31806
- <div
31807
- class="layout-persistence-badge customized"
31808
- data-testid="dashboard-layout-status"
31809
- title="Layout customizado persistido para esta persona"
31810
- >
31811
- <span class="pulse-indicator-amber"></span>
31812
- <span>Layout Customizado (Persistido)</span>
31813
- @if (lastSavedAt(); as saved) {
31814
- <span class="saved-time">· salvo às {{ saved }}</span>
31815
- }
31816
- </div>
31817
- } @else {
31818
- <div
31819
- class="layout-persistence-badge governed"
31820
- data-testid="dashboard-layout-status"
31821
- title="Layout padrão governado de fábrica"
31822
- >
31823
- <span class="pulse-indicator-cyan"></span>
31824
- <span>Layout de Fábrica (Governança)</span>
31825
- </div>
31826
- }
31827
- </div>
31828
-
31829
- <div class="toolbar-actions">
31830
- <ng-content select="[dashboard-toolbar-actions]"></ng-content>
31831
-
31832
- @if (isCustomizing() && isLayoutCustomized()) {
31833
- <button
31834
- type="button"
31835
- class="reset-layout-btn"
31836
- data-testid="reset-layout-btn"
31837
- (click)="resetToFactoryLayout()"
31838
- title="Reverter para o layout padrão de fábrica e descartar customizações desta persona"
31839
- >
31840
- <span class="material-symbols-outlined">restart_alt</span>
31841
- <span>Restaurar Fábrica</span>
31842
- </button>
31843
- }
31844
-
31845
- @if (effectiveEnableCustomization()) {
31846
- <button
31847
- type="button"
31848
- class="customize-toggle-btn"
31849
- data-testid="toggle-customization-btn"
31850
- [class.active]="isCustomizing()"
31851
- (click)="toggleCustomization()"
31852
- [title]="isCustomizing() ? 'Concluir customização de layout' : 'Alternar modo de customização de layout e widgets'"
31853
- >
31854
- <span class="material-symbols-outlined">
31855
- {{ isCustomizing() ? 'visibility' : 'dashboard_customize' }}
31856
- </span>
31857
- <span>{{ isCustomizing() ? 'Concluir Edição' : 'Customizar Layout' }}</span>
31858
- </button>
31859
- }
31860
- </div>
31861
- </header>
31862
- }
31863
-
31864
- <!-- Canvas Oficial Page Builder -->
31865
- <main class="dashboard-canvas-container">
31866
- <praxis-dynamic-page-builder
31867
- [page]="effectivePageDefinition()"
31868
- [context]="effectiveContext()"
31869
- [enableCustomization]="isCustomizing()"
31870
- [showSettingsButton]="isCustomizing() && effectiveShowSettingsButton()"
31871
- (pageChange)="onPageChange($event)"
31872
- (widgetEvent)="handleWidgetEvent($event)"
31873
- />
31874
- </main>
31875
- </div>
31876
- `, styles: [":host{display:block;width:100%}.praxis-dashboard-page{display:flex;flex-direction:column;gap:16px;max-width:1540px;margin:0 auto;width:100%}.dashboard-toolbar{display:flex;justify-content:space-between;align-items:center;padding:10px 18px;border-radius:14px;background:color-mix(in oklab,var(--card, #161b22) 60%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--border, rgba(255, 255, 255, .1));gap:16px;flex-wrap:wrap}.toolbar-brand{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.status-indicator{display:inline-flex;align-items:center;gap:8px;padding:3px 10px;border-radius:9999px;background:color-mix(in oklab,var(--ready, #238636) 12%,transparent);border:1px solid color-mix(in oklab,var(--ready, #238636) 28%,transparent);color:var(--ready, #3fb950);font-size:.68rem;font-weight:700;letter-spacing:.08em}.dot-pulse{width:6px;height:6px;border-radius:50%;background-color:var(--ready, #3fb950);box-shadow:0 0 8px var(--ready, #3fb950);animation:praxis-pulse-glow 2s infinite ease-in-out}@keyframes praxis-pulse-glow{0%,to{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.85)}}.governance-badge{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;color:var(--muted-foreground, #8b949e);font-weight:600}.governance-badge span{font-size:15px;color:var(--cobalt, #58a6ff)}.layout-persistence-badge{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:9999px;font-size:.7rem;font-weight:600;letter-spacing:.04em}.layout-persistence-badge.customized{background:color-mix(in oklab,var(--warning, #d29922) 15%,transparent);border:1px solid color-mix(in oklab,var(--warning, #d29922) 35%,transparent);color:var(--warning, #e3b341)}.layout-persistence-badge.governed{background:color-mix(in oklab,var(--cobalt, #58a6ff) 12%,transparent);border:1px solid color-mix(in oklab,var(--cobalt, #58a6ff) 30%,transparent);color:var(--cobalt, #58a6ff)}.layout-persistence-badge .saved-time{font-size:.65rem;opacity:.8}.pulse-indicator-amber{width:6px;height:6px;border-radius:50%;background-color:var(--warning, #d29922);box-shadow:0 0 6px var(--warning, #d29922)}.pulse-indicator-cyan{width:6px;height:6px;border-radius:50%;background-color:var(--cobalt, #58a6ff);box-shadow:0 0 6px var(--cobalt, #58a6ff)}.toolbar-actions{display:flex;align-items:center;gap:10px}.reset-layout-btn{display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 14px;border-radius:10px;font-size:.78rem;font-weight:600;cursor:pointer;border:1px solid color-mix(in oklab,var(--destructive, #f85149) 35%,transparent);background:color-mix(in oklab,var(--destructive, #f85149) 10%,transparent);color:var(--destructive, #f85149);transition:all .2s cubic-bezier(.16,1,.3,1)}.reset-layout-btn:hover{background:var(--destructive, #f85149);color:#fff;border-color:var(--destructive, #f85149);transform:translateY(-1px)}.reset-layout-btn span{font-size:16px}.customize-toggle-btn{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 16px;border-radius:10px;font-size:.8rem;font-weight:600;cursor:pointer;border:1px solid var(--border, rgba(255, 255, 255, .15));background:color-mix(in oklab,var(--card, #161b22) 80%,transparent);color:var(--foreground, #c9d1d9);transition:all .2s cubic-bezier(.16,1,.3,1)}.customize-toggle-btn:hover{border-color:var(--primary, #58a6ff);color:var(--primary, #58a6ff);transform:translateY(-1px)}.customize-toggle-btn.active{background:var(--primary, #1f6feb);color:var(--primary-foreground, #fff);border-color:var(--primary, #1f6feb);box-shadow:0 0 16px color-mix(in oklab,var(--primary, #1f6feb) 40%,transparent)}.customize-toggle-btn span{font-size:18px}.dashboard-canvas-container{width:100%}\n"] }]
31877
- }], propDecorators: { pageKey: [{
31878
- type: Input
31879
- }], defaultDefinition: [{
31880
- type: Input
31881
- }], context: [{
31882
- type: Input
31883
- }], title: [{
31884
- type: Input
31885
- }], subtitle: [{
31886
- type: Input
31887
- }], badge: [{
31888
- type: Input
31889
- }], showHeader: [{
31890
- type: Input
31891
- }], enableCustomization: [{
31892
- type: Input
31893
- }], showSettingsButton: [{
31894
- type: Input
31895
- }], personaScoped: [{
31896
- type: Input
31897
- }], storageKey: [{
31898
- type: Input
31899
- }], pageChange: [{
31900
- type: Output
31901
- }], widgetEvent: [{
31902
- type: Output
31903
- }], customizingChange: [{
31904
- type: Output
31905
- }], layoutReset: [{
31906
- type: Output
31907
- }] } });
31908
-
31909
31413
  /*
31910
31414
  * Public API Surface of @praxisui/page-builder
31911
31415
  */
@@ -31915,4 +31419,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31915
31419
  * Generated bundle index. Do not edit.
31916
31420
  */
31917
31421
 
31918
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, PraxisDashboardPage, TileToolbarComponent, UiCompositionResourcePreflightService, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, isComponentDocMeta, preflightUiCompositionPlan, preflightUiCompositionPlanResources, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, providePraxisPageBuilderWidgets, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan, verifyUiCompositionAuthoringSource };
31422
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, UiCompositionResourcePreflightService, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, isComponentDocMeta, preflightUiCompositionPlan, preflightUiCompositionPlanResources, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, providePraxisPageBuilderWidgets, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan, verifyUiCompositionAuthoringSource };