UNPKG

discordjs-choice-selectmenu-builder

Version:

An utility builder to represent arrays as paginated Discord select menus.

376 lines (372 loc) 15.7 kB
import { Collection, ButtonStyle, Interaction, ActionRowBuilder, StringSelectMenuBuilder, ButtonBuilder } from 'discord.js'; declare class PageManager<T> { constructor(array: T[], selected: Collection<number, T>, minChoices: number, maxChoices?: number, currentPage?: number); /** * The length that a single select menu page can have. */ length: number; /** * A reference to the array to paginate. */ array: T[]; /** * A reference to the selected elements. */ selected: Collection<number, T>; /** * The 0-indexed page the builder is currently on. * This is always in the range `0 <= current <= max` */ current: number; /** * The minimum amount of choices that a user must make. * Note that it only prevents selecting less than this value, it * can still be visually shown without any selections. */ minChoices: number; /** * The maximum amount of choices that a user may make. * This value defaults to `options.length`. */ maxChoices?: number; get carrySelected(): boolean; /** * The maximum 0-indexed page the builder can reach. * This property is derived from the page's length */ get max(): number; getPage(pageNumber?: number): [index: number, element: T][]; /** * Returns a slice of the array, along with its actual index location. * @param start - The start of the slice. * @param end - The end of the slice. * @param removeSelected - Removes selected indeces from the sliced array. */ private getSlice; /** * Get the end index of the page starting from the start parameter. * Will include more elements if the keys exist on the page. * @param start - The offset to base the end index on. * @param selectedIndeces - The selected indeces */ private getEndIndex; first(): void; previous(): void; next(): void; last(): void; private hasFreePageMovement; } /** * Represents a callback function that is passed to Array prototype methods such as * `.map()`, `.filter()` and `.forEach()` . */ type ArrayCallback<T, ReturnValue> = (element: T, index: number, array: T[]) => ReturnValue; type PageSelectComponent<ChoiceType> = { /** * The custom ID that this select menu uses. */ customId?: string; /** * A collection of selected values and the index they are found at. * The key is used to ensure pagination is applied correctly * The values represent the selected items of the array. */ selected: Collection<number, ChoiceType>; /** * The placeholder to display on the select menu. */ placeholder?: string | ((minChoices: number, maxChoices: number) => string); /** * The callback function to transform an array element into a readable * label string. Note that discord's character limit on labels apply. * @param option - An element from the `options` array. * @param index - The element's index in the `options` array. * @returns - A string that must be below Discord's character limit for * select menu option labels. * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure} */ labelFn: (option: ChoiceType, index: number) => string; /** * The callback function to transform an array element into a readable * description string. Note that discord's character limit on descriptions apply. * Will not create a description by default. * @param option - An element from the `options` array. * @param index - The element's index in the `options` array. * @returns - A string that must be below Discord's character limit for * select menu option descriptions. * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure} */ descriptionFn?: (option: ChoiceType, index: number) => string; /** * Contains data related to pages and methods to change them. */ pages: PageManager<ChoiceType>; /** * The button style for the nagivator buttons, which include * ⏮️,◀️,▶️, and ⏭️. * Note that navigator buttons only show up if there are more * options than the defined page length of this builder. */ navigatorStyle: Exclude<ButtonStyle, ButtonStyle.Link>; /** * The button style for the center button displaying the available * pages. * Note that navigator buttons only show up if there are more * options than the defined page length of this builder. */ pageLabelStyle: Exclude<ButtonStyle, ButtonStyle.Link>; }; type ChoiceSelectMenuBuilderLimits = { /** * The maximum amount of select menu options that * discord accepts. As of Jan 26 2025, it is 25. */ MenuLength: 25; /** * The maximum amount of characters that an option label * may have. As of Jan 26 2025, it is 100. */ OptionLabel: 100; /** * The maximum amount of characters that an option description * may have. As of Jan 26 2025, it is 100. */ OptionDescription: 100; }; /** * The three types of Tuples that are generated * by the UserChoiceComponent. It either includes * only the select menu, or it also includes * the page buttons. If there are no elements * present, it will return empty. */ type PageSelectMenuActionRow = [] | [menu: ActionRowBuilder<StringSelectMenuBuilder>] | [ pageButtons: ActionRowBuilder<ButtonBuilder>, menu: ActionRowBuilder<StringSelectMenuBuilder> ]; /** * Represents the three main types of setting values as selected. * - If the passed type is a function, that function will be called to set the values. * - If the passed type is an array, it will default to `Array#includes()`. * - Otherwise, `Object.is()` equality is used. */ type ChoiceSelectCallback<ChoiceType> = ChoiceType | ChoiceType[] | ArrayCallback<ChoiceType, boolean>; declare class ChoiceSelectMenuBuilder<ChoiceType> { /** * Manages a select menu interface to select elements in an array. * @param choices - The array of choices to represent. * @param selected - A callback function that defines what values are chosen. */ constructor(choices: ChoiceType[], selected?: ChoiceSelectCallback<ChoiceType>); /** * Configure the discord limits that this builder uses. * As they may change over the years, this provides a way to * update them for compatability. * @param config The config options to update to new values. If a property is omitted, it is * reset to the initial value. */ static configureLimits(config: Partial<ChoiceSelectMenuBuilderLimits>): void; /** * The limits that Discord enforces on certain select menu related properties. * Updated as of Jan 26, 2025. */ protected static DiscordLimits: ChoiceSelectMenuBuilderLimits; protected static EnforceDiscordLimits: boolean; /** * Contains all data related to this builder instance. */ data: PageSelectComponent<ChoiceType>; /** * The reference to the array this builder represents. */ options: ChoiceType[]; /** * Sets the custom ID of this builder. * @param {string} customId - The custom ID to set */ setCustomId(customId: string): this; /** * Set the minimum amount of choices of this builder. Defaults to * 0 for every new instance. * @param amount - The minimum amount of choices to select in this menu. */ setMinChoices(amount: number): this; /** * Set the maximum amount of choices of this select menu. * @param amount - The maximum amount of choices to select in this menu. */ setMaxChoices(amount: number): this; /** * Sets the callback function to transform an array element into a readable * label string. Discord's label character limit applies. * @param labelFn - The callback function to transform the element. * The returned string must be below Discord's label character limit. * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure} */ setLabel(labelFn: PageSelectComponent<ChoiceType>['labelFn']): this; /** * Sets the callback function to transform an array element into a readable * description string. Discord's description character limit applies. * Will not create a description by default. * @param descriptionFn - The callback function to transform the element. * The returned string must be below Discord's description character limit. * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure} */ setDescription(descriptionFn: NonNullable<PageSelectComponent<ChoiceType>['descriptionFn']> | null): this; /** * Set the button styles for the navigator buttons. * @param style - The style to apply on the navigator buttons. */ setNavigatorStyle(style: Exclude<ButtonStyle, ButtonStyle.Link>): this; /** * Set the button styles for the center button displaying the current page. * @param style - The style to apply on the center button displaying the current page. */ setPageLabelStyle(style: Exclude<ButtonStyle, ButtonStyle.Link>): this; /** * Set the placeholder of this builder's select menu. * @param placeholder - A static string to set as placeholder, or * a callback function to dynamically set the placeholder. Passes * the minimum and maximum choices of the current select menu. * * The placeholder must be below Discord's placeholder character limit. * @see {@link https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure */ setPlaceholder(placeholder: string | ((minChoices: number, maxChoices: number) => string) | null): this; /** * Set the selected values of this builder. * @param selected - A callback function or an object / array of objects to use. * - If the passed type is a function, that function will be called to set the values. * - If the passed type is an array, it will default to `Array#includes()`. * - Otherwise, `Object.is()` equality is used. */ setValues(selected: ChoiceSelectCallback<ChoiceType>): this; /** * Add the selected values of this builder. * @param selected - A callback function or an object / array of objects to use. * - If the passed type is a function, that function will be called to set the values. * - If the passed type is an array, it will default to `Array#includes()`. * - Otherwise, `Object.is()` equality is used. */ addValues(selected: ChoiceSelectCallback<ChoiceType>): this; /** * Filters the selected values based on the provided function. * @param valueFn - The callback function to use as filter. If this function * returns false, the selected value is removed from this menu. */ filterValues(valueFn: (value: ChoiceType, index: number) => boolean): this; /** * Clears all selected values from this menu. */ clearValues(): this; /** * Removes the last selected value and returns it. * If there are no selected values, it will return undefined. * * This value may be undefined even if `minChoices > 0`. */ popValue(): ChoiceType | undefined; /** * Returns a shallow copy of options that are visible on the current page. * If no page is specified, it will return the current page. * @param page - The page to fetch options from. */ optionsOnPage(page?: number): ChoiceType[]; /** * Determines the selected values on the current page. If no * parameter is provided, it will take the current page. * * Note that if `minChoices > 0`, selected values will always exist on the page. * @param page - The page to fetch the selected options from. */ selectedOnPage(onPage?: number): ChoiceType[]; /** * The selected values of this select menu. * Returns a shallow copy of the provided choices. * If you only need the first property, consider using * {@link ChoiceSelectMenuBuilder#firstValue} * * This array may be empty even if `minChoices > 0`. */ get values(): ChoiceType[]; /** * The first selected value of this select menu. * * This value may be undefined even if `minChoices > 0`. */ get firstValue(): ChoiceType | undefined; /** * Provides default function behaviour for non-functions passed to * methods. * ``` * const selected = [1, 2, 3]; * selectMenu.narrowSelectCallback(selected) // this is now (v) => selected.includes(v) * ``` * @param selected - The provided value or function to narrow down into a select function. * @returns - A function callback that can be used in `Array.prototype.filter()` and the like. */ private narrowSelectCallback; /** * Changes the paginated menu to the first page. If the maximum * amount of choices has been reached, it only skips to pages with * selections on it. */ toFirstPage(): this; /** * Changes the paginated menu to the previous page. If the maximum * amount of choices has been reached, only skips to pages with * selections on it. */ toPreviousPage(): this; /** * Changes the paginated menu to the next page. If the maximum * amount of choices has been reached, only skips to pages with * selections on it. */ toNextPage(): this; /** * Changes the paginated menu to the last page. If the maximum * amount of choices has been reached, it only skips to pages with * selections on it. */ toLastPage(): this; /** * Creates the action row based on this builder. * If the `choices` array is empty, no select menu will be generated. * If the array exceeds discord's limit for select menus, * a second row of page buttons will be passed. */ toActionRow(): PageSelectMenuActionRow; /** * Determines whether or not the interaction belongs to this builder. * If the interaction belongs to this builder, it handles the received * interaction response. * @param interaction - The component interaction response to check */ isInteraction(interaction: Interaction): boolean; /** * Determines whether or not the interaction belongs to this builder. * @param interaction - The interaction to narrow */ private hasComponent; /** * Parses an array of values (from a select menu) * into the selected values. This assumes that the StringSelectMenuInteraction * belongs to this ChoiceSelectMenuBuilder. If that assumption is not met or there * is some issue with the custom IDs, they will be filtered out. * @param values - The values to transform into selected values. */ private updateSelectedFromValues; /** * Transforms the provided option into a usable API Select Menu Option. * @param row - The row to transform, including its index and element. */ private toAPISelectMenuOption; /** * Generates the page buttons for the currently selected page. * Disables buttons dependent on what page the user is on and * how many choices are remaining. */ private get navigatorButtons(); } export { type ArrayCallback, type ChoiceSelectCallback, ChoiceSelectMenuBuilder };