Datagrid
Grid de dados interativo (`mk-datagrid`) com ordenação, paginação, colunas fixas, trocadas e redimensionadas, virtualização, células customizadas, edição, editor de opções, preenchimento para baixo e para cima, linhas expansíveis e seleção.
O mk-datagrid exibe e opera grandes volumes de dados tabulares: ordenação, paginação, colunas fixas, ocultas, trocadas e redimensionadas, virtualização, células customizadas, estados vazio e carregando, edição (texto, máscara e opções), preenchimento para baixo e para cima, linhas expansíveis e seleção de linhas. A navegação segue o padrão grid da WAI-ARIA APG, com uma única parada de Tab e setas entre as células. Para tabelas estáticas e pequenas, use o Table.
Padrão
columns e rows são arrays. Cada linha precisa de um identificador estável, lido por rowKey (padrão "id"). O grid nunca altera rows: toda mudança de dado é emitida como evento e aplicada pelo consumidor.
import { MkDatagrid, type MkDatagridColumn } from '@db1/makuco-ui-react';
const columns: MkDatagridColumn<Pessoa>[] = [
{ key: 'nome', label: 'Nome', sortable: true, rowHeader: true },
{ key: 'cargo', label: 'Cargo', sortable: true },
{ key: 'unidade', label: 'Unidade' },
{ key: 'email', label: 'E-mail', width: 240 },
];
<MkDatagrid caption="Pessoas" columns={columns} rows={pessoas} />import { MK_DATAGRID } from '@db1/makuco-ui-angular';
import { defineColumns } from '@db1/makuco-ui-core';
@Component({
imports: [MK_DATAGRID],
template: `<mk-datagrid caption="Pessoas" [columns]="columns" [rows]="pessoas"></mk-datagrid>`,
})
export class PessoasComponent {
columns = defineColumns<Pessoa>([
{ key: 'nome', label: 'Nome', sortable: true, rowHeader: true },
{ key: 'cargo', label: 'Cargo', sortable: true },
{ key: 'unidade', label: 'Unidade' },
{ key: 'email', label: 'E-mail', width: 240 },
]);
pessoas: Pessoa[] = [];
}rowKey aceita o nome do campo ou uma função (row) => string. Quando não resolve um valor, o grid usa o índice da linha e avisa em desenvolvimento.
Tipos das linhas e colunas
rows aceita interface e type. As colunas tipadas pela linha (accessor, editable.options e fillable.formula recebem TRow) são declaradas com o tipo exportado: MkDatagridColumn<TRow>[] no React (acrescenta cell) e DatagridColumn<TRow>[] no Angular e em JS puro. defineColumns<TRow>([...]) é um atalho equivalente.
import { MkDatagrid, type MkDatagridColumn } from '@db1/makuco-ui-react';
interface Pessoa { id: string; nome: string; salario: number }
const columns: MkDatagridColumn<Pessoa>[] = [
{ key: 'nome', label: 'Nome' },
{ key: 'salario', label: 'Salário', accessor: (pessoa) => brl(pessoa.salario) },
];
<MkDatagrid caption="Pessoas" columns={columns} rows={pessoas} />import { defineColumns } from '@db1/makuco-ui-core';
interface Pessoa { id: string; nome: string; salario: number }
columns = defineColumns<Pessoa>([
{ key: 'nome', label: 'Nome' },
{ key: 'salario', label: 'Salário', accessor: (pessoa) => brl(pessoa.salario) },
]);Regra de controle
A regra vale para as sete props de estado (sorting, page, pageSize, expandedRows, selectedRows, columnOrder, columnWidths): com um valor (inclusive []), o estado é controlado; com null ou undefined, o grid controla o estado, o que cobre o | async do Angular antes do primeiro valor. Ao voltar a null depois de controlada, o grid continua do último valor controlado, como estado interno. Cada evento traz o estado resultante no tipo da prop.
| Prop | Evento | Estado no evento |
|---|---|---|
sorting | mkSortChange | detail.sorting |
page | mkPageChange | detail.page |
pageSize | mkPageSizeChange | detail.pageSize |
expandedRows | mkRowExpand | detail.expandedRows |
selectedRows | mkSelectionChange | detail.selectedRows |
columnOrder | mkColumnOrderChange | detail.columnOrder |
columnWidths | mkColumnWidthsChange | detail.columnWidths |
const [selectedRows, setSelectedRows] = useState<string[]>([]);
<MkDatagrid
caption="Pessoas"
columns={columns}
rows={pessoas}
selectable
selectedRows={selectedRows}
onMkSelectionChange={({ detail }) => setSelectedRows(detail.selectedRows)}
/>selectedRows$ = new BehaviorSubject<string[] | null>(null);<mk-datagrid
caption="Pessoas"
[columns]="columns"
[rows]="pessoas"
[selectable]="true"
[selectedRows]="selectedRows$ | async"
(mkSelectionChange)="selectedRows$.next($event.detail.selectedRows)"
></mk-datagrid>Opções de coluna
rowHeadermarca as células da coluna comrole="rowheader": elas nomeiam a linha para leitores de tela e para o rótulo do botão de expandir.helperTextmostra o ícone de ajuda no cabeçalho, com tooltip no hover e no foco.alignalinha conteúdo e cabeçalho (start,center,end). Useendpara números.accessorcalcula o valor de colunas sem campo nos dados ou derivadas. Ele é o valor usado na ordenação.hidden: trueoculta a coluna. Para alternar, passe um novo array decolumns.
const columns: MkDatagridColumn<Pessoa>[] = [
{ key: 'nome', label: 'Nome', rowHeader: true },
{ key: 'salario', label: 'Salário', align: 'end', helperText: 'Valor bruto mensal', accessor: (p) => brl(p.salario) },
];columns = defineColumns<Pessoa>([
{ key: 'nome', label: 'Nome', rowHeader: true },
{ key: 'salario', label: 'Salário', align: 'end', helperText: 'Valor bruto mensal', accessor: (p) => brl(p.salario) },
]);Ordenação
sortable na coluna ordena localmente. sorting é uma lista de DatagridSort ({ columnKey, direction }, hoje uma entrada só): com ela, o grid emite mkSortChange e espera a prop mudar, e [] é controlado sem ordenação. detail.sorting traz a ordenação resultante, pronta para voltar à prop. Com manualSorting, o grid não reordena as linhas, para a ordenação no servidor.
A regra de controle está em Regra de controle.
import type { DatagridSort } from '@db1/makuco-ui-core';
import { MkDatagrid } from '@db1/makuco-ui-react';
const [sorting, setSorting] = useState<DatagridSort[]>([]);
<MkDatagrid
caption="Pessoas"
columns={columns}
rows={rows}
manualSorting
sorting={sorting}
onMkSortChange={({ detail }) => setSorting(detail.sorting)}
/><mk-datagrid
caption="Pessoas"
[columns]="columns"
[rows]="rows"
[manualSorting]="true"
[sorting]="sorting"
(mkSortChange)="sorting = $event.detail.sorting"
></mk-datagrid>Colunas fixas, zebrado e destaque
pinned: "start" ou "end" mantém a coluna visível na rolagem horizontal. striped alterna o fundo a partir da 1ª linha. highlightedRows destaca linhas por rowId ou por predicado.
mkRowClick dispara no clique na linha, exceto quando o clique nasce num conteúdo interativo da célula: controle nativo, elemento com papel de controle, host com focável no shadow aberto (como mk-button) ou elemento com data-mk-no-row-click.
Os exemplos completos em React e Angular estão no Storybook.
Larguras e quebra de linha
width fixa a largura em px. Colunas sem width dividem o espaço livre na proporção de flex (padrão 1), sem ficar abaixo de minWidth (padrão 120 px). O texto longo termina em reticências; wrap: true quebra o texto da coluna e deixa a linha crescer, também com virtual.
const columns = [
{ key: "nome", label: "Nome", width: 180 },
{ key: "descricao", label: "Descrição", flex: 2, minWidth: 240, wrap: true },
{ key: "cidade", label: "Cidade" },
];Células customizadas
Em React, cell na coluna renderiza o conteúdo por portal na mesma árvore React: contexto, hooks e Providers funcionam. Também é possível declarar <MkDatagridCell name="status"> como filho e apontar template: "status" na coluna. Com React.lazy e Suspense, o registro de um MkDatagridCell pode levar mais de um frame, e o aviso de template ausente pode aparecer nesse intervalo.
Em Angular, use ng-template[mkDatagridCell] com o mesmo nome de column.template. Sem [inferRow], let-row é any; com as linhas no input, ganha o tipo delas.
Os wrappers montam um componente ou uma view por célula visível e não reaproveitam conteúdo entre linhas.
Em JavaScript sem framework, renderTemplate(name, ctx, container) monta o conteúdo no contêiner e pode devolver { update, destroy, recycle }.
Os exemplos completos em React e Angular estão no Storybook.
Cabeçalho customizado
headerTemplate na coluna indica o conteúdo do cabeçalho; sem ele, o cabeçalho mostra label. O template ocupa só a área do rótulo: ordenação, ajuda, troca e redimensionamento continuam do grid. O contexto traz label, columnKey, columnIndex, align e sort, sem row.
import { MkDatagrid, MkIcon, type MkDatagridColumn } from '@db1/makuco-ui-react';
const columns: MkDatagridColumn<Pedido>[] = [
{
key: 'entrega',
label: 'Entrega',
sortable: true,
header: ({ label }) => (
<>
<MkIcon name="calendar" size="sm" /> {label}
</>
),
},
];
<MkDatagrid caption="Pedidos" columns={columns} rows={pedidos} />Para reaproveitar o template em várias colunas, use headerTemplate: 'comIcone' na coluna e <MkDatagridHeader name="comIcone">{(ctx) => ...}</MkDatagridHeader> como filho do grid.
import { MK_DATAGRID, MkIcon } from '@db1/makuco-ui-angular';
import { defineColumns } from '@db1/makuco-ui-core';
@Component({
imports: [MK_DATAGRID, MkIcon],
template: `
<mk-datagrid caption="Pedidos" [columns]="columns" [rows]="pedidos">
<ng-template mkDatagridHeader="comIcone" let-label="label">
<mk-icon name="calendar" size="sm"></mk-icon> {{ label }}
</ng-template>
</mk-datagrid>
`,
})
export class PedidosComponent {
columns = defineColumns<Pedido>([
{ key: 'entrega', label: 'Entrega', sortable: true, headerTemplate: 'comIcone' },
]);
pedidos: Pedido[] = [];
}- O nome acessível do cabeçalho é sempre o
label. Um número no template (como o3de um badge) não é anunciado nocolumnheader: usehelperTextou mostre o dado nas células. - Um controle no template (como um botão de filtro) não ordena a coluna ao ser clicado. Enter ou F2 no cabeçalho entra nos controles e Esc volta.
- O conteúdo do template é uma linha flex centralizada na vertical: ícone, chip e texto ficam no mesmo eixo do handle, da ajuda e do botão de ordenação. Conteúdo mais largo que a coluna é cortado, sem reticências, e os botões de ajuda e de ordenação continuam visíveis.
- As colunas de seleção e de expansão não aceitam template de cabeçalho.
Exemplos com contador, filtro rápido e sort do contexto estão no Storybook.
Altura das linhas
Por padrão, a linha do corpo tem no mínimo --mk-datagrid-row-height (44 px) e cresce com o conteúdo: colunas com wrap, templates de célula mais altos, editores. Sem conteúdo alto, a linha continua com 44 px. rowHeight fixa a altura de toda linha do corpo, em px: o conteúdo que não cabe é cortado e wrap não tem efeito. O cabeçalho mantém a altura nos dois casos.
<MkDatagrid virtual rowHeight={36} columns={columns} rows={rows} /><mk-datagrid virtual [rowHeight]="36" [columns]="columns" [rows]="rows"></mk-datagrid>Virtualização
virtual monta só as linhas visíveis e mede cada uma: wrap e templates altos funcionam, e --mk-datagrid-row-height é a estimativa das linhas ainda não medidas. Em listas muito grandes com conteúdo uniforme, rowHeight dispensa a medição e dá a rolagem mais precisa. O grid ocupa a altura do pai; sem altura no pai, usa --mk-datagrid-height ou 480 px. As linhas fora da janela não estão no DOM; aria-rowcount e aria-rowindex informam o total e a posição real.
Os exemplos completos em React e Angular estão no Storybook.
Paginação no servidor
pagination mostra o mk-pagination abaixo do grid e fatia rows localmente (25 por página). Com manualPagination e totalItems, rows é a página vinda do servidor; page e pageSize controlam a posição. Com loading, a página vira linhas de skeleton na mesma quantidade, e a paginação fica desabilitada.
<MkDatagrid
caption="Pessoas"
columns={columns}
rows={pagina}
loading={loading}
pagination
manualPagination
page={page}
pageSize={pageSize}
totalItems={total}
pageSizeOptions={[10, 25, 50]}
onMkPageChange={({ detail }) => carregar(detail.page, pageSize)}
onMkPageSizeChange={({ detail }) => carregar(1, detail.pageSize)}
/><mk-datagrid
caption="Pessoas"
[columns]="columns"
[rows]="pagina"
[loading]="loading"
[pagination]="true"
[manualPagination]="true"
[page]="page"
[pageSize]="pageSize"
[totalItems]="total"
[pageSizeOptions]="[10, 25, 50]"
(mkPageChange)="carregar($event.detail.page, pageSize)"
(mkPageSizeChange)="carregar(1, $event.detail.pageSize)"
></mk-datagrid>Vazio e carregando
Sem linhas e sem loading, o grid mostra o mk-empty. Com loading, com ou sem dados anteriores, o corpo mostra linhas de mk-skeleton na proporção da tabela: as linhas da página (ou as que estavam na tela), as colunas visíveis com a largura, o alinhamento e a fixação de cada uma, e o skeleton de texto com 50% a 90% da célula. O cabeçalho continua visível; ordenação, paginação e teclado ficam bloqueados. Os slots empty e loading substituem o estado vazio e as linhas de skeleton.
<MkDatagrid caption="Pessoas" columns={columns} rows={[]} loading={loading}>
<MkEmpty slot="empty">
<MkEmptyTitle>Nenhuma pessoa encontrada</MkEmptyTitle>
</MkEmpty>
</MkDatagrid><mk-datagrid caption="Pessoas" [columns]="columns" [rows]="[]" [loading]="loading">
<mk-empty slot="empty">
<mk-empty-title>Nenhuma pessoa encontrada</mk-empty-title>
</mk-empty>
</mk-datagrid>Edição e preenchimento
editable mostra um campo sempre visível na célula, no visual do mk-table-input. Enter ou sair do campo confirma, Esc desfaz. A confirmação emite mkCellChange, e o consumidor aplica o valor em rows; sem isso, o campo volta ao valor de rows.
O valor emitido tem o tipo do valor original da linha. Com máscara numérica (number, brl), o valor é em unidades, como no mk-input-number: preco: 14.9 aparece como R$ 14,90 e emite 15.9 ao digitar R$ 15,90. Campo vazio emite null. O mk-table-input avulso usa as mesmas unidades, mas sempre como string ("15.90"). Texto que não converte não emite e marca o campo com aria-invalid.
fillable numa coluna editable replica o valor para as linhas abaixo ou acima: arrastando o quadrado de 8 × 8 px (--db1-spacing-2) que a célula ativa mostra centrado no canto inferior direito, metade para fora dela (cursor em cruz), para baixo ou para cima, ou com Shift+↓/Shift+↑ (estende o intervalo) e Ctrl+D (preenche). O grid emite mkFill com direction ('down' ou 'up'), e cada linha de destino traz o value já calculado, da origem para fora.
Editor sob medida
editable.template monta um editor próprio no lugar do campo, pelo contrato de template: o contexto recebe ctx.commit(value) e ctx.cancel(). Em React e Angular, o editor é um template de célula com o nome em editable.template. Para escolher entre opções, o editor de opções tem o visual da grid; use editable.template para componentes que ele não cobre.
Modos de preenchimento
fillable: true copia o valor da origem. Um objeto escolhe o modo: { mode: 'series' } continua número, data ISO (AAAA-MM-DD) ou Date (um dia por linha) e texto com número no fim ("Lote 001"), com passo +1 para baixo e −1 para cima; { formula } calcula cada linha de destino por uma função síncrona, da origem para fora (previous é a linha mais perto da origem).
formula recebe { source, previous, index, direction, row, rowId, columnKey } e devolve o valor da célula; undefined deixa a linha de fora, e uma exceção cancela o preenchimento. direction ('down' ou 'up') permite uma progressão espelhada: ({ previous, direction }) => direction === 'up' ? previous / 1.1 : previous * 1.1.
Editor de opções
editable.options mostra o campo da grid com um chevron no fim. A linha guarda o value da opção e o campo mostra o label (optionValue e optionLabel trocam os campos lidos). As opções são uma lista fixa ou uma função (row) => SelectOption[], chamada com a linha atual.
- Digitar filtra as opções pelo
label, sem acento e sem diferenciar maiúscula, e destaca o primeiro resultado. - ↓ abre a lista com o valor atual destacado; Enter, Tab ou o clique confirmam a opção. O chevron abre e fecha a lista.
- Ao sair do campo, um texto igual a um
labelconfirma essa opção e o campo vazio confirmanull. - Um texto sem opção correspondente não emite
mkCellChange: a célula mostra o anel de erro até a escolha de uma opção ou o Esc. - Esc com a lista aberta fecha a lista; com ela fechada, volta ao valor de
rows. - Com
fillable, o valor da origem é copiado, e a linha em que ele não está entre as opções fica de fora detargets.
Os exemplos completos em React e Angular estão no Storybook.
Linhas expansíveis
O conteúdo expandido dá à primeira coluna um botão de expandir. Em React, use renderExpanded; em Angular, <ng-template mkDatagridExpand>. expandedRows controla as linhas expandidas, e mkRowExpand informa cada mudança com o conjunto resultante em detail.expandedRows.
Os exemplos completos em React e Angular estão no Storybook.
Seleção de linhas
selectable adiciona a coluna de checkbox no início do grid. O checkbox do cabeçalho marca as linhas selecionáveis da página atual. selectedRows guarda os rowIds e controla a seleção; rowSelectable desabilita linhas. mkSelectionChange traz o conjunto resultante completo.
const [selecionadas, setSelecionadas] = useState<string[]>([]);
<MkDatagrid
caption="Pessoas"
columns={columns}
rows={pessoas}
selectable
selectedRows={selecionadas}
rowSelectable={(row) => row.status === 'Ativo'}
onMkSelectionChange={(e) => setSelecionadas(e.detail.selectedRows)}
/><mk-datagrid
caption="Pessoas"
[columns]="columns"
[rows]="pessoas"
[selectable]="true"
[selectedRows]="selecionadas"
[rowSelectable]="ativa"
(mkSelectionChange)="selecionadas = $event.detail.selectedRows"
></mk-datagrid>Troca de colunas
reorderable mostra um handle no início do cabeçalho. Arrastar o handle até outro cabeçalho troca as posições das duas colunas, dentro do mesmo grupo de fixação; uma coluna sem outra coluna visível para trocar no grupo não mostra o handle. columnOrder controla a ordem e mkColumnOrderChange informa cada troca. Por teclado, Enter no cabeçalho (F2 em colunas ordenáveis) leva ao handle, e ←/→ trocam com a vizinha.
Os exemplos completos em React e Angular estão no Storybook.
Redimensionar colunas
resizable mostra um separador na borda final do cabeçalho. A largura respeita minWidth e maxWidth da coluna; duplo clique restaura. mkColumnResize informa cada frame do arrasto, e mkColumnWidthsChange informa o conjunto final. Em Angular, mkColumnResize dispara change detection a cada frame: ouça só mkColumnWidthsChange ou use runOutsideAngular.
Os exemplos completos em React e Angular estão no Storybook.
Navegação por teclado
O grid segue o padrão grid da APG e tem dois modos.
- Navegação: uma única parada de Tab. A célula ativa é a única com
tabindex="0"(roving tabindex), as setas a movem e a linha de cabeçalho faz parte do percurso. Os focáveis dentro das células saem da ordem de Tab. - Interação: Enter ou F2 foca o conteúdo da célula (um botão, um link, o campo editável). Esc, ou Tab no último focável, volta à navegação.
Digitar numa célula editável começa a edição substituindo o valor.
| Tecla | Comportamento |
|---|---|
| Tab | Entra no grid pela célula ativa; sai do grid na próxima tecla Tab. |
| ← → ↑ ↓ | Move a célula ativa. ↑ na primeira linha vai para o cabeçalho. |
| Home / End | Primeira / última célula da linha. |
| Ctrl+Home / Ctrl+End | Primeira / última célula do grid. |
| PageUp / PageDown | Uma página visível acima / abaixo. |
| Enter / Espaço no cabeçalho | Alterna a ordenação. |
| Enter no cabeçalho sem ordenação / F2 | Foco no handle ou no separador. Esc volta ao cabeçalho. |
| ← → no handle | Troca a coluna com a vizinha válida do mesmo grupo (em RTL, ← vai para a direita). |
| ← → (Shift: 32 px) / Home / End no separador | Ajusta a largura em 8 px / mínimo / máximo. |
| Espaço | Com |
| Enter / F2 | Entra no conteúdo da célula ou no campo editável. |
| Digitar numa célula editável | Começa a edição substituindo o valor. |
| ↓ / ↑ no editor de opções | ↓ abre a lista com o valor atual destacado; ↓ e ↑ movem o destaque. |
| Enter / Tab no editor de opções | Confirmam a opção destacada; Tab segue a navegação. |
| Esc | Volta à navegação; num campo, desfaz a edição. |
| Shift+↓ ou Shift+↑ / Ctrl+D | Estende o intervalo para baixo ou para cima / preenche (colunas fillable). |
Props — mk-datagrid
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
columns | DatagridColumn[] | [] | Definição das colunas (tabela abaixo). |
rows | DatagridRow[] | [] | Linhas de dados. |
rowKey | string | (row) => string | "id" | Identificador estável da linha. |
caption | string | — | Nome acessível do grid. |
virtual | boolean | false | Virtualiza as linhas: só as visíveis ficam montadas, cada uma medida. |
rowHeight | number | — | Altura fixa das linhas do corpo, em px. Omitida, a linha tem no mínimo --mk-datagrid-row-height e cresce com o conteúdo. Definida, o conteúdo é cortado e wrap não tem efeito. |
striped | boolean | false | Zebrado a partir da 1ª linha. |
highlightedRows | string[] | (row) => boolean | — | Linhas destacadas, por rowId ou predicado. |
sorting | DatagridSort[] | null | — | Ordenação controlada; [] sem ordenação, null interno. |
manualSorting | boolean | false | Não reordena as linhas, para a ordenação no servidor. |
loading | boolean | false | Troca as linhas por linhas de skeleton na proporção da tabela e bloqueia a interação. |
pagination | boolean | false | Mostra o mk-pagination integrado. |
page | number | null | — | Página atual (a partir de 1), controlada; null interno. |
pageSize | number | null | — | Linhas por página, controlada; null interno (25). |
pageSizeOptions | number[] | — | Opções de tamanho de página. |
totalItems | number | — | Total de linhas no servidor, com manualPagination. |
manualPagination | boolean | false | O grid não fatia rows, só emite os eventos. |
expandTemplate | string | — | Template do conteúdo expandido (JS). Em React, renderExpanded; em Angular, ng-template[mkDatagridExpand]. |
expandedRows | string[] | null | — | Linhas expandidas, controlada; null interno. |
selectable | boolean | false | Adiciona a coluna de checkbox (fixada no início, fora de columns). |
selectedRows | string[] | null | — | rowIds selecionados, controlada (inclusive []). null ou undefined: o grid controla a seleção. |
rowSelectable | (row) => boolean | — | false desabilita o checkbox da linha e a tira do selecionar todas. |
reorderable | boolean | false | Handle de troca em todas as colunas (column.reorderable sobrescreve). |
resizable | boolean | false | Separador de redimensionamento em todas as colunas (column.resizable sobrescreve). |
columnOrder | string[] | null | — | Ordem das chaves de columns, controlada. null ou undefined: interna. |
columnWidths | Record<string, number> | null | — | Larguras em px por chave, controlada. null ou undefined: interna. |
renderTemplate | DatagridTemplateRenderer | — | Monta as células customizadas (JS). Os wrappers o preenchem. |
renderHeaderTemplate | DatagridHeaderTemplateRenderer | — | Monta o conteúdo do cabeçalho das colunas com headerTemplate (JS). Os wrappers o preenchem. |
renderExpanded | (ctx) => ReactNode | — | Só React: conteúdo da linha expandida, no lugar de expandTemplate. |
Props — coluna (DatagridColumn)
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
key | string | — | Identificador e, sem accessor, campo lido na linha. |
label | string | — | Texto do cabeçalho. |
accessor | (row) => unknown | — | Valor de colunas derivadas. |
width | number | — | Largura fixa em px. |
flex | number | 1 | Peso na divisão do espaço livre. |
minWidth | number | 120 | Largura mínima: piso das colunas flexíveis e do redimensionamento. |
maxWidth | number | — | Largura máxima: teto do redimensionamento e da divisão flexível. |
reorderable | boolean | herda do grid | Handle de troca no cabeçalho. |
resizable | boolean | herda do grid | Separador de redimensionamento. |
align | "start" | "center" | "end" | "start" | Alinhamento do conteúdo e do cabeçalho. |
wrap | boolean | false | Quebra o texto e deixa a linha crescer. Sem efeito com rowHeight. |
sortable | boolean | false | Habilita a ordenação. |
pinned | "start" | "end" | — | Fixa a coluna na rolagem horizontal. |
hidden | boolean | false | Oculta a coluna. |
helperText | string | — | Texto de ajuda no cabeçalho. |
rowHeader | boolean | false | Células com role="rowheader". |
template | string | — | Nome do template da célula. |
headerTemplate | string | — | Nome do template do conteúdo do cabeçalho. Sem ele, o cabeçalho mostra label. Em React, header; em Angular, ng-template[mkDatagridHeader]. |
cell | (ctx) => ReactNode | — | Só React: conteúdo da célula. |
header | (ctx) => ReactNode | — | Só React: conteúdo do cabeçalho. |
editable | true | { mask, placeholder, template, options, optionValue, optionLabel } | — | Campo editável na célula. Com options, editor de opções. |
fillable | boolean | { mode?, formula? } | false | Preencher para baixo ou para cima: copia, continua a série (mode: 'series') ou calcula por formula. Exige editable. |
Inputs das diretivas Angular
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
mkDatagridCell | string | — | Nome do template, o mesmo de column.template. |
mkDatagridHeader | string | — | Nome do template do cabeçalho, o mesmo de column.headerTemplate. |
inferRow (em mkDatagridCell) | TRow[] | — | Só para tipagem: com as linhas aqui, |
inferRow (em mkDatagridExpand) | TRow[] | — | Só para tipagem do let-row em ng-template[mkDatagridExpand]. |
Eventos
| Evento | Componente | Payload | Descrição |
|---|---|---|---|
mkSortChange | mk-datagrid | { columnKey, direction, sorting } | A ordenação muda. direction: "none", "ascending" ou "descending"; sorting é a ordenação resultante ([] sem ordenação). |
mkRowClick | mk-datagrid | { rowId, row, originalEvent } | Clique na linha, exceto em conteúdo interativo da célula. |
mkPageChange | mk-datagrid | { page } | Troca de página. |
mkPageSizeChange | mk-datagrid | { pageSize } | Troca do tamanho de página. |
mkActiveCellChange | mk-datagrid | { rowId, columnKey } | A célula ativa muda. |
mkCellChange | mk-datagrid | { rowId, columnKey, value, previousValue } | Edição confirmada com valor diferente. |
mkFill | mk-datagrid | { source, targets, value, direction } | Preenchimento para baixo ou para cima (direction: 'down' | 'up'). Cada item de targets traz { rowId, value } com o valor calculado, da origem para fora. |
mkRowExpand | mk-datagrid | { rowId, expanded, expandedRows } | Linha expandida ou recolhida; expandedRows é o conjunto resultante. |
mkColumnOrderChange | mk-datagrid | { columnOrder, source, target } | Duas colunas trocam de lugar. |
mkColumnResize | mk-datagrid | { columnKey, width } | Largura provisória a cada frame do arrasto (informativo). |
mkColumnWidthsChange | mk-datagrid | { columnWidths, columnKey, width } | Ao soltar, restaurar (duplo clique) e a cada passo de teclado. |
mkSelectionChange | mk-datagrid | { selectedRows, rowIds, selected } | A seleção muda. rowIds são as linhas afetadas (uma na alternância, as da página no selecionar todas) e selected o estado aplicado a elas. |
focusCell(rowId, columnKey) rola até a célula, monta a linha se preciso e a foca. Use para devolver o foco depois de fechar um dialog aberto pela célula.
scrollToRow(rowId) rola até a linha sem mover o foco e devolve false quando ela não está entre as linhas exibidas. getState() devolve o estado atual das sete props de estado (sorting, page, pageSize, selectedRows, expandedRows, columnOrder, columnWidths), controladas ou internas, para salvar a visão do usuário e devolvê-la às props depois.
applyCellChange(rows, detail, rowKey?) e applyFill(rows, detail, rowKey?), exportadas por @db1/makuco-ui-core, aplicam o mkCellChange e o mkFill em rows e devolvem um novo array. Elas localizam a linha pela mesma regra do grid (rowKey, padrão "id").
Os eventos dos componentes internos do grid (mk-pagination e cabeçalhos) não saem pelo host. O mkOpen e o mkClose do mk-menu não borbulham: o grid os escuta na fase de captura para elevar a célula fixa com menu aberto, e um ancestral que queira escutá-los usa { capture: true }.
Slots
| Componente | Slot | Descrição |
|---|---|---|
mk-datagrid | empty | Substitui o estado vazio padrão. |
mk-datagrid | loading | Substitui as linhas de skeleton do estado carregando. |
CSS Custom Properties
| Propriedade | Padrão | Descrição |
|---|---|---|
--mk-datagrid-row-height | 44px | Altura mínima das linhas do corpo e altura do cabeçalho; no modo |
--mk-datagrid-height | altura do pai, ou 480px | Altura do grid virtual quando o pai não tem altura. |
Acessibilidade
role="grid"comaria-labelvindo decaption,aria-rowcountearia-colcount. Cada linha temaria-rowindexcom a posição real, inclusive comvirtual.- Cabeçalhos ordenáveis expõem
aria-sort, e o botão de ordenar tem o rótulo "Ordenar por {coluna}". - Com
selectable, o grid temaria-multiselectable="true"e cada linha temaria-selected. A coluna do checkbox tem a chave__select(DATAGRID_SELECT_COLUMN_KEY), aceita emfocusCellemkActiveCellChange, e conta emaria-colindexearia-colcount. Os checkboxes são nomeados "Selecionar linha {nome}" e "Selecionar todas as linhas da página", e a contagem é anunciada porrole="status". - O handle de troca é um botão "Mover coluna {nome}" e o separador tem
role="separator"comaria-valuenow,aria-valueminearia-valuemax. Ambos saem do Tab até o cabeçalho entrar em modo interação, e a troca é anunciada porrole="status". - O editor de opções é um
role="combobox"comaria-expanded,aria-controls(listarole="listbox") earia-activedescendant; o foco fica no campo e o chevron é decorativo. - A zona de arrasto do preenchimento é decorativa (
aria-hidden); a célulafillableativa anuncia o atalho poraria-description("Shift+seta para estender, Ctrl+D para preencher"). - Células editáveis têm
aria-readonly="false". O botão de expandir temaria-expanded,aria-controlse o rótulo "Expandir {nome da linha}". - Com
loading, o grid temaria-busy="true", o corpo com os skeletons ficaaria-hiddene o grid anuncia um único "Carregando…" porrole="status". - Uma única parada de Tab (roving tabindex). Enter ou F2 entra no conteúdo da célula; Esc volta à navegação.
- Foco por teclado com o anel padrão (
--stroke-info) nas células sem campo e nos cabeçalhos; nas células editáveis (e nas com fill handle), o anel contorna a célula inteira, e o campo não desenha anel próprio.
Abaixo do AA:
- Contraste do destaque: o destaque (
highlightedRows) e a célula selecionada são indicados só pelo fundo: 1,38:1 contra a célula padrão na marca winner-box, e sem diferença visível na marca makuco até a revisão da paleta. - Pendência: no tema escuro, o anel de foco sobre a célula selecionada tem 2,57:1 por dentro. O token próprio do tema escuro está pendente.
- Quadrado do preenchimento: no tema escuro, o quadrado (
--stroke-info) tem de 1,02:1 a 2,01:1 contra os fundos da célula, em todas as marcas. O atalho de teclado anunciado na célula independe dele.
As teclas do grid estão em Navegação por teclado.