inquirer-grouped-checkbox 0.1.0

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.
@@ -0,0 +1,119 @@
1
+ import * as _inquirer_type from '@inquirer/type';
2
+ import { Prettify } from '@inquirer/type';
3
+ import { Theme, Status } from '@inquirer/core';
4
+
5
+ interface GroupedCheckboxTheme {
6
+ icon: {
7
+ checked: string;
8
+ unchecked: string;
9
+ cursor: string;
10
+ };
11
+ style: {
12
+ disabledChoice: (text: string) => string;
13
+ groupHeader: (text: string, icon?: string) => string;
14
+ searchQuery: (text: string) => string;
15
+ highlight: (text: string) => string;
16
+ description: (text: string) => string;
17
+ };
18
+ helpMode: 'always' | 'never' | 'auto';
19
+ }
20
+
21
+ interface Choice<Value> {
22
+ value: Value;
23
+ name?: string;
24
+ description?: string;
25
+ short?: string;
26
+ disabled?: boolean | string;
27
+ checked?: boolean;
28
+ }
29
+ interface Group<Value> {
30
+ key: string;
31
+ label: string;
32
+ icon?: string;
33
+ choices: ReadonlyArray<Choice<Value>>;
34
+ }
35
+ interface GroupedCheckboxConfig<Value> {
36
+ message: string;
37
+ groups: ReadonlyArray<Group<Value>>;
38
+ searchable?: boolean;
39
+ pageSize?: number;
40
+ required?: boolean;
41
+ validate?: (selections: GroupedSelections<Value>) => boolean | string | Promise<boolean | string>;
42
+ theme?: PartialTheme;
43
+ }
44
+ type PartialTheme = Prettify<Partial<Theme<GroupedCheckboxTheme>> & {
45
+ checkbox?: Partial<GroupedCheckboxTheme>;
46
+ }>;
47
+ interface GroupedSelections<Value> {
48
+ [groupKey: string]: Value[];
49
+ }
50
+ interface NormalizedChoice<Value> {
51
+ value: Value;
52
+ name: string;
53
+ description?: string;
54
+ short: string;
55
+ disabled: boolean | string;
56
+ checked: boolean;
57
+ groupKey: string;
58
+ groupIndex: number;
59
+ indexInGroup: number;
60
+ }
61
+ interface NormalizedGroup<Value> {
62
+ key: string;
63
+ label: string;
64
+ icon?: string;
65
+ startIndex: number;
66
+ endIndex: number;
67
+ choices: NormalizedChoice<Value>[];
68
+ }
69
+ declare class Separator {
70
+ readonly separator: string;
71
+ constructor(separator?: string);
72
+ static isSeparator(item: unknown): item is Separator;
73
+ }
74
+
75
+ declare const groupedCheckbox: <Value>(config: {
76
+ message: string;
77
+ groups: readonly Group<Value>[];
78
+ searchable?: boolean | undefined;
79
+ pageSize?: number | undefined;
80
+ required?: boolean | undefined;
81
+ validate?: ((selections: GroupedSelections<Value>) => boolean | string | Promise<boolean | string>) | undefined;
82
+ theme?: {
83
+ icon?: {
84
+ checked: string;
85
+ unchecked: string;
86
+ cursor: string;
87
+ } | undefined;
88
+ style?: ({
89
+ disabledChoice: (text: string) => string;
90
+ groupHeader: (text: string, icon?: string) => string;
91
+ searchQuery: (text: string) => string;
92
+ highlight: (text: string) => string;
93
+ description: (text: string) => string;
94
+ } & {
95
+ answer: (text: string) => string;
96
+ message: (text: string, status: Status) => string;
97
+ error: (text: string) => string;
98
+ defaultAnswer: (text: string) => string;
99
+ help: (text: string) => string;
100
+ highlight: (text: string) => string;
101
+ key: (text: string) => string;
102
+ }) | undefined;
103
+ helpMode?: "always" | "never" | "auto" | undefined;
104
+ prefix?: string | {
105
+ [x: string & {}]: string;
106
+ idle: string;
107
+ done: string;
108
+ } | undefined;
109
+ spinner?: {
110
+ interval: number;
111
+ frames: string[];
112
+ } | undefined;
113
+ checkbox?: Partial<GroupedCheckboxTheme> | undefined;
114
+ } | undefined;
115
+ }, context?: _inquirer_type.Context) => Promise<GroupedSelections<Value>> & {
116
+ cancel: () => void;
117
+ };
118
+
119
+ export { type Choice, type Group, type GroupedCheckboxConfig, type GroupedCheckboxTheme, type GroupedSelections, type NormalizedChoice, type NormalizedGroup, Separator, groupedCheckbox as default };
package/dist/index.js ADDED
@@ -0,0 +1,441 @@
1
+ // src/index.ts
2
+ import {
3
+ createPrompt,
4
+ isBackspaceKey,
5
+ isDownKey,
6
+ isEnterKey,
7
+ isSpaceKey,
8
+ isTabKey,
9
+ isUpKey,
10
+ makeTheme,
11
+ useKeypress,
12
+ useMemo,
13
+ usePagination,
14
+ usePrefix,
15
+ useRef,
16
+ useState
17
+ } from "@inquirer/core";
18
+ import { styleText as styleText2 } from "util";
19
+
20
+ // src/theme.ts
21
+ import figures from "@inquirer/figures";
22
+ import { styleText } from "util";
23
+ var defaultTheme = {
24
+ icon: {
25
+ checked: figures.circleFilled,
26
+ unchecked: figures.circle,
27
+ cursor: figures.pointer
28
+ },
29
+ style: {
30
+ disabledChoice: (text) => styleText("dim", text),
31
+ groupHeader: (text, icon) => styleText("bold", icon ? `${icon} ${text}` : text),
32
+ searchQuery: (text) => styleText("cyan", text),
33
+ highlight: (text) => styleText("cyan", text),
34
+ description: (text) => styleText("dim", text)
35
+ },
36
+ helpMode: "auto"
37
+ };
38
+
39
+ // src/types.ts
40
+ var Separator = class _Separator {
41
+ separator;
42
+ constructor(separator = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500") {
43
+ this.separator = separator;
44
+ }
45
+ static isSeparator(item) {
46
+ return item instanceof _Separator;
47
+ }
48
+ };
49
+
50
+ // src/utils.ts
51
+ function normalizeGroups(groups) {
52
+ const normalizedGroups = [];
53
+ const flatChoices = [];
54
+ let flatIndex = 0;
55
+ groups.forEach((group, groupIndex) => {
56
+ const startIndex = flatIndex;
57
+ const normalizedChoices = [];
58
+ group.choices.forEach((choice, indexInGroup) => {
59
+ const normalizedChoice = {
60
+ value: choice.value,
61
+ name: choice.name ?? String(choice.value),
62
+ description: choice.description,
63
+ short: choice.short ?? choice.name ?? String(choice.value),
64
+ disabled: choice.disabled ?? false,
65
+ checked: choice.checked ?? false,
66
+ groupKey: group.key,
67
+ groupIndex,
68
+ indexInGroup
69
+ };
70
+ normalizedChoices.push(normalizedChoice);
71
+ flatChoices.push(normalizedChoice);
72
+ flatIndex++;
73
+ });
74
+ normalizedGroups.push({
75
+ key: group.key,
76
+ label: group.label,
77
+ icon: group.icon,
78
+ startIndex,
79
+ endIndex: flatIndex - 1,
80
+ choices: normalizedChoices
81
+ });
82
+ });
83
+ return { normalizedGroups, flatChoices };
84
+ }
85
+ function filterBySearch(flatChoices, groups, query) {
86
+ if (!query) {
87
+ return { filteredChoices: flatChoices, filteredGroups: groups };
88
+ }
89
+ const lowerQuery = query.toLowerCase();
90
+ const filteredChoices = [];
91
+ const filteredGroups = [];
92
+ let flatIndex = 0;
93
+ for (const group of groups) {
94
+ const matchingChoices = [];
95
+ const startIndex = flatIndex;
96
+ const currentGroupChoices = flatChoices.filter(
97
+ (c) => !Separator.isSeparator(c) && c.groupKey === group.key
98
+ );
99
+ for (const choice of currentGroupChoices) {
100
+ if (choice.name.toLowerCase().includes(lowerQuery)) {
101
+ matchingChoices.push(choice);
102
+ filteredChoices.push(choice);
103
+ flatIndex++;
104
+ }
105
+ }
106
+ if (matchingChoices.length > 0) {
107
+ filteredGroups.push({
108
+ ...group,
109
+ startIndex,
110
+ endIndex: flatIndex - 1,
111
+ choices: matchingChoices
112
+ });
113
+ }
114
+ }
115
+ return { filteredChoices, filteredGroups };
116
+ }
117
+ function getCurrentGroup(cursorIndex, groups) {
118
+ return groups.find((group) => cursorIndex >= group.startIndex && cursorIndex <= group.endIndex);
119
+ }
120
+ function getSelectableInGroup(group) {
121
+ return group.choices.filter((choice) => !choice.disabled);
122
+ }
123
+ function buildSelections(choices, groups) {
124
+ const selections = {};
125
+ for (const group of groups) {
126
+ selections[group.key] = [];
127
+ }
128
+ for (const choice of choices) {
129
+ if (choice.checked) {
130
+ const groupSelections = selections[choice.groupKey];
131
+ if (groupSelections) {
132
+ groupSelections.push(choice.value);
133
+ }
134
+ }
135
+ }
136
+ return selections;
137
+ }
138
+ function isSelectableItem(item) {
139
+ return !Separator.isSeparator(item) && !item.disabled;
140
+ }
141
+ function findNextSelectableIndex(items, currentIndex, direction) {
142
+ const length = items.length;
143
+ if (length === 0) return -1;
144
+ let index = currentIndex + direction;
145
+ let iterations = 0;
146
+ while (iterations < length) {
147
+ if (index < 0) index = length - 1;
148
+ if (index >= length) index = 0;
149
+ const item = items[index];
150
+ if (item && isSelectableItem(item)) {
151
+ return index;
152
+ }
153
+ index += direction;
154
+ iterations++;
155
+ }
156
+ return currentIndex;
157
+ }
158
+ function findFirstSelectableIndex(items) {
159
+ for (let i = 0; i < items.length; i++) {
160
+ const item = items[i];
161
+ if (item && isSelectableItem(item)) {
162
+ return i;
163
+ }
164
+ }
165
+ return 0;
166
+ }
167
+ function getGroupStats(group) {
168
+ const selectable = getSelectableInGroup(group);
169
+ const selected = selectable.filter((c) => c.checked).length;
170
+ return { selected, total: selectable.length };
171
+ }
172
+
173
+ // src/index.ts
174
+ var groupedCheckbox = createPrompt(
175
+ (config, done) => {
176
+ const { normalizedGroups: initialGroups, flatChoices: initialChoices } = useMemo(
177
+ () => normalizeGroups(config.groups),
178
+ [config.groups]
179
+ );
180
+ const [status, setStatus] = useState("idle");
181
+ const [choices, setChoices] = useState(
182
+ initialChoices.filter((item) => !Separator.isSeparator(item))
183
+ );
184
+ const [searchQuery, setSearchQuery] = useState("");
185
+ const [errorMessage, setErrorMessage] = useState(void 0);
186
+ const [cursorIndex, setCursorIndex] = useState(0);
187
+ const theme = makeTheme(defaultTheme, config.theme?.checkbox);
188
+ const prefix = usePrefix({ status, theme });
189
+ const { filteredChoices, filteredGroups } = useMemo(
190
+ () => filterBySearch(choices, initialGroups, searchQuery),
191
+ [choices, initialGroups, searchQuery]
192
+ );
193
+ const cursorRef = useRef(cursorIndex);
194
+ cursorRef.current = cursorIndex;
195
+ const choicesRef = useRef(choices);
196
+ choicesRef.current = choices;
197
+ const searchRef = useRef(searchQuery);
198
+ searchRef.current = searchQuery;
199
+ const filteredChoicesRef = useRef(filteredChoices);
200
+ filteredChoicesRef.current = filteredChoices;
201
+ const currentGroup = useMemo(() => getCurrentGroup(cursorIndex, filteredGroups), [cursorIndex, filteredGroups]);
202
+ const currentGroupRef = useRef(currentGroup);
203
+ currentGroupRef.current = currentGroup;
204
+ useKeypress((event) => {
205
+ const key = event;
206
+ if (status !== "idle") return;
207
+ setErrorMessage(void 0);
208
+ if (isEnterKey(key)) {
209
+ const selections = buildSelections(choicesRef.current, initialGroups);
210
+ if (config.required) {
211
+ const hasSelection = Object.values(selections).some((arr) => arr.length > 0);
212
+ if (!hasSelection) {
213
+ setErrorMessage("At least one selection is required");
214
+ return;
215
+ }
216
+ }
217
+ if (config.validate) {
218
+ const result = config.validate(selections);
219
+ if (result instanceof Promise) {
220
+ setStatus("loading");
221
+ result.then((validation) => {
222
+ if (validation === true) {
223
+ setStatus("done");
224
+ done(selections);
225
+ } else {
226
+ setStatus("idle");
227
+ setErrorMessage(typeof validation === "string" ? validation : "Invalid selection");
228
+ }
229
+ });
230
+ return;
231
+ }
232
+ if (result !== true) {
233
+ setErrorMessage(typeof result === "string" ? result : "Invalid selection");
234
+ return;
235
+ }
236
+ }
237
+ setStatus("done");
238
+ done(selections);
239
+ return;
240
+ }
241
+ if (isUpKey(key)) {
242
+ const newIndex = findNextSelectableIndex(filteredChoices, cursorRef.current, -1);
243
+ setCursorIndex(newIndex);
244
+ return;
245
+ }
246
+ if (isDownKey(key)) {
247
+ const newIndex = findNextSelectableIndex(filteredChoices, cursorRef.current, 1);
248
+ setCursorIndex(newIndex);
249
+ return;
250
+ }
251
+ if (isSpaceKey(key)) {
252
+ const currentItem = filteredChoices[cursorRef.current];
253
+ if (currentItem && isSelectableItem(currentItem)) {
254
+ const newChoices = choicesRef.current.map((choice) => {
255
+ if (choice.value === currentItem.value && choice.groupKey === currentItem.groupKey) {
256
+ return { ...choice, checked: !choice.checked };
257
+ }
258
+ return choice;
259
+ });
260
+ setChoices(newChoices);
261
+ }
262
+ return;
263
+ }
264
+ if (config.searchable) {
265
+ if (isBackspaceKey(key)) {
266
+ setSearchQuery(searchRef.current.slice(0, -1));
267
+ setCursorIndex(0);
268
+ return;
269
+ }
270
+ if (key.name === "escape") {
271
+ setSearchQuery("");
272
+ setCursorIndex(findFirstSelectableIndex(choicesRef.current));
273
+ return;
274
+ }
275
+ if (key.sequence && !key.ctrl && !key.shift && !isTabKey(key) && /^[a-zA-Z0-9\-_./\s]$/.test(key.sequence)) {
276
+ setSearchQuery(searchRef.current + key.sequence);
277
+ setCursorIndex(0);
278
+ return;
279
+ }
280
+ }
281
+ if (key.name === "a" && key.ctrl || key.name === "a" && !key.shift && !config.searchable) {
282
+ const visibleChoices = filteredChoicesRef.current.filter(
283
+ (c) => !Separator.isSeparator(c) && !c.disabled
284
+ );
285
+ const allVisibleChecked = visibleChoices.every((c) => c.checked);
286
+ const visibleValues = new Set(visibleChoices.map((c) => c.value));
287
+ setChoices(
288
+ choicesRef.current.map((choice) => {
289
+ if (!choice.disabled && visibleValues.has(choice.value)) {
290
+ return { ...choice, checked: !allVisibleChecked };
291
+ }
292
+ return choice;
293
+ })
294
+ );
295
+ return;
296
+ }
297
+ if (key.name === "i" && key.ctrl || key.name === "i" && !key.shift && !config.searchable) {
298
+ const visibleChoices = filteredChoicesRef.current.filter(
299
+ (c) => !Separator.isSeparator(c) && !c.disabled
300
+ );
301
+ const visibleValues = new Set(visibleChoices.map((c) => c.value));
302
+ setChoices(
303
+ choicesRef.current.map((choice) => {
304
+ if (!choice.disabled && visibleValues.has(choice.value)) {
305
+ return { ...choice, checked: !choice.checked };
306
+ }
307
+ return choice;
308
+ })
309
+ );
310
+ return;
311
+ }
312
+ if (key.name === "a" && key.shift && currentGroupRef.current) {
313
+ const group = currentGroupRef.current;
314
+ const visibleGroupChoices = filteredChoicesRef.current.filter(
315
+ (c) => !Separator.isSeparator(c) && c.groupKey === group.key && !c.disabled
316
+ );
317
+ const allVisibleChecked = visibleGroupChoices.every((c) => c.checked);
318
+ const visibleValues = new Set(visibleGroupChoices.map((c) => c.value));
319
+ setChoices(
320
+ choicesRef.current.map((choice) => {
321
+ if (choice.groupKey === group.key && !choice.disabled && visibleValues.has(choice.value)) {
322
+ return { ...choice, checked: !allVisibleChecked };
323
+ }
324
+ return choice;
325
+ })
326
+ );
327
+ return;
328
+ }
329
+ if (key.name === "i" && key.shift && currentGroupRef.current) {
330
+ const group = currentGroupRef.current;
331
+ const visibleGroupChoices = filteredChoicesRef.current.filter(
332
+ (c) => !Separator.isSeparator(c) && c.groupKey === group.key && !c.disabled
333
+ );
334
+ const visibleValues = new Set(visibleGroupChoices.map((c) => c.value));
335
+ setChoices(
336
+ choicesRef.current.map((choice) => {
337
+ if (choice.groupKey === group.key && !choice.disabled && visibleValues.has(choice.value)) {
338
+ return { ...choice, checked: !choice.checked };
339
+ }
340
+ return choice;
341
+ })
342
+ );
343
+ return;
344
+ }
345
+ if (isTabKey(key) && !key.shift) {
346
+ if (currentGroupRef.current && filteredGroups.length > 1) {
347
+ const currentGroupIdx = filteredGroups.findIndex((g) => g.key === currentGroupRef.current.key);
348
+ const nextGroupIdx = (currentGroupIdx + 1) % filteredGroups.length;
349
+ const nextGroup = filteredGroups[nextGroupIdx];
350
+ if (nextGroup) {
351
+ setCursorIndex(nextGroup.startIndex);
352
+ }
353
+ }
354
+ return;
355
+ }
356
+ if (isTabKey(key) && key.shift) {
357
+ if (currentGroupRef.current && filteredGroups.length > 1) {
358
+ const currentGroupIdx = filteredGroups.findIndex((g) => g.key === currentGroupRef.current.key);
359
+ const prevGroupIdx = currentGroupIdx === 0 ? filteredGroups.length - 1 : currentGroupIdx - 1;
360
+ const prevGroup = filteredGroups[prevGroupIdx];
361
+ if (prevGroup) {
362
+ setCursorIndex(prevGroup.startIndex);
363
+ }
364
+ }
365
+ return;
366
+ }
367
+ });
368
+ const page = usePagination({
369
+ items: filteredChoices,
370
+ active: cursorIndex,
371
+ pageSize: config.pageSize ?? 15,
372
+ renderItem: ({ item, index, isActive }) => {
373
+ if (Separator.isSeparator(item)) {
374
+ return ` ${item.separator}`;
375
+ }
376
+ const group = filteredGroups.find((g) => g.startIndex === index);
377
+ let header = "";
378
+ if (group) {
379
+ const stats = getGroupStats(group);
380
+ const statsText = styleText2("dim", ` (${stats.selected}/${stats.total})`);
381
+ header = `
382
+ ${theme.style.groupHeader(group.label, group.icon)}${statsText}
383
+ `;
384
+ }
385
+ const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
386
+ const cursor = isActive ? theme.icon.cursor : " ";
387
+ const color = item.checked ? theme.style.highlight : (text) => text;
388
+ const name = item.disabled ? theme.style.disabledChoice(
389
+ `${item.name}${typeof item.disabled === "string" ? ` (${item.disabled})` : ""}`
390
+ ) : color(item.name);
391
+ let line = `${header}${cursor} ${checkbox} ${name}`;
392
+ if (item.description && isActive) {
393
+ line += `
394
+ ${theme.style.description(item.description)}`;
395
+ }
396
+ return line;
397
+ }
398
+ });
399
+ let message = config.message;
400
+ if (status === "done") {
401
+ const selections = buildSelections(choices, initialGroups);
402
+ const totalSelected = Object.values(selections).reduce((sum, arr) => sum + arr.length, 0);
403
+ message += styleText2("cyan", ` ${totalSelected} item${totalSelected !== 1 ? "s" : ""} selected`);
404
+ return `${prefix} ${message}`;
405
+ }
406
+ let output = `${prefix} ${message}`;
407
+ if (config.searchable && searchQuery) {
408
+ output += ` ${theme.style.searchQuery(`[${searchQuery}]`)}`;
409
+ }
410
+ if (filteredChoices.length === 0) {
411
+ output += `
412
+ ${styleText2("dim", " No matches found")}`;
413
+ } else {
414
+ output += `
415
+ ${page}`;
416
+ }
417
+ if (theme.helpMode === "always" || theme.helpMode === "auto" && status === "idle") {
418
+ const toggleKey = config.searchable ? "ctrl+a" : "a";
419
+ const invertKey = config.searchable ? "ctrl+i" : "i";
420
+ const helpText = [
421
+ "space: select",
422
+ `${toggleKey}: toggle all`,
423
+ `${invertKey}: invert`,
424
+ config.searchable ? "type to search" : ""
425
+ ].filter(Boolean).join(", ");
426
+ output += `
427
+ ${styleText2("dim", `(${helpText})`)}`;
428
+ }
429
+ if (errorMessage) {
430
+ output += `
431
+ ${styleText2("red", errorMessage)}`;
432
+ }
433
+ return output;
434
+ }
435
+ );
436
+ var index_default = groupedCheckbox;
437
+ export {
438
+ Separator,
439
+ index_default as default
440
+ };
441
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/theme.ts","../src/types.ts","../src/utils.ts"],"sourcesContent":["import {\n createPrompt,\n isBackspaceKey,\n isDownKey,\n isEnterKey,\n isSpaceKey,\n isTabKey,\n isUpKey,\n makeTheme,\n useKeypress,\n useMemo,\n usePagination,\n usePrefix,\n useRef,\n useState,\n type KeypressEvent,\n type Status,\n} from '@inquirer/core'\nimport { styleText } from 'node:util'\nimport { defaultTheme, type GroupedCheckboxTheme } from './theme.js'\nimport type { GroupedCheckboxConfig, GroupedSelections, Item, NormalizedChoice } from './types.js'\nimport { Separator } from './types.js'\nimport {\n buildSelections,\n filterBySearch,\n findFirstSelectableIndex,\n findNextSelectableIndex,\n getCurrentGroup,\n getGroupStats,\n isSelectableItem,\n normalizeGroups,\n} from './utils.js'\n\ninterface ExtendedKey extends KeypressEvent {\n shift?: boolean\n sequence?: string\n}\n\nconst groupedCheckbox = createPrompt(\n <Value>(config: GroupedCheckboxConfig<Value>, done: (value: GroupedSelections<Value>) => void) => {\n const { normalizedGroups: initialGroups, flatChoices: initialChoices } = useMemo(\n () => normalizeGroups(config.groups),\n [config.groups],\n )\n\n const [status, setStatus] = useState<Status>('idle')\n const [choices, setChoices] = useState<NormalizedChoice<Value>[]>(\n initialChoices.filter((item): item is NormalizedChoice<Value> => !Separator.isSeparator(item)),\n )\n const [searchQuery, setSearchQuery] = useState('')\n const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined)\n const [cursorIndex, setCursorIndex] = useState(0)\n\n const theme = makeTheme<GroupedCheckboxTheme>(defaultTheme, config.theme?.checkbox)\n const prefix = usePrefix({ status, theme })\n\n const { filteredChoices, filteredGroups } = useMemo(\n () => filterBySearch(choices, initialGroups, searchQuery),\n [choices, initialGroups, searchQuery],\n )\n\n // Use ref to track current cursor for keypress handler\n const cursorRef = useRef(cursorIndex)\n cursorRef.current = cursorIndex\n\n const choicesRef = useRef(choices)\n choicesRef.current = choices\n\n const searchRef = useRef(searchQuery)\n searchRef.current = searchQuery\n\n const filteredChoicesRef = useRef(filteredChoices)\n filteredChoicesRef.current = filteredChoices\n\n const currentGroup = useMemo(() => getCurrentGroup(cursorIndex, filteredGroups), [cursorIndex, filteredGroups])\n\n const currentGroupRef = useRef(currentGroup)\n currentGroupRef.current = currentGroup\n\n useKeypress((event) => {\n const key = event as ExtendedKey\n if (status !== 'idle') return\n\n setErrorMessage(undefined)\n\n if (isEnterKey(key)) {\n const selections = buildSelections(choicesRef.current, initialGroups)\n\n if (config.required) {\n const hasSelection = Object.values(selections).some((arr) => arr.length > 0)\n if (!hasSelection) {\n setErrorMessage('At least one selection is required')\n return\n }\n }\n\n if (config.validate) {\n const result = config.validate(selections)\n if (result instanceof Promise) {\n setStatus('loading')\n result.then((validation) => {\n if (validation === true) {\n setStatus('done')\n done(selections)\n } else {\n setStatus('idle')\n setErrorMessage(typeof validation === 'string' ? validation : 'Invalid selection')\n }\n })\n return\n }\n if (result !== true) {\n setErrorMessage(typeof result === 'string' ? result : 'Invalid selection')\n return\n }\n }\n\n setStatus('done')\n done(selections)\n return\n }\n\n if (isUpKey(key)) {\n const newIndex = findNextSelectableIndex(filteredChoices, cursorRef.current, -1)\n setCursorIndex(newIndex)\n return\n }\n\n if (isDownKey(key)) {\n const newIndex = findNextSelectableIndex(filteredChoices, cursorRef.current, 1)\n setCursorIndex(newIndex)\n return\n }\n\n if (isSpaceKey(key)) {\n const currentItem = filteredChoices[cursorRef.current]\n if (currentItem && isSelectableItem(currentItem)) {\n const newChoices = choicesRef.current.map((choice) => {\n if (choice.value === currentItem.value && choice.groupKey === currentItem.groupKey) {\n return { ...choice, checked: !choice.checked }\n }\n return choice\n })\n setChoices(newChoices)\n }\n return\n }\n\n // Search input (when searchable) - handle first to capture alphanumeric keys\n if (config.searchable) {\n if (isBackspaceKey(key)) {\n setSearchQuery(searchRef.current.slice(0, -1))\n setCursorIndex(0)\n return\n }\n\n if (key.name === 'escape') {\n setSearchQuery('')\n setCursorIndex(findFirstSelectableIndex(choicesRef.current))\n return\n }\n\n // Alphanumeric input (except when Ctrl/Shift is held for shortcuts, or Tab)\n if (\n key.sequence &&\n !key.ctrl &&\n !key.shift &&\n !isTabKey(key) &&\n /^[a-zA-Z0-9\\-_./\\s]$/.test(key.sequence)\n ) {\n setSearchQuery(searchRef.current + key.sequence)\n setCursorIndex(0)\n return\n }\n }\n\n // Global toggle all: Ctrl+A (or 'a' when not searchable) - operates on filtered/visible choices only\n if ((key.name === 'a' && key.ctrl) || (key.name === 'a' && !key.shift && !config.searchable)) {\n const visibleChoices = filteredChoicesRef.current.filter(\n (c): c is NormalizedChoice<Value> => !Separator.isSeparator(c) && !c.disabled,\n )\n const allVisibleChecked = visibleChoices.every((c) => c.checked)\n const visibleValues = new Set(visibleChoices.map((c) => c.value))\n setChoices(\n choicesRef.current.map((choice) => {\n if (!choice.disabled && visibleValues.has(choice.value)) {\n return { ...choice, checked: !allVisibleChecked }\n }\n return choice\n }),\n )\n return\n }\n\n // Global invert: Ctrl+I (or 'i' when not searchable) - operates on filtered/visible choices only\n if ((key.name === 'i' && key.ctrl) || (key.name === 'i' && !key.shift && !config.searchable)) {\n const visibleChoices = filteredChoicesRef.current.filter(\n (c): c is NormalizedChoice<Value> => !Separator.isSeparator(c) && !c.disabled,\n )\n const visibleValues = new Set(visibleChoices.map((c) => c.value))\n setChoices(\n choicesRef.current.map((choice) => {\n if (!choice.disabled && visibleValues.has(choice.value)) {\n return { ...choice, checked: !choice.checked }\n }\n return choice\n }),\n )\n return\n }\n\n // Per-group toggle: 'A' (Shift+A) - operates on filtered/visible choices only\n if (key.name === 'a' && key.shift && currentGroupRef.current) {\n const group = currentGroupRef.current\n // Get visible choices in this group (filtered by search)\n const visibleGroupChoices = filteredChoicesRef.current.filter(\n (c): c is NormalizedChoice<Value> =>\n !Separator.isSeparator(c) && c.groupKey === group.key && !c.disabled,\n )\n const allVisibleChecked = visibleGroupChoices.every((c) => c.checked)\n const visibleValues = new Set(visibleGroupChoices.map((c) => c.value))\n // Toggle only the visible choices\n setChoices(\n choicesRef.current.map((choice) => {\n if (choice.groupKey === group.key && !choice.disabled && visibleValues.has(choice.value)) {\n return { ...choice, checked: !allVisibleChecked }\n }\n return choice\n }),\n )\n return\n }\n\n // Per-group invert: 'I' (Shift+I) - operates on filtered/visible choices only\n if (key.name === 'i' && key.shift && currentGroupRef.current) {\n const group = currentGroupRef.current\n // Get visible choices in this group (filtered by search)\n const visibleGroupChoices = filteredChoicesRef.current.filter(\n (c): c is NormalizedChoice<Value> =>\n !Separator.isSeparator(c) && c.groupKey === group.key && !c.disabled,\n )\n const visibleValues = new Set(visibleGroupChoices.map((c) => c.value))\n // Invert only the visible choices\n setChoices(\n choicesRef.current.map((choice) => {\n if (choice.groupKey === group.key && !choice.disabled && visibleValues.has(choice.value)) {\n return { ...choice, checked: !choice.checked }\n }\n return choice\n }),\n )\n return\n }\n\n // Tab: jump to next group\n if (isTabKey(key) && !key.shift) {\n if (currentGroupRef.current && filteredGroups.length > 1) {\n const currentGroupIdx = filteredGroups.findIndex((g) => g.key === currentGroupRef.current!.key)\n const nextGroupIdx = (currentGroupIdx + 1) % filteredGroups.length\n const nextGroup = filteredGroups[nextGroupIdx]\n if (nextGroup) {\n setCursorIndex(nextGroup.startIndex)\n }\n }\n return\n }\n\n // Shift+Tab: jump to previous group\n if (isTabKey(key) && key.shift) {\n if (currentGroupRef.current && filteredGroups.length > 1) {\n const currentGroupIdx = filteredGroups.findIndex((g) => g.key === currentGroupRef.current!.key)\n const prevGroupIdx = currentGroupIdx === 0 ? filteredGroups.length - 1 : currentGroupIdx - 1\n const prevGroup = filteredGroups[prevGroupIdx]\n if (prevGroup) {\n setCursorIndex(prevGroup.startIndex)\n }\n }\n return\n }\n })\n\n const page = usePagination<Item<Value>>({\n items: filteredChoices,\n active: cursorIndex,\n pageSize: config.pageSize ?? 15,\n renderItem: ({ item, index, isActive }) => {\n if (Separator.isSeparator(item)) {\n return ` ${item.separator}`\n }\n\n // Check if this is the first item in a group (render header)\n const group = filteredGroups.find((g) => g.startIndex === index)\n let header = ''\n if (group) {\n const stats = getGroupStats(group)\n const statsText = styleText('dim', ` (${stats.selected}/${stats.total})`)\n header = `\\n${theme.style.groupHeader(group.label, group.icon)}${statsText}\\n`\n }\n\n const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked\n const cursor = isActive ? theme.icon.cursor : ' '\n const color = item.checked ? theme.style.highlight : (text: string) => text\n const name = item.disabled\n ? theme.style.disabledChoice(\n `${item.name}${typeof item.disabled === 'string' ? ` (${item.disabled})` : ''}`,\n )\n : color(item.name)\n\n let line = `${header}${cursor} ${checkbox} ${name}`\n\n if (item.description && isActive) {\n line += `\\n ${theme.style.description(item.description)}`\n }\n\n return line\n },\n })\n\n // Build final output\n let message = config.message\n\n if (status === 'done') {\n const selections = buildSelections(choices, initialGroups)\n const totalSelected = Object.values(selections).reduce((sum, arr) => sum + arr.length, 0)\n message += styleText('cyan', ` ${totalSelected} item${totalSelected !== 1 ? 's' : ''} selected`)\n return `${prefix} ${message}`\n }\n\n let output = `${prefix} ${message}`\n\n if (config.searchable && searchQuery) {\n output += ` ${theme.style.searchQuery(`[${searchQuery}]`)}`\n }\n\n if (filteredChoices.length === 0) {\n output += `\\n${styleText('dim', ' No matches found')}`\n } else {\n output += `\\n${page}`\n }\n\n // Help text\n if (theme.helpMode === 'always' || (theme.helpMode === 'auto' && status === 'idle')) {\n const toggleKey = config.searchable ? 'ctrl+a' : 'a'\n const invertKey = config.searchable ? 'ctrl+i' : 'i'\n const helpText = [\n 'space: select',\n `${toggleKey}: toggle all`,\n `${invertKey}: invert`,\n config.searchable ? 'type to search' : '',\n ]\n .filter(Boolean)\n .join(', ')\n output += `\\n${styleText('dim', `(${helpText})`)}`\n }\n\n if (errorMessage) {\n output += `\\n${styleText('red', errorMessage)}`\n }\n\n return output\n },\n)\n\nexport default groupedCheckbox\nexport type { GroupedCheckboxTheme } from './theme.js'\nexport type {\n Choice,\n Group,\n GroupedCheckboxConfig,\n GroupedSelections,\n NormalizedChoice,\n NormalizedGroup,\n} from './types.js'\nexport { Separator }\n","import figures from '@inquirer/figures'\nimport { styleText } from 'node:util'\n\nexport interface GroupedCheckboxTheme {\n icon: {\n checked: string\n unchecked: string\n cursor: string\n }\n style: {\n disabledChoice: (text: string) => string\n groupHeader: (text: string, icon?: string) => string\n searchQuery: (text: string) => string\n highlight: (text: string) => string\n description: (text: string) => string\n }\n helpMode: 'always' | 'never' | 'auto'\n}\n\nexport const defaultTheme: GroupedCheckboxTheme = {\n icon: {\n checked: figures.circleFilled,\n unchecked: figures.circle,\n cursor: figures.pointer,\n },\n style: {\n disabledChoice: (text: string) => styleText('dim', text),\n groupHeader: (text: string, icon?: string) => styleText('bold', icon ? `${icon} ${text}` : text),\n searchQuery: (text: string) => styleText('cyan', text),\n highlight: (text: string) => styleText('cyan', text),\n description: (text: string) => styleText('dim', text),\n },\n helpMode: 'auto',\n}\n","import type { Theme } from '@inquirer/core'\nimport type { Prettify } from '@inquirer/type'\nimport type { GroupedCheckboxTheme } from './theme.js'\n\nexport interface Choice<Value> {\n value: Value\n name?: string\n description?: string\n short?: string\n disabled?: boolean | string\n checked?: boolean\n}\n\nexport interface Group<Value> {\n key: string\n label: string\n icon?: string\n choices: ReadonlyArray<Choice<Value>>\n}\n\nexport interface GroupedCheckboxConfig<Value> {\n message: string\n groups: ReadonlyArray<Group<Value>>\n searchable?: boolean\n pageSize?: number\n required?: boolean\n validate?: (selections: GroupedSelections<Value>) => boolean | string | Promise<boolean | string>\n theme?: PartialTheme\n}\n\nexport type PartialTheme = Prettify<Partial<Theme<GroupedCheckboxTheme>> & { checkbox?: Partial<GroupedCheckboxTheme> }>\n\nexport interface GroupedSelections<Value> {\n [groupKey: string]: Value[]\n}\n\nexport interface NormalizedChoice<Value> {\n value: Value\n name: string\n description?: string\n short: string\n disabled: boolean | string\n checked: boolean\n groupKey: string\n groupIndex: number\n indexInGroup: number\n}\n\nexport interface NormalizedGroup<Value> {\n key: string\n label: string\n icon?: string\n startIndex: number\n endIndex: number\n choices: NormalizedChoice<Value>[]\n}\n\nexport type Item<Value> = NormalizedChoice<Value> | Separator\n\nexport class Separator {\n readonly separator: string\n\n constructor(separator = '────────────────────') {\n this.separator = separator\n }\n\n static isSeparator(item: unknown): item is Separator {\n return item instanceof Separator\n }\n}\n","import type { Group, GroupedSelections, Item, NormalizedChoice, NormalizedGroup } from './types.js'\nimport { Separator } from './types.js'\n\nexport function normalizeGroups<Value>(groups: ReadonlyArray<Group<Value>>): {\n normalizedGroups: NormalizedGroup<Value>[]\n flatChoices: Item<Value>[]\n} {\n const normalizedGroups: NormalizedGroup<Value>[] = []\n const flatChoices: Item<Value>[] = []\n let flatIndex = 0\n\n groups.forEach((group, groupIndex) => {\n const startIndex = flatIndex\n const normalizedChoices: NormalizedChoice<Value>[] = []\n\n group.choices.forEach((choice, indexInGroup) => {\n const normalizedChoice: NormalizedChoice<Value> = {\n value: choice.value,\n name: choice.name ?? String(choice.value),\n description: choice.description,\n short: choice.short ?? choice.name ?? String(choice.value),\n disabled: choice.disabled ?? false,\n checked: choice.checked ?? false,\n groupKey: group.key,\n groupIndex,\n indexInGroup,\n }\n normalizedChoices.push(normalizedChoice)\n flatChoices.push(normalizedChoice)\n flatIndex++\n })\n\n normalizedGroups.push({\n key: group.key,\n label: group.label,\n icon: group.icon,\n startIndex,\n endIndex: flatIndex - 1,\n choices: normalizedChoices,\n })\n })\n\n return { normalizedGroups, flatChoices }\n}\n\nexport function filterBySearch<Value>(\n flatChoices: Item<Value>[],\n groups: NormalizedGroup<Value>[],\n query: string,\n): {\n filteredChoices: Item<Value>[]\n filteredGroups: NormalizedGroup<Value>[]\n} {\n if (!query) {\n return { filteredChoices: flatChoices, filteredGroups: groups }\n }\n\n const lowerQuery = query.toLowerCase()\n const filteredChoices: Item<Value>[] = []\n const filteredGroups: NormalizedGroup<Value>[] = []\n let flatIndex = 0\n\n for (const group of groups) {\n const matchingChoices: NormalizedChoice<Value>[] = []\n const startIndex = flatIndex\n\n // Use flatChoices (current state) filtered by groupKey, not group.choices (stale)\n const currentGroupChoices = flatChoices.filter(\n (c): c is NormalizedChoice<Value> => !Separator.isSeparator(c) && c.groupKey === group.key,\n )\n\n for (const choice of currentGroupChoices) {\n if (choice.name.toLowerCase().includes(lowerQuery)) {\n matchingChoices.push(choice)\n filteredChoices.push(choice)\n flatIndex++\n }\n }\n\n if (matchingChoices.length > 0) {\n filteredGroups.push({\n ...group,\n startIndex,\n endIndex: flatIndex - 1,\n choices: matchingChoices,\n })\n }\n }\n\n return { filteredChoices, filteredGroups }\n}\n\nexport function getCurrentGroup<Value>(\n cursorIndex: number,\n groups: NormalizedGroup<Value>[],\n): NormalizedGroup<Value> | undefined {\n return groups.find((group) => cursorIndex >= group.startIndex && cursorIndex <= group.endIndex)\n}\n\nexport function getSelectableInGroup<Value>(group: NormalizedGroup<Value>): NormalizedChoice<Value>[] {\n return group.choices.filter((choice) => !choice.disabled)\n}\n\nexport function toggleGroup<Value>(\n choices: NormalizedChoice<Value>[],\n group: NormalizedGroup<Value>,\n checked: boolean,\n): NormalizedChoice<Value>[] {\n return choices.map((choice) => {\n if (choice.groupKey === group.key && !choice.disabled) {\n return { ...choice, checked }\n }\n return choice\n })\n}\n\nexport function invertGroup<Value>(\n choices: NormalizedChoice<Value>[],\n group: NormalizedGroup<Value>,\n): NormalizedChoice<Value>[] {\n return choices.map((choice) => {\n if (choice.groupKey === group.key && !choice.disabled) {\n return { ...choice, checked: !choice.checked }\n }\n return choice\n })\n}\n\nexport function toggleAll<Value>(choices: NormalizedChoice<Value>[], checked: boolean): NormalizedChoice<Value>[] {\n return choices.map((choice) => {\n if (!choice.disabled) {\n return { ...choice, checked }\n }\n return choice\n })\n}\n\nexport function invertAll<Value>(choices: NormalizedChoice<Value>[]): NormalizedChoice<Value>[] {\n return choices.map((choice) => {\n if (!choice.disabled) {\n return { ...choice, checked: !choice.checked }\n }\n return choice\n })\n}\n\nexport function buildSelections<Value>(\n choices: NormalizedChoice<Value>[],\n groups: NormalizedGroup<Value>[],\n): GroupedSelections<Value> {\n const selections: GroupedSelections<Value> = {}\n\n for (const group of groups) {\n selections[group.key] = []\n }\n\n for (const choice of choices) {\n if (choice.checked) {\n const groupSelections = selections[choice.groupKey]\n if (groupSelections) {\n groupSelections.push(choice.value)\n }\n }\n }\n\n return selections\n}\n\nexport function isSelectableItem<Value>(item: Item<Value>): item is NormalizedChoice<Value> {\n return !Separator.isSeparator(item) && !item.disabled\n}\n\nexport function findNextSelectableIndex<Value>(items: Item<Value>[], currentIndex: number, direction: 1 | -1): number {\n const length = items.length\n if (length === 0) return -1\n\n let index = currentIndex + direction\n let iterations = 0\n\n while (iterations < length) {\n if (index < 0) index = length - 1\n if (index >= length) index = 0\n\n const item = items[index]\n if (item && isSelectableItem(item)) {\n return index\n }\n\n index += direction\n iterations++\n }\n\n return currentIndex\n}\n\nexport function findFirstSelectableIndex<Value>(items: Item<Value>[]): number {\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n if (item && isSelectableItem(item)) {\n return i\n }\n }\n return 0\n}\n\nexport function getGroupStats<Value>(group: NormalizedGroup<Value>): { selected: number; total: number } {\n const selectable = getSelectableInGroup(group)\n const selected = selectable.filter((c) => c.checked).length\n return { selected, total: selectable.length }\n}\n"],"mappings":"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","names":["styleText","styleText"]}