@praxisui/dynamic-form 9.0.0-beta.9 → 9.0.0-rc.1
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 +210 -2
- package/ai/component-registry.json +15640 -0
- package/docs/dynamic-form-visual-builder-parity-audit.md +268 -0
- package/docs/schema-driven-layout-materialization-rfc.md +498 -0
- package/fesm2022/{praxisui-dynamic-form-dynamic-form-agentic-authoring-turn-flow-CmFfx-VR.mjs → praxisui-dynamic-form-dynamic-form-agentic-authoring-turn-flow-w9V0aQ9B.mjs} +205 -22
- package/fesm2022/praxisui-dynamic-form.mjs +4902 -1011
- package/package.json +13 -9
- package/src/lib/config-editor/praxis-dynamic-form-config-editor.json-api.md +8 -6
- package/src/lib/praxis-dynamic-form.json-api.md +42 -9
- package/types/praxisui-dynamic-form.d.ts +168 -31
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm i @praxisui/dynamic-form@latest
|
|
|
26
26
|
Peer dependencies:
|
|
27
27
|
|
|
28
28
|
- `@angular/common`, `@angular/core`, `@angular/forms`, `@angular/cdk`, `@angular/material`, `@angular/router` `^21.0.0`
|
|
29
|
-
- `@praxisui/ai`, `@praxisui/core`, `@praxisui/dynamic-fields`, `@praxisui/metadata-editor`, `@praxisui/rich-content`, `@praxisui/settings-panel`, `@praxisui/visual-builder` `^9.0.0-beta.
|
|
29
|
+
- `@praxisui/ai`, `@praxisui/core`, `@praxisui/dynamic-fields`, `@praxisui/metadata-editor`, `@praxisui/rich-content`, `@praxisui/settings-panel`, `@praxisui/visual-builder` `^9.0.0-beta.12`
|
|
30
30
|
- `rxjs` `^7.8.0`
|
|
31
31
|
|
|
32
32
|
## Minimum Local Runtime
|
|
@@ -101,6 +101,140 @@ For schema-driven backend surfaces, prefer explicit `schemaUrl`, `submitUrl`, an
|
|
|
101
101
|
|
|
102
102
|
When using resource, schema, read, or submit flows, the host must provide the effective API/CRUD service wiring for that scope.
|
|
103
103
|
|
|
104
|
+
Schema-driven layout materialization is opt-in through `layoutPolicy`. Use it when the backend
|
|
105
|
+
schema already publishes enough `x-ui` metadata for the runtime to build the layout without
|
|
106
|
+
local `FormConfig.sections`.
|
|
107
|
+
|
|
108
|
+
```html
|
|
109
|
+
<praxis-dynamic-form
|
|
110
|
+
formId="employee-detail"
|
|
111
|
+
mode="view"
|
|
112
|
+
schemaUrl="/schemas/filtered?path=/api/employees/{id}&operation=get&schemaType=response"
|
|
113
|
+
[initialValue]="employee"
|
|
114
|
+
[layoutPolicy]="{
|
|
115
|
+
source: 'schema',
|
|
116
|
+
intent: 'detail',
|
|
117
|
+
preset: 'compactPresentation',
|
|
118
|
+
lifecycle: 'live',
|
|
119
|
+
persistence: 'transient',
|
|
120
|
+
schemaOperation: 'detail',
|
|
121
|
+
schemaType: 'response'
|
|
122
|
+
}">
|
|
123
|
+
</praxis-dynamic-form>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For create/edit command forms, the policy must point at a request schema, normally through an
|
|
127
|
+
explicit `schemaUrl` containing `schemaType=request` and `operation=post|put|patch`. If the
|
|
128
|
+
declared `schemaUrl` conflicts with `layoutPolicy.schemaType` or `layoutPolicy.schemaOperation`,
|
|
129
|
+
the runtime fails initialization instead of rendering a form from the wrong business contract.
|
|
130
|
+
|
|
131
|
+
`layoutPolicy.source = "schema"` ignores authored or persisted `sections`, but preserves
|
|
132
|
+
non-layout host/persisted concerns such as `actions`, `api`, `messages`, rules, hooks and rich
|
|
133
|
+
blocks. Host-provided non-layout config has precedence over persisted config.
|
|
134
|
+
|
|
135
|
+
When `mode="view"` and the host does not provide `presentationModeGlobal`, a schema policy with
|
|
136
|
+
`intent: "detail"` or `preset: "compactPresentation"` also enables presentation rendering. Hosts
|
|
137
|
+
that need traditional disabled controls for the same schema can pass `[presentationModeGlobal]="false"`.
|
|
138
|
+
For compact detail screens, explicit schema `x-ui.width` values are honored as 12-column spans so
|
|
139
|
+
fieldsets can render multiple read-only fields per row. Fields without an explicit width remain
|
|
140
|
+
full-width to preserve existing layouts. Generated compact sections also receive semantic header
|
|
141
|
+
icons derived from their group role, while field icons continue to come from existing schema
|
|
142
|
+
metadata.
|
|
143
|
+
In runtime rendering, compact detail containers are kept visible only when at least one referenced
|
|
144
|
+
field can actually be materialized after metadata visibility, `visible=false`, `hidden=true` and
|
|
145
|
+
field-rule overrides are applied. Boolean detail fields are valid presentation content, including
|
|
146
|
+
`false` values; marker/flag groups should render their boolean values, not collapse them as empty
|
|
147
|
+
strings. If a section has no materialized fields, the runtime hides the section instead of leaving
|
|
148
|
+
an orphan title.
|
|
149
|
+
When a migrated detail surface needs the summary density to win over generic schema widths, set
|
|
150
|
+
`detailSummary.widthPrecedence: "summary"` together with `columns` or `responsiveColumns`. The
|
|
151
|
+
default is `"schema"`, so existing forms keep honoring `x-ui.width` unless the summary policy
|
|
152
|
+
explicitly opts into overriding it for the compact read-only surface.
|
|
153
|
+
Use `"summary"` for curated operational summaries. If a field contains long narrative text,
|
|
154
|
+
legal content, observations, or values that require scan width, keep schema precedence for that
|
|
155
|
+
surface or exclude the field from the compact summary and expose it in a secondary detail group.
|
|
156
|
+
|
|
157
|
+
For fields published by the backend schema, server DTO metadata remains authoritative for semantic presentation data such as `label`, `hint`, `helpText`, `tooltip`, `tooltipOnHover`, and icon metadata. Local `FormConfig` should customize layout, grouping, transient fields, actions, and host-specific behavior, but it should not redefine DTO-owned field semantics.
|
|
158
|
+
|
|
159
|
+
Field-level access metadata follows the same authority boundary. When the backend publishes `x-ui.fieldAccess`, `@praxisui/core` preserves it in `FieldMetadata.fieldAccess` and `@praxisui/dynamic-form` can materialize it as hidden or read-only UX when the host supplies explicit `FormConfig.metadata.fieldAccessAuthorities` or enterprise runtime `authorities`. The runtime does not infer field authorities from `capabilities`; backend filtering and submit validation remain the security boundary.
|
|
160
|
+
|
|
161
|
+
Dense operational forms should keep DTO `hint`/`helpText` intact and use `FormConfig.helpPresentation` to choose the visual policy. For drawers or command forms, prefer `display: "auto"` with `preferPopoverForControls` for controls such as `toggle`, `checkbox`, and `select`; validation errors remain inline regardless of this policy. Field-level `helpDisplay` is still authoritative when present, including `helpDisplay: "auto"` for DTOs that need a local threshold.
|
|
162
|
+
|
|
163
|
+
Submit failures published in the Praxis `RestApiResponse.errors` envelope are materialized by the
|
|
164
|
+
runtime. A safe public `message` is shown to the user, while an error with a `target` matching a
|
|
165
|
+
form control is also attached to that control and marked as touched. Existing client validators
|
|
166
|
+
are preserved, and only the previous server error is cleared before a new submit attempt. Targets
|
|
167
|
+
may use Angular dotted paths or JSON Pointer syntax. Unknown targets remain form-level feedback;
|
|
168
|
+
the client does not guess a field from error text, codes, keywords, or private database details.
|
|
169
|
+
Generic network, validation, server, and save fallbacks use the platform i18n keys under
|
|
170
|
+
`global.submitError.*`; backend-owned business messages remain authoritative.
|
|
171
|
+
|
|
172
|
+
Example backend-owned `x-ui` metadata:
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"type": "object",
|
|
177
|
+
"properties": {
|
|
178
|
+
"frequencyType": {
|
|
179
|
+
"type": "string",
|
|
180
|
+
"x-ui": {
|
|
181
|
+
"label": "Frequency type",
|
|
182
|
+
"controlType": "async-select",
|
|
183
|
+
"helpText": "Select the operational class used by payroll and timekeeping rules.",
|
|
184
|
+
"tooltip": "Backend-owned DTO semantics; local FormConfig cannot override it.",
|
|
185
|
+
"tooltipOnHover": true,
|
|
186
|
+
"icon": "calendar_month",
|
|
187
|
+
"iconPosition": "start",
|
|
188
|
+
"iconColor": "primary",
|
|
189
|
+
"endpoint": "/api/frequency-types/options/filter",
|
|
190
|
+
"filterField": "name",
|
|
191
|
+
"sortField": "name",
|
|
192
|
+
"sortOrder": "asc",
|
|
193
|
+
"optionsPageSize": 20
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
In that flow, local `FormConfig` may place `frequencyType` in sections, rows, tabs, custom actions, or corporate-only local fields. It should not persist competing `label`, `helpText`, `tooltip`, or icon metadata for `frequencyType`, because the next schema reconciliation will restore the backend DTO semantics.
|
|
201
|
+
|
|
202
|
+
### ErgonX migration baseline
|
|
203
|
+
|
|
204
|
+
For ErgonX-style migrations, use schema-driven layout as the preferred target once the DTO/schema is semantically ready. Treat local `FormConfig.sections` as a temporary bridge, not as the standard for hundreds of screens.
|
|
205
|
+
|
|
206
|
+
Recommended defaults:
|
|
207
|
+
|
|
208
|
+
- detail/read-only: `layoutPolicy.source = "schema"`, `intent = "detail"`, `preset = "compactPresentation"`, `persistence = "transient"` and a response schema;
|
|
209
|
+
- create/edit: `layoutPolicy.source = "schema"`, `intent = "command"`, `preset = "groupedCommand"`, `persistence = "transient"` and a request schema;
|
|
210
|
+
- `groupedCommand` expands a single orphan `md`/`lg` field to the full row by default. Set `layoutPolicy.groupedCommand.orphanFieldExpansion = "preserve"` for intentionally compact rows, or `"all"` to expand orphan `xs`/`sm` fields too;
|
|
211
|
+
- dense command drawers: `helpPresentation.display = "auto"` with popover preference for select, checkbox, toggle, date and numeric controls;
|
|
212
|
+
- operational input-heavy forms: `fieldIconPolicy = "presentation-only"` unless the icon is part of the actual affordance.
|
|
213
|
+
|
|
214
|
+
Schema-driven command forms do not need to declare empty manual sections. Keep host config focused on behavior, messages, actions and field metadata that is genuinely local:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
const commandConfig: FormConfig = {
|
|
218
|
+
metadata: { source: 'schema' },
|
|
219
|
+
behavior: {
|
|
220
|
+
disableMountAnimation: true,
|
|
221
|
+
focusFirstError: true,
|
|
222
|
+
scrollToErrors: true,
|
|
223
|
+
},
|
|
224
|
+
messages: {
|
|
225
|
+
submitSuccess: 'Registro salvo.',
|
|
226
|
+
submitError: 'Não foi possível salvar o registro.',
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Pair this config with an explicit schema source, such as `[schemaUrl]`,
|
|
232
|
+
`[submitUrl]`, `[submitMethod]` and, in detached hosts, `[apiEndpointKey]` or
|
|
233
|
+
`[apiUrlEntry]`. A sectionless config is valid only when the schema/runtime
|
|
234
|
+
source is the canonical owner of field grouping and controls.
|
|
235
|
+
|
|
236
|
+
Do not use Angular config to fix weak DTO semantics. Missing grouping, vague `helpText`, generic labels, raw coded values, wrong control types or absent option metadata should return to backend DTO/schema hardening. The detailed migration checklist lives in `docs/schema-driven-layout-materialization-rfc.md`.
|
|
237
|
+
|
|
104
238
|
## Runtime Inputs And Outputs
|
|
105
239
|
|
|
106
240
|
Common inputs:
|
|
@@ -112,7 +246,7 @@ Common inputs:
|
|
|
112
246
|
- `apiEndpointKey`, `apiUrlEntry`
|
|
113
247
|
- `actions`, `layout`, `backConfig`, `hooks`
|
|
114
248
|
- `enableCustomization`
|
|
115
|
-
- `readonlyModeGlobal`, `disabledModeGlobal`, `presentationModeGlobal`, `visibleGlobal`
|
|
249
|
+
- `readonlyModeGlobal`, `disabledModeGlobal`, `presentationModeGlobal`, `fieldIconPolicy`, `visibleGlobal`
|
|
116
250
|
- `notifyIfOutdated`, `snoozeMs`, `autoOpenSettingsOnOutdated`
|
|
117
251
|
- `domainRules`
|
|
118
252
|
- `editorialContext`
|
|
@@ -131,6 +265,16 @@ Common outputs:
|
|
|
131
265
|
|
|
132
266
|
`formSubmit` exposes both persistence data and full UI state:
|
|
133
267
|
|
|
268
|
+
`schemaUrl`/the request schema is the only source of editable controls and the
|
|
269
|
+
command payload. `responseSchemaUrl` is diagnostic response evidence; hosts must
|
|
270
|
+
not use it to merge response-only properties into edit controls. Record identity
|
|
271
|
+
belongs in an external read-only context component and never in `formData`.
|
|
272
|
+
|
|
273
|
+
During hydration, properties absent from request-schema `fieldMetadata` do not
|
|
274
|
+
create Angular form controls, so they are absent from both `rawFormData` and the
|
|
275
|
+
prepared PUT/PATCH payload. Nested collection identity remains governed by its
|
|
276
|
+
own item-schema submit contract.
|
|
277
|
+
|
|
134
278
|
- `formData`: filtered backend payload after submit policies are applied
|
|
135
279
|
- `rawFormData`: complete form value bag, including UI-only values
|
|
136
280
|
|
|
@@ -169,10 +313,70 @@ Do not model backend DTO fields as local/transient fields. If a field belongs to
|
|
|
169
313
|
- `kind: "field"` references `fieldMetadata[].name`.
|
|
170
314
|
- `kind: "richContent"` hosts a `RichContentDocument` and does not enter `fieldMetadata`, `formData`, or HTTP payloads.
|
|
171
315
|
- `formRules` govern visibility, required state, values, labels, styles, and other whitelisted runtime properties.
|
|
316
|
+
- `formRulesState` is internal visual-builder state. LLMs and external tools should not write it directly.
|
|
172
317
|
- `formCommandRules` are used for governed side effects such as global actions.
|
|
173
318
|
|
|
174
319
|
Presentation formatting of field values is resolved by `@praxisui/dynamic-fields` from field metadata such as `valuePresentation`.
|
|
175
320
|
|
|
321
|
+
### Compact Presentation Preset
|
|
322
|
+
|
|
323
|
+
For dense enterprise read-only screens, `DynamicFormLayoutService.generateFormConfigFromMetadata`
|
|
324
|
+
can materialize a compact presentation layout directly from governed field metadata:
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
const config = layout.generateFormConfigFromMetadata(fields, {
|
|
328
|
+
layoutPreset: 'compactPresentation',
|
|
329
|
+
presentationRoleMap: {
|
|
330
|
+
Identificacao: 'core-attributes',
|
|
331
|
+
Regras: 'technical-scope',
|
|
332
|
+
Marcadores: 'behavior-flags',
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The preset keeps field semantics in `FieldMetadata`, creates compact rows from field width/data
|
|
338
|
+
type, derives semantic section header icons from group roles, marks generated sections with
|
|
339
|
+
`className: "pdx-presentation-section ..."`, and annotates
|
|
340
|
+
metadata with `generatedLayoutPreset: "compactPresentation"` and `presentationDensity: "compact"`.
|
|
341
|
+
Boolean fields are displayed through the canonical `valuePresentation: { type: "boolean" }` path,
|
|
342
|
+
so DTO-normalized booleans and legacy display values such as `S/N` are formatted by
|
|
343
|
+
`@praxisui/dynamic-fields`.
|
|
344
|
+
|
|
345
|
+
When a compact read-only screen needs operational signals, use `formBlocksBefore` with a short
|
|
346
|
+
`RichContentDocument` strip such as `metric` and `progress` nodes. Keep those blocks visual-only:
|
|
347
|
+
they must not duplicate DTO fields in `fieldMetadata`, enter `formData`, or push the first business
|
|
348
|
+
field below the useful viewport. Larger guidance cards, timelines, and stat groups belong in a
|
|
349
|
+
dedicated row, side context, or a separate rich-content demonstration tab rather than the compact
|
|
350
|
+
detail header.
|
|
351
|
+
|
|
352
|
+
The runtime exposes host-themeable CSS variables for this mode:
|
|
353
|
+
|
|
354
|
+
- `--pdx-presentation-label-width`
|
|
355
|
+
- `--pdx-presentation-label-size`
|
|
356
|
+
- `--pdx-presentation-value-size`
|
|
357
|
+
- `--pdx-presentation-row-gap`
|
|
358
|
+
- `--pdx-presentation-section-gap`
|
|
359
|
+
- `--pdx-presentation-flag-height`
|
|
360
|
+
- `--pdx-presentation-flag-padding`
|
|
361
|
+
- `--pdx-presentation-flag-radius`
|
|
362
|
+
- `--pdx-presentation-flag-font-size`
|
|
363
|
+
|
|
364
|
+
Use this preset for read/detail surfaces. Do not use it to replace backend DTO documentation,
|
|
365
|
+
business validation, or editable command forms. In table/detail workbenches, keep the table
|
|
366
|
+
selection and the detail `initialValue` synchronized in the host; the compact form only renders
|
|
367
|
+
the selected DTO state.
|
|
368
|
+
|
|
369
|
+
## LLM-Safe Authoring Subset
|
|
370
|
+
|
|
371
|
+
For AI-generated or tool-generated configuration, prefer canonical `FormConfig` JSON and keep edits reviewable:
|
|
372
|
+
|
|
373
|
+
- Write rule suggestions to `formRules[]` with `metadata: { origin: "llm", reviewStatus: "pending" }`.
|
|
374
|
+
- Do not write `formRulesState`; the editor may derive it after human review when the rule is visually representable.
|
|
375
|
+
- Treat simple field comparisons, scalar literals, field-to-field comparisons, and `and`/`or` groups as the stable visual round-trip subset.
|
|
376
|
+
- Treat advanced JsonLogic such as `!`, `xor`, `implies`, `between`, `notIn`, custom functions, context operands, and computed expressions as runtime-supported JSON-only unless a focused visual round-trip test exists.
|
|
377
|
+
- Use only properties allowed by the target rule schema. Unsupported or sanitized properties appear in rule diagnostics and should be fixed before publication.
|
|
378
|
+
- Keep side effects in `formCommandRules` with structured `globalAction: { actionId, payload }`; do not encode commands inside `formRules[].effect.properties`.
|
|
379
|
+
|
|
176
380
|
## Visual Editor
|
|
177
381
|
|
|
178
382
|
Use `PraxisDynamicFormConfigEditor` directly or enable customization on the runtime.
|
|
@@ -192,6 +396,8 @@ dialog.open(PraxisDynamicFormConfigEditor, {
|
|
|
192
396
|
|
|
193
397
|
The editor preserves the same `FormConfig` contract used by the runtime. Field type names, descriptions, and icons come from the dynamic-fields editorial metadata chain, not from a local map inside Dynamic Form.
|
|
194
398
|
|
|
399
|
+
Runtime-only rules remain valid JSON when they pass diagnostics, but they may open in JSON review instead of the visual rule builder until their condition and effect shape are covered by the visual-safe subset.
|
|
400
|
+
|
|
195
401
|
## AI Authoring
|
|
196
402
|
|
|
197
403
|
`PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST` declares executable operations for governed edits to:
|
|
@@ -205,6 +411,8 @@ The editor preserves the same `FormConfig` contract used by the runtime. Field t
|
|
|
205
411
|
|
|
206
412
|
The manifest is meant to keep AI-generated patches compatible with the visual editor and the runtime `FormConfig` contract.
|
|
207
413
|
|
|
414
|
+
Rule operations in the manifest write `formRules[]`, require pending review metadata, and intentionally avoid `formRulesState`. A valid JsonLogic condition is not automatically a visual round-trip guarantee; LLMs should use the safe subset above unless the operation explicitly targets a JSON-only/runtime-only path.
|
|
415
|
+
|
|
208
416
|
## Public API
|
|
209
417
|
|
|
210
418
|
Main exports:
|