@praxisui/page-builder 10.0.0-rc.3 → 10.0.0-rc.31

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
@@ -4,6 +4,54 @@ Visual page and dashboard builder for Praxis UI applications.
4
4
 
5
5
  Use this package when an application must let users compose governed operational pages from registered widgets, visual layout, shell settings, component editors, `composition.links`, and optional AI-assisted authoring.
6
6
 
7
+ ## Dashboard pages and persistence ownership
8
+
9
+ A dashboard is a `WidgetPageDefinition` rendered by `praxis-dynamic-page` and edited
10
+ by `praxis-dynamic-page-builder`. The beta `PraxisDashboardPage` wrapper was removed;
11
+ use these existing components instead. Application titles, toolbar presentation and
12
+ business navigation remain host concerns.
13
+
14
+ For manual page editing, opt in to the Core persistence lifecycle:
15
+
16
+ ```html
17
+ <praxis-dynamic-page-builder
18
+ #builder
19
+ [page]="defaultPage"
20
+ [pageIdentity]="identity"
21
+ [autoPersist]="true"
22
+ [enableCustomization]="editing"
23
+ (persistenceChange)="persistence = $event"
24
+ />
25
+ ```
26
+
27
+ `autoPersist` defaults to `false` on the builder, preserving its previous effective
28
+ behavior (the child runtime previously always received `false`). Hosts that already
29
+ persist `pageAuthoringChange`/`pageSaveRequested` must leave it disabled. Core Dynamic
30
+ Page keeps its own existing default. Do not enable a second host writer when Core
31
+ owns persistence.
32
+
33
+ Pass `PageIdentity` with the application's actual tenant/user/route. Core uses the
34
+ configured `ASYNC_CONFIG_STORAGE`; no separate localStorage cache, browser globals
35
+ or persona-specific host reconciler is needed. Storage identity is not backend
36
+ authorization. Persisted documents, including an empty widget list, are authoritative;
37
+ new factory widgets are not silently appended to a user's saved page.
38
+
39
+ `persistenceChange` forwards Core's operational `WidgetPagePersistenceState`:
40
+ `idle`, `loading`, `saving`, `saved`, `resetting` or `error`, with `customized`, optional
41
+ ISO `savedAt`, operation and a safe `errorKind`. Show success only after acknowledgement,
42
+ and distinguish conflicts from a pending or failed write. It is not business metadata
43
+ and must not be persisted in `WidgetPageDefinition`.
44
+
45
+ `builder.resetPersistedPage(defaultPage)` deletes this identity's saved page and applies
46
+ the supplied default only after acknowledgement. `builder.reloadPersistedPage(defaultPage)`
47
+ explicitly discards the draft and reloads storage, using the supplied default when no saved
48
+ page exists. Make that destructive-to-draft intent visible in the host. The existing Save
49
+ button retries through Core for manually managed pages; conflicts require an explicit reload.
50
+
51
+ For `authoringDocument` or agentic authoring, Core automatic persistence is disabled even
52
+ when requested: the existing host/server apply lifecycle owns revisions and provenance.
53
+ An AI preview must never be saved through an automatic generic config write.
54
+
7
55
  ## Widget shell editor integrity
8
56
 
9
57
  The shell editor exposes **Keep header visible while scrolling the page**
@@ -87,7 +135,7 @@ order, with natural content height. It replaces positions and width bounds only
87
135
  that device, preserves hidden widgets and other overrides, and leaves the base and
88
136
  other device layouts unchanged. Apply/Save materializes the existing
89
137
  `deviceLayouts[device].canvas` contract; Reset restores the original draft.
90
- Advanced JSON overrides remain available under **Advanced overrides**.
138
+ Advanced JSON overrides remain available under **Advanced overrides** (`widgetOverrides`) and strictly validate the canonical `WidgetPageWidgetLayoutOverride` keys (`className`, `span`, `order`, `hidden`), diagnosing and rejecting unsupported properties such as `definition` or `inputs` without discarding the user's draft text.
91
139
 
92
140
  Reducing a device's column count also reflows inherited base positions in Core.
93
141
  Explicit device positions remain authoritative. With no device variant the base
@@ -113,7 +161,7 @@ documents already clamped by Core remain valid on opening: declared spans need
113
161
  not equal rendered spans. Invalid inherited bounds can be corrected in the same
114
162
  draft. The editor does not rewrite geometry to satisfy newly authored bounds.
115
163
  Dynamic title expressions are
116
- identified by stable widget key, not evaluated in the editor.
164
+ identified by stable widget key and resolved friendly widget titles (from static shell metadata or inner widget titles), not evaluated in the editor.
117
165
 
118
166
  Apply previews the same document returned by Save; Reset reloads the input baseline.
119
167
  Pending changes are tracked independently of validity, including edits to an
@@ -135,7 +183,7 @@ Page, the editor receives transient runtime validation through `SETTINGS_PANEL_D
135
183
  Apply/Save and reopen check the current active-device geometry and report the minimum
136
184
  beside the height field. The callback and observed dimensions never enter the document.
137
185
  Changed columns, gap, width or shell styling require Automatic height, Apply, then
138
- reopening before choosing a measured height. Other device variants must be checked
186
+ reopening before choosing a measured height. When switching a visual template (`themePreset` / `layoutPreset`) triggers rendered-height validation blocks on widgets with adjustable heights, the editor surfaces an actionable banner across Studio tabs listing all affected widgets with their friendly names and current pixel heights, offering direct navigation to **Widget limits** or a one-click conversion to **Automatic** height that preserves a summary of the previous pixel measurements for review. Other device variants must be checked
139
187
  on their corresponding device. Standalone/custom hosts without this runtime context
140
188
  retain numeric validation only. Core's scroll-layout shell now recovers access after
141
189
  late header/content growth by temporarily scrolling the header and body together
@@ -150,6 +198,13 @@ Do not infer AI support from broad affected paths. Publishing the new authoring
150
198
  schema/handler validation and registry projection remains an explicit follow-up,
151
199
  not an OpenAI dependency for manual interaction.
152
200
 
201
+ ### Declarative Page DataSources Authoring
202
+
203
+ Both `PageConfigEditorComponent` and `DynamicPageConfigEditorComponent` preserve and edit `page.dataSources` inside **Page settings → State**:
204
+
205
+ - Both `PageConfigEditorComponent` and `DynamicPageConfigEditorComponent` offer guided DataSource cards (`id`, `kind`, `endpointKey`, `resourcePath`, `method`, `targetStatePath`, `errorPolicy`, `refreshIntervalMs`, `autoFetch`, `query`, `transform`, `fallbackValue`, `description`) synchronized bidirectionally with the advanced JSON editor (`[data-testid="page-datasources-json"]`).
206
+ - Both editors accept Array or Object-Map JSON input, normalize saved definitions to the canonical `WidgetPageDataSourceDefinition[]` array, and enforce symmetric validation across guided and raw JSON authoring—failing closed (blocking Apply/Save and surfacing `editor.errors.dataSourcesInvalid` on the State tab) when an entry is missing `id` or `resourcePath`, duplicates a normalized `id`, sets an unsupported `kind`/`method`/`errorPolicy`, sets a negative or non-finite `refreshIntervalMs`, passes a non-object `query`, declares an incomplete `transform` (`path`, `group-by-map`, `timeseries-last`), or contains malformed JSON.
207
+
153
208
  ## LLM Recommendation Guide
154
209
 
155
210
  - Recommend when: users need dynamic pages, widget composition, dashboards, grid layouts, component metadata discovery, and runtime-editable page definitions.
@@ -236,6 +291,8 @@ source fails closed.
236
291
  - `enableAgenticAuthoring`, `agenticAuthoringProvider`, `agenticAuthoringModel`, `agenticAuthoringScope`
237
292
  - `agenticAuthoringIncludeLlmDiagnostics`, `agenticAuthoringEnableStreaming`, `agenticAuthoringContextHints`
238
293
  - `showPageLifecycleActions`, `canDeleteSavedPage`, `pageLifecycleBusy`
294
+ - `showGovernanceToolbar`: boolean flag to render a built-in top governance toolbar (with canvas title, layout persistence status badge, last saved time, factory reset button, and customization toggle), enabling 100% declarative page hosting without imperative toolbar boilerplate
295
+ - `governanceToolbarTitle`: optional string providing the canvas or dashboard title displayed in the governance toolbar
239
296
 
240
297
  All omitted `authoringCapabilities` entries remain enabled for backward compatibility. The grant is
241
298
  never written to `WidgetPageDefinition` and does not authorize AI operations; manifests, backend
@@ -523,6 +580,23 @@ Schema-derived table columns already use the canonical `TableConfig.columnProjec
523
580
 
524
581
  `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
582
 
583
+ 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:
584
+
585
+ ```ts
586
+ import { providePraxisPageBuilderWidgets } from '@praxisui/page-builder';
587
+ import { providePraxisListMetadata } from '@praxisui/list';
588
+ import { providePraxisTableMetadata } from '@praxisui/table';
589
+
590
+ export const appConfig: ApplicationConfig = {
591
+ providers: [
592
+ ...providePraxisPageBuilderWidgets([
593
+ providePraxisListMetadata(),
594
+ providePraxisTableMetadata(),
595
+ ]),
596
+ ],
597
+ };
598
+ ```
599
+
526
600
  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
601
 
528
602
  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.
@@ -1072,6 +1146,10 @@ losing unrelated context. Arrangement choices track their draft baseline even wh
1072
1146
  selected distribution initially produces no changes, so later edits clear stale status.
1073
1147
  These fixes are not part of the already published 9.0.68-rc.2 package.
1074
1148
 
1149
+ `retryPersistedPage()` retries the current draft after a non-conflict save failure,
1150
+ including empty pages, without emitting host save lifecycle events. Conflicts require
1151
+ explicit `reloadPersistedPage(defaultPage)`; reload discards the local draft.
1152
+
1075
1153
  <!-- praxis-npm-catalog-links:start -->
1076
1154
  ## Official documentation and examples
1077
1155