Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
TypeScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061export type PagerState = | { kind: "at-page"; page: number } | { kind: "loading"; page: number } | { kind: "failed"; page: number };
export interface OffsetPager<T> { readonly state: PagerState; readonly items: T[]; readonly limit: number; readonly hasNext: boolean; select: (target: number) => Promise<void>;}
export { discoveredPageCount, pageCount } from "$lib/pagination";
// size the last page to its remainder, or a full page when total is unknownexport const pageRows = (page: number, limit: number, total?: number): number => total === undefined ? limit : Math.min(limit, Math.max(1, total - (page - 1) * limit));
export const createOffsetPager = <T>( initial: T[], limit: number, load: (offset: number) => Promise<T[]>): OffsetPager<T> => { let state = $state<PagerState>({ kind: "at-page", page: 1 }); let pages = $state<Record<number, T[]>>({ 1: initial });
// point to the target page immediately so the skeleton and footer follow the click const select = async (target: number) => { if (state.kind === "loading" || target < 1 || target === state.page) return;
const currentPage = state.page; state = { kind: "loading", page: target }; try { if (!pages[target]) { pages = { ...pages, [target]: await load((target - 1) * limit) }; } state = { kind: "at-page", page: target }; } catch { state = { kind: "failed", page: currentPage }; } };
return { get state() { return state; }, get items() { return pages[state.page] ?? []; }, get limit() { return limit; }, get hasNext() { // assume an in-flight page is full so the footer keeps its shape return (pages[state.page]?.length ?? limit) >= limit; }, select };};