import { LitElement } from 'lit'; export interface DataTableColumn { /** Clave del campo en la fila (o id lógico si se usa `format`). */ key: string; /** Cabecera de la columna. */ header: string; /** Formateador → string a mostrar. Si se omite, se usa row[key]. */ format?: (row: Record) => string; /** Alineación del contenido de la celda. */ align?: 'left' | 'right' | 'center'; /** (server) La columna es ordenable: cabecera clicable que emite `sortChange`. */ sortable?: boolean; /** (server) La columna es filtrable: añade un control en la fila de filtros. */ filterable?: boolean; /** (server) Tipo de control de filtro. Por defecto 'text'. */ filterType?: 'text' | 'select' | 'multiselect' | 'number' | 'date' | 'range' | 'daterange'; /** (server) Opciones para `filterType: 'select'` / `'multiselect'`. */ options?: { value: string; label: string; }[]; /** Render de celda a medida (devuelve un TemplateResult de Lit, p.ej. un `ok-toggle` o un chip). * Tiene prioridad sobre `format`/valor crudo. El módulo lo crea con su `html` (lit deduplicado). */ render?: (row: Record) => unknown; /** Oculta la columna por defecto (el usuario la reactiva en el selector de columnas). */ hidden?: boolean; /** (opcional) Ancho CSS de la columna en la vista lista en grid (p.ej. '8rem', '20%', 'minmax(8rem,1fr)'). * Si se omite, la columna ocupa `minmax(8rem,1fr)`. Sin efecto en el fallback con . */ width?: string; } /** Vista de presentación de las filas (lista/tarjetas). */ export type DataTableView = 'table' | 'cards'; export interface DataTableAction { /** Id que se emite en `rowAction`. */ id: string; /** Texto del botón (o aria-label si solo hay icono). */ label: string; /** Nombre de un ion-icon opcional. */ icon?: string; /** Color Ionic del botón (p.ej. 'danger', 'primary'). */ color?: string; /** (opcional, por fila) Si devuelve `true` para una fila, el botón de esa acción se renderiza * deshabilitado (`?disabled` + `aria-disabled="true"`). */ disabled?: (row: Record) => boolean; /** (opcional, por fila) Si devuelve `true` para una fila, el botón muestra un * `` en lugar del icono/label Y queda deshabilitado * (una acción en curso no debe ser re-clicable). */ loading?: (row: Record) => boolean; } /** Acción primaria de la topbar (botón destacado). Emite el evento `primaryAction`. */ export interface DataTablePrimaryAction { /** Texto / aria-label del botón. */ label: string; /** Nombre de un ion-icon opcional (por defecto 'add'). */ icon?: string; } /** Clave estable de fila: nombre de campo o función que la devuelve. */ export type DataTableRowKey = string | ((row: Record) => string); /** (NUEVO, additivo) Todos los textos humanos del data-table, para i18n. * Se pasan desde fuera vía la prop `.labels` (parcial); lo no pasado cae al idioma del documento * (`` → español; cualquier otro idioma → inglés). * El contenido data-driven (columns/rows/options) NO va aquí — ya es externo. */ export interface OkDataTableLabels { /** Placeholder del buscador. */ search: string; /** Estado vacío / "sin resultados". */ empty: string; /** Título del botón/panel de filtros + aria del drawer de filtros. */ filters: string; /** Botón "Limpiar" (selección y filtros). */ clear: string; /** Botón "Aplicar" (filtros). */ apply: string; /** Barra de selección: "{n} seleccionados" ({n} = nº filas). */ selected: string; /** Botón "Importar CSV". */ importCsv: string; /** Botón "Exportar CSV". */ exportCsv: string; /** Botón "Añadir" (alta). */ add: string; /** Aria del botón de menú overflow (⋮). */ moreActions: string; /** Aria del selector de "filas por página". */ rowsPerPage: string; /** Sufijo del selector compacto de tamaño de página (p.ej. "10 / pág."). */ perPageShort: string; /** Aria del botón de vista lista. */ viewList: string; /** Aria del botón de vista tarjetas. */ viewCards: string; /** Aria del selector de columnas. */ columnsVisible: string; /** Texto resumido del selector de columnas. */ columns: string; /** Cabecera de la columna de acciones de fila. */ actions: string; /** Aria del botón "Cerrar" (drawer). */ close: string; /** Título del drawer de alta. */ newRecord: string; /** Aria del drawer del formulario de alta/edición. */ form: string; /** Placeholder del input de filtro de texto. */ filterPlaceholder: string; /** Etiqueta/placeholder "Desde" (rango de fechas). */ from: string; /** Etiqueta/placeholder "Hasta" (rango de fechas). */ to: string; /** Sufijo aria "{label} desde" (rango de fechas en línea); {label} = cabecera de columna. */ fromOf: string; /** Sufijo aria "{label} hasta" (rango de fechas en línea); {label} = cabecera de columna. */ toOf: string; /** Placeholder "≥" (rango numérico, borde inferior). */ gte: string; /** Placeholder "≤" (rango numérico, borde superior). */ lte: string; /** Texto cuando una columna no tiene valores distintos (chips de filtro). */ noValues: string; /** Aria "Seleccionar todo" (checkbox de cabecera). */ selectAll: string; /** Aria "Seleccionar fila" (checkbox de fila, vista lista). */ selectRow: string; /** Aria "Seleccionar" (checkbox de tarjeta). */ select: string; /** Pager: "Mostrando {from}–{to} de" ({from}/{to} ya interpolados por el componente). */ showing: string; /** Pager: singular "registro" (cuando count === 1). */ recordSingular: string; /** Pager: plural "registros" (cuando count !== 1). */ recordPlural: string; } export declare class OkDataTable extends LitElement { static styles: import("lit").CSSResult; /** Columnas a renderizar. */ columns: DataTableColumn[]; /** Filas (objetos planos). En modo servidor, solo las de la página actual. */ rows: Record[]; /** (cliente) Campos sobre los que filtra el buscador en memoria. Vacío = sin buscador. */ searchKeys: string[]; /** Campo usado como key estable de fila. */ rowKeyField: string; /** (NUEVO, opcional) Clave estable de fila: nombre de campo o función. Tiene prioridad sobre * `rowKeyField`; por defecto usa `row.id` (vía `rowKeyField`). Se usa para selección y `repeat`. */ rowKey?: DataTableRowKey; /** Filas por página. */ pageSize: number; /** Mensaje cuando no hay filas. Si no se pasa, deriva de `this.t.empty` (inglés por defecto). */ emptyMessage?: string; /** Placeholder del buscador. Si no se pasa, deriva de `this.t.search` (inglés por defecto). */ searchPlaceholder?: string; /** (NUEVO, additivo) Textos humanos del data-table para i18n (parcial). Lo no pasado cae al * default inglés (`DEFAULT_LABELS`). No afecta a columns/rows/options (ya externos). */ labels: Partial; /** Acciones por fila (botones). */ actions: DataTableAction[]; /** Muestra el botón "+" que despliega un acordeón con el slot `create` (formulario de alta). */ addable: boolean; /** Opciones del selector de "filas por página". Vacío = sin selector. */ pageSizeOptions: number[]; /** Modo "llenar el contenedor": la tabla ocupa el alto disponible, las filas hacen scroll DENTRO * (cabecera sticky) y el pager queda SIEMPRE visible. Requiere que el contenedor tenga alto. */ fill: boolean; /** Muestra un multiselect (ion-select) en la barra para elegir qué columnas se ven. * Default ON (2026-06-14): toda tabla trae el selector de columnas. Para ocultarlo, * pon la PROPIEDAD a false (`el.columnPicker = false`); el atributo booleano no puede * apagar un default true (cualquier valor presente cuenta como true en Lit). */ columnPicker: boolean; /** Muestra botones de import/export CSV en la barra. Export vacío = solo cabeceras (estructura). */ csv: boolean; /** Nombre del fichero de export CSV. */ csvName: string; /** Activa el modo servidor: no filtra/pagina en memoria, solo emite eventos. */ serverSide: boolean; /** (server) Total de filas filtradas (lo da el runtime) para calcular el nº de páginas. */ total: number; /** (server) Página actual (0-based), controlada por el padre. */ page: number; /** (server) Muestra el buscador aunque no haya `searchKeys` (búsqueda server-side). */ searchable: boolean; /** (server) Columna de orden activa. */ sort?: string; /** (server) Dirección del orden activo. */ sortDir: 'asc' | 'desc'; /** (NUEVO) Título de la cabecera (a la izquierda, junto al contador de registros). * Tipo `string` (no opcional) para no chocar con `HTMLElement.title`; '' = sin título. */ title: string; /** (NUEVO) Conmutador de vista lista/tarjetas. Acepta `true` (= ['table','cards']) o un array de * vistas. La presencia de 'cards' (o 'card') habilita la vista tarjetas. Compatibilidad: el * antiguo valor booleano sigue funcionando. */ views: boolean | string[]; /** (NUEVO) Vista inicial al montar: 'cards' | 'table'. Por defecto 'table' (compatibilidad). Solo * aplica una vez, en el primer render; el usuario puede luego conmutar con el toggle. Si pide * 'cards' pero la vista tarjetas no está habilitada (`views`), se ignora. Evita el hack de fijar * `viewMode` por referencia tras montar (frágil si la tabla monta detrás de un `v-if`/loading). */ defaultView?: 'table' | 'cards'; /** (NUEVO, alias documentado) Habilita import/export CSV (equivalente a `exportable`+`importable` * / `csv`). Mostrar el botón de Exportar. */ exportable: boolean; /** (NUEVO) Mostrar el botón de Importar CSV. */ importable: boolean; /** (NUEVO, alias) Selector de columnas (equivalente a `columnPicker`). */ columnSelector: boolean; /** (NUEVO, alias) Opciones del selector de "filas por página" (equivalente a `pageSizeOptions`). */ pageSizes?: number[]; /** (NUEVO) Selección de filas con checkbox por fila + seleccionar-todo + barra contextual. */ selectable: boolean; /** (NUEVO) Conjunto de keys seleccionadas (controlado por el padre o interno). */ selectedKeys?: Set; /** (NUEVO) Acción primaria de la topbar (botón destacado). Emite `primaryAction`. */ primaryAction?: DataTablePrimaryAction; /** (NUEVO) Filtros EN LÍNEA en la toolbar (selects/daterange/text compactos) en vez del botón * funnel + drawer. Opt-in (por defecto `false` → se conserva el drawer). Look del screenshot: * «Todos los Estados» · «Todos los tipos» · rango de fechas, todo en una línea con el buscador. * Emite `filterChange` igual que el drawer. */ inlineFilters: boolean; /** (NUEVO) Acciones del menú overflow (botón «⋮»). Emite `menuAction` con `{ actionId }`. */ menuActions: DataTableAction[]; /** (NUEVO) Cabecera de la tarjeta: título (string/HTML). Si se omite, no hay cabecera de título. */ cardTitle?: (row: Record) => unknown; /** (NUEVO) Cabecera de la tarjeta: nombre de un ion-icon o TemplateResult. */ cardIcon?: (row: Record) => unknown; /** (NUEVO) Cuerpo a medida de la tarjeta (string/HTML). Si se omite, se listan los campos. */ renderCard?: (row: Record) => unknown; private q; private clientPage; private clientPageSize; private clientSort; private clientSortDir; private clientFilters; private filterDraft; private panel; private viewMode; private hiddenKeys; private internalSelection; private menuOpen; private menuEv?; private readonly onLocaleChanged; connectedCallback(): void; disconnectedCallback(): void; private get t(); /** Placeholder efectivo del buscador (prop explícita → label i18n → default inglés). */ private get effSearchPlaceholder(); /** Mensaje efectivo de estado vacío (prop explícita → label i18n → default inglés). */ private get effEmptyMessage(); private get effPageSizes(); private get effColumnPicker(); private get effExport(); private get effImport(); /** ¿Está habilitado el conmutador de vista lista/tarjetas? */ private get viewToggle(); /** ¿Está disponible la vista tarjetas? (presente en `views` o `views === true`). */ private get cardViewEnabled(); /** Columnas actualmente visibles (respeta el column chooser). */ private get visibleColumns(); private setVisibleColumns; private keyOf; private get selection(); private setSelection; private toggleRow; private toggleAll; private csvEscape; /** Exporta las filas a CSV (cabeceras = column.key). Si no hay filas, exporta solo la estructura. */ private exportCsv; private parseCsv; private onImportFile; private toggle; private cloneFilters; private setFilterValues; private setFilterRange; private applyFilters; private clearFilters; private serializeFilters; /** Abre el panel lateral (API pública para el módulo, p.ej. "editar" abre el form pre-rellenado). */ open(panel?: 'filters' | 'create'): void; /** Cierra el panel lateral. */ close(): void; private emit; private get hasSearch(); /** Columnas filtrables (con control en el panel de filtros). En cliente y en servidor. */ private get filterColumns(); /** ¿Hay que mostrar el botón de Filtros? (cualquier columna filtrable). */ private get hasFilterRow(); /** Nº de filtros activos (modo cliente) → badge del botón Filtros. */ private get activeFilterCount(); /** Valor crudo de una columna para ordenar/filtrar (usa format si lo hay, si no row[key]). */ private rawValue; /** Valores distintos de una columna (para los chips del filtro multi-select). */ private distinctValues; /** Filas tras buscar + filtrar + ordenar EN MEMORIA (solo modo cliente). */ private get clientFiltered(); private cell; private onSearch; /** ¿Es ordenable la columna? Servidor: opt-in (`sortable`). Cliente: por defecto SÍ (como el Hub), * salvo `sortable: false` explícito. */ private isSortable; private onHeaderClick; private onFilterInput; private onRangeInput; private onDateRangeInput; private setClientFilter; private onFilterSelect; private onInlineRange; private openMenu; firstUpdated(): void; private setViewMode; private renderFilterControl; private renderInlineFilters; private renderInlineFilter; private renderOverflowMenu; private actionButtons; private toolButton; /** Plantilla de columnas del grid de la vista lista: [checkbox] [columnas…] [acciones]. */ private gridTemplate; /** Lista de páginas a mostrar en el pager numerado (1-based): primera, última, vecinas de la * actual y «…» donde haya saltos. P.ej. en página 1 de 52 → [1,2,3,'…',52]. */ private pageList; render(): unknown; private renderDrawer; private renderClientFilter; private emptyState; private renderTable; private renderCards; } declare global { interface HTMLElementTagNameMap { 'ok-data-table': OkDataTable; } }