@discordx/pagination
Version:
Library for creating pagination messages in Discord bots
350 lines (343 loc) • 9.21 kB
text/typescript
import { BaseMessageOptions, JSONEncodable, AttachmentPayload, MessageCollectorOptionsParams, MessageComponentType, Message, ComponentEmojiResolvable, ButtonStyle, CommandInteraction, MessageComponentInteraction, ContextMenuCommandInteraction, TextBasedChannel, PartialGroupDMChannel, InteractionCollector, ButtonInteraction, StringSelectMenuInteraction, ActionRowBuilder, MessageActionRowComponentBuilder } from 'discord.js';
declare const defaultTime = 300000;
declare const defaultPerPageItem = 10;
declare const defaultIds: {
buttons: {
previous: string;
backward: string;
forward: string;
next: string;
exit: string;
};
menu: string;
};
type PaginationItem = BaseMessageOptions & {
attachments?: JSONEncodable<AttachmentPayload>[];
};
type PaginationInteractions = CommandInteraction | MessageComponentInteraction | ContextMenuCommandInteraction;
type PaginationSendTo = PaginationInteractions | Message | Exclude<TextBasedChannel, PartialGroupDMChannel>;
declare enum SelectMenuPageId {
Start = -1,
End = -2
}
interface BasicPaginationOptions extends MessageCollectorOptionsParams<MessageComponentType> {
/**
* Debug log
*/
debug?: boolean;
/**
* Enable exit button, It will close the pagination before timeout
*/
enableExit?: boolean;
/**
* Set ephemeral response
*/
ephemeral?: boolean;
/**
* Initial page (default: 0)
*/
initialPage?: number;
/**
* Number of items shown per page in select menu
*/
itemsPerPage?: number;
/**
* Pagination timeout callback
*/
onTimeout?: (page: number, message: Message) => void;
}
interface ButtonOptions {
/**
* Button emoji
*/
emoji?: ComponentEmojiResolvable | null;
/**
* Button id
*/
id?: string;
/**
* Button label
*/
label?: string;
/**
* Button style
*/
style?: ButtonStyle;
}
interface NavigationButtonOptions {
/**
* Previous button options
*/
previous?: ButtonOptions;
/**
* Backward button options (-10)
*/
backward?: ButtonOptions;
/**
* Forward button options (+10)
*/
forward?: ButtonOptions;
/**
* Next button options
*/
next?: ButtonOptions;
/**
* Exit button options
*/
exit?: ButtonOptions;
/**
* Number of pages to skip with skip buttons (default: 10)
*/
skipAmount?: number;
}
interface SelectMenuOptions {
/**
* Various labels
*/
labels?: {
end?: string;
start?: string;
};
/**
* custom select menu id (default: 'discordx@pagination@menu')
*/
menuId?: string;
/**
* Define page text, use `{page}` to print page number
* Different page texts can also be defined for different items using arrays
*/
pageText?: string | string[];
/**
* Custom range placeholder format
* Use {start}, {end}, and {total} as placeholders
*/
rangePlaceholderFormat?: string;
}
interface PaginationOptions extends BasicPaginationOptions {
/**
* Navigation button configuration
*/
buttons?: NavigationButtonOptions;
/**
* Select menu configuration
*/
selectMenu?: SelectMenuOptions;
}
interface IPaginate {
currentPage: number;
endIndex: number;
endPage: number;
pageSize: number;
pages: number[];
startIndex: number;
startPage: number;
totalItems: number;
totalPages: number;
}
interface IGeneratePage {
newMessage: BaseMessageOptions;
components: ActionRowBuilder<MessageActionRowComponentBuilder>[];
}
interface PaginationCollectors {
buttonCollector: InteractionCollector<ButtonInteraction>;
menuCollector: InteractionCollector<StringSelectMenuInteraction>;
}
declare class PaginationBuilder {
private readonly item;
private readonly currentPage;
private readonly perPage;
private readonly maxPage;
private readonly config?;
constructor(item: PaginationItem, currentPage: number, maxPage: number, config?: PaginationOptions);
private validateInputs;
private prepareMessage;
/**
* Get the display text for a page
*/
private getPageText;
/**
* Create page-specific options for select menu
*/
private createPageOptions;
private calculateButtonStates;
private createNavigationButtons;
private createButton;
/**
* Create navigation button row
*/
private createNavigationButtonRow;
generate(): {
newMessage: PaginationItem;
components: ActionRowBuilder<MessageActionRowComponentBuilder>[];
};
}
interface PaginationConfig {
totalItems: number;
currentPage?: number;
pageSize?: number;
maxPages?: number;
}
/**
* Creates pagination data for UI controls and data slicing
* @param config - Pagination configuration object
* @returns Complete pagination information
* @throws {Error} When input validation fails
*
* @example
* ```typescript
* const pagination = createPagination({
* totalItems: 100,
* currentPage: 5,
* pageSize: 10,
* maxPages: 7
* });
* ```
*/
declare function createPagination(config: PaginationConfig): IPaginate;
type Resolver = (page: number, pagination: Pagination) => PaginationItem | Promise<PaginationItem>;
declare class PaginationResolver<T extends Resolver = Resolver> {
resolver: T;
maxLength: number;
constructor(resolver: T, maxLength: number);
}
declare class Pagination<T extends PaginationResolver = PaginationResolver> {
sendTo: PaginationSendTo;
pages: PaginationItem[] | T;
config?: PaginationOptions | undefined;
maxLength: number;
currentPage: number;
collectors?: PaginationCollectors;
message?: Message;
private _isSent;
private _isFollowUp;
get isSent(): boolean;
constructor(sendTo: PaginationSendTo, pages: PaginationItem[] | T, config?: PaginationOptions | undefined);
/**
* Validate configuration and throw descriptive errors
*/
private validateConfiguration;
/**
* Validate button configuration
*/
private validateButtonOptions;
/**
* Log debug messages with consistent formatting
*/
private debug;
/**
* Handle update errors gracefully
*/
private unableToUpdate;
/**
* Get skip amount
*/
private getSkipAmount;
/**
* Get button ID with fallback to default
*/
private getButtonId;
/**
* Get menu ID with fallback to default
*/
private getMenuId;
/**
* Get time with fallback to default
*/
private getTime;
/**
* Get page
*/
getPage: (page: number) => Promise<IGeneratePage | null>;
/**
* Send pagination
* @returns
*/
send(): Promise<{
collectors: PaginationCollectors;
message: Message;
}>;
/**
* Stop the pagination collector
*/
stop(): void;
/**
* Navigate to a specific page
*/
navigateToPage(page: number): boolean;
/**
* Navigate to next page
*/
navigateNext(): boolean;
/**
* Navigate to previous page
*/
navigatePrevious(): boolean;
/**
* Check if pagination can navigate to next page
*/
canNavigateNext(): boolean;
/**
* Check if pagination can navigate to previous page
*/
canNavigatePrevious(): boolean;
/**
* Get current page info
*/
getPageInfo(): {
currentPage: number;
totalPages: number;
canNext: boolean;
canPrevious: boolean;
isFirst: boolean;
isLast: boolean;
};
/**
* Navigate to first page
*/
navigateToStart(): boolean;
/**
* Navigate to last page
*/
navigateToEnd(): boolean;
/**
* Handle exit
*/
private handleExit;
/**
* Update the pagination message with current page
*/
private updatePaginationMessage;
/**
* Prepare initial message with pagination components
*/
private prepareInitialMessage;
/**
* Send message via interaction (reply or followUp)
*/
private sendInteractionMessage;
/**
* Send message based on sendTo type
*/
private sendMessage;
/**
* Create and configure the collectors
*/
private createCollector;
/**
* Setup collector event handlers
*/
private setupCollectorEvents;
/**
* Handle button interaction
*/
private handleButtonInteraction;
/**
* Handle select menu interaction
*/
private handleSelectMenuInteraction;
/**
* Handle collector end event
*/
private handleCollectorEnd;
}
export { type BasicPaginationOptions, type ButtonOptions, type IGeneratePage, type IPaginate, type NavigationButtonOptions, Pagination, PaginationBuilder, type PaginationCollectors, type PaginationConfig, type PaginationInteractions, type PaginationItem, type PaginationOptions, PaginationResolver, type PaginationSendTo, type Resolver, type SelectMenuOptions, SelectMenuPageId, createPagination, defaultIds, defaultPerPageItem, defaultTime };