@praxisui/dynamic-form 1.0.0-beta.66 → 1.0.0-beta.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -120,6 +120,69 @@ export class FormDemoComponent {
120
120
  ```
121
121
 
122
122
  Tip: connect to a backend resource by setting `resourcePath`/`resourceId`. The component can fetch schemas and reconcile local layout with server metadata when `editModeEnabled` is true.
123
+ When a late `config` hydration rebuilds the surface, the runtime preserves the current form values already mounted in memory only when the logical context remains the same (`resourcePath`, `resourceId`, and mode). If the form was preloaded from `resourceId`, that entity hydration remains visible after the rebuild only for the same entity context; entity switches and create-mode transitions do not restore the previous record snapshot.
124
+
125
+ ### Canonical DI contract for hosts
126
+
127
+ `praxis-dynamic-form` does not register `GenericCrudService` internally.
128
+ When the runtime uses `resourcePath`, `resourceId`, schema fetch, CRUD submit, or custom endpoints, the host must provide the service in the effective host scope.
129
+
130
+ Canonical rule:
131
+ - `praxis-table` is self-hosted for `GenericCrudService`.
132
+ - `praxis-dynamic-form` is host-driven for `GenericCrudService`.
133
+ - If the host needs a specific `endpointKey` or pre-configuration, it must provide and configure the same `GenericCrudService` instance before rendering the form.
134
+
135
+ Minimal host example:
136
+
137
+ ```ts
138
+ import { Component } from '@angular/core';
139
+ import { GenericCrudService } from '@praxisui/core';
140
+ import { PraxisDynamicForm } from '@praxisui/dynamic-form';
141
+
142
+ @Component({
143
+ selector: 'app-form-host',
144
+ standalone: true,
145
+ imports: [PraxisDynamicForm],
146
+ providers: [GenericCrudService],
147
+ template: `
148
+ <praxis-dynamic-form
149
+ [formId]="'employees-form'"
150
+ [resourcePath]="'employees'"
151
+ [mode]="'edit'"
152
+ ></praxis-dynamic-form>
153
+ `,
154
+ })
155
+ export class FormHostComponent {}
156
+ ```
157
+
158
+ If the host must force a non-default API endpoint, configure the service in the same host scope:
159
+
160
+ ```ts
161
+ import { Component } from '@angular/core';
162
+ import { ApiEndpoint, GenericCrudService } from '@praxisui/core';
163
+ import { PraxisDynamicForm } from '@praxisui/dynamic-form';
164
+
165
+ @Component({
166
+ selector: 'app-form-host',
167
+ standalone: true,
168
+ imports: [PraxisDynamicForm],
169
+ providers: [GenericCrudService],
170
+ template: `
171
+ <praxis-dynamic-form
172
+ [formId]="'employees-form'"
173
+ [resourcePath]="'human-resources/employees'"
174
+ [mode]="'edit'"
175
+ ></praxis-dynamic-form>
176
+ `,
177
+ })
178
+ export class FormHostComponent {
179
+ constructor(private readonly crud: GenericCrudService<any>) {
180
+ this.crud.configure('human-resources/employees', ApiEndpoint.HumanResources);
181
+ }
182
+ }
183
+ ```
184
+
185
+ Without that provider, a standalone host can fail with `NG0201: No provider found for _GenericCrudService`.
123
186
 
124
187
  ### 2) Config Editor component
125
188
 
@@ -305,6 +368,32 @@ See public exports: `projects/praxis-dynamic-form/src/public-api.ts`.
305
368
  - `projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.json-api.md`
306
369
  - `projects/praxis-dynamic-form/docs/hot-metadata-updates.md`
307
370
 
371
+ ## Header de seção com avatar dinâmico
372
+
373
+ - `FormSection.icon` continua suportado como identidade visual estática do header.
374
+ - `FormSection.sectionHeader` amplia o contrato para permitir avatar resolvido a partir do `formData`, sem perder compatibilidade com `icon`.
375
+ - Modos suportados:
376
+ - `icon`: usa o ícone estático da seção.
377
+ - `avatar-image`: tenta resolver uma imagem a partir de `sourceField`.
378
+ - `avatar-initials`: deriva iniciais a partir de `initialsSourceField` e, na ausência dele, usa `altField`.
379
+ - `auto`: tenta imagem, depois iniciais e por fim aplica o fallback configurado.
380
+ - Campos principais de `sectionHeader`:
381
+ - `sourceField`: field cujo valor atual representa foto/avatar.
382
+ - `initialsSourceField`: field textual usado para derivar iniciais.
383
+ - `altField`: field usado como texto acessível do avatar e fallback textual para iniciais.
384
+ - `fallbackIcon`: ícone usado quando a fonte dinâmica estiver vazia ou inválida.
385
+ - `emptyState`: `fallback-icon`, `placeholder-avatar` ou `none`, útil sobretudo em fluxos `create`; o padrão efetivo é `placeholder-avatar`, neutro para qualquer domínio.
386
+ - `initialsMaxLength`: máximo de letras no avatar textual, normalizado para `1..4`.
387
+ - Formatos de imagem aceitos pelo runtime:
388
+ - URL
389
+ - data URL base64
390
+ - `File`/`Blob`
391
+ - objetos com `url`, `src`, `dataUrl`, `base64` ou `bytes`
392
+ - Comportamento típico em cadastro:
393
+ - formulário vazio: mostra placeholder neutro por padrão, ou `fallbackIcon` se `emptyState` pedir isso
394
+ - nome preenchido, sem foto: `auto` pode mostrar iniciais
395
+ - foto preenchida: mostra a imagem
396
+
308
397
  ## IA — catálogo de capacidades (composição)
309
398
 
310
399
  O assistente usa um catálogo agregado de capabilities para gerar patches seguros:
@@ -322,7 +411,7 @@ Os paths micro são normalizados para `fieldMetadata[].<prop>` para garantir que
322
411
  - Semântica de limpeza: valores `null` em `properties/propertiesWhenFalse` removem o override e retornam ao valor base do layout; ausência mantém o valor base.
323
412
  - Whitelist por tipo (somente propriedades a seguir são aplicadas; demais são descartadas e logadas em dev):
324
413
  - `field`: `visible`, `required`, `readonly`, `disabled`, `className`, `style`, `label`, `description`, `placeholder`, `hint`, `tooltip`, `prefixIcon`, `suffixIcon`, `prefixText`, `suffixText`, `defaultValue`, `options` (array `{label,value,disabled?}`), `appearance` (`fill|outline`), `color` (`primary|accent|warn`), `floatLabel` (`auto|always|never`), `hintPosition` (`start|end`), `validators` (primitivos por chave).
325
- - `section`: `visible`, `title`, `description`, `icon`, `className`, `style`, `collapsible`, `collapsed`, `headerTooltip`, `headerAlign` (`start|center`), `appearance` (`card|plain|step`), `stepLabel`, gaps (`gapBottom`, `titleGapBottom`, `descriptionGapBottom`), cores/tipografia (`titleColor`, `descriptionColor`, `titleStyle`, `descriptionStyle`).
414
+ - `section`: `visible`, `title`, `description`, `icon`, `sectionHeader` (objeto rico) e tambem subpropriedades tipadas como `sectionHeader.mode`, `sectionHeader.sourceField`, `sectionHeader.initialsSourceField`, `sectionHeader.altField`, `sectionHeader.fallbackIcon`, `sectionHeader.emptyState`, `sectionHeader.initialsMaxLength`, `className`, `style`, `collapsible`, `collapsed`, `headerTooltip`, `headerAlign` (`start|center`), `appearance` (`card|plain|step`), `stepLabel`, gaps (`gapBottom`, `titleGapBottom`, `descriptionGapBottom`), cores/tipografia (`titleColor`, `descriptionColor`, `titleStyle`, `descriptionStyle`).
326
415
  - `action`: `visible`, `disabled`, `loading`, `label`, `icon`, `tooltip`, `color` (`primary|accent|warn|basic`), `variant` (`raised|stroked|flat|fab`), `size` (`small|medium|large`), `className`, `style`.
327
416
  - `row`: `visible`, `gap`, `rowGap`, `className`, `style`.
328
417
  - `column`: `visible`, `span`, `offset`, `order`, `hidden`, `align` (`start|center|end|stretch`), `padding`, `className`, `style`.