// cli-ui/prompts.ts — thin wrappers around @inquirer/prompts with two
// conveniences the underlying library doesn't bake in:
//
//   1. A standardized "← Back" choice that callers can detect by the
//      sentinel return value `BACK`. This lets loops at any level handle
//      navigation without each call site reaching into the prompt API.
//   2. Graceful exit on Ctrl-C — inquirer throws `ExitPromptError`; we
//      catch + re-throw as our own `UserAbortError` so callers can decide
//      whether to exit (top-level) or treat as Back (nested).
import { select, checkbox, input, password, confirm, Separator, } from '@inquirer/prompts';
import { t } from './i18n.js';
export const BACK = Symbol('back');
export class UserAbortError extends Error {
    constructor() {
        super('User pressed Ctrl-C');
        this.name = 'UserAbortError';
    }
}
function rethrowAbort(err) {
    if (err && typeof err === 'object' && 'name' in err && err.name === 'ExitPromptError') {
        throw new UserAbortError();
    }
    throw err;
}
/**
 * Single-choice menu with arrow keys + Enter. If `back` is provided
 * (a key from i18n.ts pointing at a `← Back`-style string), an extra
 * back entry is appended; picking it returns the BACK sentinel.
 */
export async function menu(opts) {
    const choices = [];
    for (const c of opts.choices) {
        if (c.separatorBefore) {
            // Statically imported above. require() doesn't exist in ESM modules,
            // so an earlier lazy-import attempt crashed at runtime.
            choices.push(new Separator());
        }
        choices.push({
            value: c.value,
            name: c.name,
            description: c.description,
            disabled: c.disabled,
        });
    }
    if (opts.back) {
        choices.push({ value: BACK, name: t(opts.lang, opts.back) });
    }
    try {
        return await select({
            message: opts.message,
            choices: choices,
            default: opts.default,
            loop: false,
        });
    }
    catch (err) {
        rethrowAbort(err);
    }
}
/**
 * Multi-select with Space to toggle. Always returns an array (possibly
 * empty). No back option — typical usage is "pick which IMs to enable";
 * cancel is via Ctrl-C → UserAbortError.
 */
export async function multiSelect(opts) {
    try {
        return await checkbox({
            message: opts.message,
            choices: opts.choices,
            required: opts.required ?? false,
            loop: false,
        });
    }
    catch (err) {
        rethrowAbort(err);
    }
}
/** Free-text input with optional default + validator. */
export async function inputText(opts) {
    try {
        return await input({
            message: opts.message,
            default: opts.default,
            validate: (v) => {
                if (opts.required && !v.trim())
                    return 'Required';
                if (opts.validate)
                    return opts.validate(v);
                return true;
            },
        });
    }
    catch (err) {
        rethrowAbort(err);
    }
}
/** Hidden input for secrets (no echo). */
export async function inputSecret(opts) {
    try {
        return await password({
            message: opts.message,
            mask: '*',
            validate: (v) => {
                if (opts.required && !v)
                    return 'Required';
                if (opts.validate)
                    return opts.validate(v);
                return true;
            },
        });
    }
    catch (err) {
        rethrowAbort(err);
    }
}
/** Yes/no with arrow-key navigation. */
export async function yesNo(opts) {
    try {
        return await confirm({ message: opts.message, default: opts.default ?? false });
    }
    catch (err) {
        rethrowAbort(err);
    }
}
//# sourceMappingURL=prompts.js.map