@praxisui/manual-form 1.0.0-beta.4 → 1.0.0-beta.40

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
@@ -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: se nenhum `[formGroup]` for informado, o container cria e gerencia um `FormGroup` interno (útil para PoCs), sem garantia de validação estática de nomes.
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
- ## SSR (ConfigStorage sem localStorage)
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
- Em SSR, `localStorage` não existe. Como `praxis-manual-form` apenas depende do token `CONFIG_STORAGE`, você pode prover uma implementação segura no servidor (ex.: in‑memory) e manter `LocalStorageConfigService` no browser.
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 { CONFIG_STORAGE, LocalStorageConfigService, type ConfigStorage } from '@praxisui/core';
215
+ import { ASYNC_CONFIG_STORAGE, LocalStorageAsyncAdapter, type AsyncConfigStorage } from '@praxisui/core';
216
+ import { EMPTY, of } from 'rxjs';
117
217
 
118
- class MemoryConfigStorage implements ConfigStorage {
218
+ class MemoryAsyncStorage implements AsyncConfigStorage {
119
219
  private readonly map = new Map<string, any>();
120
- loadConfig<T>(key: string): T | null { return (this.map.get(key) as T) ?? null; }
121
- saveConfig<T>(key: string, config: T): void { this.map.set(key, config); }
122
- clearConfig(key: string): void { this.map.delete(key); }
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: CONFIG_STORAGE,
228
+ provide: ASYNC_CONFIG_STORAGE,
129
229
  useFactory: () => isPlatformServer(inject(PLATFORM_ID))
130
- ? new MemoryConfigStorage()
131
- : inject(LocalStorageConfigService),
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 `ConfigStorage`.
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 `CONFIG_STORAGE` compatível (sem localStorage).
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.