···11-import { State } from "@clack/core";
11+import { isCancel, State } from "@clack/core";
22import { MultiSelectPrompt, TextPrompt, SelectPrompt, ConfirmPrompt, block } from "@clack/core";
33import color from "picocolors";
44import { cursor, erase } from "sisteransi";
···335335336336 return new RegExp(pattern, 'g');
337337}
338338+339339+340340+export type PromptGroupAwaitedReturn<T> = {
341341+ [P in keyof T]: Exclude<Awaited<T[P]>, symbol>
342342+}
343343+344344+export interface PromptGroupOptions<T> {
345345+ /**
346346+ * Control how the group can be canceld
347347+ * if one of the prompts is canceld.
348348+ */
349349+ onCancel?: (
350350+ opts: {
351351+ results: Partial<PromptGroupAwaitedReturn<T>>
352352+ }
353353+ ) => void;
354354+}
355355+356356+export type PromptGroup<T> = {
357357+ [P in keyof T]: (
358358+ opts: {
359359+ results: Partial<PromptGroupAwaitedReturn<T>>
360360+ }
361361+ ) => Promise<T[P]>
362362+}
363363+364364+/**
365365+ * Define a group of prompts to be displayed
366366+ * and return a results of objects within the group
367367+ */
368368+export const group = async <T>(prompts: PromptGroup<T>, opts?: PromptGroupOptions<T>): Promise<PromptGroupAwaitedReturn<T>> => {
369369+ const results = {} as any;
370370+ const promptNames = Object.keys(prompts);
371371+372372+ for (const name of promptNames) {
373373+ const result = await prompts[name as keyof T]({ results }).catch((e) => { throw e });
374374+375375+ // Pass the results to the onCancel function
376376+ // so the user can decide what to do with the results
377377+ // TODO: Switch to callback within core to avoid isCancel Fn
378378+ if (typeof opts?.onCancel === 'function' && isCancel(result)) {
379379+ results[name] = "canceled";
380380+ opts.onCancel({ results });
381381+ continue;
382382+ }
383383+384384+ results[name] = result;
385385+ }
386386+387387+ return results;
388388+}