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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -523,6 +523,23 @@ Schema-derived table columns already use the canonical `TableConfig.columnProjec
523
523
 
524
524
  `ComponentDocMeta.insertionPresets` remains the canonical catalog for reusable defaults owned by one component. It is not a page/domain template system: do not publish Employee Operations presets from CRUD, tabs, or related-resource outlet metadata merely to shorten a business recipe.
525
525
 
526
+ To streamline host registration of widget providers and component metadata without repetitive manual bootstrap code, `@praxisui/page-builder` exports the `providePraxisPageBuilderWidgets(widgets?: Array<Provider | ComponentDocMeta>)` helper. Hosts can supply a bundle of standard providers or direct `ComponentDocMeta` objects; any `ComponentDocMeta` passed is automatically registered with `ComponentMetadataRegistry` during environment initialization:
527
+
528
+ ```ts
529
+ import { providePraxisPageBuilderWidgets } from '@praxisui/page-builder';
530
+ import { providePraxisListMetadata } from '@praxisui/list';
531
+ import { providePraxisTableMetadata } from '@praxisui/table';
532
+
533
+ export const appConfig: ApplicationConfig = {
534
+ providers: [
535
+ ...providePraxisPageBuilderWidgets([
536
+ providePraxisListMetadata(),
537
+ providePraxisTableMetadata(),
538
+ ]),
539
+ ],
540
+ };
541
+ ```
542
+
526
543
  For complete governed page templates, the additive `UiCompositionPlanTemplateReference` pins the canonical `ai_registry` key and complete `configJson` SHA-256. The Config Starter resolves the active `SYSTEM/GLOBAL` record, verifies the exact hash, extracts its governed `authoringPlan`, and only then invokes the existing compiler. Angular consumers can use the pure `resolveUiCompositionPlanTemplate` helper only with an explicitly supplied `UiCompositionPlanTemplateMaterialization`; the helper performs no HTTP, search, or implicit selection. The first contract accepts no non-empty overrides, fails closed for missing, inactive, malformed, or stale references, and never persists the unresolved reference. `version` and `etag` are retained as audit evidence, while `configSha256` is the required content pin.
527
544
 
528
545
  Keep the compact authoring plan, the compiled executable page, and the surrounding recipe metadata as distinct artifacts. `UiCompositionPlan` is the reviewable authoring intent; `WidgetPageDefinition` is the explicit runtime graph; recipe metadata and operational evidence document when and how the example should be used. The server compiler must produce the same executable page as the Page Builder compiler before persistence.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-07T11:07:08.250Z",
3
+ "generatedAt": "2026-10-12T00:39:17.912Z",
4
4
  "packageName": "@praxisui/page-builder",
5
- "packageVersion": "10.0.0-rc.4",
5
+ "packageVersion": "10.0.0-rc.6",
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
 
@@ -31328,6 +31329,583 @@ function providePraxisPageBuilderMetadata() {
31328
31329
  };
31329
31330
  }
31330
31331
 
31332
+ /**
31333
+ * Type guard that verifies if an item is a canonical ComponentDocMeta.
31334
+ */
31335
+ function isComponentDocMeta(value) {
31336
+ return (typeof value === 'object' &&
31337
+ value !== null &&
31338
+ 'id' in value &&
31339
+ 'selector' in value &&
31340
+ 'component' in value);
31341
+ }
31342
+ /**
31343
+ * Convenient provider factory for registering widgets in the Page Builder host.
31344
+ *
31345
+ * Accepts a list of either Angular `Provider` entries (such as `providePraxisListMetadata()`)
31346
+ * or direct `ComponentDocMeta` definitions (such as `PRAXIS_LIST_COMPONENT_METADATA`).
31347
+ * Any `ComponentDocMeta` passed will be automatically registered with the
31348
+ * `ComponentMetadataRegistry` during environment initialization.
31349
+ */
31350
+ function providePraxisPageBuilderWidgets(widgets) {
31351
+ if (!Array.isArray(widgets) || widgets.length === 0) {
31352
+ return [];
31353
+ }
31354
+ const providers = [];
31355
+ for (const item of widgets) {
31356
+ if (isComponentDocMeta(item)) {
31357
+ providers.push({
31358
+ provide: ENVIRONMENT_INITIALIZER,
31359
+ multi: true,
31360
+ useFactory: (registry) => () => {
31361
+ registry.register(item);
31362
+ },
31363
+ deps: [ComponentMetadataRegistry],
31364
+ });
31365
+ }
31366
+ else if (item) {
31367
+ providers.push(item);
31368
+ }
31369
+ }
31370
+ return providers;
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;
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
+
31331
31909
  /*
31332
31910
  * Public API Surface of @praxisui/page-builder
31333
31911
  */
@@ -31337,4 +31915,4 @@ function providePraxisPageBuilderMetadata() {
31337
31915
  * Generated bundle index. Do not edit.
31338
31916
  */
31339
31917
 
31340
- 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, preflightUiCompositionPlan, preflightUiCompositionPlanResources, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan, verifyUiCompositionAuthoringSource };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "10.0.0-rc.4",
3
+ "version": "10.0.0-rc.6",
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.4",
12
- "@praxisui/core": "^10.0.0-rc.4",
13
- "@praxisui/settings-panel": "^10.0.0-rc.4",
11
+ "@praxisui/ai": "^10.0.0-rc.6",
12
+ "@praxisui/core": "^10.0.0-rc.6",
13
+ "@praxisui/settings-panel": "^10.0.0-rc.6",
14
14
  "rxjs": "~7.8.0"
15
15
  },
16
16
  "dependencies": {
@@ -1186,6 +1186,7 @@ declare class DynamicPageConfigEditorComponent implements OnInit, SettingsValueP
1186
1186
  key: string;
1187
1187
  number: number;
1188
1188
  label: string;
1189
+ widgetKey?: string;
1189
1190
  col: number;
1190
1191
  row: number;
1191
1192
  colSpan: number;
@@ -2153,7 +2154,7 @@ type BuilderCanvasLayout = {
2153
2154
  rowUnit?: string;
2154
2155
  gap?: string;
2155
2156
  autoRows?: 'fixed' | 'content';
2156
- collisionPolicy?: 'block' | 'swap';
2157
+ collisionPolicy?: 'block' | 'swap' | 'push-down';
2157
2158
  items: Record<string, BuilderCanvasItem>;
2158
2159
  };
2159
2160
  type BuilderPageDefinition = Omit<WidgetPageDefinition, 'widgets'> & {
@@ -2726,5 +2727,110 @@ declare const PRAXIS_PAGE_BUILDER_COMPONENT_METADATA: ComponentDocMeta;
2726
2727
  /** Provider para auto-registrar metadados do componente Page Builder. */
2727
2728
  declare function providePraxisPageBuilderMetadata(): Provider;
2728
2729
 
2729
- 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, preflightUiCompositionPlan, preflightUiCompositionPlanResources, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan, verifyUiCompositionAuthoringSource };
2730
+ /**
2731
+ * Type guard that verifies if an item is a canonical ComponentDocMeta.
2732
+ */
2733
+ declare function isComponentDocMeta(value: unknown): value is ComponentDocMeta;
2734
+ /**
2735
+ * Convenient provider factory for registering widgets in the Page Builder host.
2736
+ *
2737
+ * Accepts a list of either Angular `Provider` entries (such as `providePraxisListMetadata()`)
2738
+ * or direct `ComponentDocMeta` definitions (such as `PRAXIS_LIST_COMPONENT_METADATA`).
2739
+ * Any `ComponentDocMeta` passed will be automatically registered with the
2740
+ * `ComponentMetadataRegistry` during environment initialization.
2741
+ */
2742
+ declare function providePraxisPageBuilderWidgets(widgets?: Array<Provider | ComponentDocMeta>): Provider[];
2743
+
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
+ pageKey?: string;
2780
+ /** Definição de layout padrão governada de fábrica */
2781
+ defaultDefinition?: WidgetPageDefinition;
2782
+ /** Contexto dinâmico de dados / expressões injetado nos widgets */
2783
+ context?: Record<string, unknown> | null;
2784
+ /** Título principal exibido na toolbar de governança */
2785
+ title?: string;
2786
+ /** Subtítulo descritivo */
2787
+ subtitle?: string;
2788
+ /** Texto da badge de governança */
2789
+ badge?: string;
2790
+ /** Habilitar/desabilitar exibição da toolbar superior de governança */
2791
+ showHeader: boolean;
2792
+ /** Permitir que o usuário acione o modo de customização */
2793
+ enableCustomization?: boolean;
2794
+ /** Exibir o botão de engrenagem / configurações de widget quando em edição */
2795
+ showSettingsButton?: boolean;
2796
+ /** Escopar o layout salvo por persona / usuário logado */
2797
+ personaScoped?: boolean;
2798
+ /** Sobrescrita explícita da chave de armazenamento */
2799
+ storageKey?: string;
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
+ ngOnInit(): void;
2822
+ ngOnDestroy(): void;
2823
+ toggleCustomization(): void;
2824
+ resetToFactoryLayout(): void;
2825
+ onPageChange(newDef: WidgetPageDefinition): void;
2826
+ handleWidgetEvent(envelope: WidgetEventEnvelope): void;
2827
+ private readonly onIdentitySwitch;
2828
+ private resolveActiveScopedKey;
2829
+ private loadEffectiveLayout;
2830
+ private mergeWithFactoryDefaults;
2831
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PraxisDashboardPage, never>;
2832
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PraxisDashboardPage, "praxis-dashboard-page", never, { "pageKey": { "alias": "pageKey"; "required": false; }; "defaultDefinition": { "alias": "defaultDefinition"; "required": false; }; "context": { "alias": "context"; "required": false; }; "title": { "alias": "title"; "required": false; }; "subtitle": { "alias": "subtitle"; "required": false; }; "badge": { "alias": "badge"; "required": false; }; "showHeader": { "alias": "showHeader"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "showSettingsButton": { "alias": "showSettingsButton"; "required": false; }; "personaScoped": { "alias": "personaScoped"; "required": false; }; "storageKey": { "alias": "storageKey"; "required": false; }; }, { "pageChange": "pageChange"; "widgetEvent": "widgetEvent"; "customizingChange": "customizingChange"; "layoutReset": "layoutReset"; }, never, ["[dashboard-toolbar-actions]"], true, never>;
2833
+ }
2834
+
2835
+ 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 };
2730
2836
  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 };