praxis-table
Este documento e a referencia canonica da API JSON de praxis-table.
Summary
- Tipo documental: API reference canonica de contrato JSON.
- Evidencia canonica permanece governada no frontmatter para auditoria interna, sem expor paths na publicacao.
- Objetivo operacional: consulta rapida, auditavel e deterministica sob pressao.
- Resumo funcional herdado: Referencia canonica da API JSON do
praxis-table.
Authoring contract
- O contrato primario de autoria do
praxis-tableeTableAuthoringDocument(kind: "praxis.table.editor"). TableAuthoringDocumentencapsulaconfig+bindingse e o formato correto para editor visual, editor JSON, playground e fluxos de IA.TableConfigcontinua sendo a projeção canonica de runtime consumida pela tabela apos normalizacao e apply plan.meta.schemaIdemeta.serverHashdevem ser tratados como snapshot persistido de reconciliacao, nao como fonte primaria do runtime.- Em contexto de
praxis-crud, o authoring canonico deCrudMetadatapertence a@praxisui/crud, mesmo que o ponto visual de entrada continue sendo o icone da tabela. - A superficie
crud-integration-editorda tabela existe apenas para overrides operacionais de runtime e nao deve ser tratada como editor canonico do documento CRUD.
Scope and positioning
- Escopo: contrato JSON publico e limites de comportamento observavel.
- Fora de escopo: tutorial de adocao e walkthrough operacional detalhado.
- Posicionamento: referencia canonicamente governada para consumidores, arquitetos e mantenedores.
Collection export actions
config.export.enabledhabilita o pipeline nativo de exportacao da tabela e deve declarar os formatos permitidos emconfig.export.formats.- O menu nativo de exportacao dispara
exportActione baixa o artefato retornado porPraxisCollectionExportService. - Acoes em massa podem acionar o mesmo pipeline quando usam uma chave claramente de exportacao, como
bulk-exportouexport-selected, ou quando declaramexportFormat. - Quando
exportFormate declarado, o formato precisa estar habilitado emconfig.export.formats; a tabela nao deve substituir silenciosamente por outro formato. - Acoes genericas de download, como
download-contract, permanecem no outputbulkActionenquanto nao declararemexportFormat; isso evita capturar workflows corporativos que nao sejam exportacao tabular. - Para exportar apenas a selecao, combine
behavior.selection.enabled,config.export.general.scope: "selected"e uma bulk action visivel apenas quandoselectedCount > 0. - Quando
config.export.general.scopee"selected", a exportacao sem linhas selecionadas e bloqueada com feedback de usuario em vez de gerar um arquivo vazio.
AI assistant entrypoint
config.ai.assistant.enabledcontrola a visibilidade e o acionamento do assistente de IA embarcado na tabela.- Ausencia do campo equivale ao comportamento historico: o entrypoint continua disponivel quando o adapter de IA da tabela estiver carregado.
- Use
falsepara surfaces em que o host precisa remover a acao de IA por contrato publico, sem CSS contra classes internas da tabela ou do Angular Material. - Ao mudar para
false, a tabela fecha o assistente e remove a sessao contextual da tabela no registry compartilhado de IA.
Columns visibility dropdown
config.toolbar.columnsVisibility.enabledcontrola a exibição do botão de visibilidade de colunas na barra de ferramentas.- Por padrão, o botão de visibilidade rápida de colunas estará habilitado caso a toolbar esteja visível.
- Guardrail de UX: O último controle ativo no dropdown de colunas é automaticamente desabilitado quando apenas 1 coluna permanece visível, para impedir que o usuário oculte todas as colunas de dados da tabela.
- A desativação rápida de colunas reflete instantaneamente no layout visual (
displayedColumns) e emite o eventoconfigChange.
[!WARNING] Segurança Corporativa em Cenários Corporativos: A visibilidade de colunas via dropdown da toolbar é um recurso estritamente visual (layout de apresentação do lado do cliente). A ocultação de colunas não protege o dado sensível da transmissão de rede nem de inspeção técnica. Se determinados campos (ex: salários, senhas ou tokens) forem confidenciais para o nível de permissão do usuário atual, a restrição de dados deve ser realizada obrigatoriamente no lado do servidor (através da filtragem de propriedades nas APIs de CRUD e consulta), e nunca por meio de ocultação puramente visual na tabela.
Quick filters, unified filter region, and density
- Região única de filtros e dono explícito da consulta: Em telas de coleção com
praxis-table, a própria tabela é a dona canônica dos filtros editáveis pelo usuário. Quando um campo (ex.:ativo/status) é governado porconfig.toolbar.filters.quickFilters[], evite duplicá-lo emalwaysVisibleFields(mantenha-o apenas nos escopos rápidos e opcionalmente na gaveta avançadaselectedFieldIds). config.toolbar.filters.quickFilters[]materializa um seletor de escopo governado na toolbar. Cada item declaraid,label,filtereiconopcional.- Um item com
filter: {}representa o escopo "Todos" (sem restrição editável): acioná-lo limpa critérios editáveis anteriores emfilterCriteriae emqueryContext.filtersnão estruturais sem exigir reload da página. - Critérios booleanos explícitos
false(ex.:{ ativo: false }) são preservados integralmente na serialização remota e na avaliação local.
- Um item com
- Reconciliação de atalhos externos (
queryContext.filters) vs. filtros estruturais (queryContext.meta):- Quando cards de KPI ou widgets externos aplicam um filtro editável via
queryContext.filters(ex.:{ ativo: true }), a tabela sincronizaadvancedFilterValue,activeCrossFilterseactiveQuickFilterIdcorrespondente. - Se o operador alterar o escopo rápido (
onQuickFilterChange), submeter/limpar os filtros da tabela (onAdvancedFilterSubmit/onAdvancedFilterClear) ou remover chips (onClearCrossFilter/onClearAllCrossFilters), a tabela reconcilia as chaves editáveis emqueryContext.filterse emitequeryContextChangeequeryContextClear, impedindo quequeryContext.filtersórfãos continuem sobrescrevendofilterCriteria. - Filtros estruturais de contexto (
queryContext.meta.relatedResource === true+parentFilterField,queryContext.meta.structuralFields,queryContext.meta.immutableFieldsouqueryContext.meta.structural === true) permanecem protegidos e nunca são limpos por ações de filtro do usuário.
- Quando cards de KPI ou widgets externos aplicam um filtro editável via
- A composição adaptativa é responsabilidade do runtime: identidade, escopo, consulta e comandos se reorganizam pela largura do container da tabela. Dentro da consulta, campos editáveis formam a região de critérios; tags/atalhos salvos e comandos de gerenciamento formam um único cluster auxiliar. Em largura intermediária, os critérios e esse cluster completo compartilham o mesmo fluxo de quebra para aproveitar a faixa final sem criar uma linha órfã; em largura estreita, o cluster migra inteiro para a faixa seguinte. O host não precisa declarar coordenadas, breakpoints ou ordem visual adicional.
- Em superfícies de até
640px, os campos de consulta absorvem o espaço residual da própria linha até o limite do arquétipo; em320px, entradas que não cabem em pares ocupam a largura útil integral. Presets e comandos curtos preservam largura intrínseca. Grupos binários de filtros rápidos equilibram as duas opções em até540px, enquanto grupos maiores mantêm largura por conteúdo e overflow acessível. advancedFilters.settings.alwaysVisibleFieldsdeve conter apenas critérios frequentes. Atalhos persistidos e comandos de gerenciamento não devem ser simulados como campos sempre visíveis nem reposicionados por seletores CSS internos do host.- Cada item de
tags[]deve declararid,labelepatch; as chaves e os valores depatchdevem corresponder aoFilterDTOcanônico. Tags fornecidas pelo host são acionáveis, mas não podem ser renomeadas ou excluídas como atalhos persistidos pelo usuário. A aplicação imediata é emitida porsubmit. config.toolbar.densityToggle.enabledmaterializa o seletor de densidade.valuespode restringir as opções entrecompact,comfortableespacious.- A alteração de densidade atualiza
config.appearance.densitye emiteconfigChange, permitindo ao host decidir se a preferência será apenas transitória ou persistida.
Rich content convergence
mapTableRendererToRichContentP0(...)e a ponte publica e restrita entre a taxonomia atual de cell renderers dopraxis-tablee o vocabulario compartilhado1.0de rich content em@praxisui/core.- O subconjunto promovido nesta fase e intencionalmente pequeno:
icon,image,badge,chip -> badge,avatar,progressecompose. - Renderers interativos como
button,toggle,menu,link,htmlerating, alem do shell de detail/expansion, continuam table-owned e fora do contrato compartilhado1.0ate promocao semantica explicita.
Detail rich surfaces
richContentincorpora um documento canônicopraxis.rich-content@1.0.0no corpo do registro selecionado. Use-o paracallout, cartões semânticos, ícones, hierarquia tipográfica e ações sem duplicar essa taxonomia dentro de Table.O documento é validado integralmente antes do render. Cada
actionIddo conteúdo rico precisa existir emactions.row.actions[]; referências não declaradas ficam indisponíveis e não são despachadas. Ações declaradas são mediadas pelo host e seguemonRowAction; confirmação, capabilities e autorização continuam governadas pela Table e pelo backend.O editor visual de Detalhes delega
richContent.documentaoPraxisRichContentConfigEditor, incluindo tonsneutral|info|success|warning|danger, bindings comorow.note, mídia e botões. Tokens semânticos são o caminho recomendado; gradientes são estilo avançado e exigem prova de contraste nos temas suportados.actionBarentra na mesma fronteira canônica de detail row para agrupar ações contextuais host-mediated.actionBaré host-mediated:- o host resolve visibilidade, disabled e dispatch
- o conteúdo visual de cada botão continua em
PraxisRichContent
timelineentra na mesma fronteira canônica de detail row ao lado dedetailListecardGrid.timelinee host-mediated:- a colecao vem de
fieldouitems - cada entrada usa
itemSchemapara mapeartitle,subtitle,meta,iconebadge - o host resolve dados e fallback, mas o rendering cronologico final fica no
PraxisRichContent
- a colecao vem de
behavior.detail.schemaContract.allowedNodesincluidetailListecardGridcomo surfaces canônicas de detail row.listcontinua sendo lista simples e nao aceita subtree declarativa por item.mediaBlocktambem faz parte da fronteira canonica do detail row, como primitive compartilhada para avatar/imagem, headline, subtitle, meta e trailing leve.detailListe host-mediated:- a colecao vem de
fieldouitems - cada item usa
itemSchema.nodescomRichBlockNode[] - o contexto do item expõe
detailItemedetailIndex, com aliases opcionais viaitemContext itemActionspermanecem no host, mas o conteudo visual do botao usaPraxisRichContent
- a colecao vem de
cardGridtambem e host-mediated:- o host resolve o shell do grid
- cada card e convertido para
RichCardNodee renderizado porPraxisRichContent - o conteudo dos cards e limitado a
RichPresenterNode | RichComposeNode
mediaBlocke primitive compartilhada:- a tabela nao cria renderer proprio; ela delega diretamente para
PraxisRichContent - o shape e voltado a avatar/imagem, headline, subtitle, meta e trailing leve
- a tabela nao cria renderer proprio; ela delega diretamente para
O contrato alvo do primeiro corte de colecao rica e:
type DetailListNode = {
type: 'detailList';
title?: string;
field?: string;
items?: unknown[];
emptyText?: string;
itemKeyField?: string;
itemSchema: {
layout?: 'stack' | 'row' | 'card-list';
nodes: RichBlockNode[];
};
itemContext?: {
itemAlias?: string;
indexAlias?: string;
};
itemActions?: Array<{
actionId: string;
label: string;
icon?: string;
payloadExpr?: string;
visibleWhen?: JsonLogicExpression | null;
disabledWhen?: JsonLogicExpression | null;
}>;
};
- O contrato alvo do segundo corte de cards densos e:
type CardGridNode = {
type: 'cardGrid';
title?: string;
subtitle?: string;
columns?: 1 | 2 | 3 | 4 | 'auto';
minCardWidth?: number;
cards: Array<{
id?: string;
title?: string;
subtitle?: string;
content: Array<RichPresenterNode | RichComposeNode>;
}>;
};
- O contrato alvo do terceiro corte de topo rico e:
type MediaBlockNode = {
type: 'mediaBlock';
avatar?: RichAvatarNode;
title?: RichTextNode;
subtitle?: RichTextNode;
meta?: RichComposeNode;
trailing?: RichBlockNode[];
};
- O contrato alvo do quarto corte cronologico e:
type TimelineNode = {
type: 'timeline';
title?: string;
field?: string;
items?: unknown[];
emptyText?: string;
itemSchema?: {
titleField?: string;
subtitleField?: string;
metaField?: string;
iconField?: string;
badgeField?: string;
};
};
type ActionBarNode = {
type: 'actionBar';
title?: string;
emptyText?: string;
actions: Array<{
actionId: string;
label: string;
icon?: string;
payloadExpr?: string;
visibleWhen?: JsonLogicExpression | null;
disabledWhen?: JsonLogicExpression | null;
}>;
};
Support legend
- Active: suportado e observado no runtime atual.
- Partial: suporte parcial, com restricoes conhecidas.
- Declared-only: declarado em tipos/schema sem ligacao runtime confirmada.
- Schema-only: presente em schema/modelo sem confirmacao de execucao.
- Deprecated: mantido por compatibilidade legada com migracao prevista.
Contract classification
Canonical runtime paths (public contract)
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
meta |
object | No | {} |
Active | Metadados de versao/hash/contexto da configuracao. |
columns[] |
array | Yes | [] |
Active | Definicao estrutural principal da tabela. |
behavior |
object | No | component-defaults | Active | Regras de paginação, sort, filter, selection, expansion, loading. |
behavior.loading.type |
spinner | skeleton | progress |
No | skeleton |
Active | Seleciona um dos três indicadores materializados pelo runtime. O valor legado custom, sem renderer local canônico, foi removido durante o beta. |
behavior.loading.position |
overlay | inline | replace |
No | replace |
Active | Controla se o indicador cobre, acompanha ou substitui a superfície de dados. |
behavior.loading.text |
string | No | Carregando dados... |
Active | Mensagem acessível e visual apresentada durante a leitura. |
behavior.loading.delay |
number | No | 0 |
Active | Adia apenas o indicador visual; estado, bloqueio e timeout começam com o request. |
behavior.loading.showForQuickOperations |
boolean | No | false |
Active | Quando true, ignora o atraso visual e mostra o indicador imediatamente. |
behavior.loading.requestTimeoutMs |
number | No | 30000 |
Active | Encerra requests de schema, coleção REST ou analyticsProjection que excedem o SLA e apresenta erro recuperável; 0 delega a política ao host. |
behavior.loading.allowCancel |
boolean | No | true |
Active | Em schema, coleção REST e analyticsProjection, exibe cancelamento acessível, aborta o transporte por unsubscribe e preserva dados estáveis já renderizados. |
behavior.loading.skeleton.rows |
number | No | 3 |
Active | Quantidade de linhas visuais, normalizada pelo runtime entre 1 e 12. |
behavior.loading.skeleton.animated |
boolean | No | true |
Active | Controla a animação do skeleton. |
appearance |
object | No | component-defaults | Active | Densidade, responsividade, tokens e comportamento visual. |
toolbar |
object | No | component-defaults | Active | Ações globais, busca e controles de topo. |
actions |
object | No | component-defaults | Active | Ações por linha/lote e integrações de comando. |
messages |
object | No | component-defaults | Active | Textos de UX e feedbacks operacionais. |
data |
object | No | component-defaults | Partial | Configuração de integração de dados server/client. |
localization |
object | No | component-defaults | Partial | i18n/localização em campos e mensagens. |
accessibility |
object | No | component-defaults | Partial | A11y semântica e atalhos de interação. |
rowConditionalStyles[] |
array | No | [] |
Partial | Estilos condicionais por linha. |
_rowStyleRulesState |
any | No | undefined |
Partial | Estado serializado do editor (round-trip). |
Supported legacy paths
Nenhum path legado suportado foi identificado nesta revisão baseada em evidência textual preservada.
Canonical authoring envelope
type TableAuthoringDocument = {
kind: 'praxis.table.editor';
version: 1;
config: TableConfig;
bindings?: {
resourcePath?: string | null;
horizontalScroll?: 'auto' | 'wrap' | 'none';
};
};
Internal-only paths
| Path | Internal consumer | Runtime presence | Public support | Notes |
|---|---|---|---|---|
__forceRemoteMode__ |
reconciliacao de modo de dados | Yes | No | Flag interna para forcar modo remoto em cenarios de editor/runtime. |
Experimental paths
| Path | Enablement (flag/guard) | Stability | Rollout notes | Notes |
|---|---|---|---|---|
behavior.detail.source.resourcePath |
resourceAllowList + schemaContract + renderer contract |
Partial | Guard rails ativos; requer evidência de host para produção | Fluxo com fail-closed quando contrato/allowlist falha. |
behavior.detail.source.hypermedia |
_links.capabilities + schemaContract + renderer contract |
Partial | Usa discovery canônico do backend; fail-closed sem rel="capabilities" |
Primeiro corte gera detail schema leve a partir do snapshot agregado. |
Hypermedia detail semantics
behavior.detail.source.mode = "hypermedia"começa sempre em_links.capabilities.surfaces,actionsecanonicalOperationssão lidos doResourceCapabilitySnapshotretornado pelo backend.- O primeiro corte monta um detail schema leve de resumo contextual; ele não embute execução inline de
surface.opennem de workflow. - O runtime faz prefetch por linha somente quando existe ao menos uma ação contextual configurada para projeção inline (
display="icons"|"buttons"). Ações restritas ao menu preservam discovery sob demanda ao abrir o overflow; expansionhypermediasem row actions continua resolvendo o contexto ao expandir a linha. actions.collection.discovery.enabled=falsedesliga somente a materialização automática de ações da coleção, incluindo create e workflows descobertos por HATEOAS/capabilities. Dados, schema, paginação, capabilities de leitura, ações explícitas da toolbar e ações por linha permanecem disponíveis. O default permanece habilitado quando o campo é omitido.actions.row.discovery.enabled=falsedesliga somente o enriquecimento automático de ações por linha. Use este modo para telas corporativas curadas, nas quais o host quer expor apenasactions.row.actions[]e evitar overflow/actions descobertas por HATEOAS/capabilities. O default permanece habilitado quando o campo é omitido.
Overview
Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecnico existente. O conteudo detalhado anterior foi preservado para manter rastreabilidade historica e reduzir perda de contexto.
Public contract surface
Top-level configuration blocks
| Block | Purpose | Required | Merge strategy | Notes |
|---|---|---|---|---|
meta |
Identidade/versionamento da configuração | No | shallow-merge | Pode carregar schemaId e serverHash como snapshot persistido de reconciliação; o runtime usa estado transitório para verificação ativa de schema. |
columns[] |
Estrutura de colunas e renderers | Yes | replace-array | Nucleo funcional do runtime de tabela. |
behavior |
Regras operacionais (sort/filter/paginação/expansion) | No | deep-merge | Defaults internos aplicados por ensureConfigDefaults(). |
appearance |
Densidade, responsividade e tema | No | deep-merge | Inclui normalização de horizontalScroll e breakpoints. |
toolbar |
Ações e UX de topo | No | deep-merge | Integrado com editor e quick actions. |
actions |
Ações de linha/lote | No | deep-merge | Roteia para eventos rowAction, bulkAction e flows de delete. |
messages |
Mensagens de feedback/runtime | No | deep-merge | Fallback para mensagens padrão quando ausente. |
data |
Estratégia de integração de dados | No | deep-merge | Convivência de modo remoto e local com data input. |
Nested configuration blocks
| Path | Type | Required | Default | Constraints | Notes |
|---|---|---|---|---|---|
behavior.pagination |
object | No | component-defaults | component-defined | Estratégia client/server e tamanho de página. |
behavior.filtering |
object | No | component-defaults | component-defined | Filtros simples/avançados e debounce. |
behavior.selection |
object | No | component-defaults | component-defined | Single/multiple, persistência e UX visual. |
behavior.expansion |
object | No | component-defaults | contract-version-aware | Contrato de detail row e políticas fail-closed/fallback. |
behavior.expansion.interaction.toggleIcon |
object | No | runtime-defaults | icon-name strings | Customiza ícones recolhido/expandido e ariaLabelCollapsed/ariaLabelExpanded do toggle sem alterar a lógica de expansão; usa o pipeline [praxisIcon] do host e preserva fallback legado para ariaLabel. |
behavior.expansion.interaction.motion |
object | No | runtime-defaults | preset-driven | Presets controlados (none, subtle-slide, accordion, fade-scale) com respeito a prefers-reduced-motion; durationMs aceita 0 para desabilitar motion temporal. |
appearance.responsive |
object | No | component-defaults | numeric-breakpoint | Breakpoint móvel inválido é normalizado para 768. |
toolbar.actions[] |
array | No | [] |
action-contract | Ações de toolbar com roteamento para toolbarAction/bulkAction. |
toolbar.appearance |
object | No | Material 3 fallback | token-contract | Governa preset, variante, densidade, forma, divisores e tokens públicos da toolbar sem alterar a semântica das ações. |
actions.collection.discovery.enabled |
boolean | No | true |
collection-action-discovery | Controla se ações de coleção podem ser materializadas por HATEOAS/capabilities. Configure false em lookups/seletores para manter consulta remota e somente ações explicitamente declaradas. |
actions.row.actions[].recordSurface |
object | No | none | ResourceSurfaceCatalogItem |
Preserva a identidade canônica da superfície relacionada aberta por uma ação de linha, mantendo actions.row.actions[].id como identidade do botão. |
actions.row.discovery.enabled |
boolean | No | true |
row-action-discovery | Controla se row actions podem ser enriquecidas por HATEOAS/capabilities. Configure false para manter somente ações declaradas em actions.row.actions[]. |
columns[].renderer |
object | No | field-type-driven | renderer-contract | Renderers condicionais, payload expr e ações interativas. |
Quando actions.row.discovery.enabled esta ativo e o item publica
capabilities CRUD canonicas, PraxisTable pode sintetizar entradas
contextuais view, edit e delete. Quando o backend publica
explicitamente operations["duplicate-draft"], a tabela tambem materializa
duplicate-draft como operacao estendida de item. Essas entradas continuam
sendo capabilities, nao workflow actions. Em uma tabela standalone, view/byId
abre um Dynamic Form somente leitura por surface.open, usando a resolucao
canonica do GET de item e do schema de resposta. O host deve fornecer o runtime
de surfaces e autorizar essas leituras na sua politica de rede. Surfaces nomeadas
preservam seus proprios ids, paths e schemas. Dentro de um contexto CRUD, view
continua emitindo rowAction com actionConfig apontando para a capability;
as demais capabilities delegadas e actions globais explicitas preservam seu fluxo.
Injector e origem do foco acompanham apenas o contexto efemero de execucao,
nunca o JSON authorado ou o payload HTTP.
Renderer defaults:
columns[].renderer.type = "avatar"aplicacolumns[].align = "center"quando a coluna não declara alinhamento explícito. Esse default governa header e célula para manter foto/avatar centralizados em colunas dedicadas, preservandoalign,widthe demais overrides declarados pelo host.columns[].renderer.type = "microVisualization"renderiza a visualização compacta declarada emrenderer.microVisualization.visualization. O caminho preferencial é metadata-driven: campos de schema compresentation.presenter = "microVisualization"epresentation.visualization.surface = "table-cell"são convertidos automaticamente para esse renderer quando o tipo é seguro para tabela. O contrato visual e a normalização pertencem a@praxisui/core(PraxisPresentationVisualizationConfig); a tabela apenas hospeda o HTML compacto em célula, compose item ou renderer condicional.Em
renderer.compose.items[]comtype = "value",emphasis = "strong"representa o valor primário eemphasis = "subtle"o contexto de apoio. São os únicos níveis de hierarquia visual no item de texto;stylearbitrário não integra o contrato de compose.Em tabela, campos
*Exprda visualizacao, comovalueExpr,targetExpr,segmentsExpr,toneExprefallbackTextExpr, sao resolvidos contra o contexto da linha antes de renderizar. Strings simples sao caminhos (row.slaAtual) e objetos seguem Json Logic. Parakind = "comparison", usepoints/pointsExpr;itemsfica reservado para visualizacoes orientadas a itens/etapas.
Toolbar contract
Acoes globais de toolbar, row e bulk usam
effects[].kind = "global-action"como envelope canonico de novo authoring. O campoglobalActionplano continua aceito como fallback compatibilidade, mas nao e a superficie preferida.payloadExpre escape avancado explicito deGlobalActionRef; visual authoring deve preferirpayloadestruturado e preservarpayloadExprexistente apenas quando a mesmaactionIdfor mantida.O bloco
toolbarcontinua parte do contrato público principal.Use
toolbar.actions[]para quick actions etoolbar.searchpara busca quando o host não injeta shell própria.Use
toolbar.appearancepara personalizar o chrome da toolbar por contrato governado. O runtime materializavariant,density,shape,divideretokenscomo classes e CSS custom properties públicas; o host pode trocar aparência sem redefinir intenção, capability ou roteamento.Use
toolbar.appearance.preset = "table-integrated"para compor toolbar e tabela como um unico bloco visual com tokens públicos estáveis, evitando CSS do host sobre classes internas comopraxis-toolbar-stack-topoutable-stack-top.Tokens públicos suportados em
toolbar.appearance.tokens:bg,fg,borderColor,borderWidth,radius,shadow,paddingBlock,paddingInline,minHeight,gap,actionsGap,dividerColor,actionSize,actionRadius,actionBg,actionFg,actionHoverBg,actionActiveBg,actionFocusRing,aiAccentColor,statusFg,titleFg,subtitleFg,iconFg,titleFontSize,subtitleFontSize,titleFontWeight,identityGap,identityFilterGap,identityMinHeight,identityMarginBottom,identityIconSizeeidentityIconRadius.Ações da toolbar e do estado vazio compartilham a geometria pública
--praxis-action-control-*.actionSizeeactionRadiuscontinuam sendo overrides por tabela e têm precedência sobre os defaults compartilhados.Em coleções relacionadas graváveis, CREATE permanece estável na toolbar nos estados vazio e preenchido. O estado vazio gerado é informativo e não repete CREATE;
behavior.emptyState.actionsfica reservado a uma intenção contextual explícita e distinta, preservada exatamente quando declarada pelo host.Para localizar paths específicos de toolbar, complemente a leitura com o
Appendix: JSON path index.
Messages contract
- O bloco
messagesgoverna copy operacional, affordances de confirmação, labels de toolbar e feedbacks corporativos. - Prefira
messagespara texto/public contract; reserve providers globais para políticas de tenant. - Para busca rápida de paths e defaults parciais, complemente a leitura com o
Appendix: JSON path index.
Input bindings
| Binding/Path | Type | Required | Source | Runtime normalization | Notes |
|---|---|---|---|---|---|
config |
TableConfig |
Yes (logical) | component-input | ensureConfigDefaults + guards |
Contrato JSON principal da tabela. |
resourcePath |
string |
Conditional | component-input | crudService.configure(resourcePath) |
Fonte remota de dados/schema quando em modo remoto. |
data |
any[] | null |
No | component-input | dataSource.data = data |
Ativa caminho de dados locais. |
tableId |
string |
Yes | component-input | trim + component key builder | Necessário para persistência/configuração por instância. |
componentInstanceId |
string | undefined |
No | component-input | component key scoping | Isola preferências por instância em mesma rota. |
configPersistenceStrategy |
'local-first' | 'input-first' | 'volatile' |
No | component-input | default local-first |
Controla a hidratação de preferências persistidas. volatile renderiza apenas por inputs/runtime e não consulta nem grava ASYNC_CONFIG_STORAGE, útil para surfaces executivas efêmeras abertas por surface.open. |
title |
string |
No | component-input | host-surface passthrough | Título opcional consumido por superfícies auxiliares, quick connect e contextos host. |
subtitle |
string |
No | component-input | host-surface passthrough | Subtítulo opcional para contexto operacional do host. |
icon |
string |
No | component-input | host-surface passthrough | Ícone opcional usado em affordances auxiliares do runtime. |
autoDelete |
boolean |
No | component-input | boolean coercion | Ativa deleção automática quando o host delega esse fluxo ao runtime. |
enableCustomization |
boolean |
No | component-input | boolean coercion | Controla entrada em editor/configuração; default canônico false. |
dense |
boolean |
No | component-input | boolean coercion | Entrada legada de compactação. Equivale a appearance.density="compact" apenas quando o contrato não informa appearance.density. |
notifyIfOutdated |
'inline' | 'snackbar' | 'both' | 'none' |
No | component-input | enum validation + prefs fallback | Política de aviso de drift de schema; o host escolhe banner inline, snackbar, ambos ou silêncio explícito. |
snoozeMs |
number |
No | component-input | numeric fallback + prefs fallback | Janela de snooze para avisos de drift; default do input é 86400000 (24h) e políticas globais podem complementar. |
autoOpenSettingsOnOutdated |
boolean |
No | component-input | schema-prefs resolution | Abre automaticamente o settings panel quando drift de schema é detectado. |
crudContext |
any |
No | component-input | host-context passthrough | Contexto opcional usado por flows compostos e integrações host/CRUD. |
Migration note:
enableCustomization=falseis now the canonical default.- Hosts that need runtime authoring/settings must pass
enableCustomization=trueexplicitly.
Output events
selectionChange is an active output for Dynamic Page composition. It emits
{ trigger, row?, selectedRows, selectedCount, tableId? } when the user changes
row selection through table affordances.
When the table assistant is opened, selected rows are projected into a governed
table-row-selection runtime digest with selectedCount, idField,
selectedIds and a limited sanitized sampleRows array. This digest grounds
LLM answers or requested actions about the selected records, but it does not
route the user's primary intent and it is not a second source of business rules.
The assistant can also materialize declared runtime operations through
tableRuntimeOperations. This is a reviewed, table-owned operation envelope,
not a free-form component patch. Supported operations are:
| Operation | Input | Effect |
|---|---|---|
table.filter.apply |
{ criteria } |
Applies advanced filter criteria through the same runtime path used by the filter UI. criteria is currently a simple conjunction over declared filter fields; boolean composition such as OR, anyOf, oneOf or allOf is not part of this runtime contract yet. |
table.export.run |
{ format, scope? } |
Runs the canonical Collection Export pipeline. scope may override the configured export scope for this runtime action only. |
Compound filter semantics should evolve through the canonical
PraxisDataQueryContext.filterExpression proposal in
projects/praxis-core/docs/rfc-query-context-filter-expression.md, not through
implicit OR payloads in criteria.
When /schemas/filtered publishes x-ui.resource.capabilities, the table
assistant includes a resource capability digest in its authoring contract.
capabilities.filter=true only declares the flat /filter DTO/simple
conjunction surface. capabilities.filterExpression=false tells the assistant
to clarify or explain OR/nested boolean requests instead of silently applying a
degraded filter.
| Event | Payload | Trigger | Stability | Notes |
|---|---|---|---|---|
rowClick |
{ row, index } |
Clique em linha. | Partial | Preservado da documentação anterior. |
rowDoubleClick |
{ action, row } |
Duplo clique quando habilitado. | Partial | Preservado da documentação anterior. |
rowExpansionChange |
RowExpansionChangeEvent |
Evento canônico para expand/collapse de detail row no runtime P0A (caminho não virtualizado), com payload discriminado por política de exposição (allowRawExposure + eventExposureDefault). |
Partial | Preservado da documentação anterior. |
rowAction |
{ action, row, payload?, actionConfig?, localMode?, preventedHttp? } |
Acao de linha (coluna _actions, renderer interativo ou CRUD capability sintetizada). payload e emitido quando houver payloadExpr em renderer interativo. Quando actionConfig.globalAction aponta para navigation.openRoute, o runtime resolve templates como ${row.id} antes de executar a navegação interna. Para actions como surface.open, payload.* continua sendo o envelope canônico do evento entregue ao destino. Para capabilities delegadas ao host (view em CRUD, edit/delete/duplicate-draft), actionConfig carrega a operacao canonica. O view/byId standalone abre a leitura por surface.open e nao emite um segundo pedido local. |
Partial | Preservado da documentação anterior. |
toolbarAction |
{ action, actionConfig? } |
Acao clicada em toolbar.actions[] que nao foi roteada para fluxo bulk; actionConfig carrega o objeto da acao quando disponivel. A acao create de colecao pode ser materializada automaticamente a partir de _links.create, rel capabilities, surfaces e CrudOperationResolutionService. Dentro de CRUD, a tabela delega ao owner antes de abrir. Standalone, uma surface selecionada usa uma unica tentativa de surface.open; falha de execução é fail-closed e não emite toolbarAction como segundo caminho. O fallback local só permanece quando nenhuma surface executável foi selecionada. |
Partial | Preservado da documentação anterior com materializacao CRUD de colecao e ownership explícito. |
exportAction |
{ format, request?, result?, error?, tableId? } |
Acao de exportacao acionada pelo menu export.formats[]; request segue PraxisCollectionExportRequest. |
Active | Usa o contrato canonico de Collection Export em @praxisui/core. |
exportAction |
{ format, request?, result?, error?, tableId? } |
Acao de exportacao acionada pelo menu export.formats[]; request segue PraxisCollectionExportRequest. |
Active | Usa o contrato canonico de Collection Export em @praxisui/core. |
bulkAction |
{ action, rows, actionConfig? } |
Acao em lote; actionConfig carrega a configuracao da acao quando disponivel. |
Partial | Preservado da documentação anterior. |
columnReorder |
ColumnReorderEvent |
Reordenação de coluna concluída (drag/keyboard). | Partial | Inclui metadados de origem, destino e operação. |
columnReorderAttempt |
ColumnReorderAttemptEvent |
Tentativa bloqueada por política de drop-zone. | Partial | Evento diagnóstico para observabilidade e auditoria. |
columnResize |
{ action: 'columnResize', trigger: 'pointer' | 'keyboard' | 'auto-fit', tableId, field, header, previousWidth, currentWidth, persisted } |
Redimensionamento de coluna concluido pelo separador do header. | Partial | Usa behavior.resizing.enabled, respeita columns[].resizable !== false e persiste columns[].width em px quando persistWidths !== false. autoFit !== false habilita duplo clique para medir cabeçalho e células renderizadas. A largura interna nunca fica menor que o viewport; crescimento excedente usa scroll horizontal. |
beforeDelete |
row |
Antes de delete de linha. | Partial | Preservado da documentação anterior. |
afterDelete |
row |
Depois de delete com sucesso. | Partial | Preservado da documentação anterior. |
deleteError |
{ row, error } |
Erro no delete de linha. | Partial | Preservado da documentação anterior. |
beforeBulkDelete |
rows[] |
Antes de bulk delete. | Partial | Preservado da documentação anterior. |
afterBulkDelete |
rows[] |
Depois de bulk delete com sucesso. | Partial | Preservado da documentação anterior. |
bulkDeleteError |
{ rows, error } |
Erro em operação de delete em lote. | Partial | Preservado da documentação anterior. |
schemaStatusChange |
{ outdated, serverHash?, lastVerifiedAt?, trigger?, tableId? } |
Verificação de versão de schema concluída. | Partial | Usado para notificação de drift entre runtime e servidor. |
configChange |
TableConfig |
Configuração materializada pelo runtime/editor/assistente. | Active | Permite que o host sincronize mudanças feitas por authoring em tempo de execução. |
metadataChange |
{ trigger, meta, tableId? } |
Metadados operacionais atualizados pelo runtime/editor. | Partial | Emite contexto de trigger e a carga corrente de config.meta. |
loadingStateChange |
LoadingState |
Mudança de estado (config/schema/data/render), incluindo loading, success, error e cancelled. |
Active | Unifica schema, coleção REST e analyticsProjection; timeout permanece error com causa preservada. |
External side channels
| Channel | Direction | Contract | Failure mode | Notes |
|---|---|---|---|---|
ASYNC_CONFIG_STORAGE |
bidirectional | loadConfig/saveConfig/clearConfig |
fail-open | Persistência de config e inputs por tableId/instância; não é acessado quando configPersistenceStrategy='volatile'. |
CONNECTION_STORAGE |
bidirectional | loadConnection/saveConnection |
fail-open | Persistência de resourcePath para quick-connect. |
SettingsPanelService |
bidirectional | open(...).applied$/saved$ |
fail-open | Canal de edição em runtime (quick connect/editor). |
PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER |
outbound call | Angular DI token (TableDetailResourceResolver) |
fail-closed | Resolução externa e governada de detail schema por resource; o host deve fornecer o token por DI. |
AnalyticsTableStatsApiService.execute |
outbound call | Observable<AnalyticsTableRow[]> |
fail-closed | A subscription é proprietária do transporte HTTP. unsubscribe, supersessão, timeout e destruição abortam o request em andamento; use firstValueFrom(...) apenas na borda de um consumidor que deliberadamente precise de Promise. |
resourcePath mantém precedência canônica sobre analyticsProjection: quando ambos estão presentes, o runtime cancela o transporte analítico e materializa somente a coleção REST.
Host/runtime dependencies
| Dependency | Required | Environment | Purpose | Notes |
|---|---|---|---|---|
GenericCrudService |
Yes | browser/dev/prod | data + schema I/O | Configura endpoint e executa filter/getSchema. |
TableDefaultsProvider |
Yes | browser/dev/prod/ssr | defaults canônicos | Base para merge inicial e fallback de configuração. |
SettingsPanelService |
Yes | browser/dev/prod | edição runtime | Abre editor e quick setup/quick connect. |
ASYNC_CONFIG_STORAGE |
Yes | browser/dev/prod | persistência | Guarda configurações por escopo de componente. |
CONNECTION_STORAGE |
Yes | browser/dev/prod | persistência de conexão | Mantém vínculo tableId -> resourcePath. |
LoadingOrchestrator |
Yes | browser/dev/prod/ssr | estado de loading | Coordena bloqueio/feedback por fase. |
PRAXIS_LOADING_RENDERER |
Optional | browser/dev/prod/ssr | renderer global de infraestrutura | É independente de behavior.loading.type: hoje a Table o usa no lifecycle de montagem, enquanto os indicadores de schema/coleção são materializados localmente. |
Coverage matrix
| Surface | Verified | Coverage status | Evidence | Notes |
|---|---|---|---|---|
| Runtime | true | Active | source_of_truth + conteudo preservado | Revisao estrutural concluida; validacao comportamental fina pode exigir follow-up. |
| Schema/Types | true | Partial | interfaces/modelos citados | Mapeamento formal de todos os campos ainda pode requerer refinamento. |
| Editor/Tooling | false | Partial | secoes de editor quando presentes | Cobertura de editor/tooling nem sempre confirmada por evidencia direta. |
Runtime coverage boundaries
- Cobertura consolidada com base em documentacao existente e source of truth declarado.
- Comportamentos fora de evidencia direta foram marcados como not-yet-verified ou Partial.
- Compatibilidade legada, quando detectada, foi separada em classificacao explicita.
Resolution model
Merge order
- defaults base (
createDefaultTableConfig+TableDefaultsProvider) - contrato recebido em
@Input() config - hidratação opcional de config persistida (
table-config:*) e inputs persistidos (table-inputs:*) - ajustes de runtime (
ensureConfigDefaults, guards de recursos não suportados, reconciliação de modo de dados) - alterações vindas de editor/settings panel (
applied$/saved$)
Fallback order
resourcePath explícito -> conexão persistida (CONNECTION_STORAGE) -> data local -> tabela sem fetch remoto.
Override points
@Input() config,@Input() resourcePath,@Input() data- edição via
SettingsPanelService(config editor, quick connect, quick setup) - persistência de host (
ASYNC_CONFIG_STORAGEeCONNECTION_STORAGE)
Runtime normalization
ensureConfigDefaults()preenche blocos ausentes sem sobrescrever intenção explícita do contrato.parseLegacyOrTableDocument()absorve payloads legados do editor e converte para o envelope canônico de autoria antes do apply plan.sanitizeExpansionDetailSchema()aplica contrato de nós permitidos e política de fallback.
Precedence rules
- input explícito de runtime tem precedência sobre persistência local.
- paths canônicos têm precedência sobre aliases internos remanescentes (
__forceRemoteMode__). - em
behavior.detail, contrato inválido aplica fail-closed para detail row. behavior.detail.source.mode = "hypermedia"usa_links.capabilitiescomo ponto único de entrada e não executasurface.openinline no primeiro corte.
Observação adicional:
- no primeiro corte,
behavior.detail.source.mode = "hypermedia"usa_links.capabilitiescomo ponto único de entrada, consomesurfaces/actions/canonicalOperationsdo snapshot agregado e não executasurface.openinline.
Validation and error semantics
Validation model
| Path/Rule | Validation phase | Behavior on fail | Error code / warning | Notes |
|---|---|---|---|---|
tableId para persistência |
init/runtime | warn + disable persistence | praxis-table:missing-table-id |
Tabela segue funcional sem persistir preferências. |
appearance.responsive.breakpoints.mobile |
runtime normalization | fallback para 768 |
praxis-table:responsive-breakpoint-mobile-invalid |
Comportamento fail-open com warning deduplicado. |
behavior.detail.schemaContract.kind/version |
runtime validation | fail-closed (sem render de detail) | praxis-table:expansion:detail:schema-contract-kind-version-invalid |
Bloqueia detail schema inválido. |
behavior.detail.source.resourcePath policy |
canonical URL + same-origin pathname allowlist | fail-closed | praxis-table:expansion:detail:resource-path-policy-blocked:* |
Bloqueia URL absoluta, origem divergente, traversal/representações ambíguas, path efetivo fora da allowlist e redirects. Usa credenciais same-origin e EnterpriseRuntimeContextService.effectiveRequestHeaders(). A allowlist protege o documento; autorização GET/POST continua no backend. Hosts dependentes de interceptors Angular devem usar o resolver governado de source.mode=resource ou configurar os headers canônicos. |
behavior.detail.source.hypermedia sem _links.capabilities |
runtime validation | fail-closed | praxis-table:expansion:detail:hypermedia-links-missing |
Bloqueia detail hypermedia quando o item não expõe affordance canônica. |
detail rendering contract |
runtime validation | fail-closed | praxis-table:expansion:detail:rendering-invalid |
Exige estratégia/registry consistentes. |
Error semantics
Warnings cobrem preferências inválidas e ausência de tableId para persistência. Falhas de contratos de detail schema aplicam bloqueio local (detail row) sem derrubar renderização base da tabela.
Fail-open / fail-closed behavior
| Condition | Mode | Runtime behavior | Consumer impact |
|---|---|---|---|
| Configuração persistida indisponível | fail-open | ignora storage e usa defaults/inputs | componente continua operacional |
resourcePath inválido para detail schema |
fail-closed (escopo detail) | não expande detail row e registra warning/error | linha segue visível sem detalhe |
Contrato schemaContract inválido |
fail-closed (escopo detail) | bloqueia render de detail | evita execução de contrato não confiável |
| Campos opcionais desconhecidos no JSON | fail-open | ignorados ou mantidos sem efeito | baixo impacto, requer revisão de contrato |
Invalid or unknown field handling
- Campos desconhecidos: comportamento depende da estrategia do componente (ignore, warn ou reject).
- Campos invalidos: podem gerar fallback, warning ou falha conforme implementacao.
- Registrar divergencias observadas em Known limitations and mismatches.
Runtime warnings vs hard failures
| Condition | Severity | Observability | Consumer action |
|---|---|---|---|
| partial-or-declared-only-coverage | warning | logs/eventos do componente | confirmar ligacao runtime antes de uso critico |
Detailed API
Preserved technical reference (normalized from previous revision)
Summary
Referencia canonica da API JSON do praxis-table.
- O componente consome
TableConfig+ inputs externos (resourcePath,data,tableId) e side-channels de integracao. - Este documento cobre contrato, cobertura de runtime, precedencia, defaults, eventos e exemplos copiaveis.
- Fora de escopo: implementacao detalhada do host app, backend e UI de editores alem dos contratos que afetam runtime.
Support legend
- Active
- Partial
- Declared-only
- Schema-only
- Deprecated
Overview
praxis-table é uma superfície operacional para dados corporativos. Com uma
declaração pequena, a aplicação consegue exibir dados reais, paginação, colunas,
filtros, ações, mensagens e regras visuais sem reconstruir a tela a cada novo
cenário. A primeira renderização pode nascer do recurso publicado pelo backend;
os refinamentos podem vir da aplicação, do editor visual ou das preferências
persistidas.
Em arquiteturas tradicionais, cada variação de colunas, ações e filtros costuma virar uma nova camada de HTML, estado e condicionais. Aqui, a estratégia é inverter esse custo: a mudança entra em uma configuração governada. Quando o requisito muda, a experiência evolui sem transformar cada ajuste em uma nova implementação de tabela.
Conceitos-chave:
- Uma declaração publicada define estrutura, dados e experiência.
- O backend pode descrever o recurso para que a tabela derive a primeira leitura.
- Dados, apresentação e interação ficam separados, mas evoluem no mesmo contrato.
- Regras condicionais governam estilos, visibilidade e renderização sem espalhar decisões pelo template.
- Fluxos remotos ou locais preservam paginação, ordenação e filtros de forma previsível.
Por que este componente é diferente
O valor da Table aparece quando a tela deixa de ser um template isolado e passa a ser uma superfície governada por contrato. Em tabelas convencionais, cada mudança de coluna, filtro, ação ou visual pede código e template; aqui, essas mudanças entram em uma configuração declarativa e o componente responde de forma consistente:
- A configuração da tabela governa visual, dados e regras sem espalhar decisões pelo template.
- Dados remotos e dados locais têm estratégias próprias, com impacto claro na experiência.
- O editor visual convive com a tabela renderizada para permitir autoria governada.
- Regras condicionais cobrem destaque visual, renderização e comportamento sem duplicar tela.
- Identidade estável permite persistir preferências e reconciliar instâncias com segurança.
O resultado é um componente "plataforma": cada bloco do contrato vira um módulo do componente, e as interações entre esses módulos permitem evoluir experiências corporativas sem transformar cada nova regra em uma nova implementação de tela.
Valor em uma leitura rápida
Uma tabela que vira plataforma. praxis-table transforma decisões declarativas
em experiência: colunas, ações, filtros, mensagens e regras vivem no mesmo
contrato operacional, pronto para dados remotos ou locais, sem retrabalho de
template.
- Entrega rápida: ajuste comportamento e visual por configuração governada.
- Padrão de UX: regras, ações e mensagens consistentes entre telas.
- Escalável: regras e comandos estruturados permitem crescer a complexidade sem criar forks de tela.
Menos código de tela, mais contrato
Uma tabela que vira plataforma. Em vez de programar cada capacidade de tabela do zero, você ativa recursos nativos via contrato:
- Iteração sem código de tela: adicionar botões, trocar densidade, ajustar colunas, filtros e diálogos por configuração governada.
- Lógica desacoplada: destaque de linha, visibilidade de ação
e variação visual ficam em regras condicionais, não em
*ngIfespalhado. - Ecossistema embutido: paginação remota, virtual scroll, reorder de colunas,
exportação e
praxis-filteravançado como capacidades prontas. - Eventos estruturados: ações de linha, lote, toolbar, exportação e reordenação entregam intenções claras para a aplicação.
- Governança de estado: identidade estável organiza persistência, reconciliação e isolamento de instância.
Receitas de impacto
As receitas abaixo mostram capacidades que normalmente exigiriam código de tela, mas que a Table materializa a partir do contrato. Elas funcionam como portas de entrada para o leitor entender o valor antes de mergulhar na matriz completa da API.
- Dashboard financeiro: prova
computed+ densidade + regra visual. - Micro-layout compose (CRM): prova poder de layout sem componente custom.
- Backoffice seguro: prova bulk com travas de negócio e confirmação.
- Rastreador de SLA: prova de regra temporal em JSON Logic + alerta visual declarativo.
Receita 1 - Dashboard Financeiro
{
"appearance": { "density": "compact" },
"columns": [
{ "field": "asset", "header": "Ativo" },
{ "field": "costPrice", "header": "Custo", "type": "currency", "format": "BRL|symbol|2" },
{ "field": "salePrice", "header": "Venda", "type": "currency", "format": "BRL|symbol|2" },
{
"field": "margin",
"header": "Margem",
"type": "currency",
"format": "BRL|symbol|2",
"computed": { "expression": { "-": [{ "var": "salePrice" }, { "var": "costPrice" }] }, "outputType": "number" }
}
],
"rowConditionalStyles": [
{ "condition": { "<": [{ "var": "computed.margin" }, 0] }, "cssClass": "row--danger" }
]
}
Receita 2 - Micro-layout sem scroll (compose)
{
"columns": [
{
"field": "contact",
"header": "Cliente",
"renderer": {
"type": "compose",
"compose": {
"layout": { "direction": "row", "gap": 8, "align": "center" },
"items": [
{ "type": "avatar", "avatar": { "srcField": "photoUrl", "initialsField": "name" } },
{ "type": "value", "field": "name" },
{ "type": "badge", "badge": { "textField": "status", "variant": "soft" } }
]
}
}
}
]
}
Receita 3 - Backoffice Seguro (ações em lote)
{
"actions": {
"row": {
"enabled": true,
"actions": [
{
"id": "approve",
"label": "Aprovar",
"action": "approve",
"visibleWhen": { "===": [{ "var": "status" }, "PENDENTE"] }
}
]
},
"bulk": {
"enabled": true,
"position": "toolbar",
"actions": [
{
"id": "delete",
"label": "Excluir selecionados",
"action": "delete",
"minSelections": 1,
"requiresConfirmation": true
}
]
}
},
"messages": {
"actions": {
"confirmations": {
"deleteMultiple": "Tem certeza que deseja excluir os itens selecionados?"
}
}
}
}
Internal route global action
Configurações novas devem persistir a integração em effects[].globalAction. O runtime e os validadores também
leem globalAction plano para documentos existentes, mas editores e AI manifest devem tratar esse campo como
compatibilidade. O adapter da Table preserva payload/payloadExpr ao reabrir e re-selecionar a mesma actionId,
e limpa payloads ao trocar de global action para evitar semântica cruzada.
{
"actions": {
"row": {
"enabled": true,
"actions": [
{
"id": "open-details",
"label": "Abrir detalhe",
"icon": "open_in_new",
"globalAction": {
"actionId": "navigation.openRoute",
"payload": {
"path": "/funcionarios/detalhe",
"query": { "id": "${row.id}" },
"state": { "source": "table", "selectedId": "${row.id}" }
}
}
}
]
}
}
}
Receita 4 - Rastreador de SLA (tempo + alerta visual)
{
"columns": [
{
"field": "ageDays",
"header": "Dias em aberto",
"computed": { "expression": { "daysSince": [{ "var": "createdAt" }] }, "outputType": "number" }
}
],
"rowConditionalStyles": [
{
"condition": {
"and": [
{ ">": [{ "var": "computed.ageDays" }, 5] },
{ "!==": [{ "var": "status" }, "RESOLVIDO"] }
]
},
"cssClass": "row--danger text-bold"
}
],
"rowConditionalRenderers": [
{
"condition": {
"and": [
{ ">": [{ "var": "computed.ageDays" }, 5] },
{ "!==": [{ "var": "status" }, "RESOLVIDO"] }
]
},
"tooltip": { "text": "SLA violado: ação imediata necessária", "position": "top" },
"animation": { "preset": "warning-attention", "repeat": 3 }
}
]
}
Essas quatro receitas cobrem o primeiro impacto. Cenários mais longos, como filtros avançados, logs massivos e overrides CRUD, pertencem à trilha de exemplos completos para não diluir a tese principal do runtime.
Dominando a cauda longa das interfaces
Em sistemas corporativos e aplicações complexas, o esforço de engenharia raramente está nos fluxos principais. O custo aparece na cauda longa dos requisitos de UI: variações de regras condicionais, formatações específicas, mensagens baseadas em estado e permissões de ação que mudam por linha, perfil ou contexto operacional.
praxis-table foi desenhado para reduzir drasticamente esse custo de
manutenção. Em vez de espalhar condicionais pelo código da tela, o componente
move essas decisões para uma configuração governada. Quem define a experiência
ganha controle fino sobre leitura visual, ações, filtros e mensagens, com mais
autonomia para produto e menos acoplamento no frontend.
Impacto prático:
- Menos ramificação de código no frontend.
- Mais autonomia para evoluir UX por configuração.
- Menor risco de regressão ao escalar regras condicionais.
Mapa de contrato e superfícies
O contrato governa 6 áreas principais:
| Área | O que governa | Impacto na experiência |
|---|---|---|
| Estrutura e leitura | Colunas, aparência, comportamento, mensagens e localização | Define densidade, textos, ordenação e comportamento base da tabela. |
| Dados e operação | Recurso remoto, dados locais, paginação, filtros e ordenação | Decide como a tabela busca, pagina, filtra e apresenta os registros. |
| Regras condicionais | Regras de destaque, visibilidade e variação visual | Transforma estado operacional em sinais visuais consistentes. |
| Ações e jornada | Toolbar, ações de linha, ações em lote, diálogos e exportação | Materializa comandos e confirmações sem duplicar fluxo em cada tela. |
| Integração externa | Identidade da instância, preferências e reconciliação | Preserva persistência e isolamento entre telas, usuários e contextos. |
| Eventos de saída | Intenções estruturadas do usuário | Entrega comandos claros para a aplicação executar navegação, auditoria e regra de negócio. |
A API detalha cada área e explicita onde o comportamento está ativo, parcial, declarado ou dependente de schema.
Arquitetura orientada a contrato (como funciona)
O componente separa estritamente dados, apresentação e interação, operando em dois eixos principais: motor interno da tabela e integrações externas.
Fluxo simplificado de execução:
- Interpretação da configuração: resolve se a tabela usará dados remotos, dados locais ou estado vazio.
- Montagem da superfície: renderiza colunas, toolbar, filtros e comportamentos visuais definidos pela configuração.
- Pipeline de dados + motor de regras:
- remoto: consulta a operação publicada pelo backend;
- local: aplica paginação, ordenação e filtros no conjunto recebido;
- regras: avalia destaque visual, visibilidade de ações e variações por linha.
- Ciclo de eventos: emite ações estruturadas para que a aplicação reaja às intenções do usuário.
Integração com ecossistema Praxis (frontend e backend)
praxis-table compõe o ecossistema Praxis de ponta a ponta. O mapa de
integração cobre frontend, contratos e backend.
Frontend (UI):
| Componente | Papel na experiência | Como se conecta |
|---|---|---|
praxis-table-toolbar |
Barra superior/inferior com ações, bulk e export | toolbar, actions, export, behavior.filtering.* |
praxis-filter |
Filtro avançado acoplado à toolbar | behavior.filtering.advancedFilters.*, behavior.filtering.debounceTime, resourcePath |
praxis-empty-state-card |
Estado inicial quando não há conexão remota | exibido quando não há resourcePath válido |
PraxisAiAssistantShellComponent |
Copiloto semântico opcional nos slots de toolbar | habilitado pelo runtime com turn orchestration e contexto seguro; ao minimizar, a sessão fica no registry com presence: "origin-anchor" e o affordance volta ao gatilho da tabela (não exposto no JSON) |
| Angular Material + CDK | Base de tabela, menus, seleção e virtual scroll | behavior.pagination.*, behavior.selection.*, behavior.virtualization.*, appearance.spacing.* |
Backend e contratos:
| Componente | Papel na experiência | Como se conecta |
|---|---|---|
praxis-metadata-starter |
Publica OpenAPI + x-ui e o endpoint GET /schemas/filtered |
A tabela deriva colunas, filtros e validações a partir do contrato |
praxis-api-quickstart |
Exemplo pronto com recursos, filtros e CRUD padronizados | Demonstra o fluxo completo com resourcePath apontando para a API |
No modo de edição, quando a aplicação habilita customização, a tabela exibe o editor visual para ajustar colunas, comportamento, aparência e regras sem editar código de tela. Esse editor compõe a configuração com consistência e evita divergência entre o que o usuário authora e o que a tabela renderiza.
Checklist de integração (pre-flight)
Antes de plugar a tabela em uma aplicação, valide estes pontos:
- A instância tem identidade estável para persistir preferências sem colisão.
- O modo de dados está decidido: recurso remoto ou conjunto local informado pela aplicação.
- As colunas descrevem o conjunto de dados real e usam apresentação coerente.
- Ações de linha, lote e toolbar estão alinhadas com os comandos da aplicação.
- Regras condicionais têm fonte clara e não ficam espalhadas pelo template.
- Aparência, mensagens e localização foram revisadas para evitar inconsistências entre padrões globais e comportamento esperado.
Top-level contract
O contrato principal e TableConfig (alias de TableConfigV2) com extensoes de runtime aceitas no JSON:
- Base tipada:
meta,columns,columnProjection,behavior,appearance,toolbar,actions,export,messages,localization. - Extensoes fora do tipo estrito:
dialogs.confirm.delete,rowConditionalRenderers[], aliases legados debehavior.virtualScroll.*e chaves legadas de header emactions.row.*. - Artefatos auxiliares fora do
TableConfig:crud-overrides:<componentKeyId>e o envelope autoradoTableAuthoringDocument, que carregabindings.resourcePathebindings.horizontalScroll. A chave operacional da linha pertence aoTableConfigemconfig.meta.idField.
Projeção governada de colunas
Quando columnProjection.source = "schema", a declaração explícita de columns é opcional.
A lista estrutural de colunas é materializada em tempo de execução a partir de /schemas/filtered;
a configuração declara apenas a seleção ordenada em columnProjection.include e as decisões
editoriais pontuais em columnProjection.overrides, indexadas pelo nome canônico do campo:
{
"columnProjection": {
"source": "schema",
"include": ["competencia", "salarioBruto", "salarioLiquido"],
"overrides": {
"salarioLiquido": {
"sticky": "end",
"width": "160px"
}
}
}
}
Quando consumido dentro de <praxis-crud>, o contrato também auto-infere a schemaUrl
de behavior.filtering.advancedFilters a partir de resource.schemaPath ou resource.path
(normalizado para /schemas/filtered?path=/api/.../filter&operation=post&schemaType=request),
eliminando URLs estáticas duplicadas nos arquivos de configuração.
O runtime reaplica os overrides após bootstrap e atualização do schema. Uma chave
desconhecida não cria coluna, e field não pode ser alterado pelo override. Este
contrato não cria “defaults da surface” paralelos: tipo, visibilidade, ordem e
apresentação continuam pertencendo ao schema canônico; a página conserva apenas
as decisões editoriais específicas da experiência.
Durante a renderização, columns contém a materialização completa somente em
memória. Ao salvar, aplicar ou emitir configChange, o runtime compacta essa
materialização novamente: a ordem e os campos canônicos formam include, as
diferenças formam overrides e colunas computadas/client-owned sem equivalente
no schema formam additions. Uma addition cujo field colida com o schema é
ignorada; ela não pode sombrear a identidade canônica.
include é uma allowlist ordenada. Em recursos financeiros, pessoais ou
regulados, ela deve ser preferida para impedir que um novo campo do schema passe
a integrar a experiência sem decisão editorial explícita. A ausência de
include significa “todos os campos que o backend marcou como visíveis”.
Coverage matrix
Resumo de cobertura por bloco:
| Bloco | Leitura executiva | Referencia detalhada |
|---|---|---|
TableConfig + extensoes |
Contrato canônico consumido pelo runtime | ### JSON coverage matrix (TableConfig + extras) |
| Inputs/outputs do componente | API pública para host Angular | ### Component inputs e ### Component outputs |
| Caminhos JSON completos | Índice detalhado para escrita manual e validação | ## JSON path index |
Preserved source snapshot
| Source | Kind | Notes |
|---|---|---|
projects/praxis-table/src/lib/praxis-table.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/praxis-table.html |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/praxis-table.scss |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/praxis-table-toolbar.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/praxis-table-config-editor.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/behavior-config-editor/behavior-config-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/header-appearance-editor/header-appearance-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/columns-config-editor/columns-config-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/rules-editor/table-rules-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/toolbar-actions-editor/toolbar-actions-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/filter-settings/filter-settings.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/messages-localization-editor/messages-localization-editor.component.ts |
local-file | referencia preservada da versao anterior |
projects/praxis-table/src/lib/dialogs/confirm-dialog-appearance-editor.component.ts |
local-file | referencia preservada da versao anterior |
Events
selectionChange is an active output for Dynamic Page composition. It emits
{ trigger, row?, selectedRows, selectedCount, tableId? } when the user changes
row selection through table affordances.
| Event | Payload | Trigger | Stability | Notes |
|---|---|---|---|---|
rowClick |
{ row, index } |
Clique em linha. | Partial | Preservado da documentação anterior. |
rowDoubleClick |
{ action, row } |
Duplo clique quando habilitado. | Partial | Preservado da documentação anterior. |
rowExpansionChange |
RowExpansionChangeEvent |
Evento canônico para expand/collapse de detail row no runtime P0A (caminho não virtualizado), com payload discriminado por política de exposição (allowRawExposure + eventExposureDefault). |
Partial | Preservado da documentação anterior. |
rowAction |
{ action, row, payload?, actionConfig?, localMode?, preventedHttp? } |
Acao de linha (coluna _actions ou renderer interativo). payload e emitido quando houver payloadExpr em renderer interativo. |
Partial | Preservado da documentação anterior. |
toolbarAction |
{ action, actionConfig? } |
Acao clicada em toolbar.actions[] que nao foi roteada para fluxo bulk; actionConfig carrega o objeto da acao quando disponivel. |
Partial | Preservado da documentação anterior. |
bulkAction |
{ action, rows, actionConfig? } |
Acao em lote; actionConfig carrega a configuracao da acao quando disponivel. |
Partial | Preservado da documentação anterior. |
columnReorder |
`{ action, trigger: 'drag' \ | 'keyboard' \ | Partial | Preservado da documentação anterior. |
columnReorderAttempt |
`{ action: 'columnReorderAttempt', trigger: 'drag' \ | 'keyboard', operationId, tableId, sourceField, targetField, previousIndex, currentIndex, sourceZone, targetZone, result: 'blocked', reasonCode: 'drop-zone-policy-blocked', configuredColumnDropZones[] }` | Partial | Preservado da documentação anterior. |
columnResize |
{ action: 'columnResize', trigger: 'pointer' | 'keyboard' | 'auto-fit', tableId, field, header, previousWidth, currentWidth, persisted } |
Separador de resize no header. | Partial | Mutacao visual/runtime de largura; nao redefine schema nem dados. A tabela ocupa ao menos o viewport, pode crescer com scroll horizontal e, com autoFit !== false, ajusta a coluna ao conteúdo renderizado por duplo clique. |
beforeDelete |
row |
Antes de delete de linha. | Partial | Preservado da documentação anterior. |
afterDelete |
row |
Depois de delete com sucesso. | Partial | Preservado da documentação anterior. |
deleteError |
{ row, error } |
Erro no delete de linha. | Partial | Preservado da documentação anterior. |
beforeBulkDelete |
rows[] |
Antes de bulk delete. | Partial | Preservado da documentação anterior. |
Styling API
CSS vars principais
| CSS var | Efeito |
|---|---|
--p-table-header-bg |
fundo do header |
--p-table-header-fg |
cor de texto/icone do header |
--p-table-border-color |
cor de borda da tabela |
--p-table-row-even-bg |
zebra row |
--p-table-row-hover-bg |
hover row |
--p-table-row-selected-bg |
row selecionada |
--p-table-row-height |
altura da linha; sobrescreve o default do preset de densidade |
--p-table-header-height |
altura do header; sobrescreve o default do preset de densidade |
--p-table-column-resize-hit-area |
area clicavel do separador de resize |
--p-table-column-resize-separator-color |
cor base da divisoria de resize |
--p-table-column-resize-separator-hover-color |
cor da divisoria em hover/focus |
--p-table-column-resize-active-color |
cor da divisoria durante resize |
--p-header-padding |
padding do header |
--p-cell-padding |
padding das células; sobrescreve o default do preset de densidade |
--p-header-font-size |
fonte do header |
--p-header-font-weight |
peso do header |
--p-header-letter-spacing |
tracking do header |
--p-header-text-transform |
caixa do texto do header |
--p-table-reorder-transition-duration |
duracao da animacao de reorder das colunas |
--p-table-drag-preview-scale |
escala visual do preview durante drag |
--p-table-drag-preview-shadow |
sombra do preview durante drag |
--p-table-drag-status-enter-duration |
duracao da entrada da mensagem visual de reorder |
--p-actions-btn-size |
tamanho da superfície visível dos botões de ação; o alvo interativo permanece em 44px |
--p-actions-icon-size |
tamanho dos ícones de ação dentro da superfície canônica |
--p-table-paginator-container-min-height |
altura minima do paginator |
--p-table-paginator-container-padding |
padding do paginator |
--p-table-paginator-container-gap |
espaçamento entre controles do paginator |
--p-table-paginator-action-size |
tamanho dos botoes de navegacao do paginator |
--p-table-paginator-select-width |
largura do seletor de tamanho de pagina |
--p-table-paginator-select-height |
altura do seletor de tamanho de pagina |
--p-table-paginator-select-padding-inline |
padding horizontal do seletor de tamanho de pagina |
--p-table-state-success-* |
tokens de estado success |
--p-table-state-warning-* |
tokens de estado warning |
--p-table-state-danger-* |
tokens de estado danger |
--p-table-state-highlight-* |
tokens de estado highlight |
Host classes
| Classe no host | Efeito |
|---|---|
density-compact |
densidade compacta |
density-comfortable |
densidade padrao |
density-spacious |
densidade espacada |
row-borders |
bordas horizontais entre linhas |
col-borders |
bordas verticais entre colunas |
pfx-column-drag-enabled |
habilita layout base de DnD de colunas |
pfx-column-drag-indicator |
habilita indicador visual de drag |
pfx-column-resize-enabled |
habilita separadores de resize no header |
pfx-column-resizing |
estado ativo enquanto uma coluna esta sendo redimensionada |
appearance.density seleciona apenas o preset de defaults. appearance.spacing.* e defaults globais também alimentam tokens *-default. Hosts podem redefinir livremente os tokens finais sem depender de seletores internos, por exemplo --p-table-row-height, --p-table-header-height, --p-cell-padding, --p-actions-btn-size e --p-table-paginator-select-height. Em virtualização sem itemHeight explícito, o runtime deriva a altura da densidade efetiva.
DnD classes (globais)
| Classe CSS | Escopo | Efeito |
|---|---|---|
pfx-column-drag-preview |
preview gerado pelo CDK (inserido globalmente) | card visual do header durante drag (gradiente, borda, sombra e escala leve) |
Horizontal scroll classes
A superficie usa horizontalScroll com classes:
scroll-autoscroll-wrapscroll-none
Em scroll-auto, o viewport e uma regiao focalizavel por teclado para que o scroll horizontal continue acessivel sem mouse, inclusive no Safari. O nome acessivel usa accessibility.ariaLabels.scrollViewport, depois toolbar.title e, por fim, o fallback localizado do runtime. scroll-wrap e scroll-none nao introduzem uma parada de tabulacao adicional.
Mobile card mode
appearance.responsive.mobile.cardMode: true materializa cada linha não virtualizada como um card rotulado quando a menor largura entre o viewport e o host da tabela entra em appearance.responsive.breakpoints.mobile. Isso inclui widgets redimensionados e painéis estreitos em desktop. Um host ainda sem medida usa o viewport como referência. A tabela continua sendo a fonte semântica e todos os campos permanecem no DOM; cada valor recebe o respectivo cabeçalho como rótulo visual. Até 480 px de área interna, rótulo e valor ficam empilhados. Essa adaptação não altera a política de horizontalScroll nem ativa cartões sem cardMode: true.
appearance.responsive.mobile.priorityColumns é uma lista ordenada de fields que aparecem primeiro no card. Campos não prioritários continuam disponíveis abaixo deles; o runtime não oculta dados silenciosamente. Tabelas virtualizadas mantêm o modo de rolagem horizontal, pois um card pode ter altura variável.
Row/cell conditional styling
rowConditionalStylesaplica classes/estilo por linha.columns[].conditionalStylesaplica por celula.- Para intenções semânticas cobertas pelo catálogo oficial, use
surfacePresetRef, por exemplo{ "id": "warning", "catalogVersion": "0.2.0" }. A versão0.2.0oferecesuccess,warning,dangerehighlightnos escopos de linha e célula. - Fundo sólido determinístico sem
colorusa foreground acessível derivado no runtime; a cor derivada não é persistida noTableConfig. colorexplícito continua sendo intenção autorada e deve atingir contraste WCAG AA (4.5:1) contra o fundo sólido efetivo.- O authoring bloqueia pares explícitos abaixo de AA. Para configuração legada ou manual que bypassou esse gate, o runtime substitui apenas o foreground renderizado por um fallback acessível e preserva o documento original para diagnóstico/correção governada.
- Hover e zebra não apagam uma superfície condicional. Seleção possui precedência explícita com seu próprio par
--p-table-row-selected-bg/--p-table-row-selected-fg. - Alpha,
var(...),cssClassexterna, gradiente e shorthand não determinístico exigem preview contextual e não devem ser declarados acessíveis apenas por validação estrutural. O fundo contextual fica adiado no HTML inicial. Após o render, o runtime aplica fundo e foreground no mesmo frame e emite evidência DOMderived-contextualsomente quando uma transparência ou variável CSS puder ser composta até uma base opaca e reduzida a uma única cor sólida. Gradientes, imagens e composições sem base opaca permanecemunresolved-suppressed, sem pintar o fundo inseguro. - Em CSP estrito, estilos condicionais inline são desativados e o runtime não faz reparos via CSSOM. Apenas um
surfacePresetRefválido é convertido na classe privada correspondente;cssClassarbitrária falha fechado. Os nomes dessas classes são detalhe interno e não fazem parte do contrato de authoring. - A observação runtime publica
affordances.visualMaterialization.inlineStyle,governedClassesurfacePresetCatalog(ID, versão, tema, modo, escopos e presets instalados), sem expor nonce ou a política CSP bruta. O backend usa essa evidência somente para restringir o preview: estilos inline exigeminlineStyle=supported; presets exigem instalação compatível comprovada. Capability ausente,unknown, versão/escopo/preset divergente ou modo de tema ainda não certificado falham fechado. mutednão integra o catálogo acessível: opacidade aplicada à linha pode compor com descendentes e invalidar o contraste. O modohigh-contrasté observado pelo runtime, mas permanece não aplicável pelo authoring até ter evidência visual certificada; o catálogo0.2.0está certificado paralightedark.- Quando a cor comunicar estado ou classificação de negócio, materialize também uma pista visível independente de cor, como marcador lateral, ícone ou label.
Examples
Minimal valid
{
"appearance": { "density": "compact" },
"columns": [
{ "field": "asset", "header": "Ativo" },
{ "field": "costPrice", "header": "Custo", "type": "currency", "format": "BRL|symbol|2" },
{ "field": "salePrice", "header": "Venda", "type": "currency", "format": "BRL|symbol|2" },
{
"field": "margin",
"header": "Margem",
"type": "currency",
"format": "BRL|symbol|2",
"computed": { "expression": { "-": [{ "var": "salePrice" }, { "var": "costPrice" }] }, "outputType": "number" }
}
],
"rowConditionalStyles": [
{ "condition": { "<": [{ "var": "computed.margin" }, 0] }, "cssClass": "row--danger" }
]
}
Typical/common
{
"columns": [
{
"field": "contact",
"header": "Cliente",
"renderer": {
"type": "compose",
"compose": {
"layout": { "direction": "row", "gap": 8, "align": "center" },
"items": [
{ "type": "avatar", "avatar": { "srcField": "photoUrl", "initialsField": "name" } },
{ "type": "value", "field": "name" },
{ "type": "badge", "badge": { "textField": "status", "variant": "soft" } }
]
}
}
}
]
}
Advanced
{
"actions": {
"row": {
"enabled": true,
"actions": [
{
"id": "approve",
"label": "Aprovar",
"action": "approve",
"visibleWhen": { "===": [{ "var": "status" }, "PENDENTE"] }
}
]
},
"bulk": {
"enabled": true,
"position": "toolbar",
"actions": [
{
"id": "delete",
"label": "Excluir selecionados",
"action": "delete",
"minSelections": 1,
"requiresConfirmation": true
}
]
}
},
"messages": {
"actions": {
"confirmations": {
"deleteMultiple": "Tem certeza que deseja excluir os itens selecionados?"
}
}
}
}
Enterprise scenario
{
"columns": [
{
"field": "ageDays",
"header": "Dias em aberto",
"computed": { "expression": { "daysSince": [{ "var": "createdAt" }] }, "outputType": "number" }
}
],
"rowConditionalStyles": [
{
"condition": {
"and": [
{ ">": [{ "var": "computed.ageDays" }, 5] },
{ "!==": [{ "var": "status" }, "RESOLVIDO"] }
]
},
"cssClass": "row--danger text-bold"
}
],
"rowConditionalRenderers": [
{
"condition": {
"and": [
{ ">": [{ "var": "computed.ageDays" }, 5] },
{ "!==": [{ "var": "status" }, "RESOLVIDO"] }
]
},
"tooltip": { "text": "SLA violado: acao imediata necessaria", "position": "top" },
"animation": { "preset": "warning-attention", "repeat": 3 }
}
]
}
Known limitations and mismatches
| Path/Behavior | Observed behavior (runtime) | Desired behavior | Impact | Tracking issue | Target fix |
|---|---|---|---|---|---|
| coverage/mapping | Evidência textual preservada indica itens Partial/Declared-only. | Cobertura confirmada por evidência runtime + schema + editor. | Pode gerar uso de paths não totalmente ligados. | to-be-linked | next-doc-cycle |
Compatibility and migration notes
- No corte beta que unificou o lifecycle operacional, consumidores que chamavam diretamente os helpers públicos do componente devem migrar
canCancelRemoteLoad()paracanCancelLoad()ecancelRemoteLoad()paracancelLoad(). Não há aliases paralelos. - Paths e aliases legados continuam aceitos para compatibilidade (
behavior.virtualScroll.*, chaves legadas de header emactions.row.*), mas novos contratos devem usar caminhos canonicos atuais. - O side-channel de overrides CRUD (
crud-overrides:<componentKeyId>) nao faz parte doTableConfig; mantenha migracao/backup dessa chave separado do payload principal. - Para regex em regras, a forma canonica persistida e infixa (
field matches value);matches(field, value)permanece como legado suportado. - O editor manual de regras da tabela autora apenas JSON Logic.
- Se houver comportamento divergente entre schema e runtime, priorize as indicacoes desta pagina em
Known limitations and mismatchese mantenhahas_known_mismatches=trueno frontmatter enquanto a lacuna existir.
Source references
projects/praxis-table/src/lib/praxis-table.tsprojects/praxis-table/src/lib/praxis-table.htmlprojects/praxis-table/src/lib/praxis-table.scssprojects/praxis-table/src/lib/praxis-table-toolbar.tsprojects/praxis-table/src/lib/praxis-table-config-editor.tsprojects/praxis-table/src/lib/behavior-config-editor/behavior-config-editor.component.tsprojects/praxis-table/src/lib/header-appearance-editor/header-appearance-editor.component.tsprojects/praxis-table/src/lib/columns-config-editor/columns-config-editor.component.tsprojects/praxis-table/src/lib/rules-editor/table-rules-editor.component.tsprojects/praxis-table/src/lib/toolbar-actions-editor/toolbar-actions-editor.component.tsprojects/praxis-table/src/lib/filter-settings/filter-settings.component.tsprojects/praxis-table/src/lib/messages-localization-editor/messages-localization-editor.component.tsprojects/praxis-table/src/lib/dialogs/confirm-dialog-appearance-editor.component.tsprojects/praxis-table/src/lib/crud-integration-editor/crud-integration-editor.component.tsprojects/praxis-core/src/lib/models/table-config-v2.model.tsprojects/praxis-table/src/lib/utils/action-utils.tsprojects/praxis-core/src/lib/tokens/global-action.catalog.tsprojects/praxis-core/src/lib/models/global-action.model.tsprojects/praxis-core/src/lib/actions/global-action-ui.ts
Appendix: JSON path index
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
columns[] |
TableColumnConfig[] |
Yes | [] |
Active | Definicao de colunas, renderers e regras de exibicao. |
behavior |
TableBehaviorConfig |
No | defaults do runtime | Partial | Inclui paginacao, filtro, selecao e expansao por blocos. |
toolbar.actions[] |
ToolbarActionConfig[] |
No | [] |
Partial | Acoes de toolbar com roteamento para toolbarAction e bulkAction. |
toolbar.title |
string |
No | undefined |
Active | Titulo renderizado na regiao de identidade da toolbar principal, antes de filtros e acoes. |
toolbar.subtitle |
string |
No | undefined |
Active | Texto auxiliar renderizado abaixo do titulo quando houver espaco. |
toolbar.icon |
string |
No | undefined |
Active | Icone semantico renderizado junto ao titulo da toolbar via PraxisIconDirective. |
toolbar.textAlign |
'start' | 'center' | 'end' |
No | 'start' |
Active | Alinhamento textual do bloco de identidade da toolbar. |
toolbar.appearance |
TableToolbarAppearanceConfig |
No | fallback M3 | Active | Chrome visual governado da toolbar; tokens viram --p-table-toolbar-* no runtime. |
toolbar.appearance.tokens.titleFg |
string |
No | fallback M3 | Active | Cor do titulo na identidade da toolbar; use tokens semanticos do host para suportar tema claro/escuro. |
toolbar.appearance.tokens.subtitleFg |
string |
No | fallback M3 | Active | Cor do subtitulo na identidade da toolbar. |
toolbar.appearance.tokens.iconFg |
string |
No | fallback M3 | Active | Cor do icone da identidade; o fundo tonal e derivado dessa cor para manter contraste suave. |
toolbar.appearance.tokens.titleFontSize |
string |
No | 14px |
Active | Tamanho tipografico do titulo da identidade. |
toolbar.appearance.tokens.subtitleFontSize |
string |
No | 11.5px |
Active | Tamanho tipografico do subtitulo da identidade. |
toolbar.appearance.tokens.titleFontWeight |
string |
No | 700 |
Active | Peso tipografico do titulo da identidade. |
toolbar.appearance.tokens.identityGap |
string |
No | 8px |
Active | Espaco entre icone e copy da identidade da toolbar. |
toolbar.appearance.tokens.identityFilterGap |
string |
No | 8px |
Active | Respiro vertical entre identidade e filtros/controles quando a identidade ocupa linha propria. |
toolbar.appearance.tokens.identityMinHeight |
string |
No | 30px |
Active | Altura minima do bloco de identidade da toolbar. |
toolbar.appearance.tokens.identityMarginBottom |
string |
No | 2px |
Active | Espacamento inferior complementar da identidade da toolbar. |
toolbar.appearance.tokens.identityIconSize |
string |
No | 28px |
Active | Tamanho do container do icone da identidade. |
toolbar.appearance.tokens.identityIconRadius |
string |
No | 8px |
Active | Raio do container do icone da identidade. |
toolbar.columnsVisibility |
object |
No | habilitado se a toolbar estiver ativa | Active | Controle rápido de visibilidade de colunas no toolbar (dropdown). |
toolbar.filters.quickFilters[] |
ToolbarFilterConfig[] |
No | [] |
Active | Seletor de escopo governado: no máximo um filtro rápido é combinado com os critérios ativos; acionar o item atual restaura os critérios anteriores. |
toolbar.densityToggle |
object |
No | desabilitado | Active | Seletor governado de densidade com opções compact, comfortable e spacious. |
messages |
TableMessagesConfig |
No | defaults internos | Partial | Overrides de i18n e mensagens operacionais. |
data |
TableDataConfig |
No | modo local/remoto autodetectado | Partial | Integra origem local ou remota conforme resourcePath/inputs. |
Appendix: Events summary
selectionChange emits { trigger, row?, selectedRows, selectedCount, tableId?, resourceIdentity? }
for row selection changes initiated by the user and with trigger: "data-reconcile"
when a data update removes identities from the effective selection. Rehydrating the
same identities does not emit a new selection event.
Assistant turns can also receive the selected-row digest as context; textual matching on row values must not decide primary intent.
| Event | Payload | Trigger | Stability |
|---|---|---|---|
rowClick |
{ row, index } |
clique de linha no corpo da tabela | Partial |
rowAction |
{ action, row, payload?, actionConfig? } |
acao interativa de linha (_actions/renderer); navigation.openRoute resolve templates de linha antes da execucao e surface.open preserva payload.* como envelope canonico do evento |
Partial |
toolbarAction |
{ action, actionConfig? } |
acao de toolbar fora de fluxo bulk | Partial |
exportAction |
{ format, request?, result?, error?, tableId? } |
exportacao por PraxisCollectionExportRequest |
Active |
bulkAction |
{ action, rows, actionConfig? } |
acao em lote sobre linhas selecionadas | Partial |
loadingStateChange |
LoadingState |
mudanca de estado (config/schema/data/render) |
Active |
Appendix: Styling API summary
| Token/Class | Scope | Purpose | Notes |
|---|---|---|---|
--p-table-header-bg / --p-table-header-fg |
css vars | aparencia de cabecalho e contraste | Tokens principais de tema para header. |
--p-table-row-* |
css vars | zebra, hover e estado selecionado de linha | Aplicados no runtime de render da tabela. |
density-compact / density-comfortable / density-spacious |
host classes | controle de densidade visual | Derivadas de appearance.density. |
.pfx-column-drag-enabled |
host class | habilita feedback visual de reordenacao | Ativada quando contrato de reorder esta habilitado. |
.pfx-column-drag-indicator |
host class | indicador visual durante drag/drop | Integrada ao runtime de columnReorder. |
.praxis-header-sort-trigger |
internal header zone | zona dedicada de sort no header | Recebe mat-sort-header; reorder por drag continua implicito no header cell. |
Fallback global de aparencia
Quando o host salva GlobalConfig.table.appearance, a tabela usa esses valores como fallback corporativo para:
appearance.densityappearance.spacing.cellPaddingappearance.spacing.headerPaddingappearance.typography.fontSizeappearance.typography.headerFontSize
Precedencia efetiva:
TableConfiglocal informado pelo hostGlobalConfig.table.appearance- defaults hardcoded de
createDefaultTableConfig()
Campos fora de table.appearance mantem a semantica anterior de fallback do provider.
Editor and tooling notes
- Cobertura de editor/tooling foi separada da cobertura de runtime para evitar confusao de suporte.
- Quando nao houver evidencia direta no codigo, o status deve permanecer not yet verified.
Appendix: Examples summary
Appendix minimal valid
{
"columns": []
}
Appendix typical/common
{
"columns": [
{
"field": "name",
"header": "Nome"
}
],
"behavior": {
"pagination": {
"enabled": true,
"pageSize": 25
}
}
}
Appendix advanced
{
"columns": [
{
"field": "status",
"header": "Status",
"renderer": {
"type": "badge"
}
}
],
"toolbar": {
"actions": [
{
"id": "refresh",
"label": "Atualizar"
}
]
},
"behavior": {
"selection": {
"mode": "multiple"
}
}
}
Appendix enterprise scenario
{
"columns": [],
"messages": {
"emptyState": "Nenhum registro encontrado."
},
"behavior": {
"expansion": {
"enabled": true
}
},
"data": {
"mode": "remote",
"resourcePath": "customers/table"
}
}
Nota: exemplos especificos do componente foram preservados na secao detalhada para evitar perda de cobertura durante esta migracao canonicamente orientada.
Known limitations and mismatches
| Path/Behavior | Observed behavior (runtime) | Desired behavior | Impact | Tracking issue | Target fix |
|---|---|---|---|---|---|
| coverage/mapping | Documento anterior indica cobertura parcial ou declared-only. | Cobertura totalmente rastreada por superficie. | Pode haver diferenca entre schema e runtime/editor. | to-be-linked | next-doc-cycle |
Compatibility and migration notes
| Concern | Affected versions | Migration action | Deadline | Notes |
|---|---|---|---|---|
| legacy aliases and mixed status vocabulary | pre-canonical docs | unificar para taxonomia canonica (Active/Partial/Declared-only/...) | next-doc-cycle | manter backward compatibility documentada |
Governed embeds
Contextual detail presentation
behavior.detail owns the shared schema, source, rendering, height and lazy-load configuration. presentation.placement selects row (the default) or bottom; presentation.initiallyCollapsed sets the initial disclosure state. For bottom presentation, presentation.bottomStackPosition selects afterControls (the default) or beforeControls, and presentation.emptyBehavior selects an instructional message (the default) or hide. A missing height defaults to dynamic sizing. height.mode accepts explicit dynamic or fixed; fixed mode requires a positive px. behavior.expansion owns row interaction only. Do not store detail inside expansion: the finite migration moves that branch and rejects differing old/new definitions. Runtime does not read the old path.
Bottom detail uses the existing selection model. Exactly one visible record with a stable identity may provide the body. Zero or multiple selections retain an explicit empty/status region; a retained selection outside the current page never reads a detail body. Refreshing the same ID refreshes its context. Selection never executes a business action.
Use detail.presentation.configure to choose bottom: it disables row expansion and enables single selection when selection is disabled, preserving an already enabled multiple-selection policy. Choosing row enables row expansion; disabling detail disables expansion. Conflicting hand-authored configurations fail closed. detail.configure and expansion.configure apply their declared activation semantics. detail.source.configure changes only the source; extension properties inside that source never act as presentation commands. Unknown extensions remain preserved, while malformed known groups, booleans and source modes block Apply. An existing dynamic height requires an explicit positive fixed-height adjustment before choosing bottom.
The Details section edits the authored tree and preserves field expressions, unknown nodes and provider references. Its local preview does not perform remote reads or persist sample values. Invalid advanced JSON blocks Apply/Save. Discard restores detail edits; global defaults retain their existing reset semantics.
The bottom body defaults to dynamic height with a small-viewport CSS limit. Fixed mode starts at 192px in the editor and provides vertical scrolling. It is outside the virtual viewport and defaults to after the footer controls, preserving the collection stack. Explicit collapse persists across selection changes. Inline charts require the Charts provider; unresolved references remain explained placeholders.
behavior.detail.schemaContract.allowedNodesagora tambem pode incluirformRef,tableRef,chartRef,templateRefediagramEmbed.- Esses nodes continuam host-mediated:
- o host resolve discovery, registry, abertura e policy
- a tabela padroniza o shell, os metadados e a CTA do embed
- o miolo visual continua delegado para
PraxisRichContent
diagramEmbedadicionaprovider,sourceousourceFieldpara preview governado de diagrama, sem abrir uma segunda DSL de detail row.
type DetailEmbedNode = {
type: 'formRef' | 'tableRef' | 'chartRef' | 'templateRef';
title?: string;
subtitle?: string;
description?: string;
caption?: string;
emptyText?: string;
schemaId?: string;
templateId?: string;
inputs?: Record<string, unknown>;
presetRef?: CorePresetRef;
action?: {
actionId: string;
label: string;
icon?: string;
payloadExpr?: string;
visibleWhen?: JsonLogicExpression | null;
disabledWhen?: JsonLogicExpression | null;
};
};
type DiagramEmbedNode = {
type: 'diagramEmbed';
title?: string;
subtitle?: string;
description?: string;
caption?: string;
emptyText?: string;
provider: 'mermaid' | 'bpmn' | 'custom';
source?: string;
sourceField?: string;
inputs?: Record<string, unknown>;
presetRef?: CorePresetRef;
action?: {
actionId: string;
label: string;
icon?: string;
payloadExpr?: string;
visibleWhen?: JsonLogicExpression | null;
disabledWhen?: JsonLogicExpression | null;
};
};
Filter presentation
FilterPresentationConfig is owned by Core. Tables author it at behavior.filtering.advancedFilters.settings.presentation; standalone filters use FilterConfig.presentation, projected directly to the runtime presentation input. It changes presentation only, never the filter DTO or query semantics.
With filter persistence enabled, an acknowledged persisted FilterConfig.presentation overrides the authored input for the same component identity on reload. Apply remains a preview-only operation. Hosts that require input-only materialization set disablePersistence, which prevents preference loading and saving.
The guided preferences editor roundtrips the complete effective FilterConfig; changing presentation or another managed section preserves unmanaged siblings such as selectedFieldIds and field metadata overrides.
{
"header": { "visible": true, "text": "Filtros", "position": "above", "size": "medium" },
"advancedAction": { "display": "icon-text", "text": "Mais filtros", "icon": "filter_list", "size": "compact", "position": "end" }
}
| Region | Optional properties |
|---|---|
header |
visible: boolean, text: string, icon: string, position: above | inline, size: small | medium | large |
advancedAction |
display: icon | text | icon-text, text: string, icon: string, size: compact | standard, position: start | end |
tokens |
String values for gap, headerGap, headerColor, headerFontSize, headerFontWeight, iconSize, actionGap, actionFontSize, actionFontWeight |
Absent presentation preserves the existing icon action and hidden heading. header.visible explicitly enables the heading. An empty icon removes that icon. If the advanced action uses icon-only display with an empty icon, it falls back to its localized/authored text so the action remains discoverable. Text-only display never renders an icon. Nonempty authored text takes precedence over localized copy and the default catalog label. Empty or whitespace-only header/action text inherits the localized label, so it cannot create an unnamed action. Action position applies inside the auxiliary controls group, not the page. Existing showAdvancedButton controls whether the advanced action is available; presentation introduces no second visibility switch.
The embedded table supplies the heading, advanced-action label, dialog title and opening/unavailable feedback from the praxisTableRuntime catalog through the existing filter i18n input. Host locale changes and external translator overrides apply without modifying the filter query. Explicit presentation text still wins; clearing it restores catalog resolution. Standalone filters keep their explicit i18n input. Other legacy filter-manager copy is outside this localized projection.
Tokens project to CSS custom properties --pfx-filter-gap, --pfx-filter-header-gap, --pfx-filter-header-color, --pfx-filter-header-font-size, --pfx-filter-header-font-weight, --pfx-filter-icon-size, --pfx-filter-action-gap, --pfx-filter-action-font-size, and --pfx-filter-action-font-weight. Prefer the semantic size/position controls for ordinary authoring; tokens are for deliberate theme customization.
AI authoring extends existing operations: filter.advanced.configure receives settings.presentation for tables; filter.settings.configure receives presentation for standalone filters. Neither operation authors a query through this object.
Corporate context changes use the existing EnterpriseRuntimeContextService: Table invalidates rows, selection, discovery and pending data/detail responses before a new remote load. Local hosts must replace data for the effective context and discard their own obsolete asynchronous deliveries. This is runtime state isolation, not backend authorization. initiallyCollapsed is reapplied after persisted hydration and configuration Apply.