DataTable

La tabla densa del panel: columnas tipadas, orden, selección y estados vacío y cargando.

Usar

import { DataTable } from "@unozero-ai/ui/react";

<DataTable></DataTable>

Columnas tipadas

Cada columna es un DataTableColumn<T>: una key, una cabecera (header) y, cuando la celda no es row[key] tal cual, una función cell que recibe la fila ya tipada. rowKey devuelve el identificador estable de cada fila (sin él, usa row.id o la posición) y label da el nombre accesible de la tabla. En móvil la tabla se desplaza en horizontal dentro de su borde, sin empujar la página.

Los importes llevan numeric: van a la derecha, en mono y con tabular-nums, porque son cifras que se comparan con la fila de abajo (la Regla de los Tres Papeles). Los números de factura y las fechas llevan mono, que pone la letra sin mover la alineación. Ninguna celda se parte en dos líneas: si no cabe, la tabla se desplaza. En el kit React esto se hacía con align="right" y clases en lo que devolvía cell; ahora la celda se pinta dentro del shadow DOM de la tabla, donde las clases de tu página no llegan. Para una cabecera fija, da un alto máximo a su parte: uz-data-table::part(scroller) { max-height: 24rem }.

Con estados

El estado de cada fila va en un Badge, no en texto coloreado. Mapea cada estado del dominio a su palabra y su variante en un solo objeto, así la tabla, los filtros y el detalle dicen lo mismo. La palabra carga el significado y el color lo confirma (la Regla del Tenant): «No show» y «Cancelada» se distinguen sin mirar el tono.

cell devuelve texto, un nodo del DOM o una plantilla de Lit, nunca JSX: React no pinta dentro del shadow DOM de la tabla. Aquí la celda crea un <uz-badge> con document.createElement. Si tu proyecto tiene lit entre sus dependencias, html`<uz-badge variant=${…}>…</uz-badge>` hace lo mismo en una línea.

Ordenar y seleccionar

Con sortable, la cabecera de la columna es un botón que alterna el orden ascendente y descendente, marca aria-sort y ordena por row[key]. Guarda en la fila el valor que ordena (la fecha en ISO, el importe como número) y dale formato en cell. Cada cambio llega a onSort con { key, direction }.

sortKey y sortDirection fijan el orden de partida. El envoltorio de React vuelve a poner las props en cada render: si pasas sortKey, guárdalo en el estado desde onSort, como aquí, o el siguiente render devolverá la tabla al orden inicial.

selectable añade una columna de casillas y una cabecera que marca todas, con estado intermedio. onSelectionChange recibe { selected, rows }: las claves de rowKey y las filas. selected también se puede fijar, por ejemplo para vaciar la selección después de enviar los recordatorios.

Marca las reservas a las que quieres enviar el recordatorio de llegada.

Fila clicable

Con clickable, cada fila recibe foco, se resalta al pasar el ratón y emite onRowClick con { row, index } al pulsarla o con Enter y Espacio. Úsalo cuando toda la fila lleva al detalle. En el kit React bastaba con pasar onRowClick y la fila no recibía foco, así que hacía falta un botón en cada fila para quien navega con teclado; ahora el teclado llega a la fila y ese botón sobra.

Pulsa una fila, o llega a ella con Tab y pulsa Enter.

Vacía

Sin filas, la tabla mantiene sus cabeceras y muestra emptyMessage (empty-message en HTML). Escribe un mensaje que diga por qué está vacía y si eso es bueno, no un «Sin datos» genérico (que es lo que sale si no pasas nada); si necesitas un enlace o formato, usa el slot empty. Para una sección entera sin contenido y con una acción para empezar, usa EmptyState en lugar de la tabla.

Cargando

Con loading, la tabla pinta filas de esqueleto bajo sus cabeceras reales (skeletonRows, 5 por defecto) y se marca con aria-busy. Sustituye al TableSkeleton del kit React: la tabla que espera es la misma que luego muestra los datos, así que nada salta cuando llegan. Pide tantas filas de esqueleto como esperas recibir. Pulsa el botón para volver a consultar.

Volver a consultar el PMS

Con paginación

DataTable pinta las filas que recibe; la paginación va fuera, con Pagination. Pide los datos ya paginados al servidor y di cuántos resultados hay en total: el lector necesita saber si está viendo 10 reservas o 10 de 47.

Cuando el orden lo hace el servidor, cancela el evento en onSort con e.preventDefault(): la tabla solo cambia el indicador de la cabecera y deja de reordenar la página visible, que sería ordenar 10 filas de 47. Pide entonces la primera página con el orden nuevo.

Mostrando 1–10 de 47 reservas

API

Generada del custom-elements.json que publica @unozero-ai/ui. Las partes se estilan desde tu CSS con el nombre del elemento: uz-button::part(base).

DataTable · <uz-data-table>

PropTipoDefectoDescripción
columnsDataTableColumn[][]Las columnas: clave, cabecera, alineación, orden y celda (ver DataTableColumn).
datareadonly any[][]Las filas que se pintan, ya paginadas si hay paginación.
rowKey(row: any, index: number) => RowKey | undefined—Clave estable de cada fila; por defecto row.id o la posición.
selectedRowKey[][]Claves de las filas seleccionadas.
labelstring""Nombre accesible de la tabla.
emptyMessagestring""Texto de la tabla vacía; por defecto, el label global noData.
loadingbooleanfalsePinta filas de esqueleto bajo las cabeceras mientras llegan los datos.
skeletonRowsnumber5Cuántas filas de esqueleto pinta loading.
selectablebooleanfalseAñade la columna de casillas para seleccionar filas.
clickablebooleanfalseCada fila recibe foco y emite uz-row-click al pulsarla o con Enter/Espacio.
sortKeystring""Clave de la columna por la que se ordena.
sortDirection"asc" | "desc""asc"Sentido del orden: asc o desc.
rows—Alias de data.
EventoDescripción
onSort{ key, direction }, cancelable.
onSelectionChange{ selected, rows }.
onRowClick{ row, index }.
SlotDescripción
emptyContenido de la tabla vacía.
Parte CSSDescripción
uz-data-table::part(scroller)El contenedor con borde y scroll.
uz-data-table::part(table)El <table>.