@praxisui/manual-form 1.0.0-beta.4 → 1.0.0-beta.41
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 +140 -13
- package/fesm2022/praxisui-manual-form.mjs +3639 -185
- 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,12 @@
|
|
|
1
1
|
# Manual Form Toolkit
|
|
2
2
|
|
|
3
|
+
## 🔰 Exemplos / Quickstart
|
|
4
|
+
|
|
5
|
+
Para ver esta biblioteca em funcionamento em uma aplicação completa, utilize o projeto de exemplo (Quickstart):
|
|
6
|
+
|
|
7
|
+
- Repositório: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
8
|
+
- O Quickstart demonstra a integração das bibliotecas `@praxisui/*` em um app Angular, incluindo instalação, configuração e uso em telas reais.
|
|
9
|
+
|
|
3
10
|
## Instalação
|
|
4
11
|
|
|
5
12
|
```bash
|
|
@@ -35,6 +42,74 @@ O exemplo `/cargos/manual-form` demonstra uso declarativo:
|
|
|
35
42
|
</praxis-manual-form>
|
|
36
43
|
```
|
|
37
44
|
|
|
45
|
+
### Padrão didático para exemplos renderizados
|
|
46
|
+
|
|
47
|
+
Para páginas de documentação que precisam mostrar o componente antes de blocos longos de texto,
|
|
48
|
+
use o wrapper `praxis-manual-form-doc-example`. Ele já entrega:
|
|
49
|
+
|
|
50
|
+
- Banner curto com foco no exemplo live.
|
|
51
|
+
- Tabs para alternar entre `Live`, `Template`, `TS` e `Config`.
|
|
52
|
+
- Toggle de modo de customização (liga/desliga) com evento.
|
|
53
|
+
- Botão de cópia do snippet ativo.
|
|
54
|
+
- Callouts opcionais de `IMPORTANTE`, `NOTA` e `DICA`.
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<praxis-manual-form-doc-example
|
|
58
|
+
title="Cadastro de cargo"
|
|
59
|
+
subtitle="Preview primeiro, explicações depois."
|
|
60
|
+
level="Intermediario"
|
|
61
|
+
bannerTitle="Veja o componente em ação"
|
|
62
|
+
bannerDescription="Explore o live e abra código apenas quando necessário."
|
|
63
|
+
[templateCode]="templateSnippet"
|
|
64
|
+
[tsCode]="tsSnippet"
|
|
65
|
+
[configCode]="configSnippet"
|
|
66
|
+
[customizationEnabled]="editMode()"
|
|
67
|
+
(customizationEnabledChange)="editMode.set($event)"
|
|
68
|
+
important="Persista o draft no submit."
|
|
69
|
+
note="A aba Live abre por padrão."
|
|
70
|
+
tip="Use a aba Config para explicar contratos JSON."
|
|
71
|
+
>
|
|
72
|
+
<div exampleLive>
|
|
73
|
+
<praxis-manual-form
|
|
74
|
+
[formGroup]="form"
|
|
75
|
+
formId="cargo-manual-form"
|
|
76
|
+
[editModeEnabled]="editMode()"
|
|
77
|
+
>
|
|
78
|
+
<pdx-text-input formControlName="nome" label="Nome"></pdx-text-input>
|
|
79
|
+
</praxis-manual-form>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div exampleDiagram>
|
|
83
|
+
<!-- Mermaid, SVG ou fluxo simplificado -->
|
|
84
|
+
</div>
|
|
85
|
+
</praxis-manual-form-doc-example>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Também existe um showcase pronto para consumo direto:
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<praxis-manual-form-doc-example-showcase></praxis-manual-form-doc-example-showcase>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Esse showcase já inclui providers locais de `API_URL` e `ASYNC_CONFIG_STORAGE`, evitando erro de injeção em páginas de documentação.
|
|
95
|
+
|
|
96
|
+
### Diagrama de funcionamento (alto nível)
|
|
97
|
+
|
|
98
|
+
```mermaid
|
|
99
|
+
flowchart LR
|
|
100
|
+
Host[Template com <pdx-*>] --> ManualForm[praxis-manual-form]
|
|
101
|
+
ManualForm --> Detect[Detecta campos]
|
|
102
|
+
Detect --> Meta[Infere FieldMetadata]
|
|
103
|
+
Meta --> Group[Cria/Adota FormGroup]
|
|
104
|
+
Group --> Render[Renderiza campos + validações]
|
|
105
|
+
ManualForm --> Instance[ManualFormInstance]
|
|
106
|
+
Instance --> Storage[ConfigStorage]
|
|
107
|
+
ManualForm -->|editMode| Editor[Metadata Editor]
|
|
108
|
+
Editor --> Patch[Aplica patch]
|
|
109
|
+
Patch --> Instance
|
|
110
|
+
Instance --> Persist[saveDraft / resetToSeed]
|
|
111
|
+
```
|
|
112
|
+
|
|
38
113
|
### Editor de metadados integrado
|
|
39
114
|
|
|
40
115
|
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 +133,24 @@ export class CargoManualFormComponent {
|
|
|
58
133
|
}
|
|
59
134
|
```
|
|
60
135
|
|
|
136
|
+
### Toolbar de campo (modo de edicao)
|
|
137
|
+
|
|
138
|
+
Quando `editModeEnabled` estiver ativo, o manual-form exibe uma toolbar flutuante ao clicar
|
|
139
|
+
no campo. Ela permite alternar `required`, `readOnly`, `hidden` e `disabled`, e abrir o editor
|
|
140
|
+
completo de metadados.
|
|
141
|
+
|
|
142
|
+
Atalhos de teclado (quando o campo esta focado):
|
|
143
|
+
- `F2` ou `Alt+F10` abre a toolbar e move o foco para o primeiro botao.
|
|
144
|
+
- `ESC` fecha a toolbar.
|
|
145
|
+
|
|
146
|
+
Observacao: se um componente de campo interromper o clique (stopPropagation), a toolbar nao
|
|
147
|
+
abrira via mouse. Use os atalhos de teclado ou evite bloquear o click no host do campo.
|
|
148
|
+
|
|
149
|
+
Token de z-index:
|
|
150
|
+
- `--pdx-manual-toolbar-z` (default: `2001`).
|
|
151
|
+
Classe de overlay (para temas corporativos):
|
|
152
|
+
- `.pdx-manual-toolbar-panel` (aplicada no CDK Overlay para customizacoes).
|
|
153
|
+
|
|
61
154
|
## Motivações
|
|
62
155
|
|
|
63
156
|
- DX coerente para formulários manuais (sem JSON).
|
|
@@ -93,7 +186,7 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
|
|
|
93
186
|
## Padrão corporativo recomendado
|
|
94
187
|
|
|
95
188
|
- 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:
|
|
189
|
+
- Modo dinâmico: opção para PoCs e exemplos rápidos; veja os detalhes na seção “Guia rápido”.
|
|
97
190
|
|
|
98
191
|
## Configurações avançadas
|
|
99
192
|
|
|
@@ -104,37 +197,44 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
|
|
|
104
197
|
- Autosave
|
|
105
198
|
- `@Input() enableAutoSave: boolean` (padrão: `true`) e `@Input() autoSaveDebounceMs: number` (padrão: `800`).
|
|
106
199
|
|
|
107
|
-
|
|
200
|
+
### API pública adicional
|
|
201
|
+
|
|
202
|
+
- `ManualFormInstance.metadataChanges()`
|
|
203
|
+
- Emite sempre que o mapa de `FieldMetadata` é atualizado no runtime.
|
|
204
|
+
- Timing: após `patchFieldMetadata()`, `replaceConfig()`, `resetToSeed()` e cargas de config persistida.
|
|
108
205
|
|
|
109
|
-
|
|
206
|
+
## SSR (AsyncConfigStorage sem localStorage)
|
|
207
|
+
|
|
208
|
+
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
209
|
|
|
111
210
|
Exemplo (Angular com `app.config.server.ts`):
|
|
112
211
|
|
|
113
212
|
```ts
|
|
114
213
|
// app.config.server.ts
|
|
115
214
|
import { ApplicationConfig, PLATFORM_ID, inject, isPlatformServer } from '@angular/core';
|
|
116
|
-
import {
|
|
215
|
+
import { ASYNC_CONFIG_STORAGE, LocalStorageAsyncAdapter, type AsyncConfigStorage } from '@praxisui/core';
|
|
216
|
+
import { EMPTY, of } from 'rxjs';
|
|
117
217
|
|
|
118
|
-
class
|
|
218
|
+
class MemoryAsyncStorage implements AsyncConfigStorage {
|
|
119
219
|
private readonly map = new Map<string, any>();
|
|
120
|
-
loadConfig<T>(key: string)
|
|
121
|
-
saveConfig<T>(key: string, config: T)
|
|
122
|
-
clearConfig(key: string)
|
|
220
|
+
loadConfig<T>(key: string) { return of((this.map.get(key) as T) ?? null); }
|
|
221
|
+
saveConfig<T>(key: string, config: T) { this.map.set(key, config); return EMPTY; }
|
|
222
|
+
clearConfig(key: string) { this.map.delete(key); return EMPTY; }
|
|
123
223
|
}
|
|
124
224
|
|
|
125
225
|
export const appConfig: ApplicationConfig = {
|
|
126
226
|
providers: [
|
|
127
227
|
{
|
|
128
|
-
provide:
|
|
228
|
+
provide: ASYNC_CONFIG_STORAGE,
|
|
129
229
|
useFactory: () => isPlatformServer(inject(PLATFORM_ID))
|
|
130
|
-
? new
|
|
131
|
-
: inject(
|
|
230
|
+
? new MemoryAsyncStorage()
|
|
231
|
+
: inject(LocalStorageAsyncAdapter),
|
|
132
232
|
},
|
|
133
233
|
],
|
|
134
234
|
};
|
|
135
235
|
```
|
|
136
236
|
|
|
137
|
-
Alternativas no servidor: usar cookies, cache distribuído (ex.: Redis) ou persistir por sessão do usuário. Basta implementar a interface `
|
|
237
|
+
Alternativas no servidor: usar cookies, cache distribuído (ex.: Redis) ou persistir por sessão do usuário. Basta implementar a interface `AsyncConfigStorage`.
|
|
138
238
|
|
|
139
239
|
### Exemplo (nested form)
|
|
140
240
|
|
|
@@ -192,6 +292,14 @@ export class MinhaPagina {
|
|
|
192
292
|
</praxis-manual-form>
|
|
193
293
|
```
|
|
194
294
|
|
|
295
|
+
Observações importantes:
|
|
296
|
+
- Aplique `[formGroup]` diretamente no seletor `<praxis-manual-form>` (no host).
|
|
297
|
+
- Evite envolver o componente com um `<form [formGroup]>` externo; não há necessidade e pode causar forms aninhados.
|
|
298
|
+
|
|
299
|
+
Modo dinâmico (sem host tipado):
|
|
300
|
+
- Quando nenhum `[formGroup]` é informado no host, o container renderiza internamente um `<form [formGroup]="formGroup">` para atender o Angular Forms e evitar o erro NG01050.
|
|
301
|
+
- Isso dispensa qualquer “shim” externo para os exemplos dinâmicos.
|
|
302
|
+
|
|
195
303
|
## API do ManualFormComponent (resumo)
|
|
196
304
|
|
|
197
305
|
- Inputs (sinais):
|
|
@@ -255,6 +363,20 @@ Exemplo de uso no host:
|
|
|
255
363
|
</praxis-manual-form>
|
|
256
364
|
```
|
|
257
365
|
|
|
366
|
+
#### O que o editor cobre (tabs)
|
|
367
|
+
|
|
368
|
+
O editor do formulario (Settings Panel) expõe:
|
|
369
|
+
- **Campos**: visibilidade, obrigatorio, somente leitura, desabilitado.
|
|
370
|
+
- **Acoes**: layout da barra, botoes padrao e acoes customizadas.
|
|
371
|
+
- **Mensagens**: feedbacks de sucesso/erro, loading e confirmacoes.
|
|
372
|
+
- **Comportamento**: flags de UX (ex.: focusFirstError, scrollToErrors).
|
|
373
|
+
- **Dicas**: textos auxiliares para modos de tela (i18n/UX).
|
|
374
|
+
- **Hooks**: JSON com hooks de lifecycle (antes/depois de init/submit).
|
|
375
|
+
- **Regras**: regras de layout/visibilidade (JSON).
|
|
376
|
+
- **Cascatas**: dependencias entre campos via metadados.
|
|
377
|
+
|
|
378
|
+
Obs.: a execucao de hooks/regras depende do host registrar os providers correspondentes.
|
|
379
|
+
|
|
258
380
|
## Extensibilidade por DI
|
|
259
381
|
|
|
260
382
|
- Customize a inferência de `FieldControlType` via tokens:
|
|
@@ -285,7 +407,7 @@ Exemplo de uso no host:
|
|
|
285
407
|
- Preferir host tipado e `usePathNames=true` para nested forms.
|
|
286
408
|
- Habilitar autosave com debounce adequado.
|
|
287
409
|
- Evitar lógica pesada em templates; delegar inferências ao container.
|
|
288
|
-
- No SSR, sempre prover `
|
|
410
|
+
- No SSR, sempre prover `ASYNC_CONFIG_STORAGE` compatível (sem localStorage).
|
|
289
411
|
|
|
290
412
|
## Licença
|
|
291
413
|
|
|
@@ -297,6 +419,11 @@ Apache-2.0 — consulte `LICENSE` neste pacote ou no repositório raiz.
|
|
|
297
419
|
- Layout é responsabilidade do host; não há reordenação automática por metadados.
|
|
298
420
|
- Modo dinâmico sem `[formGroup]` não habilita validação estática de `formControlName` no IDE.
|
|
299
421
|
|
|
422
|
+
## Notas adicionais
|
|
423
|
+
|
|
424
|
+
- Quando `editModeEnabled` estiver ativo, o container renderiza o assistente AI (Praxis AI) no header do formulario.
|
|
425
|
+
- `componentInstanceId` ajuda a compor a chave de persistencia (com `formId` e `persistenceOptions`), evitando conflito entre instancias da mesma tela.
|
|
426
|
+
|
|
300
427
|
## Comparativo — Manual vs Dinâmico (JSON)
|
|
301
428
|
|
|
302
429
|
- Manual: controle máximo do HTML; evolui por metadados incrementais; ótimo para telas estáveis com design específico.
|