Skip to content

Pagination

The pagination helpers turn three numbers — items per page, total item count, and the current page — into everything you need to render a paged list: offsets, page counts, the first and last item on a page, and boundary checks. There are two entry points: the Paginator class and the pagination factory.

import { pagination, Paginator } from '@0x26e/utils'

The pagination factory

pagination(perPage, itemCount) is a one-line shortcut that creates a Paginator, sets the items per page, and sets the total item count — leaving you to set the page.

function pagination(perPage: number, itemCount: number): Paginator

Parameters

ParameterTypeDescription
perPagenumberThe number of items shown on each page.
itemCountnumberThe total number of items across all pages.

Returns Paginator — a configured instance, ready for .setPage(...).

Worked example

A list of 100 items, 10 per page, viewing page 2:

import { pagination } from '@0x26e/utils'
 
const page = pagination(10, 100).setPage(2)
 
page.getPage() // 2
page.getFirstItemOnPage() // 11
page.getLastItemOnPage() // 20
page.getPageCount() // 10
page.getOffset() // 10
page.getCountdownOffset() // 80
page.getLength() // 10
page.getFirstPage() // 1
page.getLastPage() // 10
page.isFirst() // false
page.isLast() // false

Use getOffset() and getLength() to slice your data — they map directly onto a SQL LIMIT/OFFSET or Array.prototype.slice:

const all = await db.items.count() // 100
const page = pagination(10, all).setPage(2)
 
const rows = await db.items.findMany({
  skip: page.getOffset(), // 10
  take: page.getLength(), // 10
})

A last-page example shows how getLength shrinks for a partial final page. With 95 items, 10 per page, page 10 holds only 5 items:

const last = pagination(10, 95).setPage(10)
last.getPageCount() // 10
last.getLength() // 5  (only 5 items on the final page)
last.isLast() // true

The Paginator class

pagination() is built on the Paginator class. Construct it directly when you want to set values step by step — every setter returns the instance, so calls chain.

const paginator = new Paginator()
paginator.setPage(2).setItemsPerPage(10).setItemCount(100)
 
paginator.getPage() // 2
paginator.getFirstItemOnPage() // 11
paginator.getLastItemOnPage() // 20
paginator.getPageCount() // 10
paginator.isFirst() // false
paginator.isLast() // false

Base page and clamping

By default pages are 1-based — the first page is 1. Change this with setBase(...) if your UI counts from 0. The current page is also clamped to a valid range when itemCount is known, so asking for a page beyond the last returns the last page's values rather than going out of bounds.

Some getters return null until itemCount is set

Paginator works without a total count, but anything that depends on knowing how many items exist — getLastPage, getPageCount, getCountdownOffset, and the item count — returns null until you call setItemCount(...). The pagination() factory always sets it, so they return numbers there.

Setters

Each setter mutates the instance and returns this for chaining.

MethodReturnsDescription
setPage(page: number)thisSets the current page number.
setItemsPerPage(itemsPerPage: number)thisSets items per page (floored at 1).
setItemCount(itemCount?: number | null)thisSets the total item count (floored at 0); pass null to clear it.
setBase(base: number)thisSets the base page number (the number of the first page).

Getters & checks

MethodReturnsDescription
getPage()numberThe current page number (clamped to the valid range when item count is known).
getBase()numberThe base page number.
getFirstPage()numberThe first page number (equal to the base).
getLastPage()number | nullThe last page number, or null if item count is not set.
getFirstItemOnPage()numberSequence number of the first item on the current page (0 when there are no items).
getLastItemOnPage()numberSequence number of the last item on the current page.
getPageCount()number | nullTotal number of pages, or null if item count is not set.
getOffset()numberAbsolute index of the first item on the current page (page index × items per page).
getCountdownOffset()number | nullAbsolute index of the first item counting from the end, or null if item count is not set.
getLength()numberNumber of items on the current page (less than the page size on a partial final page).
getItemCount()number | nullThe total number of items, or null if not set.
getItemsPerPage()numberThe number of items per page.
isFirst()booleantrue when the current page is the first page.
isLast()booleantrue when the current page is the last page (false if item count is not set).

getOffset vs getCountdownOffset

getOffset() is the index of the current page's first item counted from the start of the list — use it for OFFSET. getCountdownOffset() is that same first item counted from the end, which is handy for "newest first" feeds where you page backwards through a fixed total. On page 2 of 100 items at 10 per page, getOffset() is 10 while getCountdownOffset() is 80.

js-utils — A TypeScript utility collection similar to Laravel helpers. Released under the MIT license.