@praxisui/table 5.0.0-beta.0 → 7.0.0-beta.0

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,4 +1,4 @@
1
- ---
1
+ ---
2
2
  title: "Table"
3
3
  slug: "table-overview"
4
4
  description: "Visao geral do @praxisui/table com TableConfig unificada, filtros, renderers, performance e integracao enterprise."
@@ -50,12 +50,12 @@ last_updated: "2026-03-07"
50
50
 
51
51
  # @praxisui/table
52
52
 
53
- > Estado canônico do workspace Angular: JSON Logic é o único contrato ativo de regras. Menções a DSL neste documento existem apenas como contexto histórico de migração ou referência para payloads legados.
53
+ > Estado canônico do workspace Angular: JSON Logic é o único contrato ativo de regras condicionais.
54
54
 
55
55
  ## Documentation
56
56
 
57
- - Documentação oficial: https://praxisui.dev
58
- - Aplicação de referência: https://github.com/codexrodrigues/praxis-ui-quickstart
57
+ - Documentação oficial: https://praxisui.dev
58
+ - Aplicação de referência: https://github.com/codexrodrigues/praxis-ui-quickstart
59
59
  - Indicado para: data grids enterprise com filtros, edicao, virtualizacao, renderers e governanca de configuracao
60
60
 
61
61
  ## When to use
@@ -64,7 +64,67 @@ last_updated: "2026-03-07"
64
64
  - Governar configuracao de colunas, toolbar e comportamento em runtime
65
65
  - Integrar tabelas a fluxos CRUD, IA e editores visuais do ecossistema Praxis UI
66
66
 
67
- ## `x-ui.analytics` como fallback tabular canônico
67
+ ## Rich Content Convergence
68
+
69
+ - `mapTableRendererToRichContentP0(...)` e a ponte canonica entre os renderers de celula da tabela e o vocabulario compartilhado `1.0` de rich content em `@praxisui/core`.
70
+ - O subconjunto promovido nesta fase e intencionalmente pequeno: `icon`, `image`, `badge`, `chip -> badge`, `avatar`, `progress` e `compose`.
71
+ - Renderers interativos como `button`, `toggle`, `menu`, `link`, `html` e `rating`, alem do shell de detail/expansion, continuam table-owned ate promocao semantica explicita.
72
+
73
+ ## Detail Rich Surfaces
74
+
75
+ - `behavior.expansion.detail.schemaContract.allowedNodes` agora inclui `detailList` como node canônico novo para colecoes ricas no detail row.
76
+ - A mesma fronteira agora inclui `cardGrid` como container canônico para grades densas de cards no detail.
77
+ - `mediaBlock` entrou como primitive compartilhada para headers/identidade rica no topo do detail, sem criar renderer paralelo table-owned.
78
+ - `timeline` entrou como surface cronologica compartilhada para atividade recente, preservando o shell host-owned da tabela.
79
+ - `actionBar` entrou como surface host-mediated para grupos de ações contextuais no detail, sem duplicar `row actions`.
80
+ - `tableRef`, `formRef`, `chartRef`, `templateRef` e `diagramEmbed` agora entram como embeds governados no detail row.
81
+ - `list` continua significando colecao simples. Ele nao foi promovido para subtree declarativa por item.
82
+ - `detailList` e host-mediated:
83
+ - o host resolve a colecao e despacha `itemActions`
84
+ - cada item renderiza sua subtree declarativa via `PraxisRichContent`
85
+ - `cardGrid` tambem e host-mediated:
86
+ - o host resolve apenas o shell responsivo do grid
87
+ - cada card continua renderizado como `RichCardNode` via `PraxisRichContent`
88
+ - `actionBar` tambem e host-mediated:
89
+ - o host continua dono de dispatch, disabled, `visibleWhen` e `payloadExpr`
90
+ - o miolo visual de cada botão continua delegado para `PraxisRichContent`
91
+ - embeds governados tambem sao host-mediated:
92
+ - o host continua dono de discovery, resolucao e abertura de surface
93
+ - o shell visual, metadados e CTA do embed ficam padronizados na tabela
94
+ - `diagramEmbed` adiciona preview governado de fonte, sem abrir uma DSL paralela no detail
95
+ - `mediaBlock` e host-neutral:
96
+ - o contrato base vive em `@praxisui/core`
97
+ - o rendering vive em `@praxisui/rich-content`
98
+ - a tabela apenas o aceita no detail schema e o delega para o runtime compartilhado
99
+ - O primeiro corte cobre:
100
+ - `field` ou `items`
101
+ - `emptyText`
102
+ - `itemSchema.nodes`
103
+ - `itemContext` (`detailItem` / `detailIndex`)
104
+ - `itemActions` com `payloadExpr`, `visibleWhen` e `disabledWhen`
105
+ - O segundo corte cobre:
106
+ - `columns` (`1 | 2 | 3 | 4 | 'auto'`)
107
+ - `minCardWidth`
108
+ - `cards[]` com `title`, `subtitle` e `content` limitado a `RichPresenterNode | RichComposeNode`
109
+ - O terceiro corte agora cobre:
110
+ - `mediaBlock.avatar`
111
+ - `mediaBlock.title`
112
+ - `mediaBlock.subtitle`
113
+ - `mediaBlock.meta`
114
+ - `mediaBlock.trailing`
115
+ - O quarto corte agora cobre:
116
+ - `timeline.field` ou `timeline.items`
117
+ - `timeline.emptyText`
118
+ - `timeline.itemSchema.titleField`
119
+ - `timeline.itemSchema.subtitleField`
120
+ - `timeline.itemSchema.metaField`
121
+ - `timeline.itemSchema.iconField`
122
+ - `timeline.itemSchema.badgeField`
123
+ - O quinto corte agora cobre:
124
+ - `tableRef`, `formRef`, `chartRef` e `templateRef` com `description`, `caption`, `inputs`, `presetRef`, `emptyText` e `action`
125
+ - `diagramEmbed` com `provider`, `source` ou `sourceField`, `presetRef` e `action`
126
+
127
+ ## `x-ui.analytics` como fallback tabular canônico
68
128
 
69
129
  O `@praxisui/table` materializa a familia `analytic-table` quando o `@praxisui/core`
70
130
  resolve que uma projection de `x-ui.analytics` continua valida, mas nao e um chart
@@ -95,7 +155,7 @@ Filtro runtime:
95
155
  - somente `filters` entram no request remoto nesta fase
96
156
  - `sort`, `limit` e agregacao continuam vindo da projection publicada
97
157
 
98
- > Componente de tabela empresarial avançado com arquitetura unificada
158
+ > Componente de tabela empresarial avançado com arquitetura unificada
99
159
 
100
160
  ## Customization Mode Contract
101
161
 
@@ -109,92 +169,92 @@ Filtro runtime:
109
169
  - Hosts that relied on the previous implicit authoring behavior must now declare `[enableCustomization]="true"` explicitly.
110
170
  - This is an intentional breaking change for enterprise governance: authoring is opt-in, not ambient.
111
171
 
112
- ## 🌟 Visão Geral
172
+ ## 🌟 Visão Geral
113
173
 
114
- A biblioteca `@praxisui/table` fornece um componente de tabela robusto e altamente configurável para aplicações Angular empresariais. Com a nova arquitetura unificada, oferece uma experiência de desenvolvimento simplificada mantendo todos os recursos avançados.
174
+ A biblioteca `@praxisui/table` fornece um componente de tabela robusto e altamente configurável para aplicações Angular empresariais. Com a nova arquitetura unificada, oferece uma experiência de desenvolvimento simplificada mantendo todos os recursos avançados.
115
175
 
116
- ## 🎨 Tema M3 (tokens mínimos)
176
+ ## 🎨 Tema M3 (tokens mínimos)
117
177
 
118
178
  Para garantir que a tabela, filtros e editores reflitam o tema do app host:
119
179
 
120
- - Superfícies: `--md-sys-color-surface`, `--md-sys-color-surface-variant`, `--md-sys-color-surface-container-*`
180
+ - Superfícies: `--md-sys-color-surface`, `--md-sys-color-surface-variant`, `--md-sys-color-surface-container-*`
121
181
  - Texto/contorno: `--md-sys-color-on-surface`, `--md-sys-color-on-surface-variant`, `--md-sys-color-on-primary`, `--md-sys-color-outline`, `--md-sys-color-outline-variant`
122
- - Semânticos: `--md-sys-color-primary`, `--md-sys-color-secondary`, `--md-sys-color-tertiary`, `--md-sys-color-error`
182
+ - Semânticos: `--md-sys-color-primary`, `--md-sys-color-secondary`, `--md-sys-color-tertiary`, `--md-sys-color-error`
123
183
  - Containers: `--md-sys-color-primary-container`, `--md-sys-color-secondary-container`, `--md-sys-color-tertiary-container`, `--md-sys-color-error-container`
124
184
  - Overlay: `--md-sys-color-scrim`
125
- - Elevação: `--md-sys-elevation-level1`–`--md-sys-elevation-level3`
185
+ - Elevação: `--md-sys-elevation-level1`–`--md-sys-elevation-level3`
126
186
 
127
- Observação: tokens `--md-sys-*` e `--mdc-theme-*` continuam aceitos quando presentes.
128
- Nota: a classe de tema é decisão do host (`.dark-theme` ou `.theme-dark`/`.theme-light`); mantenha tokens e componentes no mesmo escopo.
187
+ Observação: tokens `--md-sys-*` e `--mdc-theme-*` continuam aceitos quando presentes.
188
+ Nota: a classe de tema é decisão do host (`.dark-theme` ou `.theme-dark`/`.theme-light`); mantenha tokens e componentes no mesmo escopo.
129
189
 
130
- ## Características Principais
190
+ ## ✨ Características Principais
131
191
 
132
- ### 🏗️ Arquitetura Unificada
192
+ ### 🏗️ Arquitetura Unificada
133
193
 
134
- - **Interface única**: `TableConfig` consolidada
194
+ - **Interface única**: `TableConfig` consolidada
135
195
  - **Type Safety**: Tipagem forte em toda a API
136
- - **Performance otimizada**: Eliminação de overhead de adaptação
137
- - **API simplificada**: Menos confusão, mais produtividade
138
-
139
- ### 📊 Recursos Avançados
140
-
141
- - **Paginação inteligente**: Client-side e server-side
142
- - **Ordenação múltipla**: Suporte a multi-sort
143
- - **Filtros dinâmicos**: Global e por coluna
144
- - **Seleção de linhas**: Single, multiple e bulk actions
145
- - **Redimensionamento**: Colunas redimensionáveis
146
- - **Virtualização**: Para grandes volumes de dados
147
- - **Exportação**: CSV, Excel, PDF
196
+ - **Performance otimizada**: Eliminação de overhead de adaptação
197
+ - **API simplificada**: Menos confusão, mais produtividade
198
+
199
+ ### 📊 Recursos Avançados
200
+
201
+ - **Paginação inteligente**: Client-side e server-side
202
+ - **Ordenação múltipla**: Suporte a multi-sort
203
+ - **Filtros dinâmicos**: Global e por coluna
204
+ - **Seleção de linhas**: Single, multiple e bulk actions
205
+ - **Redimensionamento**: Colunas redimensionáveis
206
+ - **Virtualização**: Para grandes volumes de dados
207
+ - **Exportação**: CSV, Excel, PDF
148
208
  - **Acessibilidade**: WCAG 2.1 AA compliant
149
- - **Verificação de Schema**: ETag/If-None-Match com notificações (somente em customização)
209
+ - **Verificação de Schema**: ETag/If-None-Match com notificações (somente em customização)
150
210
 
151
211
  ## Expansion Hypermedia
152
212
 
153
- O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"` é
213
+ O primeiro corte de `behavior.expansion.detail.source.mode = "hypermedia"` é
154
214
  `capabilities-first`:
155
215
 
156
- - a row expandida começa em `_links.capabilities`
157
- - `surfaces`, `actions` e operações canônicas vêm do snapshot agregado retornado
216
+ - a row expandida começa em `_links.capabilities`
217
+ - `surfaces`, `actions` e operações canônicas vêm do snapshot agregado retornado
158
218
  pelo backend
159
219
  - o detail renderiza um resumo contextual somente leitura, com foco em UX de
160
- negócio e affordances disponíveis naquele registro
161
- - este corte não executa `surface.open` inline nem dispara workflow inline
162
- - quando o item não expõe `rel="capabilities"`, o runtime aplica fail-closed
220
+ negócio e affordances disponíveis naquele registro
221
+ - este corte não executa `surface.open` inline nem dispara workflow inline
222
+ - quando o item não expõe `rel="capabilities"`, o runtime aplica fail-closed
163
223
 
164
- Observação de escala:
224
+ Observação de escala:
165
225
  - o prefetch por linha continua ativo quando `actions.row.enabled=true`
166
- - quando apenas o expansion `hypermedia` está ligado, o discovery contextual é
226
+ - quando apenas o expansion `hypermedia` está ligado, o discovery contextual é
167
227
  resolvido sob demanda ao expandir a linha
168
228
 
169
- ### 📄 Contrato Inline do Filtro
229
+ ### 📄 Contrato Inline do Filtro
170
230
 
171
231
  - Referencia canonica: `projects/praxis-dynamic-fields/docs/dynamic-fields-inline-components-guide.md` (slug publicado: `dynamic-fields-inline-components-guide`)
172
232
  - No contexto da tabela, use este contrato para definir `controlType` inline e politica de compatibilidade (canonica vs legado).
173
233
 
174
- ### 🧭 Decisoes de Arquitetura (ADR)
234
+ ### 🧭 Decisoes de Arquitetura (ADR)
175
235
 
176
236
  - Bundle/adapters: `projects/praxis-table/docs/adr/2026-03-filter-drawer-adapter-light-entrypoint.md`
177
237
 
178
- ### 🎨 Editores Visuais
238
+ ### 🎨 Editores Visuais
179
239
 
180
- - **Behavior Editor**: Configuração de comportamentos
181
- - **Columns Editor**: Gestão avançada de colunas
182
- - **Toolbar Editor**: Personalização de ações
183
- - **Messages Editor**: Textos e localização
240
+ - **Behavior Editor**: Configuração de comportamentos
241
+ - **Columns Editor**: Gestão avançada de colunas
242
+ - **Toolbar Editor**: Personalização de ações
243
+ - **Messages Editor**: Textos e localização
184
244
 
185
245
  Nota (Regras)
186
- - A antiga aba visual genérica foi removida deste pacote. O editor especializado de regras da Tabela está disponível no painel de configuração.
246
+ - A antiga aba visual genérica foi removida deste pacote. O editor especializado de regras da Tabela já está disponível no painel de configuração.
187
247
 
188
- ### 🧩 Editor de Regras (column-first)
248
+ ### 🧩 Editor de Regras (column-first)
189
249
 
190
- O novo editor é "column-first" e usa uma tipagem compartilhada com o Editor de Colunas. Principais pontos:
250
+ O novo editor é "column-first" e usa uma tipagem compartilhada com o Editor de Colunas. Principais pontos:
191
251
 
192
- - Escopo: aplique regras na linha inteira (rowConditionalStyles) ou em uma coluna específica (columns[].conditionalStyles).
193
- - Operadores por tipo: o conjunto de operadores é filtrado por tipo (string/number/date/boolean/enum).
194
- - Editores de valor dinâmicos: inputs numéricos, listas (CSV/múltipla seleção), datepickers.
195
- - Grupos lógicos: construa condições com AND/OR/NOT e reordene via arrastar-e-soltar (CDK DragDrop).
196
- - Preview: execute Testar para ver quantas linhas seriam afetadas pelas regras ativas.
197
- - Import/Export: exporta JSON sem o campo `enabled`; importa com validação estrutural de JSON Logic e sanitização de estilos (allowlist).
252
+ - Escopo: aplique regras na linha inteira (rowConditionalStyles) ou em uma coluna específica (columns[].conditionalStyles).
253
+ - Operadores por tipo: o conjunto de operadores é filtrado por tipo (string/number/date/boolean/enum).
254
+ - Editores de valor dinâmicos: inputs numéricos, listas (CSV/múltipla seleção), datepickers.
255
+ - Grupos lógicos: construa condições com AND/OR/NOT e reordene via arrastar-e-soltar (CDK DragDrop).
256
+ - Preview: execute “Testar” para ver quantas linhas seriam afetadas pelas regras ativas.
257
+ - Import/Export: exporta JSON sem o campo `enabled`; importa com validação estrutural de JSON Logic e sanitização de estilos (allowlist).
198
258
 
199
259
  Exemplos de JSON Logic:
200
260
 
@@ -208,80 +268,77 @@ Exemplos de JSON Logic:
208
268
  ```
209
269
 
210
270
  Notas sobre enum/CSV:
211
- - Para campos enumerados, as opções são inferidas de `valueMapping` da coluna ou de `fields?.options`.
212
- - Para `in/not in` em números/strings, use CSV (ex.: `10, 20, 30` ou `Alice, Bob`).
271
+ - Para campos enumerados, as opções são inferidas de `valueMapping` da coluna ou de `fields?.options`.
272
+ - Para `in/not in` em números/strings, use CSV (ex.: `10, 20, 30` ou `Alice, Bob`).
213
273
 
214
- #### Extensões de DSL (runtime nativo + custom)
274
+ #### Operadores e helpers de JSON Logic
215
275
 
216
- O runtime da tabela inclui helpers de JSON/tempo/listas/texto sem configuração extra:
276
+ O runtime da tabela já inclui operadores e helpers canônicos para JSON/tempo/listas/texto sem configuração extra:
217
277
 
218
278
  - JSON: `jsonGet`, `hasJsonKey`, `jsonPathMatches`, `jsonEq`, `jsonIn`, `jsonType`
219
279
  - Texto/valor: `isBlank`, `eqIgnoreCase`, `coalesce`
220
280
  - Faixas: `between`, `dateBetween`
221
- - Coleções: `containsAny`, `containsAll`, `len`, `lenEq`, `lenGt`, `lenLt`, `lenAtLeast`
281
+ - Coleções: `containsAny`, `containsAll`, `len`, `lenEq`, `lenGt`, `lenLt`, `lenAtLeast`
222
282
  - Tempo: `today`, `now`, `dateAdd`, `dateFormat`, `isToday`, `inLast`, `isPast`, `isPastOrNow`, `isFuture`, `isFutureOrNow`, `weekdayIn`
223
283
 
224
- Exemplos de DSL (canônica):
225
- - `jsonEq(payload, '$.user.name', 'Alice')`
226
- - `jsonIn(customer, '$.id', [10, 20])`
227
- - `eqIgnoreCase(status, 'ATIVO')`
228
- - `between(amount, 10, 20)`
229
- - `dateBetween(createdAt, '2025-01-01', '2025-12-31')`
230
- - `containsAll(tags, ['vip', 'gold'])`
231
-
232
- Observação de gramática:
233
- - comparações diretas sobre retorno de função (`fn(...) == 'x'`) não são suportadas pela gramática atual; prefira funções predicativas (booleanas) na `condition`.
284
+ Exemplos de JSON Logic:
285
+ - `{ "===": [{ "jsonGet": [{ "var": "payload" }, "$.user.name"] }, "Alice"] }`
286
+ - `{ "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }`
287
+ - `{ "eqIgnoreCase": [{ "var": "status" }, "ATIVO"] }`
288
+ - `{ "between": [{ "var": "amount" }, 10, 20] }`
289
+ - `{ "dateBetween": [{ "var": "createdAt" }, "2025-01-01", "2025-12-31"] }`
290
+ - `{ "containsAll": [{ "var": "tags" }, ["vip", "gold"]] }`
234
291
 
235
- Guia completo: `projects/praxis-table/docs/DSL-Extensions-Guide.md`
292
+ Guia completo: `projects/praxis-table/docs/json-logic-operators-and-helpers.md`
236
293
 
237
- #### 🎨 Efeitos (Conteúdo C)
294
+ #### 🎨 Efeitos (Conteúdo C)
238
295
 
239
- O bloco de Efeitos permite aplicar estilo e visuais quando a condição é verdadeira:
296
+ O bloco de Efeitos permite aplicar estilo e visuais quando a condição é verdadeira:
240
297
 
241
- - Toolbar de texto com ícones (negrito, itálico, sublinhado) e presets rápidos (tachado, maiúsculas/minúsculas/capitalizar, tamanho +/- e reset).
242
- - Presets de feedback com ícones (sucesso, aviso, erro, info) mantêm o rótulo via tooltip e `aria-label`.
243
- - “Posição do valor como grupo de alternância (antes / entre-1 / entre-2 / depois / oculto).
244
- - Ordem dos visuais com seletor compacto (3 mais comuns) e menu para opções extras.
245
- - Layout do compose: espaçamento, alinhamento, quebra de linha e reticências.
298
+ - Toolbar de texto com ícones (negrito, itálico, sublinhado) e presets rápidos (tachado, maiúsculas/minúsculas/capitalizar, tamanho +/- e reset).
299
+ - Presets de feedback com ícones (sucesso, aviso, erro, info) — mantêm o rótulo via tooltip e `aria-label`.
300
+ - “Posição do valor” como grupo de alternância (antes / entre-1 / entre-2 / depois / oculto).
301
+ - “Ordem dos visuais” com seletor compacto (3 mais comuns) e menu para opções extras.
302
+ - Layout do compose: espaçamento, alinhamento, quebra de linha e reticências.
246
303
 
247
304
  Dicas
248
- - Use Resetar texto para reverter efeitos de texto sem perder cor de fundo/borda.
249
- - Para acessibilidade, os grupos possuem `role="toolbar"`, tooltips e navegação por teclado consistente.
305
+ - Use “Resetar texto” para reverter efeitos de texto sem perder cor de fundo/borda.
306
+ - Para acessibilidade, os grupos possuem `role="toolbar"`, tooltips e navegação por teclado consistente.
250
307
 
251
308
  Como reverter efeitos
252
- - Reset Text remove apenas propriedades de tipografia e transformação de texto.
253
- - Limpar efeitos apaga classe e estilo livres do bloco rápido.
309
+ - “Reset Text” remove apenas propriedades de tipografia e transformação de texto.
310
+ - “Limpar efeitos” apaga classe e estilo livres do bloco rápido.
254
311
 
255
- Observação: capturas de tela antes/depois podem ser adicionadas no PR conforme necessário.
312
+ Observação: capturas de tela “antes/depois” podem ser adicionadas no PR conforme necessário.
256
313
 
257
314
  #### Relacionais (lookup)
258
315
 
259
- Campos relacionais (FK/objetos) podem ser editados no Rules Editor com busca assíncrona (typeahead) e seleção single/multiple.
316
+ Campos relacionais (FK/objetos) podem ser editados no Rules Editor com busca assíncrona (typeahead) e seleção single/multiple.
260
317
 
261
- Boas práticas
318
+ Boas práticas
262
319
  - Informe `resourcePath` (ou `endpoint`) no `FieldDefinition` para habilitar o lookup via `GenericCrudService` do host.
263
- - Defina `valueField` (chave estável, tipicamente `id`) e `displayField` (label amigável, como `name`).
320
+ - Defina `valueField` (chave estável, tipicamente `id`) e `displayField` (label amigável, como `name`).
264
321
 
265
- ## 🔎 Filtro: Atalhos para Período (DateRange)
322
+ ## 🔎 Filtro: Atalhos para Período (DateRange)
266
323
 
267
- Habilite atalhos de período no filtro dinâmico sem alterar o contrato do `praxis-filter` apenas via metadata do campo:
324
+ Habilite atalhos de período no filtro dinâmico sem alterar o contrato do `praxis-filter` — apenas via metadata do campo:
268
325
 
269
326
  ```ts
270
327
  // Em FilterConfig (ou na metadata de campos do filtro)
271
328
  {
272
329
  name: 'period',
273
- label: 'Período',
330
+ label: 'Período',
274
331
  controlType: 'dateRange',
275
332
  showShortcuts: true,
276
333
  shortcuts: ['thisMonth','lastMonth','thisYear'],
277
334
  // Opcional:
278
- // i18nShortcuts: { thisMonth: 'Este mês', lastMonth: 'Mês passado' },
335
+ // i18nShortcuts: { thisMonth: 'Este mês', lastMonth: 'Mês passado' },
279
336
  // applyOnShortcutClick: true
280
337
  }
281
338
  ```
282
- - Para múltipla seleção, use `multiple: true` no `FieldDefinition` quando aplicável.
283
- - No runtime da tabela não é necessário registrar funções JSON/data manualmente; os helpers são embutidos.
284
- - APIs com busca: suporte a um parâmetro livre de texto (por ex. `search`) facilita a experiência do autocomplete.
339
+ - Para múltipla seleção, use `multiple: true` no `FieldDefinition` quando aplicável.
340
+ - No runtime da tabela não é necessário registrar funções JSON/data manualmente; os helpers já são embutidos.
341
+ - APIs com busca: suporte a um parâmetro livre de texto (por ex. `search`) facilita a experiência do autocomplete.
285
342
 
286
343
  Exemplo de FieldDefinition (lookup)
287
344
  ```ts
@@ -293,108 +350,107 @@ const fields: FieldDefinition[] = [
293
350
  type: 'object',
294
351
  // Habilita o lookup via GenericCrudService
295
352
  resourcePath: 'customers',
296
- // Mapeia o id/label que virão do backend
353
+ // Mapeia o id/label que virão do backend
297
354
  valueField: 'id',
298
355
  displayField: 'name',
299
- // Se quiser multiseleção em todo o app
356
+ // Se quiser multiseleção em todo o app
300
357
  // multiple: true,
301
358
  },
302
359
  ];
303
360
  ```
304
361
 
305
- Operadores e DSL gerada (relacional)
306
- - `id ==` `jsonEq(customer, '$.id', 10)`
307
- - `id in` `jsonIn(customer, '$.id', [10, 20])`
308
- - `has property` `hasJsonKey(customer, '$.meta.etag')`
309
- - Condições por caminho (join simples): use `key ==` (JSON Path + valor)
362
+ Operadores relacionais em JSON Logic
363
+ - `id ==` -> `{ "jsonEq": [{ "var": "customer" }, "$.id", 10] }`
364
+ - `id in` -> `{ "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }`
365
+ - `has property` -> `{ "hasJsonKey": [{ "var": "customer" }, "$.meta.etag"] }`
366
+ - Condições por caminho (join simples): use `jsonEq/jsonIn` sobre o path necessário
310
367
 
311
368
  UI (no editor)
312
- - `id ==` (single): autocomplete + chip label [id] com ação Limpar”.
313
- - `id in` (multi): autocomplete + chips removíveis por item.
369
+ - `id ==` (single): autocomplete + chip “label [id]” com ação “Limpar”.
370
+ - `id in` (multi): autocomplete + chips removíveis por item.
314
371
  - `has property`: input do caminho (ex.: `$.meta.etag`).
315
372
 
316
373
  Formato esperado do payload (relacional)
317
374
 
318
- Para que o editor/preview e o runtime avaliem corretamente as regras relacionais, o valor do campo deve ser um objeto (ou compatível com JSON) contendo ao menos o identificador e, opcionalmente, propriedades exibidas:
375
+ Para que o editor/preview e o runtime avaliem corretamente as regras relacionais, o valor do campo deve ser um objeto (ou compatível com JSON) contendo ao menos o identificador e, opcionalmente, propriedades exibidas:
319
376
 
320
377
  ```ts
321
378
  // Exemplo de linha (row) com campo relacional "customer"
322
379
  const row = {
323
380
  id: 123,
324
381
  customer: {
325
- id: 10, // usado em id == / id in via jsonEq/jsonIn
326
- name: 'ACME', // usado para exibir label no autocomplete/chip
382
+ id: 10, // ← usado em id == / id in via jsonEq/jsonIn
383
+ name: 'ACME', // ← usado para exibir label no autocomplete/chip
327
384
  meta: { etag: 'v1' },
328
385
  },
329
386
  };
330
387
 
331
- // Regras DSL comuns
388
+ // Regras relacionais em JSON Logic
332
389
  // id ==
333
- // jsonEq(customer, '$.id', 10)
390
+ // { "jsonEq": [{ "var": "customer" }, "$.id", 10] }
334
391
  // id in
335
- // jsonIn(customer, '$.id', [10, 20])
392
+ // { "jsonIn": [{ "var": "customer" }, "$.id", [10, 20]] }
336
393
  // has property
337
- // hasJsonKey(customer, '$.meta.etag')
394
+ // { "hasJsonKey": [{ "var": "customer" }, "$.meta.etag"] }
338
395
  // caminho/valor (join simples)
339
- // jsonEq(customer, '$.name', 'ACME')
396
+ // { "jsonEq": [{ "var": "customer" }, "$.name", "ACME"] }
340
397
  ```
341
398
 
342
399
  Notas
343
- - O editor usa `displayField` (ex.: `name`) para compor o rótulo, e `valueField` (ex.: `id`) para gerar a DSL.
344
- - Se o backend devolver o relacionamento "normalizado" (ex.: `customerId` e `customerName` na mesma linha), você ainda pode expressar condições com operadores padrão (`==`, `in`) no campo numérico/literal a abordagem relacional é útil quando o payload contém o objeto.
400
+ - O editor usa `displayField` (ex.: `name`) para compor o rótulo, e `valueField` (ex.: `id`) para gerar o AST Json Logic correspondente.
401
+ - Se o backend devolver o relacionamento já "normalizado" (ex.: `customerId` e `customerName` na mesma linha), você ainda pode expressar condições com operadores padrão (`==`, `in`) no campo numérico/literal — a abordagem relacional é útil quando o payload contém o objeto.
345
402
 
346
- Onde é consumido (preview e runtime)
403
+ Onde é consumido (preview e runtime)
347
404
 
348
- - Preview/validação no Editor de Regras:
349
- - Authoring canônico manual e visual em JSON Logic: `projects/praxis-table/src/lib/rules-editor/table-rules-editor.component.ts`
405
+ - Preview/validação no Editor de Regras:
406
+ - Authoring canônico manual e visual em JSON Logic: `projects/praxis-table/src/lib/rules-editor/table-rules-editor.component.ts`
350
407
  - Runtime na Tabela (aplica `rowConditionalStyles`/`conditionalStyles`):
351
- - JSON Logic canônico + compatibilidade transitória de leitura DSL: `projects/praxis-table/src/lib/praxis-table.ts`
408
+ - JSON Logic canônico: `projects/praxis-table/src/lib/praxis-table.ts`
352
409
 
353
- Observação
354
- - JSON Logic é o contrato canônico para novas regras e para o editor de regras da tabela.
355
- - O runtime ainda mantém compatibilidade transitória para regras DSL antigas.
410
+ Observação
411
+ - JSON Logic é o contrato canônico para novas regras e para o editor de regras da tabela.
356
412
 
357
413
 
358
- ### ⚙️ Painel de Configurações
414
+ ### ⚙️ Painel de Configurações
359
415
 
360
- Para abrir o painel de configurações, habilite o modo de edição na tabela:
416
+ Para abrir o painel de configurações, habilite o modo de edição na tabela:
361
417
 
362
418
  ```html
363
419
  <praxis-table [enableCustomization]="true"></praxis-table>
364
420
  ```
365
421
 
366
- Um botão de engrenagem será exibido no canto superior direito. Ao clicar nele, o `SettingsPanel` é aberto permitindo ajustar:
422
+ Um botão de engrenagem será exibido no canto superior direito. Ao clicar nele, o `SettingsPanel` é aberto permitindo ajustar:
367
423
 
368
- - **Comportamento**: paginação, ordenação, filtros e recursos avançados.
424
+ - **Comportamento**: paginação, ordenação, filtros e recursos avançados.
369
425
  - **Colunas**: visibilidade, ordem, largura e estilo.
370
- - **Toolbar**: ações e botões da barra de ferramentas.
371
- - **Mensagens**: textos e rótulos exibidos na interface.
426
+ - **Toolbar**: ações e botões da barra de ferramentas.
427
+ - **Mensagens**: textos e rótulos exibidos na interface.
372
428
 
373
- As alterações podem ser aplicadas temporariamente com **Aplicar** ou salvas de forma persistente com **Salvar & Fechar**.
429
+ As alterações podem ser aplicadas temporariamente com **Aplicar** ou salvas de forma persistente com **Salvar & Fechar**.
374
430
 
375
- ## 🚀 Instalação
431
+ ## 🚀 Instalação
376
432
 
377
433
  ```bash
378
434
  npm install @praxisui/core @praxisui/table
379
435
  ```
380
436
 
381
- Peers necessários (instale no app host):
437
+ Peers necessários (instale no app host):
382
438
  - `@angular/core` `^20.0.0`, `@angular/common` `^20.0.0`
383
439
  - `@praxisui/core` `^0.0.1`
384
- - `@praxisui/dynamic-fields` `^0.0.1` (quando usar editores/inputs dinâmicos)
385
- - `@praxisui/dynamic-form` `^0.0.1` (quando integrar com formulários dinâmicos)
386
- - `@praxisui/settings-panel` `^0.0.1` (para painel de configuração embutido)
440
+ - `@praxisui/dynamic-fields` `^0.0.1` (quando usar editores/inputs dinâmicos)
441
+ - `@praxisui/dynamic-form` `^0.0.1` (quando integrar com formulários dinâmicos)
442
+ - `@praxisui/settings-panel` `^0.0.1` (para painel de configuração embutido)
387
443
 
388
- ## 📝 Uso Básico
444
+ ## 📝 Uso Básico
389
445
 
390
446
  ### Conectando ao Backend com `resourcePath`
391
447
 
392
- A forma mais poderosa de usar a `<praxis-table>` é conectá-la diretamente a um endpoint de API compatível com o ecossistema Praxis. Isso é feito através do input `resourcePath`.
448
+ A forma mais poderosa de usar a `<praxis-table>` é conectá-la diretamente a um endpoint de API compatível com o ecossistema Praxis. Isso é feito através do input `resourcePath`.
393
449
 
394
- Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
450
+ Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
395
451
 
396
- 1. **Busca automática de dados**: A tabela gerencia a paginação, ordenação e filtros, fazendo as requisições necessárias ao backend.
397
- 2. **Geração dinâmica de colunas**: A tabela busca os metadados (schema) do backend para gerar as colunas automaticamente, respeitando as configurações definidas no `praxis-metadata-core` (via anotação `@UISchema`).
452
+ 1. **Busca automática de dados**: A tabela gerencia a paginação, ordenação e filtros, fazendo as requisições necessárias ao backend.
453
+ 2. **Geração dinâmica de colunas**: A tabela busca os metadados (schema) do backend para gerar as colunas automaticamente, respeitando as configurações definidas no `praxis-metadata-core` (via anotação `@UISchema`).
398
454
 
399
455
  ```html
400
456
  <!-- Exemplo no template do seu componente -->
@@ -404,12 +460,12 @@ Quando `resourcePath` é fornecido, a tabela se torna "inteligente":
404
460
  Neste exemplo:
405
461
 
406
462
  - `resourcePath="human-resources/departamentos"` instrui a tabela a se comunicar com o endpoint `/api/human-resources/departamentos`.
407
- - A tabela fará requisições como `POST /api/human-resources/departamentos/filter` para obter os dados e `GET /schemas/filtered?path=/api/human-resources/departamentos/all&operation=get&schemaType=response` para obter o schema estrutural usado no bootstrap das colunas.
408
- - `enableCustomization` controla explicitamente o gate de edição visual. O default canônico agora é `false`; declare `[enableCustomization]="true"` quando o host quiser expor customização e surfaces editoriais.
463
+ - A tabela fará requisições como `POST /api/human-resources/departamentos/filter` para obter os dados e `GET /schemas/filtered?path=/api/human-resources/departamentos/all&operation=get&schemaType=response` para obter o schema estrutural usado no bootstrap das colunas.
464
+ - `enableCustomization` controla explicitamente o gate de edição visual. O default canônico agora é `false`; declare `[enableCustomization]="true"` quando o host quiser expor customização e surfaces editoriais.
409
465
 
410
466
  ### Consulta Declarativa com `queryContext`
411
467
 
412
- Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântico primário da tabela passa a ser `queryContext`.
468
+ Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântico primário da tabela passa a ser `queryContext`.
413
469
 
414
470
  ```html
415
471
  <praxis-table
@@ -424,23 +480,23 @@ Para orquestração entre widgets em `praxis-dynamic-page`, o contrato semântic
424
480
 
425
481
  Regras atuais:
426
482
 
427
- - `queryContext.filters` participa do pipeline efetivo da tabela
483
+ - `queryContext.filters` já participa do pipeline efetivo da tabela
428
484
  - `filterCriteria` continua aceito como bridge legada de compatibilidade
429
485
  - em novo authoring, examples e bindings, prefira `queryContext`
430
486
 
431
487
  ### Empty State + Quick Connect (sem `resourcePath`)
432
488
 
433
- Se a tabela for renderizada sem `resourcePath`, um cartão de "Empty State" é exibido convidando a conectar o componente a um recurso. Basta clicar em "Conectar a recurso" para abrir um painel rápido com um único campo:
489
+ Se a tabela for renderizada sem `resourcePath`, um cartão de "Empty State" é exibido convidando a conectar o componente a um recurso. Basta clicar em "Conectar a recurso" para abrir um painel rápido com um único campo:
434
490
 
435
491
  ```text
436
492
  resourcePath: ex.: human-resources/departamentos
437
493
  ```
438
494
 
439
- Ao aplicar/salvar, a `<praxis-table>` é automaticamente configurada para buscar o schema e os dados do backend. Esse fluxo evita telas em branco e simplifica o onboarding do componente em páginas novas.
495
+ Ao aplicar/salvar, a `<praxis-table>` é automaticamente configurada para buscar o schema e os dados do backend. Esse fluxo evita telas em branco e simplifica o onboarding do componente em páginas novas.
440
496
 
441
- ### Fluxo de Comunicação do `resourcePath`
497
+ ### Fluxo de Comunicação do `resourcePath`
442
498
 
443
- O diagrama abaixo ilustra como a propriedade `resourcePath` conecta o componente frontend ao backend no runtime atual da tabela. Antes de iniciar o fluxo remoto, a lib resolve o modo de dados com precedência **`resourcePath` explícito > `data` local > conexão persistida**. Quando o modo efetivo é `remote`, o bootstrap ocorre em três etapas principais: **Configurar**, **Carregar Schema estrutural** e **Buscar Dados**.
499
+ O diagrama abaixo ilustra como a propriedade `resourcePath` conecta o componente frontend ao backend no runtime atual da tabela. Antes de iniciar o fluxo remoto, a lib resolve o modo de dados com precedência **`resourcePath` explícito > `data` local > conexão persistida**. Quando o modo efetivo é `remote`, o bootstrap ocorre em três etapas principais: **Configurar**, **Carregar Schema estrutural** e **Buscar Dados**.
444
500
 
445
501
  ```mermaid
446
502
  sequenceDiagram
@@ -455,7 +511,7 @@ sequenceDiagram
455
511
 
456
512
  activate Praxis_Table
457
513
  Praxis_Table->>Praxis_Table: ngOnInit()/ngOnChanges() resolve dataMode
458
- Note over Praxis_Table: remote quando resourcePath efetivo
514
+ Note over Praxis_Table: remote quando há resourcePath efetivo
459
515
  Praxis_Table->>Crud_Service: 1. Chama crudService.configure("human-resources/departamentos")
460
516
 
461
517
  activate Crud_Service
@@ -466,7 +522,7 @@ sequenceDiagram
466
522
  Praxis_Table->>Crud_Service: Chama crudService.getSchema()
467
523
 
468
524
  activate Crud_Service
469
- Crud_Service->>Crud_Service: schemaUrl() preserva o base path canônico
525
+ Crud_Service->>Crud_Service: schemaUrl() preserva o base path canônico
470
526
  Crud_Service->>Crud_Service: Deriva path="/api/human-resources/departamentos/all"<br>operation="get", schemaType="response"
471
527
  Crud_Service->>Docs_Controller: GET /schemas/filtered?path=.../all&operation=get&schemaType=response
472
528
  deactivate Crud_Service
@@ -481,21 +537,21 @@ sequenceDiagram
481
537
  Crud_Service-->>Praxis_Table: Normaliza schema e retorna FieldDefinition[]
482
538
  deactivate Crud_Service
483
539
 
484
- Praxis_Table->>Praxis_Table: Constrói as colunas da tabela<br>a partir do schema recebido
540
+ Praxis_Table->>Praxis_Table: Constrói as colunas da tabela<br>a partir do schema recebido
485
541
 
486
542
  Praxis_Table->>Praxis_Table: 3. Chama this.fetchData()
487
543
  Praxis_Table->>Crud_Service: Chama crudService.filter(...) para buscar dados
488
544
 
489
545
  activate Crud_Service
490
- Crud_Service->>Crud_Service: getEndpointUrl('filter') constrói a URL: <br> "/api/human-resources/departamentos/filter"
491
- Crud_Service->>BE_Controller: Requisição HTTP POST para .../filter
546
+ Crud_Service->>Crud_Service: getEndpointUrl('filter') constrói a URL: <br> "/api/human-resources/departamentos/filter"
547
+ Crud_Service->>BE_Controller: Requisição HTTP POST para .../filter
492
548
  deactivate Crud_Service
493
549
 
494
550
  activate BE_Controller
495
- BE_Controller->>Abstract_Controller: Herda o método que lida com @PostMapping("/filter")
551
+ BE_Controller->>Abstract_Controller: Herda o método que lida com @PostMapping("/filter")
496
552
 
497
553
  activate Abstract_Controller
498
- Abstract_Controller->>Abstract_Controller: Processa a requisição e busca os dados
554
+ Abstract_Controller->>Abstract_Controller: Processa a requisição e busca os dados
499
555
  Abstract_Controller-->>BE_Controller: Retorna os dados
500
556
  deactivate Abstract_Controller
501
557
 
@@ -512,21 +568,21 @@ sequenceDiagram
512
568
 
513
569
  Notas importantes:
514
570
 
515
- - O host informa `resourcePath` sem o prefixo `/api`; o `GenericCrudService` resolve as URLs reais do backend a partir da configuração de API do host.
516
- - O bootstrap de schema não depende mais de uma chamada frontend para `GET /{resource}/schemas`; o runtime consome diretamente `/schemas/filtered` com `ETag`/`X-Schema-Hash`.
571
+ - O host informa `resourcePath` sem o prefixo `/api`; o `GenericCrudService` resolve as URLs reais do backend a partir da configuração de API do host.
572
+ - O bootstrap de schema não depende mais de uma chamada frontend para `GET /{resource}/schemas`; o runtime consome diretamente `/schemas/filtered` com `ETag`/`X-Schema-Hash`.
517
573
  - O `praxis-filter` acoplado acompanha o mesmo `resourcePath` em modo remoto e deriva seu schema via `/schemas/filtered?path=.../filter&operation=post&schemaType=request`.
518
- - Sem `resourcePath` efetivo, a tabela não entra nesse fluxo remoto; ela cai em `local` ou `empty` conforme a precedência canônica.
574
+ - Sem `resourcePath` efetivo, a tabela não entra nesse fluxo remoto; ela cai em `local` ou `empty` conforme a precedência canônica.
519
575
 
520
- ## ℹ️ Dicas de UX (Tabela)
576
+ ## ℹ️ Dicas de UX (Tabela)
521
577
 
522
- - Multisort: habilite em Comportamento Ordenação. No uso, mantenha Ctrl/Cmd pressionado ao clicar em múltiplas colunas.
523
- - Duplo clique na linha: configure em Comportamento Interação (habilitar e escolha a ação: editar/visualizar/personalizada).
524
- - Virtualização: habilite em Comportamento Virtualização para listas grandes (requer altura de linha previsível).
525
- - Densidade e linhas de grade: ajuste em Comportamento Aparência rápida (compacta/confortável/espaçosa; bordas horizontais/verticais).
578
+ - Multi‑sort: habilite em Comportamento → Ordenação. No uso, mantenha Ctrl/Cmd pressionado ao clicar em múltiplas colunas.
579
+ - Duplo clique na linha: configure em Comportamento → Interação (habilitar e escolha a ação: editar/visualizar/personalizada).
580
+ - Virtualização: habilite em Comportamento → Virtualização para listas grandes (requer altura de linha previsível).
581
+ - Densidade e linhas de grade: ajuste em Comportamento → Aparência rápida (compacta/confortável/espaçosa; bordas horizontais/verticais).
526
582
 
527
583
  ## Rolagem Horizontal (owner do scroll)
528
584
 
529
- Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem horizontal quando o conteúdo excede a largura do container. Isso evita cortes de conteúdo e comportamentos inconsistentes entre projetos.
585
+ Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem horizontal quando o conteúdo excede a largura do container. Isso evita cortes de conteúdo e comportamentos inconsistentes entre projetos.
530
586
 
531
587
  ### Input: `horizontalScroll`
532
588
 
@@ -534,17 +590,17 @@ Por padrão, a `<praxis-table>` agora assume a responsabilidade pela rolagem hor
534
590
  @Input() horizontalScroll: 'auto' | 'wrap' | 'none' = 'auto';
535
591
  ```
536
592
 
537
- - `auto` (padrão): a tabela cria um viewport com `overflow-x: auto` e permite que a tabela interna cresça com `width: max-content`. Quando a soma das colunas > container, aparece a barra de rolagem horizontal neste viewport.
538
- - `wrap`: permite quebra de linha nas células (libera `white-space: normal`), reduzindo a largura necessária; ideal quando você prefere minimizar a rolagem horizontal.
539
- - `none`: desabilita o comportamento interno; o host (página) deve fornecer o container com `overflow-x: auto` e as regras de largura necessárias.
593
+ - `auto` (padrão): a tabela cria um viewport com `overflow-x: auto` e permite que a tabela interna cresça com `width: max-content`. Quando a soma das colunas > container, aparece a barra de rolagem horizontal neste viewport.
594
+ - `wrap`: permite quebra de linha nas células (libera `white-space: normal`), reduzindo a largura necessária; ideal quando você prefere minimizar a rolagem horizontal.
595
+ - `none`: desabilita o comportamento interno; o host (página) deve fornecer o container com `overflow-x: auto` e as regras de largura necessárias.
540
596
 
541
597
  Exemplo:
542
598
 
543
599
  ```html
544
- <!-- Comportamento padrão (auto) -->
600
+ <!-- Comportamento padrão (auto) -->
545
601
  <praxis-table resourcePath="employees"></praxis-table>
546
602
 
547
- <!-- Reduz rolagem: permite quebra de linha nas células -->
603
+ <!-- Reduz rolagem: permite quebra de linha nas células -->
548
604
  <praxis-table resourcePath="employees" horizontalScroll="wrap"></praxis-table>
549
605
 
550
606
  <!-- Host controla o scroll horizontal -->
@@ -554,28 +610,28 @@ Exemplo:
554
610
  </div>
555
611
  ```
556
612
 
557
- ### Editor de Configuração (Settings Panel)
613
+ ### Editor de Configuração (Settings Panel)
558
614
 
559
- Na aba “Visão Geral & Comportamento”, um seletor Scroll Horizontal com as opções `Auto`, `Wrap` e `Host` (none). As alterações podem ser aplicadas (Aplicar) ou salvas (Salvar & Fechar). O valor é persistido junto com outras preferências da tabela.
615
+ Na aba “Visão Geral & Comportamento”, há um seletor “Scroll Horizontal” com as opções `Auto`, `Wrap` e `Host` (none). As alterações podem ser aplicadas (Aplicar) ou salvas (Salvar & Fechar). O valor é persistido junto com outras preferências da tabela.
560
616
 
561
617
  ### Notas
562
618
 
563
- - O caminho virtual (CDK Virtual Scroll) permanece sendo o owner da rolagem vertical; o viewport horizontal é um contêiner externo que não interfere no scroll vertical.
564
- - Cabeçalho sticky continua funcional. Teste combinações com colunas sticky/virt para seu caso.
619
+ - O caminho virtual (CDK Virtual Scroll) permanece sendo o owner da rolagem vertical; o viewport horizontal é um contêiner externo que não interfere no scroll vertical.
620
+ - Cabeçalho sticky continua funcional. Teste combinações com colunas sticky/virt para seu caso.
565
621
  - Para grids alternativos (ex.: Kendo), as mesmas regras de `max-content`/`min-width: 100%` se aplicam ao elemento de tabela interno.
566
622
 
567
- ## Virtualização (CDK)
623
+ ## Virtualização (CDK)
568
624
 
569
- Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são renderizadas com `cdk-virtual-scroll-viewport` (cabeçalho permanece igual).
625
+ Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são renderizadas com `cdk-virtual-scroll-viewport` (cabeçalho permanece igual).
570
626
 
571
627
  - Propriedades:
572
- - `itemHeight`: altura da linha (px); padrão 44.
628
+ - `itemHeight`: altura da linha (px); padrão 44.
573
629
  - `bufferSize`: itens adicionais de buffer.
574
- - `minContainerHeight`: altura mínima do viewport (px ou CSS, ex.: `320` ou `50vh`).
575
- - `strategy`: `fixed` | `dynamic` (atual uso visual não altera lógica de medição).
576
- - Observação: sticky/pinned em colunas pode ter limitações em conjunto com virtual scroll (mantido sob feature flag; caminho não‑virtual preservado como fallback).
630
+ - `minContainerHeight`: altura mínima do viewport (px ou CSS, ex.: `320` ou `50vh`).
631
+ - `strategy`: `fixed` | `dynamic` (atual uso visual não altera lógica de medição).
632
+ - Observação: sticky/pinned em colunas pode ter limitações em conjunto com virtual scroll (mantido sob feature flag; caminho não‑virtual preservado como fallback).
577
633
 
578
- ## Paginação (posição/estilo)
634
+ ## Paginação (posição/estilo)
579
635
 
580
636
  ### Concept Usage
581
637
 
@@ -587,16 +643,16 @@ Quando `behavior.virtualization.enabled` estiver ativo, as linhas da tabela são
587
643
  - `behavior.pagination.position`: `top` | `bottom` | `both`.
588
644
  - `behavior.pagination.style`: `default` | `compact` (aplica classe de estilo no paginator).
589
645
 
590
- Nota sobre estratégia (client vs server)
591
- - Se `behavior.pagination.strategy` não estiver definido, a tabela assume `server` automaticamente quando `resourcePath` (dados remotos). Caso contrário, usa `client`.
646
+ Nota sobre estratégia (client vs server)
647
+ - Se `behavior.pagination.strategy` não estiver definido, a tabela assume `server` automaticamente quando há `resourcePath` (dados remotos). Caso contrário, usa `client`.
592
648
  - O mesmo vale para `behavior.sorting.strategy`.
593
649
 
594
650
  ## Duplo clique na linha
595
651
 
596
- Ative em Comportamento Interação.
652
+ Ative em Comportamento → Interação.
597
653
 
598
654
  - Output: `rowDoubleClick` com payload `{ action: string; row: any }`.
599
- - Ação: `edit` | `view` | `custom` (quando `custom`, use `customAction` no Behavior para definir o identificador).
655
+ - Ação: `edit` | `view` | `custom` (quando `custom`, use `customAction` no Behavior para definir o identificador).
600
656
 
601
657
  Exemplo de uso (template do host):
602
658
 
@@ -615,16 +671,16 @@ onRowDoubleClick(evt: { action: string; row: any }) {
615
671
  } else if (evt.action === 'view') {
616
672
  // abrir detalhe somente leitura
617
673
  } else {
618
- // ação customizada
674
+ // ação customizada
619
675
  }
620
676
  }
621
677
  ```
622
678
 
623
- ## Ordenação inicial (defaultSort)
679
+ ## Ordenação inicial (defaultSort)
624
680
 
625
681
  - Configure em `behavior.sorting.defaultSort`.
626
- - Aceita objeto único (coluna/direção) ou array para multisort.
627
- - Status runtime atual: `behavior.sorting.multiSort` está **schema-only** (apenas 1 critério efetivo em runtime).
682
+ - Aceita objeto único (coluna/direção) ou array para multi‑sort.
683
+ - Status runtime atual: `behavior.sorting.multiSort` está **schema-only** (apenas 1 critério efetivo em runtime).
628
684
 
629
685
  Exemplos:
630
686
 
@@ -649,20 +705,20 @@ sorting: {
649
705
  }
650
706
  ```
651
707
 
652
- Observação: quando informado, o defaultSort é aplicado na carga inicial se não houver estado de ordenação ativo.
653
- Observação enterprise: para evitar ambiguidade de contrato, mantenha `multiSort: false` no runtime atual. Se um array for informado em `defaultSort`, trate como payload de compatibilidade/roadmap e valide no host como single-sort efetivo.
708
+ Observação: quando informado, o defaultSort é aplicado na carga inicial se não houver estado de ordenação ativo.
709
+ Observação enterprise: para evitar ambiguidade de contrato, mantenha `multiSort: false` no runtime atual. Se um array for informado em `defaultSort`, trate como payload de compatibilidade/roadmap e valide no host como single-sort efetivo.
654
710
 
655
- ### Roadmap / migração de multiSort
711
+ ### Roadmap / migração de multiSort
656
712
 
657
713
  - Curto prazo: `multiSort` segue schema-only no runtime.
658
- - Recomendação de migração: desenhar integrações com fallback para ordenação única (`column` + `direction`).
659
- - Planejamento: quando multi-sort runtime for implementado, publicar release note com guia de ativação gradual (feature-flag + validação de payload legado).
714
+ - Recomendação de migração: desenhar integrações com fallback para ordenação única (`column` + `direction`).
715
+ - Planejamento: quando multi-sort runtime for implementado, publicar release note com guia de ativação gradual (feature-flag + validação de payload legado).
660
716
 
661
- ## Coluna de ações (sticky)
717
+ ## Coluna de ações (sticky)
662
718
 
663
- Nota: por padrão a coluna de ações vem desabilitada. Habilite explicitamente em `actions.row.enabled` e defina as ações desejadas.
719
+ Nota: por padrão a coluna de ações vem desabilitada. Habilite explicitamente em `actions.row.enabled` e defina as ações desejadas.
664
720
 
665
- - Fixe a coluna de ações no início/fim configurando `actions.row.sticky`:
721
+ - Fixe a coluna de ações no início/fim configurando `actions.row.sticky`:
666
722
 
667
723
  ```ts
668
724
  actions: {
@@ -675,11 +731,11 @@ actions: {
675
731
  }
676
732
  ```
677
733
 
678
- Observação: em modo virtualizado, sticky pode ter limitações dependendo do layout.
734
+ Observação: em modo virtualizado, sticky pode ter limitações dependendo do layout.
679
735
 
680
736
  ## Colunas de dados (sticky)
681
737
 
682
- Fixe colunas específicas no início/fim usando `columns[].sticky`:
738
+ Fixe colunas específicas no início/fim usando `columns[].sticky`:
683
739
 
684
740
  ```ts
685
741
  columns: [
@@ -690,28 +746,28 @@ columns: [
690
746
  ```
691
747
 
692
748
  - Valores aceitos: `true` | `'start'` | `'end'`.
693
- - `true` equivale a `'start'` (fixa no início).
749
+ - `true` equivale a `'start'` (fixa no início).
694
750
  - Dica: combine com `width` para evitar jitter de layout.
695
751
 
696
752
  Onde configurar no Editor Visual:
697
753
 
698
- - Aba Colunas grupo “Posição Fixa”: escolha entre Nenhum / Início / Fim.
699
- - Para a coluna de ações, use a aba Barra de Ferramentas & Ações” grupo Coluna de Ações” Fixar coluna de ações”.
754
+ - Aba “Colunas” → grupo “Posição Fixa”: escolha entre Nenhum / Início / Fim.
755
+ - Para a coluna de ações, use a aba “Barra de Ferramentas & Ações” → grupo “Coluna de Ações” → “Fixar coluna de ações”.
700
756
 
701
- ## 🔒 Verificação de Schema (ETag) e Notificações (somente em customização)
757
+ ## 🔒 Verificação de Schema (ETag) e Notificações (somente em customização)
702
758
 
703
- Quando existe uma configuração salva (colunas presentes), a tabela não baixa o schema bruto do servidor para montar as colunas. Em vez disso, valida se uma nova versão do schema usando ETag/If-None-Match. Notificações são exibidas somente quando o modo de customização está ativo (`enableCustomization = true`).
759
+ Quando já existe uma configuração salva (colunas presentes), a tabela não baixa o schema bruto do servidor para montar as colunas. Em vez disso, valida se há uma nova versão do schema usando ETag/If-None-Match. Notificações são exibidas somente quando o modo de customização está ativo (`enableCustomization = true`).
704
760
 
705
761
  ### Comportamento
706
762
 
707
763
  - Primeira vez (sem colunas):
708
764
  - Baixa o schema (200), gera as colunas e persiste `config.meta` (incluindo `schemaId`, `serverHash`, `lastVerifiedAt`).
709
- - Próximas vezes (colunas existentes):
710
- - Faz uma verificação leve em `/schemas/filtered` com `If-None-Match: "<serverHash>"`.
711
- - 304 Not Modified: atualiza `config.meta.lastVerifiedAt` e segue usando a configuração local.
712
- - 200 OK (hash mudou): atualiza `config.meta.serverHash/lastVerifiedAt`, marca estado `schemaOutdated=true` e (em modo de customização) exibe aviso e CTA para reconciliar. O schema bruto não é usado/armazenado nesta etapa.
765
+ - Próximas vezes (colunas já existentes):
766
+ - Faz uma verificação leve em `/schemas/filtered` com `If-None-Match: "<serverHash>"`.
767
+ - 304 Not Modified: atualiza `config.meta.lastVerifiedAt` e segue usando a configuração local.
768
+ - 200 OK (hash mudou): atualiza `config.meta.serverHash/lastVerifiedAt`, marca estado `schemaOutdated=true` e (em modo de customização) exibe aviso e CTA para reconciliar. O schema bruto não é usado/armazenado nesta etapa.
713
769
 
714
- ### Diagrama: Verificação de Schema via ETag
770
+ ### Diagrama: Verificação de Schema via ETag
715
771
 
716
772
  ```mermaid
717
773
  sequenceDiagram
@@ -728,15 +784,15 @@ sequenceDiagram
728
784
  PT->>PT: Persiste config + meta (serverHash, lastVerifiedAt)
729
785
  end
730
786
 
731
- opt Próximas vezes (colunas existentes)
787
+ opt Próximas vezes (colunas existentes)
732
788
  PT->>API: GET /schemas/filtered?path=... (If-None-Match: "<serverHash>")
733
- alt Igual (sem mudanças)
789
+ alt Igual (sem mudanças)
734
790
  API-->>PT: 304 Not Modified (sem body)
735
791
  PT->>PT: Atualiza lastVerifiedAt; segue usando config
736
792
  else Diferente (mudou)
737
793
  API-->>PT: 200 OK (com ETag/X-Schema-Hash)
738
794
  PT->>PT: Atualiza serverHash + lastVerifiedAt; schemaOutdated=true
739
- Note over PT: Em customização: mostrar banner/snackbar + badge e CTA Reconciliar
795
+ Note over PT: Em customização: mostrar banner/snackbar + badge e CTA “Reconciliar”
740
796
  end
741
797
  end
742
798
  ```
@@ -749,30 +805,30 @@ sequenceDiagram
749
805
  - `autoOpenSettingsOnOutdated: boolean = false`
750
806
  - Outputs:
751
807
  - `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; trigger?: string; tableId?: string }`
752
- - Emitido tanto na verificação leve (304/200) quanto no bootstrap do schema (primeira carga via `loadSchema()`).
808
+ - Emitido tanto na verificação leve (304/200) quanto no bootstrap do schema (primeira carga via `loadSchema()`).
753
809
  - `metadataChange: { trigger: string; meta: any; tableId?: string }`
754
- - Emitido quando `config.meta` é atualizado (ex.: após bootstrap ou verificação ETag). Útil para sincronizar sidebars/bridges de metadados.
810
+ - Emitido quando `config.meta` é atualizado (ex.: após bootstrap ou verificação ETag). Útil para sincronizar sidebars/bridges de metadados.
755
811
 
756
812
  ### Fallback Global (opcional)
757
813
 
758
- - Quando os inputs do widget permanecem com os valores padrão da biblioteca e não overrides locais equivalentes, a Tabela aplica como último fallback as preferências globais lidas via `GlobalConfigService.getSchemaPrefsGlobal()`.
759
- - Cadeia de precedência (inalterada): `@Inputs (widget)` Prefs do widget Prefs da página Prefs globais Defaults.
760
- - Não persistência no widget a partir das globais; o fallback é aplicado somente em memória.
814
+ - Quando os inputs do widget permanecem com os valores padrão da biblioteca e não há overrides locais equivalentes, a Tabela aplica como último fallback as preferências globais lidas via `GlobalConfigService.getSchemaPrefsGlobal()`.
815
+ - Cadeia de precedência (inalterada): `@Inputs (widget)` → Prefs do widget → Prefs da página → Prefs globais → Defaults.
816
+ - Não há persistência no widget a partir das globais; o fallback é aplicado somente em memória.
761
817
 
762
- ### Persistência por hash (ConfigStorage)
818
+ ### Persistência por hash (ConfigStorage)
763
819
 
764
- - `schemaIgnore:{tableId}:{serverHash}` ignora avisos para este hash.
765
- - `schemaSnooze:{tableId}:{serverHash}` ISODate até quando não avisar (lembrar depois).
766
- - `schemaNotified:{tableId}:{serverHash}` evita snackbar duplicado.
820
+ - `schemaIgnore:{tableId}:{serverHash}` → ignora avisos para este hash.
821
+ - `schemaSnooze:{tableId}:{serverHash}` → ISODate até quando não avisar (lembrar depois).
822
+ - `schemaNotified:{tableId}:{serverHash}` → evita snackbar duplicado.
767
823
 
768
824
  ### UX
769
825
 
770
- - Banner inline (acima da tabela) quando `schemaOutdated=true`, com ações:
771
- - Reconciliar (abre Configurações)
826
+ - Banner inline (acima da tabela) quando `schemaOutdated=true`, com ações:
827
+ - Reconciliar (abre Configurações)
772
828
  - Lembrar depois (snooze)
773
829
  - Ignorar (silenciar para este hash)
774
- - Snackbar opcional (uma vez por hash) com ação Reconciliar”.
775
- - Badge “!” na engrenagem com tooltip contextual: Schema do servidor mudou Reconciliar”.
830
+ - Snackbar opcional (uma vez por hash) com ação “Reconciliar”.
831
+ - Badge “!” na engrenagem com tooltip contextual: “Schema do servidor mudou — Reconciliar”.
776
832
 
777
833
  ### Exemplo de uso
778
834
 
@@ -798,56 +854,56 @@ onSchemaStatus(ev: { outdated: boolean; serverHash?: string; lastVerifiedAt?: st
798
854
 
799
855
  ### Notas
800
856
 
801
- - A verificação leve não grava nem usa o schema bruto quando `config.columns` existe.
802
- - Em ambientes sem customização (`enableCustomization=false`), não notificações visuais; ainda assim `schemaStatusChange` é emitido e `config.meta.lastVerifiedAt` atualizado.
857
+ - A verificação leve não grava nem usa o schema bruto quando `config.columns` já existe.
858
+ - Em ambientes sem customização (`enableCustomization=false`), não há notificações visuais; ainda assim `schemaStatusChange` é emitido e `config.meta.lastVerifiedAt` atualizado.
803
859
 
804
- ## Filtro Avançado (PraxisFilter)
860
+ ## Filtro Avançado (PraxisFilter)
805
861
 
806
- ### Boas práticas para estabilidade
862
+ ### Boas práticas para estabilidade
807
863
 
808
- - Evite literais em bindings para o carregador dinâmico:
809
- - Não use `[fields]="[pinnedFieldMeta]"`; prefira um array estável como `pinnedFieldMetaArray` atualizado apenas quando o metadata mudar.
810
- - Reutilize `FormGroup` quando possível. Se precisar trocar o `FormGroup` sem mudar os campos, deixe o `DynamicFieldLoader` reatribuir os controles (rebind-only) em vez de recriar componentes.
811
- - Evite recriar arrays/objetos desnecessariamente em `ngOnChanges`/`ngAfterViewInit`. Prefira atualizar valores (`setValue`, `patchValue`) e manter referências estáveis.
812
- - Observers (Resize/Mutation): atualize `overlayOrigin` e largura apenas quando houver mudanças reais; isso evita loops de CD.
864
+ - Evite literais em bindings para o carregador dinâmico:
865
+ - Não use `[fields]="[pinnedFieldMeta]"`; prefira um array estável como `pinnedFieldMetaArray` atualizado apenas quando o metadata mudar.
866
+ - Reutilize `FormGroup` quando possível. Se precisar trocar o `FormGroup` sem mudar os campos, deixe o `DynamicFieldLoader` reatribuir os controles (rebind-only) em vez de recriar componentes.
867
+ - Evite recriar arrays/objetos desnecessariamente em `ngOnChanges`/`ngAfterViewInit`. Prefira atualizar valores (`setValue`, `patchValue`) e manter referências estáveis.
868
+ - Observers (Resize/Mutation): atualize `overlayOrigin` e largura apenas quando houver mudanças reais; isso evita loops de CD.
813
869
 
814
- ### Diagnóstico e Logs
870
+ ### Diagnóstico e Logs
815
871
 
816
- - O `DynamicFieldLoader` possui logs de diagnóstico que podem ser habilitados em tempo de execução definindo `window.__PRAXIS_DEBUG_DFL__ = true` no console do navegador.
872
+ - O `DynamicFieldLoader` possui logs de diagnóstico que podem ser habilitados em tempo de execução definindo `window.__PRAXIS_DEBUG_DFL__ = true` no console do navegador.
817
873
  - Quando desabilitado (default), o carregador reduz a verbosidade de logs.
818
874
 
819
875
  ### Comportamento do carregador (v20+)
820
876
 
821
- - Guardas internas evitam re-renderizações desnecessárias:
822
- - Se o snapshot do conteúdo dos campos (nome + controlType) for idêntico e o `FormGroup` não tiver mudado, a renderização é ignorada.
823
- - Se apenas o `FormGroup` mudou (mesmo snapshot de campos), os controles são reatribuídos aos componentes existentes (rebind-only), preservando o estado visual e evitando recriações.
877
+ - Guardas internas evitam re-renderizações desnecessárias:
878
+ - Se o snapshot do conteúdo dos campos (nome + controlType) for idêntico e o `FormGroup` não tiver mudado, a renderização é ignorada.
879
+ - Se apenas o `FormGroup` mudou (mesmo snapshot de campos), os controles são reatribuídos aos componentes existentes (rebind-only), preservando o estado visual e evitando recriações.
824
880
 
825
881
  ### Testes
826
882
 
827
- - testes cobrindo:
828
- - Reatribuição de `FormControl` em troca de `FormGroup` (select/multiselect/autocomplete).
829
- - Ignorar re-render quando apenas a referência do array muda mas o conteúdo é igual.
883
+ - Há testes cobrindo:
884
+ - Reatribuição de `FormControl` em troca de `FormGroup` (select/multiselect/autocomplete).
885
+ - Ignorar re-render quando apenas a referência do array muda mas o conteúdo é igual.
830
886
  - Recriar componentes quando `controlType` muda.
831
887
 
832
888
  ### Fluxo de Schema e Metadados
833
889
 
834
890
  - O `PraxisFilter` busca schema do DTO de filtro via `/schemas/filtered` com ETag/If-None-Match
835
891
  e emite `metaChanged` com `{ schemaId, serverHash, context }`.
836
- - O schema é normalizado e `advancedConfig.metadata` é preenchido para auditoria/telemetria.
837
- - Detalhes: `projects/praxis-core/docs/schema-flow.md` (canônico) e `docs/schemas/fluxo-schema.md` (resumo operacional) para cliente/caching, 200/304 e reconciliadores Form/Filter.
892
+ - O schema é normalizado e `advancedConfig.metadata` é preenchido para auditoria/telemetria.
893
+ - Detalhes: `projects/praxis-core/docs/schema-flow.md` (canônico) e `docs/schemas/fluxo-schema.md` (resumo operacional) para cliente/caching, 200/304 e reconciliadores Form/Filter.
838
894
 
839
- ### Resolução da chave primária (idField)
895
+ ### Resolução da chave primária (idField)
840
896
 
841
897
  - O backend anota o schema com `x-ui.resource.idField` (e `idFieldValid`) via `/schemas/filtered`.
842
- - A tabela adota o campo identificador automaticamente com a seguinte precedência:
843
- - `@Input() idField` `crudContext.idField` `config.meta.idField` (persistido) `GenericCrudService.getResourceIdField()` (derivado do schema) `'id'`.
844
- - Se `config.meta.idField` divergir do servidor, o componente alerta o usuário e mantém o valor do TableConfig até reconciliação.
845
- - A resolução ocorre no `loadSchema()` e também é considerada em tempo de execução para evitar corridas.
846
- - Para recursos cuja PK não é `id`, defina `getIdFieldName()` no controller backend correspondente.
898
+ - A tabela adota o campo identificador automaticamente com a seguinte precedência:
899
+ - `@Input() idField` → `crudContext.idField` → `config.meta.idField` (persistido) → `GenericCrudService.getResourceIdField()` (derivado do schema) → `'id'`.
900
+ - Se `config.meta.idField` divergir do servidor, o componente alerta o usuário e mantém o valor do TableConfig até reconciliação.
901
+ - A resolução ocorre no `loadSchema()` e também é considerada em tempo de execução para evitar corridas.
902
+ - Para recursos cuja PK não é `id`, defina `getIdFieldName()` no controller backend correspondente.
847
903
 
848
904
  ### Diagramas
849
905
 
850
- Fluxo (Grid): adoção de schema e idField
906
+ Fluxo (Grid): adoção de schema e idField
851
907
 
852
908
  ```mermaid
853
909
  sequenceDiagram
@@ -867,7 +923,7 @@ sequenceDiagram
867
923
  PT->>PT: construir colunas e renderizar
868
924
  ```
869
925
 
870
- Fluxo (Delete): resolução do identificador
926
+ Fluxo (Delete): resolução do identificador
871
927
 
872
928
  ```mermaid
873
929
  sequenceDiagram
@@ -876,7 +932,7 @@ sequenceDiagram
876
932
  participant GS as GenericCrudService
877
933
  participant API as Backend
878
934
 
879
- PT->>PT: key = getIdField() (precedência)
935
+ PT->>PT: key = getIdField() (precedência)
880
936
  PT->>PT: id = getNestedPropertyValue(row, key)
881
937
  PT->>GS: delete(id)
882
938
  GS->>API: DELETE {resource}/{id}
@@ -885,17 +941,17 @@ sequenceDiagram
885
941
  PT->>PT: fetchData() em modo remoto
886
942
  ```
887
943
 
888
- ### Troubleshooting rápido (idField)
944
+ ### Troubleshooting rápido (idField)
889
945
 
890
- - A ação delete falhou por ID ausente: verifique se o schema contém `x-ui.resource.idField` e se a coluna correspondente existe no dataset.
891
- - O ID está em outra propriedade: defina `@Input() idField` ou `crudContext.idField` temporariamente; ajuste o backend com `getIdFieldName()` para persistir o comportamento.
892
- - Cache 304 sem idField aplicado: confirme que o serviço recebeu o body pelo menos uma vez (200) e que `GenericCrudService.getResourceIdField()` retorna o valor esperado.
946
+ - A ação delete falhou por ID ausente: verifique se o schema contém `x-ui.resource.idField` e se a coluna correspondente existe no dataset.
947
+ - O ID está em outra propriedade: defina `@Input() idField` ou `crudContext.idField` temporariamente; ajuste o backend com `getIdFieldName()` para persistir o comportamento.
948
+ - Cache 304 sem idField aplicado: confirme que o serviço recebeu o body pelo menos uma vez (200) e que `GenericCrudService.getResourceIdField()` retorna o valor esperado.
893
949
 
894
950
  ### Uso com Dados Locais (Client-Side)
895
951
 
896
- Se você precisar fornecer os dados manualmente (por exemplo, de uma fonte que não é uma API Praxis), pode usar o input `[data]` e omitir o `resourcePath`.
897
- Importante: o modo local está protegido por feature flag e exige `behavior.localDataMode.enabled = true` (default é `false`).
898
- Quando a flag está ativa, as operações de paginação, ordenação e filtro são executadas no lado do cliente.
952
+ Se você precisar fornecer os dados manualmente (por exemplo, de uma fonte que não é uma API Praxis), pode usar o input `[data]` e omitir o `resourcePath`.
953
+ Importante: o modo local está protegido por feature flag e exige `behavior.localDataMode.enabled = true` (default é `false`).
954
+ Quando a flag está ativa, as operações de paginação, ordenação e filtro são executadas no lado do cliente.
899
955
 
900
956
  ```typescript
901
957
  import { PraxisTable } from "@praxisui/table";
@@ -908,7 +964,7 @@ import { TableConfig } from "@praxisui/core";
908
964
  template: ` <praxis-table [config]="tableConfig" [data]="employees"> </praxis-table> `,
909
965
  })
910
966
  export class ExampleComponent {
911
- // Configuração de colunas e comportamento é obrigatória neste modo
967
+ // Configuração de colunas e comportamento é obrigatória neste modo
912
968
  tableConfig: TableConfig = {
913
969
  columns: [
914
970
  { field: "id", header: "ID", type: "number" },
@@ -919,57 +975,57 @@ export class ExampleComponent {
919
975
  pagination: { enabled: true, pageSize: 10 },
920
976
  sorting: { enabled: true },
921
977
  filtering: { enabled: true },
922
- localDataMode: { enabled: true }, // obrigatório para fluxo local oficial
978
+ localDataMode: { enabled: true }, // obrigatório para fluxo local oficial
923
979
  },
924
980
  };
925
981
 
926
982
  employees = [
927
- { id: 1, name: "João Silva", email: "joao@empresa.com" },
983
+ { id: 1, name: "João Silva", email: "joao@empresa.com" },
928
984
  { id: 2, name: "Maria Santos", email: "maria@empresa.com" },
929
985
  // ... mais dados
930
986
  ];
931
987
  }
932
988
  ```
933
989
 
934
- ## ⚙️ Fluxo de Paginação e Filtros (Server-Side)
990
+ ## ⚙️ Fluxo de Paginação e Filtros (Server-Side)
935
991
 
936
- Quando a `<praxis-table>` opera com `resourcePath`, o runtime resolve o modo remoto e passa a delegar paginação, ordenação e filtros ao backend. Isso reduz tráfego, preserva a semântica do DTO de filtro e mantém o banco como fonte de verdade para `WHERE`, `ORDER BY`, `LIMIT` e `OFFSET`.
992
+ Quando a `<praxis-table>` opera com `resourcePath`, o runtime resolve o modo remoto e passa a delegar paginação, ordenação e filtros ao backend. Isso reduz tráfego, preserva a semântica do DTO de filtro e mantém o banco como fonte de verdade para `WHERE`, `ORDER BY`, `LIMIT` e `OFFSET`.
937
993
 
938
- Importante: se você não configurar explicitamente as estratégias de paginação/ordenação no `TableConfig`, a tabela resolve automaticamente como `server` quando `resourcePath`. Se preferir operar no cliente, defina `behavior.pagination.strategy = 'client'` e/ou `behavior.sorting.strategy = 'client'` conscientemente.
994
+ Importante: se você não configurar explicitamente as estratégias de paginação/ordenação no `TableConfig`, a tabela resolve automaticamente como `server` quando há `resourcePath`. Se preferir operar no cliente, defina `behavior.pagination.strategy = 'client'` e/ou `behavior.sorting.strategy = 'client'` conscientemente.
939
995
 
940
- ### Versão Pedagógica de Alto Nível
996
+ ### Versão Pedagógica de Alto Nível
941
997
 
942
- Esta é a leitura adequada para documentação pública e landing pages.
998
+ Esta é a leitura adequada para documentação pública e landing pages.
943
999
 
944
1000
  ```mermaid
945
1001
  sequenceDiagram
946
- participant Usuario as Usuário
1002
+ participant Usuario as Usuário
947
1003
  participant Tabela as praxis-table
948
1004
  participant Frontend as GenericCrudService
949
1005
  participant Backend as API Praxis
950
1006
  participant Banco as Banco de Dados
951
1007
 
952
- Usuario->>Tabela: muda página, ordena ou aplica filtro
953
- Tabela->>Tabela: consolida filterCriteria + paginação + sort
1008
+ Usuario->>Tabela: muda página, ordena ou aplica filtro
1009
+ Tabela->>Tabela: consolida filterCriteria + paginação + sort
954
1010
  Tabela->>Frontend: filter(criteria, pageable)
955
1011
  Frontend->>Backend: POST /api/.../filter?page&size&sort
956
1012
  Backend->>Banco: executa consulta filtrada e paginada
957
- Banco-->>Backend: retorna página de resultados
958
- Backend-->>Frontend: responde com página de DTOs
1013
+ Banco-->>Backend: retorna página de resultados
1014
+ Backend-->>Frontend: responde com página de DTOs
959
1015
  Frontend-->>Tabela: entrega Page<T>
960
- Tabela->>Tabela: atualiza linhas, paginação e estado visual
1016
+ Tabela->>Tabela: atualiza linhas, paginação e estado visual
961
1017
  ```
962
1018
 
963
- Leitura pedagógica:
1019
+ Leitura pedagógica:
964
1020
 
965
- 1. **A tabela captura a intenção do usuário**: página, ordenação e filtros viram estado de consulta.
966
- 2. **O frontend envia o DTO de filtro para o endpoint canônico**: corpo JSON para filtro, query params para paginação e sort.
967
- 3. **O backend aplica o filtro no conjunto remoto**: não é a UI que filtra localmente em modo remoto.
968
- 4. **O resultado volta paginado**: a tabela apenas renderiza a página retornada pela API.
1021
+ 1. **A tabela captura a intenção do usuário**: página, ordenação e filtros viram estado de consulta.
1022
+ 2. **O frontend envia o DTO de filtro para o endpoint canônico**: corpo JSON para filtro, query params para paginação e sort.
1023
+ 3. **O backend aplica o filtro no conjunto remoto**: não é a UI que filtra localmente em modo remoto.
1024
+ 4. **O resultado volta já paginado**: a tabela apenas renderiza a página retornada pela API.
969
1025
 
970
- ### Versão Detalhada e Fiel ao Runtime Atual
1026
+ ### Versão Detalhada e Fiel ao Runtime Atual
971
1027
 
972
- Esta versão documenta o fluxo real do `praxis-table`, do `praxis-filter`, do `GenericCrudService` e do `praxis-metadata-starter`.
1028
+ Esta versão documenta o fluxo real do `praxis-table`, do `praxis-filter`, do `GenericCrudService` e do `praxis-metadata-starter`.
973
1029
 
974
1030
  ```mermaid
975
1031
  sequenceDiagram
@@ -997,12 +1053,12 @@ sequenceDiagram
997
1053
  Crud-->>Filtro: metadata de filtro
998
1054
  end
999
1055
 
1000
- alt paginação
1056
+ alt paginação
1001
1057
  Tabela->>Tabela: onPageChange(pageIndex, pageSize)
1002
- else ordenação
1058
+ else ordenação
1003
1059
  Tabela->>Tabela: onSortChange(active, direction)
1004
1060
  Tabela->>Tabela: reseta pageIndex = 0
1005
- else filtro avançado
1061
+ else filtro avançado
1006
1062
  Filtro-->>Tabela: submit/change/clear
1007
1063
  Tabela->>Tabela: onAdvancedFilterSubmit(criteria)
1008
1064
  end
@@ -1015,7 +1071,7 @@ sequenceDiagram
1015
1071
  Crud->>Controller: POST /filter?page&size&sort
1016
1072
  Note over Crud,Controller: body = filterCriteria JSON
1017
1073
 
1018
- Controller->>Controller: page,size,sort de query params
1074
+ Controller->>Controller: lê page,size,sort de query params
1019
1075
  Controller->>Controller: PageableBuilder.from(page,size,sort,...)
1020
1076
  Controller->>Service: filterMappedWithIncludeIds(filterDTO, pageable, includeIds, toDto)
1021
1077
 
@@ -1035,56 +1091,56 @@ sequenceDiagram
1035
1091
 
1036
1092
  ### Pontos-Chave do Fluxo Real
1037
1093
 
1038
- 1. **`resourcePath` não dispara fetch**: em modo remoto, a tabela primeiro configura o `GenericCrudService` e pode carregar schema antes da primeira busca.
1039
- 2. **O filtro avançado vive em `praxis-filter`**: os eventos reais são `submit`, `change` e `clear`, que a tabela recebe como `onAdvancedFilterSubmit`, `onAdvancedFilterChange` e `onAdvancedFilterClear`.
1040
- 3. **O controller não recebe `Pageable` pronto do Spring nesse endpoint**: ele reconstrói o `Pageable` a partir de `page`, `size` e `sort`.
1094
+ 1. **`resourcePath` não dispara só fetch**: em modo remoto, a tabela primeiro configura o `GenericCrudService` e pode carregar schema antes da primeira busca.
1095
+ 2. **O filtro avançado vive em `praxis-filter`**: os eventos reais são `submit`, `change` e `clear`, que a tabela recebe como `onAdvancedFilterSubmit`, `onAdvancedFilterChange` e `onAdvancedFilterClear`.
1096
+ 3. **O controller não recebe `Pageable` pronto do Spring nesse endpoint**: ele reconstrói o `Pageable` a partir de `page`, `size` e `sort`.
1041
1097
  4. **O backend do starter responde com `RestApiResponse<Page<...>>`**: o `GenericCrudService` faz `unwrapPageResponse(...)` para entregar `Page<T>` ao runtime da tabela.
1042
- 5. **A coluna ordenada pode mapear para `sortField`**: o `active` da UI não é necessariamente o campo final enviado ao backend.
1098
+ 5. **A coluna ordenada pode mapear para `sortField`**: o `active` da UI não é necessariamente o campo final enviado ao backend.
1043
1099
 
1044
- ## 🎨 Edição Visual da Tabela: O Poder do Low-Code
1100
+ ## 🎨 Edição Visual da Tabela: O Poder do Low-Code
1045
1101
 
1046
- A `<praxis-table>` vem com um poderoso editor de configuração visual que permite personalizar quase todos os aspectos da sua tabela em tempo real, sem escrever uma única linha de código. O runtime expõe esse editor somente quando o host ativa `[enableCustomization]="true"`.
1102
+ A `<praxis-table>` vem com um poderoso editor de configuração visual que permite personalizar quase todos os aspectos da sua tabela em tempo real, sem escrever uma única linha de código. O runtime expõe esse editor somente quando o host ativa `[enableCustomization]="true"`.
1047
1103
 
1048
- A seguir, veja os principais recursos que você pode configurar visualmente:
1104
+ A seguir, veja os principais recursos que você pode configurar visualmente:
1049
1105
 
1050
1106
  ### 1. Gerenciamento de Colunas
1051
1107
 
1052
- Controle total sobre as colunas da sua tabela. Dentro do editor, você pode:
1108
+ Controle total sobre as colunas da sua tabela. Dentro do editor, você pode:
1053
1109
 
1054
- - **Reordenar com Arrastar e Soltar:** Simplesmente clique e arraste uma coluna para a posição desejada.
1055
- - **Alterar Visibilidade:** Use a caixa de seleção ao lado de cada coluna para mostrá-la ou ocultá-la instantaneamente.
1056
- - **Editar Títulos e Largura:** Clique em uma coluna para abrir suas propriedades e altere o texto do cabeçalho, defina uma largura fixa (ex: `150px`) ou deixe-a automática.
1110
+ - **Reordenar com Arrastar e Soltar:** Simplesmente clique e arraste uma coluna para a posição desejada.
1111
+ - **Alterar Visibilidade:** Use a caixa de seleção ao lado de cada coluna para mostrá-la ou ocultá-la instantaneamente.
1112
+ - **Editar Títulos e Largura:** Clique em uma coluna para abrir suas propriedades e altere o texto do cabeçalho, defina uma largura fixa (ex: `150px`) ou deixe-a automática.
1057
1113
 
1058
- ### 2. Transformação de Dados Sem Código
1114
+ ### 2. Transformação de Dados Sem Código
1059
1115
 
1060
- Converta dados brutos em informações claras e formatadas para o usuário.
1116
+ Converta dados brutos em informações claras e formatadas para o usuário.
1061
1117
 
1062
- - **Formatação Automática:** Selecione uma coluna e escolha seu "Tipo de Dado". Se escolher `Moeda`, os valores serão formatados como `R$ 1.234,56`. Se escolher `Data`, você pode selecionar formatos como `dd/MM/yyyy` ou `25 de janeiro de 2025`.
1063
- - **Mapeamento de Valores:** Transforme códigos e valores brutos em texto legível. Na seção "Mapeamento de Valores", você pode definir visualmente que o valor `true` deve ser exibido como "Ativo" e `false` como "Inativo", ou que o código `1` significa "Pendente" e `2` significa "Aprovado".
1118
+ - **Formatação Automática:** Selecione uma coluna e escolha seu "Tipo de Dado". Se escolher `Moeda`, os valores serão formatados como `R$ 1.234,56`. Se escolher `Data`, você pode selecionar formatos como `dd/MM/yyyy` ou `25 de janeiro de 2025`.
1119
+ - **Mapeamento de Valores:** Transforme códigos e valores brutos em texto legível. Na seção "Mapeamento de Valores", você pode definir visualmente que o valor `true` deve ser exibido como "Ativo" e `false` como "Inativo", ou que o código `1` significa "Pendente" e `2` significa "Aprovado".
1064
1120
 
1065
- ### 3. Colunas Calculadas com Fórmulas Visuais
1121
+ ### 3. Colunas Calculadas com Fórmulas Visuais
1066
1122
 
1067
1123
  Crie novas colunas dinamicamente a partir de dados existentes, sem precisar programar.
1068
1124
 
1069
- - **Concatenar Texto:** Crie uma "Coluna Calculada", escolha a fórmula "Concatenar" e selecione os campos `nome` e `sobrenome` para criar uma coluna "Nome Completo".
1070
- - **Realizar Operações Matemáticas:** Use a fórmula "Operação Matemática" para criar uma coluna que calcula `preço * quantidade`.
1071
- - **Criar Valores Condicionais (IF/ELSE):** Com a fórmula "Condicional", você pode criar uma coluna "Nível de Risco" que exibe "Alto" se o `valor` for maior que 1000, e "Baixo" caso contrário.
1125
+ - **Concatenar Texto:** Crie uma "Coluna Calculada", escolha a fórmula "Concatenar" e selecione os campos `nome` e `sobrenome` para criar uma coluna "Nome Completo".
1126
+ - **Realizar Operações Matemáticas:** Use a fórmula "Operação Matemática" para criar uma coluna que calcula `preço * quantidade`.
1127
+ - **Criar Valores Condicionais (IF/ELSE):** Com a fórmula "Condicional", você pode criar uma coluna "Nível de Risco" que exibe "Alto" se o `valor` for maior que 1000, e "Baixo" caso contrário.
1072
1128
 
1073
- ### 4. Formatação Condicional (Regras de Estilo)
1129
+ ### 4. Formatação Condicional (Regras de Estilo)
1074
1130
 
1075
- Destaque informações importantes aplicando estilos que mudam com base nos dados da linha.
1131
+ Destaque informações importantes aplicando estilos que mudam com base nos dados da linha.
1076
1132
 
1077
- - **Crie Regras Visuais:** Na seção de "Formatação Condicional", crie uma nova regra.
1078
- - **Defina a Condição:** Estabeleça a condição, por exemplo: "Quando a coluna `status` tiver o valor igual a 'Urgente'".
1079
- - **Aplique o Estilo:** Use seletores de cor para definir que, quando a condição for verdadeira, a cor de fundo da célula ou da linha inteira deve se tornar vermelha e o texto, branco.
1133
+ - **Crie Regras Visuais:** Na seção de "Formatação Condicional", crie uma nova regra.
1134
+ - **Defina a Condição:** Estabeleça a condição, por exemplo: "Quando a coluna `status` tiver o valor igual a 'Urgente'".
1135
+ - **Aplique o Estilo:** Use seletores de cor para definir que, quando a condição for verdadeira, a cor de fundo da célula ou da linha inteira deve se tornar vermelha e o texto, branco.
1080
1136
 
1081
1137
  ### 5. Comportamentos da Tabela
1082
1138
 
1083
- Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba "Comportamento", você pode:
1139
+ Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba "Comportamento", você pode:
1084
1140
 
1085
- - **Ativar/Desativar Paginação:** Com um único interruptor, ative a paginação para tabelas com muitos dados e defina quantos itens exibir por página.
1086
- - **Controlar Ordenação e Filtros:** Habilite a capacidade dos usuários de ordenar colunas e filtrar os dados com simples caixas de seleção.
1087
- - **Gerenciar Seleção de Linhas:** Permita que os usuários selecionem uma ou várias linhas para realizar ações em lote.
1141
+ - **Ativar/Desativar Paginação:** Com um único interruptor, ative a paginação para tabelas com muitos dados e defina quantos itens exibir por página.
1142
+ - **Controlar Ordenação e Filtros:** Habilite a capacidade dos usuários de ordenar colunas e filtrar os dados com simples caixas de seleção.
1143
+ - **Gerenciar Seleção de Linhas:** Permita que os usuários selecionem uma ou várias linhas para realizar ações em lote.
1088
1144
 
1089
1145
  ### Editores Especializados
1090
1146
 
@@ -1093,7 +1149,7 @@ Habilite e configure as funcionalidades centrais da tabela com um clique. Na aba
1093
1149
  ```typescript
1094
1150
  import { BehaviorConfigEditorComponent } from '@praxisui/table';
1095
1151
 
1096
- // Usar como componente standalone para edição específica
1152
+ // Usar como componente standalone para edição específica
1097
1153
  <behavior-config-editor
1098
1154
  [config]="tableConfig"
1099
1155
  (configChange)="onBehaviorChange($event)">
@@ -1112,9 +1168,9 @@ import { ColumnsConfigEditorComponent } from '@praxisui/table';
1112
1168
  </columns-config-editor>
1113
1169
  ```
1114
1170
 
1115
- ## 🔧 Configuração Avançada
1171
+ ## 🔧 Configuração Avançada
1116
1172
 
1117
- ### Performance com Virtualização
1173
+ ### Performance com Virtualização
1118
1174
 
1119
1175
  ```typescript
1120
1176
  const highVolumeConfig: TableConfig = {
@@ -1162,7 +1218,7 @@ const accessibleConfig: TableConfig = {
1162
1218
  };
1163
1219
  ```
1164
1220
 
1165
- ### Aparência Customizada
1221
+ ### Aparência Customizada
1166
1222
 
1167
1223
  ```typescript
1168
1224
  const styledConfig: TableConfig = {
@@ -1195,7 +1251,7 @@ const styledConfig: TableConfig = {
1195
1251
  };
1196
1252
  ```
1197
1253
 
1198
- ## 🎯 Event Handling
1254
+ ## 🎯 Event Handling
1199
1255
 
1200
1256
  ### Eventos da Tabela
1201
1257
 
@@ -1213,7 +1269,7 @@ const styledConfig: TableConfig = {
1213
1269
  </praxis-table>
1214
1270
  ```
1215
1271
 
1216
- ### Implementação dos Handlers
1272
+ ### Implementação dos Handlers
1217
1273
 
1218
1274
  ```typescript
1219
1275
  export class MyComponent {
@@ -1240,25 +1296,25 @@ export class MyComponent {
1240
1296
  }
1241
1297
  ```
1242
1298
 
1243
- ## 🛠️ Utilitários e Helpers
1299
+ ## 🛠️ Utilitários e Helpers
1244
1300
 
1245
1301
  ### Helper Functions
1246
1302
 
1247
1303
  ```typescript
1248
1304
  import { createDefaultTableConfig, isValidTableConfig, cloneTableConfig, mergeTableConfigs } from "@praxisui/core";
1249
1305
 
1250
- // Criar configuração padrão
1306
+ // Criar configuração padrão
1251
1307
  const defaultConfig = createDefaultTableConfig();
1252
1308
 
1253
- // Validar configuração
1309
+ // Validar configuração
1254
1310
  if (isValidTableConfig(myConfig)) {
1255
- // Configuração válida
1311
+ // Configuração válida
1256
1312
  }
1257
1313
 
1258
- // Clonar configuração
1314
+ // Clonar configuração
1259
1315
  const clonedConfig = cloneTableConfig(originalConfig);
1260
1316
 
1261
- // Merge configurações
1317
+ // Merge configurações
1262
1318
  const mergedConfig = mergeTableConfigs(baseConfig, overrides);
1263
1319
  ```
1264
1320
 
@@ -1272,10 +1328,10 @@ export class MyComponent {
1272
1328
  constructor(private configService: TableConfigService) {}
1273
1329
 
1274
1330
  ngOnInit() {
1275
- // Usar serviço para gerenciar configuração
1331
+ // Usar serviço para gerenciar configuração
1276
1332
  this.configService.setConfig(this.tableConfig);
1277
1333
 
1278
- // Verificar recursos disponíveis
1334
+ // Verificar recursos disponíveis
1279
1335
  // No runtime atual, multiSort permanece schema-only.
1280
1336
  const hasMultiSort = false;
1281
1337
  const hasBulkActions = this.configService.isFeatureEnabled('bulkActions');
@@ -1283,7 +1339,7 @@ export class MyComponent {
1283
1339
  }
1284
1340
  ```
1285
1341
 
1286
- ## 🧪 Testes
1342
+ ## 🧪 Testes
1287
1343
 
1288
1344
  ### Unit Tests
1289
1345
 
@@ -1322,11 +1378,11 @@ describe("PraxisTable", () => {
1322
1378
  });
1323
1379
  ```
1324
1380
 
1325
- ## 📋 Migration Guide
1381
+ ## 📋 Migration Guide
1326
1382
 
1327
- ### Migração da Arquitetura V1/V2
1383
+ ### Migração da Arquitetura V1/V2
1328
1384
 
1329
- Se você estava usando as versões anteriores com dual architecture, aqui estão as principais mudanças:
1385
+ Se você estava usando as versões anteriores com dual architecture, aqui estão as principais mudanças:
1330
1386
 
1331
1387
  #### Imports Atualizados
1332
1388
 
@@ -1338,14 +1394,14 @@ import { TableConfigV1, TableConfigV2, TableConfigUnified } from "@praxisui/core
1338
1394
  import { TableConfig } from "@praxisui/core";
1339
1395
  ```
1340
1396
 
1341
- #### Serviços Removidos
1397
+ #### Serviços Removidos
1342
1398
 
1343
1399
  ```typescript
1344
1400
  // Antes
1345
1401
  import { TableConfigAdapterService } from "@praxisui/table";
1346
1402
 
1347
- // Depois - Não mais necessário
1348
- // Uso direto da configuração
1403
+ // Depois - Não mais necessário
1404
+ // Uso direto da configuração
1349
1405
  ```
1350
1406
 
1351
1407
  #### Tipos Simplificados
@@ -1360,29 +1416,29 @@ config: TableConfig;
1360
1416
 
1361
1417
  ### Breaking Changes
1362
1418
 
1363
- 1. **TableConfigAdapterService**: Removido - uso direto da configuração
1419
+ 1. **TableConfigAdapterService**: Removido - uso direto da configuração
1364
1420
  2. **TableConfigMigrationService**: Simplificado - funcionalidade integrada
1365
1421
  3. **TableConfigUnified**: Renomeado para `TableConfig`
1366
1422
 
1367
- ## 🔍 Troubleshooting
1423
+ ## 🔍 Troubleshooting
1368
1424
 
1369
1425
  ### Problemas Comuns
1370
1426
 
1371
- #### Configuração não está funcionando
1427
+ #### Configuração não está funcionando
1372
1428
 
1373
1429
  ```typescript
1374
- // Verificar se a configuração é válida
1430
+ // Verificar se a configuração é válida
1375
1431
  import { isValidTableConfig } from "@praxisui/core";
1376
1432
 
1377
1433
  if (!isValidTableConfig(myConfig)) {
1378
- console.error("Configuração inválida:", myConfig);
1434
+ console.error("Configuração inválida:", myConfig);
1379
1435
  }
1380
1436
  ```
1381
1437
 
1382
1438
  #### Performance Issues
1383
1439
 
1384
1440
  ```typescript
1385
- // Habilitar virtualização para grandes datasets
1441
+ // Habilitar virtualização para grandes datasets
1386
1442
  const config: TableConfig = {
1387
1443
  // ...
1388
1444
  performance: {
@@ -1398,7 +1454,7 @@ const config: TableConfig = {
1398
1454
  #### Acessibilidade
1399
1455
 
1400
1456
  ```typescript
1401
- // Garantir que acessibilidade está habilitada
1457
+ // Garantir que acessibilidade está habilitada
1402
1458
  const config: TableConfig = {
1403
1459
  // ...
1404
1460
  accessibility: {
@@ -1408,35 +1464,35 @@ const config: TableConfig = {
1408
1464
  };
1409
1465
  ```
1410
1466
 
1411
- ## 📚 API Reference
1467
+ ## 📚 API Reference
1412
1468
 
1413
1469
  ### Interfaces Principais
1414
1470
 
1415
1471
  #### TableConfig
1416
1472
 
1417
- Interface principal para configuração da tabela.
1473
+ Interface principal para configuração da tabela.
1418
1474
 
1419
1475
  #### ColumnDefinition
1420
1476
 
1421
- Define configuração individual de colunas.
1477
+ Define configuração individual de colunas.
1422
1478
 
1423
1479
  #### TableBehaviorConfig
1424
1480
 
1425
- Configurações de comportamento (paginação, ordenação, etc.).
1481
+ Configurações de comportamento (paginação, ordenação, etc.).
1426
1482
 
1427
1483
  #### TableAppearanceConfig
1428
1484
 
1429
- Configurações de aparência visual.
1485
+ Configurações de aparência visual.
1430
1486
 
1431
- Para documentação completa da API, consulte `projects/praxis-core/README.md`.
1487
+ Para documentação completa da API, consulte `projects/praxis-core/README.md`.
1432
1488
 
1433
- ## 🤝 Contribuição
1489
+ ## 🤝 Contribuição
1434
1490
 
1435
1491
  ### Como Contribuir
1436
1492
 
1437
1493
  1. Fork o projeto
1438
1494
  2. Crie branch para feature (`git checkout -b feature/nova-funcionalidade`)
1439
- 3. Commit mudanças (`git commit -m 'Add: nova funcionalidade'`)
1495
+ 3. Commit mudanças (`git commit -m 'Add: nova funcionalidade'`)
1440
1496
  4. Push para branch (`git push origin feature/nova-funcionalidade`)
1441
1497
  5. Abra Pull Request
1442
1498
 
@@ -1444,12 +1500,12 @@ Para documentação completa da API, consulte `projects/praxis-core/README.md`.
1444
1500
 
1445
1501
  - Seguir Angular Style Guide
1446
1502
  - Adicionar testes para novas features
1447
- - Manter documentação atualizada
1503
+ - Manter documentação atualizada
1448
1504
  - Usar TypeScript strict mode
1449
1505
 
1450
- ## 🔍 Exemplo de Integração com PraxisFilter
1506
+ ## 🔍 Exemplo de Integração com PraxisFilter
1451
1507
 
1452
- O `PraxisFilter` pode ser acoplado à barra de ferramentas da tabela. O exemplo abaixo mostra a busca de pessoas por CPF e status.
1508
+ O `PraxisFilter` pode ser acoplado à barra de ferramentas da tabela. O exemplo abaixo mostra a busca de pessoas por CPF e status.
1453
1509
 
1454
1510
  ```html
1455
1511
  <praxis-filter [resourcePath]="'pessoas'" [formId]="'pessoas-filter'" [persistenceKey]="'pessoas-filter-v1'" [alwaysVisibleFields]="['status']" (requestSearch)="onFilter($event)"></praxis-filter> <praxis-table [data]="tableData"></praxis-table>
@@ -1464,16 +1520,16 @@ onFilter(dto: any) {
1464
1520
  }
1465
1521
  ```
1466
1522
 
1467
- ### ⚙️ Configuração do Filtro
1523
+ ### ⚙️ Configuração do Filtro
1468
1524
 
1469
- O `PraxisFilter` pode ser configurado por inputs/JSON de configuração. O atalho
1470
- visual por ícone de engrenagem não é exposto por padrão na tabela/demo.
1471
- Quando necessário, também é possível abrir o painel programaticamente via
1472
- `openSettings()`. Nesse painel é possível ajustar:
1525
+ O `PraxisFilter` pode ser configurado por inputs/JSON de configuração. O atalho
1526
+ visual por ícone de engrenagem não é exposto por padrão na tabela/demo.
1527
+ Quando necessário, também é possível abrir o painel programaticamente via
1528
+ `openSettings()`. Nesse painel é possível ajustar:
1473
1529
 
1474
- - **alwaysVisibleFields** campos que permanecem sempre visíveis
1475
- - **alwaysVisibleFieldMetadataOverrides** patch de metadata por campo sempre visível (controle, clearButton, inlineAutoSize etc.)
1476
- - **showAdvanced** define se a seção avançada inicia aberta
1530
+ - **alwaysVisibleFields** – campos que permanecem sempre visíveis
1531
+ - **alwaysVisibleFieldMetadataOverrides** – patch de metadata por campo sempre visível (controle, clearButton, inlineAutoSize etc.)
1532
+ - **showAdvanced** – define se a seção avançada inicia aberta
1477
1533
 
1478
1534
  ```ts
1479
1535
  @ViewChild(PraxisFilter) filter!: PraxisFilter;
@@ -1483,100 +1539,100 @@ abrirConfiguracoes() {
1483
1539
  }
1484
1540
  ```
1485
1541
 
1486
- Ao aplicar ou salvar, as escolhas são validadas contra os metadados
1542
+ Ao aplicar ou salvar, as escolhas são validadas contra os metadados
1487
1543
  do **DTO de filtro** (schema de `POST /{resource}/filter`). Campos ausentes
1488
- no DTO não são aplicados em `alwaysVisibleFields`.
1489
- O componente exibe uma barra de progresso durante o processo de persistência e
1490
- mensagens de sucesso ou erro via _snack bar_, garantindo uma experiência
1544
+ no DTO não são aplicados em `alwaysVisibleFields`.
1545
+ O componente exibe uma barra de progresso durante o processo de persistência e
1546
+ mensagens de sucesso ou erro via _snack bar_, garantindo uma experiência
1491
1547
  consistente.
1492
1548
 
1493
- ### 🔖 Miniguia: Atalhos do Filtro (tags)
1549
+ ### 🔖 Mini‑guia: Atalhos do Filtro (tags)
1494
1550
 
1495
- Atalhos são chips que guardam um conjunto de filtros (DTO) para reuso rápido.
1551
+ Atalhos são “chips” que guardam um conjunto de filtros (DTO) para reuso rápido.
1496
1552
 
1497
1553
  - Criar/Salvar
1498
- - Modal (padrão): o host do diálogo exibe o botão quando `allowSaveTags === true`.
1499
- - Gaveta (Drawer): o Adapter recebe `allowSaveTags?`, `i18nSaveAsShortcut?` e `onSaveShortcut?` (opcionais). O host deve exibir o botão e chamar `onSaveShortcut(clean({ ...initialDto, ...lastValue }))`.
1500
- - O DTO é limpo antes de persistir (remove `'' | null | undefined`).
1554
+ - Modal (padrão): o host do diálogo exibe o botão quando `allowSaveTags === true`.
1555
+ - Gaveta (Drawer): o Adapter recebe `allowSaveTags?`, `i18nSaveAsShortcut?` e `onSaveShortcut?` (opcionais). O host deve exibir o botão e chamar `onSaveShortcut(clean({ ...initialDto, ...lastValue }))`.
1556
+ - O DTO é limpo antes de persistir (remove `'' | null | undefined`).
1501
1557
  - Aplicar
1502
1558
  - Clique/Enter no chip aplica imediatamente `tag.patch` (substitui o estado atual), emite `submit` e persiste.
1503
- - O chip ativo é destacado (cor/borda + ícone de check) quando o DTO atual é igual ao patch do atalho.
1559
+ - O chip ativo é destacado (cor/borda + ícone de “check”) quando o DTO atual é igual ao patch do atalho.
1504
1560
  - Editar/Renomear
1505
- - Apenas atalhos do usuário exibem ícone de lápis. Predefinidos mostram ícone de cadeado (somente leitura).
1561
+ - Apenas atalhos do usuário exibem ícone de lápis. Predefinidos mostram ícone de “cadeado” (somente leitura).
1506
1562
  - Excluir (com Undo)
1507
- - Exclusão remove imediatamente o atalho do usuário e exibe snackbar Atalho removido com ação Desfazer quando `confirmTagDelete === true`.
1508
- - Ao clicar em Desfazer”, o atalho é restaurado na mesma posição e os eventos são reemitidos.
1563
+ - Exclusão remove imediatamente o atalho do usuário e exibe snackbar “Atalho removido” com ação “Desfazer” quando `confirmTagDelete === true`.
1564
+ - Ao clicar em “Desfazer”, o atalho é restaurado na mesma posição e os eventos são reemitidos.
1509
1565
  - i18n
1510
- - Chaves úteis: `saveAsShortcut`, `renameShortcut`, `removeShortcut`, `shortcutSaved`, `shortcutRemoved`, `undo`, `readonlyShortcut`.
1566
+ - Chaves úteis: `saveAsShortcut`, `renameShortcut`, `removeShortcut`, `shortcutSaved`, `shortcutRemoved`, `undo`, `readonlyShortcut`.
1511
1567
 
1512
- Veja também: `docs/host-crud-integration.md` (guia operacional host) e `projects/praxis-crud/docs/host-crud-runtime-and-openmode.md` (contrato técnico canônico) para detalhes do contrato do Adapter.
1568
+ Veja também: `docs/host-crud-integration.md` (guia operacional host) e `projects/praxis-crud/docs/host-crud-runtime-and-openmode.md` (contrato técnico canônico) para detalhes do contrato do Adapter.
1513
1569
 
1514
1570
  ### Novos Inputs/Outputs (PraxisFilter)
1515
1571
 
1516
1572
  - Inputs (efetivos apenas quando `enableCustomization = true`):
1517
- - `enableCustomization: boolean` habilita o gate de customização para notificações de schema.
1518
- - `notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'` seleciona como o runtime publica avisos de drift quando a política operacional estiver habilitada.
1519
- - `snoozeMs: number = 86400000` tempo de soneca para avisos (ms).
1520
- - `autoOpenSettingsOnOutdated: boolean = false` abre Configurações ao detectar schema desatualizado.
1573
+ - `enableCustomization: boolean` — habilita o gate de customização para notificações de schema.
1574
+ - `notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'` — seleciona como o runtime publica avisos de drift quando a política operacional estiver habilitada.
1575
+ - `snoozeMs: number = 86400000` — tempo de soneca para avisos (ms).
1576
+ - `autoOpenSettingsOnOutdated: boolean = false` — abre Configurações ao detectar schema desatualizado.
1521
1577
  - Output:
1522
- - `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; tableId?: string }` emitido após verificação leve (304/200).
1578
+ - `schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; tableId?: string }` — emitido após verificação leve (304/200).
1523
1579
 
1524
1580
  #### Fallback Global (opcional)
1525
1581
 
1526
- - Quando os inputs do componente permanecem com os valores padrão e não overrides locais, o Filter utiliza como último fallback as preferências globais via `GlobalConfigService.getSchemaPrefsGlobal()`.
1527
- - Cadeia de precedência (inalterada): `@Inputs (widget)` Prefs do widget Prefs da página Prefs globais Defaults.
1528
- - O fallback global não é persistido no componente; serve apenas para defaults em memória.
1582
+ - Quando os inputs do componente permanecem com os valores padrão e não há overrides locais, o Filter utiliza como último fallback as preferências globais via `GlobalConfigService.getSchemaPrefsGlobal()`.
1583
+ - Cadeia de precedência (inalterada): `@Inputs (widget)` → Prefs do widget → Prefs da página → Prefs globais → Defaults.
1584
+ - O fallback global não é persistido no componente; serve apenas para defaults em memória.
1529
1585
 
1530
- Notas rápidas (Flow ETag no Filter):
1531
- - Verificação leve sempre no init (sem baixar o corpo): usa ETag/If-None-Match em `/schemas/filtered` (path=`.../filter`, operation=`post`, schemaType=`request`, `includeInternalSchemas=true`).
1586
+ Notas rápidas (Flow ETag no Filter):
1587
+ - Verificação leve sempre no init (sem baixar o corpo): usa ETag/If-None-Match em `/schemas/filtered` (path=`.../filter`, operation=`post`, schemaType=`request`, `includeInternalSchemas=true`).
1532
1588
  - 304: atualiza `lastVerifiedAt`; emite `schemaStatusChange(outdated=false)`.
1533
- - 200: atualiza `serverHash/lastVerifiedAt`; marca `outdated=true` apenas quando em customização; não aplica o schema automaticamente.
1534
- - O corpo do schema é baixado apenas quando necessário para renderização (ex.: `alwaysVisibleFields` ou ao abrir o painel Avançado).
1589
+ - 200: atualiza `serverHash/lastVerifiedAt`; marca `outdated=true` apenas quando em customização; não aplica o schema automaticamente.
1590
+ - O corpo do schema é baixado apenas quando necessário para renderização (ex.: `alwaysVisibleFields` ou ao abrir o painel Avançado).
1535
1591
 
1536
- ## Formatação de Colunas (format)
1592
+ ## Formatação de Colunas (format)
1537
1593
 
1538
- Cada coluna pode declarar `type` e uma string de formatação `format` consumida pelo `DataFormattingService`. Os tipos suportados são: `string`, `number`, `currency`, `percentage`, `date`, `datetime`, `time`, `boolean`, `custom`.
1594
+ Cada coluna pode declarar `type` e uma string de formatação `format` consumida pelo `DataFormattingService`. Os tipos suportados são: `string`, `number`, `currency`, `percentage`, `date`, `datetime`, `time`, `boolean`, `custom`.
1539
1595
 
1540
1596
  Regra geral:
1541
- - `format` explícito continua com precedência máxima.
1542
- - Para `number`, `currency`, `percentage`, `date`, `datetime` e `time`, a tabela também consegue derivar formatação básica a partir de `type + config.localization`, mesmo quando `format` estiver ausente.
1543
- - `string`, `boolean` e `custom` continuam conservadores; nesses casos, use `format` explícito quando precisar de transformação.
1597
+ - `format` explícito continua com precedência máxima.
1598
+ - Para `number`, `currency`, `percentage`, `date`, `datetime` e `time`, a tabela também consegue derivar formatação básica a partir de `type + config.localization`, mesmo quando `format` estiver ausente.
1599
+ - `string`, `boolean` e `custom` continuam conservadores; nesses casos, use `format` explícito quando precisar de transformação.
1544
1600
 
1545
1601
  Nota de plataforma:
1546
- - o contrato público da tabela continua sendo `column.type + config.localization + format`.
1547
- - a tabela converge internamente para a semântica canônica horizontal do core, mas não expõe `valuePresentation` como bloco público de configuração de coluna.
1602
+ - o contrato público da tabela continua sendo `column.type + config.localization + format`.
1603
+ - a tabela converge internamente para a semântica canônica horizontal do core, mas não expõe `valuePresentation` como bloco público de configuração de coluna.
1548
1604
 
1549
- Tipos e padrões de `format`:
1605
+ Tipos e padrões de `format`:
1550
1606
  - number (DecimalPipe)
1551
- - Padrões: `minInt.minFrac-maxFrac`
1607
+ - Padrões: `minInt.minFrac-maxFrac`
1552
1608
  - Exemplos: `1.0-0`, `1.2-2`, `1.0-3|nosep` (remove separador de milhar)
1553
1609
  - currency (CurrencyPipe)
1554
1610
  - Sintaxe: `CURRENCY|DISPLAY|DECIMALS[|nosep]`
1555
1611
  - Exemplos: `BRL|symbol|2`, `USD|code|0`, `EUR|symbol|2|nosep`
1556
1612
  - percentage (PercentPipe/DecimalPipe)
1557
1613
  - Sem multiplicador: `1.0-0` (PercentPipe)
1558
- - Multiplicar por 100: `1.1-1|x100` (DecimalPipe×100 + `%`)
1614
+ - Multiplicar por 100: `1.1-1|x100` (DecimalPipe×100 + `%`)
1559
1615
  - date (DatePipe)
1560
1616
  - Tokens Angular: `shortDate`, `mediumDate`, `longDate`, `fullDate`, `short`, `shortTime`
1561
- - Padrões customizados: `dd/MM/yyyy`, `yyyy-MM-dd`, `dd/MM/yyyy HH:mm`
1562
- - string (transformações + truncamento)
1617
+ - Padrões customizados: `dd/MM/yyyy`, `yyyy-MM-dd`, `dd/MM/yyyy HH:mm`
1618
+ - string (transformações + truncamento)
1563
1619
  - Transform: `uppercase` | `lowercase` | `titlecase` | `capitalize` | `none`
1564
1620
  - Transform + truncar: `<transform>|truncate|<max>|<suffix>`
1565
1621
  - Exemplos: `uppercase|truncate|50|...`, `titlecase`
1566
- - boolean (pré-definidos ou custom)
1622
+ - boolean (pré-definidos ou custom)
1567
1623
  - Presets: `true-false` | `yes-no` | `active-inactive` | `on-off` | `enabled-disabled`
1568
1624
  - Custom: `custom|Verdadeiro|Falso`
1569
1625
 
1570
1626
  Exemplos de ColumnDefinition:
1571
1627
  ```ts
1572
- { field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: 'Salário' }
1628
+ { field: 'salario', type: 'currency', format: 'BRL|symbol|2', header: 'Salário' }
1573
1629
  { field: 'desconto', type: 'percentage', format: '1.1-1|x100', header: 'Desconto' }
1574
1630
  { field: 'criadoEm', type: 'date', format: 'dd/MM/yyyy', header: 'Criado em' }
1575
- { field: 'nome', type: 'string', format: 'titlecase|truncate|32|…', header: 'Nome' }
1631
+ { field: 'nome', type: 'string', format: 'titlecase|truncate|32|…', header: 'Nome' }
1576
1632
  { field: 'ativo', type: 'boolean', format: 'yes-no', header: 'Ativo' }
1577
1633
  ```
1578
1634
 
1579
- Exemplos com defaults implícitos por `type + localization`:
1635
+ Exemplos com defaults implícitos por `type + localization`:
1580
1636
  ```ts
1581
1637
  {
1582
1638
  localization: {
@@ -1586,22 +1642,22 @@ Exemplos com defaults implícitos por `type + localization`:
1586
1642
  number: { decimalSeparator: ',', thousandsSeparator: '.', defaultPrecision: 2, negativeSign: '-', negativeSignPosition: 'before' },
1587
1643
  },
1588
1644
  columns: [
1589
- { field: 'salario', type: 'currency', header: 'Salário' },
1645
+ { field: 'salario', type: 'currency', header: 'Salário' },
1590
1646
  { field: 'criadoEm', type: 'date', header: 'Criado em' },
1591
1647
  { field: 'taxa', type: 'percentage', header: 'Taxa' },
1592
1648
  ],
1593
1649
  }
1594
1650
  ```
1595
1651
 
1596
- Observações:
1597
- - `|nosep` remove separadores de milhar da saída formatada.
1598
- - Para datas inválidas ou valores não numéricos, o serviço retorna o valor original (com aviso no console).
1599
- - Colunas com renderizador `custom` não passam por formatação automática.
1600
- - Precedência de locale para formatação: `config.localization.locale` -> `LOCALE_ID` do host.
1601
- - Quando `config.localization.currency` estiver presente, a tabela usa esse bloco como override para código, símbolo, posição, espaçamento e precisão da moeda.
1652
+ Observações:
1653
+ - `|nosep` remove separadores de milhar da saída formatada.
1654
+ - Para datas inválidas ou valores não numéricos, o serviço retorna o valor original (com aviso no console).
1655
+ - Colunas com renderizador `custom` não passam por formatação automática.
1656
+ - Precedência de locale para formatação: `config.localization.locale` -> `LOCALE_ID` do host.
1657
+ - Quando `config.localization.currency` estiver presente, a tabela usa esse bloco como override para código, símbolo, posição, espaçamento e precisão da moeda.
1602
1658
  - Quando `config.localization.number` estiver presente, a tabela respeita `decimalSeparator`, `thousandsSeparator`, `defaultPrecision`, `negativeSign` e `negativeSignPosition` em number/currency/percentage.
1603
1659
 
1604
- Exemplos práticos no workspace (rotas):
1660
+ Exemplos práticos no workspace (rotas):
1605
1661
  - Regras Visuais (Simples): `/table-rules-simple`
1606
1662
  - Regras Visuais (Complexas): `/table-rules-complex`
1607
1663
 
@@ -1642,22 +1698,22 @@ A11y, seguranca e performance:
1642
1698
  - URL da imagem sanitizada (bloqueia esquemas perigosos)
1643
1699
  - imagem com `loading=\"lazy\"`
1644
1700
 
1645
- ## 📊 Roadmap
1701
+ ## 📊 Roadmap
1646
1702
 
1647
- ### Próximas Versões
1703
+ ### Próximas Versões
1648
1704
 
1649
- - Arquitetura unificada (v2.0.0)
1650
- - 🔄 Enhanced mobile support (v2.1.0)
1651
- - 📋 Advanced export options (v2.2.0)
1652
- - 🎨 Theme customization (v2.3.0)
1705
+ - ✅ Arquitetura unificada (v2.0.0)
1706
+ - 🔄 Enhanced mobile support (v2.1.0)
1707
+ - 📋 Advanced export options (v2.2.0)
1708
+ - 🎨 Theme customization (v2.3.0)
1653
1709
 
1654
- ## 📄 Licença
1710
+ ## 📄 Licença
1655
1711
 
1656
- Apache-2.0 consulte `LICENSE` na raiz do workspace para detalhes.
1712
+ Apache-2.0 — consulte `LICENSE` na raiz do workspace para detalhes.
1657
1713
 
1658
1714
  ---
1659
1715
 
1660
1716
  **Parte do Praxis UI Workspace**
1661
- **Versão**: 2.0.0 (Unified Architecture)
1717
+ **Versão**: 2.0.0 (Unified Architecture)
1662
1718
  **Compatibilidade**: Angular 18+
1663
1719