@praxisui/crud 9.0.0-beta.80 → 9.0.0-beta.82
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 +5 -1
- package/ai/component-registry.json +76 -14
- package/fesm2022/praxisui-crud.mjs +48 -8
- package/package.json +7 -7
- package/types/praxisui-crud.d.ts +13 -1
package/README.md
CHANGED
|
@@ -159,7 +159,11 @@ const explicitEditAction: CrudAction = {
|
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
Drawer mode works without a host adapter: the package opens its standard form
|
|
162
|
-
dialog host with drawer presentation.
|
|
162
|
+
dialog host with drawer presentation. The native drawer remains anchored to its
|
|
163
|
+
configured viewport edge while applying initial or remembered size and while
|
|
164
|
+
maximizing or restoring. The default edge is right/top; a configured left edge
|
|
165
|
+
is preserved by the same lifecycle. `defaults.modal.edgeGap` controls the
|
|
166
|
+
viewport inset while maximized. Provide `CRUD_DRAWER_ADAPTER` only when a
|
|
163
167
|
host must replace that standard shell with a real corporate drawer implementation.
|
|
164
168
|
|
|
165
169
|
For native edit drawers, the runtime presents the selected record's canonical
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-20T13:31:18.568Z",
|
|
4
4
|
"packageName": "@praxisui/crud",
|
|
5
|
-
"packageVersion": "9.0.0-beta.
|
|
5
|
+
"packageVersion": "9.0.0-beta.82",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 2,
|
|
@@ -5771,18 +5771,34 @@
|
|
|
5771
5771
|
"minWidth": {
|
|
5772
5772
|
"type": "string"
|
|
5773
5773
|
},
|
|
5774
|
+
"minHeight": {
|
|
5775
|
+
"type": "string"
|
|
5776
|
+
},
|
|
5774
5777
|
"maxWidth": {
|
|
5775
5778
|
"type": "string"
|
|
5776
5779
|
},
|
|
5780
|
+
"maxHeight": {
|
|
5781
|
+
"type": "string"
|
|
5782
|
+
},
|
|
5777
5783
|
"density": {
|
|
5778
5784
|
"type": "string"
|
|
5779
5785
|
},
|
|
5786
|
+
"backdropStyle": {
|
|
5787
|
+
"enum": [
|
|
5788
|
+
"blur",
|
|
5789
|
+
"dim",
|
|
5790
|
+
"transparent"
|
|
5791
|
+
]
|
|
5792
|
+
},
|
|
5780
5793
|
"canMaximize": {
|
|
5781
5794
|
"type": "boolean"
|
|
5782
5795
|
},
|
|
5783
5796
|
"rememberLastState": {
|
|
5784
5797
|
"type": "boolean"
|
|
5785
5798
|
},
|
|
5799
|
+
"closeOnSave": {
|
|
5800
|
+
"type": "boolean"
|
|
5801
|
+
},
|
|
5786
5802
|
"startMaximized": {
|
|
5787
5803
|
"type": "boolean"
|
|
5788
5804
|
},
|
|
@@ -5793,7 +5809,27 @@
|
|
|
5793
5809
|
"type": "boolean"
|
|
5794
5810
|
},
|
|
5795
5811
|
"fullscreenBreakpoint": {
|
|
5796
|
-
"type": "
|
|
5812
|
+
"type": "number"
|
|
5813
|
+
},
|
|
5814
|
+
"position": {
|
|
5815
|
+
"type": "object",
|
|
5816
|
+
"properties": {
|
|
5817
|
+
"top": {
|
|
5818
|
+
"type": "string"
|
|
5819
|
+
},
|
|
5820
|
+
"bottom": {
|
|
5821
|
+
"type": "string"
|
|
5822
|
+
},
|
|
5823
|
+
"left": {
|
|
5824
|
+
"type": "string"
|
|
5825
|
+
},
|
|
5826
|
+
"right": {
|
|
5827
|
+
"type": "string"
|
|
5828
|
+
}
|
|
5829
|
+
}
|
|
5830
|
+
},
|
|
5831
|
+
"edgeGap": {
|
|
5832
|
+
"type": "number"
|
|
5797
5833
|
}
|
|
5798
5834
|
}
|
|
5799
5835
|
},
|
|
@@ -5826,6 +5862,7 @@
|
|
|
5826
5862
|
"open-mode-unsupported",
|
|
5827
5863
|
"drawer-runtime-unavailable",
|
|
5828
5864
|
"modal-size-invalid",
|
|
5865
|
+
"drawer-position-lifecycle-unstable",
|
|
5829
5866
|
"back-policy-invalid"
|
|
5830
5867
|
],
|
|
5831
5868
|
"description": "Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter."
|
|
@@ -5836,6 +5873,7 @@
|
|
|
5836
5873
|
"open-mode-supported",
|
|
5837
5874
|
"modal-size-valid",
|
|
5838
5875
|
"drawer-runtime-available",
|
|
5876
|
+
"drawer-position-lifecycle-stable",
|
|
5839
5877
|
"back-policy-valid",
|
|
5840
5878
|
"settings-panel-shell-compatible"
|
|
5841
5879
|
],
|
|
@@ -6191,6 +6229,12 @@
|
|
|
6191
6229
|
"code": "CRUD_DRAWER_RUNTIME_AVAILABLE",
|
|
6192
6230
|
"description": "Drawer open mode uses the default dialog-backed drawer runtime with CRUD-owned chrome, responsive right-panel sizing, Escape/backdrop handling and semantic close/save results; a host drawer adapter is optional only for shell-specific presentation."
|
|
6193
6231
|
},
|
|
6232
|
+
{
|
|
6233
|
+
"validatorId": "drawer-position-lifecycle-stable",
|
|
6234
|
+
"level": "error",
|
|
6235
|
+
"code": "CRUD_DRAWER_POSITION_LIFECYCLE_STABLE",
|
|
6236
|
+
"description": "A drawer must preserve its configured viewport edge through open, remembered-size restoration, maximize and restore."
|
|
6237
|
+
},
|
|
6194
6238
|
{
|
|
6195
6239
|
"validatorId": "back-policy-valid",
|
|
6196
6240
|
"level": "error",
|
|
@@ -6261,6 +6305,7 @@
|
|
|
6261
6305
|
"FormConfig and FieldMetadata edits must delegate to dynamic-form or metadata-editor manifests.",
|
|
6262
6306
|
"TableConfig edits must delegate to praxis-table; CRUD owns only shell orchestration and list surface binding.",
|
|
6263
6307
|
"Delete behavior is destructive and requires explicit confirmation plus backend capability support.",
|
|
6308
|
+
"Drawer position and edgeGap must round-trip without changing the configured edge during open, remembered-size restoration, maximize or restore.",
|
|
6264
6309
|
"crudContext must remain reference-stable across change detection cycles."
|
|
6265
6310
|
],
|
|
6266
6311
|
"examples": [
|
|
@@ -6379,6 +6424,23 @@
|
|
|
6379
6424
|
},
|
|
6380
6425
|
"isPositive": true
|
|
6381
6426
|
},
|
|
6427
|
+
{
|
|
6428
|
+
"id": "crud-drawer-left-edge",
|
|
6429
|
+
"request": "Open CRUD forms in a left drawer with an 8px maximized inset.",
|
|
6430
|
+
"operationId": "dialog.size.set",
|
|
6431
|
+
"target": "dialogHost",
|
|
6432
|
+
"params": {
|
|
6433
|
+
"defaultOpenMode": "drawer",
|
|
6434
|
+
"modal": {
|
|
6435
|
+
"position": {
|
|
6436
|
+
"left": "0",
|
|
6437
|
+
"top": "0"
|
|
6438
|
+
},
|
|
6439
|
+
"edgeGap": 8
|
|
6440
|
+
}
|
|
6441
|
+
},
|
|
6442
|
+
"isPositive": true
|
|
6443
|
+
},
|
|
6382
6444
|
{
|
|
6383
6445
|
"id": "crud-permissions-no-delete",
|
|
6384
6446
|
"request": "Hide delete when the resource capabilities do not allow it.",
|
|
@@ -6621,9 +6683,9 @@
|
|
|
6621
6683
|
{
|
|
6622
6684
|
"chunkIndex": 16,
|
|
6623
6685
|
"chunkKind": "authoring_manifest",
|
|
6624
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.edit.configure\",\"title\":\"Configure edit surface\",\"scope\":\"interaction\",\"targetKind\":\"editSurface\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-edit-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource.idField\",\"CrudLauncherService.resolveOpenMode\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"action-not-found\",\"id-param-missing\",\"open-mode-binding-incomplete\",\"resource-edit-not-supported\",\"submit-url-not-canonical\"],\"description\":\"Configures edit action routing/form binding and ensures id parameter mapping is available to the launcher.\"}}],\"validators\":[\"action-exists\",\"id-field-known\",\"id-param-mapping-valid\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-edit-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"surface.view.configure\",\"title\":\"Configure view surface\",\"scope\":\"interaction\",\"targetKind\":\"viewSurface\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-view-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"resource-view-not-supported\",\"readonly-form-delegation-missing\"],\"description\":\"Configures view action binding and delegates readonly form behavior to the dynamic-form manifest.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"resource-view-supported\",\"form-child-operation-delegated\",\"readonly-form-delegation-valid\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"delete.enabled.set\",\"title\":\"Configure delete behavior\",\"scope\":\"interaction\",\"targetKind\":\"deleteBehavior\",\"target\":{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-delete-behavior-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource\",\"GET /{resource}/{id}/capabilities\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].requiresConfirmation\",\"CrudMetadata.actions[].autoDelete\",\"CrudMetadata.actions[].form\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"delete-action-not-found\",\"resource-delete-not-supported\",\"destructive-delete-not-confirmed\",\"delete-submit-url-not-canonical\"],\"description\":\"Enables or disables delete behavior with capability checks and explicit confirmation for destructive changes.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"delete-action-exists\",\"resource-delete-supported\",\"destructive-delete-confirmed\",\"submit-url-canonical\",\"permissions-delete-valid\"],\"affectedPaths\":[\"actions[].disabled\",\"actions[].requiresConfirmation\",\"actions[].autoDelete\",\"actions[].form\",\"actions[].form.submitUrl\",\"actions[].form.submitMethod\",\"actions[].form.apiEndpointKey\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\",\"explicit-confirmation-provided\"]},{\"operationId\":\"dialog.size.set\",\"title\":\"Configure CRUD dialog host defaults\",\"scope\":\"interaction\",\"targetKind\":\"dialogHost\",\"target\":{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"
|
|
6686
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"surface.edit.configure\",\"title\":\"Configure edit surface\",\"scope\":\"interaction\",\"targetKind\":\"editSurface\",\"target\":{\"kind\":\"editSurface\",\"resolver\":\"crud-action-by-id:edit\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-edit-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource.idField\",\"CrudLauncherService.resolveOpenMode\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"action-not-found\",\"id-param-missing\",\"open-mode-binding-incomplete\",\"resource-edit-not-supported\",\"submit-url-not-canonical\"],\"description\":\"Configures edit action routing/form binding and ensures id parameter mapping is available to the launcher.\"}}],\"validators\":[\"action-exists\",\"id-field-known\",\"id-param-mapping-valid\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"submit-url-canonical\",\"resource-edit-supported\",\"form-child-operation-delegated\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"surface.view.configure\",\"title\":\"Configure view surface\",\"scope\":\"interaction\",\"targetKind\":\"viewSurface\",\"target\":{\"kind\":\"viewSurface\",\"resolver\":\"crud-action-by-id:view\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-view-surface-configure\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudLauncherService.resolveOpenMode\",\"DynamicFormDialogHostComponent\",\"api_metadata\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].form\",\"CrudMetadata.actions[].params\",\"CrudMetadata.actions[].back\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"action-not-found\",\"open-mode-binding-incomplete\",\"resource-view-not-supported\",\"readonly-form-delegation-missing\"],\"description\":\"Configures view action binding and delegates readonly form behavior to the dynamic-form manifest.\"}}],\"validators\":[\"action-exists\",\"open-mode-binding-complete\",\"schema-url-canonical\",\"resource-view-supported\",\"form-child-operation-delegated\",\"readonly-form-delegation-valid\"],\"affectedPaths\":[\"actions[].openMode\",\"actions[].route\",\"actions[].formId\",\"actions[].form\",\"actions[].params\",\"actions[].back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"delete.enabled.set\",\"title\":\"Configure delete behavior\",\"scope\":\"interaction\",\"targetKind\":\"deleteBehavior\",\"target\":{\"kind\":\"deleteBehavior\",\"resolver\":\"crud-action-by-id:delete\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"required\":[\"enabled\"],\"properties\":{\"enabled\":{\"type\":\"boolean\"},\"actionId\":{\"type\":\"string\"},\"requiresConfirmation\":{\"type\":\"boolean\"},\"autoDelete\":{\"type\":\"boolean\"},\"form\":{\"type\":\"object\",\"properties\":{\"submitUrl\":{\"type\":\"string\"},\"submitMethod\":{\"enum\":[\"delete\"]},\"apiEndpointKey\":{\"type\":\"string\"}}}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-delete-behavior-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.actions\",\"CrudMetadata.resource\",\"GET /{resource}/{id}/capabilities\"],\"writes\":[\"CrudMetadata.actions[]\",\"CrudMetadata.actions[].requiresConfirmation\",\"CrudMetadata.actions[].autoDelete\",\"CrudMetadata.actions[].form\"],\"identityKeys\":[\"actionId\"],\"failureModes\":[\"delete-action-not-found\",\"resource-delete-not-supported\",\"destructive-delete-not-confirmed\",\"delete-submit-url-not-canonical\"],\"description\":\"Enables or disables delete behavior with capability checks and explicit confirmation for destructive changes.\"}}],\"destructive\":true,\"requiresConfirmation\":true,\"validators\":[\"delete-action-exists\",\"resource-delete-supported\",\"destructive-delete-confirmed\",\"submit-url-canonical\",\"permissions-delete-valid\"],\"affectedPaths\":[\"actions[].disabled\",\"actions[].requiresConfirmation\",\"actions[].autoDelete\",\"actions[].form\",\"actions[].form.submitUrl\",\"actions[].form.submitMethod\",\"actions[].form.apiEndpointKey\"],\"submissionImpact\":\"affects-schema-backed-data\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\",\"explicit-confirmation-provided\"]},{\"operationId\":\"dialog.size.set\",\"title\":\"Configure CRUD dialog host defaults\",\"scope\":\"interaction\",\"targetKind\":\"dialogHost\",\"target\":{\"kind\":\"dialogHost\",\"resolver\":\"crud-dialog-host-defaults\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"defaultOpenMode\":{\"enum\":[\"route\",\"modal\",\"drawer\"]},\"modal\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"string\"},\"height\":{\"type\":\"string\"},\"minWidth\":{\"type\":\"string\"},\"minHeight\":{\"type\":\"string\"},\"maxWidth\":{\"type\":\"string\"},\"maxHeight\":{\"type\":\"string\"},\"density\":{\"type\":\"string\"},\"backdropStyle\":{\"enum\":[\"blur\",\"dim\",\"transparent\"]},\"canMaximize\":{\"type\":\"boolean\"},\"rememberLastState\":{\"type\":\"boolean\"},\"closeOnSave\":{\"type\":\"boolean\"},\"startMaximized\":{\"type\":\"boolean\"},\"disableCloseOnEsc\":{\"type\":\"boolean\"},\"disableCloseOnBackdrop\":{\"type\":\"boolean\"},\"fullscreenBreakpoint\":{\"type\":\"number\"},\"position\":{\"type\":\"object\",\"properties\":{\"top\":{\"type\":\"string\"},\"bottom\":{\"type\":\"string\"},\"left\":{\"type\":\"string\"},\"right\":{\"type\":\"string\"}}},\"edgeGap\":{\"type\":\"number\"}}},\"back\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-dialog-host-set\",\"handlerContract\":{\"reads\":[\"CrudMetadata.defaults\",\"CrudLauncherService.resolveOpenMode\",\"DialogService\",\"DynamicFormDialogHostComponent\",\"CRUD_DRAWER_ADAPTER\"],\"writes\":[\"CrudMetadata.defaults.openMode\",\"CrudMetadata.defaults.modal\",\"CrudMetadata.defaults.back\"],\"identityKeys\":[\"crudId\"],\"failureModes\":[\"open-mode-unsupported\",\"drawer-runtime-unavailable\",\"modal-size-invalid\",\"drawer-position-lifecycle-unstable\",\"back-policy-invalid\"],\"description\":\"Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter.\"}}],\"validators\":[\"open-mode-supported\",\"modal-size-valid\",\"drawer-runtime-available\",\"drawer-position-lifecycle-stable\",\"back-policy-valid\",\"settings-panel-shell-compatible\"],\"affectedPaths\":[\"defaults.openMode\",\"defaults.modal\",\"defaults.back\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\"]}]}",
|
|
6625
6687
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
6626
|
-
"contentHash": "
|
|
6688
|
+
"contentHash": "fd3bf3bc17cd6b87cb72593a28663e189ef6ce74dd1cfb7f72dbae38b434c3bb",
|
|
6627
6689
|
"sourceKind": "component_definition",
|
|
6628
6690
|
"sourceId": "praxis-crud",
|
|
6629
6691
|
"corpusVersion": "1.0.0"
|
|
@@ -6631,9 +6693,9 @@
|
|
|
6631
6693
|
{
|
|
6632
6694
|
"chunkIndex": 17,
|
|
6633
6695
|
"chunkKind": "authoring_manifest",
|
|
6634
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"form.childOperation.delegate\",\"title\":\"Delegate child form/table/dialog authoring operation\",\"scope\":\"global\",\"targetKind\":\"childOperation\",\"target\":{\"kind\":\"childOperation\",\"resolver\":\"child-authoring-manifest-operation\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"required\":[\"childComponentId\",\"childOperationId\",\"reason\"],\"properties\":{\"childComponentId\":{\"enum\":[\"praxis-dynamic-form\",\"praxis-table\",\"praxis-dialog\",\"praxis-settings-panel\"]},\"childOperationId\":{\"type\":\"string\"},\"reason\":{\"type\":\"string\"},\"childTarget\":{\"type\":\"object\"},\"childParams\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-child-operation-delegate\",\"handlerContract\":{\"reads\":[\"PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST\",\"PRAXIS_TABLE_AUTHORING_MANIFEST\",\"PRAXIS_DIALOG_AUTHORING_MANIFEST\",\"PRAXIS_SETTINGS_PANEL_AUTHORING_MANIFEST\"],\"writes\":[\"delegatedAuthoringOperations[]\"],\"identityKeys\":[\"childComponentId\",\"childOperationId\"],\"failureModes\":[\"child-manifest-missing\",\"child-operation-not-found\",\"attempted-local-child-config-write\"],\"description\":\"Records explicit delegation when requested edits belong to child manifests instead of CRUD orchestration.\"}}],\"validators\":[\"child-manifest-available\",\"child-operation-known\",\"no-local-form-config-write\",\"no-local-table-config-write\",\"delegation-target-valid\"],\"affectedPaths\":[\"delegatedAuthoringOperations\"],\"submissionImpact\":\"none\",\"preconditions\":[\"child-manifest-available\"]}]}",
|
|
6696
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"operations\",\"operations\":[{\"operationId\":\"permissions.set\",\"title\":\"Configure CRUD permissions\",\"scope\":\"interaction\",\"targetKind\":\"permissions\",\"target\":{\"kind\":\"permissions\",\"resolver\":\"crud-resource-capabilities\",\"ambiguityPolicy\":\"fail\",\"required\":true},\"inputSchema\":{\"type\":\"object\",\"properties\":{\"requiredCapabilities\":{\"type\":\"array\",\"items\":{\"enum\":[\"create\",\"view\",\"edit\",\"delete\"]}},\"actionPermissions\":{\"type\":\"object\"},\"denyWhenMissingCapability\":{\"type\":\"boolean\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-permissions-set\",\"handlerContract\":{\"reads\":[\"GET /{resource}/capabilities\",\"GET /{resource}/{id}/capabilities\",\"CrudMetadata.actions\"],\"writes\":[\"CrudMetadata.actions[].disabled\",\"CrudMetadata.actions[].visibleWhen\",\"CrudMetadata.actions[].requiresConfirmation\"],\"identityKeys\":[\"resourcePath\"],\"failureModes\":[\"capability-not-found\",\"action-permission-conflict\",\"delete-permission-without-confirmation\"],\"description\":\"Aligns CRUD action visibility/disablement with resource capabilities without inventing a second permission source.\"}}],\"validators\":[\"resource-capabilities-resolvable\",\"action-permission-supported\",\"delete-permission-requires-confirmation\",\"permissions-do-not-shadow-backend\"],\"affectedPaths\":[\"actions[].disabled\",\"actions[].visibleWhen\",\"actions[].requiresConfirmation\"],\"submissionImpact\":\"config-only\",\"preconditions\":[\"crud-metadata-loaded\",\"resource-capabilities-resolved\"]},{\"operationId\":\"form.childOperation.delegate\",\"title\":\"Delegate child form/table/dialog authoring operation\",\"scope\":\"global\",\"targetKind\":\"childOperation\",\"target\":{\"kind\":\"childOperation\",\"resolver\":\"child-authoring-manifest-operation\",\"ambiguityPolicy\":\"fail\",\"required\":false},\"inputSchema\":{\"type\":\"object\",\"required\":[\"childComponentId\",\"childOperationId\",\"reason\"],\"properties\":{\"childComponentId\":{\"enum\":[\"praxis-dynamic-form\",\"praxis-table\",\"praxis-dialog\",\"praxis-settings-panel\"]},\"childOperationId\":{\"type\":\"string\"},\"reason\":{\"type\":\"string\"},\"childTarget\":{\"type\":\"object\"},\"childParams\":{\"type\":\"object\"}}},\"effects\":[{\"kind\":\"compile-domain-patch\",\"handler\":\"crud-child-operation-delegate\",\"handlerContract\":{\"reads\":[\"PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST\",\"PRAXIS_TABLE_AUTHORING_MANIFEST\",\"PRAXIS_DIALOG_AUTHORING_MANIFEST\",\"PRAXIS_SETTINGS_PANEL_AUTHORING_MANIFEST\"],\"writes\":[\"delegatedAuthoringOperations[]\"],\"identityKeys\":[\"childComponentId\",\"childOperationId\"],\"failureModes\":[\"child-manifest-missing\",\"child-operation-not-found\",\"attempted-local-child-config-write\"],\"description\":\"Records explicit delegation when requested edits belong to child manifests instead of CRUD orchestration.\"}}],\"validators\":[\"child-manifest-available\",\"child-operation-known\",\"no-local-form-config-write\",\"no-local-table-config-write\",\"delegation-target-valid\"],\"affectedPaths\":[\"delegatedAuthoringOperations\"],\"submissionImpact\":\"none\",\"preconditions\":[\"child-manifest-available\"]}]}",
|
|
6635
6697
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
6636
|
-
"contentHash": "
|
|
6698
|
+
"contentHash": "626b7e33a2f7248d888938c7871c10835318980d934d916133b2c331f3047906",
|
|
6637
6699
|
"sourceKind": "component_definition",
|
|
6638
6700
|
"sourceId": "praxis-crud",
|
|
6639
6701
|
"corpusVersion": "1.0.0"
|
|
@@ -6641,9 +6703,9 @@
|
|
|
6641
6703
|
{
|
|
6642
6704
|
"chunkIndex": 18,
|
|
6643
6705
|
"chunkKind": "authoring_manifest",
|
|
6644
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"validators\",\"validators\":[{\"validatorId\":\"resource-exists-in-api-metadata\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_EXISTS\",\"description\":\"Resource must exist in api_metadata or resource discovery.\"},{\"validatorId\":\"resource-path-canonical\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_PATH_CANONICAL\",\"description\":\"Resource path must be canonical and not a local alias.\"},{\"validatorId\":\"resource-key-stable\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_KEY_STABLE\",\"description\":\"Resource key must remain stable for surfaces/actions/capabilities.\"},{\"validatorId\":\"id-field-known\",\"level\":\"error\",\"code\":\"CRUD_ID_FIELD_KNOWN\",\"description\":\"CRUD id field must exist for edit/view/delete flows.\"},{\"validatorId\":\"resource-capabilities-resolvable\",\"level\":\"error\",\"code\":\"CRUD_CAPABILITIES_RESOLVABLE\",\"description\":\"Resource capabilities must be resolvable before action enablement is authored.\"},{\"validatorId\":\"domain-catalog-context-resolvable\",\"level\":\"error\",\"code\":\"CRUD_DOMAIN_CATALOG_CONTEXT_RESOLVABLE\",\"description\":\"Domain Catalog governance context must resolve for the resource key and requested probe before authoring uses it.\"},{\"validatorId\":\"domain-catalog-read-only\",\"level\":\"error\",\"code\":\"CRUD_DOMAIN_CATALOG_READ_ONLY\",\"description\":\"Domain Catalog is read-only semantic context; CRUD may reference a probe but must not persist copied catalog rules.\"},{\"validatorId\":\"ai-usage-visibility-respected\",\"level\":\"error\",\"code\":\"CRUD_AI_USAGE_VISIBILITY_RESPECTED\",\"description\":\"Authoring must respect Domain Catalog aiUsage.visibility before exposing field data, prompts or generated patches.\"},{\"validatorId\":\"no-form-config-rule-materialization\",\"level\":\"error\",\"code\":\"CRUD_NO_FORM_RULE_MATERIALIZATION\",\"description\":\"Shared domain governance must not be materialized into FormConfig rules unless a backend policy explicitly authorizes it.\"},{\"validatorId\":\"table-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_TABLE_CHILD_DELEGATED\",\"description\":\"Table semantics must be delegated to praxis-table.\"},{\"validatorId\":\"query-context-valid\",\"level\":\"error\",\"code\":\"CRUD_QUERY_CONTEXT_VALID\",\"description\":\"Query context must be valid for the bound resource.\"},{\"validatorId\":\"filter-criteria-bridge-valid\",\"level\":\"warning\",\"code\":\"CRUD_FILTER_CRITERIA_BRIDGE_VALID\",\"description\":\"filterCriteria is a bridge; prefer queryContext for new remote authoring.\"},{\"validatorId\":\"crud-context-stable\",\"level\":\"error\",\"code\":\"CRUD_CONTEXT_STABLE\",\"description\":\"Authoring must not break stable crudContext references.\"},{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-create-supported\",\"level\":\"error\",\"code\":\"CRUD_CREATE_SUPPORTED\",\"description\":\"Create surface requires resource create capability.\"},{\"validatorId\":\"resource-edit-supported\",\"level\":\"error\",\"code\":\"CRUD_EDIT_SUPPORTED\",\"description\":\"Edit surface requires resource edit capability.\"},{\"validatorId\":\"resource-view-supported\",\"level\":\"error\",\"code\":\"CRUD_VIEW_SUPPORTED\",\"description\":\"View surface requires resource view capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"},{\"validatorId\":\"id-param-mapping-valid\",\"level\":\"error\",\"code\":\"CRUD_ID_PARAM_MAPPING_VALID\",\"description\":\"Edit/view actions must map resource id into route/query/input as required.\"},{\"validatorId\":\"readonly-form-delegation-valid\",\"level\":\"error\",\"code\":\"CRUD_READONLY_FORM_DELEGATED\",\"description\":\"Readonly form behavior belongs to the dynamic-form manifest.\"},{\"validatorId\":\"delete-action-exists\",\"level\":\"error\",\"code\":\"CRUD_DELETE_ACTION_EXISTS\",\"description\":\"Delete behavior requires a delete action target.\"},{\"validatorId\":\"resource-delete-supported\",\"level\":\"error\",\"code\":\"CRUD_DELETE_SUPPORTED\",\"description\":\"Delete behavior requires resource delete capability.\"},{\"validatorId\":\"destructive-delete-confirmed\",\"level\":\"error\",\"code\":\"CRUD_DELETE_CONFIRMED\",\"description\":\"Destructive delete behavior requires explicit confirmation.\"},{\"validatorId\":\"permissions-delete-valid\",\"level\":\"error\",\"code\":\"CRUD_DELETE_PERMISSION_VALID\",\"description\":\"Delete permission cannot bypass resource capabilities or confirmation policy.\"},{\"validatorId\":\"open-mode-supported\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_SUPPORTED\",\"description\":\"Open mode must be route, modal or drawer.\"},{\"validatorId\":\"modal-size-valid\",\"level\":\"error\",\"code\":\"CRUD_MODAL_SIZE_VALID\",\"description\":\"Modal sizing defaults must be valid DialogConfig values.\"},{\"validatorId\":\"drawer-runtime-available\",\"level\":\"error\",\"code\":\"CRUD_DRAWER_RUNTIME_AVAILABLE\",\"description\":\"Drawer open mode uses the default dialog-backed drawer runtime with CRUD-owned chrome, responsive right-panel sizing, Escape/backdrop handling and semantic close/save results; a host drawer adapter is optional only for shell-specific presentation.\"},{\"validatorId\":\"back-policy-valid\",\"level\":\"error\",\"code\":\"CRUD_BACK_POLICY_VALID\",\"description\":\"Back policy must be valid for route/modal/drawer behavior.\"},{\"validatorId\":\"settings-panel-shell-compatible\",\"level\":\"warning\",\"code\":\"CRUD_SETTINGS_PANEL_COMPATIBLE\",\"description\":\"Authoring shell must preserve apply/save/reset semantics.\"},{\"validatorId\":\"action-permission-supported\",\"level\":\"error\",\"code\":\"CRUD_ACTION_PERMISSION_SUPPORTED\",\"description\":\"Action permissions must map to supported resource capabilities.\"},{\"validatorId\":\"delete-permission-requires-confirmation\",\"level\":\"error\",\"code\":\"CRUD_DELETE_PERMISSION_CONFIRMATION\",\"description\":\"Delete permission enablement requires confirmation policy.\"},{\"validatorId\":\"permissions-do-not-shadow-backend\",\"level\":\"error\",\"code\":\"CRUD_PERMISSIONS_NO_BACKEND_SHADOW\",\"description\":\"UI permissions must not shadow backend capability denial.\"},{\"validatorId\":\"child-manifest-available\",\"level\":\"error\",\"code\":\"CRUD_CHILD_MANIFEST_AVAILABLE\",\"description\":\"Delegated child manifest must be available.\"},{\"validatorId\":\"child-operation-known\",\"level\":\"error\",\"code\":\"CRUD_CHILD_OPERATION_KNOWN\",\"description\":\"Delegated operation must exist in the child manifest.\"},{\"validatorId\":\"no-local-form-config-write\",\"level\":\"error\",\"code\":\"CRUD_NO_LOCAL_FORM_CONFIG_WRITE\",\"description\":\"CRUD must not locally redefine FormConfig semantics.\"},{\"validatorId\":\"no-local-table-config-write\",\"level\":\"error\",\"code\":\"CRUD_NO_LOCAL_TABLE_CONFIG_WRITE\",\"description\":\"CRUD must not locally redefine TableConfig semantics.\"},{\"validatorId\":\"delegation-target-valid\",\"level\":\"error\",\"code\":\"CRUD_DELEGATION_TARGET_VALID\",\"description\":\"Delegation target must be resolvable by the child manifest.\"}]}",
|
|
6706
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"validators\",\"validators\":[{\"validatorId\":\"resource-exists-in-api-metadata\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_EXISTS\",\"description\":\"Resource must exist in api_metadata or resource discovery.\"},{\"validatorId\":\"resource-path-canonical\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_PATH_CANONICAL\",\"description\":\"Resource path must be canonical and not a local alias.\"},{\"validatorId\":\"resource-key-stable\",\"level\":\"error\",\"code\":\"CRUD_RESOURCE_KEY_STABLE\",\"description\":\"Resource key must remain stable for surfaces/actions/capabilities.\"},{\"validatorId\":\"id-field-known\",\"level\":\"error\",\"code\":\"CRUD_ID_FIELD_KNOWN\",\"description\":\"CRUD id field must exist for edit/view/delete flows.\"},{\"validatorId\":\"resource-capabilities-resolvable\",\"level\":\"error\",\"code\":\"CRUD_CAPABILITIES_RESOLVABLE\",\"description\":\"Resource capabilities must be resolvable before action enablement is authored.\"},{\"validatorId\":\"domain-catalog-context-resolvable\",\"level\":\"error\",\"code\":\"CRUD_DOMAIN_CATALOG_CONTEXT_RESOLVABLE\",\"description\":\"Domain Catalog governance context must resolve for the resource key and requested probe before authoring uses it.\"},{\"validatorId\":\"domain-catalog-read-only\",\"level\":\"error\",\"code\":\"CRUD_DOMAIN_CATALOG_READ_ONLY\",\"description\":\"Domain Catalog is read-only semantic context; CRUD may reference a probe but must not persist copied catalog rules.\"},{\"validatorId\":\"ai-usage-visibility-respected\",\"level\":\"error\",\"code\":\"CRUD_AI_USAGE_VISIBILITY_RESPECTED\",\"description\":\"Authoring must respect Domain Catalog aiUsage.visibility before exposing field data, prompts or generated patches.\"},{\"validatorId\":\"no-form-config-rule-materialization\",\"level\":\"error\",\"code\":\"CRUD_NO_FORM_RULE_MATERIALIZATION\",\"description\":\"Shared domain governance must not be materialized into FormConfig rules unless a backend policy explicitly authorizes it.\"},{\"validatorId\":\"table-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_TABLE_CHILD_DELEGATED\",\"description\":\"Table semantics must be delegated to praxis-table.\"},{\"validatorId\":\"query-context-valid\",\"level\":\"error\",\"code\":\"CRUD_QUERY_CONTEXT_VALID\",\"description\":\"Query context must be valid for the bound resource.\"},{\"validatorId\":\"filter-criteria-bridge-valid\",\"level\":\"warning\",\"code\":\"CRUD_FILTER_CRITERIA_BRIDGE_VALID\",\"description\":\"filterCriteria is a bridge; prefer queryContext for new remote authoring.\"},{\"validatorId\":\"crud-context-stable\",\"level\":\"error\",\"code\":\"CRUD_CONTEXT_STABLE\",\"description\":\"Authoring must not break stable crudContext references.\"},{\"validatorId\":\"action-exists\",\"level\":\"error\",\"code\":\"CRUD_ACTION_EXISTS\",\"description\":\"Target action must exist or be created through CRUD action orchestration.\"},{\"validatorId\":\"open-mode-binding-complete\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_BINDING_COMPLETE\",\"description\":\"route requires route; modal/drawer require formId unless resolved by governed overrides.\"},{\"validatorId\":\"schema-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SCHEMA_URL_CANONICAL\",\"description\":\"Schema URLs must be canonical for the bound resource/action.\"},{\"validatorId\":\"submit-url-canonical\",\"level\":\"error\",\"code\":\"CRUD_SUBMIT_URL_CANONICAL\",\"description\":\"Submit URL and method must be canonical and declared together.\"},{\"validatorId\":\"resource-create-supported\",\"level\":\"error\",\"code\":\"CRUD_CREATE_SUPPORTED\",\"description\":\"Create surface requires resource create capability.\"},{\"validatorId\":\"resource-edit-supported\",\"level\":\"error\",\"code\":\"CRUD_EDIT_SUPPORTED\",\"description\":\"Edit surface requires resource edit capability.\"},{\"validatorId\":\"resource-view-supported\",\"level\":\"error\",\"code\":\"CRUD_VIEW_SUPPORTED\",\"description\":\"View surface requires resource view capability.\"},{\"validatorId\":\"form-child-operation-delegated\",\"level\":\"error\",\"code\":\"CRUD_FORM_CHILD_DELEGATED\",\"description\":\"FormConfig and FieldMetadata edits must delegate to dynamic-form/metadata-editor manifests.\"},{\"validatorId\":\"id-param-mapping-valid\",\"level\":\"error\",\"code\":\"CRUD_ID_PARAM_MAPPING_VALID\",\"description\":\"Edit/view actions must map resource id into route/query/input as required.\"},{\"validatorId\":\"readonly-form-delegation-valid\",\"level\":\"error\",\"code\":\"CRUD_READONLY_FORM_DELEGATED\",\"description\":\"Readonly form behavior belongs to the dynamic-form manifest.\"},{\"validatorId\":\"delete-action-exists\",\"level\":\"error\",\"code\":\"CRUD_DELETE_ACTION_EXISTS\",\"description\":\"Delete behavior requires a delete action target.\"},{\"validatorId\":\"resource-delete-supported\",\"level\":\"error\",\"code\":\"CRUD_DELETE_SUPPORTED\",\"description\":\"Delete behavior requires resource delete capability.\"},{\"validatorId\":\"destructive-delete-confirmed\",\"level\":\"error\",\"code\":\"CRUD_DELETE_CONFIRMED\",\"description\":\"Destructive delete behavior requires explicit confirmation.\"},{\"validatorId\":\"permissions-delete-valid\",\"level\":\"error\",\"code\":\"CRUD_DELETE_PERMISSION_VALID\",\"description\":\"Delete permission cannot bypass resource capabilities or confirmation policy.\"},{\"validatorId\":\"open-mode-supported\",\"level\":\"error\",\"code\":\"CRUD_OPEN_MODE_SUPPORTED\",\"description\":\"Open mode must be route, modal or drawer.\"},{\"validatorId\":\"modal-size-valid\",\"level\":\"error\",\"code\":\"CRUD_MODAL_SIZE_VALID\",\"description\":\"Modal sizing defaults must be valid DialogConfig values.\"},{\"validatorId\":\"drawer-runtime-available\",\"level\":\"error\",\"code\":\"CRUD_DRAWER_RUNTIME_AVAILABLE\",\"description\":\"Drawer open mode uses the default dialog-backed drawer runtime with CRUD-owned chrome, responsive right-panel sizing, Escape/backdrop handling and semantic close/save results; a host drawer adapter is optional only for shell-specific presentation.\"},{\"validatorId\":\"drawer-position-lifecycle-stable\",\"level\":\"error\",\"code\":\"CRUD_DRAWER_POSITION_LIFECYCLE_STABLE\",\"description\":\"A drawer must preserve its configured viewport edge through open, remembered-size restoration, maximize and restore.\"},{\"validatorId\":\"back-policy-valid\",\"level\":\"error\",\"code\":\"CRUD_BACK_POLICY_VALID\",\"description\":\"Back policy must be valid for route/modal/drawer behavior.\"},{\"validatorId\":\"settings-panel-shell-compatible\",\"level\":\"warning\",\"code\":\"CRUD_SETTINGS_PANEL_COMPATIBLE\",\"description\":\"Authoring shell must preserve apply/save/reset semantics.\"},{\"validatorId\":\"action-permission-supported\",\"level\":\"error\",\"code\":\"CRUD_ACTION_PERMISSION_SUPPORTED\",\"description\":\"Action permissions must map to supported resource capabilities.\"},{\"validatorId\":\"delete-permission-requires-confirmation\",\"level\":\"error\",\"code\":\"CRUD_DELETE_PERMISSION_CONFIRMATION\",\"description\":\"Delete permission enablement requires confirmation policy.\"},{\"validatorId\":\"permissions-do-not-shadow-backend\",\"level\":\"error\",\"code\":\"CRUD_PERMISSIONS_NO_BACKEND_SHADOW\",\"description\":\"UI permissions must not shadow backend capability denial.\"},{\"validatorId\":\"child-manifest-available\",\"level\":\"error\",\"code\":\"CRUD_CHILD_MANIFEST_AVAILABLE\",\"description\":\"Delegated child manifest must be available.\"},{\"validatorId\":\"child-operation-known\",\"level\":\"error\",\"code\":\"CRUD_CHILD_OPERATION_KNOWN\",\"description\":\"Delegated operation must exist in the child manifest.\"},{\"validatorId\":\"no-local-form-config-write\",\"level\":\"error\",\"code\":\"CRUD_NO_LOCAL_FORM_CONFIG_WRITE\",\"description\":\"CRUD must not locally redefine FormConfig semantics.\"},{\"validatorId\":\"no-local-table-config-write\",\"level\":\"error\",\"code\":\"CRUD_NO_LOCAL_TABLE_CONFIG_WRITE\",\"description\":\"CRUD must not locally redefine TableConfig semantics.\"},{\"validatorId\":\"delegation-target-valid\",\"level\":\"error\",\"code\":\"CRUD_DELEGATION_TARGET_VALID\",\"description\":\"Delegation target must be resolvable by the child manifest.\"}]}",
|
|
6645
6707
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
6646
|
-
"contentHash": "
|
|
6708
|
+
"contentHash": "696e76f0b2bfe99ce6dec91c073c9aa2b81c1287118b0645db6e8a0485a909f0",
|
|
6647
6709
|
"sourceKind": "component_definition",
|
|
6648
6710
|
"sourceId": "praxis-crud",
|
|
6649
6711
|
"corpusVersion": "1.0.0"
|
|
@@ -6651,9 +6713,9 @@
|
|
|
6651
6713
|
{
|
|
6652
6714
|
"chunkIndex": 19,
|
|
6653
6715
|
"chunkKind": "authoring_manifest",
|
|
6654
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"roundTripRequirements\",\"roundTripRequirements\":[\"CrudMetadata is the canonical CRUD document shape.\",\"CrudAuthoringDocument wraps CrudMetadata without introducing host-local aliases.\",\"Resource path and resource key have separate semantics: path is operational, key is discovery/capability identity.\",\"Domain Catalog context is referenced through resourceKey/release/probe and stays read-only; CRUD may attach queryContext.meta.domainCatalog but must not copy shared governance rules into FormConfig.\",\"Open mode round-trip must preserve route, formId, form contract, params, initialValue and back policy.\",\"FormConfig and FieldMetadata edits must delegate to dynamic-form or metadata-editor manifests.\",\"TableConfig edits must delegate to praxis-table; CRUD owns only shell orchestration and list surface binding.\",\"Delete behavior is destructive and requires explicit confirmation plus backend capability support.\",\"crudContext must remain reference-stable across change detection cycles.\"]}",
|
|
6716
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"roundTripRequirements\",\"roundTripRequirements\":[\"CrudMetadata is the canonical CRUD document shape.\",\"CrudAuthoringDocument wraps CrudMetadata without introducing host-local aliases.\",\"Resource path and resource key have separate semantics: path is operational, key is discovery/capability identity.\",\"Domain Catalog context is referenced through resourceKey/release/probe and stays read-only; CRUD may attach queryContext.meta.domainCatalog but must not copy shared governance rules into FormConfig.\",\"Open mode round-trip must preserve route, formId, form contract, params, initialValue and back policy.\",\"FormConfig and FieldMetadata edits must delegate to dynamic-form or metadata-editor manifests.\",\"TableConfig edits must delegate to praxis-table; CRUD owns only shell orchestration and list surface binding.\",\"Delete behavior is destructive and requires explicit confirmation plus backend capability support.\",\"Drawer position and edgeGap must round-trip without changing the configured edge during open, remembered-size restoration, maximize or restore.\",\"crudContext must remain reference-stable across change detection cycles.\"]}",
|
|
6655
6717
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
6656
|
-
"contentHash": "
|
|
6718
|
+
"contentHash": "9223b66da0df1282bc6777e827642542a75e6d7487177eed5de185ec4be35716",
|
|
6657
6719
|
"sourceKind": "component_definition",
|
|
6658
6720
|
"sourceId": "praxis-crud",
|
|
6659
6721
|
"corpusVersion": "1.0.0"
|
|
@@ -6661,9 +6723,9 @@
|
|
|
6661
6723
|
{
|
|
6662
6724
|
"chunkIndex": 20,
|
|
6663
6725
|
"chunkKind": "authoring_manifest",
|
|
6664
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"examples\",\"examples\":[{\"id\":\"crud-bind-funcionarios-resource\",\"request\":\"Bind this CRUD to funcionarios using id as the identifier.\",\"operationId\":\"resource.bind\",\"target\":\"resource:funcionarios\",\"params\":{\"resourcePath\":\"/funcionarios\",\"resourceKey\":\"funcionarios\",\"idField\":\"id\"},\"isPositive\":true},{\"id\":\"crud-attach-lgpd-cpf-context\",\"request\":\"Use the Domain Catalog LGPD context for cpf before changing the employee CRUD.\",\"operationId\":\"domain.governanceContext.attach\",\"target\":\"domainCatalog:human-resources.funcionarios:cpf\",\"params\":{\"resourceKey\":\"human-resources.funcionarios\",\"query\":\"cpf\",\"itemTypes\":[\"governance\"],\"intent\":\"authoring\"},\"isPositive\":true},{\"id\":\"crud-list-query-context\",\"request\":\"Filter the list by active employees using the canonical query context.\",\"operationId\":\"list.surface.configure\",\"target\":\"listSurface\",\"params\":{\"queryContext\":{\"filters\":[{\"field\":\"active\",\"operator\":\"eq\",\"value\":true}]}},\"isPositive\":true},{\"id\":\"crud-create-modal\",\"request\":\"Open create in a modal with the employee form.\",\"operationId\":\"surface.create.configure\",\"target\":\"action:create\",\"params\":{\"actionId\":\"create\",\"openMode\":\"modal\",\"formId\":\"employee-create\"},\"isPositive\":true},{\"id\":\"crud-edit-route-with-id\",\"request\":\"Edit should navigate to /employees/:id and map the row id.\",\"operationId\":\"surface.edit.configure\",\"target\":\"action:edit\",\"params\":{\"actionId\":\"edit\",\"openMode\":\"route\",\"route\":\"/employees/:id/edit\",\"params\":[{\"from\":\"id\",\"to\":\"routeParam\",\"name\":\"id\"}]},\"isPositive\":true},{\"id\":\"crud-view-drawer-readonly\",\"request\":\"Open view in a drawer and keep the form readonly.\",\"operationId\":\"surface.view.configure\",\"target\":\"action:view\",\"params\":{\"actionId\":\"view\",\"openMode\":\"drawer\",\"formId\":\"employee-view\"},\"isPositive\":true},{\"id\":\"crud-delete-enable-confirmed\",\"request\":\"Enable delete but require confirmation.\",\"operationId\":\"delete.enabled.set\",\"target\":\"action:delete\",\"params\":{\"enabled\":true,\"actionId\":\"delete\",\"requiresConfirmation\":true,\"autoDelete\":true},\"isPositive\":true},{\"id\":\"crud-dialog-size-medium\",\"request\":\"Make CRUD modals 900px wide and remember their last state.\",\"operationId\":\"dialog.size.set\",\"target\":\"dialogHost\",\"params\":{\"defaultOpenMode\":\"modal\",\"modal\":{\"width\":\"900px\",\"rememberLastState\":true}},\"isPositive\":true},{\"id\":\"crud-permissions-no-delete\",\"request\":\"Hide delete when the resource capabilities do not allow it.\",\"operationId\":\"permissions.set\",\"target\":\"permissions:delete\",\"params\":{\"requiredCapabilities\":[\"delete\"],\"denyWhenMissingCapability\":true},\"isPositive\":true},{\"id\":\"crud-delegate-form-layout\",\"request\":\"Add a new field to the create form.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-dynamic-form:field.add\",\"params\":{\"childComponentId\":\"praxis-dynamic-form\",\"childOperationId\":\"field.add\",\"reason\":\"Form field semantics belong to dynamic-form\"},\"isPositive\":true},{\"id\":\"crud-delegate-table-column\",\"request\":\"Add a salary column to the list table.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-table:column.add\",\"params\":{\"childComponentId\":\"praxis-table\",\"childOperationId\":\"column.add\",\"reason\":\"Table column semantics belong to praxis-table\"},\"isPositive\":true},{\"id\":\"crud-reject-local-form-rules\",\"request\":\"Put this dynamic-form validation rule directly inside CRUD.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-dynamic-form:rules.add\",\"params\":{\"childComponentId\":\"praxis-dynamic-form\",\"childOperationId\":\"rules.add\",\"reason\":\"CRUD must not redefine FormConfig rules\"},\"isPositive\":false},{\"id\":\"crud-reject-copy-domain-rule-to-formconfig\",\"request\":\"Copy the LGPD rule from Domain Catalog directly into the create form JSON.\",\"operationId\":\"domain.governanceContext.attach\",\"target\":\"domainCatalog:human-resources.funcionarios:cpf\",\"params\":{\"resourceKey\":\"human-resources.funcionarios\",\"query\":\"cpf\",\"itemTypes\":[\"governance\"],\"intent\":\"authoring\"},\"isPositive\":false},{\"id\":\"crud-reject-delete-without-capability\",\"request\":\"Force delete even though the backend does not expose delete capability.\",\"operationId\":\"delete.enabled.set\",\"target\":\"action:delete\",\"params\":{\"enabled\":true,\"actionId\":\"delete\",\"requiresConfirmation\":false},\"isPositive\":false}]}",
|
|
6726
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"examples\",\"examples\":[{\"id\":\"crud-bind-funcionarios-resource\",\"request\":\"Bind this CRUD to funcionarios using id as the identifier.\",\"operationId\":\"resource.bind\",\"target\":\"resource:funcionarios\",\"params\":{\"resourcePath\":\"/funcionarios\",\"resourceKey\":\"funcionarios\",\"idField\":\"id\"},\"isPositive\":true},{\"id\":\"crud-attach-lgpd-cpf-context\",\"request\":\"Use the Domain Catalog LGPD context for cpf before changing the employee CRUD.\",\"operationId\":\"domain.governanceContext.attach\",\"target\":\"domainCatalog:human-resources.funcionarios:cpf\",\"params\":{\"resourceKey\":\"human-resources.funcionarios\",\"query\":\"cpf\",\"itemTypes\":[\"governance\"],\"intent\":\"authoring\"},\"isPositive\":true},{\"id\":\"crud-list-query-context\",\"request\":\"Filter the list by active employees using the canonical query context.\",\"operationId\":\"list.surface.configure\",\"target\":\"listSurface\",\"params\":{\"queryContext\":{\"filters\":[{\"field\":\"active\",\"operator\":\"eq\",\"value\":true}]}},\"isPositive\":true},{\"id\":\"crud-create-modal\",\"request\":\"Open create in a modal with the employee form.\",\"operationId\":\"surface.create.configure\",\"target\":\"action:create\",\"params\":{\"actionId\":\"create\",\"openMode\":\"modal\",\"formId\":\"employee-create\"},\"isPositive\":true},{\"id\":\"crud-edit-route-with-id\",\"request\":\"Edit should navigate to /employees/:id and map the row id.\",\"operationId\":\"surface.edit.configure\",\"target\":\"action:edit\",\"params\":{\"actionId\":\"edit\",\"openMode\":\"route\",\"route\":\"/employees/:id/edit\",\"params\":[{\"from\":\"id\",\"to\":\"routeParam\",\"name\":\"id\"}]},\"isPositive\":true},{\"id\":\"crud-view-drawer-readonly\",\"request\":\"Open view in a drawer and keep the form readonly.\",\"operationId\":\"surface.view.configure\",\"target\":\"action:view\",\"params\":{\"actionId\":\"view\",\"openMode\":\"drawer\",\"formId\":\"employee-view\"},\"isPositive\":true},{\"id\":\"crud-delete-enable-confirmed\",\"request\":\"Enable delete but require confirmation.\",\"operationId\":\"delete.enabled.set\",\"target\":\"action:delete\",\"params\":{\"enabled\":true,\"actionId\":\"delete\",\"requiresConfirmation\":true,\"autoDelete\":true},\"isPositive\":true},{\"id\":\"crud-dialog-size-medium\",\"request\":\"Make CRUD modals 900px wide and remember their last state.\",\"operationId\":\"dialog.size.set\",\"target\":\"dialogHost\",\"params\":{\"defaultOpenMode\":\"modal\",\"modal\":{\"width\":\"900px\",\"rememberLastState\":true}},\"isPositive\":true},{\"id\":\"crud-drawer-left-edge\",\"request\":\"Open CRUD forms in a left drawer with an 8px maximized inset.\",\"operationId\":\"dialog.size.set\",\"target\":\"dialogHost\",\"params\":{\"defaultOpenMode\":\"drawer\",\"modal\":{\"position\":{\"left\":\"0\",\"top\":\"0\"},\"edgeGap\":8}},\"isPositive\":true},{\"id\":\"crud-permissions-no-delete\",\"request\":\"Hide delete when the resource capabilities do not allow it.\",\"operationId\":\"permissions.set\",\"target\":\"permissions:delete\",\"params\":{\"requiredCapabilities\":[\"delete\"],\"denyWhenMissingCapability\":true},\"isPositive\":true},{\"id\":\"crud-delegate-form-layout\",\"request\":\"Add a new field to the create form.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-dynamic-form:field.add\",\"params\":{\"childComponentId\":\"praxis-dynamic-form\",\"childOperationId\":\"field.add\",\"reason\":\"Form field semantics belong to dynamic-form\"},\"isPositive\":true},{\"id\":\"crud-delegate-table-column\",\"request\":\"Add a salary column to the list table.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-table:column.add\",\"params\":{\"childComponentId\":\"praxis-table\",\"childOperationId\":\"column.add\",\"reason\":\"Table column semantics belong to praxis-table\"},\"isPositive\":true},{\"id\":\"crud-reject-local-form-rules\",\"request\":\"Put this dynamic-form validation rule directly inside CRUD.\",\"operationId\":\"form.childOperation.delegate\",\"target\":\"praxis-dynamic-form:rules.add\",\"params\":{\"childComponentId\":\"praxis-dynamic-form\",\"childOperationId\":\"rules.add\",\"reason\":\"CRUD must not redefine FormConfig rules\"},\"isPositive\":false},{\"id\":\"crud-reject-copy-domain-rule-to-formconfig\",\"request\":\"Copy the LGPD rule from Domain Catalog directly into the create form JSON.\",\"operationId\":\"domain.governanceContext.attach\",\"target\":\"domainCatalog:human-resources.funcionarios:cpf\",\"params\":{\"resourceKey\":\"human-resources.funcionarios\",\"query\":\"cpf\",\"itemTypes\":[\"governance\"],\"intent\":\"authoring\"},\"isPositive\":false},{\"id\":\"crud-reject-delete-without-capability\",\"request\":\"Force delete even though the backend does not expose delete capability.\",\"operationId\":\"delete.enabled.set\",\"target\":\"action:delete\",\"params\":{\"enabled\":true,\"actionId\":\"delete\",\"requiresConfirmation\":false},\"isPositive\":false}]}",
|
|
6665
6727
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
6666
|
-
"contentHash": "
|
|
6728
|
+
"contentHash": "f2821fa0869a580cc33fbbd1d29f12c791082edab5b40787179d612d187a2990",
|
|
6667
6729
|
"sourceKind": "component_definition",
|
|
6668
6730
|
"sourceId": "praxis-crud",
|
|
6669
6731
|
"corpusVersion": "1.0.0"
|
|
@@ -6876,7 +6938,7 @@
|
|
|
6876
6938
|
"name": "data.metadata.defaults.modal",
|
|
6877
6939
|
"type": "DialogConfig",
|
|
6878
6940
|
"required": false,
|
|
6879
|
-
"description": "Dialog defaults
|
|
6941
|
+
"description": "Dialog defaults for size, behavior, viewport edge position, and maximized edge gap."
|
|
6880
6942
|
},
|
|
6881
6943
|
{
|
|
6882
6944
|
"name": "data.metadata.defaults.back",
|
|
@@ -3765,6 +3765,15 @@ class PraxisCrudComponent {
|
|
|
3765
3765
|
}
|
|
3766
3766
|
await this.onAction(action, row ?? undefined, event);
|
|
3767
3767
|
}
|
|
3768
|
+
async onToolbarAction(event) {
|
|
3769
|
+
const action = String(event?.action || '').trim();
|
|
3770
|
+
if (!action)
|
|
3771
|
+
return;
|
|
3772
|
+
const row = this.extractSelectedRowFromToolbarAction(event);
|
|
3773
|
+
if (row)
|
|
3774
|
+
this.selectedRow = row;
|
|
3775
|
+
await this.onAction(action, row ?? undefined, event);
|
|
3776
|
+
}
|
|
3768
3777
|
ngOnChanges(changes) {
|
|
3769
3778
|
if (!changes['metadata'] && !changes['context']) {
|
|
3770
3779
|
return;
|
|
@@ -4294,6 +4303,20 @@ class PraxisCrudComponent {
|
|
|
4294
4303
|
const first = Array.isArray(event?.rows) ? event.rows[0] : null;
|
|
4295
4304
|
return this.isRecord(first) ? first : null;
|
|
4296
4305
|
}
|
|
4306
|
+
extractSelectedRowFromToolbarAction(event) {
|
|
4307
|
+
if (this.isRecord(event?.selectedRow))
|
|
4308
|
+
return event.selectedRow;
|
|
4309
|
+
if (this.isRecord(event?.row))
|
|
4310
|
+
return event.row;
|
|
4311
|
+
const first = Array.isArray(event?.selectedRows) ? event.selectedRows[0] : null;
|
|
4312
|
+
return this.isRecord(first) ? first : null;
|
|
4313
|
+
}
|
|
4314
|
+
extractDiscoveryActionConfig(event) {
|
|
4315
|
+
const config = event?.actionConfig;
|
|
4316
|
+
return this.isRecord(config) && typeof config['resourceKey'] === 'string'
|
|
4317
|
+
? config
|
|
4318
|
+
: null;
|
|
4319
|
+
}
|
|
4297
4320
|
resolveSelectedRowForAction(action) {
|
|
4298
4321
|
const normalized = String(action || '').trim().toLowerCase();
|
|
4299
4322
|
if (!normalized || normalized === 'create' || normalized === 'add' || normalized === 'new') {
|
|
@@ -4306,7 +4329,7 @@ class PraxisCrudComponent {
|
|
|
4306
4329
|
if (!this.surfaceService) {
|
|
4307
4330
|
return false;
|
|
4308
4331
|
}
|
|
4309
|
-
const providedSurface = this.resolveProvidedSurface(normalizedAction, runtimeEvent
|
|
4332
|
+
const providedSurface = this.resolveProvidedSurface(normalizedAction, this.extractDiscoveryActionConfig(runtimeEvent));
|
|
4310
4333
|
if (!providedSurface && !this.isDiscoveryManagedCrudAction(normalizedAction)) {
|
|
4311
4334
|
return false;
|
|
4312
4335
|
}
|
|
@@ -4393,7 +4416,7 @@ class PraxisCrudComponent {
|
|
|
4393
4416
|
if (!normalizedAction || this.isDiscoveryManagedCrudAction(normalizedAction) || !this.surfaceService) {
|
|
4394
4417
|
return false;
|
|
4395
4418
|
}
|
|
4396
|
-
const providedAction = this.resolveProvidedWorkflowAction(normalizedAction, runtimeEvent
|
|
4419
|
+
const providedAction = this.resolveProvidedWorkflowAction(normalizedAction, this.extractDiscoveryActionConfig(runtimeEvent));
|
|
4397
4420
|
const catalog = providedAction ? null : await this.resolveDiscoveredActionCatalog(row);
|
|
4398
4421
|
const discoveredAction = providedAction || this.selectDiscoveredWorkflowAction(normalizedAction, catalog?.actions || []);
|
|
4399
4422
|
const resourcePath = String(catalog?.resourcePath || this.resolveResourcePath(this.resolvedMetadata) || '').trim();
|
|
@@ -5124,7 +5147,7 @@ class PraxisCrudComponent {
|
|
|
5124
5147
|
}
|
|
5125
5148
|
}
|
|
5126
5149
|
interpolateTranslationParams(text, params) {
|
|
5127
|
-
return Object.entries(params).reduce((current, [name, value]) => current.
|
|
5150
|
+
return Object.entries(params).reduce((current, [name, value]) => current.split(`{${name}}`).join(value), text);
|
|
5128
5151
|
}
|
|
5129
5152
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5130
5153
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", componentInstanceId: "componentInstanceId", context: "context", enableCustomization: "enableCustomization", authoringCapability: "authoringCapability" }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", error: "error", rowClick: "rowClick", selectionChange: "selectionChange", tableRuntimeConfigChange: "tableRuntimeConfigChange", crudAuthoringDocumentApplied: "crudAuthoringDocumentApplied", crudAuthoringDocumentSaved: "crudAuthoringDocumentSaved" }, providers: [
|
|
@@ -5145,7 +5168,7 @@ class PraxisCrudComponent {
|
|
|
5145
5168
|
(rowClick)="onTableRowClick($event)"
|
|
5146
5169
|
(selectionChange)="onTableSelectionChange($event)"
|
|
5147
5170
|
(rowAction)="onAction($event.action, $event.row, $event)"
|
|
5148
|
-
(toolbarAction)="
|
|
5171
|
+
(toolbarAction)="onToolbarAction($event)"
|
|
5149
5172
|
(bulkAction)="onBulkAction($event)"
|
|
5150
5173
|
(collectionLinksChange)="onCollectionLinksChange($event)"
|
|
5151
5174
|
(reset)="onResetPreferences()"
|
|
@@ -5184,7 +5207,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5184
5207
|
(rowClick)="onTableRowClick($event)"
|
|
5185
5208
|
(selectionChange)="onTableSelectionChange($event)"
|
|
5186
5209
|
(rowAction)="onAction($event.action, $event.row, $event)"
|
|
5187
|
-
(toolbarAction)="
|
|
5210
|
+
(toolbarAction)="onToolbarAction($event)"
|
|
5188
5211
|
(bulkAction)="onBulkAction($event)"
|
|
5189
5212
|
(collectionLinksChange)="onCollectionLinksChange($event)"
|
|
5190
5213
|
(reset)="onResetPreferences()"
|
|
@@ -6529,14 +6552,28 @@ const dialogHostSchema = {
|
|
|
6529
6552
|
width: { type: 'string' },
|
|
6530
6553
|
height: { type: 'string' },
|
|
6531
6554
|
minWidth: { type: 'string' },
|
|
6555
|
+
minHeight: { type: 'string' },
|
|
6532
6556
|
maxWidth: { type: 'string' },
|
|
6557
|
+
maxHeight: { type: 'string' },
|
|
6533
6558
|
density: { type: 'string' },
|
|
6559
|
+
backdropStyle: { enum: ['blur', 'dim', 'transparent'] },
|
|
6534
6560
|
canMaximize: { type: 'boolean' },
|
|
6535
6561
|
rememberLastState: { type: 'boolean' },
|
|
6562
|
+
closeOnSave: { type: 'boolean' },
|
|
6536
6563
|
startMaximized: { type: 'boolean' },
|
|
6537
6564
|
disableCloseOnEsc: { type: 'boolean' },
|
|
6538
6565
|
disableCloseOnBackdrop: { type: 'boolean' },
|
|
6539
|
-
fullscreenBreakpoint: { type: '
|
|
6566
|
+
fullscreenBreakpoint: { type: 'number' },
|
|
6567
|
+
position: {
|
|
6568
|
+
type: 'object',
|
|
6569
|
+
properties: {
|
|
6570
|
+
top: { type: 'string' },
|
|
6571
|
+
bottom: { type: 'string' },
|
|
6572
|
+
left: { type: 'string' },
|
|
6573
|
+
right: { type: 'string' },
|
|
6574
|
+
},
|
|
6575
|
+
},
|
|
6576
|
+
edgeGap: { type: 'number' },
|
|
6540
6577
|
},
|
|
6541
6578
|
},
|
|
6542
6579
|
back: { type: 'object' },
|
|
@@ -6763,10 +6800,10 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6763
6800
|
writes: ['CrudMetadata.defaults.openMode', 'CrudMetadata.defaults.modal', 'CrudMetadata.defaults.back'],
|
|
6764
6801
|
identityKeys: ['crudId'],
|
|
6765
6802
|
inputSchema: dialogHostSchema,
|
|
6766
|
-
failureModes: ['open-mode-unsupported', 'drawer-runtime-unavailable', 'modal-size-invalid', 'back-policy-invalid'],
|
|
6803
|
+
failureModes: ['open-mode-unsupported', 'drawer-runtime-unavailable', 'modal-size-invalid', 'drawer-position-lifecycle-unstable', 'back-policy-invalid'],
|
|
6767
6804
|
description: 'Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter.',
|
|
6768
6805
|
} }],
|
|
6769
|
-
validators: ['open-mode-supported', 'modal-size-valid', 'drawer-runtime-available', 'back-policy-valid', 'settings-panel-shell-compatible'],
|
|
6806
|
+
validators: ['open-mode-supported', 'modal-size-valid', 'drawer-runtime-available', 'drawer-position-lifecycle-stable', 'back-policy-valid', 'settings-panel-shell-compatible'],
|
|
6770
6807
|
affectedPaths: ['defaults.openMode', 'defaults.modal', 'defaults.back'],
|
|
6771
6808
|
submissionImpact: 'config-only',
|
|
6772
6809
|
preconditions: ['crud-metadata-loaded'],
|
|
@@ -6843,6 +6880,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6843
6880
|
{ validatorId: 'open-mode-supported', level: 'error', code: 'CRUD_OPEN_MODE_SUPPORTED', description: 'Open mode must be route, modal or drawer.' },
|
|
6844
6881
|
{ validatorId: 'modal-size-valid', level: 'error', code: 'CRUD_MODAL_SIZE_VALID', description: 'Modal sizing defaults must be valid DialogConfig values.' },
|
|
6845
6882
|
{ validatorId: 'drawer-runtime-available', level: 'error', code: 'CRUD_DRAWER_RUNTIME_AVAILABLE', description: 'Drawer open mode uses the default dialog-backed drawer runtime with CRUD-owned chrome, responsive right-panel sizing, Escape/backdrop handling and semantic close/save results; a host drawer adapter is optional only for shell-specific presentation.' },
|
|
6883
|
+
{ validatorId: 'drawer-position-lifecycle-stable', level: 'error', code: 'CRUD_DRAWER_POSITION_LIFECYCLE_STABLE', description: 'A drawer must preserve its configured viewport edge through open, remembered-size restoration, maximize and restore.' },
|
|
6846
6884
|
{ validatorId: 'back-policy-valid', level: 'error', code: 'CRUD_BACK_POLICY_VALID', description: 'Back policy must be valid for route/modal/drawer behavior.' },
|
|
6847
6885
|
{ validatorId: 'settings-panel-shell-compatible', level: 'warning', code: 'CRUD_SETTINGS_PANEL_COMPATIBLE', description: 'Authoring shell must preserve apply/save/reset semantics.' },
|
|
6848
6886
|
{ validatorId: 'action-permission-supported', level: 'error', code: 'CRUD_ACTION_PERMISSION_SUPPORTED', description: 'Action permissions must map to supported resource capabilities.' },
|
|
@@ -6863,6 +6901,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6863
6901
|
'FormConfig and FieldMetadata edits must delegate to dynamic-form or metadata-editor manifests.',
|
|
6864
6902
|
'TableConfig edits must delegate to praxis-table; CRUD owns only shell orchestration and list surface binding.',
|
|
6865
6903
|
'Delete behavior is destructive and requires explicit confirmation plus backend capability support.',
|
|
6904
|
+
'Drawer position and edgeGap must round-trip without changing the configured edge during open, remembered-size restoration, maximize or restore.',
|
|
6866
6905
|
'crudContext must remain reference-stable across change detection cycles.',
|
|
6867
6906
|
],
|
|
6868
6907
|
examples: [
|
|
@@ -6874,6 +6913,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6874
6913
|
{ id: 'crud-view-drawer-readonly', request: 'Open view in a drawer and keep the form readonly.', operationId: 'surface.view.configure', target: 'action:view', params: { actionId: 'view', openMode: 'drawer', formId: 'employee-view' }, isPositive: true },
|
|
6875
6914
|
{ id: 'crud-delete-enable-confirmed', request: 'Enable delete but require confirmation.', operationId: 'delete.enabled.set', target: 'action:delete', params: { enabled: true, actionId: 'delete', requiresConfirmation: true, autoDelete: true }, isPositive: true },
|
|
6876
6915
|
{ id: 'crud-dialog-size-medium', request: 'Make CRUD modals 900px wide and remember their last state.', operationId: 'dialog.size.set', target: 'dialogHost', params: { defaultOpenMode: 'modal', modal: { width: '900px', rememberLastState: true } }, isPositive: true },
|
|
6916
|
+
{ id: 'crud-drawer-left-edge', request: 'Open CRUD forms in a left drawer with an 8px maximized inset.', operationId: 'dialog.size.set', target: 'dialogHost', params: { defaultOpenMode: 'drawer', modal: { position: { left: '0', top: '0' }, edgeGap: 8 } }, isPositive: true },
|
|
6877
6917
|
{ id: 'crud-permissions-no-delete', request: 'Hide delete when the resource capabilities do not allow it.', operationId: 'permissions.set', target: 'permissions:delete', params: { requiredCapabilities: ['delete'], denyWhenMissingCapability: true }, isPositive: true },
|
|
6878
6918
|
{ id: 'crud-delegate-form-layout', request: 'Add a new field to the create form.', operationId: 'form.childOperation.delegate', target: 'praxis-dynamic-form:field.add', params: { childComponentId: 'praxis-dynamic-form', childOperationId: 'field.add', reason: 'Form field semantics belong to dynamic-form' }, isPositive: true },
|
|
6879
6919
|
{ id: 'crud-delegate-table-column', request: 'Add a salary column to the list table.', operationId: 'form.childOperation.delegate', target: 'praxis-table:column.add', params: { childComponentId: 'praxis-table', childOperationId: 'column.add', reason: 'Table column semantics belong to praxis-table' }, isPositive: true },
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.82",
|
|
4
4
|
"description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
|
-
"@praxisui/dynamic-form": "^9.0.0-beta.
|
|
9
|
-
"@praxisui/table": "^9.0.0-beta.
|
|
10
|
-
"@praxisui/core": "^9.0.0-beta.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.0-beta.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.0-beta.
|
|
8
|
+
"@praxisui/dynamic-form": "^9.0.0-beta.82",
|
|
9
|
+
"@praxisui/table": "^9.0.0-beta.82",
|
|
10
|
+
"@praxisui/core": "^9.0.0-beta.82",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.0-beta.82",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.0-beta.82",
|
|
13
13
|
"@angular/cdk": "^21.0.0",
|
|
14
14
|
"@angular/forms": "^21.0.0",
|
|
15
15
|
"@angular/material": "^21.0.0",
|
|
16
16
|
"@angular/router": "^21.0.0",
|
|
17
|
-
"@praxisui/ai": "^9.0.0-beta.
|
|
17
|
+
"@praxisui/ai": "^9.0.0-beta.82",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
package/types/praxisui-crud.d.ts
CHANGED
|
@@ -20,14 +20,20 @@ interface DialogConfig<D = any> extends MatDialogConfig<D> {
|
|
|
20
20
|
disableCloseOnEsc?: boolean;
|
|
21
21
|
/** Density hint consumed by CRUD dialog host chrome */
|
|
22
22
|
density?: 'default' | 'compact';
|
|
23
|
+
/** Praxis backdrop visual preset */
|
|
24
|
+
backdropStyle?: 'blur' | 'dim' | 'transparent';
|
|
23
25
|
/** Enable maximize button */
|
|
24
26
|
canMaximize?: boolean;
|
|
25
27
|
/** Persist last dialog size/state for the same form */
|
|
26
28
|
rememberLastState?: boolean;
|
|
29
|
+
/** Keep the dialog open after a successful form submission */
|
|
30
|
+
closeOnSave?: boolean;
|
|
27
31
|
/** Start dialog maximized */
|
|
28
32
|
startMaximized?: boolean;
|
|
29
33
|
/** Screen width in px where dialog starts fullscreen */
|
|
30
34
|
fullscreenBreakpoint?: number;
|
|
35
|
+
/** Viewport inset in px applied while the dialog or drawer is maximized */
|
|
36
|
+
edgeGap?: number;
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
declare class DialogService {
|
|
@@ -131,7 +137,10 @@ interface CrudValidationContext {
|
|
|
131
137
|
|
|
132
138
|
type CrudActionRuntimeEvent = {
|
|
133
139
|
action?: string;
|
|
134
|
-
actionConfig?: ResourceActionCatalogItem | ResourceSurfaceCatalogItem | null;
|
|
140
|
+
actionConfig?: ToolbarAction | ResourceActionCatalogItem | ResourceSurfaceCatalogItem | null;
|
|
141
|
+
row?: Record<string, unknown>;
|
|
142
|
+
selectedRow?: Record<string, unknown>;
|
|
143
|
+
selectedRows?: Record<string, unknown>[];
|
|
135
144
|
rows?: Record<string, unknown>[];
|
|
136
145
|
resourceIdentity?: MaterializedResourceIdentity | null;
|
|
137
146
|
};
|
|
@@ -227,6 +236,7 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
227
236
|
onTableRowClick(event: unknown): void;
|
|
228
237
|
onTableSelectionChange(event: unknown): void;
|
|
229
238
|
onBulkAction(event: CrudActionRuntimeEvent): Promise<void>;
|
|
239
|
+
onToolbarAction(event: CrudActionRuntimeEvent): Promise<void>;
|
|
230
240
|
ngOnChanges(changes: SimpleChanges): void;
|
|
231
241
|
onAction(action: string, row?: Record<string, unknown>, runtimeEvent?: CrudActionRuntimeEvent): Promise<void>;
|
|
232
242
|
private hasExplicitOpenBinding;
|
|
@@ -261,6 +271,8 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
261
271
|
private extractRowFromEvent;
|
|
262
272
|
private extractSelectedRowFromEvent;
|
|
263
273
|
private extractSelectedRowFromBulkAction;
|
|
274
|
+
private extractSelectedRowFromToolbarAction;
|
|
275
|
+
private extractDiscoveryActionConfig;
|
|
264
276
|
private resolveSelectedRowForAction;
|
|
265
277
|
private tryOpenDiscoveredCrudSurface;
|
|
266
278
|
private resolveDiscoveredSurfaceCatalog;
|