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