mirror of
https://github.com/discordjs/discord.js.git
synced 2026-06-03 01:20:07 +00:00
153 lines
4.6 KiB
TypeScript
153 lines
4.6 KiB
TypeScript
import type { APIRadioGroupComponent, APIRadioGroupOption } from 'discord-api-types/v10';
|
|
import { ComponentType } from 'discord-api-types/v10';
|
|
import type { RestOrArray } from '../../util/normalizeArray';
|
|
import { normalizeArray } from '../../util/normalizeArray';
|
|
import { ComponentBuilder } from '../Component';
|
|
import { radioGroupOptionPredicate, radioGroupPredicate } from './Assertions';
|
|
import { RadioGroupOptionBuilder } from './RadioGroupOption';
|
|
|
|
/**
|
|
* A builder that creates API-compatible JSON data for radio groups.
|
|
*/
|
|
export class RadioGroupBuilder extends ComponentBuilder<APIRadioGroupComponent> {
|
|
/**
|
|
* The options within this radio group.
|
|
*/
|
|
public readonly options: RadioGroupOptionBuilder[];
|
|
|
|
/**
|
|
* Creates a new radio group from API data.
|
|
*
|
|
* @param data - The API data to create this radio group with
|
|
* @example
|
|
* Creating a radio group from an API data object:
|
|
* ```ts
|
|
* const radioGroup = new RadioGroupBuilder({
|
|
* custom_id: 'select_options',
|
|
* options: [
|
|
* { label: 'Option 1', value: 'option_1' },
|
|
* { label: 'Option 2', value: 'option_2' },
|
|
* ],
|
|
* });
|
|
* ```
|
|
* @example
|
|
* Creating a radio group using setters and API data:
|
|
* ```ts
|
|
* const radioGroup = new RadioGroupBuilder()
|
|
* .setCustomId('choose_items')
|
|
* .setOptions([
|
|
* { label: 'Item A', value: 'item_a' },
|
|
* { label: 'Item B', value: 'item_b' },
|
|
* ])
|
|
* ```
|
|
*/
|
|
public constructor(data?: Partial<APIRadioGroupComponent>) {
|
|
const { options, ...initData } = data ?? {};
|
|
super({ ...initData, type: ComponentType.RadioGroup });
|
|
this.options = options?.map((option: APIRadioGroupOption) => new RadioGroupOptionBuilder(option)) ?? [];
|
|
}
|
|
|
|
/**
|
|
* Sets the custom id of this radio group.
|
|
*
|
|
* @param customId - The custom id to use
|
|
*/
|
|
public setCustomId(customId: string) {
|
|
this.data.custom_id = customId;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Adds options to this radio group.
|
|
*
|
|
* @param options - The options to add
|
|
*/
|
|
public addOptions(...options: RestOrArray<APIRadioGroupOption | RadioGroupOptionBuilder>) {
|
|
const normalizedOptions = normalizeArray(options);
|
|
|
|
this.options.push(
|
|
...normalizedOptions.map((normalizedOption) => {
|
|
// I do this because TS' duck typing causes issues,
|
|
// if I put in a CheckboxGroupOption, TS lets it pass but
|
|
// it fails to convert to a checkbox group option at runtime
|
|
const json = 'toJSON' in normalizedOption ? normalizedOption.toJSON() : normalizedOption;
|
|
const option = new RadioGroupOptionBuilder(json);
|
|
radioGroupOptionPredicate.parse(option.toJSON());
|
|
return option;
|
|
}),
|
|
);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the options for this radio group.
|
|
*
|
|
* @param options - The options to use
|
|
*/
|
|
public setOptions(...options: RestOrArray<APIRadioGroupOption | RadioGroupOptionBuilder>) {
|
|
return this.spliceOptions(0, this.options.length, ...options);
|
|
}
|
|
|
|
/**
|
|
* Removes, replaces, or inserts options for this radio group.
|
|
*
|
|
* @remarks
|
|
* This method behaves similarly
|
|
* to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
|
|
* It's useful for modifying and adjusting the order of existing options.
|
|
* @param index - The index to start at
|
|
* @param deleteCount - The number of options to remove
|
|
* @param options - The replacing option objects or builders
|
|
*/
|
|
public spliceOptions(
|
|
index: number,
|
|
deleteCount: number,
|
|
...options: RestOrArray<APIRadioGroupOption | RadioGroupOptionBuilder>
|
|
) {
|
|
const normalizedOptions = normalizeArray(options);
|
|
|
|
const clone = [...this.options];
|
|
|
|
clone.splice(
|
|
index,
|
|
deleteCount,
|
|
...normalizedOptions.map((normalizedOption) => {
|
|
// I do this because TS' duck typing causes issues,
|
|
// if I put in a CheckboxGroupOption, TS lets it pass but
|
|
// it fails to convert to a radio group option at runtime
|
|
const json = 'toJSON' in normalizedOption ? normalizedOption.toJSON() : normalizedOption;
|
|
const option = new RadioGroupOptionBuilder(json);
|
|
radioGroupOptionPredicate.parse(option.toJSON());
|
|
return option;
|
|
}),
|
|
);
|
|
|
|
this.options.splice(0, this.options.length, ...clone);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether selecting options is required.
|
|
*
|
|
* @param required - Whether selecting options is required
|
|
*/
|
|
public setRequired(required: boolean) {
|
|
this.data.required = required;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc ComponentBuilder.toJSON}
|
|
*/
|
|
public override toJSON(): APIRadioGroupComponent {
|
|
const data = {
|
|
...this.data,
|
|
options: this.options.map((option) => option.toJSON()),
|
|
};
|
|
|
|
radioGroupPredicate.parse(data);
|
|
|
|
return data as APIRadioGroupComponent;
|
|
}
|
|
}
|