feat: components v2 in builders (#10788)

* feat: thumbnail component

* chore: just a temp file to track remaining components

* feat: file component

* feat: section component

* feat: text display component

* chore: bump alpha version of dtypes

* chore: simplify ComponentBuilder base type

* feat: MediaGallery

* feat: Section builder

* chore: tests for sections

* chore: forgot you

* chore: docs

* fix: missing comma

* fix: my bad

* feat: container builder

* chore: requested changes

* chore: missed u

* chore: type tests

* chore: setId/clearId

* chore: apply suggestions from code review

* chore: unify pick

* chore: some requested changes

* chore: tests and small fixes

* chore: added tests that need fixing

* fix: tests

* chore: cleanup on isle protected

* docs: remove locale

* chore: types for new message builder

* chore: fix tests

* chore: attempt 1 at message builder assertions

* chore: apply suggestions

* Update packages/builders/src/messages/Assertions.ts

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* Update packages/builders/src/components/v2/Thumbnail.ts

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* fix: tests

* chore: fmt

* Apply suggestions from code review

Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>

* chore: fix pnpm lockfile revert

---------

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>
This commit is contained in:
Vlad Frangu
2025-04-23 20:29:15 +03:00
committed by GitHub
parent 42ce116226
commit abc5d99ce8
31 changed files with 2176 additions and 116 deletions

View File

@@ -1,7 +1,12 @@
import type { APIButtonComponent, APIMessageComponent, APIModalComponent } from 'discord-api-types/v10';
import type {
APIBaseComponent,
APIButtonComponent,
APIMessageComponent,
APIModalComponent,
APISectionAccessoryComponent,
} from 'discord-api-types/v10';
import { ButtonStyle, ComponentType } from 'discord-api-types/v10';
import { ActionRowBuilder } from './ActionRow.js';
import type { AnyAPIActionRowComponent } from './Component.js';
import { ComponentBuilder } from './Component.js';
import type { BaseButtonBuilder } from './button/Button.js';
import {
@@ -18,11 +23,33 @@ import { RoleSelectMenuBuilder } from './selectMenu/RoleSelectMenu.js';
import { StringSelectMenuBuilder } from './selectMenu/StringSelectMenu.js';
import { UserSelectMenuBuilder } from './selectMenu/UserSelectMenu.js';
import { TextInputBuilder } from './textInput/TextInput.js';
import { ContainerBuilder } from './v2/Container.js';
import { FileBuilder } from './v2/File.js';
import { MediaGalleryBuilder } from './v2/MediaGallery.js';
import { SectionBuilder } from './v2/Section.js';
import { SeparatorBuilder } from './v2/Separator.js';
import { TextDisplayBuilder } from './v2/TextDisplay.js';
import { ThumbnailBuilder } from './v2/Thumbnail.js';
/**
* The builders that may be used as top-level components on messages
*/
export type MessageTopLevelComponentBuilder =
| ActionRowBuilder
| ContainerBuilder
| FileBuilder
| MediaGalleryBuilder
| SectionBuilder
| SeparatorBuilder
| TextDisplayBuilder;
/**
* The builders that may be used for messages.
*/
export type MessageComponentBuilder = ActionRowBuilder | MessageActionRowComponentBuilder;
export type MessageComponentBuilder =
| MessageActionRowComponentBuilder
| MessageTopLevelComponentBuilder
| ThumbnailBuilder;
/**
* The builders that may be used for modals.
@@ -97,6 +124,34 @@ export interface MappedComponentTypes {
* The channel select component type is associated with a {@link ChannelSelectMenuBuilder}.
*/
[ComponentType.ChannelSelect]: ChannelSelectMenuBuilder;
/**
* The thumbnail component type is associated with a {@link ThumbnailBuilder}.
*/
[ComponentType.Thumbnail]: ThumbnailBuilder;
/**
* The file component type is associated with a {@link FileBuilder}.
*/
[ComponentType.File]: FileBuilder;
/**
* The separator component type is associated with a {@link SeparatorBuilder}.
*/
[ComponentType.Separator]: SeparatorBuilder;
/**
* The text display component type is associated with a {@link TextDisplayBuilder}.
*/
[ComponentType.TextDisplay]: TextDisplayBuilder;
/**
* The media gallery component type is associated with a {@link MediaGalleryBuilder}.
*/
[ComponentType.MediaGallery]: MediaGalleryBuilder;
/**
* The section component type is associated with a {@link SectionBuilder}.
*/
[ComponentType.Section]: SectionBuilder;
/**
* The container component type is associated with a {@link ContainerBuilder}.
*/
[ComponentType.Container]: ContainerBuilder;
}
/**
@@ -122,7 +177,7 @@ export function createComponentBuilder<ComponentBuilder extends MessageComponent
export function createComponentBuilder(
data: APIMessageComponent | APIModalComponent | MessageComponentBuilder,
): ComponentBuilder<AnyAPIActionRowComponent> {
): ComponentBuilder<APIBaseComponent<ComponentType>> {
if (data instanceof ComponentBuilder) {
return data;
}
@@ -144,36 +199,20 @@ export function createComponentBuilder(
return new MentionableSelectMenuBuilder(data);
case ComponentType.ChannelSelect:
return new ChannelSelectMenuBuilder(data);
// Will be handled later
case ComponentType.Section: {
throw new Error('Not implemented yet: ComponentType.Section case');
}
case ComponentType.TextDisplay: {
throw new Error('Not implemented yet: ComponentType.TextDisplay case');
}
case ComponentType.Thumbnail: {
throw new Error('Not implemented yet: ComponentType.Thumbnail case');
}
case ComponentType.MediaGallery: {
throw new Error('Not implemented yet: ComponentType.MediaGallery case');
}
case ComponentType.File: {
throw new Error('Not implemented yet: ComponentType.File case');
}
case ComponentType.Separator: {
throw new Error('Not implemented yet: ComponentType.Separator case');
}
case ComponentType.Container: {
throw new Error('Not implemented yet: ComponentType.Container case');
}
case ComponentType.Thumbnail:
return new ThumbnailBuilder(data);
case ComponentType.File:
return new FileBuilder(data);
case ComponentType.Separator:
return new SeparatorBuilder(data);
case ComponentType.TextDisplay:
return new TextDisplayBuilder(data);
case ComponentType.MediaGallery:
return new MediaGalleryBuilder(data);
case ComponentType.Section:
return new SectionBuilder(data);
case ComponentType.Container:
return new ContainerBuilder(data);
default:
// @ts-expect-error This case can still occur if we get a newer unsupported component type
throw new Error(`Cannot properly serialize component type: ${data.type}`);
@@ -199,3 +238,15 @@ function createButtonBuilder(data: APIButtonComponent): ButtonBuilder {
throw new Error(`Cannot properly serialize button with style: ${data.style}`);
}
}
export function resolveAccessoryComponent(component: APISectionAccessoryComponent) {
switch (component.type) {
case ComponentType.Button:
return createButtonBuilder(component);
case ComponentType.Thumbnail:
return new ThumbnailBuilder(component);
default:
// @ts-expect-error This case can still occur if we get a newer unsupported component type
throw new Error(`Cannot properly serialize section accessory component: ${component.type}`);
}
}