inquirer-ts-checkbox-plus-prompt
Version:
Checkbox with autocomplete and other additions for Inquirer
274 lines (267 loc) • 10.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var chalk = require('chalk');
var cliCursor = require('cli-cursor');
var figures = require('figures');
var Choices = require('inquirer/lib/objects/choices');
var Base = require('inquirer/lib/prompts/base');
var observe = require('inquirer/lib/utils/events');
var Paginator = require('inquirer/lib/utils/paginator');
var operators = require('rxjs/operators');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
var cliCursor__default = /*#__PURE__*/_interopDefaultLegacy(cliCursor);
var figures__default = /*#__PURE__*/_interopDefaultLegacy(figures);
var Choices__default = /*#__PURE__*/_interopDefaultLegacy(Choices);
var Base__default = /*#__PURE__*/_interopDefaultLegacy(Base);
var observe__default = /*#__PURE__*/_interopDefaultLegacy(observe);
var Paginator__default = /*#__PURE__*/_interopDefaultLegacy(Paginator);
class CheckboxPlusPrompt extends Base__default["default"] {
constructor(questions, rl, answers) {
super(questions, rl, answers);
this.pointer = 0;
if (this.opt.highlight == null) {
this.opt.highlight = false;
}
if (typeof this.opt.searchable == null) {
this.opt.searchable = false;
}
if (typeof this.opt.default == null) {
this.opt.default = undefined;
}
if (this.opt.source == null) {
this.throwParamError('source');
}
this.pointer = 0;
this.firstSourceLoading = true;
this.choices = new Choices__default["default"]([], answers);
this.checkedChoices = [];
this.value = [];
this.lastQuery = undefined;
this.searching = false;
this.lastSourcePromise = undefined;
this.default = this.opt.default;
this.opt.default = undefined;
this.selection = [];
this.done = undefined;
this.paginator = new Paginator__default["default"](this.screen);
}
_run(callback) {
this.done = callback;
this.executeSource().then(() => {
const events = observe__default["default"](this.rl);
const validation = this.handleSubmitEvents(events.line.pipe(operators.map(this.getCurrentValue.bind(this))));
validation.success.forEach(this.onEnd.bind(this));
validation.error.forEach(this.onError.bind(this));
events.normalizedUpKey.pipe(operators.takeUntil(validation.success)).forEach(this.onUpKey.bind(this));
events.normalizedDownKey
.pipe(operators.takeUntil(validation.success))
.forEach(this.onDownKey.bind(this));
events.spaceKey.pipe(operators.takeUntil(validation.success)).forEach(this.onSpaceKey.bind(this));
if (this.opt.searchable === false) {
events.numberKey.pipe(operators.takeUntil(validation.success)).forEach(this.onNumberKey.bind(this));
events.aKey.pipe(operators.takeUntil(validation.success)).forEach(this.onAllKey.bind(this));
events.iKey.pipe(operators.takeUntil(validation.success)).forEach(this.onInverseKey.bind(this));
}
else {
events.keypress.pipe(operators.takeUntil(validation.success)).forEach(this.onKeypress.bind(this));
}
if (this.rl.line) {
this.onKeypress();
}
cliCursor__default["default"].hide();
this.render();
});
return this;
}
getValue(choice) {
if (choice.type === 'separator') {
return undefined;
}
return choice.value;
}
executeSource() {
let sourcePromise;
this.rl.line = this.rl.line.trim();
if (this.rl.line === this.lastQuery) {
return Promise.resolve(undefined);
}
if (this.opt.searchable) {
sourcePromise = this.opt.source(this.answers, this.rl.line);
}
else {
sourcePromise = this.opt.source(this.answers, undefined);
}
this.lastQuery = this.rl.line;
this.lastSourcePromise = sourcePromise;
this.searching = true;
sourcePromise.then((choices) => {
if (this.lastSourcePromise !== sourcePromise) {
return;
}
this.searching = false;
this.choices = new Choices__default["default"](choices, this.answers);
this.choices.forEach((choice) => {
if (this.value.some((eachValue) => this.getValue(choice) === eachValue)) {
this.toggleChoice(choice, true);
}
else {
this.toggleChoice(choice, false);
}
if (this.default != null) {
if (this.default.some((defaultValue) => this.getValue(choice) === defaultValue)) {
this.toggleChoice(choice, true);
}
}
});
this.pointer = 0;
this.render();
this.default = undefined;
this.firstSourceLoading = false;
});
return sourcePromise;
}
render(error) {
let message = this.getQuestion();
let bottomContent = '';
if (this.status === 'answered') {
message += chalk__default["default"].cyan(this.selection.join(', '));
return this.screen.render(message, bottomContent);
}
if (this.firstSourceLoading) {
if (this.opt.searchable) {
message += `(Press ${chalk__default["default"].cyan.bold('<space>')} to select, or type anything to filter the list)`;
}
else {
message += `(Press ${chalk__default["default"].cyan.bold('<space>')} to select, ${chalk__default["default"].cyan.bold('<a>')} to toggle all, ${chalk__default["default"].cyan.bold('<i>')} to invert selection)`;
}
}
if (this.opt.searchable) {
message += this.rl.line;
}
if (this.searching) {
message += `\n ${chalk__default["default"].cyan('Searching...')}`;
}
else if (!this.choices.length) {
message += `\n ${chalk__default["default"].yellow('No results...')}`;
}
else {
const choicesStr = this.renderChoices(this.choices, this.pointer);
const choice = this.choices.getChoice(this.pointer);
const indexPosition = this.choices.indexOf(choice);
message += `\n${this.paginator.paginate(choicesStr, indexPosition, this.opt.pageSize)}`;
}
if (error) {
bottomContent = chalk__default["default"].red('>> ') + error;
}
return this.screen.render(message, bottomContent);
}
onEnd(state) {
this.status = 'answered';
this.render();
this.screen.done();
cliCursor__default["default"].show();
this.done?.('value' in state ? state.value : undefined);
}
onError(state) {
this.render(state.isValid);
}
getCurrentValue() {
this.selection = this.checkedChoices.map((checkedChoice) => checkedChoice.short);
const values = this.checkedChoices.map((checkedChoice) => checkedChoice.value);
return values;
}
onUpKey() {
const len = this.choices.realLength;
this.pointer = this.pointer > 0 ? this.pointer - 1 : len - 1;
this.render();
}
onDownKey() {
const len = this.choices.realLength;
this.pointer = this.pointer < len - 1 ? this.pointer + 1 : 0;
this.render();
}
onNumberKey(input) {
if (input <= this.choices.realLength) {
this.pointer = input - 1;
this.toggleChoice(this.choices.getChoice(this.pointer));
}
this.render();
}
onSpaceKey() {
if (this.choices.getChoice(this.pointer) == null) {
return;
}
this.toggleChoice(this.choices.getChoice(this.pointer));
this.render();
}
onAllKey() {
const shouldBeChecked = Boolean(this.choices.find((choice) => {
return choice.type !== 'separator' && !choice.checked;
}));
this.choices.forEach((choice) => {
if (choice.type !== 'separator') {
choice.checked = shouldBeChecked;
}
return choice;
});
this.render();
}
onInverseKey() {
this.choices.forEach((choice) => {
if (choice.type !== 'separator') {
choice.checked = !choice.checked;
}
});
this.render();
}
onKeypress() {
this.executeSource();
this.render();
}
toggleChoice(choice, nextChecked) {
if (choice.type === 'separator') {
return;
}
const checked = nextChecked == null ? !(choice.checked ?? false) : nextChecked;
this.value = this.value.filter((eachValue) => eachValue !== choice.value);
this.checkedChoices = this.checkedChoices.filter((checkedChoice) => checkedChoice.value !== choice.value);
choice.checked = false;
if (checked === true) {
this.value.push(choice.value);
this.checkedChoices.push(choice);
choice.checked = true;
}
}
static getCheckboxFigure(checked = false) {
return checked ? chalk__default["default"].green(figures__default["default"].radioOn) : figures__default["default"].radioOff;
}
renderChoices(choices, pointer) {
const output = [];
let separatorOffset = 0;
choices.forEach((choice, index) => {
if (choice.type === 'separator') {
separatorOffset += 1;
output.push(` ${choice}\n`);
return;
}
if (choice.disabled) {
separatorOffset += 1;
output.push(` - ${choice.name} (${typeof choice.disabled === 'string' ? choice.disabled : 'Disabled'})\n`);
return;
}
if (index - separatorOffset === pointer) {
output.push(chalk__default["default"].cyan(figures__default["default"].pointer));
output.push(CheckboxPlusPrompt.getCheckboxFigure(choice.checked));
output.push(' ');
output.push(this.opt.highlight ? chalk__default["default"].gray(choice.name) : choice.name);
}
else {
output.push(` ${CheckboxPlusPrompt.getCheckboxFigure(choice.checked)} ${choice.name}`);
}
output.push('\n');
});
return output.join('').replace(/\n$/, '');
}
}
exports.CheckboxPlusPrompt = CheckboxPlusPrompt;