{"version":3,"file":"use-paginated-query.cjs","names":[],"sources":["../../src/query/use-paginated-query.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport type { QueryKey, UseQueryOptions } from \"@tanstack/react-query\";\n\nimport type { OffsetPage, OffsetParams } from \"./pagination\";\n\nexport interface UsePaginatedQueryOptions<T> extends Omit<\n    UseQueryOptions<OffsetPage<T>, Error, OffsetPage<T>, QueryKey>,\n    \"queryKey\" | \"queryFn\"\n> {\n    /** Base query key — the current page/sort is appended for cache isolation. */\n    queryKey: QueryKey;\n    /** Fetcher receiving the offset params; return the backend envelope. */\n    queryFn: (params: OffsetParams) => Promise<OffsetPage<T>> | OffsetPage<T>;\n    /** Initial 1-based page. Default: 1. */\n    initialPage?: number;\n    /** Page size. Default: 20. */\n    pageSize?: number;\n    /**\n     * Query-param name for the page size. fastapi-pagination uses `\"size\"`\n     * (default); SDK `BasePaginationFilterSchema` configs may use `\"page_size\"`.\n     */\n    sizeParam?: \"size\" | \"page_size\";\n    /** Initial `order_by` (only sent when set). */\n    orderBy?: string;\n    /** Initial `ascending` (only sent when `orderBy` is set). Default: false. */\n    ascending?: boolean;\n}\n\nexport interface UsePaginatedQueryResult<T> {\n    /** The current page envelope, or undefined while the first load is pending. */\n    page: OffsetPage<T> | undefined;\n    /** The rows of the current page (empty array while pending). */\n    items: T[];\n    /** Current 1-based page number (controlled by the hook). */\n    pageNumber: number;\n    /** Total page count from the last successful response. */\n    pageCount: number;\n    /** Total row count from the last successful response. */\n    total: number;\n    hasNext: boolean;\n    hasPrev: boolean;\n    isLoading: boolean;\n    isFetching: boolean;\n    error: Error | null;\n    /** Jump to a specific 1-based page (clamped to >= 1). */\n    setPage: (page: number) => void;\n    /** Go to the next page when available. */\n    next: () => void;\n    /** Go to the previous page when available. */\n    prev: () => void;\n    /** Refetch the current page. */\n    refetch: () => void;\n}\n\n/**\n * Offset-pagination hook over TanStack Query for the fastapi-pagination /\n * Tempest envelope (`{ items, total, page, size, pages }`).\n *\n * It owns the page state, sends `page` + the size param (`size` by default,\n * or `page_size` via `sizeParam`) plus optional `order_by`/`ascending` to your\n * fetcher, keeps the previous page visible while the next loads, and derives\n * `hasNext`/`hasPrev`/`pageCount`.\n *\n * @example\n * const users = usePaginatedQuery<User>({\n *     queryKey: [\"users\"],\n *     pageSize: 25,\n *     queryFn: (params) => usersService.listUsers(params),\n * });\n * // users.items, users.next(), users.hasNext, users.pageCount\n */\nexport function usePaginatedQuery<T>(\n    options: UsePaginatedQueryOptions<T>,\n): UsePaginatedQueryResult<T> {\n    const {\n        queryKey,\n        queryFn,\n        initialPage = 1,\n        pageSize = 20,\n        sizeParam = \"size\",\n        orderBy,\n        ascending = false,\n        ...queryOptions\n    } = options;\n\n    const [pageNumber, setPageNumber] = useState(initialPage);\n\n    const query = useQuery<OffsetPage<T>, Error>({\n        ...queryOptions,\n        queryKey: [...queryKey, { page: pageNumber, pageSize, sizeParam, orderBy, ascending }],\n        queryFn: () => {\n            const params: OffsetParams = { page: pageNumber, [sizeParam]: pageSize };\n            if (orderBy) {\n                params.order_by = orderBy;\n                params.ascending = ascending;\n            }\n            return queryFn(params);\n        },\n        placeholderData: keepPreviousData,\n    });\n\n    const page = query.data;\n    const pageCount = page?.pages ?? 0;\n    const hasNext = pageNumber < pageCount;\n    const hasPrev = pageNumber > 1;\n\n    const setPage = useCallback((next: number) => setPageNumber(Math.max(1, next)), []);\n    const next = useCallback(() => setPageNumber((p) => (p < pageCount ? p + 1 : p)), [pageCount]);\n    const prev = useCallback(() => setPageNumber((p) => (p > 1 ? p - 1 : p)), []);\n\n    return {\n        page,\n        items: page?.items ?? [],\n        pageNumber,\n        pageCount,\n        total: page?.total ?? 0,\n        hasNext,\n        hasPrev,\n        isLoading: query.isLoading,\n        isFetching: query.isFetching,\n        error: query.error,\n        setPage,\n        next,\n        prev,\n        refetch: () => void query.refetch(),\n    };\n}\n"],"mappings":"0DAwEA,SAAgB,EACZ,EAC0B,CAC1B,GAAM,CACF,WACA,UACA,cAAc,EACd,WAAW,GACX,YAAY,OACZ,UACA,YAAY,GACZ,GAAG,GACH,EAEE,CAAC,EAAY,IAAA,EAAiB,EAAA,SAAA,CAAS,CAAW,EAElD,GAAA,EAAQ,EAAA,SAAA,CAA+B,CACzC,GAAG,EACH,SAAU,CAAC,GAAG,EAAU,CAAE,KAAM,EAAY,WAAU,YAAW,UAAS,WAAU,CAAC,EACrF,YAAe,CACX,IAAM,EAAuB,CAAE,KAAM,GAAa,GAAY,CAAS,EAKvE,OAJI,IACA,EAAO,SAAW,EAClB,EAAO,UAAY,GAEhB,EAAQ,CAAM,CACzB,EACA,gBAAiB,EAAA,gBACrB,CAAC,EAEK,EAAO,EAAM,KACb,EAAY,GAAM,OAAS,EAC3B,EAAU,EAAa,EACvB,EAAU,EAAa,EAEvB,GAAA,EAAU,EAAA,YAAA,CAAa,GAAiB,EAAc,KAAK,IAAI,EAAG,CAAI,CAAC,EAAG,CAAC,CAAC,EAC5E,GAAA,EAAO,EAAA,YAAA,KAAkB,EAAe,GAAO,EAAI,EAAY,EAAI,EAAI,CAAE,EAAG,CAAC,CAAS,CAAC,EACvF,GAAA,EAAO,EAAA,YAAA,KAAkB,EAAe,GAAO,EAAI,EAAI,EAAI,EAAI,CAAE,EAAG,CAAC,CAAC,EAE5E,MAAO,CACH,OACA,MAAO,GAAM,OAAS,CAAC,EACvB,aACA,YACA,MAAO,GAAM,OAAS,EACtB,UACA,UACA,UAAW,EAAM,UACjB,WAAY,EAAM,WAClB,MAAO,EAAM,MACb,UACA,OACA,OACA,YAAe,KAAK,EAAM,QAAQ,CACtC,CACJ"}