import type * as Types from "../types"; import type { DataRow, Row } from "../types"; import { GAP } from "../constants"; import { clamp } from "@milaboratories/helpers"; export class AsyncData implements Types.DataSource { constructor( public readonly api: Types.ExternalApi, public readonly rowHeight: number, public readonly resolvePrimaryKey: Types.ResolvePrimaryKey, ) {} get height() { return this.rowHeight + GAP; } async getHeight(): Promise { return (await this.api.count()) * this.height; } async getRows(scrollTop: number, bodyHeight: number): Promise { const offset = clamp(Math.floor(scrollTop / this.height), 0, Number.POSITIVE_INFINITY); const limit = Math.ceil(bodyHeight + 40 / this.height); // @TODO safe window const rows = await this.api.query({ offset, limit }); return rows.map((dataRow, index) => ({ dataRow, index: offset + index, primaryKey: this.resolvePrimaryKey(dataRow, offset + index) as Types.PrimaryKey, offset: (offset + index) * (this.rowHeight + GAP), height: this.rowHeight, })); } }