@lunibee/builders 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -21
- package/package.json +1 -1
- package/src/attachment.ts +10 -1
- package/src/commands.ts +189 -82
- package/src/components.ts +237 -81
- package/src/embed.ts +35 -14
- package/src/index.ts +103 -34
package/src/components.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Re-export the canonical
|
|
1
|
+
// Re-export the canonical ButtonType from @lunibee/types so the builders package
|
|
2
2
|
// never ships a drifting duplicate (the old local copy was missing `Premium: 6`).
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
3
|
+
import { ButtonType } from "@lunibee/types";
|
|
4
|
+
export { ButtonType };
|
|
5
5
|
|
|
6
6
|
/** Component type constants exposed by Lunibee. */
|
|
7
|
-
export const
|
|
7
|
+
export const ComponentEnum = {
|
|
8
8
|
ActionRow: 1,
|
|
9
9
|
Button: 2,
|
|
10
10
|
StringSelect: 3,
|
|
@@ -22,14 +22,18 @@ export const ComponentType = {
|
|
|
22
22
|
ContentInventoryEntry: 16,
|
|
23
23
|
Container: 17,
|
|
24
24
|
} as const;
|
|
25
|
-
export const
|
|
25
|
+
export const TextInputType = { Short: 1, Paragraph: 2 } as const;
|
|
26
|
+
/** One {@link TextInputType} value, usable as a type. */
|
|
27
|
+
export type TextInputType = (typeof TextInputType)[keyof typeof TextInputType];
|
|
28
|
+
/** One {@link ComponentEnum} value, usable as a type. */
|
|
29
|
+
export type ComponentEnum = (typeof ComponentEnum)[keyof typeof ComponentEnum];
|
|
26
30
|
export interface APIComponentEmoji {
|
|
27
31
|
id?: string | null;
|
|
28
32
|
name?: string | null;
|
|
29
33
|
animated?: boolean;
|
|
30
34
|
}
|
|
31
35
|
export interface APIButtonComponent {
|
|
32
|
-
type: typeof
|
|
36
|
+
type: typeof ComponentEnum.Button;
|
|
33
37
|
style: 1 | 2 | 3 | 4 | 5 | 6;
|
|
34
38
|
custom_id?: string;
|
|
35
39
|
label?: string;
|
|
@@ -47,7 +51,7 @@ export interface APISelectOption {
|
|
|
47
51
|
default?: boolean;
|
|
48
52
|
}
|
|
49
53
|
export interface APIStringSelectComponent {
|
|
50
|
-
type: typeof
|
|
54
|
+
type: typeof ComponentEnum.StringSelect;
|
|
51
55
|
custom_id?: string;
|
|
52
56
|
placeholder?: string;
|
|
53
57
|
min_values?: number;
|
|
@@ -58,10 +62,10 @@ export interface APIStringSelectComponent {
|
|
|
58
62
|
}
|
|
59
63
|
export interface APIEntitySelectComponent {
|
|
60
64
|
type:
|
|
61
|
-
| typeof
|
|
62
|
-
| typeof
|
|
63
|
-
| typeof
|
|
64
|
-
| typeof
|
|
65
|
+
| typeof ComponentEnum.UserSelect
|
|
66
|
+
| typeof ComponentEnum.RoleSelect
|
|
67
|
+
| typeof ComponentEnum.MentionableSelect
|
|
68
|
+
| typeof ComponentEnum.ChannelSelect;
|
|
65
69
|
custom_id?: string;
|
|
66
70
|
placeholder?: string;
|
|
67
71
|
min_values?: number;
|
|
@@ -71,8 +75,8 @@ export interface APIEntitySelectComponent {
|
|
|
71
75
|
default_values?: APISelectDefaultValue[];
|
|
72
76
|
}
|
|
73
77
|
export interface APITextInputComponent {
|
|
74
|
-
type: typeof
|
|
75
|
-
style: typeof
|
|
78
|
+
type: typeof ComponentEnum.TextInput;
|
|
79
|
+
style: typeof TextInputType.Short | typeof TextInputType.Paragraph;
|
|
76
80
|
custom_id?: string;
|
|
77
81
|
label?: string;
|
|
78
82
|
placeholder?: string;
|
|
@@ -83,8 +87,8 @@ export interface APITextInputComponent {
|
|
|
83
87
|
}
|
|
84
88
|
export interface APIModalComponent {
|
|
85
89
|
type: 9;
|
|
86
|
-
custom_id
|
|
87
|
-
title
|
|
90
|
+
custom_id: string;
|
|
91
|
+
title: string;
|
|
88
92
|
components: APIActionRowComponent[];
|
|
89
93
|
}
|
|
90
94
|
export type APIActionRowChild =
|
|
@@ -93,20 +97,20 @@ export type APIActionRowChild =
|
|
|
93
97
|
| APIEntitySelectComponent
|
|
94
98
|
| APITextInputComponent;
|
|
95
99
|
export interface APIActionRowComponent {
|
|
96
|
-
type: typeof
|
|
100
|
+
type: typeof ComponentEnum.ActionRow;
|
|
97
101
|
components: APIActionRowChild[];
|
|
98
102
|
}
|
|
99
103
|
export interface APISectionComponent {
|
|
100
|
-
type: typeof
|
|
104
|
+
type: typeof ComponentEnum.Section;
|
|
101
105
|
components?: APIComponent[]; // text displays
|
|
102
106
|
accessory?: APIComponent; // buttons, thumbnails, etc.
|
|
103
107
|
}
|
|
104
108
|
export interface APITextDisplayComponent {
|
|
105
|
-
type: typeof
|
|
109
|
+
type: typeof ComponentEnum.TextDisplay;
|
|
106
110
|
content: string;
|
|
107
111
|
}
|
|
108
112
|
export interface APIMediaGalleryComponent {
|
|
109
|
-
type: typeof
|
|
113
|
+
type: typeof ComponentEnum.MediaGallery;
|
|
110
114
|
items: { media: { url: string; description?: string } }[];
|
|
111
115
|
}
|
|
112
116
|
/** Default values accepted by an auto-populated entity select. */
|
|
@@ -115,17 +119,17 @@ export interface APISelectDefaultValue {
|
|
|
115
119
|
type: "user" | "role" | "channel";
|
|
116
120
|
}
|
|
117
121
|
export interface APIFileComponent {
|
|
118
|
-
type: typeof
|
|
122
|
+
type: typeof ComponentEnum.File;
|
|
119
123
|
file: { url: string };
|
|
120
124
|
spoiler?: boolean;
|
|
121
125
|
}
|
|
122
126
|
export interface APISeparatorComponent {
|
|
123
|
-
type: typeof
|
|
127
|
+
type: typeof ComponentEnum.Separator;
|
|
124
128
|
spacing?: 1 | 2;
|
|
125
129
|
divider?: boolean;
|
|
126
130
|
}
|
|
127
131
|
export interface APIThumbnailComponent {
|
|
128
|
-
type: typeof
|
|
132
|
+
type: typeof ComponentEnum.Thumbnail;
|
|
129
133
|
url: string;
|
|
130
134
|
proxy_url?: string;
|
|
131
135
|
width?: number;
|
|
@@ -134,11 +138,11 @@ export interface APIThumbnailComponent {
|
|
|
134
138
|
spoiler?: boolean;
|
|
135
139
|
}
|
|
136
140
|
export interface APIContentInventoryEntryComponent {
|
|
137
|
-
type: typeof
|
|
141
|
+
type: typeof ComponentEnum.ContentInventoryEntry;
|
|
138
142
|
id: string;
|
|
139
143
|
}
|
|
140
144
|
export interface APIContainerComponent {
|
|
141
|
-
type: typeof
|
|
145
|
+
type: typeof ComponentEnum.Container;
|
|
142
146
|
components: APIComponent[];
|
|
143
147
|
accent_color?: number;
|
|
144
148
|
spoiler?: boolean;
|
|
@@ -158,7 +162,7 @@ export type APIComponent =
|
|
|
158
162
|
| APIContentInventoryEntryComponent
|
|
159
163
|
| APIContainerComponent;
|
|
160
164
|
|
|
161
|
-
export class
|
|
165
|
+
export class CreateActionRow<
|
|
162
166
|
T extends { toJSON(): APIActionRowChild } = { toJSON(): APIActionRowChild },
|
|
163
167
|
> {
|
|
164
168
|
readonly #components: T[] = [];
|
|
@@ -184,18 +188,18 @@ export class ActionRowBuilder<
|
|
|
184
188
|
throw new RangeError("An action row needs at least one component.");
|
|
185
189
|
const types = components.map((component) => component.type);
|
|
186
190
|
if (
|
|
187
|
-
types.some((type) => type !==
|
|
191
|
+
types.some((type) => type !== ComponentEnum.Button) &&
|
|
188
192
|
components.length > 1
|
|
189
193
|
)
|
|
190
194
|
throw new RangeError(
|
|
191
195
|
"A select menu or text input must be alone in its action row.",
|
|
192
196
|
);
|
|
193
|
-
return { type:
|
|
197
|
+
return { type: ComponentEnum.ActionRow, components };
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
|
-
export class
|
|
200
|
+
export class CreateStringSelect {
|
|
197
201
|
readonly #data: APIStringSelectComponent = {
|
|
198
|
-
type:
|
|
202
|
+
type: ComponentEnum.StringSelect,
|
|
199
203
|
};
|
|
200
204
|
public setCustomId(value: string): this {
|
|
201
205
|
validateText(value, 100, "Component custom ID");
|
|
@@ -261,19 +265,19 @@ export class StringSelectBuilder {
|
|
|
261
265
|
return structuredClone(this.#data);
|
|
262
266
|
}
|
|
263
267
|
}
|
|
264
|
-
export class
|
|
268
|
+
export class CreateButton {
|
|
265
269
|
readonly #data: APIButtonComponent = {
|
|
266
|
-
type:
|
|
267
|
-
style:
|
|
270
|
+
type: ComponentEnum.Button,
|
|
271
|
+
style: ButtonType.Secondary,
|
|
268
272
|
};
|
|
269
273
|
/** Sets the style and drops fields that style cannot carry. */
|
|
270
274
|
public setStyle(style: APIButtonComponent["style"]): this {
|
|
271
275
|
const data = this.#data;
|
|
272
276
|
data.style = style;
|
|
273
|
-
if (style ===
|
|
277
|
+
if (style === ButtonType.Link) {
|
|
274
278
|
delete data.custom_id;
|
|
275
279
|
delete data.sku_id;
|
|
276
|
-
} else if (style ===
|
|
280
|
+
} else if (style === ButtonType.Premium) {
|
|
277
281
|
delete data.custom_id;
|
|
278
282
|
delete data.url;
|
|
279
283
|
delete data.label;
|
|
@@ -286,7 +290,7 @@ export class ButtonBuilder {
|
|
|
286
290
|
}
|
|
287
291
|
public setCustomId(value: string): this {
|
|
288
292
|
validateText(value, 100, "Button custom ID");
|
|
289
|
-
if (this.#data.style ===
|
|
293
|
+
if (this.#data.style === ButtonType.Link)
|
|
290
294
|
throw new TypeError("Link buttons cannot use custom IDs.");
|
|
291
295
|
this.#data.custom_id = value;
|
|
292
296
|
return this;
|
|
@@ -306,14 +310,14 @@ export class ButtonBuilder {
|
|
|
306
310
|
cause: error,
|
|
307
311
|
});
|
|
308
312
|
}
|
|
309
|
-
this.setStyle(
|
|
313
|
+
this.setStyle(ButtonType.Link);
|
|
310
314
|
this.#data.url = url.toString();
|
|
311
315
|
return this;
|
|
312
316
|
}
|
|
313
317
|
/** Makes this a premium (purchase) button for a SKU. Premium buttons carry no label, emoji, custom ID or URL. */
|
|
314
318
|
public setSKUId(skuId: string): this {
|
|
315
319
|
validateText(skuId, 20, "Button SKU ID");
|
|
316
|
-
this.setStyle(
|
|
320
|
+
this.setStyle(ButtonType.Premium);
|
|
317
321
|
this.#data.sku_id = skuId;
|
|
318
322
|
return this;
|
|
319
323
|
}
|
|
@@ -328,13 +332,13 @@ export class ButtonBuilder {
|
|
|
328
332
|
}
|
|
329
333
|
public toJSON(): APIButtonComponent {
|
|
330
334
|
const data = this.#data;
|
|
331
|
-
if (data.style ===
|
|
335
|
+
if (data.style === ButtonType.Link) {
|
|
332
336
|
if (!data.url) throw new TypeError("Link buttons require a URL.");
|
|
333
337
|
if (data.custom_id || data.sku_id)
|
|
334
338
|
throw new TypeError(
|
|
335
339
|
"Link buttons cannot have a custom ID or SKU ID.",
|
|
336
340
|
);
|
|
337
|
-
} else if (data.style ===
|
|
341
|
+
} else if (data.style === ButtonType.Premium) {
|
|
338
342
|
if (!data.sku_id)
|
|
339
343
|
throw new TypeError("Premium buttons require a SKU ID.");
|
|
340
344
|
if (data.custom_id || data.url || data.label || data.emoji)
|
|
@@ -349,25 +353,25 @@ export class ButtonBuilder {
|
|
|
349
353
|
"Only link buttons have a URL and only premium buttons have a SKU ID.",
|
|
350
354
|
);
|
|
351
355
|
}
|
|
352
|
-
if (data.style !==
|
|
356
|
+
if (data.style !== ButtonType.Premium && !data.label && !data.emoji)
|
|
353
357
|
throw new TypeError("Buttons require a label or an emoji.");
|
|
354
358
|
return structuredClone(data);
|
|
355
359
|
}
|
|
356
360
|
}
|
|
357
|
-
export class
|
|
361
|
+
export class CreateEntitySelect {
|
|
358
362
|
readonly #data: APIEntitySelectComponent;
|
|
359
363
|
public constructor(
|
|
360
364
|
type:
|
|
361
|
-
| typeof
|
|
362
|
-
| typeof
|
|
363
|
-
| typeof
|
|
364
|
-
| typeof
|
|
365
|
+
| typeof ComponentEnum.UserSelect
|
|
366
|
+
| typeof ComponentEnum.RoleSelect
|
|
367
|
+
| typeof ComponentEnum.MentionableSelect
|
|
368
|
+
| typeof ComponentEnum.ChannelSelect,
|
|
365
369
|
) {
|
|
366
370
|
if (
|
|
367
|
-
type !==
|
|
368
|
-
type !==
|
|
369
|
-
type !==
|
|
370
|
-
type !==
|
|
371
|
+
type !== ComponentEnum.UserSelect &&
|
|
372
|
+
type !== ComponentEnum.RoleSelect &&
|
|
373
|
+
type !== ComponentEnum.MentionableSelect &&
|
|
374
|
+
type !== ComponentEnum.ChannelSelect
|
|
371
375
|
)
|
|
372
376
|
throw new TypeError("Invalid select component type.");
|
|
373
377
|
this.#data = { type };
|
|
@@ -409,7 +413,7 @@ export class EntitySelectBuilder {
|
|
|
409
413
|
return structuredClone(this.#data);
|
|
410
414
|
}
|
|
411
415
|
}
|
|
412
|
-
export class
|
|
416
|
+
export class CreateModal {
|
|
413
417
|
readonly #components: Array<{ toJSON(): APIActionRowComponent }> = [];
|
|
414
418
|
#custom_id?: string;
|
|
415
419
|
#title?: string;
|
|
@@ -435,6 +439,14 @@ export class ModalBuilder {
|
|
|
435
439
|
this.#components.push(...components);
|
|
436
440
|
return this;
|
|
437
441
|
}
|
|
442
|
+
/** Adds text inputs, each in its own action row (Discord's modal layout). @param inputs Text inputs, at most 5 per modal. */
|
|
443
|
+
public addTextInputs(...inputs: CreateTextInput[]): this {
|
|
444
|
+
return this.addComponents(
|
|
445
|
+
...inputs.map((input) =>
|
|
446
|
+
new CreateActionRow<CreateTextInput>().addComponents(input),
|
|
447
|
+
),
|
|
448
|
+
);
|
|
449
|
+
}
|
|
438
450
|
public toJSON(): APIModalComponent {
|
|
439
451
|
if (!this.#custom_id || !this.#title)
|
|
440
452
|
throw new TypeError("Modals require a custom ID and a title.");
|
|
@@ -442,16 +454,16 @@ export class ModalBuilder {
|
|
|
442
454
|
throw new RangeError("Modals require at least one component.");
|
|
443
455
|
return {
|
|
444
456
|
type: 9,
|
|
445
|
-
|
|
446
|
-
|
|
457
|
+
custom_id: this.#custom_id,
|
|
458
|
+
title: this.#title,
|
|
447
459
|
components: this.#components.map((component) => component.toJSON()),
|
|
448
460
|
};
|
|
449
461
|
}
|
|
450
462
|
}
|
|
451
|
-
export class
|
|
463
|
+
export class CreateTextInput {
|
|
452
464
|
readonly #data: APITextInputComponent = {
|
|
453
|
-
type:
|
|
454
|
-
style:
|
|
465
|
+
type: ComponentEnum.TextInput,
|
|
466
|
+
style: TextInputType.Short,
|
|
455
467
|
};
|
|
456
468
|
public setStyle(style: APITextInputComponent["style"]): this {
|
|
457
469
|
this.#data.style = style;
|
|
@@ -505,7 +517,7 @@ export class TextInputBuilder {
|
|
|
505
517
|
}
|
|
506
518
|
}
|
|
507
519
|
|
|
508
|
-
export class
|
|
520
|
+
export class CreateContainer {
|
|
509
521
|
readonly #components: { toJSON(): APIComponent }[] = [];
|
|
510
522
|
#accentColor?: number;
|
|
511
523
|
#spoiler?: boolean;
|
|
@@ -531,7 +543,7 @@ export class ContainerBuilder {
|
|
|
531
543
|
}
|
|
532
544
|
public toJSON(): APIContainerComponent {
|
|
533
545
|
const data: APIContainerComponent = {
|
|
534
|
-
type:
|
|
546
|
+
type: ComponentEnum.Container,
|
|
535
547
|
components: this.#components.map((c) => c.toJSON()),
|
|
536
548
|
};
|
|
537
549
|
if (this.#accentColor !== undefined)
|
|
@@ -541,7 +553,7 @@ export class ContainerBuilder {
|
|
|
541
553
|
}
|
|
542
554
|
}
|
|
543
555
|
|
|
544
|
-
export class
|
|
556
|
+
export class CreateSection {
|
|
545
557
|
readonly #components: { toJSON(): APIComponent }[] = [];
|
|
546
558
|
#accessory?: { toJSON(): APIComponent };
|
|
547
559
|
public addComponents(...components: { toJSON(): APIComponent }[]): this {
|
|
@@ -556,7 +568,7 @@ export class SectionBuilder {
|
|
|
556
568
|
}
|
|
557
569
|
public toJSON(): APISectionComponent {
|
|
558
570
|
return {
|
|
559
|
-
type:
|
|
571
|
+
type: ComponentEnum.Section,
|
|
560
572
|
components: this.#components.length
|
|
561
573
|
? this.#components.map((c) => c.toJSON())
|
|
562
574
|
: undefined,
|
|
@@ -565,7 +577,7 @@ export class SectionBuilder {
|
|
|
565
577
|
}
|
|
566
578
|
}
|
|
567
579
|
|
|
568
|
-
export class
|
|
580
|
+
export class CreateTextDisplay {
|
|
569
581
|
#content = "";
|
|
570
582
|
public setContent(content: string): this {
|
|
571
583
|
validateText(content, 4000, "Text display content");
|
|
@@ -574,13 +586,13 @@ export class TextDisplayBuilder {
|
|
|
574
586
|
}
|
|
575
587
|
public toJSON(): APITextDisplayComponent {
|
|
576
588
|
return {
|
|
577
|
-
type:
|
|
589
|
+
type: ComponentEnum.TextDisplay,
|
|
578
590
|
content: this.#content,
|
|
579
591
|
};
|
|
580
592
|
}
|
|
581
593
|
}
|
|
582
594
|
|
|
583
|
-
export class
|
|
595
|
+
export class CreateMediaGallery {
|
|
584
596
|
readonly #items: { media: { url: string; description?: string } }[] = [];
|
|
585
597
|
public addItems(...items: { url: string; description?: string }[]): this {
|
|
586
598
|
if (!items.length) {
|
|
@@ -596,13 +608,13 @@ export class MediaGalleryBuilder {
|
|
|
596
608
|
}
|
|
597
609
|
public toJSON(): APIMediaGalleryComponent {
|
|
598
610
|
return {
|
|
599
|
-
type:
|
|
611
|
+
type: ComponentEnum.MediaGallery,
|
|
600
612
|
items: structuredClone(this.#items),
|
|
601
613
|
};
|
|
602
614
|
}
|
|
603
615
|
}
|
|
604
616
|
|
|
605
|
-
export class
|
|
617
|
+
export class CreateFileComponent {
|
|
606
618
|
#url = "";
|
|
607
619
|
#spoiler?: boolean;
|
|
608
620
|
public setUrl(url: string): this {
|
|
@@ -617,7 +629,7 @@ export class FileComponentBuilder {
|
|
|
617
629
|
public toJSON(): APIFileComponent {
|
|
618
630
|
if (!this.#url) throw new Error("File component must have a URL.");
|
|
619
631
|
const data: APIFileComponent = {
|
|
620
|
-
type:
|
|
632
|
+
type: ComponentEnum.File,
|
|
621
633
|
file: { url: this.#url },
|
|
622
634
|
};
|
|
623
635
|
if (this.#spoiler !== undefined) data.spoiler = this.#spoiler;
|
|
@@ -625,7 +637,7 @@ export class FileComponentBuilder {
|
|
|
625
637
|
}
|
|
626
638
|
}
|
|
627
639
|
|
|
628
|
-
export class
|
|
640
|
+
export class CreateSeparator {
|
|
629
641
|
#spacing?: 1 | 2;
|
|
630
642
|
#divider?: boolean;
|
|
631
643
|
public setSpacing(spacing: 1 | 2): this {
|
|
@@ -638,7 +650,7 @@ export class SeparatorBuilder {
|
|
|
638
650
|
}
|
|
639
651
|
public toJSON(): APISeparatorComponent {
|
|
640
652
|
const data: APISeparatorComponent = {
|
|
641
|
-
type:
|
|
653
|
+
type: ComponentEnum.Separator,
|
|
642
654
|
};
|
|
643
655
|
if (this.#spacing !== undefined) data.spacing = this.#spacing;
|
|
644
656
|
if (this.#divider !== undefined) data.divider = this.#divider;
|
|
@@ -646,7 +658,7 @@ export class SeparatorBuilder {
|
|
|
646
658
|
}
|
|
647
659
|
}
|
|
648
660
|
|
|
649
|
-
export class
|
|
661
|
+
export class CreateThumbnail {
|
|
650
662
|
#url = "";
|
|
651
663
|
#description?: string;
|
|
652
664
|
#spoiler?: boolean;
|
|
@@ -668,7 +680,7 @@ export class ThumbnailBuilder {
|
|
|
668
680
|
}
|
|
669
681
|
public toJSON(): APIThumbnailComponent {
|
|
670
682
|
const data: APIThumbnailComponent = {
|
|
671
|
-
type:
|
|
683
|
+
type: ComponentEnum.Thumbnail,
|
|
672
684
|
url: this.#url,
|
|
673
685
|
};
|
|
674
686
|
if (this.#description !== undefined)
|
|
@@ -678,7 +690,7 @@ export class ThumbnailBuilder {
|
|
|
678
690
|
}
|
|
679
691
|
}
|
|
680
692
|
|
|
681
|
-
export class
|
|
693
|
+
export class CreateContentInventoryEntry {
|
|
682
694
|
#id = "";
|
|
683
695
|
public setId(id: string): this {
|
|
684
696
|
validateText(id, 100, "Content inventory entry ID");
|
|
@@ -687,7 +699,7 @@ export class ContentInventoryEntryBuilder {
|
|
|
687
699
|
}
|
|
688
700
|
public toJSON(): APIContentInventoryEntryComponent {
|
|
689
701
|
return {
|
|
690
|
-
type:
|
|
702
|
+
type: ComponentEnum.ContentInventoryEntry,
|
|
691
703
|
id: this.#id,
|
|
692
704
|
};
|
|
693
705
|
}
|
|
@@ -719,30 +731,30 @@ function validateLength(value: number, field: string, max = 4000): void {
|
|
|
719
731
|
);
|
|
720
732
|
}
|
|
721
733
|
|
|
722
|
-
/** Discord.js-familiar alias for {@link
|
|
723
|
-
export {
|
|
734
|
+
/** Discord.js-familiar alias for {@link CreateStringSelect}. */
|
|
735
|
+
export { CreateStringSelect as CreateStringSelectMenu };
|
|
724
736
|
/** User select menu builder (Discord.js-familiar). */
|
|
725
|
-
export class
|
|
737
|
+
export class CreateUserSelectMenu extends CreateEntitySelect {
|
|
726
738
|
public constructor() {
|
|
727
|
-
super(
|
|
739
|
+
super(ComponentEnum.UserSelect);
|
|
728
740
|
}
|
|
729
741
|
}
|
|
730
742
|
/** Role select menu builder (Discord.js-familiar). */
|
|
731
|
-
export class
|
|
743
|
+
export class CreateRoleSelectMenu extends CreateEntitySelect {
|
|
732
744
|
public constructor() {
|
|
733
|
-
super(
|
|
745
|
+
super(ComponentEnum.RoleSelect);
|
|
734
746
|
}
|
|
735
747
|
}
|
|
736
748
|
/** Mentionable select menu builder (Discord.js-familiar). */
|
|
737
|
-
export class
|
|
749
|
+
export class CreateMentionableSelectMenu extends CreateEntitySelect {
|
|
738
750
|
public constructor() {
|
|
739
|
-
super(
|
|
751
|
+
super(ComponentEnum.MentionableSelect);
|
|
740
752
|
}
|
|
741
753
|
}
|
|
742
754
|
/** Channel select menu builder (Discord.js-familiar). */
|
|
743
|
-
export class
|
|
755
|
+
export class CreateChannelSelectMenu extends CreateEntitySelect {
|
|
744
756
|
public constructor() {
|
|
745
|
-
super(
|
|
757
|
+
super(ComponentEnum.ChannelSelect);
|
|
746
758
|
}
|
|
747
759
|
}
|
|
748
760
|
|
|
@@ -757,3 +769,147 @@ function assertSelect(data: {
|
|
|
757
769
|
if ((data.min_values ?? 1) > (data.max_values ?? 1))
|
|
758
770
|
throw new RangeError("min_values cannot exceed max_values.");
|
|
759
771
|
}
|
|
772
|
+
|
|
773
|
+
/** Discord's flag for a message laid out with Components V2 (containers, text displays...). */
|
|
774
|
+
const IS_COMPONENTS_V2 = 1 << 15;
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* A message payload laid out with Components V2: the components, and the flag
|
|
778
|
+
* Discord requires for them. A V2 message cannot also carry `content` or `embeds`.
|
|
779
|
+
* @param components Top-level components (containers, sections, text displays, action rows...).
|
|
780
|
+
* @param options Extra message fields, such as `allowed_mentions` or `ephemeral`; `flags` are combined.
|
|
781
|
+
* @example channel.send(componentsV2Message(new CreateContainer().addComponents(new CreateTextDisplay().setContent("Hi"))))
|
|
782
|
+
*/
|
|
783
|
+
export function componentsV2Message<
|
|
784
|
+
T extends Record<string, unknown> = Record<string, never>,
|
|
785
|
+
>(
|
|
786
|
+
components: { toJSON(): APIComponent } | Array<{ toJSON(): APIComponent }>,
|
|
787
|
+
options?: T & { flags?: number },
|
|
788
|
+
): { components: APIComponent[]; flags: number } & T {
|
|
789
|
+
const list = Array.isArray(components) ? components : [components];
|
|
790
|
+
if (!list.length)
|
|
791
|
+
throw new TypeError(
|
|
792
|
+
"A Components V2 message needs at least one component.",
|
|
793
|
+
);
|
|
794
|
+
return {
|
|
795
|
+
...(options ?? ({} as T)),
|
|
796
|
+
components: list.map((component) => component.toJSON()),
|
|
797
|
+
flags: (options?.flags ?? 0) | IS_COMPONENTS_V2,
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// ─── Deprecated names (0.2.2), removed in 2.0 ────────────────────────────────
|
|
802
|
+
// Builders are now `CreateX` (`ButtonBuilder` → `CreateButton`); `…Style` became
|
|
803
|
+
// `…Type` and `…Type` became `…Enum`.
|
|
804
|
+
|
|
805
|
+
/** @deprecated Use {@link CreateButton}. Removed in 2.0. */
|
|
806
|
+
export const ButtonBuilder = CreateButton;
|
|
807
|
+
/** @deprecated Use {@link CreateButton}. Removed in 2.0. */
|
|
808
|
+
export type ButtonBuilder = CreateButton;
|
|
809
|
+
|
|
810
|
+
/** @deprecated Use {@link CreateChannelSelectMenu}. Removed in 2.0. */
|
|
811
|
+
export const ChannelSelectMenuBuilder = CreateChannelSelectMenu;
|
|
812
|
+
/** @deprecated Use {@link CreateChannelSelectMenu}. Removed in 2.0. */
|
|
813
|
+
export type ChannelSelectMenuBuilder = CreateChannelSelectMenu;
|
|
814
|
+
|
|
815
|
+
/** @deprecated Use {@link CreateContainer}. Removed in 2.0. */
|
|
816
|
+
export const ContainerBuilder = CreateContainer;
|
|
817
|
+
/** @deprecated Use {@link CreateContainer}. Removed in 2.0. */
|
|
818
|
+
export type ContainerBuilder = CreateContainer;
|
|
819
|
+
|
|
820
|
+
/** @deprecated Use {@link CreateContentInventoryEntry}. Removed in 2.0. */
|
|
821
|
+
export const ContentInventoryEntryBuilder = CreateContentInventoryEntry;
|
|
822
|
+
/** @deprecated Use {@link CreateContentInventoryEntry}. Removed in 2.0. */
|
|
823
|
+
export type ContentInventoryEntryBuilder = CreateContentInventoryEntry;
|
|
824
|
+
|
|
825
|
+
/** @deprecated Use {@link CreateEntitySelect}. Removed in 2.0. */
|
|
826
|
+
export const EntitySelectBuilder = CreateEntitySelect;
|
|
827
|
+
/** @deprecated Use {@link CreateEntitySelect}. Removed in 2.0. */
|
|
828
|
+
export type EntitySelectBuilder = CreateEntitySelect;
|
|
829
|
+
|
|
830
|
+
/** @deprecated Use {@link CreateFileComponent}. Removed in 2.0. */
|
|
831
|
+
export const FileComponentBuilder = CreateFileComponent;
|
|
832
|
+
/** @deprecated Use {@link CreateFileComponent}. Removed in 2.0. */
|
|
833
|
+
export type FileComponentBuilder = CreateFileComponent;
|
|
834
|
+
|
|
835
|
+
/** @deprecated Use {@link CreateMediaGallery}. Removed in 2.0. */
|
|
836
|
+
export const MediaGalleryBuilder = CreateMediaGallery;
|
|
837
|
+
/** @deprecated Use {@link CreateMediaGallery}. Removed in 2.0. */
|
|
838
|
+
export type MediaGalleryBuilder = CreateMediaGallery;
|
|
839
|
+
|
|
840
|
+
/** @deprecated Use {@link CreateMentionableSelectMenu}. Removed in 2.0. */
|
|
841
|
+
export const MentionableSelectMenuBuilder = CreateMentionableSelectMenu;
|
|
842
|
+
/** @deprecated Use {@link CreateMentionableSelectMenu}. Removed in 2.0. */
|
|
843
|
+
export type MentionableSelectMenuBuilder = CreateMentionableSelectMenu;
|
|
844
|
+
|
|
845
|
+
/** @deprecated Use {@link CreateModal}. Removed in 2.0. */
|
|
846
|
+
export const ModalBuilder = CreateModal;
|
|
847
|
+
/** @deprecated Use {@link CreateModal}. Removed in 2.0. */
|
|
848
|
+
export type ModalBuilder = CreateModal;
|
|
849
|
+
|
|
850
|
+
/** @deprecated Use {@link CreateRoleSelectMenu}. Removed in 2.0. */
|
|
851
|
+
export const RoleSelectMenuBuilder = CreateRoleSelectMenu;
|
|
852
|
+
/** @deprecated Use {@link CreateRoleSelectMenu}. Removed in 2.0. */
|
|
853
|
+
export type RoleSelectMenuBuilder = CreateRoleSelectMenu;
|
|
854
|
+
|
|
855
|
+
/** @deprecated Use {@link CreateSection}. Removed in 2.0. */
|
|
856
|
+
export const SectionBuilder = CreateSection;
|
|
857
|
+
/** @deprecated Use {@link CreateSection}. Removed in 2.0. */
|
|
858
|
+
export type SectionBuilder = CreateSection;
|
|
859
|
+
|
|
860
|
+
/** @deprecated Use {@link CreateSeparator}. Removed in 2.0. */
|
|
861
|
+
export const SeparatorBuilder = CreateSeparator;
|
|
862
|
+
/** @deprecated Use {@link CreateSeparator}. Removed in 2.0. */
|
|
863
|
+
export type SeparatorBuilder = CreateSeparator;
|
|
864
|
+
|
|
865
|
+
/** @deprecated Use {@link CreateStringSelect}. Removed in 2.0. */
|
|
866
|
+
export const StringSelectBuilder = CreateStringSelect;
|
|
867
|
+
/** @deprecated Use {@link CreateStringSelect}. Removed in 2.0. */
|
|
868
|
+
export type StringSelectBuilder = CreateStringSelect;
|
|
869
|
+
|
|
870
|
+
/** @deprecated Use {@link CreateStringSelectMenu}. Removed in 2.0. */
|
|
871
|
+
export const StringSelectMenuBuilder = CreateStringSelect;
|
|
872
|
+
/** @deprecated Use {@link CreateStringSelectMenu}. Removed in 2.0. */
|
|
873
|
+
export type StringSelectMenuBuilder = CreateStringSelect;
|
|
874
|
+
|
|
875
|
+
/** @deprecated Use {@link CreateTextDisplay}. Removed in 2.0. */
|
|
876
|
+
export const TextDisplayBuilder = CreateTextDisplay;
|
|
877
|
+
/** @deprecated Use {@link CreateTextDisplay}. Removed in 2.0. */
|
|
878
|
+
export type TextDisplayBuilder = CreateTextDisplay;
|
|
879
|
+
|
|
880
|
+
/** @deprecated Use {@link CreateTextInput}. Removed in 2.0. */
|
|
881
|
+
export const TextInputBuilder = CreateTextInput;
|
|
882
|
+
/** @deprecated Use {@link CreateTextInput}. Removed in 2.0. */
|
|
883
|
+
export type TextInputBuilder = CreateTextInput;
|
|
884
|
+
|
|
885
|
+
/** @deprecated Use {@link CreateThumbnail}. Removed in 2.0. */
|
|
886
|
+
export const ThumbnailBuilder = CreateThumbnail;
|
|
887
|
+
/** @deprecated Use {@link CreateThumbnail}. Removed in 2.0. */
|
|
888
|
+
export type ThumbnailBuilder = CreateThumbnail;
|
|
889
|
+
|
|
890
|
+
/** @deprecated Use {@link CreateUserSelectMenu}. Removed in 2.0. */
|
|
891
|
+
export const UserSelectMenuBuilder = CreateUserSelectMenu;
|
|
892
|
+
/** @deprecated Use {@link CreateUserSelectMenu}. Removed in 2.0. */
|
|
893
|
+
export type UserSelectMenuBuilder = CreateUserSelectMenu;
|
|
894
|
+
|
|
895
|
+
/** @deprecated Use {@link CreateActionRow}. Removed in 2.0. */
|
|
896
|
+
export const ActionRowBuilder = CreateActionRow;
|
|
897
|
+
/** @deprecated Use {@link CreateActionRow}. Removed in 2.0. */
|
|
898
|
+
export type ActionRowBuilder<
|
|
899
|
+
T extends { toJSON(): APIActionRowChild } = { toJSON(): APIActionRowChild },
|
|
900
|
+
> = CreateActionRow<T>;
|
|
901
|
+
|
|
902
|
+
/** @deprecated Use {@link ButtonType}. Removed in 2.0. */
|
|
903
|
+
export const ButtonStyle = ButtonType;
|
|
904
|
+
/** @deprecated Use {@link ButtonType}. Removed in 2.0. */
|
|
905
|
+
export type ButtonStyle = ButtonType;
|
|
906
|
+
|
|
907
|
+
/** @deprecated Use {@link TextInputType}. Removed in 2.0. */
|
|
908
|
+
export const TextInputStyle = TextInputType;
|
|
909
|
+
/** @deprecated Use {@link TextInputType}. Removed in 2.0. */
|
|
910
|
+
export type TextInputStyle = TextInputType;
|
|
911
|
+
|
|
912
|
+
/** @deprecated Use {@link ComponentEnum}. Removed in 2.0. */
|
|
913
|
+
export const ComponentType = ComponentEnum;
|
|
914
|
+
/** @deprecated Use {@link ComponentEnum}. Removed in 2.0. */
|
|
915
|
+
export type ComponentType = ComponentEnum;
|