diff --git a/packages/discord.js/src/structures/ActionRowBuilder.js b/packages/discord.js/src/structures/ActionRowBuilder.js index 1af68fe77..bd3a78352 100644 --- a/packages/discord.js/src/structures/ActionRowBuilder.js +++ b/packages/discord.js/src/structures/ActionRowBuilder.js @@ -1,6 +1,7 @@ 'use strict'; const { ActionRowBuilder: BuildersActionRow, ComponentBuilder } = require('@discordjs/builders'); +const Components = require('../util/Components'); const Transformers = require('../util/Transformers'); /** @@ -11,7 +12,7 @@ class ActionRowBuilder extends BuildersActionRow { constructor({ components, ...data } = {}) { super({ ...Transformers.toSnakeCase(data), - components: components?.map(c => (c instanceof ComponentBuilder ? c : Transformers.toSnakeCase(c))), + components: components?.map(c => (c instanceof ComponentBuilder ? c : Components.createComponentBuilder(c))), }); } } diff --git a/packages/discord.js/src/util/Components.js b/packages/discord.js/src/util/Components.js index 5465e1d4f..1d655fe2b 100644 --- a/packages/discord.js/src/util/Components.js +++ b/packages/discord.js/src/util/Components.js @@ -1,6 +1,7 @@ 'use strict'; // This file contains the typedefs for camel-cased JSON data +const { ComponentBuilder } = require('@discordjs/builders'); const { ComponentType } = require('discord-api-types/v10'); /** * @typedef {Object} BaseComponentData @@ -90,13 +91,40 @@ class Components extends null { throw new Error(`Found unknown component type: ${data.type}`); } } + + /** + * Transforms API data into a component builder + * @param {APIMessageComponent|ComponentBuilder} data The data to create the component from + * @returns {ComponentBuilder} + */ + static createComponentBuilder(data) { + if (data instanceof ComponentBuilder) { + return data; + } + + switch (data.type) { + case ComponentType.ActionRow: + return new ActionRowBuilder(data); + case ComponentType.Button: + return new ButtonBuilder(data); + case ComponentType.SelectMenu: + return new SelectMenuBuilder(data); + case ComponentType.TextInput: + return new TextInputComponent(data); + default: + throw new Error(`Found unknown component type: ${data.type}`); + } + } } module.exports = Components; const ActionRow = require('../structures/ActionRow'); +const ActionRowBuilder = require('../structures/ActionRowBuilder'); +const ButtonBuilder = require('../structures/ButtonBuilder'); const ButtonComponent = require('../structures/ButtonComponent'); const Component = require('../structures/Component'); +const SelectMenuBuilder = require('../structures/SelectMenuBuilder'); const SelectMenuComponent = require('../structures/SelectMenuComponent'); const TextInputComponent = require('../structures/TextInputComponent'); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 38bda77b6..052380314 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -13,7 +13,6 @@ import { inlineCode, italic, JSONEncodable, - MappedComponentTypes, quote, roleMention, SelectMenuBuilder as BuilderSelectMenuComponent, @@ -29,6 +28,7 @@ import { ModalActionRowComponentBuilder, ModalBuilder as BuildersModal, AnyComponentBuilder, + ComponentBuilder, } from '@discordjs/builders'; import { Collection } from '@discordjs/collection'; import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest'; @@ -2546,12 +2546,31 @@ export class Util extends null { ): Promise<{ id: Snowflake; position: number }[]>; } +export interface MappedComponentBuilderTypes { + [ComponentType.Button]: ButtonBuilder; + [ComponentType.SelectMenu]: SelectMenuBuilder; + [ComponentType.ActionRow]: ActionRowBuilder; + [ComponentType.TextInput]: TextInputBuilder; +} + +export interface MappedComponentTypes { + [ComponentType.Button]: ButtonComponent; + [ComponentType.SelectMenu]: SelectMenuComponent; + [ComponentType.ActionRow]: ActionRowComponent; + [ComponentType.TextInput]: TextInputComponent; +} + export class Components extends null { - public static createComponentBuilder( + public static createComponent( data: APIMessageComponent & { type: T }, ): MappedComponentTypes[T]; - public static createComponentBuilder(data: C): C; - public static createComponentBuilder(data: APIMessageComponent | Component): Component; + public static createComponent(data: C): C; + public static createComponent(data: APIMessageComponent | Component): Component; + public static createComponentBuilder( + data: APIMessageComponent & { type: T }, + ): MappedComponentBuilderTypes[T]; + public static createComponentBuilder(data: C): C; + public static createComponentBuilder(data: APIMessageComponent | ComponentBuilder): ComponentBuilder; } export class Formatters extends null {