@praxisui/dynamic-form 9.0.0-beta.9 → 9.0.0-beta.90
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
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "RFC - Schema-driven Layout Materialization For Dynamic Form"
|
|
3
|
+
doc_type: "rfc"
|
|
4
|
+
component: "praxis-dynamic-form"
|
|
5
|
+
status: "implemented-partial"
|
|
6
|
+
owner: "praxis-ui"
|
|
7
|
+
last_updated: "2026-06-29"
|
|
8
|
+
classification: "contrato-publico, arquitetural"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# RFC - Schema-driven Layout Materialization For Dynamic Form
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Implemented partial, review-revised.
|
|
16
|
+
|
|
17
|
+
This document records the platform design direction and the first runtime implementation tranche.
|
|
18
|
+
|
|
19
|
+
Specialized review approved the direction and blocked implementation readiness until ownership, precedence, persistence, preset naming, operation schema source, section id stability and visual acceptance criteria were made explicit. The current implementation keeps schema-driven layout opt-in, validates declared schema URL context, preserves non-layout config concerns, and leaves visual acceptance as a promotion gate.
|
|
20
|
+
|
|
21
|
+
## Context
|
|
22
|
+
|
|
23
|
+
Praxis Dynamic Form already consumes backend metadata and can generate form layouts from schema-derived fields. In practice, hosts still repeat `FormConfig.sections` locally for read-only detail views and for create/edit command forms, even when the backend DTOs publish `x-ui` metadata such as `group`, `order`, `width`, labels, help text, read-only hints and presentation metadata.
|
|
24
|
+
|
|
25
|
+
The Ergon migration exposed this as a recurring platform issue. The `ERGadm00034` screen for codigos de frequencia currently needs local section configs for detail and command forms although the Java DTOs already publish grouped metadata. The same pattern appears in other migrated forms, including regras de frequencia, tipos de rubrica and vinculos funcionais.
|
|
26
|
+
|
|
27
|
+
This is not an Ergon-only design problem. If every migrated screen must author local `FormConfig.sections`, the platform loses the main benefit of schema-driven UI: one canonical backend contract feeding many hosts consistently.
|
|
28
|
+
|
|
29
|
+
## Classification
|
|
30
|
+
|
|
31
|
+
This RFC is classified as `contrato-publico` and `arquitetural`.
|
|
32
|
+
|
|
33
|
+
The affected public surface is the Dynamic Form layout contract around schema materialization, `FormConfig`, generated presets, and the way consumers opt into generated read-only and editable layouts.
|
|
34
|
+
|
|
35
|
+
## Impact Map
|
|
36
|
+
|
|
37
|
+
- Canonical subprojects affected: `praxis-ui-angular`, primarily `@praxisui/dynamic-form` and `@praxisui/core`.
|
|
38
|
+
- Consumers impacted: `ergon-web`, `@praxisui/crud`, surface action launchers, official examples, playgrounds and any host using `schemaUrl`, `resourcePath` or local `FormConfig`.
|
|
39
|
+
- Public docs potentially affected: Dynamic Form README, JSON API docs, authoring docs, docs shell registry, landing-page published guides and AI authoring manifests.
|
|
40
|
+
- Examples and recipes potentially affected: Dynamic Form examples, CRUD dialog examples, schema-driven resource examples and Ergon migration recipes.
|
|
41
|
+
- Minimum validations needed for implementation: focused unit tests for the shared materializer, Dynamic Form runtime tests, CRUD dialog-host tests and visual checks for desktop and narrow viewports.
|
|
42
|
+
- Breaking-change risk: medium if defaults are changed; low if the new behavior is opt-in and authored configs keep precedence by default.
|
|
43
|
+
|
|
44
|
+
## Problem
|
|
45
|
+
|
|
46
|
+
The platform currently supports the pieces of schema-driven layout, but the behavior is not materialized as a first-class runtime policy.
|
|
47
|
+
|
|
48
|
+
Observed gaps:
|
|
49
|
+
|
|
50
|
+
- `SchemaNormalizerService` normalizes `x-ui` metadata such as `group`, `order`, `width`, visibility and value presentation.
|
|
51
|
+
- `mapFieldDefinitionToMetadata()` preserves the same metadata on `FieldMetadata`.
|
|
52
|
+
- `DynamicFormLayoutService.generateFormConfigFromMetadata()` can create grouped layouts and already supports a compact presentation preset.
|
|
53
|
+
- `PraxisDynamicForm.generatedLayoutPreset` is currently an initial-generation hint. It does not define a durable runtime policy when a host passes a config or when local persisted config exists.
|
|
54
|
+
- `SurfaceOpenMaterializerService` has its own local layout builder, which risks duplicating and diverging from Dynamic Form layout behavior.
|
|
55
|
+
- CRUD dialog flows can render schema-driven forms, but there is no canonical way to ask for a grouped command layout instead of relying on default generated layout or local config.
|
|
56
|
+
|
|
57
|
+
The result is repeated local `FormConfig.sections` in application screens. This creates drift from the backend DTO contract, increases migration effort and makes the first migrated screens poor templates for hundreds of future screens.
|
|
58
|
+
|
|
59
|
+
## Existing Capability Assessment
|
|
60
|
+
|
|
61
|
+
This is `suportado-parcialmente` and `ja-suportado-mal-materializado`, not a complete absence of metadata contract.
|
|
62
|
+
|
|
63
|
+
The backend can already publish the metadata required for a reasonable layout. The missing platform capability is an explicit, reusable and opt-in runtime materialization policy that turns schema metadata into stable read-only and editable layouts without forcing every host to write sections by hand.
|
|
64
|
+
|
|
65
|
+
## Goals
|
|
66
|
+
|
|
67
|
+
- Let hosts render grouped read-only detail views from schema metadata without local `FormConfig.sections`.
|
|
68
|
+
- Let hosts render grouped create/edit command forms from schema metadata without local `FormConfig.sections`.
|
|
69
|
+
- Preserve authored `FormConfig` as the default behavior to avoid breaking existing consumers.
|
|
70
|
+
- Centralize the layout algorithm so Dynamic Form, CRUD and surface action launchers do not diverge.
|
|
71
|
+
- Keep the backend as the canonical owner of field semantics.
|
|
72
|
+
- Allow host config to continue owning non-layout concerns such as actions, messages, hooks and behavior.
|
|
73
|
+
- Provide a migration path for Ergon and other hosts to remove repeated local layout sections gradually.
|
|
74
|
+
|
|
75
|
+
## Non-goals
|
|
76
|
+
|
|
77
|
+
- Do not generate DTO documentation from UI labels or property names.
|
|
78
|
+
- Do not move domain semantics from backend DTOs into Angular configs.
|
|
79
|
+
- Do not change Dynamic Form defaults in this RFC.
|
|
80
|
+
- Do not overwrite or silently discard authored `FormConfig.sections`.
|
|
81
|
+
- Do not create an Ergon-specific preset.
|
|
82
|
+
- Do not introduce new backend `x-ui` metadata until existing metadata is proven insufficient.
|
|
83
|
+
|
|
84
|
+
## Proposed Design
|
|
85
|
+
|
|
86
|
+
Introduce an opt-in schema-driven layout policy for Dynamic Form.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
export type DynamicFormLayoutSource = 'authored' | 'schema';
|
|
90
|
+
|
|
91
|
+
export type DynamicFormSchemaLayoutPreset =
|
|
92
|
+
| 'default'
|
|
93
|
+
| 'compactPresentation'
|
|
94
|
+
| 'groupedCommand';
|
|
95
|
+
|
|
96
|
+
export type DynamicFormLayoutIntent = 'detail' | 'command';
|
|
97
|
+
|
|
98
|
+
export type DynamicFormLayoutLifecycle = 'initial' | 'live';
|
|
99
|
+
|
|
100
|
+
export type DynamicFormLayoutPersistence = 'transient' | 'authorable';
|
|
101
|
+
|
|
102
|
+
export type DynamicFormLayoutDetachBehavior = 'none' | 'explicit';
|
|
103
|
+
|
|
104
|
+
export interface DynamicFormDetailSummaryPolicy {
|
|
105
|
+
includeFields?: readonly string[];
|
|
106
|
+
excludeFields?: readonly string[];
|
|
107
|
+
includeGroups?: readonly string[];
|
|
108
|
+
excludeGroups?: readonly string[];
|
|
109
|
+
includeRoles?: readonly string[];
|
|
110
|
+
excludeRoles?: readonly string[];
|
|
111
|
+
maxFields?: number;
|
|
112
|
+
fieldPriority?: Record<string, number>;
|
|
113
|
+
groupPriority?: Record<string, number>;
|
|
114
|
+
columns?: number;
|
|
115
|
+
responsiveColumns?: Partial<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>>;
|
|
116
|
+
widthPrecedence?: 'schema' | 'summary';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface DynamicFormLayoutPolicy {
|
|
120
|
+
source: DynamicFormLayoutSource;
|
|
121
|
+
preset?: DynamicFormSchemaLayoutPreset;
|
|
122
|
+
intent?: DynamicFormLayoutIntent;
|
|
123
|
+
lifecycle?: DynamicFormLayoutLifecycle;
|
|
124
|
+
persistence?: DynamicFormLayoutPersistence;
|
|
125
|
+
detachBehavior?: DynamicFormLayoutDetachBehavior;
|
|
126
|
+
schemaOperation?: 'detail' | 'create' | 'update' | 'view';
|
|
127
|
+
schemaType?: 'request' | 'response';
|
|
128
|
+
detailSummary?: DynamicFormDetailSummaryPolicy;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The default policy is equivalent to today's behavior:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
{
|
|
136
|
+
source: 'authored',
|
|
137
|
+
lifecycle: 'initial',
|
|
138
|
+
persistence: 'authorable'
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
When `source` is `schema`, the form materializes its layout from current schema metadata. In that mode, `FormConfig.sections` are not the source of truth for layout. The host may still pass the parts of `FormConfig` that are not layout-owned, such as actions, messages, behavior, hooks and submit behavior.
|
|
143
|
+
|
|
144
|
+
The policy should be explicit. A host that wants a read-only generated detail should request `intent: 'detail'`, `preset: 'compactPresentation'`, `source: 'schema'`, `lifecycle: 'live'` and `persistence: 'transient'`. A host that wants a create/edit form should request `intent: 'command'`, `preset: 'groupedCommand'`, the correct request schema operation and transient schema materialization unless the user explicitly detaches the generated layout.
|
|
145
|
+
|
|
146
|
+
## Presets
|
|
147
|
+
|
|
148
|
+
### `compactPresentation` with `intent: 'detail'`
|
|
149
|
+
|
|
150
|
+
Use for read-only detail surfaces.
|
|
151
|
+
|
|
152
|
+
Expected behavior:
|
|
153
|
+
|
|
154
|
+
- Group fields by schema `group`.
|
|
155
|
+
- Sort groups and fields by schema `order`.
|
|
156
|
+
- Respect `formHidden`, visibility rules and read-only presentation metadata.
|
|
157
|
+
- Use a consistent label/value hierarchy with distinct label, value, null and helper states.
|
|
158
|
+
- Use chips only for short statuses, categories or boolean/status values.
|
|
159
|
+
- Keep long values readable, wrapping safely without horizontal scroll.
|
|
160
|
+
- Avoid editable controls.
|
|
161
|
+
- Avoid card grids and decorative section containers as the default for operational detail screens.
|
|
162
|
+
- Preserve stable section ids derived from deterministic group keys.
|
|
163
|
+
- In `mode="view"`, activate presentation rendering when the host does not explicitly provide `presentationModeGlobal`; an explicit `false` keeps the same schema in traditional read-only controls.
|
|
164
|
+
- Honor explicit schema `x-ui.width` as 12-column spans by default so migrated operational detail screens can use dense fieldset rows. Preserve full-width rows when width is absent.
|
|
165
|
+
- Let `layoutPolicy.detailSummary.widthPrecedence: 'summary'` make `detailSummary.columns`/`responsiveColumns` override explicit `x-ui.width` only for the compact read-only summary surface.
|
|
166
|
+
- Treat `widthPrecedence: 'summary'` as a curated-summary density tool: long narrative, legal, multiline or audit-heavy values should stay schema-width owned or be moved out of the compact summary through include/exclude policies.
|
|
167
|
+
- Derive compact section header icons from semantic group roles (`identity`, `rules`, `markers`) while keeping field-level icons owned by existing schema metadata.
|
|
168
|
+
- Allow `layoutPolicy.detailSummary` to select/exclude fields and groups, cap the first compact panel with `maxFields`, and sort with field/group priority when the schema publishes summary/detail roles or priorities.
|
|
169
|
+
- Keep excluded summary fields out of generated rows and mark them hidden in generated field metadata for that transient compact surface, without mutating backend schema semantics.
|
|
170
|
+
|
|
171
|
+
This preset is the platform replacement for local read-only detail sections in migrated screens.
|
|
172
|
+
|
|
173
|
+
This RFC keeps the existing public `compactPresentation` vocabulary. It does not introduce `compactGroupedDetail` as a second public alias during beta.
|
|
174
|
+
|
|
175
|
+
Example policy for a master-detail read-only summary:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
const detailLayoutPolicy: DynamicFormLayoutPolicy = {
|
|
179
|
+
source: 'schema',
|
|
180
|
+
intent: 'detail',
|
|
181
|
+
preset: 'compactPresentation',
|
|
182
|
+
lifecycle: 'live',
|
|
183
|
+
persistence: 'transient',
|
|
184
|
+
schemaType: 'response',
|
|
185
|
+
detailSummary: {
|
|
186
|
+
includeGroups: [
|
|
187
|
+
'Identificacao',
|
|
188
|
+
'Marcadores',
|
|
189
|
+
'Aplicabilidade/preenchimento',
|
|
190
|
+
],
|
|
191
|
+
excludeGroups: ['Escopo', 'Quantidades', 'Empresa'],
|
|
192
|
+
maxFields: 8,
|
|
193
|
+
fieldPriority: {
|
|
194
|
+
codigo: 0,
|
|
195
|
+
mnemonico: 1,
|
|
196
|
+
ativo: 2,
|
|
197
|
+
},
|
|
198
|
+
columns: 3,
|
|
199
|
+
responsiveColumns: { xs: 1, sm: 1, md: 2, lg: 3, xl: 3 },
|
|
200
|
+
widthPrecedence: 'summary',
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `groupedCommand`
|
|
206
|
+
|
|
207
|
+
Use for create/edit command forms.
|
|
208
|
+
|
|
209
|
+
Expected behavior:
|
|
210
|
+
|
|
211
|
+
- Group fields by schema `group`.
|
|
212
|
+
- Sort groups and fields by schema `order`.
|
|
213
|
+
- Respect validators, required state, disabled/read-only state, help text and option metadata.
|
|
214
|
+
- Use `width` metadata plus field archetype rules to create predictable grid spans.
|
|
215
|
+
- Use full-width rows for long text, descriptions, multiline controls and high-density option controls when needed.
|
|
216
|
+
- Use compact clusters for booleans, short enums and small numeric fields.
|
|
217
|
+
- Expand an otherwise orphan medium/wide field to the full row by default, while preserving compact `xs`/`sm` fields. Use `groupedCommand.orphanFieldExpansion = "preserve"` when the empty space is intentional, or `"all"` when compact orphan fields must also fill the row.
|
|
218
|
+
- Keep validation feedback near the field that caused it.
|
|
219
|
+
- Prefer editable controls over presentation roles.
|
|
220
|
+
- Keep command actions visually stable and accessible.
|
|
221
|
+
- Preserve stable section ids derived from deterministic group keys.
|
|
222
|
+
|
|
223
|
+
This preset is the platform replacement for local create/edit `FormConfig.sections` when the backend command DTO already publishes sufficient `@UISchema` metadata.
|
|
224
|
+
|
|
225
|
+
### `default`
|
|
226
|
+
|
|
227
|
+
Preserve current generated behavior for consumers that only need a basic generated layout.
|
|
228
|
+
|
|
229
|
+
## Materialization Algorithm
|
|
230
|
+
|
|
231
|
+
The canonical algorithm should be implemented once and reused.
|
|
232
|
+
|
|
233
|
+
Proposed flow:
|
|
234
|
+
|
|
235
|
+
1. Normalize schema metadata through the existing schema normalizer.
|
|
236
|
+
2. Map schema fields to `FieldMetadata`.
|
|
237
|
+
3. Filter out fields hidden for the active form surface.
|
|
238
|
+
4. Group fields by `group`, using a stable fallback group when absent.
|
|
239
|
+
5. Sort groups by the minimum field order inside the group.
|
|
240
|
+
6. Sort fields by `order`, then by stable field key.
|
|
241
|
+
7. Convert `width` metadata to responsive spans.
|
|
242
|
+
8. Create stable section ids from normalized group keys.
|
|
243
|
+
9. Emit generated `FormConfig.sections` with provenance metadata indicating schema materialization.
|
|
244
|
+
10. Merge non-layout host config without letting local field semantics override schema-owned field semantics.
|
|
245
|
+
|
|
246
|
+
For command forms, the materializer must use the request schema for the active operation. For detail/view surfaces, it must use the response schema for the active detail or view surface. The source operation is part of the policy, not an incidental caller detail.
|
|
247
|
+
|
|
248
|
+
Stable section ids must be deterministic. The implementation must normalize group keys consistently, remove locale-dependent accents for id generation, lower-case, replace non-alphanumeric runs with `-`, and append a deterministic suffix when collisions occur. If only a human label is available, the generated id is stable only relative to that label and must be treated as generated, not as a durable backend identity.
|
|
249
|
+
|
|
250
|
+
The width mapping should be centralized. A starting policy:
|
|
251
|
+
|
|
252
|
+
- `xs` and compact controls: 3 or 4 desktop columns, 12 on narrow screens.
|
|
253
|
+
- `sm`: 4 desktop columns, 12 on narrow screens.
|
|
254
|
+
- `md`: 6 desktop columns, 12 on narrow screens.
|
|
255
|
+
- `lg`, `xl`, multiline and full-width controls: 12 columns unless the preset defines a narrower command layout.
|
|
256
|
+
|
|
257
|
+
The exact mapping can be tuned in implementation, but it must live in the shared materializer and not in host screens.
|
|
258
|
+
|
|
259
|
+
## Canonical Ownership
|
|
260
|
+
|
|
261
|
+
`@praxisui/core` owns the pure materialization helper and the minimal structural types required by both Dynamic Form and core surface materializers.
|
|
262
|
+
|
|
263
|
+
Candidate owner:
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
materializeFormLayoutFromMetadata(fields, policy)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
`@praxisui/dynamic-form` owns the component input, runtime behavior, editor integration, generated `FormConfig` rendering and documentation of how `generatedLayoutPreset` relates to schema materialization.
|
|
270
|
+
|
|
271
|
+
`@praxisui/crud` consumes the public Dynamic Form policy rather than building its own form layout logic.
|
|
272
|
+
|
|
273
|
+
Core surface action materializers must stop injecting local `config.sections` for generated layouts once the policy is available. They should pass the schema layout policy plus existing `initialValue`, `mode`, `resourceId`, action and submit inputs.
|
|
274
|
+
|
|
275
|
+
`praxis-metadata-starter` should not change in the first implementation phase unless a real metadata gap is found after using existing `x-ui` fields.
|
|
276
|
+
|
|
277
|
+
## Runtime Rules
|
|
278
|
+
|
|
279
|
+
- Authored config keeps precedence by default.
|
|
280
|
+
- Schema-driven runtime layout must be opt-in.
|
|
281
|
+
- Generated schema sections must not be persisted as authored user config by default.
|
|
282
|
+
- Schema-driven `lifecycle: 'live'` layout must use a transient composition path, not the current initial-generation path that immediately persists generated config.
|
|
283
|
+
- If customization is enabled, the user must explicitly detach the generated layout before it becomes authored config.
|
|
284
|
+
- Local config may provide actions, messages, hooks and behavior while schema remains the source of field semantics.
|
|
285
|
+
- Section ids generated from group names must be stable to support rules, tests and authoring references.
|
|
286
|
+
- If a host passes both authored sections and `source: 'schema'`, schema layout wins only when the policy explicitly requests schema materialization. The component should surface a developer warning in non-production builds.
|
|
287
|
+
- The existing reconciler remains responsible for updating schema-owned field metadata in authored configs. Schema-driven live layout is a separate composition step and must not be implemented as a small extension of the existing reconciler because that reconciler intentionally preserves sections.
|
|
288
|
+
|
|
289
|
+
### Precedence Matrix
|
|
290
|
+
|
|
291
|
+
| Policy | Persisted config | Input config sections | Result |
|
|
292
|
+
| --- | --- | --- | --- |
|
|
293
|
+
| `source: 'authored'` | present | any | Use persisted or input-first config according to existing persistence strategy. |
|
|
294
|
+
| `source: 'authored'` | absent | present | Use input config and existing reconciliation behavior. |
|
|
295
|
+
| `source: 'schema', persistence: 'transient'` | present | any | Materialize layout from schema; do not persist generated sections; merge only host-owned non-layout config. |
|
|
296
|
+
| `source: 'schema', persistence: 'transient'` | absent | present | Ignore input `sections`; merge host-owned non-layout config; warn in dev when sections were supplied. |
|
|
297
|
+
| `source: 'schema', persistence: 'authorable'` | any | any | Allowed only after explicit detach; generated sections become authored config from that point forward. |
|
|
298
|
+
|
|
299
|
+
### Ownership Of Config Fragments
|
|
300
|
+
|
|
301
|
+
- Layout-owned by schema policy: `sections`, rows, columns, items, generated spans and generated section order.
|
|
302
|
+
- Schema-owned by backend metadata: field labels, field type, required state, read-only state, option metadata, validators, visibility metadata, value presentation and domain semantics.
|
|
303
|
+
- Host-owned by local config: actions, messages, hooks, submit behavior, toolbar/header action composition and screen-specific behavior.
|
|
304
|
+
- Mixed or gated by explicit design review: visual blocks, form blocks, custom content projections and any layout item that is not a direct schema field.
|
|
305
|
+
|
|
306
|
+
## Migration Plan
|
|
307
|
+
|
|
308
|
+
### Phase 1 - RFC and platform alignment
|
|
309
|
+
|
|
310
|
+
- Publish this RFC.
|
|
311
|
+
- Confirm the contract with platform maintainers.
|
|
312
|
+
- Do not change runtime behavior yet.
|
|
313
|
+
|
|
314
|
+
### Phase 2 - Shared materializer
|
|
315
|
+
|
|
316
|
+
- Add a pure layout materializer in `@praxisui/core`.
|
|
317
|
+
- Move or align duplicated layout logic used by Dynamic Form and surface materializers.
|
|
318
|
+
- Add focused unit tests for grouping, ordering, width mapping, hidden fields and stable ids.
|
|
319
|
+
|
|
320
|
+
### Phase 3 - Dynamic Form public opt-in
|
|
321
|
+
|
|
322
|
+
- Add the layout policy input.
|
|
323
|
+
- Keep `generatedLayoutPreset` working for existing consumers.
|
|
324
|
+
- Document the relationship between legacy initial generation and runtime schema materialization.
|
|
325
|
+
- Keep `compactPresentation` as the detail presentation preset and avoid introducing `compactGroupedDetail` as a public alias.
|
|
326
|
+
- Add tests proving authored config remains default.
|
|
327
|
+
|
|
328
|
+
### Phase 4 - CRUD and surface actions
|
|
329
|
+
|
|
330
|
+
- Allow CRUD dialog hosts and surface action launchers to pass the policy.
|
|
331
|
+
- Extend the CRUD dialog data contract so `data.action.form` or `data.inputs` can carry the policy to `<praxis-dynamic-form>`.
|
|
332
|
+
- Use `groupedCommand` for create/edit dialogs where schema metadata is sufficient.
|
|
333
|
+
- Use `compactPresentation` with detail intent for read-only detail actions where appropriate.
|
|
334
|
+
- Replace duplicated `SurfaceOpenMaterializerService` local section generation with the shared materializer or by passing the policy downstream.
|
|
335
|
+
|
|
336
|
+
### Phase 5 - Ergon migration cleanup
|
|
337
|
+
|
|
338
|
+
- Remove local repeated `FormConfig.sections` from migrated screens that can rely on schema metadata.
|
|
339
|
+
- Keep local config only for screen-specific actions, labels, hooks or behavior that are not field layout.
|
|
340
|
+
- Validate ERGadm00034 as the reference screen before applying the pattern broadly.
|
|
341
|
+
|
|
342
|
+
## Acceptance Criteria
|
|
343
|
+
|
|
344
|
+
- A read-only detail surface can render grouped fields from schema metadata without local sections.
|
|
345
|
+
- A create/edit command form can render grouped fields from schema metadata without local sections.
|
|
346
|
+
- Existing consumers using authored `FormConfig.sections` keep the same default behavior.
|
|
347
|
+
- Dynamic Form and surface action materialization share the same grouping and width algorithm.
|
|
348
|
+
- CRUD dialog forms can opt into `groupedCommand`.
|
|
349
|
+
- Generated section ids are stable.
|
|
350
|
+
- Runtime and presentation mode suppress generated or authored sections/rows/columns that do not contain any visible field or visible rich content block; customization mode still exposes empty containers for authoring.
|
|
351
|
+
- Documentation explains when to use authored config versus schema materialization.
|
|
352
|
+
- Ergon reference screens can remove repeated local layout sections without losing grouping quality.
|
|
353
|
+
- Detail layout has consistent label/value hierarchy, readable null and long-value states, no horizontal scroll on narrow viewports and no editable controls.
|
|
354
|
+
- Command layout handles required, invalid, dirty, disabled, read-only and saving states without shifting or hiding actions.
|
|
355
|
+
- Actions distinguish primary, secondary and destructive intent visually and accessibly.
|
|
356
|
+
- Keyboard focus, tab order, accessible names and contrast meet platform accessibility expectations.
|
|
357
|
+
|
|
358
|
+
## Validation Plan
|
|
359
|
+
|
|
360
|
+
Implementation should use focused validation:
|
|
361
|
+
|
|
362
|
+
- Unit tests for the shared materializer.
|
|
363
|
+
- Dynamic Form tests for config precedence, runtime schema policy and preset selection.
|
|
364
|
+
- Dynamic Form tests proving transient schema sections are not persisted unless explicitly detached.
|
|
365
|
+
- CRUD tests for forwarding the policy to Dynamic Form.
|
|
366
|
+
- Surface materializer tests proving generated local `config.sections` are no longer duplicated.
|
|
367
|
+
- Public API review for exported types and barrels.
|
|
368
|
+
- Focused builds for `@praxisui/core`, `@praxisui/dynamic-form` and a direct consumer.
|
|
369
|
+
- AI authoring manifest and capabilities updates with focused specs where applicable.
|
|
370
|
+
- JSON API docs, README, docs manifest and public docs registry review where applicable.
|
|
371
|
+
- Documentation manifest validation where applicable.
|
|
372
|
+
- Visual validation on desktop and narrow viewport for at least one read-only detail and one command form before promoting the pattern as a migration template.
|
|
373
|
+
- ERGadm00034 visual validation with realistic PT-BR data, empty values, long text, small and large groups, invalid required fields, option source loading/empty states, disabled/read-only states, submit/saving state and dialog/drawer narrow viewport.
|
|
374
|
+
|
|
375
|
+
Broad workspace builds are not required for the RFC-only step.
|
|
376
|
+
|
|
377
|
+
## Implementation Notes
|
|
378
|
+
|
|
379
|
+
- The public input is `layoutPolicy`.
|
|
380
|
+
- `layoutPolicy.source = "schema"` is opt-in. CRUD dialogs do not enable it implicitly.
|
|
381
|
+
- Generated schema sections are transient and are not persisted by the runtime.
|
|
382
|
+
- Host non-layout config has precedence over persisted non-layout config when both exist.
|
|
383
|
+
- Persisted and host-authored `sections` are ignored in schema layout mode.
|
|
384
|
+
- `schemaType` and `schemaOperation` are validated against `schemaUrl` when the URL declares `schemaType` and `operation`.
|
|
385
|
+
- Stable section ids are based on group tokens, not group index.
|
|
386
|
+
|
|
387
|
+
## Open Questions
|
|
388
|
+
|
|
389
|
+
- Should operation-level schema metadata eventually declare preferred layout preset for `create`, `update`, `detail` and `view` surfaces after the frontend policy proves stable?
|
|
390
|
+
- Should group icons remain host-authored, come from a platform icon policy, or eventually become backend metadata after a real gap is proven?
|
|
391
|
+
- Should visual blocks participate in schema materialization, or remain explicitly authored only?
|
|
392
|
+
|
|
393
|
+
## Risks
|
|
394
|
+
|
|
395
|
+
- Changing defaults would break existing authored layouts. The implementation must avoid this.
|
|
396
|
+
- Duplicating layout algorithms would recreate the current problem in another layer.
|
|
397
|
+
- Treating local host config as field semantics would weaken the backend DTO contract.
|
|
398
|
+
- Adding new metadata too early would expand the public contract before proving existing `x-ui` fields are insufficient.
|
|
399
|
+
- Persisting transient generated layouts by accident would turn schema materialization into silent authored config.
|
|
400
|
+
- Using the wrong operation schema could leak detail-only fields into create/edit forms.
|
|
401
|
+
- Promoting ERGadm00034 as a template before visual validation could institutionalize poor layouts across hundreds of screens.
|
|
402
|
+
|
|
403
|
+
## Relationship To Ergon Migration
|
|
404
|
+
|
|
405
|
+
The immediate trigger was ERGadm00034, but the problem already appears across read-only and editable forms in the Ergon migration.
|
|
406
|
+
|
|
407
|
+
Ergon may continue using local configs as a temporary bridge, but the intended platform direction is to remove repeated `FormConfig.sections` when the backend DTO already publishes complete field metadata.
|
|
408
|
+
|
|
409
|
+
## ErgonX Migration Playbook
|
|
410
|
+
|
|
411
|
+
Use this section as the operational checklist before promoting a migrated Ergon screen as a reusable example.
|
|
412
|
+
|
|
413
|
+
### 1. Prove the DTO/schema is ready
|
|
414
|
+
|
|
415
|
+
The backend DTO and `/schemas/filtered` response are the source of truth for field semantics. Before a screen uses schema-driven layout, confirm that every visible field has:
|
|
416
|
+
|
|
417
|
+
- a business label in the correct language;
|
|
418
|
+
- a stable `group` and `order` that match the real business grouping, not only the legacy visual row;
|
|
419
|
+
- an appropriate `controlType`, read-only/required state, validators and option metadata;
|
|
420
|
+
- domain-oriented `helpText` only when the user needs decision support;
|
|
421
|
+
- `width` metadata when the field should share a dense row with related fields;
|
|
422
|
+
- resolved display/value presentation for coded values when the user should not see only raw codes.
|
|
423
|
+
|
|
424
|
+
Do not compensate for weak DTO metadata with local Angular labels, local help copy, hardcoded option labels, or local concatenation of code and description. If the schema is weak, return to DTO/schema hardening and add schema/OpenAPI tests there.
|
|
425
|
+
|
|
426
|
+
### 2. Choose the layout policy by surface
|
|
427
|
+
|
|
428
|
+
Use `layoutPolicy` only when schema metadata is complete enough to generate the layout.
|
|
429
|
+
|
|
430
|
+
| Surface | Recommended policy | Schema source | Notes |
|
|
431
|
+
| --- | --- | --- | --- |
|
|
432
|
+
| Read-only detail panel | `source: "schema"`, `intent: "detail"`, `preset: "compactPresentation"`, `persistence: "transient"`, optional `detailSummary` | response schema | Use for legacy detail blocks such as identification, rules and markers. |
|
|
433
|
+
| Create/edit drawer or dialog | `source: "schema"`, `intent: "command"`, `preset: "groupedCommand"`, `persistence: "transient"` | request schema | Use only after command DTO metadata and write API gates are ready. |
|
|
434
|
+
| Custom visual composition | `source: "authored"` | authored config | Use for genuinely custom content, embedded child resources or non-field visual blocks. |
|
|
435
|
+
| Transitional migration | authored sections plus schema-owned field metadata | response/request schema | Acceptable while DTO grouping is being corrected; document the temporary debt. |
|
|
436
|
+
|
|
437
|
+
For command forms, `schemaUrl` must identify the request operation. A create/edit form rendered from a response schema is a contract defect because it can expose read-only, derived or detail-only fields as editable.
|
|
438
|
+
|
|
439
|
+
### 3. Apply the corporate help policy
|
|
440
|
+
|
|
441
|
+
Large enterprise forms should not render every DTO description inline. Inline help is useful for short guidance, but dense groups become noisy when every toggle, select and date field owns multiple lines of explanatory text.
|
|
442
|
+
|
|
443
|
+
Recommended default for Ergon-style command drawers:
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
helpPresentation: {
|
|
447
|
+
display: 'auto',
|
|
448
|
+
inlineMaxLength: 48,
|
|
449
|
+
preferPopoverForControls: ['select', 'checkbox', 'toggle', 'date', 'datepicker', 'numeric'],
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
Use field-level `helpDisplay` only when the DTO has a specific need:
|
|
454
|
+
|
|
455
|
+
- `inline`: short mandatory operational clarification that should always be visible;
|
|
456
|
+
- `popover`: longer guidance, policy explanation or rare decision support;
|
|
457
|
+
- `hidden`: text not useful in the current UI surface;
|
|
458
|
+
- `auto`: allow the runtime threshold to decide.
|
|
459
|
+
|
|
460
|
+
Validation errors are not help text. They remain near the field and must not be moved into the help affordance.
|
|
461
|
+
|
|
462
|
+
### 4. Keep field icons intentional
|
|
463
|
+
|
|
464
|
+
For dense command forms, prefer `fieldIconPolicy: "presentation-only"` unless icons are required for recognition. This keeps schema icon metadata useful in read-only presentation while avoiding visual clutter inside every input.
|
|
465
|
+
|
|
466
|
+
Use `fieldIconPolicy: "all"` only when icons are part of the field affordance or when a migrated screen has explicit visual requirements. Use `none` only for surfaces where icons would compete with compact operational scanning.
|
|
467
|
+
|
|
468
|
+
### 5. Preserve Praxis actions and loading patterns
|
|
469
|
+
|
|
470
|
+
Migrated screens should use native Praxis action discovery, surfaces and capabilities for row, collection and global actions. Do not implement an Ergon-local action launcher when the backend publishes actions or surfaces that Praxis can discover.
|
|
471
|
+
|
|
472
|
+
For loading states, avoid whole-page flicker. Prefer stable shells, table/detail skeletons or top progress indicators that preserve layout while data refreshes. A migration example should prove that refresh, filter, pagination and row selection do not blank the whole screen.
|
|
473
|
+
|
|
474
|
+
### 6. Visual QA gate for a reference screen
|
|
475
|
+
|
|
476
|
+
Before using a screen as a migration template, run at least one desktop browser validation with realistic PT-BR data and capture:
|
|
477
|
+
|
|
478
|
+
- initial loading, loaded, empty and error states;
|
|
479
|
+
- filter/search interaction and pagination;
|
|
480
|
+
- row selection and detail update without page flicker;
|
|
481
|
+
- create/edit drawer with short and long help text;
|
|
482
|
+
- required, invalid, dirty, disabled, read-only and saving states;
|
|
483
|
+
- keyboard tab order, focus visibility, accessible names and contrast;
|
|
484
|
+
- long labels/values without overlap or horizontal scroll in the target desktop viewport.
|
|
485
|
+
|
|
486
|
+
Mobile can be deferred when the product decision says it is not priority, but narrow drawer behavior still needs enough validation to avoid broken desktop split-screen usage.
|
|
487
|
+
|
|
488
|
+
### 7. Handoff artifact for each Ergon screen
|
|
489
|
+
|
|
490
|
+
Each migrated screen should record the following in its Ergon migration folder:
|
|
491
|
+
|
|
492
|
+
- DTO/schema readiness result and unresolved semantic gaps;
|
|
493
|
+
- chosen `layoutPolicy`, `helpPresentation` and `fieldIconPolicy`;
|
|
494
|
+
- actions consumed from native Praxis discovery and any missing backend capability;
|
|
495
|
+
- visual QA evidence and known accepted deviations;
|
|
496
|
+
- temporary authored config sections that should be removed after DTO/schema hardening.
|
|
497
|
+
|
|
498
|
+
This keeps ERGadm00034 useful as a repeatable migration reference instead of a one-off visual implementation.
|