type RowLike = string | Record<string, unknown>;
type PrimaryKey<T> = keyof T & (string | number | symbol);
interface ClusterizeOptions<TRow = RowLike> {
    rowHeight: number;
    fetchOnInit: () => Promise<TRow[] | {
        totalRows: number;
        rows: TRow[];
    }>;
    fetchOnScroll: (offset: number) => Promise<TRow[]>;
    renderSkeletonRow: (height: number, index: number) => string;
    renderRaw?: (index: number, data: TRow) => string;
    scrollElem: HTMLElement;
    contentElem: HTMLElement;
    buffer?: number;
    prefetchRows?: number;
    cacheTTL?: number;
    debounceMs?: number;
    autoEvict?: boolean;
    scrollingProgress?: (firstVisible: number) => void;
    debug?: boolean;
    /** paint skeletons immediately (default = true) */
    showInitSkeletons?: boolean;
    buildIndex?: boolean;
    primaryKey?: PrimaryKey<TRow>;
}
interface CacheEntry<TRow = RowLike> {
    html: string;
    ts: number;
    data?: TRow;
}
interface Patch<TRow> {
    id?: unknown;
    index?: number;
    data: TRow;
}
declare class ClusterizeLazy<TRow = RowLike> {
    private readonly opts;
    private totalRows;
    private cache;
    private readonly inFlight;
    private readonly v;
    private readonly now;
    private debounceTimer;
    private pendingOffset;
    private readonly cleanup?;
    private readonly index?;
    private readonly log;
    constructor(opts: ClusterizeOptions<TRow>);
    destroy(): void;
    refresh(): void;
    scrollToRow(i: number, smooth?: boolean): void;
    getLoadedCount(): number;
    /** replace rows in place; ids take precedence over numeric indexes */
    update(patches: Patch<TRow>[]): void;
    /** insert rows at position (defaults to 0) */
    insert(rows: TRow[], at?: number): void;
    /** remove rows by id or numeric index */
    remove(keys: Array<unknown>): void;
    /** low-level dump for debug or power users */
    _dump(): {
        cache: (CacheEntry<TRow> | undefined)[];
        index: Map<unknown, number> | undefined;
    };
    private paintInitialSkeletons;
    private firstFetch;
    private render;
    private installRows;
    private renderRaw;
    private isLive;
    private evictStale;
    private resolveIndex;
    /** shift index entries after an insertion/deletion */
    private shiftIndex;
    /** fully rebuild index (cheap on V-lists) */
    private rebuildIndex;
    private scheduleFetch;
}

/**
 * Compatibility factory.
 * Lets you call either `new Clusterize(opts)` or just `Clusterize(opts)`.
 */
declare function Clusterize<TRow = RowLike>(opts: ClusterizeOptions<TRow>): ClusterizeLazy<TRow>;
declare namespace Clusterize {
    var prototype: ClusterizeLazy<any>;
}

export { ClusterizeLazy, type ClusterizeOptions, type PrimaryKey, type RowLike, Clusterize as default };
