import type { ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, RoleSelectMenuBuilder, UserSelectMenuBuilder, StringSelectMenuBuilder, } from "discord.js"; import { ActionRowBuilder, BaseSelectMenuBuilder, ButtonBuilder, } from "discord.js"; export class V2ActionRowBuilder< T extends | ButtonBuilder | ChannelSelectMenuBuilder | MentionableSelectMenuBuilder | RoleSelectMenuBuilder | UserSelectMenuBuilder | StringSelectMenuBuilder, > extends ActionRowBuilder { /** * Set the components in this action row * @param components - The components to include (1-5 buttons OR 1 select menu) * @returns The action row instance */ setComponents(components: T[]) { this.validateComponents(components); super.setComponents(components); return this; } private validateComponents(components: T[]) { if (components.length === 0) { throw new Error("Action row must contain at least 1 component"); } // Check if first component is any type of select menu const isSelectMenu = components[0] instanceof BaseSelectMenuBuilder; if (isSelectMenu) { // Select menu must be alone in the row if (components.length > 1) { throw new Error( "Action row can only contain 1 select menu and no other components", ); } return; // Valid single select menu } // If not a select menu, must be 1-5 buttons if (components.length > 5) { throw new Error("Action row can only contain up to 5 buttons"); } // Verify all components are buttons const hasNonButton = components.some((c) => !(c instanceof ButtonBuilder)); if (hasNonButton) { throw new Error( "Action row must contain only buttons when not using a select menu", ); } } } /** * Helper function to create an action row component * @param components - The components to include in the row (1-5 buttons OR 1 select menu) * @returns The action row instance * * @example * ```typescript * // Create an action row with buttons * const buttonRow = makeActionRow([ * makeButton({ label: 'Click me' }), * makeButton({ label: 'Or me' }) * ]); * * // Create an action row with a select menu * const menuRow = makeActionRow([ * new SelectMenuBuilder().setOptions([ * { label: 'Option 1', value: '1' }, * { label: 'Option 2', value: '2' } * ]) * ]); * ``` */ export function makeActionRow< T extends | ButtonBuilder | ChannelSelectMenuBuilder | MentionableSelectMenuBuilder | RoleSelectMenuBuilder | UserSelectMenuBuilder | StringSelectMenuBuilder, >(components: T[]): V2ActionRowBuilder { const row = new V2ActionRowBuilder(); row.setComponents(components); return row; }