DataTablePRO
Tabla avanzada todo-en-uno con búsqueda global, sort multi-columna, filtros por columna (texto, select, avanzado), paginación interna, selección de filas con acciones masivas, visibilidad de columnas, exportación CSV/JSON y modo de carga skeleton. Cero dependencias externas.
AL Ana López Kuro Games SL | España | Activo | € 2800 | 12 mar 2024 | |
BD Bruno Díaz HoYoverse Europe | Alemania | Activo | € 5200 | 5 nov 2023 | |
CR Carla Ruiz Level-5 Studios | España | Prospecto | — | 20 ene 2026 | |
DM Diego Mora Cygames Inc. | Japón | Activo | € 9100 | 18 jul 2022 | |
EV Elena Vidal Square Enix | Francia | Inactivo | — | 29 abr 2023 |
Instalación#
bash
pnpm add @tsukira/uiUso#
tsx
import { DataTable, defineColumns } from "@tsukira/ui"; interface Contacto { id: string; nombre: string; mrr: number; } const columns = defineColumns<Contacto>([ { key: "nombre", header: "Nombre", sortable: true, searchable: true }, { key: "mrr", header: "MRR", sortable: true, align: "right", dataType: "number", cell: (r) => `€ ${r.mrr}` },]); <DataTable data={contactos} columns={columns} rowKey={(r) => r.id} searchable pageSize={10}/>Ejemplos#
Sorting y paginación interna
Haz clic en las cabeceras para ordenar · pageSize controla filas por páginaMRR | ||
|---|---|---|
| Diego Mora | Cygames Inc. | € 9100 |
| Karen Blanco | From Software | € 7800 |
| Bruno Díaz | HoYoverse Europe | € 5200 |
Selección y acciones masivas
selectable activa checkboxes · bulkActions aparece al seleccionar filasEstado | MRR | ||
|---|---|---|---|
| Ana López | Activo | € 2800 | |
| Bruno Díaz | Activo | € 5200 | |
| Carla Ruiz | Prospecto | — | |
| Diego Mora | Activo | € 9100 |
Densidad y cabecera fija
density='compact' · stickyHeader · maxBodyHeight habilita scroll vertical internoMRR | |||
|---|---|---|---|
| Ana López | Kuro Games SL | España | € 2800 |
| Bruno Díaz | HoYoverse Europe | Alemania | € 5200 |
| Carla Ruiz | Level-5 Studios | España | — |
| Diego Mora | Cygames Inc. | Japón | € 9100 |
| Elena Vidal | Square Enix | Francia | — |
| Fede Gil | Bandai Namco | Italia | € 3400 |
| Gema Ortiz | Capcom Europe | España | — |
| Hugo Sanz | Konami Digital | México | — |
| Irene Peña | Atlus West | Argentina | € 1650 |
| Javier Torres | Grasshopper Mfr. | Colombia | — |
| Karen Blanco | From Software | Portugal | € 7800 |
| Luis Martín | Platinum Games | Chile | — |
Fusión: CRM con filtro de búsqueda externo
Input controlado que filtra el texto de búsqueda + DataTable con Chip de filtro activo removibleEstado | MRR | |||
|---|---|---|---|---|
ALAna López | Kuro Games SL | España | Activo | € 2800 |
BDBruno Díaz | HoYoverse Europe | Alemania | Activo | € 5200 |
CRCarla Ruiz | Level-5 Studios | España | Prospecto | — |
DMDiego Mora | Cygames Inc. | Japón | Activo | € 9100 |
Fusión: acciones por fila
rowActions muestra un menú de opciones en cada fila — editar, ver perfil o eliminarEstado | Actions | ||
|---|---|---|---|
ALAna López | Kuro Games SL | Activo | |
BDBruno Díaz | HoYoverse Europe | Activo | |
CRCarla Ruiz | Level-5 Studios | Prospecto | |
DMDiego Mora | Cygames Inc. | Activo |
DataTable V2: Virtualización, Agrupamiento y Edición Inline
Doble click en Contacto, Estado o MRR para editar · Agrupa por País/Estado · Soporta 1000+ filas de forma fluida|
Agrupar por:
AL Ana López Kuro Games | España | Activo | — |
IL Irene López Atlus | España | Activo | € 1200 |
EL Elena López Capcom | España | Activo | € 2400 |
AL Ana López Square Enix | España | Activo | € 3600 |
IL Irene López Level-5 | España | Activo | € 4800 |
EL Elena López Kuro Games | España | Activo | € 6000 |
AL Ana López Atlus | España | Activo | € 7200 |
IL Irene López Capcom | España | Activo | € 8400 |
EL Elena López Square Enix | España | Activo | € 9600 |
AL Ana López Level-5 | España | Activo | € 10.800 |
IL Irene López Kuro Games | España | Activo | € 12.000 |
EL Elena López Atlus | España | Activo | € 13.200 |
AL Ana López Capcom | España | Activo | € 14.400 |
IL Irene López Square Enix | España | Activo | € 600 |
EL Elena López Level-5 | España | Activo | € 1800 |
API#
DataTablePropsextends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect' | 'title' | 'style'>| Prop | Tipo | Default | Descripción |
|---|---|---|---|
style | React.CSSProperties | — | Estilo inline del root. |
data* | T[] | — | Filas. |
columns* | Column<T>[] | — | Definición de columnas. |
rowKey* | (row: T, index: number) => string | number | — | Identificador único por fila. `index` es el índice **global** dentro de `data`. |
titleAs | 'h2' | 'h3' | 'h4' | 'h5' | 'div' | `'h3'` | Heading tag para el título — default `'h3'`. Usa `'div'` para no afectar el outline a11y. |
description | ReactNode | — | Descripción bajo el título. |
toolbarActions | ReactNode | — | Acciones libres en la toolbar (botones). |
hideToolbar | boolean | — | Ocultar la toolbar completa. |
searchKeys | string[] | — | — |
searchPlaceholder | string | — | — |
searchDebounceMs | number | — | Debounce de la búsqueda en ms. |
initialSort | SortState[] | — | Sort inicial. |
pageSizes | number[] | [10,25,50,100]) | Tamaños seleccionables (default [10,25,50,100]). |
hidePagination | boolean | — | — |
selectedKeys | (string | number)[] | — | — |
onSelectionChange | ((keys: (string | number)[], rows: T[]) => void) | — | — |
bulkActions | BulkAction[] | — | Acciones masivas — se muestran cuando hay seleccionados. |
expandedKeys | (string | number)[] | — | Claves expandidas (controlled). |
defaultExpandedKeys | (string | number)[] | — | Claves expandidas inicialmente (uncontrolled). |
onExpandedChange | ((keys: (string | number)[]) => void) | — | — |
showColumnsMenu | boolean | — | Mostrar el menú de columnas en la toolbar. |
showDensityToggle | boolean | — | — |
striped | boolean | — | — |
stickyHeader | boolean | — | Header pegajoso al hacer scroll vertical. |
maxBodyHeight | number | string | — | Altura máxima del body — habilita scroll vertical interno. |
empty | ReactNode | — | — |
loading | boolean | — | — |
skeletonRows | number | min(pageSize, 8) o 5 | Nº de filas skeleton a renderizar cuando `loading`. Default: min(pageSize, 8) o 5. |
error | ReactNode | — | Si se pasa, muestra el estado de error en vez del body. |
onRetry | (() => void) | — | Si se pasa junto con `error`, renderiza un botón "Reintentar". |
exportable | boolean | — | Habilita botón export (CSV). |
exportFilename | string | — | Nombre del archivo exportado (sin extensión). |
onExport | ((rows: T[], context: { format: 'csv' | 'json' | — | Custom export handler (si se pasa, sobrescribe el export default). |
scope* | 'all' | 'selected' | 'page' }) => void) | — | — |
exportOptions | { formats?: ('csv' | 'json')[] | — | Si se pasa, el botón "Exportar" abre un menú con formato + alcance. Sin esta prop, el click exporta directamente todos los filtrados como CSV. |
scopes | ('all' | 'selected' | 'page')[] | — | — |
onRefresh | (() => void | Promise<unknown>) | — | Mostrar botón refresh (llama onRefresh). Si devuelve `Promise`, el icono gira hasta resolverse. |
stale | boolean | — | Pinta un dot junto al icono refresh para señalar que los datos están desactualizados. |
manualFilter | boolean | — | Si true, no se filtra en cliente — sólo emite `onFilterChange`. |
manualPagination | boolean | — | Si true, no se pagina en cliente — sólo emite `onPageChange`. |
manualSearch | boolean | — | Si true, no se busca en cliente — sólo emite `onSearchChange`. |
totalRows | number | — | Total de filas (requerido para paginación server-side). |
onSortChange | ((sorts: SortState[]) => void) | — | — |
onFilterChange | ((filters: Record<string, FilterValue>) => void) | — | — |
onPageChange | ((page: number, pageSize: number) => void) | — | — |
onSearchChange | ((query: string) => void) | — | — |
enableSavedViews | boolean | — | Habilita el menú de "Vistas guardadas" en la toolbar. Requiere `storageKey` para persistir (sin él, las vistas viven sólo en memoria de la sesión). |
rowHeight | number | — | Altura de fila en px. Si se omite, se estima por la densidad de la tabla. |
groupByKey | string | — | Key de columna para agrupar filas. |
onRowEditSave | ((row: T, rowIndex: number, key: string, newValue: any) => void | Promise<void>) | — | Callback cuando se guarda una edición inline. |