@praxisui/dynamic-form 9.0.0-beta.41 → 9.0.0-beta.42
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 +7 -0
- package/ai/component-registry.json +31 -9
- package/docs/schema-driven-layout-materialization-rfc.md +7 -1
- package/fesm2022/praxisui-dynamic-form.mjs +35 -2
- package/package.json +8 -8
- package/src/lib/praxis-dynamic-form.json-api.md +1 -1
- package/types/praxisui-dynamic-form.d.ts +1 -0
|
@@ -113,6 +113,7 @@ export interface DynamicFormDetailSummaryPolicy {
|
|
|
113
113
|
groupPriority?: Record<string, number>;
|
|
114
114
|
columns?: number;
|
|
115
115
|
responsiveColumns?: Partial<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>>;
|
|
116
|
+
widthPrecedence?: 'schema' | 'summary';
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
export interface DynamicFormLayoutPolicy {
|
|
@@ -160,7 +161,9 @@ Expected behavior:
|
|
|
160
161
|
- Avoid card grids and decorative section containers as the default for operational detail screens.
|
|
161
162
|
- Preserve stable section ids derived from deterministic group keys.
|
|
162
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.
|
|
163
|
-
- Honor explicit schema `x-ui.width` as 12-column spans so migrated operational detail screens can use dense fieldset rows. Preserve full-width rows when width is absent.
|
|
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.
|
|
164
167
|
- Derive compact section header icons from semantic group roles (`identity`, `rules`, `markers`) while keeping field-level icons owned by existing schema metadata.
|
|
165
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.
|
|
166
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.
|
|
@@ -192,6 +195,9 @@ const detailLayoutPolicy: DynamicFormLayoutPolicy = {
|
|
|
192
195
|
mnemonico: 1,
|
|
193
196
|
ativo: 2,
|
|
194
197
|
},
|
|
198
|
+
columns: 3,
|
|
199
|
+
responsiveColumns: { xs: 1, sm: 1, md: 2, lg: 3, xl: 3 },
|
|
200
|
+
widthPrecedence: 'summary',
|
|
195
201
|
},
|
|
196
202
|
};
|
|
197
203
|
```
|
|
@@ -5952,7 +5952,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
5952
5952
|
{ name: 'readUrl', type: 'string', description: 'Endpoint canonico de leitura para surfaces VIEW/READ_PROJECTION' },
|
|
5953
5953
|
{ name: 'mode', type: 'string', allowedValues: ['create', 'edit', 'view'], description: 'Modo de operação' },
|
|
5954
5954
|
{ name: 'generatedLayoutPreset', type: 'string', allowedValues: ['default', 'compactPresentation'], description: 'Preset usado apenas ao gerar a configuracao inicial a partir de metadata/schema; nao reprocessa layouts persistidos ou autorados.' },
|
|
5955
|
-
{ name: 'layoutPolicy', type: 'DynamicFormLayoutPolicy', description: 'Politica opt-in para layout schema-driven transient. Use source=schema apenas quando o backend schema for a fonte canonica do agrupamento; use detailSummary para seleção de campos e densidade responsiva do resumo read-only compacto sem FormConfig.sections locais.' },
|
|
5955
|
+
{ name: 'layoutPolicy', type: 'DynamicFormLayoutPolicy', description: 'Politica opt-in para layout schema-driven transient. Use source=schema apenas quando o backend schema for a fonte canonica do agrupamento; use detailSummary para seleção de campos e densidade responsiva do resumo read-only compacto sem FormConfig.sections locais. Quando o resumo precisar vencer x-ui.width publicado para outras surfaces, use detailSummary.widthPrecedence=summary.' },
|
|
5956
5956
|
{ name: 'fieldIconPolicy', type: 'string', allowedValues: ['all', 'presentation-only', 'none'], description: 'Politica visual do host para icones prefix/suffix de campos vindos da metadata. Use presentation-only para manter icones decorativos em apresentacao e ocultar em controles tradicionais.' },
|
|
5957
5957
|
{ name: 'enableCustomization', type: 'boolean', description: 'Habilita edição visual' }
|
|
5958
5958
|
],
|
|
@@ -12207,11 +12207,19 @@ class PraxisDynamicForm {
|
|
|
12207
12207
|
}
|
|
12208
12208
|
return;
|
|
12209
12209
|
}
|
|
12210
|
+
const configuredReadUrl = String(this.readUrl || '').trim();
|
|
12211
|
+
if (!configuredReadUrl && !String(this.resourcePath || '').trim()) {
|
|
12212
|
+
if (this.hydrateEntityFromInitialValue()) {
|
|
12213
|
+
return;
|
|
12214
|
+
}
|
|
12215
|
+
this.entityHydrationPending = false;
|
|
12216
|
+
this.warnLog('Skipping entity load because no readUrl or resourcePath is configured.', { id: this.pendingEntityId, formId: this.formId }, { actionId: 'entity.load.skip', throttleKey: 'praxis-dynamic-form:entity-load-without-resource' });
|
|
12217
|
+
return;
|
|
12218
|
+
}
|
|
12210
12219
|
this.loadedEntityId = this.pendingEntityId;
|
|
12211
12220
|
this.entityHydrationPending = true;
|
|
12212
12221
|
const httpContext = new HttpContext().set(PRAXIS_LOADING_CTX, this.buildLoadingContext('data', 'Carregando dados...', false));
|
|
12213
12222
|
this.emitLoadingState('data', 'loading', 'Carregando dados do formulário...');
|
|
12214
|
-
const configuredReadUrl = String(this.readUrl || '').trim();
|
|
12215
12223
|
const request$ = configuredReadUrl
|
|
12216
12224
|
? this.http
|
|
12217
12225
|
.get(this.resolveReadHref(configuredReadUrl), {
|
|
@@ -12248,6 +12256,22 @@ class PraxisDynamicForm {
|
|
|
12248
12256
|
},
|
|
12249
12257
|
});
|
|
12250
12258
|
}
|
|
12259
|
+
hydrateEntityFromInitialValue() {
|
|
12260
|
+
const normalized = this.getNormalizedInitialValue();
|
|
12261
|
+
if (!normalized) {
|
|
12262
|
+
return false;
|
|
12263
|
+
}
|
|
12264
|
+
this.loadedEntityId = this.pendingEntityId;
|
|
12265
|
+
this.loadedEntityData = normalized;
|
|
12266
|
+
this.entityHydrationPending = false;
|
|
12267
|
+
if (Object.keys(this.form.controls || {}).length) {
|
|
12268
|
+
this.form.patchValue(normalized, { emitEvent: false });
|
|
12269
|
+
}
|
|
12270
|
+
this.hydratedEntityId = this.pendingEntityId;
|
|
12271
|
+
this.debugLog('[PDF] loadEntity:initialValue', { id: this.pendingEntityId });
|
|
12272
|
+
this.emitLoadingState('data', 'success', 'Dados carregados.');
|
|
12273
|
+
return true;
|
|
12274
|
+
}
|
|
12251
12275
|
buildFormFromConfig(options = { reason: 'initialization' }) {
|
|
12252
12276
|
this.runtimeFieldMetadata = null;
|
|
12253
12277
|
const fieldMetadata = this.getRuntimeFieldMetadata();
|
|
@@ -34611,6 +34635,7 @@ const ENUMS = {
|
|
|
34611
34635
|
layoutPolicyIntent: ['detail', 'command'],
|
|
34612
34636
|
layoutPolicyLifecycle: ['initial', 'live'],
|
|
34613
34637
|
layoutPolicyPersistence: ['transient', 'authorable'],
|
|
34638
|
+
layoutPolicyWidthPrecedence: ['schema', 'summary'],
|
|
34614
34639
|
fieldIconPolicy: ['all', 'presentation-only', 'none'],
|
|
34615
34640
|
notifyIfOutdated: ['inline', 'snackbar', 'both', 'none'],
|
|
34616
34641
|
labelPosition: ['above', 'left'],
|
|
@@ -34875,6 +34900,14 @@ const FORM_COMPONENT_AI_CAPABILITIES = {
|
|
|
34875
34900
|
description: 'Mapa de colunas por breakpoint xs/sm/md/lg/xl para detalhes read-only compactos em drawers, side sheets e desktop largo.',
|
|
34876
34901
|
safetyNotes: 'Prefira valores simples como { lg: 3, md: 2, sm: 1 }; nao copie layout manual para sections.',
|
|
34877
34902
|
},
|
|
34903
|
+
{
|
|
34904
|
+
path: 'inputs.layoutPolicy.detailSummary.widthPrecedence',
|
|
34905
|
+
category: 'inputs',
|
|
34906
|
+
valueKind: 'enum',
|
|
34907
|
+
allowedValues: ENUMS.layoutPolicyWidthPrecedence,
|
|
34908
|
+
description: 'Define se larguras explicitas do schema ou a densidade do resumo controlam os spans no compactPresentation read-only.',
|
|
34909
|
+
safetyNotes: 'Default schema preserva x-ui.width; use summary apenas quando columns/responsiveColumns devem vencer larguras genericas do schema nessa surface.',
|
|
34910
|
+
},
|
|
34878
34911
|
{
|
|
34879
34912
|
path: 'inputs.fieldIconPolicy',
|
|
34880
34913
|
category: 'inputs',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/dynamic-form",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.42",
|
|
4
4
|
"description": "Angular dynamic form engine for Praxis UI: metadata-driven forms, hooks, and services integrating @praxisui/* packages.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"@angular/forms": "^21.0.0",
|
|
10
10
|
"@angular/material": "^21.0.0",
|
|
11
11
|
"@angular/router": "^21.0.0",
|
|
12
|
-
"@praxisui/ai": "^9.0.0-beta.
|
|
13
|
-
"@praxisui/dynamic-fields": "^9.0.0-beta.
|
|
14
|
-
"@praxisui/metadata-editor": "^9.0.0-beta.
|
|
15
|
-
"@praxisui/rich-content": "^9.0.0-beta.
|
|
16
|
-
"@praxisui/settings-panel": "^9.0.0-beta.
|
|
17
|
-
"@praxisui/visual-builder": "^9.0.0-beta.
|
|
18
|
-
"@praxisui/core": "^9.0.0-beta.
|
|
12
|
+
"@praxisui/ai": "^9.0.0-beta.42",
|
|
13
|
+
"@praxisui/dynamic-fields": "^9.0.0-beta.42",
|
|
14
|
+
"@praxisui/metadata-editor": "^9.0.0-beta.42",
|
|
15
|
+
"@praxisui/rich-content": "^9.0.0-beta.42",
|
|
16
|
+
"@praxisui/settings-panel": "^9.0.0-beta.42",
|
|
17
|
+
"@praxisui/visual-builder": "^9.0.0-beta.42",
|
|
18
|
+
"@praxisui/core": "^9.0.0-beta.42",
|
|
19
19
|
"rxjs": "^7.8.0"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
@@ -578,7 +578,7 @@ No ecossistema Praxis, ele funciona tanto como runtime final quanto como superfi
|
|
|
578
578
|
| `componentInstanceId` | `string \| undefined` | `undefined` | Active | Isola instancias com mesmo `formId`. |
|
|
579
579
|
| `layout` | `FormLayout \| undefined` | `undefined` | Partial | Funciona como override estrutural em parte dos fluxos de layout/editor. |
|
|
580
580
|
| `generatedLayoutPreset` | `'default' \| 'compactPresentation'` | `'default'` | Active | Usado apenas ao criar a configuracao inicial a partir de schema/metadata; nao reprocessa layouts persistidos ou authorados. |
|
|
581
|
-
| `layoutPolicy` | `DynamicFormLayoutPolicy \| null` | `null` | Active | Politica opt-in para materializar layout a partir do schema atual. Use `source: 'schema'` com `persistence: 'transient'` para detalhe/read-only e command forms schema-driven sem persistir `sections` geradas nem reabrir configuracao local salva; politicas de host em `config`, como `helpPresentation`, continuam sendo aplicadas ao layout materializado. Em `mode='view'`, `intent: 'detail'` ou `preset: 'compactPresentation'` ativa apresentacao quando `presentationModeGlobal` nao foi informado; use `[presentationModeGlobal]=false` para controles read-only tradicionais. No preset `compactPresentation`, `x-ui.width` explicito empacota campos em linhas de 12 colunas e tem precedencia sobre `detailSummary.columns
|
|
581
|
+
| `layoutPolicy` | `DynamicFormLayoutPolicy \| null` | `null` | Active | Politica opt-in para materializar layout a partir do schema atual. Use `source: 'schema'` com `persistence: 'transient'` para detalhe/read-only e command forms schema-driven sem persistir `sections` geradas nem reabrir configuracao local salva; politicas de host em `config`, como `helpPresentation`, continuam sendo aplicadas ao layout materializado. Em `mode='view'`, `intent: 'detail'` ou `preset: 'compactPresentation'` ativa apresentacao quando `presentationModeGlobal` nao foi informado; use `[presentationModeGlobal]=false` para controles read-only tradicionais. No preset `compactPresentation`, `x-ui.width` explicito empacota campos em linhas de 12 colunas e tem precedencia sobre `detailSummary.columns` por default; campos sem width permanecem full-width, a menos que `detailSummary.columns`/`responsiveColumns` declare a densidade do resumo. Use `detailSummary.widthPrecedence='summary'` quando a densidade do resumo read-only deve sobrescrever `x-ui.width` apenas nessa surface compacta. Use `responsiveColumns`, por exemplo `{ lg: 3, md: 2, sm: 1 }`, para drawers, side sheets e painéis corporativos estreitos sem copiar `FormConfig.sections` locais. `schemaType` e `schemaOperation` sao validados contra `schemaUrl` quando a URL declara esses parametros. |
|
|
582
582
|
| `backConfig` | `BackConfig \| undefined` | `undefined` | Active | Integra retorno/navegacao no painel de configuracao; `confirmOnDirty` tem precedencia sobre `behavior.confirmOnUnsavedChanges` no cancel. |
|
|
583
583
|
| `hooks` | `FormHooksLayout \| undefined` | `undefined` | Active | Override direto de hooks sobre `config.hooks`. |
|
|
584
584
|
| `customEndpoints` | `EndpointConfig` | `{}` | Active | Override de endpoints no CRUD service interno. |
|
|
@@ -1017,6 +1017,7 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
|
|
|
1017
1017
|
private hostConfigHasAuthoredLocalFieldsNotInLocalConfig;
|
|
1018
1018
|
private syncWithServer;
|
|
1019
1019
|
private loadEntity;
|
|
1020
|
+
private hydrateEntityFromInitialValue;
|
|
1020
1021
|
private buildFormFromConfig;
|
|
1021
1022
|
private resetFormValueChangesSubscription;
|
|
1022
1023
|
private resetDependencyPolicySubscription;
|