import { useInterpret, useSelector } from '@xstate/react'; import type { PaginationMachineState } from './paginationMachine'; import { paginationMachine } from './paginationMachine'; export type UsePaginationOpts = { pagesCount: number; pagesToDisplay?: number; onPageChange?: (page: number) => void; initialState?: { currentPage?: number; }; }; const selectors = { context(state: PaginationMachineState) { return state.context; }, }; /** * Hook to used inside the component to handle paginatioMachie logic. * @param pagesCount The total number of pages. * @param pagesToDisplay The total number of pages to display. * @param onPageChange The callback to call when the page changes. * @param initialState The initial state. * @returns UsePaginationReturn * - pages: The pages to display. * - currentPage: The current page. * - next: The function to go to the next page. * - prev: The function to go to the previous page. * - goTo: The function to go to a specific page. * * @example * const { pages, currentPage, next, prev, goTo } = usePagination({ * pagesCount: 10, * pagesToDisplay: 5, * onPageChange: (page) => console.log(page), * initialState: { * currentPage: 1, * }, * }); * @example */ export function usePagination(opts: UsePaginationOpts) { const service = useInterpret(() => paginationMachine .withContext({ pagesCount: opts.pagesCount, pagesToDisplay: opts.pagesToDisplay, currentPage: opts.initialState?.currentPage ?? 1, }) .withConfig({ actions: { onPageChange: (ctx) => { opts.onPageChange?.(ctx.currentPage!); }, }, }), ); const context = useSelector(service, selectors.context); function next() { service.send({ type: 'NEXT' }); } function prev() { service.send({ type: 'PREV' }); } function goTo(page: number) { service.send({ type: 'GOTO', input: page }); } return { ...context, next, prev, goTo, }; } export type UsePaginationReturn = ReturnType;