import type { AtomType } from "../Mutables/atom/atom"; import type { AsyncActionOptions, AsyncActionReturnType } from "./asyncActionTypes"; /** * Everything `asyncAction` returns, plus a `page` atom and a `next()` method. * * @template T - The wrapped async function type. */ export type PaginatedAsyncActionReturnType Promise> = AsyncActionReturnType & { /** * Total number of pages. * * Default is `-1`, meaning unknown. Set it from the API response: * * ```ts * const fetchPosts = paginatedAsyncAction(async () => { * const res = await fetch(`/api/posts?page=${fetchPosts.page.val}`); * const json = await res.json(); * fetchPosts.totalPages.set(json.totalPages); * return json.items; * }); * ``` * * When `-1`, `next()` always proceeds (we don't know the limit yet). * Once set, `next()` becomes a no-op when `page >= totalPages`. */ totalPages: AtomType; /** * Current page number (1-based). * * It is a plain atom — use `.val` to read, `.set()` / `.update()` to write: * * ```ts * action.page.val // read * action.page.set(1) // reset to first page * action.page.set(n) // jump to any page * ``` * * Read it from inside the async callback via closure: * * ```ts * const fetchPosts = paginatedAsyncAction(async () => { * const page = fetchPosts.page.val; * const res = await fetch(`/api/posts?page=${page}`); * return res.json(); * }); * ``` */ page: AtomType; /** * Increment `page` by 1 then call the action with the provided arguments. * * Has the same signature as the wrapped async function so any arguments * the action accepts can be passed straight through: * * ```ts * fetchPosts.next(); // 0-arg action * fetchUserPosts.next(userId); // 1-arg action * ``` */ next: (...args: Parameters) => ReturnType | undefined; }; /** * `paginatedAsyncAction` — an `asyncAction` with a `page` atom and a `next()` * method for simple pagination. * * The wrapped callback reads the current page via closure rather than receiving * it as a parameter, keeping the function signature clean for any other * arguments the action needs. * * --- * * ### Usage * * ```ts * const fetchPosts = paginatedAsyncAction(async () => { * const page = fetchPosts.page.val; // ← closure access * const res = await fetch(`/api/posts?_page=${page}&_limit=10`); * return res.json(); * }); * * // Load first page on mount * fetchPosts(); * * // Advance to next page (e.g. on button click or onVisible sentinel) * fetchPosts.next(); * * // Reset to page 1 manually * fetchPosts.page.set(1); * fetchPosts(); * ``` * * ### With extra arguments * * ```ts * const fetchUserPosts = paginatedAsyncAction(async (userId: number) => { * const page = fetchUserPosts.page.val; * const res = await fetch(`/api/users/${userId}/posts?page=${page}`); * return res.json(); * }); * * fetchUserPosts(5); // userId = 5, page = 1 * fetchUserPosts.next(5); // userId = 5, page = 2 * fetchUserPosts.next(5); // userId = 5, page = 3 * fetchUserPosts.page.set(1) // back to page 1 * fetchUserPosts(5); // reload page 1 * ``` * * ### Infinite scroll sentinel * * ```ts * html` * ${fetchPosts.data.val?.map(p => html`
  • ${p.title}
  • `)} *
    fetchPosts.next())}>
    * ` * ``` * * @param fn - Async function. Read `action.page.val` inside via closure. * @param options - Forwarded to the underlying `asyncAction`. */ export declare function paginatedAsyncAction Promise>(fn: T, options?: AsyncActionOptions): PaginatedAsyncActionReturnType; //# sourceMappingURL=paginatedAsyncAction.d.ts.map