forked from discordjs/discord.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCheckboxGroup.ts
More file actions
174 lines (158 loc) · 5.23 KB
/
CheckboxGroup.ts
File metadata and controls
174 lines (158 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import type { APICheckboxGroupComponent, APICheckboxGroupOption } 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 { checkboxGroupOptionPredicate, checkboxGroupPredicate } from './Assertions';
import { CheckboxGroupOptionBuilder } from './CheckboxGroupOption';
/**
* A builder that creates API-compatible JSON data for checkbox groups.
*/
export class CheckboxGroupBuilder extends ComponentBuilder<APICheckboxGroupComponent> {
/**
* The options within this checkbox group.
*/
public readonly options: CheckboxGroupOptionBuilder[];
/**
* Creates a new checkbox group from API data.
*
* @param data - The API data to create this checkbox group with
* @example
* Creating a checkbox group from an API data object:
* ```ts
* const checkboxGroup = new CheckboxGroupBuilder({
* custom_id: 'select_options',
* options: [
* { label: 'Option 1', value: 'option_1' },
* { label: 'Option 2', value: 'option_2' },
* ],
* });
* ```
* @example
* Creating a checkbox group using setters and API data:
* ```ts
* const checkboxGroup = new CheckboxGroupBuilder()
* .setCustomId('choose_items')
* .setOptions([
* { label: 'Item A', value: 'item_a' },
* { label: 'Item B', value: 'item_b' },
* ])
* .setMinValues(1)
* .setMaxValues(2);
* ```
*/
public constructor(data?: Partial<APICheckboxGroupComponent>) {
const { options, ...initData } = data ?? {};
super({ ...initData, type: ComponentType.CheckboxGroup });
this.options = options?.map((option: APICheckboxGroupOption) => new CheckboxGroupOptionBuilder(option)) ?? [];
}
/**
* Sets the custom id of this checkbox group.
*
* @param customId - The custom id to use
*/
public setCustomId(customId: string) {
this.data.custom_id = customId;
return this;
}
/**
* Adds options to this checkbox group.
*
* @param options - The options to add
*/
public addOptions(...options: RestOrArray<APICheckboxGroupOption | CheckboxGroupOptionBuilder>) {
const normalizedOptions = normalizeArray(options);
this.options.push(
...normalizedOptions.map((normalizedOption) => {
// I do this because TS' duck typing causes issues,
// if I put in a RadioGroupOption, 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 CheckboxGroupOptionBuilder(json);
checkboxGroupOptionPredicate.parse(option.toJSON());
return option;
}),
);
return this;
}
/**
* Sets the options for this checkbox group.
*
* @param options - The options to use
*/
public setOptions(options: RestOrArray<APICheckboxGroupOption | CheckboxGroupOptionBuilder>) {
return this.spliceOptions(0, this.options.length, ...options);
}
/**
* Removes, replaces, or inserts options for this checkbox 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<APICheckboxGroupOption | CheckboxGroupOptionBuilder>
) {
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 RadioGroupOption, 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 CheckboxGroupOptionBuilder(json);
checkboxGroupOptionPredicate.parse(option.toJSON());
return option;
}),
);
this.options.splice(0, this.options.length, ...clone);
return this;
}
/**
* Sets the minimum number of options that must be selected.
*
* @param minValues - The minimum number of options that must be selected
*/
public setMinValues(minValues: number) {
this.data.min_values = minValues;
return this;
}
/**
* Sets the maximum number of options that can be selected.
*
* @param maxValues - The maximum number of options that can be selected
*/
public setMaxValues(maxValues: number) {
this.data.max_values = maxValues;
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(): APICheckboxGroupComponent {
const data = {
...this.data,
options: this.options.map((option) => option.toJSON()),
};
checkboxGroupPredicate.parse(data);
return data as APICheckboxGroupComponent;
}
}