UNPKG

@vtex/admin-ui

Version:

> VTEX admin component library

143 lines (121 loc) 2.83 kB
import { useCallback, useReducer } from 'react' export function usePaginationState( params: UsePaginationParams ): UsePaginationReturn { const { pageSize, initialPage = 1, total = pageSize, stateReducer = defaultReducer, } = params const [state, dispatch] = useReducer( stateReducer, getState(initialPage, pageSize, total) ) const paginate = useCallback( (args: PaginationActionType) => { dispatch({ ...args, pageSize }) }, [pageSize, dispatch] ) return { ...state, paginate } } export function checkDisabled(range: [number, number], total: number) { return { prevDisabled: range[0] <= 1, nextDisabled: range[1] >= total, } } export function setMax(value: number, max: number) { return value <= max ? value : max } export function getState( page: number, pageSize: number, total: number ): PaginationState { const range: [number, number] = [ setMax((page - 1) * pageSize + 1, total), setMax(page * pageSize, total), ] return { currentPage: page, range, total, ...checkDisabled(range, total), } } export function defaultReducer( state: PaginationState, action: PaginationAction ): PaginationState { switch (action.type) { case 'next': { if (state.nextDisabled) return state return getState(state.currentPage + 1, action.pageSize, state.total) } case 'prev': { if (state.prevDisabled) return state return getState(state.currentPage - 1, action.pageSize, state.total) } case 'reset': { return getState(1, action.pageSize, state.total) } case 'navigate': { return getState(action.page, action.pageSize, state.total) } case 'setTotal': { return getState(1, action.pageSize, action.total) } default: return state } } export type PaginationActionType = | { type: 'next' | 'prev' | 'reset' } | { type: 'setTotal' total: number } | { type: 'navigate' page: number } export interface UsePaginationParams { /** * Amount of itens that will be displayed in a page */ pageSize: number /** * Total of items that are being paginated * @default pageSize */ total?: number /** * Initial page * @default 1 */ initialPage?: number /** * Reducer used to handle state in usePagination hook */ stateReducer?: ( state: PaginationState, action: PaginationAction ) => PaginationState } export interface PaginationState { currentPage: number range: [number, number] total: number prevDisabled: boolean nextDisabled: boolean } export type PaginationAction = PaginationActionType & { pageSize: number } export interface UsePaginationReturn extends PaginationState { paginate: (args: PaginationActionType) => void }