@praxisui/page-builder 9.0.65 → 9.0.67
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 +162 -2
- package/ai/component-registry.json +13 -7
- package/fesm2022/praxisui-page-builder.mjs +1570 -187
- package/package.json +4 -4
- package/types/praxisui-page-builder.d.ts +108 -2
package/README.md
CHANGED
|
@@ -4,6 +4,141 @@ 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
|
+
## Widget shell editor integrity
|
|
8
|
+
|
|
9
|
+
The shell editor exposes **Keep header visible while scrolling the page**
|
|
10
|
+
(`widget.shell.stickyHeader`). It retains the current title/subtitle rather than
|
|
11
|
+
copying record state into the host. Apply/save/reopen/reset use the same shell
|
|
12
|
+
document and the existing identity-authoring capability governs the option.
|
|
13
|
+
Pinning is visible in presentation mode, not while dragging/editing the canvas;
|
|
14
|
+
hidden headers, collapsed/overlay widgets and scroll recovery retain their own
|
|
15
|
+
behavior. Hosts with a fixed heading provide the Core CSS length
|
|
16
|
+
`--pdx-shell-sticky-header-offset`. The default remains normal flow.
|
|
17
|
+
|
|
18
|
+
The page editor keeps Material tab pagination/keyboard navigation with wrapped labels
|
|
19
|
+
for narrow panels. Its configuration summary is progressively disclosed; when hosted
|
|
20
|
+
in Settings Panel it does not repeat the shell's title, reset action or dirty status.
|
|
21
|
+
The selected widget/layout remains visible while scrolling the limits inspector.
|
|
22
|
+
Rendered-height diagnostics appear at the visible height field only; diagnostics for
|
|
23
|
+
another target or a hidden height field remain in the section summary. The validity
|
|
24
|
+
and apply/save protocol are unchanged.
|
|
25
|
+
|
|
26
|
+
Dynamic Page height validation follows viewport resize and Angular render completion
|
|
27
|
+
while the editor remains open. It reuses the runtime's transient validator and updates
|
|
28
|
+
the existing field diagnostics/Apply/Save gates only when the diagnostic changes.
|
|
29
|
+
The entered height and dirty baseline are preserved; rendered measurements never become
|
|
30
|
+
constraints or persisted page fields. Final value production also revalidates, so a late
|
|
31
|
+
failure must remain an invalid, open draft in Settings Panel.
|
|
32
|
+
|
|
33
|
+
This validates the active rendered geometry, not all possible devices, virtualized
|
|
34
|
+
contents or future CSS-only changes without a render/resize notification.
|
|
35
|
+
|
|
36
|
+
The shell editor validates non-empty appearance overrides with the browser CSS parser for
|
|
37
|
+
their actual property: backgrounds, colors, radius, shadow, padding and typography. Empty
|
|
38
|
+
overrides remain valid; tokens, gradients and CSS expressions are preserved, not resolved
|
|
39
|
+
into host-specific values. Invalid editable values block Apply/Save and the settings-value
|
|
40
|
+
provider. Hidden appearance fields in permission-limited editors remain preserved.
|
|
41
|
+
|
|
42
|
+
This is browser syntax validation, not URL sanitization, token-resolution verification or
|
|
43
|
+
backend authorization. SSR has no interactive CSS parser and defers this check to the browser.
|
|
44
|
+
Existing accepted JSON paths and the AI authoring manifest remain unchanged.
|
|
45
|
+
|
|
46
|
+
The appearance/action editor adapts to narrow panels, and validation messages reserve their
|
|
47
|
+
own space. The archetype lab now exposes a local edit toggle at narrow breakpoints, where
|
|
48
|
+
the demo's global toggle is hidden. This is a tested entrypoint, not full mobile certification.
|
|
49
|
+
Read the
|
|
50
|
+
[lab certification record](../../src/app/features/dynamic-page-lab/ERGON_ARCHETYPE_CERTIFICATION.md)
|
|
51
|
+
for the exact tested scope and remaining corporate gates.
|
|
52
|
+
|
|
53
|
+
## Direct canvas manipulation
|
|
54
|
+
|
|
55
|
+
The builder consumes the shared Core canvas: select a widget to expose eight direct resize
|
|
56
|
+
grips, drag its header to move it, or use the focused grip's arrow keys to change size.
|
|
57
|
+
The global widget selector/directional controls are collapsed as an alternative. The
|
|
58
|
+
contextual **Resize widget** action retains larger 44px controls. These access paths share
|
|
59
|
+
one geometry, constraints, collision, preview and cancellation implementation; they add no
|
|
60
|
+
Page Builder settings, persistence flags or AI operations. `widget.moveResize` continues
|
|
61
|
+
to address the existing canonical `canvas.items` document.
|
|
62
|
+
|
|
63
|
+
Manual resize now previews coordinated space redistribution in Core, with green
|
|
64
|
+
availability, amber minimum-size feedback and red exceeded-limit feedback on the
|
|
65
|
+
affected widgets. Release commits the valid distribution atomically; Escape cancels
|
|
66
|
+
all affected items. This is not automatic repacking or a new AI operation. Explicit
|
|
67
|
+
content-aware minimums remain important, including in restored layouts; changing a
|
|
68
|
+
recipe does not silently rewrite a saved user page. Auto-content rows still do not
|
|
69
|
+
provide pixel-continuous vertical shrinking of a one-row widget.
|
|
70
|
+
|
|
71
|
+
### Device composition
|
|
72
|
+
|
|
73
|
+
**Page settings → Responsiveness** opens on Mobile and shows one device at a time.
|
|
74
|
+
**Stack widgets** prepares a single-column variant in the base canvas's visual reading
|
|
75
|
+
order, with natural content height. It replaces positions and width bounds only for
|
|
76
|
+
that device, preserves hidden widgets and other overrides, and leaves the base and
|
|
77
|
+
other device layouts unchanged. Apply/Save materializes the existing
|
|
78
|
+
`deviceLayouts[device].canvas` contract; Reset restores the original draft.
|
|
79
|
+
Advanced JSON overrides remain available under **Advanced overrides**.
|
|
80
|
+
|
|
81
|
+
Reducing a device's column count also reflows inherited base positions in Core.
|
|
82
|
+
Explicit device positions remain authoritative. With no device variant the base
|
|
83
|
+
canvas is still inherited; the editor does not silently apply a mobile template.
|
|
84
|
+
Grouping settings are preserved for flow layouts; canvas geometry currently takes
|
|
85
|
+
precedence over grouping. The editor explains this distinction in the Grouping tab.
|
|
86
|
+
|
|
87
|
+
### Visual widget limits
|
|
88
|
+
|
|
89
|
+
Open **Page settings → Widget limits** in the default Dynamic Page editor to set
|
|
90
|
+
minimum/maximum width (columns) and height (rows). Choose the base canvas or a
|
|
91
|
+
desktop, tablet or mobile override, without closing the editor. Blank base fields use Core defaults (minimum one,
|
|
92
|
+
maximum grid width/unbounded row span); blank device fields inherit base limits.
|
|
93
|
+
An untouched device target does not create an override in the document. Validation
|
|
94
|
+
uses the final draft, including device layouts created in Responsiveness during the same session.
|
|
95
|
+
|
|
96
|
+
The editor writes existing `canvas.items[key].constraints` and
|
|
97
|
+
`deviceLayouts[device].canvas.items[key].constraints`, preserving locks, geometry,
|
|
98
|
+
unknown fields and untouched overrides. It rejects non-positive/non-integer
|
|
99
|
+
values, reversed or inherited conflicting ranges, minimums wider than the grid,
|
|
100
|
+
and newly authored limits that would change the current effective size. Existing
|
|
101
|
+
documents already clamped by Core remain valid on opening: declared spans need
|
|
102
|
+
not equal rendered spans. Invalid inherited bounds can be corrected in the same
|
|
103
|
+
draft. The editor does not rewrite geometry to satisfy newly authored bounds.
|
|
104
|
+
Dynamic title expressions are
|
|
105
|
+
identified by stable widget key, not evaluated in the editor.
|
|
106
|
+
|
|
107
|
+
Apply previews the same document returned by Save; Reset reloads the input baseline.
|
|
108
|
+
Pending changes are tracked independently of validity, including edits to an
|
|
109
|
+
already-invalid input document. Invalid limit fields expose Material errors and
|
|
110
|
+
accessible invalid/described-by state; correcting them clears their error state.
|
|
111
|
+
Closing after Apply may ask to discard the unsaved editor draft: the applied
|
|
112
|
+
preview remains active, as the shared Settings Panel explicitly explains.
|
|
113
|
+
Remote user/tenant persistence is unchanged. In `autoRows: 'content'`, the same editor
|
|
114
|
+
also exposes **Default / Automatic / Adjustable** height, pixel height, top inset,
|
|
115
|
+
and pixel minimum/maximum. It writes Core `canvas.items[key].contentSize` and its
|
|
116
|
+
device override, plus `constraints.minHeightPx/maxHeightPx`. Default removes an
|
|
117
|
+
override, Automatic writes `'auto'` (including when base height is bounded), and
|
|
118
|
+
Adjustable writes `{ heightPx, offsetTopPx }`. Minimum height is 160px; invalid
|
|
119
|
+
sizes/inherited ranges block Apply/Save with a field error. No child inputs are changed.
|
|
120
|
+
North grips preserve the bottom through the inset; Automatic clears both dimensions.
|
|
121
|
+
The 160px editor floor measures the **outer box**, not usable body space. Core resize
|
|
122
|
+
gestures also protect the rendered header and a body reserve. When opened by Dynamic
|
|
123
|
+
Page, the editor receives transient runtime validation through `SETTINGS_PANEL_DATA`:
|
|
124
|
+
Apply/Save and reopen check the current active-device geometry and report the minimum
|
|
125
|
+
beside the height field. The callback and observed dimensions never enter the document.
|
|
126
|
+
Changed columns, gap, width or shell styling require Automatic height, Apply, then
|
|
127
|
+
reopening before choosing a measured height. Other device variants must be checked
|
|
128
|
+
on their corresponding device. Standalone/custom hosts without this runtime context
|
|
129
|
+
retain numeric validation only. Core's scroll-layout shell now recovers access after
|
|
130
|
+
late header/content growth by temporarily scrolling the header and body together
|
|
131
|
+
inside the unchanged box. Normal body-only scrolling returns when space recovers.
|
|
132
|
+
That runtime safeguard does not approve an insufficient editor height, write measured
|
|
133
|
+
constraints, or certify every device/child component's usable-height ergonomics.
|
|
134
|
+
|
|
135
|
+
The AI manifest was reviewed: `canvas.configure.items` and `widget.add.canvasItem`
|
|
136
|
+
do not currently provide a concrete nested schema proving these new pixel fields.
|
|
137
|
+
This cut certifies manual runtime/editor behavior only, not agentic height authoring.
|
|
138
|
+
Do not infer AI support from broad affected paths. Publishing the new authoring
|
|
139
|
+
schema/handler validation and registry projection remains an explicit follow-up,
|
|
140
|
+
not an OpenAI dependency for manual interaction.
|
|
141
|
+
|
|
7
142
|
## LLM Recommendation Guide
|
|
8
143
|
|
|
9
144
|
- Recommend when: users need dynamic pages, widget composition, dashboards, grid layouts, component metadata discovery, and runtime-editable page definitions.
|
|
@@ -202,10 +337,15 @@ Current capabilities include:
|
|
|
202
337
|
|
|
203
338
|
- inspecting persisted links, endpoints, intent, condition, transform and policy;
|
|
204
339
|
- highlighting widget, state and global-action flows in the same graph;
|
|
205
|
-
- creating
|
|
206
|
-
-
|
|
340
|
+
- creating connections with **New connection** or by dragging a port; both open the same draft for source, destination, value and missing-value review;
|
|
341
|
+
- editing a selected link with **Edit connection**, preserving its ID, nested ownership and existing transform/condition/policy;
|
|
342
|
+
- validating drafts with Core `CompositionValidatorService` and the host `ComponentMetadataRegistry` before **Apply connection**; cancel leaves the page unchanged, apply creates one undo entry, and an external page change blocks a stale draft;
|
|
343
|
+
- presenting the same radial diagram with larger readable node captions, directional wires and a **Present diagram** mode;
|
|
344
|
+
- offering the existing table-to-detail shortcut only for its exact ports and an unwired destination, without keyword-based ranking or claims of AI recommendation; `rowClick` projects `payload.row.id`, while `selectionChange` projects `payload.selectedRows.0.id` with pipeline `fallbackValue: null` so deselection clears the destination;
|
|
207
345
|
- explaining nested component ports by showing the `nestedPath` while preserving the top-level widget as the canonical endpoint owner.
|
|
208
346
|
|
|
347
|
+
**Apply connection** changes the builder page; **Save page** persists it through the host. Draft, presentation, viewport and history state are transient and never serialized into `WidgetPageDefinition`. **Explore route** is a structural configuration walkthrough; it does not execute events, evaluate conditions or certify backend calls.
|
|
348
|
+
|
|
209
349
|
For nested components, keep `ref.widget` pointed at the top-level host widget and describe the internal target with `ref.nestedPath`. The editor should make that ownership visible instead of flattening child widgets into a second page-level widget namespace.
|
|
210
350
|
|
|
211
351
|
## Settings Panel Bridge
|
|
@@ -420,3 +560,23 @@ Main exports:
|
|
|
420
560
|
- Use component-owned config editors through metadata instead of duplicating widget-specific editors in Page Builder.
|
|
421
561
|
- Keep diagnostics and streaming opt-in for hosts that need auditability or richer authoring feedback.
|
|
422
562
|
- Use the official documentation for extended recipes, playground routes, and advanced AI authoring flows.
|
|
563
|
+
|
|
564
|
+
### Montagem manual de master detail a partir de uma página vazia
|
|
565
|
+
|
|
566
|
+
1. Insira Filter, Table e Dynamic Form e conecte-os ao recurso pelo catálogo.
|
|
567
|
+
2. No filtro, carregue o schema e selecione os campos sempre visíveis.
|
|
568
|
+
3. Na tabela, habilite seleção única por clique e escolha paginação no servidor para APIs paginadas; no formulário, escolha modo `view`.
|
|
569
|
+
4. Crie as conexões `Filter.change → Table.queryContext` e `Table.selectionChange → Dynamic Form.resourceId`. O editor usa os contratos públicos das portas para propor as transformações do filtro e do identificador.
|
|
570
|
+
5. Configure a grade, salve a página e reabra para conferir filtro, seleção e detalhe.
|
|
571
|
+
|
|
572
|
+
Ao converter uma página sem posições em grade, o editor acrescenta posições para todos os widgets e usa altura de conteúdo como padrão. Isso garante visibilidade; a distribuição lado a lado continua sendo uma decisão de layout do autor. O diagrama radial mantém os modos de edição e apresentação.
|
|
573
|
+
|
|
574
|
+
### Menu de ações e tamanho preciso
|
|
575
|
+
|
|
576
|
+
O editor de shell aceita `placement: 'menu'` para manter uma ação em Mais ações mesmo
|
|
577
|
+
com espaço livre no cabeçalho. A edição do canvas oferece `Mais ações → Tamanho…`,
|
|
578
|
+
com largura em colunas e altura em linhas ou pixels conforme `autoRows`. O ajuste usa
|
|
579
|
+
as restrições e o layout de dispositivo canônicos, com prévia e aplicação explícita.
|
|
580
|
+
Selecionar o widget continua expondo suas alças; o ícone dedicado e os painéis de setas
|
|
581
|
+
separados foram removidos. O editor oferece presets exatos de largura e recuperação do último resize da sessão,
|
|
582
|
+
incluindo vizinhos. Clique duplo e histórico geral continuam fora desta entrega.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-07T00:54:55.301Z",
|
|
4
4
|
"packageName": "@praxisui/page-builder",
|
|
5
|
-
"packageVersion": "9.0.
|
|
5
|
+
"packageVersion": "9.0.67",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 1,
|
|
@@ -2059,7 +2059,13 @@
|
|
|
2059
2059
|
"type": "string"
|
|
2060
2060
|
},
|
|
2061
2061
|
"shell": {
|
|
2062
|
-
"type": "object"
|
|
2062
|
+
"type": "object",
|
|
2063
|
+
"properties": {
|
|
2064
|
+
"stickyHeader": {
|
|
2065
|
+
"type": "boolean",
|
|
2066
|
+
"description": "Retain the existing header within the widget during page scrolling; suspended for drag authoring, collapsed/overlay states and scroll recovery."
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2063
2069
|
}
|
|
2064
2070
|
}
|
|
2065
2071
|
},
|
|
@@ -3783,9 +3789,9 @@
|
|
|
3783
3789
|
{
|
|
3784
3790
|
"chunkIndex": 10,
|
|
3785
3791
|
"chunkKind": "authoring_manifest",
|
|
3786
|
-
"content": "{\"operationId\":\"widget.shell.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.0\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure widget shell Effects: compile-domain-patch. Rename the employees widget card and enable the refresh shell action.\",\"scope\":\"templating\",\"target\":{\"kind\":\"widgetShell\",\"resolver\":\"widget-shell-by-widget-key\",\"required\":true},\"inputContract\":{\"required\":[\"widgetKey\"],\"properties\":[\"widgetKey\",\"shell\"],\"semanticTerms\":[\"widgetKey\",\"shell\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"widgets[].shell\"],\"validators\":[{\"validatorId\":\"widget-exists\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_WIDGET_EXISTS\",\"description\":\"Target widget must exist.\"},{\"validatorId\":\"widget-shell-shape-valid\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_SHELL_SHAPE\",\"description\":\"Widget shell config must match the shell editor contract.\"},{\"validatorId\":\"settings-panel-bridge-available\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_SETTINGS_BRIDGE\",\"description\":\"Settings panel bridge must be available for shell/page editors.\"},{\"validatorId\":\"child-inputs-not-mutated\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_CHILD_INPUTS_NOT_MUTATED\",\"description\":\"Shell edits cannot mutate child inputs.\"}],\"preconditions\":[\"page-loaded\",\"target-widget-exists\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"configure-widget-shell\",\"request\":\"Rename the employees widget card and enable the refresh shell action.\",\"operationId\":\"widget.shell.configure\",\"target\":\"employees-table\",\"params\":{\"widgetKey\":\"employees-table\",\"shell\":{\"title\":\"Employees\",\"actions\":[{\"id\":\"refresh\"}]}},\"isPositive\":true}],\"negativeExamples\":[]}",
|
|
3792
|
+
"content": "{\"operationId\":\"widget.shell.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.0\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operation_card\",\"semanticSummary\":\"Configure widget shell Effects: compile-domain-patch. Rename the employees widget card and enable the refresh shell action.\",\"scope\":\"templating\",\"target\":{\"kind\":\"widgetShell\",\"resolver\":\"widget-shell-by-widget-key\",\"required\":true},\"inputContract\":{\"required\":[\"widgetKey\"],\"properties\":[\"widgetKey\",\"shell\"],\"semanticTerms\":[\"widgetKey\",\"shell\",\"shell.stickyHeader\"]},\"effects\":[\"compile-domain-patch\"],\"affectedPaths\":[\"widgets[].shell\"],\"validators\":[{\"validatorId\":\"widget-exists\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_WIDGET_EXISTS\",\"description\":\"Target widget must exist.\"},{\"validatorId\":\"widget-shell-shape-valid\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_SHELL_SHAPE\",\"description\":\"Widget shell config must match the shell editor contract.\"},{\"validatorId\":\"settings-panel-bridge-available\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_SETTINGS_BRIDGE\",\"description\":\"Settings panel bridge must be available for shell/page editors.\"},{\"validatorId\":\"child-inputs-not-mutated\",\"level\":\"error\",\"code\":\"PAGE_BUILDER_CHILD_INPUTS_NOT_MUTATED\",\"description\":\"Shell edits cannot mutate child inputs.\"}],\"preconditions\":[\"page-loaded\",\"target-widget-exists\"],\"submissionImpact\":\"config-only\",\"presentationAffordances\":[],\"positiveExamples\":[{\"id\":\"configure-widget-shell\",\"request\":\"Rename the employees widget card and enable the refresh shell action.\",\"operationId\":\"widget.shell.configure\",\"target\":\"employees-table\",\"params\":{\"widgetKey\":\"employees-table\",\"shell\":{\"title\":\"Employees\",\"actions\":[{\"id\":\"refresh\"}]}},\"isPositive\":true}],\"negativeExamples\":[]}",
|
|
3787
3793
|
"sourcePointer": "projects/praxis-page-builder/src/lib/ai/praxis-page-builder-authoring-manifest.ts",
|
|
3788
|
-
"contentHash": "
|
|
3794
|
+
"contentHash": "12355c4633b7f09a4c4e46d4edac2f23a2ff0e45b6d2a27251ec93b181e50b6e",
|
|
3789
3795
|
"sourceKind": "component_definition",
|
|
3790
3796
|
"sourceId": "praxis-page-builder",
|
|
3791
3797
|
"corpusVersion": "1.0.0"
|
|
@@ -3893,9 +3899,9 @@
|
|
|
3893
3899
|
{
|
|
3894
3900
|
"chunkIndex": 21,
|
|
3895
3901
|
"chunkKind": "authoring_manifest",
|
|
3896
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.0\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"page.configure\",\"title\":\"Configure page metadata\",\"scope\":\"global\",\"targetKind\":\"page\",\"target\":{\"kind\":\"page\",\"resolver\":\"widget-page-definition-root\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\"},\"layoutPreset\":{\"type\":\"string\"},\"themePreset\":{\"type\":\"string\"},\"context\":{\"type\":\"object\"},\"metadata\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-page-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition\",\"DynamicPageConfigEditorComponent\",\"SettingsPanelBridge\"],\"writes\":[\"page.title\",\"page.layoutPreset\",\"page.themePreset\",\"page.context\",\"page.metadata\"],\"identityKeys\":[\"pageIdentity.componentId\",\"pageIdentity.scope\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\"},\"layoutPreset\":{\"type\":\"string\"},\"themePreset\":{\"type\":\"string\"},\"context\":{\"type\":\"object\"},\"metadata\":{\"type\":\"object\"}}},\"failureModes\":[\"page-not-loaded\",\"context-not-json\",\"settings-panel-bridge-missing\"],\"description\":\"Updates root page metadata while preserving the renderable WidgetPageDefinition shape.\"}}],\"validators\":[\"widget-page-definition-valid\",\"no-legacy-grid-page-definition\",\"page-context-json-valid\",\"settings-panel-round-trip-valid\"],\"affectedPaths\":[\"title\",\"layoutPreset\",\"themePreset\",\"context\",\"metadata\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\"]},{\"operationId\":\"canvas.configure\",\"title\":\"Configure page canvas\",\"scope\":\"layout\",\"targetKind\":\"canvas\",\"target\":{\"kind\":\"canvas\",\"resolver\":\"widget-page-canvas\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"columns\":{\"type\":\"number\"},\"rowUnit\":{\"type\":\"number\"},\"gap\":{\"type\":\"number\"},\"items\":{\"type\":\"array\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-canvas-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.canvas\",\"DynamicPageBuilderComponent\"],\"writes\":[\"page.canvas.columns\",\"page.canvas.rowUnit\",\"page.canvas.gap\",\"page.canvas.items\"],\"identityKeys\":[\"canvas\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"columns\":{\"type\":\"number\"},\"rowUnit\":{\"type\":\"number\"},\"gap\":{\"type\":\"number\"},\"items\":{\"type\":\"array\"}}},\"failureModes\":[\"canvas-missing\",\"canvas-item-references-missing-widget\",\"invalid-grid-geometry\"],\"description\":\"Configures the top-level canvas without introducing legacy GridPageDefinition semantics.\"}}],\"validators\":[\"canvas-columns-integer\",\"canvas-row-unit-valid\",\"canvas-gap-valid\",\"canvas-items-reference-existing-widgets\"],\"affectedPaths\":[\"canvas.columns\",\"canvas.rowUnit\",\"canvas.gap\",\"canvas.items\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\"]},{\"operationId\":\"widget.add\",\"title\":\"Add widget to page\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"componentId\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"componentId\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"inputs\":{\"type\":\"object\"},\"canvasItem\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-add\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetPageDefinition.canvas\",\"ComponentDocRegistry\",\"PAGE_BUILDER_WIDGET_AI_CATALOGS\"],\"writes\":[\"page.widgets[]\",\"page.canvas.items[]\"],\"identityKeys\":[\"widgetKey\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"componentId\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"componentId\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"inputs\":{\"type\":\"object\"},\"canvasItem\":{\"type\":\"object\"}}},\"failureModes\":[\"widget-key-duplicate\",\"component-not-registered\",\"canvas-item-invalid\",\"child-input-contract-unknown\"],\"description\":\"Adds a registered component as a widget and places it on the canvas using a stable widgetKey.\"}}],\"validators\":[\"widget-key-unique\",\"component-registered\",\"canvas-item-valid\",\"child-inputs-delegated\",\"widget-key-not-array-index\"],\"affectedPaths\":[\"widgets[]\",\"canvas.items[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"component-catalog-loaded\"]},{\"operationId\":\"widget.remove\",\"title\":\"Remove widget from page\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"confirmed\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-remove\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetPageDefinition.canvas.items\",\"WidgetPageDefinition.composition.links\"],\"writes\":[\"page.widgets[]\",\"page.canvas.items[]\",\"page.composition.links[]\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"destructive-removal-not-confirmed\",\"dangling-composition-link\"],\"description\":\"Removes a widget and cleans canvas items and composition links that reference it.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"widget-exists\",\"destructive-removal-confirmed\",\"composition-links-cleaned\",\"canvas-items-reference-existing-widgets\"],\"affectedPaths\":[\"widgets[]\",\"canvas.items[]\",\"composition.links[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]},{\"operationId\":\"widget.moveResize\",\"title\":\"Move or resize widget\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"canvasItem\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"canvasItem\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-move-resize\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.canvas.items\",\"WidgetPageDefinition.widgets\"],\"writes\":[\"page.canvas.items[]\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"canvas-item-invalid\",\"canvas-overlap-invalid\"],\"description\":\"Updates canvas placement for an existing widget using widgetKey as the stable identity.\"}}],\"validators\":[\"widget-exists\",\"canvas-item-valid\",\"canvas-item-targets-existing-widget\",\"canvas-overlap-policy-valid\"],\"affectedPaths\":[\"canvas.items[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]},{\"operationId\":\"widget.shell.configure\",\"title\":\"Configure widget shell\",\"scope\":\"templating\",\"targetKind\":\"widgetShell\",\"target\":{\"kind\":\"widgetShell\",\"resolver\":\"widget-shell-by-widget-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"shell\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-shell-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetShellEditorComponent\",\"SettingsPanelBridge\"],\"writes\":[\"page.widgets[].shell\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"settings-panel-bridge-missing\",\"shell-config-invalid\"],\"description\":\"Updates the page-builder-owned widget shell without editing child component inputs.\"}}],\"validators\":[\"widget-exists\",\"widget-shell-shape-valid\",\"settings-panel-bridge-available\",\"child-inputs-not-mutated\"],\"affectedPaths\":[\"widgets[].shell\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]}]}",
|
|
3902
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.0\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"page.configure\",\"title\":\"Configure page metadata\",\"scope\":\"global\",\"targetKind\":\"page\",\"target\":{\"kind\":\"page\",\"resolver\":\"widget-page-definition-root\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\"},\"layoutPreset\":{\"type\":\"string\"},\"themePreset\":{\"type\":\"string\"},\"context\":{\"type\":\"object\"},\"metadata\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-page-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition\",\"DynamicPageConfigEditorComponent\",\"SettingsPanelBridge\"],\"writes\":[\"page.title\",\"page.layoutPreset\",\"page.themePreset\",\"page.context\",\"page.metadata\"],\"identityKeys\":[\"pageIdentity.componentId\",\"pageIdentity.scope\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\"},\"layoutPreset\":{\"type\":\"string\"},\"themePreset\":{\"type\":\"string\"},\"context\":{\"type\":\"object\"},\"metadata\":{\"type\":\"object\"}}},\"failureModes\":[\"page-not-loaded\",\"context-not-json\",\"settings-panel-bridge-missing\"],\"description\":\"Updates root page metadata while preserving the renderable WidgetPageDefinition shape.\"}}],\"validators\":[\"widget-page-definition-valid\",\"no-legacy-grid-page-definition\",\"page-context-json-valid\",\"settings-panel-round-trip-valid\"],\"affectedPaths\":[\"title\",\"layoutPreset\",\"themePreset\",\"context\",\"metadata\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\"]},{\"operationId\":\"canvas.configure\",\"title\":\"Configure page canvas\",\"scope\":\"layout\",\"targetKind\":\"canvas\",\"target\":{\"kind\":\"canvas\",\"resolver\":\"widget-page-canvas\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"columns\":{\"type\":\"number\"},\"rowUnit\":{\"type\":\"number\"},\"gap\":{\"type\":\"number\"},\"items\":{\"type\":\"array\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-canvas-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.canvas\",\"DynamicPageBuilderComponent\"],\"writes\":[\"page.canvas.columns\",\"page.canvas.rowUnit\",\"page.canvas.gap\",\"page.canvas.items\"],\"identityKeys\":[\"canvas\"],\"inputSchema\":{\"type\":\"object\",\"properties\":{\"columns\":{\"type\":\"number\"},\"rowUnit\":{\"type\":\"number\"},\"gap\":{\"type\":\"number\"},\"items\":{\"type\":\"array\"}}},\"failureModes\":[\"canvas-missing\",\"canvas-item-references-missing-widget\",\"invalid-grid-geometry\"],\"description\":\"Configures the top-level canvas without introducing legacy GridPageDefinition semantics.\"}}],\"validators\":[\"canvas-columns-integer\",\"canvas-row-unit-valid\",\"canvas-gap-valid\",\"canvas-items-reference-existing-widgets\"],\"affectedPaths\":[\"canvas.columns\",\"canvas.rowUnit\",\"canvas.gap\",\"canvas.items\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\"]},{\"operationId\":\"widget.add\",\"title\":\"Add widget to page\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"componentId\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"componentId\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"inputs\":{\"type\":\"object\"},\"canvasItem\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-add\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetPageDefinition.canvas\",\"ComponentDocRegistry\",\"PAGE_BUILDER_WIDGET_AI_CATALOGS\"],\"writes\":[\"page.widgets[]\",\"page.canvas.items[]\"],\"identityKeys\":[\"widgetKey\"],\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"componentId\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"componentId\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"inputs\":{\"type\":\"object\"},\"canvasItem\":{\"type\":\"object\"}}},\"failureModes\":[\"widget-key-duplicate\",\"component-not-registered\",\"canvas-item-invalid\",\"child-input-contract-unknown\"],\"description\":\"Adds a registered component as a widget and places it on the canvas using a stable widgetKey.\"}}],\"validators\":[\"widget-key-unique\",\"component-registered\",\"canvas-item-valid\",\"child-inputs-delegated\",\"widget-key-not-array-index\"],\"affectedPaths\":[\"widgets[]\",\"canvas.items[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"component-catalog-loaded\"]},{\"operationId\":\"widget.remove\",\"title\":\"Remove widget from page\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"confirmed\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-remove\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetPageDefinition.canvas.items\",\"WidgetPageDefinition.composition.links\"],\"writes\":[\"page.widgets[]\",\"page.canvas.items[]\",\"page.composition.links[]\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"destructive-removal-not-confirmed\",\"dangling-composition-link\"],\"description\":\"Removes a widget and cleans canvas items and composition links that reference it.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"widget-exists\",\"destructive-removal-confirmed\",\"composition-links-cleaned\",\"canvas-items-reference-existing-widgets\"],\"affectedPaths\":[\"widgets[]\",\"canvas.items[]\",\"composition.links[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]},{\"operationId\":\"widget.moveResize\",\"title\":\"Move or resize widget\",\"scope\":\"layout\",\"targetKind\":\"widget\",\"target\":{\"kind\":\"widget\",\"resolver\":\"widget-by-stable-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\",\"canvasItem\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"canvasItem\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-move-resize\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.canvas.items\",\"WidgetPageDefinition.widgets\"],\"writes\":[\"page.canvas.items[]\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"canvas-item-invalid\",\"canvas-overlap-invalid\"],\"description\":\"Updates canvas placement for an existing widget using widgetKey as the stable identity.\"}}],\"validators\":[\"widget-exists\",\"canvas-item-valid\",\"canvas-item-targets-existing-widget\",\"canvas-overlap-policy-valid\"],\"affectedPaths\":[\"canvas.items[]\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]},{\"operationId\":\"widget.shell.configure\",\"title\":\"Configure widget shell\",\"scope\":\"templating\",\"targetKind\":\"widgetShell\",\"target\":{\"kind\":\"widgetShell\",\"resolver\":\"widget-shell-by-widget-key\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"widgetKey\"],\"properties\":{\"widgetKey\":{\"type\":\"string\"},\"shell\":{\"type\":\"object\",\"properties\":{\"stickyHeader\":{\"type\":\"boolean\",\"description\":\"Retain the existing header within the widget during page scrolling; suspended for drag authoring, collapsed/overlay states and scroll recovery.\"}}}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"page-builder-widget-shell-configure\",\"handlerContract\":{\"reads\":[\"WidgetPageDefinition.widgets\",\"WidgetShellEditorComponent\",\"SettingsPanelBridge\"],\"writes\":[\"page.widgets[].shell\"],\"identityKeys\":[\"widgetKey\"],\"failureModes\":[\"widget-not-found\",\"settings-panel-bridge-missing\",\"shell-config-invalid\"],\"description\":\"Updates the page-builder-owned widget shell without editing child component inputs.\"}}],\"validators\":[\"widget-exists\",\"widget-shell-shape-valid\",\"settings-panel-bridge-available\",\"child-inputs-not-mutated\"],\"affectedPaths\":[\"widgets[].shell\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"page-loaded\",\"target-widget-exists\"]}]}",
|
|
3897
3903
|
"sourcePointer": "projects/praxis-page-builder/src/lib/ai/praxis-page-builder-authoring-manifest.ts",
|
|
3898
|
-
"contentHash": "
|
|
3904
|
+
"contentHash": "9c3f606edc681ae101c35f0f28dd14c59a3978e73357a81b1c85080d9280c239",
|
|
3899
3905
|
"sourceKind": "component_definition",
|
|
3900
3906
|
"sourceId": "praxis-page-builder",
|
|
3901
3907
|
"corpusVersion": "1.0.0"
|