import * as React from "react"; import type { PaginationContext, PaginationEvent } from "./types"; import { getTotalPages, getTransformedRange } from "./utils"; function pageReducer(state: PaginationContext, event: PaginationEvent) { const totalPages = getTotalPages(state); switch (event.type) { case "SET_COUNT": if (event.count < 0 || event.count === state.count) { return state; } return { ...state, count: event.count }; case "SET_PAGE": if ( event.page < 1 || event.page > totalPages || event.page === state.page ) { return state; } return { ...state, page: event.page }; case "SET_PAGE_SIZE": return { ...state, pageSize: event.size }; case "FIRST_PAGE": return { ...state, page: 1 }; case "LAST_PAGE": return { ...state, page: totalPages }; case "PREVIOUS_PAGE": return { ...state, page: Math.max(state.page - 1, 1) }; case "NEXT_PAGE": return { ...state, page: Math.min(state.page + 1, totalPages), }; } } const PaginationContext = React.createContext(null!); const PaginationDispatch = React.createContext>( null!, ); export function Pagination({ count = 0, pageSize = 25, siblingCount = 1, page = 1, onPageChange, ...props }: { count: number; pageSize: number; siblingCount: number; page: number; onPageChange: (page: number) => void; } & React.ComponentPropsWithRef<"div">) { const [state, send] = React.useReducer(pageReducer, { count: count ?? 0, pageSize: pageSize ?? 25, siblingCount: siblingCount ?? 1, page: page ?? 1, }); React.useEffect(() => { if (count != null && count !== state.count) { send({ type: "SET_COUNT", count: count }); } }, [count]); React.useEffect(() => { if (pageSize != null && pageSize !== state.pageSize) { send({ type: "SET_PAGE_SIZE", size: pageSize }); } }, [pageSize]); React.useEffect(() => { if (page != null && state.page !== page) { send({ type: "SET_PAGE", page }); } }, [page]); React.useEffect(() => { onPageChange?.(state.page); }, [state.page]); return (
); } Pagination.PrevTrigger = PrevTrigger; Pagination.NextTrigger = NextTrigger; Pagination.PageList = PageList; function PrevTrigger(props: React.ComponentPropsWithRef<"button">) { const ctx = React.useContext(PaginationContext); const send = React.use(PaginationDispatch); return ( ) : (
), )}
); }