@praxisui/page-builder 10.0.0-rc.36 → 10.0.0-rc.38

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,8 @@ 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
+ For the prospective governed-page journey, see [Create, review and publish pages — UX design](docs/governed-page-publication-ux.md). This is a storyboard and acceptance criteria for subsequent host/lifecycle integration; it does not make page creation or publication available in the current builder.
8
+
7
9
  ## Dashboard pages and persistence ownership
8
10
 
9
11
  A dashboard is a `WidgetPageDefinition` rendered by `praxis-dynamic-page` and edited
@@ -1156,3 +1158,60 @@ explicit `reloadPersistedPage(defaultPage)`; reload discards the local draft.
1156
1158
  - [Canonical technical overview: Overview](https://praxisui.dev/docs/components/praxis-page-builder)
1157
1159
  - [Praxis Angular public catalog](https://praxisui.dev/angular)
1158
1160
  <!-- praxis-npm-catalog-links:end -->
1161
+
1162
+ ### Optional editing highlight
1163
+
1164
+ This feature was added in source after `10.0.0-rc.36`; it is not yet part of a published package release.
1165
+
1166
+ `WidgetShellConfig.appearance.card.interactionHighlight` selects `standard` or
1167
+ `gradient`. Omit it to inherit the shell preset; the final default is `standard`.
1168
+ An explicit `standard` overrides a gradient preset. This is editing chrome: it
1169
+ appears on selection or keyboard focus while customization is enabled, never as a
1170
+ permanent border in the published page. Focusing a child control does not change selection; the highlight itself does not emit selection.
1171
+ The gradient uses the current primary, tertiary and secondary theme tokens. Resize
1172
+ grips follow the same choice. Internal control focus indicators remain intact;
1173
+ blocked canvas operations retain the error indicator and forced colors use a solid
1174
+ system-color outline. The highlight follows the resolved card radius (square for
1175
+ content-only shells).
1176
+
1177
+ ```json
1178
+ {"shell":{"kind":"dashboard-card","appearance":{"card":{"interactionHighlight":"gradient"}}}}
1179
+ ```
1180
+
1181
+ In Widget settings → Appearance, choose Inherit, Standard or Gradient and inspect
1182
+ its preview. Apply updates the local draft; the host controls remote persistence.
1183
+ Saving the settings panel alone is not proof of a server write: the reference Page
1184
+ Builder host requires Save page. Reopening and Reset preserve the distinction between
1185
+ an omitted value and an explicit override. Editing appearance on a widget without a
1186
+ shell preserves content-only presentation (`kind: 'none'`); a card requires an explicit
1187
+ choice. The option does not change child component inputs or enable customization.
1188
+
1189
+ This preference controls editing appearance; it grants no authorization and carries
1190
+ no business selection state. The host integrates persistence, identity and tenant
1191
+ scope through the canonical configuration infrastructure, including its ETag
1192
+ contract; this option requires no separate ETag implementation in the host. Editing only this preference must preserve unrelated
1193
+ shell settings, including `bodyLayout`, `windowActions` and action `pressed` values.
1194
+ Local editor round-trip tests do not prove remote tenant isolation or ETag behavior.
1195
+
1196
+ The existing AI operation `widget.shell.configure` merges partial shell input.
1197
+ Omitting `interactionHighlight` from that input preserves an existing override; it
1198
+ does not perform the visual editor's Inherit action, which removes the field from
1199
+ the complete saved document. Explicit `standard` disables the gradient but remains
1200
+ an override. Resetting an existing override to inherited styling through this AI
1201
+ operation remains unsupported; this option does not imply full editor/AI parity.
1202
+
1203
+ The historical live shell-authoring trial recorded in the validation report did
1204
+ not establish SSE, apply and persisted reopen support: its global assistant entry
1205
+ had no pinned widget target. Contextual child authoring also needs the correct
1206
+ operation owner and complete Page Builder document, rather than a child manifest
1207
+ and `definition.inputs`. Schema publication and compiler unit tests alone do not
1208
+ prove that journey. This integration preserves current dispatch; the historical
1209
+ failure is not a claim that every path on the current main has been disproven.
1210
+ Use the separately validated visual editor path for this preference until a
1211
+ successful shell-authoring AI journey is recorded for the integrated source.
1212
+
1213
+ ## Reusable copy and save-as journey
1214
+
1215
+ `PraxisPageCopyActionComponent` and `PraxisPageSaveAsComponent` provide reusable authoring controls for copying the current draft and saving a new page with a menu name/icon and confirmed internal route. Hosts provide an explicit `PageSaveAsAdapter`; the controls own validation feedback, retry snapshot/key, busy state, obsolete callback rejection and the last confirmed link. They do not provide storage or grant publication authority.
1216
+
1217
+ Connect `saveRequested` to `DynamicPageBuilderComponent.saveCurrentPage()` and its `pageSaveRequested` to `saveAs.save($event)` with `autoPersist=false`. Keep host routing, persistence and authorization in the adapter. See [contract, integration and proof limits](https://github.com/codexrodrigues/praxis-ui-angular/blob/main/projects/praxis-page-builder/docs/page-save-as.md). The first Hero proof is browser-local, not governed corporate publication; importing hosts require the matching packaged API before merge.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-21T13:45:30.091Z",
3
+ "generatedAt": "2026-10-23T20:24:09.136Z",
4
4
  "packageName": "@praxisui/page-builder",
5
- "packageVersion": "10.0.0-rc.36",
5
+ "packageVersion": "10.0.0-rc.38",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -2147,6 +2147,14 @@
2147
2147
  "fallbackBackground": {
2148
2148
  "type": "string",
2149
2149
  "description": "Opaque background for reduced transparency, unsupported blur and fullscreen/expanded modes."
2150
+ },
2151
+ "interactionHighlight": {
2152
+ "type": "string",
2153
+ "enum": [
2154
+ "standard",
2155
+ "gradient"
2156
+ ],
2157
+ "description": "Editing selection and keyboard-focus highlight. Absence in the saved shell inherits the preset, then standard. This operation merges partial input: omission preserves an existing override; use the visual editor to remove it. Gradient uses theme colors; never changes child inputs."
2150
2158
  }
2151
2159
  }
2152
2160
  },
@@ -3929,9 +3937,9 @@
3929
3937
  {
3930
3938
  "chunkIndex": 10,
3931
3939
  "chunkKind": "authoring_manifest",
3932
- "content": "{\"operationId\":\"widget.shell.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.2\",\"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.appearance\",\"shell.avatar\",\"shell.stickyHeader\",\"shell.appearance.card\",\"shell.appearance.header\",\"shell.avatar.imageSrc\",\"shell.avatar.name\",\"shell.avatar.initials\",\"shell.appearance.card.background\",\"shell.appearance.card.borderColor\",\"shell.appearance.card.borderWidth\",\"shell.appearance.card.borderStyle\",\"shell.appearance.card.borderRadius\",\"shell.appearance.card.shadow\",\"shell.appearance.card.backdropFilter\",\"shell.appearance.card.fallbackBackground\",\"shell.appearance.header.background\",\"shell.appearance.header.borderColor\",\"shell.appearance.header.borderWidth\",\"shell.appearance.header.borderStyle\",\"shell.appearance.header.titleColor\",\"shell.appearance.header.subtitleColor\",\"shell.appearance.header.iconColor\"]},\"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\":[]}",
3940
+ "content": "{\"operationId\":\"widget.shell.configure\",\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.2\",\"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.appearance\",\"shell.avatar\",\"shell.stickyHeader\",\"shell.appearance.card\",\"shell.appearance.header\",\"shell.avatar.imageSrc\",\"shell.avatar.name\",\"shell.avatar.initials\",\"shell.appearance.card.background\",\"shell.appearance.card.borderColor\",\"shell.appearance.card.borderWidth\",\"shell.appearance.card.borderStyle\",\"shell.appearance.card.borderRadius\",\"shell.appearance.card.shadow\",\"shell.appearance.card.backdropFilter\",\"shell.appearance.card.fallbackBackground\",\"shell.appearance.card.interactionHighlight\",\"shell.appearance.header.background\",\"shell.appearance.header.borderColor\",\"shell.appearance.header.borderWidth\",\"shell.appearance.header.borderStyle\",\"shell.appearance.header.titleColor\",\"shell.appearance.header.subtitleColor\",\"shell.appearance.header.iconColor\",\"standard\",\"gradient\"]},\"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\":[]}",
3933
3941
  "sourcePointer": "projects/praxis-page-builder/src/lib/ai/praxis-page-builder-authoring-manifest.ts",
3934
- "contentHash": "c160a825b90e04e842010a9ca9a4249a41f1bca027461453f2c8827ff9f346d8",
3942
+ "contentHash": "6e03c9b2e76b14b1ce517ce4abbb9bd95191513436e17ddb98d719a718a2f26a",
3935
3943
  "sourceKind": "component_definition",
3936
3944
  "sourceId": "praxis-page-builder",
3937
3945
  "corpusVersion": "1.0.0"
@@ -4049,9 +4057,9 @@
4049
4057
  {
4050
4058
  "chunkIndex": 22,
4051
4059
  "chunkKind": "authoring_manifest",
4052
- "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.2\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operations\",\"operations\":[{\"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\":{\"appearance\":{\"type\":\"object\",\"properties\":{\"card\":{\"type\":\"object\",\"properties\":{\"background\":{\"type\":\"string\"},\"borderColor\":{\"type\":\"string\"},\"borderWidth\":{\"type\":\"string\",\"description\":\"CSS border width; accepts per-side values.\"},\"borderStyle\":{\"type\":\"string\",\"description\":\"CSS border style: solid, dashed, dotted, double, none; accepts per-side values.\"},\"borderRadius\":{\"type\":\"string\"},\"shadow\":{\"type\":\"string\"},\"backdropFilter\":{\"type\":\"string\",\"description\":\"CSS backdrop effect for a translucent card, e.g. blur(16px) saturate(125%). none disables it.\"},\"fallbackBackground\":{\"type\":\"string\",\"description\":\"Opaque background for reduced transparency, unsupported blur and fullscreen/expanded modes.\"}}},\"header\":{\"type\":\"object\",\"properties\":{\"background\":{\"type\":\"string\"},\"borderColor\":{\"type\":\"string\"},\"borderWidth\":{\"type\":\"string\",\"description\":\"CSS width of the bottom header divider.\"},\"borderStyle\":{\"type\":\"string\",\"description\":\"CSS style of the bottom header divider.\"},\"titleColor\":{\"type\":\"string\"},\"subtitleColor\":{\"type\":\"string\"},\"iconColor\":{\"type\":\"string\"}}}}},\"avatar\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"imageSrc\":{\"type\":\"string\",\"description\":\"Photo URL or shell template, including ${transient.employee.avatarUrl}.\"},\"name\":{\"type\":\"string\",\"description\":\"Accessible name and initials fallback; supports shell templates.\"},\"initials\":{\"type\":\"string\",\"description\":\"Optional explicit initials fallback.\"}}},\"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\"]}]}",
4060
+ "content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.5.2\",\"componentId\":\"praxis-page-builder\",\"ownerPackage\":\"@praxisui/page-builder\",\"configSchemaId\":\"WidgetPageDefinition\",\"chunkSection\":\"operations\",\"operations\":[{\"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\":{\"appearance\":{\"type\":\"object\",\"properties\":{\"card\":{\"type\":\"object\",\"properties\":{\"background\":{\"type\":\"string\"},\"borderColor\":{\"type\":\"string\"},\"borderWidth\":{\"type\":\"string\",\"description\":\"CSS border width; accepts per-side values.\"},\"borderStyle\":{\"type\":\"string\",\"description\":\"CSS border style: solid, dashed, dotted, double, none; accepts per-side values.\"},\"borderRadius\":{\"type\":\"string\"},\"shadow\":{\"type\":\"string\"},\"backdropFilter\":{\"type\":\"string\",\"description\":\"CSS backdrop effect for a translucent card, e.g. blur(16px) saturate(125%). none disables it.\"},\"fallbackBackground\":{\"type\":\"string\",\"description\":\"Opaque background for reduced transparency, unsupported blur and fullscreen/expanded modes.\"},\"interactionHighlight\":{\"type\":\"string\",\"enum\":[\"standard\",\"gradient\"],\"description\":\"Editing selection and keyboard-focus highlight. Absence in the saved shell inherits the preset, then standard. This operation merges partial input: omission preserves an existing override; use the visual editor to remove it. Gradient uses theme colors; never changes child inputs.\"}}},\"header\":{\"type\":\"object\",\"properties\":{\"background\":{\"type\":\"string\"},\"borderColor\":{\"type\":\"string\"},\"borderWidth\":{\"type\":\"string\",\"description\":\"CSS width of the bottom header divider.\"},\"borderStyle\":{\"type\":\"string\",\"description\":\"CSS style of the bottom header divider.\"},\"titleColor\":{\"type\":\"string\"},\"subtitleColor\":{\"type\":\"string\"},\"iconColor\":{\"type\":\"string\"}}}}},\"avatar\":{\"type\":\"object\",\"additionalProperties\":false,\"properties\":{\"imageSrc\":{\"type\":\"string\",\"description\":\"Photo URL or shell template, including ${transient.employee.avatarUrl}.\"},\"name\":{\"type\":\"string\",\"description\":\"Accessible name and initials fallback; supports shell templates.\"},\"initials\":{\"type\":\"string\",\"description\":\"Optional explicit initials fallback.\"}}},\"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\"]}]}",
4053
4061
  "sourcePointer": "projects/praxis-page-builder/src/lib/ai/praxis-page-builder-authoring-manifest.ts",
4054
- "contentHash": "d1344e0691b8d7554e89281657b007367b84c26532b30b968bbe8d1b2b6183c9",
4062
+ "contentHash": "8166c3f95e7db89082089c9625aa34b15b95bdf8c676a9d5bd2f9f0661af7cf0",
4055
4063
  "sourceKind": "component_definition",
4056
4064
  "sourceId": "praxis-page-builder",
4057
4065
  "corpusVersion": "1.0.0"