@praxisui/manual-form 1.0.0-beta.5 → 1.0.0-beta.52
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 +183 -13
- package/fesm2022/praxisui-manual-form.mjs +3664 -210
- package/fesm2022/praxisui-manual-form.mjs.map +1 -1
- package/index.d.ts +237 -12
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Manual Form"
|
|
3
|
+
slug: "manual-form-overview"
|
|
4
|
+
description: "Visao geral do @praxisui/manual-form com formularios declarativos, autodeteccao de campos, autosave, persistencia e hot update de metadata."
|
|
5
|
+
doc_type: "reference"
|
|
6
|
+
document_kind: "component-overview"
|
|
7
|
+
component: "manual-form"
|
|
8
|
+
category: "components"
|
|
9
|
+
audience:
|
|
10
|
+
- "frontend"
|
|
11
|
+
- "host"
|
|
12
|
+
- "architect"
|
|
13
|
+
level: "intermediate"
|
|
14
|
+
status: "active"
|
|
15
|
+
owner: "praxis-ui"
|
|
16
|
+
tags:
|
|
17
|
+
- "manual-form"
|
|
18
|
+
- "forms"
|
|
19
|
+
- "autosave"
|
|
20
|
+
- "metadata-editor"
|
|
21
|
+
- "dynamic-fields"
|
|
22
|
+
order: 38
|
|
23
|
+
icon: "file-pen"
|
|
24
|
+
toc: true
|
|
25
|
+
sidebar: true
|
|
26
|
+
search_boost: 0.95
|
|
27
|
+
reading_time: 14
|
|
28
|
+
estimated_setup_time: 20
|
|
29
|
+
version: "1.0"
|
|
30
|
+
related_docs:
|
|
31
|
+
- "manual-form-api-reference"
|
|
32
|
+
- "host-manual-form-integration"
|
|
33
|
+
- "manual-form-toolbar-execution"
|
|
34
|
+
- "consumer-integration-quickstart"
|
|
35
|
+
- "host-integration-guide"
|
|
36
|
+
keywords:
|
|
37
|
+
- "praxis manual form"
|
|
38
|
+
- "manual form toolkit"
|
|
39
|
+
- "form autosave"
|
|
40
|
+
- "field metadata bridge"
|
|
41
|
+
last_updated: "2026-03-07"
|
|
42
|
+
---
|
|
43
|
+
|
|
1
44
|
# Manual Form Toolkit
|
|
2
45
|
|
|
46
|
+
## 🔰 Exemplos / Quickstart
|
|
47
|
+
|
|
48
|
+
Para ver esta biblioteca em funcionamento em uma aplicação completa, utilize o projeto de exemplo (Quickstart):
|
|
49
|
+
|
|
50
|
+
- Repositório: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
51
|
+
- O Quickstart demonstra a integração das bibliotecas `@praxisui/*` em um app Angular, incluindo instalação, configuração e uso em telas reais.
|
|
52
|
+
|
|
3
53
|
## Instalação
|
|
4
54
|
|
|
5
55
|
```bash
|
|
@@ -35,6 +85,74 @@ O exemplo `/cargos/manual-form` demonstra uso declarativo:
|
|
|
35
85
|
</praxis-manual-form>
|
|
36
86
|
```
|
|
37
87
|
|
|
88
|
+
### Padrão didático para exemplos renderizados
|
|
89
|
+
|
|
90
|
+
Para páginas de documentação que precisam mostrar o componente antes de blocos longos de texto,
|
|
91
|
+
use o wrapper `praxis-manual-form-doc-example`. Ele já entrega:
|
|
92
|
+
|
|
93
|
+
- Banner curto com foco no exemplo live.
|
|
94
|
+
- Tabs para alternar entre `Live`, `Template`, `TS` e `Config`.
|
|
95
|
+
- Toggle de modo de customização (liga/desliga) com evento.
|
|
96
|
+
- Botão de cópia do snippet ativo.
|
|
97
|
+
- Callouts opcionais de `IMPORTANTE`, `NOTA` e `DICA`.
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<praxis-manual-form-doc-example
|
|
101
|
+
title="Cadastro de cargo"
|
|
102
|
+
subtitle="Preview primeiro, explicações depois."
|
|
103
|
+
level="Intermediario"
|
|
104
|
+
bannerTitle="Veja o componente em ação"
|
|
105
|
+
bannerDescription="Explore o live e abra código apenas quando necessário."
|
|
106
|
+
[templateCode]="templateSnippet"
|
|
107
|
+
[tsCode]="tsSnippet"
|
|
108
|
+
[configCode]="configSnippet"
|
|
109
|
+
[customizationEnabled]="editMode()"
|
|
110
|
+
(customizationEnabledChange)="editMode.set($event)"
|
|
111
|
+
important="Persista o draft no submit."
|
|
112
|
+
note="A aba Live abre por padrão."
|
|
113
|
+
tip="Use a aba Config para explicar contratos JSON."
|
|
114
|
+
>
|
|
115
|
+
<div exampleLive>
|
|
116
|
+
<praxis-manual-form
|
|
117
|
+
[formGroup]="form"
|
|
118
|
+
formId="cargo-manual-form"
|
|
119
|
+
[editModeEnabled]="editMode()"
|
|
120
|
+
>
|
|
121
|
+
<pdx-text-input formControlName="nome" label="Nome"></pdx-text-input>
|
|
122
|
+
</praxis-manual-form>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div exampleDiagram>
|
|
126
|
+
<!-- Mermaid, SVG ou fluxo simplificado -->
|
|
127
|
+
</div>
|
|
128
|
+
</praxis-manual-form-doc-example>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Também existe um showcase pronto para consumo direto:
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<praxis-manual-form-doc-example-showcase></praxis-manual-form-doc-example-showcase>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Esse showcase já inclui providers locais de `API_URL` e `ASYNC_CONFIG_STORAGE`, evitando erro de injeção em páginas de documentação.
|
|
138
|
+
|
|
139
|
+
### Diagrama de funcionamento (alto nível)
|
|
140
|
+
|
|
141
|
+
```mermaid
|
|
142
|
+
flowchart LR
|
|
143
|
+
Host[Template com <pdx-*>] --> ManualForm[praxis-manual-form]
|
|
144
|
+
ManualForm --> Detect[Detecta campos]
|
|
145
|
+
Detect --> Meta[Infere FieldMetadata]
|
|
146
|
+
Meta --> Group[Cria/Adota FormGroup]
|
|
147
|
+
Group --> Render[Renderiza campos + validações]
|
|
148
|
+
ManualForm --> Instance[ManualFormInstance]
|
|
149
|
+
Instance --> Storage[ConfigStorage]
|
|
150
|
+
ManualForm -->|editMode| Editor[Metadata Editor]
|
|
151
|
+
Editor --> Patch[Aplica patch]
|
|
152
|
+
Patch --> Instance
|
|
153
|
+
Instance --> Persist[saveDraft / resetToSeed]
|
|
154
|
+
```
|
|
155
|
+
|
|
38
156
|
### Editor de metadados integrado
|
|
39
157
|
|
|
40
158
|
Use o `ManualFieldMetadataBridgeService` para abrir o editor visual a partir de qualquer campo detectado pelo container. O serviço carrega o módulo sob demanda, aplica o patch retornado e chama `saveDraft()` para persistir as alterações no runtime.
|
|
@@ -58,6 +176,24 @@ export class CargoManualFormComponent {
|
|
|
58
176
|
}
|
|
59
177
|
```
|
|
60
178
|
|
|
179
|
+
### Toolbar de campo (modo de edicao)
|
|
180
|
+
|
|
181
|
+
Quando `editModeEnabled` estiver ativo, o manual-form exibe uma toolbar flutuante ao clicar
|
|
182
|
+
no campo. Ela permite alternar `required`, `readOnly`, `hidden` e `disabled`, e abrir o editor
|
|
183
|
+
completo de metadados.
|
|
184
|
+
|
|
185
|
+
Atalhos de teclado (quando o campo esta focado):
|
|
186
|
+
- `F2` ou `Alt+F10` abre a toolbar e move o foco para o primeiro botao.
|
|
187
|
+
- `ESC` fecha a toolbar.
|
|
188
|
+
|
|
189
|
+
Observacao: se um componente de campo interromper o clique (stopPropagation), a toolbar nao
|
|
190
|
+
abrira via mouse. Use os atalhos de teclado ou evite bloquear o click no host do campo.
|
|
191
|
+
|
|
192
|
+
Token de z-index:
|
|
193
|
+
- `--pdx-manual-toolbar-z` (default: `2001`).
|
|
194
|
+
Classe de overlay (para temas corporativos):
|
|
195
|
+
- `.pdx-manual-toolbar-panel` (aplicada no CDK Overlay para customizacoes).
|
|
196
|
+
|
|
61
197
|
## Motivações
|
|
62
198
|
|
|
63
199
|
- DX coerente para formulários manuais (sem JSON).
|
|
@@ -93,7 +229,7 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
|
|
|
93
229
|
## Padrão corporativo recomendado
|
|
94
230
|
|
|
95
231
|
- Host tipado: o host deve criar um `FormGroup` tipado e passá‑lo via `[formGroup]`. O container adota esse grupo, aplica metadados/validators e evita interceptações internas. Isso habilita o Angular Language Service a validar `formControlName` e melhora a DX.
|
|
96
|
-
- Modo dinâmico:
|
|
232
|
+
- Modo dinâmico: opção para PoCs e exemplos rápidos; veja os detalhes na seção “Guia rápido”.
|
|
97
233
|
|
|
98
234
|
## Configurações avançadas
|
|
99
235
|
|
|
@@ -104,37 +240,44 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
|
|
|
104
240
|
- Autosave
|
|
105
241
|
- `@Input() enableAutoSave: boolean` (padrão: `true`) e `@Input() autoSaveDebounceMs: number` (padrão: `800`).
|
|
106
242
|
|
|
107
|
-
|
|
243
|
+
### API pública adicional
|
|
244
|
+
|
|
245
|
+
- `ManualFormInstance.metadataChanges()`
|
|
246
|
+
- Emite sempre que o mapa de `FieldMetadata` é atualizado no runtime.
|
|
247
|
+
- Timing: após `patchFieldMetadata()`, `replaceConfig()`, `resetToSeed()` e cargas de config persistida.
|
|
108
248
|
|
|
109
|
-
|
|
249
|
+
## SSR (AsyncConfigStorage sem localStorage)
|
|
250
|
+
|
|
251
|
+
Em SSR, `localStorage` não existe. Como `praxis-manual-form` depende do token `ASYNC_CONFIG_STORAGE`, você pode prover uma implementação segura no servidor (ex.: in‑memory) e manter `LocalStorageAsyncAdapter` no browser.
|
|
110
252
|
|
|
111
253
|
Exemplo (Angular com `app.config.server.ts`):
|
|
112
254
|
|
|
113
255
|
```ts
|
|
114
256
|
// app.config.server.ts
|
|
115
257
|
import { ApplicationConfig, PLATFORM_ID, inject, isPlatformServer } from '@angular/core';
|
|
116
|
-
import {
|
|
258
|
+
import { ASYNC_CONFIG_STORAGE, LocalStorageAsyncAdapter, type AsyncConfigStorage } from '@praxisui/core';
|
|
259
|
+
import { EMPTY, of } from 'rxjs';
|
|
117
260
|
|
|
118
|
-
class
|
|
261
|
+
class MemoryAsyncStorage implements AsyncConfigStorage {
|
|
119
262
|
private readonly map = new Map<string, any>();
|
|
120
|
-
loadConfig<T>(key: string)
|
|
121
|
-
saveConfig<T>(key: string, config: T)
|
|
122
|
-
clearConfig(key: string)
|
|
263
|
+
loadConfig<T>(key: string) { return of((this.map.get(key) as T) ?? null); }
|
|
264
|
+
saveConfig<T>(key: string, config: T) { this.map.set(key, config); return EMPTY; }
|
|
265
|
+
clearConfig(key: string) { this.map.delete(key); return EMPTY; }
|
|
123
266
|
}
|
|
124
267
|
|
|
125
268
|
export const appConfig: ApplicationConfig = {
|
|
126
269
|
providers: [
|
|
127
270
|
{
|
|
128
|
-
provide:
|
|
271
|
+
provide: ASYNC_CONFIG_STORAGE,
|
|
129
272
|
useFactory: () => isPlatformServer(inject(PLATFORM_ID))
|
|
130
|
-
? new
|
|
131
|
-
: inject(
|
|
273
|
+
? new MemoryAsyncStorage()
|
|
274
|
+
: inject(LocalStorageAsyncAdapter),
|
|
132
275
|
},
|
|
133
276
|
],
|
|
134
277
|
};
|
|
135
278
|
```
|
|
136
279
|
|
|
137
|
-
Alternativas no servidor: usar cookies, cache distribuído (ex.: Redis) ou persistir por sessão do usuário. Basta implementar a interface `
|
|
280
|
+
Alternativas no servidor: usar cookies, cache distribuído (ex.: Redis) ou persistir por sessão do usuário. Basta implementar a interface `AsyncConfigStorage`.
|
|
138
281
|
|
|
139
282
|
### Exemplo (nested form)
|
|
140
283
|
|
|
@@ -192,6 +335,14 @@ export class MinhaPagina {
|
|
|
192
335
|
</praxis-manual-form>
|
|
193
336
|
```
|
|
194
337
|
|
|
338
|
+
Observações importantes:
|
|
339
|
+
- Aplique `[formGroup]` diretamente no seletor `<praxis-manual-form>` (no host).
|
|
340
|
+
- Evite envolver o componente com um `<form [formGroup]>` externo; não há necessidade e pode causar forms aninhados.
|
|
341
|
+
|
|
342
|
+
Modo dinâmico (sem host tipado):
|
|
343
|
+
- Quando nenhum `[formGroup]` é informado no host, o container renderiza internamente um `<form [formGroup]="formGroup">` para atender o Angular Forms e evitar o erro NG01050.
|
|
344
|
+
- Isso dispensa qualquer “shim” externo para os exemplos dinâmicos.
|
|
345
|
+
|
|
195
346
|
## API do ManualFormComponent (resumo)
|
|
196
347
|
|
|
197
348
|
- Inputs (sinais):
|
|
@@ -255,6 +406,20 @@ Exemplo de uso no host:
|
|
|
255
406
|
</praxis-manual-form>
|
|
256
407
|
```
|
|
257
408
|
|
|
409
|
+
#### O que o editor cobre (tabs)
|
|
410
|
+
|
|
411
|
+
O editor do formulario (Settings Panel) expõe:
|
|
412
|
+
- **Campos**: visibilidade, obrigatorio, somente leitura, desabilitado.
|
|
413
|
+
- **Acoes**: layout da barra, botoes padrao e acoes customizadas.
|
|
414
|
+
- **Mensagens**: feedbacks de sucesso/erro, loading e confirmacoes.
|
|
415
|
+
- **Comportamento**: flags de UX (ex.: focusFirstError, scrollToErrors).
|
|
416
|
+
- **Dicas**: textos auxiliares para modos de tela (i18n/UX).
|
|
417
|
+
- **Hooks**: JSON com hooks de lifecycle (antes/depois de init/submit).
|
|
418
|
+
- **Regras**: regras de layout/visibilidade (JSON).
|
|
419
|
+
- **Cascatas**: dependencias entre campos via metadados.
|
|
420
|
+
|
|
421
|
+
Obs.: a execucao de hooks/regras depende do host registrar os providers correspondentes.
|
|
422
|
+
|
|
258
423
|
## Extensibilidade por DI
|
|
259
424
|
|
|
260
425
|
- Customize a inferência de `FieldControlType` via tokens:
|
|
@@ -285,7 +450,7 @@ Exemplo de uso no host:
|
|
|
285
450
|
- Preferir host tipado e `usePathNames=true` para nested forms.
|
|
286
451
|
- Habilitar autosave com debounce adequado.
|
|
287
452
|
- Evitar lógica pesada em templates; delegar inferências ao container.
|
|
288
|
-
- No SSR, sempre prover `
|
|
453
|
+
- No SSR, sempre prover `ASYNC_CONFIG_STORAGE` compatível (sem localStorage).
|
|
289
454
|
|
|
290
455
|
## Licença
|
|
291
456
|
|
|
@@ -297,6 +462,11 @@ Apache-2.0 — consulte `LICENSE` neste pacote ou no repositório raiz.
|
|
|
297
462
|
- Layout é responsabilidade do host; não há reordenação automática por metadados.
|
|
298
463
|
- Modo dinâmico sem `[formGroup]` não habilita validação estática de `formControlName` no IDE.
|
|
299
464
|
|
|
465
|
+
## Notas adicionais
|
|
466
|
+
|
|
467
|
+
- Quando `editModeEnabled` estiver ativo, o container renderiza o assistente AI (Praxis AI) no header do formulario.
|
|
468
|
+
- `componentInstanceId` ajuda a compor a chave de persistencia (com `formId` e `persistenceOptions`), evitando conflito entre instancias da mesma tela.
|
|
469
|
+
|
|
300
470
|
## Comparativo — Manual vs Dinâmico (JSON)
|
|
301
471
|
|
|
302
472
|
- Manual: controle máximo do HTML; evolui por metadados incrementais; ótimo para telas estáveis com design específico.
|