export type ColumnId = string; export interface Column { id: ColumnId; name: string; visible?: boolean; searchPlaceholder?: string | false; datalist?: boolean; sortable?: boolean; compare?: (a: RowData, b: RowData) => number; render?: (row: RowData, td: HTMLTableCellElement) => void; renderHeader?: (th: HTMLTableCellElement) => void; /** Preferred column width in CSS pixels. Honored by Resizable / preserveColumnWidths. */ width?: number; } export type SortOrder = "ascent" | "descent"; export interface SortState { columnId: ColumnId; order: SortOrder; } export type RowData = Record; export type CellFormatter = (value: string | number | boolean | null | undefined, columnId: ColumnId) => Node; export interface Formatters { theadCell?: CellFormatter; tbodyCell?: CellFormatter; tfootCell?: CellFormatter; } export interface Plugin { addEventListeners(): void; removeEventListeners(): void; } export interface PaginationRenderParams { currentPage: number; totalPages: number; maxPageButtons?: number; } export interface PaginationOptions { pageSize: number; container: HTMLElement | null; maxPageButtons?: number; render?: (params: PaginationRenderParams) => HTMLElement; } export interface ColumnSearchOptions { placeholder?: string; debounce?: number; datalist?: boolean; } export interface ColumnSelectorRenderParams { columns: Column[]; toggleColumn: (columnId: ColumnId) => void; } export interface ColumnSelectorOptions { container: HTMLElement | null; render?: (params: ColumnSelectorRenderParams) => HTMLElement; } export type SortDirection = "ascending" | "descending" | "none"; export interface SortIndicatorOptions { render?: (direction: SortDirection) => HTMLElement | null; } export interface ComponentOptions { pagination?: PaginationOptions; columnSearch?: ColumnSearchOptions; columnSelector?: ColumnSelectorOptions; sortIndicator?: SortIndicatorOptions; } export interface TableOptions { data: RowData[]; columns: Column[]; plugins?: Plugin[]; components?: ComponentOptions; formatters?: Formatters; } export declare class Table { container: HTMLElement; readonly options: TableOptions; private static instanceCount; private readonly instanceId; private readonly emptyString; private filters; private filteredData; private sortState; private displayDataCache; private searchDebounceTimers; private plugins; pagination?: Pagination; private columnSelector?; /** * Fixed widths declared via column.width or renderHeader(th.style.width). * Kept on the Table instance (not DOM style) so Resizable.reset() cannot * erase the author's intent before the next preserveColumnWidths(). */ private fixedColumnWidths; constructor(options: TableOptions); getVisibleColumns(): Column[]; getDisplayData(): RowData[]; private invalidateDisplayCache; /** * Resolve a column's fixed width (px), if any. * Priority: column.width → fixedColumnWidths map (from renderHeader style.width). * Never relies on th.style.width at measure time — Resizable.reset() clears it. */ private getFixedColumnWidth; private applyWidthToCell; private layoutObserver; private pendingPreserve; /** * Re-run preserveColumnWidths once the table (or its parent) actually has a * non-zero layout size. MIDI library renders into a Bootstrap modal that is * display:none on first load — preserve then sees parentWidth=0 and the * fixed 32px toolbar column only becomes correct on the next explicit * preserve (sort / filter / resize). Observe until laid out, then disconnect. */ private ensureLayoutObserver; private preserveColumnWidths; private getResizablePlugin; /** * Clear locked column widths and return to content-based (auto) layout. * Call when the container size or data shape changes and you want columns * to reflow naturally (e.g. after a responsive breakpoint, sidebar toggle, * or navigating to a view with different available width). * * @param relock - If true (default), re-measure and lock widths again under * fixed layout after the browser has applied auto layout. If false, leave * the table in auto layout until the next resize drag or preserve. */ resetColumnWidths(relock?: boolean): void; private compareRows; private getColumn; private isSortableEnabled; isColumnSortable(columnId: ColumnId): boolean; isColumnObjectSortable(column: Column): boolean; private getSortDirectionFor; private renderSortIndicator; private addPlugins; private addComponents; private defaultCellFormatter; private getCellFormatter; private renderColumns; private renderSearchRow; private renderThead; private renderTbody; private computeFilteredData; applyFilters(): void; private getColumnDatalistValues; private appendDatalistOptions; private createDatalist; private updateSearchDatalists; setData(data: RowData[]): void; setFilter(columnId: ColumnId, keyword: string): void; getFilter(columnId: ColumnId): string; private updateSearchInputValidity; sortBy(columnId: ColumnId, order?: SortOrder): void; getSortState(): SortState | null; private updateSortIndicators; private syncSearchInput; private renderColumnSelector; toggleColumn(columnId: ColumnId): void; render(container: HTMLElement): HTMLElement; update(): HTMLElement; updateTbody(): void; getRowElement(index: number): HTMLTableRowElement | undefined; getPageForIndex(index: number): number; destroy(): void; } type HoverStatus = "left" | "right" | "in" | "out"; declare class Cell { protected collisionWidth: number; protected findCell(event: PointerEvent, tagNames: string[]): HTMLElement | undefined; protected getHoverStatus(event: PointerEvent, cell: HTMLElement | undefined): HoverStatus; protected findIndex(cells: HTMLCollectionOf, cell: HTMLElement): number; } export declare class Editable extends Cell implements Plugin { private readonly table; private readonly onPointerDown; private readonly onBlur; constructor(table: Table); addEventListeners(): void; removeEventListeners(): void; private editCell; private saveCell; } export declare class Resizable extends Cell implements Plugin { private resizingCells; private readonly table; private readonly onPointerMove; private readonly onPointerDown; private readonly onPointerUp; private readonly onResize; constructor(table: Table); addEventListeners(): void; removeEventListeners(): void; reset(): void; private setPointerStyle; private resizeStartCell; private resizeEndCell; private isFixedWidthCell; private hoverCellBorder; } export declare class Sortable extends Cell implements Plugin { private sorting; private resizable?; private pointerDownCell; private readonly table; private readonly onPointerDown; private readonly onPointerUp; private readonly onKeyDown; constructor(table: Table, options?: { resizable?: Resizable; }); addEventListeners(): void; removeEventListeners(): void; private resolveHeaderColumnId; private handlePointerDown; private sortRows; private handleKeyDown; } export declare class Pagination { private readonly table; readonly pagination: PaginationOptions; currentPage: number; private readonly onClick; constructor(table: Table); addEventListeners(): void; removeEventListeners(): void; getTotalPages(): number; private handleClick; goToPage(page: number): void; render(): void; } export declare function defaultPagination({ currentPage, totalPages, maxPageButtons }: PaginationRenderParams): HTMLElement; export declare function defaultSortIndicator(direction: SortDirection): HTMLElement | null; export declare function defaultColumnSelector({ columns, toggleColumn }: ColumnSelectorRenderParams): HTMLElement; export {}; //# sourceMappingURL=table.d.ts.map