import type { ReactNode } from 'react'; /** * Dirección de ordenamiento para columnas sortables */ export type SortDirection = 'asc' | 'desc' | null; /** * Definición de una columna de la tabla */ export interface TableColumn { /** * Título que se muestra en el header de la columna */ header: ReactNode; /** * Key del objeto de datos para acceder al valor * Puede ser una string o una función que retorna el valor */ accessor: keyof T | ((row: T) => any); /** * Si la columna es sortable (ordenable) * @default false */ sortable?: boolean; /** * Función custom para renderizar el contenido de la celda * Si no se provee, se usa el valor del accessor directamente */ render?: (value: any, row: T, index: number) => ReactNode; /** * Alineación del contenido de la celda * @default 'left' */ align?: 'left' | 'center' | 'right'; /** * Ancho de la columna (CSS width) */ width?: string; /** * Si la columna debe mantenerse fija a la derecha al hacer scroll horizontal * @default false */ stickyRight?: boolean; /** * Si el ancho (`width`) debe respetarse como una medida FIJA que no crece para repartir * el espacio sobrante. Por defecto, un `width` en px se transforma en `minmax(width, 1fr)` * para que la columna se expanda; con `fixedWidth` la columna se queda exactamente en `width` * (útil para columnas utilitarias: selección, estado por compañía, acciones). Opt-in y * retrocompatible. @default false */ fixedWidth?: boolean; /** * Si el header debe renderizarse tal cual (ReactNode completo), sin el que trunca * el texto ni los iconos de orden internos. Útil para cabeceras compuestas * (título + filtro por columna). El propio header gestiona su orden. @default false */ headerRaw?: boolean; } /** * Props de paginación para la tabla */ export interface PaginationProps { /** * Página actual (1-indexed) */ currentPage: number; /** * Total de páginas */ totalPages: number; /** * Callback cuando cambia la página */ onPageChange: (page: number) => void; /** * Si se muestran los números de página en el centro del paginador. * * Por defecto NO se muestran: la navegación queda en los cuatro chevrones * (primera · anterior · siguiente · última) más el campo «Página», que es como se ve en las * pantallas del vertical financiero tomadas como canon. Enciéndelo donde saltar de página por * número aporte algo. * * Cuando está activo se pinta una ventana de hasta 3 números centrada en la página actual. * * @default false */ showPageNumbers?: boolean; /** * Texto del botón "Anterior" * @default 'Anterior' */ previousLabel?: string; /** * Texto del botón "Siguiente" * @default 'Siguiente' */ nextLabel?: string; /** * Cantidad de registros por página actualmente seleccionada. * Requerido para mostrar el selector de tamaño de página. */ pageSize?: number; /** * Opciones disponibles para el selector de registros por página. * Si no se provee, el selector no se muestra. * @example [10, 25, 50, 100] */ pageSizeOptions?: number[]; /** * Callback cuando el usuario cambia la cantidad de registros por página. */ onPageSizeChange?: (size: number) => void; /** * Total de registros para mostrar contexto en la barra. * @example 40 → mostrará "40 registros" */ totalRecords?: number; /** * Etiqueta junto al selector de registros por página. * @default 'por pág.' */ perPageLabel?: string; /** * Etiqueta para el total de registros. * @default 'registros' */ recordsLabel?: string; /** * Etiqueta del input para ir a una página específica. * @default 'Pág.' */ goToPageLabel?: string; /** * Nombre accesible del input «ir a página». * * Existe porque estaba escrito EN ESPAÑOL dentro del componente: era el único texto de la barra * que un host en inglés no podía traducir, y las otras cinco etiquetas ya eran props. * @default 'Ir a página' */ goToPageAriaLabel?: string; /** * Nombre accesible del botón que salta a la PRIMERA página. * Existe aparte de `previousLabel` porque son dos acciones distintas: reusar el mismo texto * hacía que un lector de pantalla anunciara «Primera página, Anterior». * @default 'Primera página' */ firstPageLabel?: string; /** * Nombre accesible del botón que salta a la ÚLTIMA página. * Ver `firstPageLabel`. * @default 'Última página' */ lastPageLabel?: string; } /** * Props del componente Table */ export interface TableProps { /** * Título opcional de la tabla */ title?: string; /** * Definición de las columnas */ columns: TableColumn[]; /** * Datos de las filas */ data: T[]; /** * Variante visual de la tabla * @default 'basic' */ variant?: 'basic' | 'fullWidth' | 'striped' | 'grid'; /** * Si se muestra el borde del container * @default true */ showBorder?: boolean; /** * Si se muestra la sombra del container * @default true */ showShadow?: boolean; /** * Callback cuando se hace click en una fila */ onRowClick?: (row: T, index: number) => void; /** * Callback cuando se hace **doble clic** en una fila. * * Es el mecanismo opt-in para las tablas que quieren manejar el gesto de doble clic. Al * proveerlo, la fila deja de comportarse como texto seleccionable (`user-select: none`), que es * lo que impedía que el gesto llegara al consumidor: en un navegador real el segundo clic * selecciona la palabra bajo el cursor y `onRowClick` se descartaba por el guardia de selección. * * Las tablas que NO lo proveen no cambian en nada: siguen permitiendo seleccionar y copiar el * texto de las celdas. * * La fila es focalizable y `Enter`/`Espacio` la activan. Si además hay `onRowClick`, el teclado * sigue disparando `onRowClick` (comportamiento previo); si `onRowDoubleClick` es el único * callback, el teclado dispara este. * * @example * abrirModal(row)} /> */ onRowDoubleClick?: (row: T, index: number) => void; /** * Desactiva la selección de texto (`user-select: none`) en las filas de datos sin necesidad de * registrar `onRowDoubleClick`. Útil cuando el host compone el doble clic desde fuera (un * `onDoubleClick` en un envoltorio) y solo necesita que el clic sobreviva al gesto. * * Se aplica aunque la fila no sea interactiva: si lo pasás sin ningún callback, la tabla queda * de solo lectura y sin selección de texto. * * `onRowDoubleClick` ya lo activa por su cuenta, así que no hace falta combinarlos. * Opt-in y retrocompatible. @default false */ disableRowTextSelection?: boolean; /** * Evita que `onRowClick` se dispare cuando el gesto termina siendo un doble clic: la invocación * de `onRowClick` se aplaza `doubleClickDelay` ms y se cancela si llega el `dblclick`. * * Solo tiene efecto cuando hay `onRowClick` **y** `onRowDoubleClick`. Por defecto está apagado y * ambos callbacks se disparan (primero `onRowClick`, luego `onRowDoubleClick`), que es la * semántica nativa del DOM. Enciéndelo cuando el clic simple hace algo que no debe ocurrir antes * del doble clic (por ejemplo, navegar al detalle). * * Opt-in y retrocompatible. @default false */ suppressRowClickOnDoubleClick?: boolean; /** * Milisegundos que espera `suppressRowClickOnDoubleClick` antes de dar el clic por simple. * Sin efecto si esa prop está apagada. @default 250 */ doubleClickDelay?: number; /** * Callback cuando cambia el sort */ onSort?: (column: keyof T | string, direction: SortDirection) => void; /** * Estado de sort controlado desde fuera */ sortColumn?: keyof T | string; /** * Dirección de sort controlada desde fuera */ sortDirection?: SortDirection; /** * Si la tabla debe ocupar todo el ancho disponible * @default false */ fullWidth?: boolean; /** * Texto a mostrar cuando no hay datos * @default 'No hay datos disponibles' */ emptyMessage?: string; /** * Si se está cargando la información * @default false */ loading?: boolean; /** * Número de filas skeleton a mostrar cuando loading=true * @default 5 */ loadingRows?: number; /** * Props de paginación (si se provee, se muestra paginación) */ pagination?: PaginationProps; /** * Si se muestra el padding del container * @default true */ showPadding?: boolean; /** * Clases CSS adicionales para el container */ className?: string; /** * Callback para determinar si una fila está seleccionada */ isRowSelected?: (row: T, index: number) => boolean; /** * ID único para accesibilidad */ id?: string; /** * Si el header de columnas debe quedar fijo (sticky) al hacer scroll vertical * del contenedor. Opt-in y retrocompatible. * @default false */ stickyHeader?: boolean; /** * Pinta la banda gris `#f8f9fc` del canon en la cabecera de columnas SIN fijarla. * * Ese fondo venía atado a `stickyHeader`, que además convierte la tabla en el * contenedor de scroll (`flex-1 min-h-0 overflow-auto`). Una tabla que vive dentro * de otra caja —la de líneas del detalle— quiere la banda pero NO ese * comportamiento, y sin esta opción su cabecera salía en blanco mientras la del * listado de documentos, a dos palmos, salía gris: la misma tabla con dos caras. * * Es opt-in a propósito: encenderla por defecto teñiría de gris la cabecera de * todas las tablas del kit, que hoy son blancas y nadie ha pedido cambiar. * @default false */ headerBand?: boolean; /** * Alto mínimo del CONTENEDOR DE FILAS (`div[role="table"]`), en px. * * Sirve para que una tabla con pocos registros no se lea como una franja: * reserva el alto de N filas y el hueco queda DENTRO de la caja de filas. * * Va aquí y no en el envoltorio del consumidor porque ahí el sobrante lo * absorbía el contenedor del paginador —que es el que crece— y el resultado era * un paginador altísimo debajo de una tabla igual de estrecha: justo lo * contrario de lo que se busca. */ minGridHeight?: number; /** * Hover de fila del prototipo: fondo azul muy claro (#f0f7ff) en toda la fila y acento * izquierdo azul (#0066ff) de 3px en la primera celda. Opt-in y retrocompatible. * @default false */ accentHover?: boolean; /** * Densidad compacta: reduce el alto de las filas al mínimo necesario (44px en lugar de 56px) * para mostrar más registros en pantalla sin que queden estrechas. Opt-in y retrocompatible. * @default false */ dense?: boolean; } /** * Props del TableHeader (uso interno) */ export interface TableHeaderProps { /** Banda gris del canon en la cabecera, sin fijarla. Ver `TableProps.headerBand`. */ headerBand?: boolean; column: TableColumn; sortable: boolean; sorted: boolean; sortDirection: SortDirection; onSort: () => void; /** Si el header debe quedar fijo (sticky) al hacer scroll vertical. */ stickyHeader?: boolean; /** Densidad compacta: iguala el alto del header al de las filas compactas (44px). */ dense?: boolean; } /** * Props del TableCell (uso interno) */ export interface TableCellProps { children: ReactNode; align?: 'left' | 'center' | 'right'; width?: string; } /** * Props del TableRow (uso interno) */ export interface TableRowProps { children: ReactNode; onClick?: () => void; striped?: boolean; index: number; } //# sourceMappingURL=Table.types.d.ts.map