@praxisui/page-builder 10.0.0-rc.5 → 10.0.0-rc.7
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,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-12T01:05:29.617Z",
|
|
4
4
|
"packageName": "@praxisui/page-builder",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.7",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 1,
|
|
@@ -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 } 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';
|
|
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 } 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';
|
|
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,6 +32,7 @@ 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';
|
|
35
36
|
|
|
36
37
|
const PLACEHOLDER = 1;
|
|
37
38
|
|
|
@@ -31369,6 +31370,535 @@ function providePraxisPageBuilderWidgets(widgets) {
|
|
|
31369
31370
|
return providers;
|
|
31370
31371
|
}
|
|
31371
31372
|
|
|
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 = input(undefined, ...(ngDevMode ? [{ debugName: "pageKey" }] : /* istanbul ignore next */ []));
|
|
31409
|
+
/** Definição de layout padrão governada de fábrica */
|
|
31410
|
+
defaultDefinition = input(undefined, ...(ngDevMode ? [{ debugName: "defaultDefinition" }] : /* istanbul ignore next */ []));
|
|
31411
|
+
/** Contexto dinâmico de dados / expressões injetado nos widgets */
|
|
31412
|
+
context = input(undefined, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
31413
|
+
/** Título principal exibido na toolbar de governança */
|
|
31414
|
+
title = input(undefined, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
31415
|
+
/** Subtítulo descritivo */
|
|
31416
|
+
subtitle = input(undefined, ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
31417
|
+
/** Texto da badge de governança */
|
|
31418
|
+
badge = input(undefined, ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
31419
|
+
/** Habilitar/desabilitar exibição da toolbar superior de governança */
|
|
31420
|
+
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
|
|
31421
|
+
/** Permitir que o usuário acione o modo de customização */
|
|
31422
|
+
enableCustomization = input(undefined, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : /* istanbul ignore next */ []));
|
|
31423
|
+
/** Exibir o botão de engrenagem / configurações de widget quando em edição */
|
|
31424
|
+
showSettingsButton = input(undefined, ...(ngDevMode ? [{ debugName: "showSettingsButton" }] : /* istanbul ignore next */ []));
|
|
31425
|
+
/** Escopar o layout salvo por persona / usuário logado */
|
|
31426
|
+
personaScoped = input(undefined, ...(ngDevMode ? [{ debugName: "personaScoped" }] : /* istanbul ignore next */ []));
|
|
31427
|
+
/** Sobrescrita explícita da chave de armazenamento */
|
|
31428
|
+
storageKey = input(undefined, ...(ngDevMode ? [{ debugName: "storageKey" }] : /* istanbul ignore next */ []));
|
|
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
|
+
const def = this.defaultDefinition();
|
|
31448
|
+
if (def)
|
|
31449
|
+
return def;
|
|
31450
|
+
const fromRoute = this.route?.snapshot?.data?.['defaultDefinition'];
|
|
31451
|
+
if (fromRoute)
|
|
31452
|
+
return fromRoute;
|
|
31453
|
+
return { widgets: [] };
|
|
31454
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveDefaultDefinition" }] : /* istanbul ignore next */ []));
|
|
31455
|
+
effectiveContext = computed(() => {
|
|
31456
|
+
const ctx = this.context();
|
|
31457
|
+
if (ctx !== undefined)
|
|
31458
|
+
return ctx;
|
|
31459
|
+
return this.route?.snapshot?.data?.['context'] || null;
|
|
31460
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveContext" }] : /* istanbul ignore next */ []));
|
|
31461
|
+
effectiveTitle = computed(() => {
|
|
31462
|
+
return this.title() || this.route?.snapshot?.data?.['title'] || 'HQ TACTICAL OPERATIONAL MATRIX';
|
|
31463
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveTitle" }] : /* istanbul ignore next */ []));
|
|
31464
|
+
effectiveBadge = computed(() => {
|
|
31465
|
+
const b = this.badge();
|
|
31466
|
+
if (b !== undefined)
|
|
31467
|
+
return b;
|
|
31468
|
+
return this.route?.snapshot?.data?.['badge'] ?? 'Praxis Page Builder 10.0 · Canvas Governed';
|
|
31469
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveBadge" }] : /* istanbul ignore next */ []));
|
|
31470
|
+
effectiveEnableCustomization = computed(() => {
|
|
31471
|
+
const ec = this.enableCustomization();
|
|
31472
|
+
if (ec !== undefined)
|
|
31473
|
+
return ec;
|
|
31474
|
+
const fromRoute = this.route?.snapshot?.data?.['enableCustomization'];
|
|
31475
|
+
return fromRoute !== undefined ? fromRoute : true;
|
|
31476
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveEnableCustomization" }] : /* istanbul ignore next */ []));
|
|
31477
|
+
effectiveShowSettingsButton = computed(() => {
|
|
31478
|
+
const sb = this.showSettingsButton();
|
|
31479
|
+
if (sb !== undefined)
|
|
31480
|
+
return sb;
|
|
31481
|
+
const fromRoute = this.route?.snapshot?.data?.['showSettingsButton'];
|
|
31482
|
+
return fromRoute !== undefined ? fromRoute : true;
|
|
31483
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveShowSettingsButton" }] : /* istanbul ignore next */ []));
|
|
31484
|
+
effectivePersonaScoped = computed(() => {
|
|
31485
|
+
const ps = this.personaScoped();
|
|
31486
|
+
if (ps !== undefined)
|
|
31487
|
+
return ps;
|
|
31488
|
+
const fromRoute = this.route?.snapshot?.data?.['personaScoped'];
|
|
31489
|
+
return fromRoute !== undefined ? fromRoute : true;
|
|
31490
|
+
}, ...(ngDevMode ? [{ debugName: "effectivePersonaScoped" }] : /* istanbul ignore next */ []));
|
|
31491
|
+
effectiveStorageKey = computed(() => {
|
|
31492
|
+
const sk = this.storageKey();
|
|
31493
|
+
if (sk)
|
|
31494
|
+
return sk;
|
|
31495
|
+
const fromRoute = this.route?.snapshot?.data?.['storageKey'];
|
|
31496
|
+
if (fromRoute)
|
|
31497
|
+
return fromRoute;
|
|
31498
|
+
return `dynamic-page:${this.effectivePageKey()}`;
|
|
31499
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveStorageKey" }] : /* istanbul ignore next */ []));
|
|
31500
|
+
constructor() {
|
|
31501
|
+
effect(() => {
|
|
31502
|
+
const def = this.effectiveDefaultDefinition();
|
|
31503
|
+
if (!this.isLayoutCustomized()) {
|
|
31504
|
+
this.effectivePageDefinition.set(def);
|
|
31505
|
+
}
|
|
31506
|
+
});
|
|
31507
|
+
}
|
|
31508
|
+
ngOnInit() {
|
|
31509
|
+
this.effectivePageDefinition.set(this.effectiveDefaultDefinition());
|
|
31510
|
+
this.loadEffectiveLayout();
|
|
31511
|
+
if (typeof window !== 'undefined') {
|
|
31512
|
+
window.addEventListener('praxis:identity-switch', this.onIdentitySwitch);
|
|
31513
|
+
window.PAX_SAVE_DASHBOARD_LAYOUT = (def) => this.onPageChange(def);
|
|
31514
|
+
window.PAX_RELOAD_DASHBOARD_LAYOUT = () => this.loadEffectiveLayout();
|
|
31515
|
+
}
|
|
31516
|
+
}
|
|
31517
|
+
ngOnDestroy() {
|
|
31518
|
+
if (typeof window !== 'undefined') {
|
|
31519
|
+
window.removeEventListener('praxis:identity-switch', this.onIdentitySwitch);
|
|
31520
|
+
delete window.PAX_SAVE_DASHBOARD_LAYOUT;
|
|
31521
|
+
delete window.PAX_RELOAD_DASHBOARD_LAYOUT;
|
|
31522
|
+
}
|
|
31523
|
+
}
|
|
31524
|
+
toggleCustomization() {
|
|
31525
|
+
const nextState = !this.isCustomizing();
|
|
31526
|
+
this.isCustomizing.set(nextState);
|
|
31527
|
+
this.customizingChange.emit(nextState);
|
|
31528
|
+
}
|
|
31529
|
+
resetToFactoryLayout() {
|
|
31530
|
+
const key = this.resolveActiveScopedKey();
|
|
31531
|
+
if (typeof localStorage !== 'undefined') {
|
|
31532
|
+
try {
|
|
31533
|
+
localStorage.removeItem(key);
|
|
31534
|
+
}
|
|
31535
|
+
catch { }
|
|
31536
|
+
}
|
|
31537
|
+
if (this.asyncConfigStorage) {
|
|
31538
|
+
this.asyncConfigStorage.clearConfig(this.effectiveStorageKey()).pipe(take(1)).subscribe({
|
|
31539
|
+
next: () => { },
|
|
31540
|
+
error: () => { },
|
|
31541
|
+
});
|
|
31542
|
+
}
|
|
31543
|
+
const factoryDef = this.effectiveDefaultDefinition();
|
|
31544
|
+
this.effectivePageDefinition.set(factoryDef);
|
|
31545
|
+
this.isLayoutCustomized.set(false);
|
|
31546
|
+
this.lastSavedAt.set(null);
|
|
31547
|
+
this.layoutReset.emit();
|
|
31548
|
+
this.pageChange.emit(factoryDef);
|
|
31549
|
+
this.cdr.markForCheck();
|
|
31550
|
+
}
|
|
31551
|
+
onPageChange(newDef) {
|
|
31552
|
+
if (!newDef?.widgets)
|
|
31553
|
+
return;
|
|
31554
|
+
this.effectivePageDefinition.set(newDef);
|
|
31555
|
+
this.isLayoutCustomized.set(true);
|
|
31556
|
+
const now = new Date();
|
|
31557
|
+
const timeStr = now.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
31558
|
+
this.lastSavedAt.set(timeStr);
|
|
31559
|
+
const key = this.resolveActiveScopedKey();
|
|
31560
|
+
if (typeof localStorage !== 'undefined') {
|
|
31561
|
+
try {
|
|
31562
|
+
localStorage.setItem(key, JSON.stringify(newDef));
|
|
31563
|
+
}
|
|
31564
|
+
catch { }
|
|
31565
|
+
}
|
|
31566
|
+
if (this.asyncConfigStorage) {
|
|
31567
|
+
this.asyncConfigStorage.saveConfig(this.effectiveStorageKey(), newDef).pipe(take(1)).subscribe({
|
|
31568
|
+
next: () => { },
|
|
31569
|
+
error: (err) => console.warn('[PraxisDashboardPage] Falha ao persistir layout remoto:', err),
|
|
31570
|
+
});
|
|
31571
|
+
}
|
|
31572
|
+
this.pageChange.emit(newDef);
|
|
31573
|
+
this.cdr.markForCheck();
|
|
31574
|
+
}
|
|
31575
|
+
handleWidgetEvent(envelope) {
|
|
31576
|
+
this.widgetEvent.emit(envelope);
|
|
31577
|
+
// Orquestração automática de navegação se o evento for de navegação
|
|
31578
|
+
const envAny = envelope;
|
|
31579
|
+
const isNavigate = envelope?.output === 'navigate' ||
|
|
31580
|
+
envAny?.['type'] === 'navigate' ||
|
|
31581
|
+
envAny?.['action'] === 'navigate';
|
|
31582
|
+
if (isNavigate) {
|
|
31583
|
+
const payload = envelope.payload;
|
|
31584
|
+
const targetUrl = (payload?.['url'] || payload?.['path'] || payload?.['route']);
|
|
31585
|
+
if (targetUrl && this.router) {
|
|
31586
|
+
this.router.navigateByUrl(targetUrl);
|
|
31587
|
+
}
|
|
31588
|
+
}
|
|
31589
|
+
}
|
|
31590
|
+
onIdentitySwitch = () => {
|
|
31591
|
+
this.isLayoutCustomized.set(false);
|
|
31592
|
+
this.effectivePageDefinition.set(this.effectiveDefaultDefinition());
|
|
31593
|
+
this.loadEffectiveLayout();
|
|
31594
|
+
};
|
|
31595
|
+
resolveActiveScopedKey() {
|
|
31596
|
+
const baseKey = this.effectiveStorageKey();
|
|
31597
|
+
if (!this.effectivePersonaScoped()) {
|
|
31598
|
+
return baseKey;
|
|
31599
|
+
}
|
|
31600
|
+
let personaId = 'default';
|
|
31601
|
+
if (typeof window !== 'undefined') {
|
|
31602
|
+
try {
|
|
31603
|
+
const storedPersona = localStorage.getItem('praxis:auth:current-persona');
|
|
31604
|
+
if (storedPersona) {
|
|
31605
|
+
const parsed = JSON.parse(storedPersona);
|
|
31606
|
+
if (parsed?.id)
|
|
31607
|
+
personaId = parsed.id;
|
|
31608
|
+
}
|
|
31609
|
+
else if (window.__praxis_current_persona_id) {
|
|
31610
|
+
personaId = window.__praxis_current_persona_id;
|
|
31611
|
+
}
|
|
31612
|
+
}
|
|
31613
|
+
catch { }
|
|
31614
|
+
}
|
|
31615
|
+
return `${baseKey}:${personaId}`;
|
|
31616
|
+
}
|
|
31617
|
+
loadEffectiveLayout() {
|
|
31618
|
+
const scopedKey = this.resolveActiveScopedKey();
|
|
31619
|
+
const factoryDef = this.effectiveDefaultDefinition();
|
|
31620
|
+
// 1. Renderização imediata a partir do cache local da persona
|
|
31621
|
+
let stored = null;
|
|
31622
|
+
if (typeof localStorage !== 'undefined') {
|
|
31623
|
+
try {
|
|
31624
|
+
const raw = localStorage.getItem(scopedKey);
|
|
31625
|
+
if (raw)
|
|
31626
|
+
stored = JSON.parse(raw);
|
|
31627
|
+
}
|
|
31628
|
+
catch { }
|
|
31629
|
+
}
|
|
31630
|
+
if (stored && stored.widgets && stored.widgets.length > 0) {
|
|
31631
|
+
this.isLayoutCustomized.set(true);
|
|
31632
|
+
this.effectivePageDefinition.set(this.mergeWithFactoryDefaults(stored, factoryDef));
|
|
31633
|
+
}
|
|
31634
|
+
else {
|
|
31635
|
+
this.isLayoutCustomized.set(false);
|
|
31636
|
+
this.effectivePageDefinition.set(factoryDef);
|
|
31637
|
+
}
|
|
31638
|
+
// 2. Sincronização assíncrona com backend (praxis-config-starter)
|
|
31639
|
+
if (this.asyncConfigStorage) {
|
|
31640
|
+
this.asyncConfigStorage
|
|
31641
|
+
.loadConfig(this.effectiveStorageKey())
|
|
31642
|
+
.pipe(take(1))
|
|
31643
|
+
.subscribe({
|
|
31644
|
+
next: (remote) => {
|
|
31645
|
+
if (remote && remote.widgets && remote.widgets.length > 0) {
|
|
31646
|
+
this.isLayoutCustomized.set(true);
|
|
31647
|
+
const healed = this.mergeWithFactoryDefaults(remote, factoryDef);
|
|
31648
|
+
this.effectivePageDefinition.set(healed);
|
|
31649
|
+
if (typeof localStorage !== 'undefined') {
|
|
31650
|
+
try {
|
|
31651
|
+
localStorage.setItem(scopedKey, JSON.stringify(healed));
|
|
31652
|
+
}
|
|
31653
|
+
catch { }
|
|
31654
|
+
}
|
|
31655
|
+
}
|
|
31656
|
+
else {
|
|
31657
|
+
this.isLayoutCustomized.set(false);
|
|
31658
|
+
this.effectivePageDefinition.set(factoryDef);
|
|
31659
|
+
if (typeof localStorage !== 'undefined') {
|
|
31660
|
+
try {
|
|
31661
|
+
localStorage.removeItem(scopedKey);
|
|
31662
|
+
}
|
|
31663
|
+
catch { }
|
|
31664
|
+
}
|
|
31665
|
+
}
|
|
31666
|
+
this.cdr.markForCheck();
|
|
31667
|
+
},
|
|
31668
|
+
error: (err) => {
|
|
31669
|
+
console.warn('[PraxisDashboardPage] Não foi possível carregar config remota:', err);
|
|
31670
|
+
},
|
|
31671
|
+
});
|
|
31672
|
+
}
|
|
31673
|
+
this.cdr.markForCheck();
|
|
31674
|
+
}
|
|
31675
|
+
mergeWithFactoryDefaults(stored, factory) {
|
|
31676
|
+
if (!stored?.widgets?.length)
|
|
31677
|
+
return factory;
|
|
31678
|
+
if (!factory?.widgets?.length)
|
|
31679
|
+
return stored;
|
|
31680
|
+
const factoryMap = new Map(factory.widgets.map((w) => [w.key, w]));
|
|
31681
|
+
const mergedWidgets = stored.widgets.map((w) => {
|
|
31682
|
+
const defaultWidget = factoryMap.get(w.key);
|
|
31683
|
+
if (!defaultWidget)
|
|
31684
|
+
return w;
|
|
31685
|
+
const wAny = w;
|
|
31686
|
+
const hasGrid = defaultWidget['grid'] || wAny['grid'];
|
|
31687
|
+
return {
|
|
31688
|
+
...defaultWidget,
|
|
31689
|
+
...w,
|
|
31690
|
+
...(hasGrid ? { grid: { ...(defaultWidget['grid'] || {}), ...(wAny['grid'] || {}) } } : {}),
|
|
31691
|
+
};
|
|
31692
|
+
});
|
|
31693
|
+
// Anexa widgets recém-adicionados na fábrica que a versão customizada ainda não conhecia
|
|
31694
|
+
const storedKeys = new Set(stored.widgets.map((w) => w.key));
|
|
31695
|
+
for (const fw of factory.widgets) {
|
|
31696
|
+
if (!storedKeys.has(fw.key)) {
|
|
31697
|
+
mergedWidgets.push(fw);
|
|
31698
|
+
}
|
|
31699
|
+
}
|
|
31700
|
+
return {
|
|
31701
|
+
...factory,
|
|
31702
|
+
...stored,
|
|
31703
|
+
widgets: mergedWidgets,
|
|
31704
|
+
};
|
|
31705
|
+
}
|
|
31706
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDashboardPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
31707
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDashboardPage, isStandalone: true, selector: "praxis-dashboard-page", inputs: { pageKey: { classPropertyName: "pageKey", publicName: "pageKey", isSignal: true, isRequired: false, transformFunction: null }, defaultDefinition: { classPropertyName: "defaultDefinition", publicName: "defaultDefinition", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, showSettingsButton: { classPropertyName: "showSettingsButton", publicName: "showSettingsButton", isSignal: true, isRequired: false, transformFunction: null }, personaScoped: { classPropertyName: "personaScoped", publicName: "personaScoped", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", widgetEvent: "widgetEvent", customizingChange: "customizingChange", layoutReset: "layoutReset" }, ngImport: i0, template: `
|
|
31708
|
+
<div class="praxis-dashboard-page dashboard-page-wrapper">
|
|
31709
|
+
<!-- Toolbar de Governança do Dashboard -->
|
|
31710
|
+
@if (showHeader()) {
|
|
31711
|
+
<header class="dashboard-toolbar" data-testid="dashboard-governance-toolbar">
|
|
31712
|
+
<div class="toolbar-brand">
|
|
31713
|
+
<div class="status-indicator">
|
|
31714
|
+
<span class="dot-pulse"></span>
|
|
31715
|
+
<span class="status-label">{{ effectiveTitle() }}</span>
|
|
31716
|
+
</div>
|
|
31717
|
+
|
|
31718
|
+
@if (effectiveBadge(); as badgeText) {
|
|
31719
|
+
<span class="governance-badge">
|
|
31720
|
+
<span class="material-symbols-outlined">dashboard_customize</span>
|
|
31721
|
+
{{ badgeText }}
|
|
31722
|
+
</span>
|
|
31723
|
+
}
|
|
31724
|
+
|
|
31725
|
+
<!-- Layout Persistence Status Badge -->
|
|
31726
|
+
@if (isLayoutCustomized()) {
|
|
31727
|
+
<div
|
|
31728
|
+
class="layout-persistence-badge customized"
|
|
31729
|
+
data-testid="dashboard-layout-status"
|
|
31730
|
+
title="Layout customizado persistido para esta persona"
|
|
31731
|
+
>
|
|
31732
|
+
<span class="pulse-indicator-amber"></span>
|
|
31733
|
+
<span>Layout Customizado (Persistido)</span>
|
|
31734
|
+
@if (lastSavedAt(); as saved) {
|
|
31735
|
+
<span class="saved-time">· salvo às {{ saved }}</span>
|
|
31736
|
+
}
|
|
31737
|
+
</div>
|
|
31738
|
+
} @else {
|
|
31739
|
+
<div
|
|
31740
|
+
class="layout-persistence-badge governed"
|
|
31741
|
+
data-testid="dashboard-layout-status"
|
|
31742
|
+
title="Layout padrão governado de fábrica"
|
|
31743
|
+
>
|
|
31744
|
+
<span class="pulse-indicator-cyan"></span>
|
|
31745
|
+
<span>Layout de Fábrica (Governança)</span>
|
|
31746
|
+
</div>
|
|
31747
|
+
}
|
|
31748
|
+
</div>
|
|
31749
|
+
|
|
31750
|
+
<div class="toolbar-actions">
|
|
31751
|
+
<ng-content select="[dashboard-toolbar-actions]"></ng-content>
|
|
31752
|
+
|
|
31753
|
+
@if (isCustomizing() && isLayoutCustomized()) {
|
|
31754
|
+
<button
|
|
31755
|
+
type="button"
|
|
31756
|
+
class="reset-layout-btn"
|
|
31757
|
+
data-testid="reset-layout-btn"
|
|
31758
|
+
(click)="resetToFactoryLayout()"
|
|
31759
|
+
title="Reverter para o layout padrão de fábrica e descartar customizações desta persona"
|
|
31760
|
+
>
|
|
31761
|
+
<span class="material-symbols-outlined">restart_alt</span>
|
|
31762
|
+
<span>Restaurar Fábrica</span>
|
|
31763
|
+
</button>
|
|
31764
|
+
}
|
|
31765
|
+
|
|
31766
|
+
@if (effectiveEnableCustomization()) {
|
|
31767
|
+
<button
|
|
31768
|
+
type="button"
|
|
31769
|
+
class="customize-toggle-btn"
|
|
31770
|
+
data-testid="toggle-customization-btn"
|
|
31771
|
+
[class.active]="isCustomizing()"
|
|
31772
|
+
(click)="toggleCustomization()"
|
|
31773
|
+
[title]="isCustomizing() ? 'Concluir customização de layout' : 'Alternar modo de customização de layout e widgets'"
|
|
31774
|
+
>
|
|
31775
|
+
<span class="material-symbols-outlined">
|
|
31776
|
+
{{ isCustomizing() ? 'visibility' : 'dashboard_customize' }}
|
|
31777
|
+
</span>
|
|
31778
|
+
<span>{{ isCustomizing() ? 'Concluir Edição' : 'Customizar Layout' }}</span>
|
|
31779
|
+
</button>
|
|
31780
|
+
}
|
|
31781
|
+
</div>
|
|
31782
|
+
</header>
|
|
31783
|
+
}
|
|
31784
|
+
|
|
31785
|
+
<!-- Canvas Oficial Page Builder -->
|
|
31786
|
+
<main class="dashboard-canvas-container">
|
|
31787
|
+
<praxis-dynamic-page-builder
|
|
31788
|
+
[page]="effectivePageDefinition()"
|
|
31789
|
+
[context]="effectiveContext()"
|
|
31790
|
+
[enableCustomization]="isCustomizing()"
|
|
31791
|
+
[showSettingsButton]="isCustomizing() && effectiveShowSettingsButton()"
|
|
31792
|
+
(pageChange)="onPageChange($event)"
|
|
31793
|
+
(widgetEvent)="handleWidgetEvent($event)"
|
|
31794
|
+
/>
|
|
31795
|
+
</main>
|
|
31796
|
+
</div>
|
|
31797
|
+
`, 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 });
|
|
31798
|
+
}
|
|
31799
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDashboardPage, decorators: [{
|
|
31800
|
+
type: Component,
|
|
31801
|
+
args: [{ selector: 'praxis-dashboard-page', standalone: true, imports: [CommonModule, DynamicPageBuilderComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
31802
|
+
<div class="praxis-dashboard-page dashboard-page-wrapper">
|
|
31803
|
+
<!-- Toolbar de Governança do Dashboard -->
|
|
31804
|
+
@if (showHeader()) {
|
|
31805
|
+
<header class="dashboard-toolbar" data-testid="dashboard-governance-toolbar">
|
|
31806
|
+
<div class="toolbar-brand">
|
|
31807
|
+
<div class="status-indicator">
|
|
31808
|
+
<span class="dot-pulse"></span>
|
|
31809
|
+
<span class="status-label">{{ effectiveTitle() }}</span>
|
|
31810
|
+
</div>
|
|
31811
|
+
|
|
31812
|
+
@if (effectiveBadge(); as badgeText) {
|
|
31813
|
+
<span class="governance-badge">
|
|
31814
|
+
<span class="material-symbols-outlined">dashboard_customize</span>
|
|
31815
|
+
{{ badgeText }}
|
|
31816
|
+
</span>
|
|
31817
|
+
}
|
|
31818
|
+
|
|
31819
|
+
<!-- Layout Persistence Status Badge -->
|
|
31820
|
+
@if (isLayoutCustomized()) {
|
|
31821
|
+
<div
|
|
31822
|
+
class="layout-persistence-badge customized"
|
|
31823
|
+
data-testid="dashboard-layout-status"
|
|
31824
|
+
title="Layout customizado persistido para esta persona"
|
|
31825
|
+
>
|
|
31826
|
+
<span class="pulse-indicator-amber"></span>
|
|
31827
|
+
<span>Layout Customizado (Persistido)</span>
|
|
31828
|
+
@if (lastSavedAt(); as saved) {
|
|
31829
|
+
<span class="saved-time">· salvo às {{ saved }}</span>
|
|
31830
|
+
}
|
|
31831
|
+
</div>
|
|
31832
|
+
} @else {
|
|
31833
|
+
<div
|
|
31834
|
+
class="layout-persistence-badge governed"
|
|
31835
|
+
data-testid="dashboard-layout-status"
|
|
31836
|
+
title="Layout padrão governado de fábrica"
|
|
31837
|
+
>
|
|
31838
|
+
<span class="pulse-indicator-cyan"></span>
|
|
31839
|
+
<span>Layout de Fábrica (Governança)</span>
|
|
31840
|
+
</div>
|
|
31841
|
+
}
|
|
31842
|
+
</div>
|
|
31843
|
+
|
|
31844
|
+
<div class="toolbar-actions">
|
|
31845
|
+
<ng-content select="[dashboard-toolbar-actions]"></ng-content>
|
|
31846
|
+
|
|
31847
|
+
@if (isCustomizing() && isLayoutCustomized()) {
|
|
31848
|
+
<button
|
|
31849
|
+
type="button"
|
|
31850
|
+
class="reset-layout-btn"
|
|
31851
|
+
data-testid="reset-layout-btn"
|
|
31852
|
+
(click)="resetToFactoryLayout()"
|
|
31853
|
+
title="Reverter para o layout padrão de fábrica e descartar customizações desta persona"
|
|
31854
|
+
>
|
|
31855
|
+
<span class="material-symbols-outlined">restart_alt</span>
|
|
31856
|
+
<span>Restaurar Fábrica</span>
|
|
31857
|
+
</button>
|
|
31858
|
+
}
|
|
31859
|
+
|
|
31860
|
+
@if (effectiveEnableCustomization()) {
|
|
31861
|
+
<button
|
|
31862
|
+
type="button"
|
|
31863
|
+
class="customize-toggle-btn"
|
|
31864
|
+
data-testid="toggle-customization-btn"
|
|
31865
|
+
[class.active]="isCustomizing()"
|
|
31866
|
+
(click)="toggleCustomization()"
|
|
31867
|
+
[title]="isCustomizing() ? 'Concluir customização de layout' : 'Alternar modo de customização de layout e widgets'"
|
|
31868
|
+
>
|
|
31869
|
+
<span class="material-symbols-outlined">
|
|
31870
|
+
{{ isCustomizing() ? 'visibility' : 'dashboard_customize' }}
|
|
31871
|
+
</span>
|
|
31872
|
+
<span>{{ isCustomizing() ? 'Concluir Edição' : 'Customizar Layout' }}</span>
|
|
31873
|
+
</button>
|
|
31874
|
+
}
|
|
31875
|
+
</div>
|
|
31876
|
+
</header>
|
|
31877
|
+
}
|
|
31878
|
+
|
|
31879
|
+
<!-- Canvas Oficial Page Builder -->
|
|
31880
|
+
<main class="dashboard-canvas-container">
|
|
31881
|
+
<praxis-dynamic-page-builder
|
|
31882
|
+
[page]="effectivePageDefinition()"
|
|
31883
|
+
[context]="effectiveContext()"
|
|
31884
|
+
[enableCustomization]="isCustomizing()"
|
|
31885
|
+
[showSettingsButton]="isCustomizing() && effectiveShowSettingsButton()"
|
|
31886
|
+
(pageChange)="onPageChange($event)"
|
|
31887
|
+
(widgetEvent)="handleWidgetEvent($event)"
|
|
31888
|
+
/>
|
|
31889
|
+
</main>
|
|
31890
|
+
</div>
|
|
31891
|
+
`, 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"] }]
|
|
31892
|
+
}], ctorParameters: () => [], propDecorators: { pageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageKey", required: false }] }], defaultDefinition: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultDefinition", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], showSettingsButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSettingsButton", required: false }] }], personaScoped: [{ type: i0.Input, args: [{ isSignal: true, alias: "personaScoped", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }], pageChange: [{
|
|
31893
|
+
type: Output
|
|
31894
|
+
}], widgetEvent: [{
|
|
31895
|
+
type: Output
|
|
31896
|
+
}], customizingChange: [{
|
|
31897
|
+
type: Output
|
|
31898
|
+
}], layoutReset: [{
|
|
31899
|
+
type: Output
|
|
31900
|
+
}] } });
|
|
31901
|
+
|
|
31372
31902
|
/*
|
|
31373
31903
|
* Public API Surface of @praxisui/page-builder
|
|
31374
31904
|
*/
|
|
@@ -31378,4 +31908,4 @@ function providePraxisPageBuilderWidgets(widgets) {
|
|
|
31378
31908
|
* Generated bundle index. Do not edit.
|
|
31379
31909
|
*/
|
|
31380
31910
|
|
|
31381
|
-
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 };
|
|
31911
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/page-builder",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.7",
|
|
4
4
|
"description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"@angular/forms": "^21.0.0",
|
|
9
9
|
"@angular/cdk": "^21.0.0",
|
|
10
10
|
"@angular/material": "^21.0.0",
|
|
11
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
12
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
13
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
11
|
+
"@praxisui/ai": "^10.0.0-rc.7",
|
|
12
|
+
"@praxisui/core": "^10.0.0-rc.7",
|
|
13
|
+
"@praxisui/settings-panel": "^10.0.0-rc.7",
|
|
14
14
|
"rxjs": "~7.8.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
@@ -2741,5 +2741,97 @@ declare function isComponentDocMeta(value: unknown): value is ComponentDocMeta;
|
|
|
2741
2741
|
*/
|
|
2742
2742
|
declare function providePraxisPageBuilderWidgets(widgets?: Array<Provider | ComponentDocMeta>): Provider[];
|
|
2743
2743
|
|
|
2744
|
-
|
|
2744
|
+
/**
|
|
2745
|
+
* Praxis UI Platform — Zero-Code Canonical Smart Dashboard Page
|
|
2746
|
+
*
|
|
2747
|
+
* Componente governado de página inteira que orquestra automaticamente a experiência
|
|
2748
|
+
* completa de um dashboard corporativo baseado no Praxis Page Builder.
|
|
2749
|
+
*
|
|
2750
|
+
* Suporta nativamente:
|
|
2751
|
+
* - Toolbar executiva de governança e telemetria de layout
|
|
2752
|
+
* - Alternância entre modo de visualização e modo de customização de widgets
|
|
2753
|
+
* - Persistência transparente de layout por persona/usuário (CONFIG_STORAGE / ASYNC_CONFIG_STORAGE)
|
|
2754
|
+
* - Auto-healing entre layout de fábrica e layout salvo
|
|
2755
|
+
* - Restauração segura para layout de fábrica
|
|
2756
|
+
* - Orquestração reativa de eventos de navegação de widgets
|
|
2757
|
+
*
|
|
2758
|
+
* Pode ser utilizado diretamente como alvo de rotas do Angular:
|
|
2759
|
+
* ```typescript
|
|
2760
|
+
* {
|
|
2761
|
+
* path: '',
|
|
2762
|
+
* component: PraxisDashboardPage,
|
|
2763
|
+
* data: {
|
|
2764
|
+
* pageKey: 'hq-dashboard',
|
|
2765
|
+
* defaultDefinition: DASHBOARD_PAGE_DEFINITION,
|
|
2766
|
+
* title: 'HQ TACTICAL OPERATIONAL MATRIX',
|
|
2767
|
+
* badge: 'Praxis Page Builder · Canvas Governed',
|
|
2768
|
+
* }
|
|
2769
|
+
* }
|
|
2770
|
+
* ```
|
|
2771
|
+
*/
|
|
2772
|
+
declare class PraxisDashboardPage implements OnInit, OnDestroy {
|
|
2773
|
+
private readonly router;
|
|
2774
|
+
private readonly route;
|
|
2775
|
+
private readonly configStorage;
|
|
2776
|
+
private readonly asyncConfigStorage;
|
|
2777
|
+
private readonly cdr;
|
|
2778
|
+
/** Chave identificadora do dashboard para fins de persistência (ex: 'hq-dashboard') */
|
|
2779
|
+
readonly pageKey: _angular_core.InputSignal<string | undefined>;
|
|
2780
|
+
/** Definição de layout padrão governada de fábrica */
|
|
2781
|
+
readonly defaultDefinition: _angular_core.InputSignal<WidgetPageDefinition | undefined>;
|
|
2782
|
+
/** Contexto dinâmico de dados / expressões injetado nos widgets */
|
|
2783
|
+
readonly context: _angular_core.InputSignal<Record<string, unknown> | null | undefined>;
|
|
2784
|
+
/** Título principal exibido na toolbar de governança */
|
|
2785
|
+
readonly title: _angular_core.InputSignal<string | undefined>;
|
|
2786
|
+
/** Subtítulo descritivo */
|
|
2787
|
+
readonly subtitle: _angular_core.InputSignal<string | undefined>;
|
|
2788
|
+
/** Texto da badge de governança */
|
|
2789
|
+
readonly badge: _angular_core.InputSignal<string | undefined>;
|
|
2790
|
+
/** Habilitar/desabilitar exibição da toolbar superior de governança */
|
|
2791
|
+
readonly showHeader: _angular_core.InputSignal<boolean>;
|
|
2792
|
+
/** Permitir que o usuário acione o modo de customização */
|
|
2793
|
+
readonly enableCustomization: _angular_core.InputSignal<boolean | undefined>;
|
|
2794
|
+
/** Exibir o botão de engrenagem / configurações de widget quando em edição */
|
|
2795
|
+
readonly showSettingsButton: _angular_core.InputSignal<boolean | undefined>;
|
|
2796
|
+
/** Escopar o layout salvo por persona / usuário logado */
|
|
2797
|
+
readonly personaScoped: _angular_core.InputSignal<boolean | undefined>;
|
|
2798
|
+
/** Sobrescrita explícita da chave de armazenamento */
|
|
2799
|
+
readonly storageKey: _angular_core.InputSignal<string | undefined>;
|
|
2800
|
+
/** Notificação de alteração no layout da página */
|
|
2801
|
+
readonly pageChange: EventEmitter<WidgetPageDefinition>;
|
|
2802
|
+
/** Eventos emitidos por ações interativas de widgets */
|
|
2803
|
+
readonly widgetEvent: EventEmitter<WidgetEventEnvelope>;
|
|
2804
|
+
/** Notificação de alteração no status de customização (edição ativa) */
|
|
2805
|
+
readonly customizingChange: EventEmitter<boolean>;
|
|
2806
|
+
/** Notificação de layout restaurado para os padrões de fábrica */
|
|
2807
|
+
readonly layoutReset: EventEmitter<void>;
|
|
2808
|
+
readonly isCustomizing: _angular_core.WritableSignal<boolean>;
|
|
2809
|
+
readonly isLayoutCustomized: _angular_core.WritableSignal<boolean>;
|
|
2810
|
+
readonly lastSavedAt: _angular_core.WritableSignal<string | null>;
|
|
2811
|
+
readonly effectivePageDefinition: _angular_core.WritableSignal<WidgetPageDefinition>;
|
|
2812
|
+
readonly effectivePageKey: _angular_core.Signal<string>;
|
|
2813
|
+
readonly effectiveDefaultDefinition: _angular_core.Signal<WidgetPageDefinition>;
|
|
2814
|
+
readonly effectiveContext: _angular_core.Signal<Record<string, unknown> | null>;
|
|
2815
|
+
readonly effectiveTitle: _angular_core.Signal<string>;
|
|
2816
|
+
readonly effectiveBadge: _angular_core.Signal<string>;
|
|
2817
|
+
readonly effectiveEnableCustomization: _angular_core.Signal<boolean>;
|
|
2818
|
+
readonly effectiveShowSettingsButton: _angular_core.Signal<boolean>;
|
|
2819
|
+
readonly effectivePersonaScoped: _angular_core.Signal<boolean>;
|
|
2820
|
+
readonly effectiveStorageKey: _angular_core.Signal<string>;
|
|
2821
|
+
constructor();
|
|
2822
|
+
ngOnInit(): void;
|
|
2823
|
+
ngOnDestroy(): void;
|
|
2824
|
+
toggleCustomization(): void;
|
|
2825
|
+
resetToFactoryLayout(): void;
|
|
2826
|
+
onPageChange(newDef: WidgetPageDefinition): void;
|
|
2827
|
+
handleWidgetEvent(envelope: WidgetEventEnvelope): void;
|
|
2828
|
+
private readonly onIdentitySwitch;
|
|
2829
|
+
private resolveActiveScopedKey;
|
|
2830
|
+
private loadEffectiveLayout;
|
|
2831
|
+
private mergeWithFactoryDefaults;
|
|
2832
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PraxisDashboardPage, never>;
|
|
2833
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PraxisDashboardPage, "praxis-dashboard-page", never, { "pageKey": { "alias": "pageKey"; "required": false; "isSignal": true; }; "defaultDefinition": { "alias": "defaultDefinition"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "badge": { "alias": "badge"; "required": false; "isSignal": true; }; "showHeader": { "alias": "showHeader"; "required": false; "isSignal": true; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; "isSignal": true; }; "showSettingsButton": { "alias": "showSettingsButton"; "required": false; "isSignal": true; }; "personaScoped": { "alias": "personaScoped"; "required": false; "isSignal": true; }; "storageKey": { "alias": "storageKey"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "widgetEvent": "widgetEvent"; "customizingChange": "customizingChange"; "layoutReset": "layoutReset"; }, never, ["[dashboard-toolbar-actions]"], true, never>;
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
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 };
|
|
2745
2837
|
export type { Capability, CapabilityCatalog, CapabilityCategory, ComponentPaletteData, ComponentPaletteSelection, ConfirmDialogData, PageBuilderAgenticAuthoringAttachmentSummary, PageBuilderAgenticAuthoringCandidate, PageBuilderAgenticAuthoringComponentCapabilitiesResult, PageBuilderAgenticAuthoringComponentCapability, PageBuilderAgenticAuthoringComponentCapabilityCatalog, PageBuilderAgenticAuthoringComponentCapabilityExample, PageBuilderAgenticAuthoringComponentFieldAlias, PageBuilderAgenticAuthoringConversationMessage, PageBuilderAgenticAuthoringGateResult, PageBuilderAgenticAuthoringIntentResolutionRequest, PageBuilderAgenticAuthoringIntentResolutionResult, PageBuilderAgenticAuthoringOptions, PageBuilderAgenticAuthoringPendingClarification, PageBuilderAgenticAuthoringPromptRequest, PageBuilderAgenticAuthoringProvider, PageBuilderAgenticAuthoringQuickReply, PageBuilderAgenticAuthoringResourceCandidatesRequest, PageBuilderAgenticAuthoringResourceCandidatesResult, PageBuilderAgenticAuthoringSharedRuleHandoff, PageBuilderAgenticAuthoringTarget, PageBuilderAgenticAuthoringTurnStreamConnectionError, PageBuilderAgenticAuthoringTurnStreamEvent, PageBuilderAgenticAuthoringTurnStreamRequest, PageBuilderAgenticAuthoringTurnStreamStartResponse, PageBuilderApplyRequest, PageBuilderApplyResult, PageBuilderAuthoringCapabilities, PageBuilderCompiledFormPatch, PageBuilderMinimalFormPlanResult, PageBuilderPreviewDiagnostics, PageBuilderPreviewResult, PageBuilderProjectKnowledgeAudit, UiCompositionAuthoringSourceDiagnostic, UiCompositionAuthoringSourceDiagnosticCode, UiCompositionAuthoringSourceVerification, UiCompositionAuthoringSourceVerificationContext, UiCompositionPlan, UiCompositionPlanAuthoringInput, UiCompositionPlanAuthoringSource, UiCompositionPlanBinding, UiCompositionPlanCompileResult, UiCompositionPlanComponentPortEndpoint, UiCompositionPlanContextScope, UiCompositionPlanContextScopeTarget, UiCompositionPlanContextValue, UiCompositionPlanDiagnostic, UiCompositionPlanEndpoint, UiCompositionPlanGlobalActionEndpoint, UiCompositionPlanGlobalActionSourceEndpoint, UiCompositionPlanInputSource, UiCompositionPlanPreflightResult, UiCompositionPlanSelectCase, UiCompositionPlanSelectionSync, UiCompositionPlanSelectionSyncMapping, UiCompositionPlanSourceEndpoint, UiCompositionPlanStateEndpoint, UiCompositionPlanTargetEndpoint, UiCompositionPlanTemplateMaterialization, UiCompositionPlanTemplateRef, UiCompositionPlanTemplateReference, UiCompositionPlanTemplateResolutionResult, UiCompositionPlanTemplateRevision, UiCompositionPlanTransform, UiCompositionPlanTransformOutput, UiCompositionPlanWidget, UiCompositionResourceSchemaRequest, UiCompositionResourceSchemaResolution, UiCompositionResourceSchemaResolver, ValueKind };
|