@praxisui/manual-form 1.0.0-beta.30 → 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
@@ -42,6 +42,74 @@ O exemplo `/cargos/manual-form` demonstra uso declarativo:
42
42
  </praxis-manual-form>
43
43
  ```
44
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
+
45
113
  ### Editor de metadados integrado
46
114
 
47
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.
@@ -65,6 +133,24 @@ export class CargoManualFormComponent {
65
133
  }
66
134
  ```
67
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
+
68
154
  ## Motivações
69
155
 
70
156
  - DX coerente para formulários manuais (sem JSON).
@@ -100,7 +186,7 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
100
186
  ## Padrão corporativo recomendado
101
187
 
102
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.
103
- - 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”.
104
190
 
105
191
  ## Configurações avançadas
106
192
 
@@ -111,37 +197,44 @@ Essa base permite que hosts manualmente criem formulários com componentes Praxi
111
197
  - Autosave
112
198
  - `@Input() enableAutoSave: boolean` (padrão: `true`) e `@Input() autoSaveDebounceMs: number` (padrão: `800`).
113
199
 
114
- ## SSR (ConfigStorage sem localStorage)
200
+ ### API pública adicional
115
201
 
116
- 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.
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.
205
+
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.
117
209
 
118
210
  Exemplo (Angular com `app.config.server.ts`):
119
211
 
120
212
  ```ts
121
213
  // app.config.server.ts
122
214
  import { ApplicationConfig, PLATFORM_ID, inject, isPlatformServer } from '@angular/core';
123
- 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';
124
217
 
125
- class MemoryConfigStorage implements ConfigStorage {
218
+ class MemoryAsyncStorage implements AsyncConfigStorage {
126
219
  private readonly map = new Map<string, any>();
127
- loadConfig<T>(key: string): T | null { return (this.map.get(key) as T) ?? null; }
128
- saveConfig<T>(key: string, config: T): void { this.map.set(key, config); }
129
- 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; }
130
223
  }
131
224
 
132
225
  export const appConfig: ApplicationConfig = {
133
226
  providers: [
134
227
  {
135
- provide: CONFIG_STORAGE,
228
+ provide: ASYNC_CONFIG_STORAGE,
136
229
  useFactory: () => isPlatformServer(inject(PLATFORM_ID))
137
- ? new MemoryConfigStorage()
138
- : inject(LocalStorageConfigService),
230
+ ? new MemoryAsyncStorage()
231
+ : inject(LocalStorageAsyncAdapter),
139
232
  },
140
233
  ],
141
234
  };
142
235
  ```
143
236
 
144
- 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`.
145
238
 
146
239
  ### Exemplo (nested form)
147
240
 
@@ -270,6 +363,20 @@ Exemplo de uso no host:
270
363
  </praxis-manual-form>
271
364
  ```
272
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
+
273
380
  ## Extensibilidade por DI
274
381
 
275
382
  - Customize a inferência de `FieldControlType` via tokens:
@@ -300,7 +407,7 @@ Exemplo de uso no host:
300
407
  - Preferir host tipado e `usePathNames=true` para nested forms.
301
408
  - Habilitar autosave com debounce adequado.
302
409
  - Evitar lógica pesada em templates; delegar inferências ao container.
303
- - No SSR, sempre prover `CONFIG_STORAGE` compatível (sem localStorage).
410
+ - No SSR, sempre prover `ASYNC_CONFIG_STORAGE` compatível (sem localStorage).
304
411
 
305
412
  ## Licença
306
413
 
@@ -312,6 +419,11 @@ Apache-2.0 — consulte `LICENSE` neste pacote ou no repositório raiz.
312
419
  - Layout é responsabilidade do host; não há reordenação automática por metadados.
313
420
  - Modo dinâmico sem `[formGroup]` não habilita validação estática de `formControlName` no IDE.
314
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
+
315
427
  ## Comparativo — Manual vs Dinâmico (JSON)
316
428
 
317
429
  - Manual: controle máximo do HTML; evolui por metadados incrementais; ótimo para telas estáveis com design específico.