@yaebal/pagination

paginated inline lists with automatic prev/next navigation. renders a page of items as a message, attaches ◀ / ▶ buttons, and handles the button presses — editing the message in place.

install

shell
pnpm add @yaebal/pagination

registration

pagination(options) returns a Pagination object. call bot.install(list.plugin()) to register the callback handler, then list.send(ctx) to display the first page.

user-list.ts
import { Bot } from "@yaebal/core";
import { pagination } from "@yaebal/pagination";

const bot = new Bot(token);

const userList = pagination<string>({
  id: "users",        // namespaces callback_data — must be unique per list
  pageSize: 5,        // items per page (default 5)
  source: async (ctx) => fetchAllUsers(),   // may be async
  line: (name, index) => `${index + 1}. ${name}`,
});

// register the prev/next button handler
bot.install(userList.plugin());

// send the first page on command
bot.command("users", (ctx) => userList.send(ctx));

api

exportkinddescription
paginationfunction(options: PaginationOptions<T>) => Pagination
PaginationOptionsinterfaceconfiguration — see options table.
Paginationinterfacethe object returned by pagination().

PaginationOptions

fieldtyperequireddescription
idstringyesunique namespace for this list's callback_data. must not contain :.
source(ctx: Context) => T[] | Promise<T[]>yesreturns the full item list. called on every page render.
line(item: T, index: number) => stringyesrenders one item. index is the global index across all pages.
pageSizenumbernoitems per page. default 5.
header(page: number, pages: number) => stringnocustom page header. default: "page N/M". page is 0-based (add 1 for display); pages is the total page count (1-based).

Pagination object

membersignaturedescription
plugin()() => Pluginreturns a plugin that intercepts ◀ / ▶ callback queries and edits the message. install with bot.install(list.plugin()).
send(ctx, page?)(ctx: Context, page?: number) => Promise<unknown>sends the list starting at page (default 0). only shows ▶ on the first page; both ◀ and ▶ in the middle; only ◀ on the last.

custom header example

custom-header.ts
const itemList = pagination<string>({
  id: "items",
  source: () => ["apple", "banana", "cherry", "date", "elderberry", "fig"],
  line: (item, i) => `${i}: ${item}`,
  header: (page, pages) => `results — page ${page + 1} of ${pages}`,
});
each id must be unique. the id is baked into the callback_data via @yaebal/callback-data. two lists with the same id will intercept each other's button presses. @yaebal/keyboard and @yaebal/callback-data are peer dependencies installed automatically.