mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 03:53:29 +01:00
feat!: More label components and text display in modal (#11078)
BREAKING CHANGE: Modals only have adding (no setting) and splicing has been replaced with a generalised splice method to support all components.
This commit is contained in:
@@ -23,6 +23,7 @@ const selectMenuDataWithoutOptions = {
|
|||||||
min_values: 1,
|
min_values: 1,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
placeholder: 'test',
|
placeholder: 'test',
|
||||||
|
required: false,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const selectMenuData: APISelectMenuComponent = {
|
const selectMenuData: APISelectMenuComponent = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ComponentType, TextInputStyle, type APIModalInteractionResponseCallbackData } from 'discord-api-types/v10';
|
import { ComponentType, TextInputStyle, type APIModalInteractionResponseCallbackData } from 'discord-api-types/v10';
|
||||||
import { describe, test, expect } from 'vitest';
|
import { describe, test, expect } from 'vitest';
|
||||||
import { ModalBuilder, TextInputBuilder, LabelBuilder } from '../../src/index.js';
|
import { ModalBuilder, TextInputBuilder, LabelBuilder, TextDisplayBuilder } from '../../src/index.js';
|
||||||
|
|
||||||
const modal = () => new ModalBuilder();
|
const modal = () => new ModalBuilder();
|
||||||
|
|
||||||
@@ -9,19 +9,27 @@ const label = () =>
|
|||||||
.setLabel('label')
|
.setLabel('label')
|
||||||
.setTextInputComponent(new TextInputBuilder().setCustomId('text').setStyle(TextInputStyle.Short));
|
.setTextInputComponent(new TextInputBuilder().setCustomId('text').setStyle(TextInputStyle.Short));
|
||||||
|
|
||||||
|
const textDisplay = () => new TextDisplayBuilder().setContent('text');
|
||||||
|
|
||||||
describe('Modals', () => {
|
describe('Modals', () => {
|
||||||
test('GIVEN valid fields THEN builder does not throw', () => {
|
test('GIVEN valid fields THEN builder does not throw', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
modal().setTitle('test').setCustomId('foobar').setLabelComponents(label()).toJSON(),
|
modal().setTitle('test').setCustomId('foobar').addLabelComponents(label()).toJSON(),
|
||||||
).not.toThrowError();
|
).not.toThrowError();
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
modal().setTitle('test').setCustomId('foobar').setLabelComponents(label()).toJSON(),
|
modal().setTitle('test').setCustomId('foobar').addLabelComponents(label()).toJSON(),
|
||||||
|
).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
modal().setTitle('test').setCustomId('foobar').addTextDisplayComponents(textDisplay()).toJSON(),
|
||||||
).not.toThrowError();
|
).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('GIVEN invalid fields THEN builder does throw', () => {
|
test('GIVEN invalid fields THEN builder does throw', () => {
|
||||||
expect(() => modal().setTitle('test').setCustomId('foobar').toJSON()).toThrowError();
|
expect(() => modal().setTitle('test').setCustomId('foobar').toJSON()).toThrowError();
|
||||||
// @ts-expect-error: CustomId is invalid
|
|
||||||
|
// @ts-expect-error: Custom id is invalid
|
||||||
expect(() => modal().setTitle('test').setCustomId(42).toJSON()).toThrowError();
|
expect(() => modal().setTitle('test').setCustomId(42).toJSON()).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -42,14 +50,8 @@ describe('Modals', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: ComponentType.Label,
|
type: ComponentType.TextDisplay,
|
||||||
label: 'label',
|
content: 'yooooooooo',
|
||||||
description: 'description',
|
|
||||||
component: {
|
|
||||||
type: ComponentType.TextInput,
|
|
||||||
style: TextInputStyle.Paragraph,
|
|
||||||
custom_id: 'custom id',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies APIModalInteractionResponseCallbackData;
|
} satisfies APIModalInteractionResponseCallbackData;
|
||||||
@@ -60,19 +62,14 @@ describe('Modals', () => {
|
|||||||
modal()
|
modal()
|
||||||
.setTitle(modalData.title)
|
.setTitle(modalData.title)
|
||||||
.setCustomId('custom id')
|
.setCustomId('custom id')
|
||||||
.setLabelComponents(
|
.addLabelComponents(
|
||||||
new LabelBuilder()
|
new LabelBuilder()
|
||||||
.setId(33)
|
.setId(33)
|
||||||
.setLabel('label')
|
.setLabel('label')
|
||||||
.setDescription('description')
|
.setDescription('description')
|
||||||
.setTextInputComponent(new TextInputBuilder().setCustomId('custom id').setStyle(TextInputStyle.Paragraph)),
|
.setTextInputComponent(new TextInputBuilder().setCustomId('custom id').setStyle(TextInputStyle.Paragraph)),
|
||||||
)
|
)
|
||||||
.addLabelComponents(
|
.addTextDisplayComponents((textDisplay) => textDisplay.setContent('yooooooooo'))
|
||||||
new LabelBuilder()
|
|
||||||
.setLabel('label')
|
|
||||||
.setDescription('description')
|
|
||||||
.setTextInputComponent(new TextInputBuilder().setCustomId('custom id').setStyle(TextInputStyle.Paragraph)),
|
|
||||||
)
|
|
||||||
.toJSON(),
|
.toJSON(),
|
||||||
).toEqual(modalData);
|
).toEqual(modalData);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ export type ModalActionRowComponentBuilder = TextInputBuilder;
|
|||||||
*/
|
*/
|
||||||
export type AnyActionRowComponentBuilder = MessageActionRowComponentBuilder | ModalActionRowComponentBuilder;
|
export type AnyActionRowComponentBuilder = MessageActionRowComponentBuilder | ModalActionRowComponentBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any modal component builder.
|
||||||
|
*/
|
||||||
|
export type AnyModalComponentBuilder = LabelBuilder | TextDisplayBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Components here are mapped to their respective builder.
|
* Components here are mapped to their respective builder.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,24 @@
|
|||||||
import { ComponentType } from 'discord-api-types/v10';
|
import { ComponentType } from 'discord-api-types/v10';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { selectMenuStringPredicate } from '../Assertions';
|
import {
|
||||||
|
selectMenuChannelPredicate,
|
||||||
|
selectMenuMentionablePredicate,
|
||||||
|
selectMenuRolePredicate,
|
||||||
|
selectMenuStringPredicate,
|
||||||
|
selectMenuUserPredicate,
|
||||||
|
} from '../Assertions';
|
||||||
import { textInputPredicate } from '../textInput/Assertions';
|
import { textInputPredicate } from '../textInput/Assertions';
|
||||||
|
|
||||||
export const labelPredicate = z.object({
|
export const labelPredicate = z.object({
|
||||||
type: z.literal(ComponentType.Label),
|
type: z.literal(ComponentType.Label),
|
||||||
label: z.string().min(1).max(45),
|
label: z.string().min(1).max(45),
|
||||||
description: z.string().min(1).max(100).optional(),
|
description: z.string().min(1).max(100).optional(),
|
||||||
component: z.union([selectMenuStringPredicate, textInputPredicate]),
|
component: z.union([
|
||||||
|
selectMenuStringPredicate,
|
||||||
|
textInputPredicate,
|
||||||
|
selectMenuUserPredicate,
|
||||||
|
selectMenuRolePredicate,
|
||||||
|
selectMenuMentionablePredicate,
|
||||||
|
selectMenuChannelPredicate,
|
||||||
|
]),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,15 +1,33 @@
|
|||||||
import type { APILabelComponent, APIStringSelectComponent, APITextInputComponent } from 'discord-api-types/v10';
|
import type {
|
||||||
|
APIChannelSelectComponent,
|
||||||
|
APILabelComponent,
|
||||||
|
APIMentionableSelectComponent,
|
||||||
|
APIRoleSelectComponent,
|
||||||
|
APIStringSelectComponent,
|
||||||
|
APITextInputComponent,
|
||||||
|
APIUserSelectComponent,
|
||||||
|
} from 'discord-api-types/v10';
|
||||||
import { ComponentType } from 'discord-api-types/v10';
|
import { ComponentType } from 'discord-api-types/v10';
|
||||||
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
||||||
import { validate } from '../../util/validation.js';
|
import { validate } from '../../util/validation.js';
|
||||||
import { ComponentBuilder } from '../Component.js';
|
import { ComponentBuilder } from '../Component.js';
|
||||||
import { createComponentBuilder } from '../Components.js';
|
import { createComponentBuilder } from '../Components.js';
|
||||||
|
import { ChannelSelectMenuBuilder } from '../selectMenu/ChannelSelectMenu.js';
|
||||||
|
import { MentionableSelectMenuBuilder } from '../selectMenu/MentionableSelectMenu.js';
|
||||||
|
import { RoleSelectMenuBuilder } from '../selectMenu/RoleSelectMenu.js';
|
||||||
import { StringSelectMenuBuilder } from '../selectMenu/StringSelectMenu.js';
|
import { StringSelectMenuBuilder } from '../selectMenu/StringSelectMenu.js';
|
||||||
|
import { UserSelectMenuBuilder } from '../selectMenu/UserSelectMenu.js';
|
||||||
import { TextInputBuilder } from '../textInput/TextInput.js';
|
import { TextInputBuilder } from '../textInput/TextInput.js';
|
||||||
import { labelPredicate } from './Assertions.js';
|
import { labelPredicate } from './Assertions.js';
|
||||||
|
|
||||||
export interface LabelBuilderData extends Partial<Omit<APILabelComponent, 'component'>> {
|
export interface LabelBuilderData extends Partial<Omit<APILabelComponent, 'component'>> {
|
||||||
component?: StringSelectMenuBuilder | TextInputBuilder;
|
component?:
|
||||||
|
| ChannelSelectMenuBuilder
|
||||||
|
| MentionableSelectMenuBuilder
|
||||||
|
| RoleSelectMenuBuilder
|
||||||
|
| StringSelectMenuBuilder
|
||||||
|
| TextInputBuilder
|
||||||
|
| UserSelectMenuBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +67,6 @@ export class LabelBuilder extends ComponentBuilder<APILabelComponent> {
|
|||||||
|
|
||||||
this.data = {
|
this.data = {
|
||||||
...structuredClone(rest),
|
...structuredClone(rest),
|
||||||
// @ts-expect-error https://github.com/discordjs/discord.js/pull/11078
|
|
||||||
component: component ? createComponentBuilder(component) : undefined,
|
component: component ? createComponentBuilder(component) : undefined,
|
||||||
type: ComponentType.Label,
|
type: ComponentType.Label,
|
||||||
};
|
};
|
||||||
@@ -98,6 +115,60 @@ export class LabelBuilder extends ComponentBuilder<APILabelComponent> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a user select menu component to this label.
|
||||||
|
*
|
||||||
|
* @param input - A function that returns a component builder or an already built builder
|
||||||
|
*/
|
||||||
|
public setUserSelectMenuComponent(
|
||||||
|
input: APIUserSelectComponent | UserSelectMenuBuilder | ((builder: UserSelectMenuBuilder) => UserSelectMenuBuilder),
|
||||||
|
): this {
|
||||||
|
this.data.component = resolveBuilder(input, UserSelectMenuBuilder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a role select menu component to this label.
|
||||||
|
*
|
||||||
|
* @param input - A function that returns a component builder or an already built builder
|
||||||
|
*/
|
||||||
|
public setRoleSelectMenuComponent(
|
||||||
|
input: APIRoleSelectComponent | RoleSelectMenuBuilder | ((builder: RoleSelectMenuBuilder) => RoleSelectMenuBuilder),
|
||||||
|
): this {
|
||||||
|
this.data.component = resolveBuilder(input, RoleSelectMenuBuilder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a mentionable select menu component to this label.
|
||||||
|
*
|
||||||
|
* @param input - A function that returns a component builder or an already built builder
|
||||||
|
*/
|
||||||
|
public setMentionableSelectMenuComponent(
|
||||||
|
input:
|
||||||
|
| APIMentionableSelectComponent
|
||||||
|
| MentionableSelectMenuBuilder
|
||||||
|
| ((builder: MentionableSelectMenuBuilder) => MentionableSelectMenuBuilder),
|
||||||
|
): this {
|
||||||
|
this.data.component = resolveBuilder(input, MentionableSelectMenuBuilder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a channel select menu component to this label.
|
||||||
|
*
|
||||||
|
* @param input - A function that returns a component builder or an already built builder
|
||||||
|
*/
|
||||||
|
public setChannelSelectMenuComponent(
|
||||||
|
input:
|
||||||
|
| APIChannelSelectComponent
|
||||||
|
| ChannelSelectMenuBuilder
|
||||||
|
| ((builder: ChannelSelectMenuBuilder) => ChannelSelectMenuBuilder),
|
||||||
|
): this {
|
||||||
|
this.data.component = resolveBuilder(input, ChannelSelectMenuBuilder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a text input component to this label.
|
* Sets a text input component to this label.
|
||||||
*
|
*
|
||||||
@@ -118,6 +189,7 @@ export class LabelBuilder extends ComponentBuilder<APILabelComponent> {
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
...structuredClone(rest),
|
...structuredClone(rest),
|
||||||
|
// The label predicate validates the component.
|
||||||
component: component?.toJSON(false),
|
component: component?.toJSON(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export abstract class BaseSelectMenuBuilder<Data extends APISelectMenuComponent>
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
protected abstract override readonly data: Partial<
|
protected abstract override readonly data: Partial<
|
||||||
Pick<Data, 'custom_id' | 'disabled' | 'id' | 'max_values' | 'min_values' | 'placeholder'>
|
Pick<Data, 'custom_id' | 'disabled' | 'id' | 'max_values' | 'min_values' | 'placeholder' | 'required'>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,4 +75,15 @@ export abstract class BaseSelectMenuBuilder<Data extends APISelectMenuComponent>
|
|||||||
this.data.disabled = disabled;
|
this.data.disabled = disabled;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this select menu is required.
|
||||||
|
*
|
||||||
|
* @remarks Only for use in modals.
|
||||||
|
* @param required - Whether this string select menu is required
|
||||||
|
*/
|
||||||
|
public setRequired(required = true) {
|
||||||
|
this.data.required = required;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,17 +147,6 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether this string select menu is required.
|
|
||||||
*
|
|
||||||
* @remarks Only for use in modals.
|
|
||||||
* @param required - Whether this string select menu is required
|
|
||||||
*/
|
|
||||||
public setRequired(required = true) {
|
|
||||||
this.data.required = required;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc ComponentBuilder.toJSON}
|
* {@inheritDoc ComponentBuilder.toJSON}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ComponentType } from 'discord-api-types/v10';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { customIdPredicate } from '../../Assertions.js';
|
import { customIdPredicate } from '../../Assertions.js';
|
||||||
import { labelPredicate } from '../../components/label/Assertions.js';
|
import { labelPredicate } from '../../components/label/Assertions.js';
|
||||||
|
import { textDisplayPredicate } from '../../components/v2/Assertions.js';
|
||||||
|
|
||||||
const titlePredicate = z.string().min(1).max(45);
|
const titlePredicate = z.string().min(1).max(45);
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ export const modalPredicate = z.object({
|
|||||||
.length(1),
|
.length(1),
|
||||||
}),
|
}),
|
||||||
labelPredicate,
|
labelPredicate,
|
||||||
|
textDisplayPredicate,
|
||||||
])
|
])
|
||||||
.array()
|
.array()
|
||||||
.min(1)
|
.min(1)
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
import type { JSONEncodable } from '@discordjs/util';
|
import type { JSONEncodable } from '@discordjs/util';
|
||||||
import type { APILabelComponent, APIModalInteractionResponseCallbackData } from 'discord-api-types/v10';
|
import type {
|
||||||
|
APILabelComponent,
|
||||||
|
APIModalInteractionResponseCallbackData,
|
||||||
|
APITextDisplayComponent,
|
||||||
|
} from 'discord-api-types/v10';
|
||||||
import type { ActionRowBuilder } from '../../components/ActionRow.js';
|
import type { ActionRowBuilder } from '../../components/ActionRow.js';
|
||||||
|
import type { AnyModalComponentBuilder } from '../../components/Components.js';
|
||||||
import { createComponentBuilder } from '../../components/Components.js';
|
import { createComponentBuilder } from '../../components/Components.js';
|
||||||
import { LabelBuilder } from '../../components/label/Label.js';
|
import { LabelBuilder } from '../../components/label/Label.js';
|
||||||
|
import { TextDisplayBuilder } from '../../components/v2/TextDisplay.js';
|
||||||
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
||||||
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
||||||
import { validate } from '../../util/validation.js';
|
import { validate } from '../../util/validation.js';
|
||||||
import { modalPredicate } from './Assertions.js';
|
import { modalPredicate } from './Assertions.js';
|
||||||
|
|
||||||
export interface ModalBuilderData extends Partial<Omit<APIModalInteractionResponseCallbackData, 'components'>> {
|
export interface ModalBuilderData extends Partial<Omit<APIModalInteractionResponseCallbackData, 'components'>> {
|
||||||
components: (ActionRowBuilder | LabelBuilder)[];
|
components: (ActionRowBuilder | AnyModalComponentBuilder)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +30,7 @@ export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCa
|
|||||||
/**
|
/**
|
||||||
* The components within this modal.
|
* The components within this modal.
|
||||||
*/
|
*/
|
||||||
public get components(): readonly (ActionRowBuilder | LabelBuilder)[] {
|
public get components(): readonly (ActionRowBuilder | AnyModalComponentBuilder)[] {
|
||||||
return this.data.components;
|
return this.data.components;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +44,6 @@ export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCa
|
|||||||
|
|
||||||
this.data = {
|
this.data = {
|
||||||
...structuredClone(rest),
|
...structuredClone(rest),
|
||||||
// @ts-expect-error https://github.com/discordjs/discord.js/pull/11078
|
|
||||||
components: components.map((component) => createComponentBuilder(component)),
|
components: components.map((component) => createComponentBuilder(component)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -80,56 +85,54 @@ export class ModalBuilder implements JSONEncodable<APIModalInteractionResponseCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the labels for this modal.
|
* Adds text display components to this modal.
|
||||||
*
|
*
|
||||||
* @param components - The components to set
|
* @param components - The components to add
|
||||||
*/
|
*/
|
||||||
public setLabelComponents(
|
public addTextDisplayComponents(
|
||||||
...components: RestOrArray<APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder)>
|
...components: RestOrArray<
|
||||||
|
APITextDisplayComponent | TextDisplayBuilder | ((builder: TextDisplayBuilder) => TextDisplayBuilder)
|
||||||
|
>
|
||||||
) {
|
) {
|
||||||
const normalized = normalizeArray(components);
|
const normalized = normalizeArray(components);
|
||||||
this.spliceLabelComponents(0, this.data.components.length, ...normalized);
|
const resolved = normalized.map((row) => resolveBuilder(row, TextDisplayBuilder));
|
||||||
|
|
||||||
|
this.data.components.push(...resolved);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes, replaces, or inserts labels for this modal.
|
* Removes, replaces, or inserts components for this modal.
|
||||||
*
|
*
|
||||||
* @remarks
|
* @remarks
|
||||||
* This method behaves similarly
|
* This method behaves similarly
|
||||||
* to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
|
* to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
|
||||||
* The maximum amount of labels that can be added is 5.
|
* The maximum amount of components that can be added is 5.
|
||||||
*
|
*
|
||||||
* It's useful for modifying and adjusting order of the already-existing labels of a modal.
|
* It's useful for modifying and adjusting order of the already-existing components of a modal.
|
||||||
* @example
|
* @example
|
||||||
* Remove the first label:
|
* Remove the first component:
|
||||||
* ```ts
|
* ```ts
|
||||||
* modal.spliceLabelComponents(0, 1);
|
* modal.spliceComponents(0, 1);
|
||||||
* ```
|
* ```
|
||||||
* @example
|
* @example
|
||||||
* Remove the first n labels:
|
* Remove the first n components:
|
||||||
* ```ts
|
* ```ts
|
||||||
* const n = 4;
|
* const n = 4;
|
||||||
* modal.spliceLabelComponents(0, n);
|
* modal.spliceComponents(0, n);
|
||||||
* ```
|
* ```
|
||||||
* @example
|
* @example
|
||||||
* Remove the last label:
|
* Remove the last component:
|
||||||
* ```ts
|
* ```ts
|
||||||
* modal.spliceLabelComponents(-1, 1);
|
* modal.spliceComponents(-1, 1);
|
||||||
* ```
|
* ```
|
||||||
* @param index - The index to start at
|
* @param index - The index to start at
|
||||||
* @param deleteCount - The number of labels to remove
|
* @param deleteCount - The number of components to remove
|
||||||
* @param labels - The replacing label objects
|
* @param components - The replacing components
|
||||||
*/
|
*/
|
||||||
public spliceLabelComponents(
|
public spliceComponents(index: number, deleteCount: number, ...components: AnyModalComponentBuilder[]): this {
|
||||||
index: number,
|
this.data.components.splice(index, deleteCount, ...components);
|
||||||
deleteCount: number,
|
|
||||||
...labels: (APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder))[]
|
|
||||||
): this {
|
|
||||||
const resolved = labels.map((label) => resolveBuilder(label, LabelBuilder));
|
|
||||||
this.data.components.splice(index, deleteCount, ...resolved);
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user