@sapphy/pagination
v1.0.0
Published
A lightweight Discord.js library for creating paginated embed messages with button-based navigation
Maintainers
Readme
Discord Embed Pagination
A lightweight Discord.js library for creating paginated embed messages with button-based navigation.
Features
- 🎯 Simple API - Easy to use with minimal configuration
- 🎨 Customizable - Custom embed generators and navigation emojis
- 🔒 Secure - Permission checks and user-specific interactions
- ⏱️ Auto-cleanup - Automatic message cleanup after timeout
- 🧪 TypeScript Support - Full type safety with strict mode
- 📦 Lightweight - No external dependencies except Discord.js
- 🧪 Well Tested - Comprehensive unit tests with Vitest
Installation
npm install @sapphy/paginationRequirements
- Node.js 18.0.0 or higher
- Discord.js 14.0.0 or higher
Quick Start
import { EmbedPaginator } from 'discord-embed-pagination';
// Your data to paginate
const users = [
{ id: 1, name: 'Alice', role: 'Admin' },
{ id: 2, name: 'Bob', role: 'Moderator' },
// ... more data
];
// Create a paginator
const paginator = new EmbedPaginator({
itemsPerPage: 10,
data: users,
embedColor: '#0099ff'
});
// Start pagination in a channel
await paginator.start(message.channel);API Reference
EmbedPaginator
The main class for creating paginated embed messages.
Constructor
new EmbedPaginator<T>(options: PaginationOptions<T>)Options
interface PaginationOptions<T = any> {
itemsPerPage: number; // Number of items per page
data: T[]; // Array of data to paginate
maxPages?: number; // Optional maximum number of pages
timeout?: number; // Timeout in milliseconds (default: 60000)
ephemeral?: boolean; // Whether the message is ephemeral (default: false)
authorOnly?: boolean; // Only allow original user to interact (default: true)
embedColor?: ColorResolvable; // Embed color (default: '#0099ff')
navigationEmojis?: Partial<NavigationEmojis>; // Custom navigation emojis
embedGenerator?: (page: number, items: T[], totalPages: number) => EmbedBuilder; // Custom embed generator
pageFormatter?: (currentPage: number, totalPages: number) => string; // Custom page formatter
}Methods
start(channel: TextBasedChannel): Promise<Message>- Start paginationstop(): Promise<void>- Stop pagination and clean upgoToPage(page: number): Promise<void>- Navigate to specific pagenextPage(): Promise<void>- Navigate to next pagepreviousPage(): Promise<void>- Navigate to previous pagegetStats(): PaginationStats- Get pagination statistics
PaginationManager
Manager class for handling multiple pagination instances.
const manager = new PaginationManager();
// Create a paginator
const paginator = manager.createPaginator(options);
// Get paginator by ID
const paginator = manager.getPaginator(id);
// Remove a paginator
manager.removePaginator(id);
// Clean up all instances
await manager.cleanup();ButtonNavigation
Utility class for button navigation (used internally).
Static Methods
createButton(type: NavigationType, disabled?: boolean, emoji?: string): ButtonBuildercreateNavigationButtons(currentPage: number, totalPages: number, customEmojis?: Partial<NavigationEmojis>): ActionRowBuilderhandleInteraction(interaction: ButtonInteraction, currentPage: number, totalPages: number, updateCallback: Function): Promise<void>
Examples
Basic Pagination
const paginator = new EmbedPaginator({
itemsPerPage: 10,
data: userList,
embedColor: '#0099ff'
});
await paginator.start(message.channel);Custom Embed Generator
const paginator = new EmbedPaginator({
itemsPerPage: 5,
data: products,
embedGenerator: (page, items, totalPages) => {
const embed = new EmbedBuilder()
.setTitle('Products Catalog')
.setDescription(items.map(product =>
`**${product.name}** - $${product.price}`
).join('\n'));
return embed;
}
});Custom Navigation Emojis
const paginator = new EmbedPaginator({
itemsPerPage: 8,
data: items,
navigationEmojis: {
FIRST: '🏠',
PREVIOUS: '⬅️',
NEXT: '➡️',
LAST: '🏁'
}
});Using PaginationManager
const manager = new PaginationManager();
// Create multiple paginators
const paginator1 = manager.createPaginator(options1);
const paginator2 = manager.createPaginator(options2);
// Later...
await manager.stopUserPaginations(userId); // Stop all for a user
await manager.stopChannelPaginations(channelId); // Stop all in a channelButton Navigation
The library creates four navigation buttons:
- First (
⏮️) - Jump to first page - Previous (
◀️) - Go to previous page - Next (
▶️) - Go to next page - Last (
⏭️) - Jump to last page
Buttons are automatically disabled when at the beginning or end of the pagination.
Customization
Navigation Emojis
You can customize the navigation emojis:
const paginator = new EmbedPaginator({
// ... other options
navigationEmojis: {
FIRST: '🏠',
PREVIOUS: '⬅️',
NEXT: '➡️',
LAST: '🏁'
}
});Page Formatting
Customize the page number display:
const paginator = new EmbedPaginator({
// ... other options
pageFormatter: (current, total) => `📄 ${current}/${total}`
});Embed Styling
Customize the embed appearance:
const paginator = new EmbedPaginator({
// ... other options
embedColor: '#ff00ff',
ephemeral: true,
authorOnly: false
});Error Handling
The library throws specific errors for common issues:
import {
PaginationError,
InvalidOptionsError,
PermissionError,
TimeoutError
} from '@sapphy/pagination';
try {
await paginator.start(channel);
} catch (error) {
if (error instanceof InvalidOptionsError) {
console.error('Invalid options:', error.message);
} else if (error instanceof PermissionError) {
console.error('Permission error:', error.message);
} else if (error instanceof TimeoutError) {
console.error('Timeout:', error.message);
}
}Testing
Run the tests:
npm testRun tests with coverage:
npm run test:coverageContributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Ensure all tests pass (
npm test) - Submit a pull request
License
MIT License - see LICENSE file for details.
Changelog
v1.0.0
- Initial release
- Basic pagination functionality
- Button-based navigation
- Custom embed generators
- TypeScript support
- Comprehensive tests
