Skip to main content
Module

x/cliffy/prompt/checkbox.ts

Command line framework for deno 🦕 Including Commandline-Interfaces, Prompts, CLI-Table, Arguments Parser and more...
Extremely Popular
Go to Latest
File
import type { KeyCode } from "../keycode/mod.ts";import { blue, dim, green, red, yellow } from "./deps.ts";import { Figures } from "./figures.ts";import { GenericList, GenericListKeys, GenericListOption, GenericListOptions, GenericListOptionSettings, GenericListSettings,} from "./_generic_list.ts";import { GenericPrompt } from "./_generic_prompt.ts";
/** Checkbox key options. */export interface CheckboxKeys extends GenericListKeys { check?: string[];}
/** Checkbox option options. */export interface CheckboxOption extends GenericListOption { checked?: boolean; icon?: boolean;}
/** Checkbox option settings. */export interface CheckboxOptionSettings extends GenericListOptionSettings { checked: boolean; icon: boolean;}
/** Checkbox options type. */export type CheckboxValueOptions = (string | CheckboxOption)[];/** Checkbox option settings type. */export type CheckboxValueSettings = CheckboxOptionSettings[];
/** Checkbox prompt options. */export interface CheckboxOptions extends GenericListOptions<string[], string[]> { options: CheckboxValueOptions; check?: string; uncheck?: string; minOptions?: number; maxOptions?: number; keys?: CheckboxKeys;}
/** Checkbox prompt settings. */interface CheckboxSettings extends GenericListSettings<string[], string[]> { options: CheckboxValueSettings; check: string; uncheck: string; minOptions: number; maxOptions: number; keys?: CheckboxKeys;}
/** Checkbox prompt representation. */export class Checkbox extends GenericList<string[], string[], CheckboxSettings> { /** * Inject prompt value. Can be used for unit tests or pre selections. * @param value Array of input values. */ public static inject(value: string[]): void { GenericPrompt.inject(value); }
/** Execute the prompt and show cursor on end. */ public static prompt(options: CheckboxOptions): Promise<string[]> { return new this({ pointer: blue(Figures.POINTER_SMALL), prefix: yellow("? "), indent: " ", listPointer: blue(Figures.POINTER), maxRows: 10, searchLabel: blue(Figures.SEARCH), minOptions: 0, maxOptions: Infinity, check: green(Figures.TICK), uncheck: red(Figures.CROSS), ...options, keys: { check: ["space"], ...(options.keys ?? {}), }, options: Checkbox.mapOptions(options), }).prompt(); }
/** * Create list separator. * @param label Separator label. */ public static separator(label?: string): CheckboxOption { return { ...super.separator(label), icon: false, }; }
/** * Map string option values to options and set option defaults. * @param options Checkbox options. */ protected static mapOptions(options: CheckboxOptions): CheckboxValueSettings { return options.options .map((item: string | CheckboxOption) => typeof item === "string" ? { value: item } : item ) .map((item) => ({ ...this.mapOption(item), checked: typeof item.checked === "undefined" && options.default && options.default.indexOf(item.value) !== -1 ? true : !!item.checked, icon: typeof item.icon === "undefined" ? true : item.icon, })); }
/** * Render checkbox option. * @param item Checkbox option settings. * @param isSelected Set to true if option is selected. */ protected getListItem( item: CheckboxOptionSettings, isSelected?: boolean, ): string { let line = this.settings.indent;
// pointer line += isSelected ? this.settings.listPointer + " " : " ";
// icon if (item.icon) { let check = item.checked ? this.settings.check + " " : this.settings.uncheck + " "; if (item.disabled) { check = dim(check); } line += check; } else { line += " "; }
// value line += `${ isSelected && !item.disabled ? this.highlight(item.name, (val) => val) : this.highlight(item.name) }`;
return line; }
/** Get value of checked options. */ protected getValue(): string[] { return this.settings.options .filter((item) => item.checked) .map((item) => item.value); }
/** * Handle user input event. * @param event Key event. */ protected async handleEvent(event: KeyCode): Promise<void> { switch (true) { case this.isKey(this.settings.keys, "check", event): this.checkValue(); break; default: await super.handleEvent(event); } }
/** Check selected option. */ protected checkValue(): void { const item = this.options[this.listIndex]; if (item.disabled) { this.setErrorMessage("This option is disabled and cannot be changed."); } else { item.checked = !item.checked; } }
/** * Validate input value. * @param value User input value. * @return True on success, false or error message on error. */ protected validate(value: string[]): boolean | string { const isValidValue = Array.isArray(value) && value.every((val) => typeof val === "string" && val.length > 0 && this.settings.options.findIndex((option: CheckboxOptionSettings) => option.value === val ) !== -1 );
if (!isValidValue) { return false; }
if (value.length < this.settings.minOptions) { return `The minimum number of options is ${this.settings.minOptions} but got ${value.length}.`; } if (value.length > this.settings.maxOptions) { return `The maximum number of options is ${this.settings.maxOptions} but got ${value.length}.`; }
return true; }
/** * Map input value to output value. * @param value Input value. * @return Output value. */ protected transform(value: string[]): string[] { return value.map((val) => val.trim()); }
/** * Format output value. * @param value Output value. */ protected format(value: string[]): string { return value.map((val) => this.getOptionByValue(val)?.name ?? val) .join(", "); }}