@topcli/prompts 2.0.0 → 2.2.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.
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2023-2024 TopCli
1
+ Copyright 2023-2025 TopCli
2
2
 
3
3
  Permission to use, copy, modify, and/or distribute this software for any purpose
4
4
  with or without fee is hereby granted, provided that the above copyright notice
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
 
13
13
  ## Requirements
14
- - [Node.js](https://nodejs.org/en/) v18 or higher
14
+ - [Node.js](https://nodejs.org/en/) v20 or higher
15
15
 
16
16
  ## Getting Started
17
17
 
@@ -53,12 +53,16 @@ question(message: string, options?: PromptOptions): Promise<string>
53
53
 
54
54
  Simple prompt, similar to `rl.question()` with an improved UI.
55
55
 
56
+ Use `options.defaultValue` to set a default value.
57
+
56
58
  Use `options.secure` if you need to hide both input and answer.
57
59
 
58
60
  Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
59
61
 
60
62
  Use `options.validators` to handle user input.
61
63
 
64
+ Use `options.skip` to skip prompt. It will return `options.defaultValue` if given, `""` otherwise.
65
+
62
66
  **Example**
63
67
 
64
68
  ```js
@@ -95,35 +99,39 @@ select(message: string, options: SelectOptions): Promise<string>
95
99
 
96
100
  Scrollable select depending `maxVisible` (default `8`).
97
101
 
98
- Use `ignoreValues` to skip result render & clear lines after a selected one.
102
+ Use `options.ignoreValues` to skip result render & clear lines after a selected one.
99
103
 
100
- Use `validators` to handle user input.
104
+ Use `options.validators` to handle user input.
101
105
 
102
- Use `autocomplete` to allow filtered choices. This can be useful for a large list of choices.
106
+ Use `options.autocomplete` to allow filtered choices. This can be useful for a large list of choices.
103
107
 
104
- Use `caseSensitive` to make autocomplete filters case sensitive. Default `false`
108
+ Use `options.caseSensitive` to make autocomplete filters case sensitive. Default `false`
105
109
 
106
110
  Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
107
111
 
112
+ Use `options.skip` to skip prompt. It will return the first choice.
113
+
108
114
  ### `multiselect()`
109
115
 
110
116
  ```ts
111
117
  multiselect(message: string, options: MultiselectOptions): Promise<[string]>
112
118
  ```
113
119
 
114
- Scrollable multiselect depending `maxVisible` (default `8`).<br>
115
- Use `preSelectedChoices` to pre-select choices.
120
+ Scrollable multiselect depending `options.maxVisible` (default `8`).<br>
121
+ Use `options.preSelectedChoices` to pre-select choices.
116
122
 
117
- Use `validators` to handle user input.
123
+ Use `options.validators` to handle user input.
118
124
 
119
- Use `showHint: false` to disable hint (this option is truthy by default).
125
+ Use `options.showHint: false` to disable hint (this option is truthy by default).
120
126
 
121
- Use `autocomplete` to allow filtered choices. This can be useful for a large list of choices.
127
+ Use `options.autocomplete` to allow filtered choices. This can be useful for a large list of choices.
122
128
 
123
- Use `caseSensitive` to make autocomplete filters case sensitive. Default `false`.
129
+ Use `options.caseSensitive` to make autocomplete filters case sensitive. Default `false`.
124
130
 
125
131
  Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
126
132
 
133
+ Use `options.skip` to skip prompt. It will return `options.preSelectedChoices` if given, `[]` otherwise.
134
+
127
135
  ### `confirm()`
128
136
 
129
137
  ```ts
@@ -137,6 +145,8 @@ Boolean prompt, default to `options.initial` (`false`).
137
145
 
138
146
  Use `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).
139
147
 
148
+ Use `options.skip` to skip prompt. It will return `options.initial` (`false` by default)
149
+
140
150
  ### `PromptAgent`
141
151
 
142
152
  The `PromptAgent` class allows to programmatically set the next answers for any prompt function, this can be useful for testing.
package/dist/index.cjs CHANGED
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // index.ts
31
- var prompts_exports = {};
32
- __export(prompts_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
33
  PromptAgent: () => PromptAgent,
34
34
  confirm: () => confirm,
35
35
  multiselect: () => multiselect,
@@ -37,7 +37,7 @@ __export(prompts_exports, {
37
37
  required: () => required,
38
38
  select: () => select
39
39
  });
40
- module.exports = __toCommonJS(prompts_exports);
40
+ module.exports = __toCommonJS(index_exports);
41
41
 
42
42
  // src/prompts/question.ts
43
43
  var import_node_os2 = require("os");
@@ -46,7 +46,7 @@ var import_wcwidth = __toESM(require("@topcli/wcwidth"), 1);
46
46
 
47
47
  // src/prompts/abstract.ts
48
48
  var import_node_os = require("os");
49
- var import_node_readline = require("readline");
49
+ var import_node_readline = __toESM(require("readline"), 1);
50
50
  var import_node_stream = require("stream");
51
51
  var import_node_events = __toESM(require("events"), 1);
52
52
 
@@ -128,6 +128,7 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
128
128
  stdout;
129
129
  message;
130
130
  signal;
131
+ skip;
131
132
  history;
132
133
  agent;
133
134
  mute;
@@ -142,7 +143,8 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
142
143
  stdin: input = process.stdin,
143
144
  stdout: output = process.stdout,
144
145
  message,
145
- signal
146
+ signal,
147
+ skip = false
146
148
  } = options;
147
149
  if (typeof message !== "string") {
148
150
  throw new TypeError(`message must be string, ${typeof message} given.`);
@@ -157,13 +159,14 @@ var AbstractPrompt = class _AbstractPrompt extends import_node_events.default {
157
159
  this.stdout = output;
158
160
  this.message = message;
159
161
  this.signal = signal;
162
+ this.skip = skip;
160
163
  this.history = [];
161
164
  this.agent = PromptAgent.agent();
162
165
  this.mute = false;
163
166
  if (this.stdout.isTTY) {
164
167
  this.stdin.setRawMode(true);
165
168
  }
166
- this.rl = (0, import_node_readline.createInterface)({
169
+ this.rl = import_node_readline.default.createInterface({
167
170
  input,
168
171
  output: new import_node_stream.Writable({
169
172
  write: (chunk, encoding, callback) => {
@@ -340,7 +343,11 @@ var QuestionPrompt = class extends AbstractPrompt {
340
343
  this.answerBuffer = void 0;
341
344
  this.#writeAnswer();
342
345
  }
343
- question() {
346
+ async question() {
347
+ if (this.skip) {
348
+ this.destroy();
349
+ return this.defaultValue ?? "";
350
+ }
344
351
  return new Promise(async (resolve, reject) => {
345
352
  this.answer = this.agent.nextAnswers.shift();
346
353
  if (this.answer !== void 0) {
@@ -417,7 +424,7 @@ var ConfirmPrompt = class extends AbstractPrompt {
417
424
  process.once("exit", this.#boundExitEvent);
418
425
  });
419
426
  }
420
- #onKeypress(resolve, value, key) {
427
+ #onKeypress(resolve, _value, key) {
421
428
  this.stdout.moveCursor(
422
429
  -this.stdout.columns,
423
430
  -Math.floor((0, import_wcwidth2.default)(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns)
@@ -459,7 +466,11 @@ var ConfirmPrompt = class extends AbstractPrompt {
459
466
  this.stdout.clearScreenDown();
460
467
  this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${(0, import_node_util3.styleText)("bold", this.message)}${import_node_os3.EOL}`);
461
468
  }
462
- confirm() {
469
+ async confirm() {
470
+ if (this.skip) {
471
+ this.destroy();
472
+ return this.initial;
473
+ }
463
474
  return new Promise(async (resolve, reject) => {
464
475
  const answer = this.agent.nextAnswers.shift();
465
476
  if (answer !== void 0) {
@@ -653,7 +664,12 @@ var SelectPrompt = class extends AbstractPrompt {
653
664
  render();
654
665
  }
655
666
  }
656
- select() {
667
+ async select() {
668
+ if (this.skip) {
669
+ this.destroy();
670
+ const answer = this.options.choices[0];
671
+ return typeof answer === "string" ? answer : answer.value;
672
+ }
657
673
  return new Promise((resolve, reject) => {
658
674
  const answer = this.agent.nextAnswers.shift();
659
675
  if (answer !== void 0) {
@@ -773,7 +789,7 @@ var MultiselectPrompt = class extends AbstractPrompt {
773
789
  constructor(options) {
774
790
  const {
775
791
  choices,
776
- preSelectedChoices,
792
+ preSelectedChoices = [],
777
793
  validators = [],
778
794
  showHint = true,
779
795
  ...baseOptions
@@ -797,9 +813,6 @@ var MultiselectPrompt = class extends AbstractPrompt {
797
813
  }
798
814
  }
799
815
  }
800
- if (!preSelectedChoices) {
801
- return;
802
- }
803
816
  for (const choice of preSelectedChoices) {
804
817
  const choiceIndex = this.filteredChoices.findIndex((item) => {
805
818
  if (typeof item === "string") {
@@ -864,6 +877,25 @@ var MultiselectPrompt = class extends AbstractPrompt {
864
877
  const formattedChoice = (0, import_node_util5.styleText)("yellow", choices);
865
878
  this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${import_node_os5.EOL}`);
866
879
  }
880
+ #selectedChoices() {
881
+ return [...this.selectedIndexes].reduce(
882
+ (acc, index) => {
883
+ const choice = this.filteredChoices[index];
884
+ if (typeof choice === "string") {
885
+ acc.values.push(choice);
886
+ acc.labels.push(choice);
887
+ } else {
888
+ acc.values.push(choice.value);
889
+ acc.labels.push(choice.label);
890
+ }
891
+ return acc;
892
+ },
893
+ {
894
+ values: [],
895
+ labels: []
896
+ }
897
+ );
898
+ }
867
899
  #onProcessExit() {
868
900
  this.stdin.off("keypress", this.#boundKeyPressEvent);
869
901
  this.stdout.moveCursor(-this.stdout.columns, 0);
@@ -888,14 +920,7 @@ var MultiselectPrompt = class extends AbstractPrompt {
888
920
  this.selectedIndexes = new Set([...this.selectedIndexes].filter((index) => index !== this.activeIndex));
889
921
  render();
890
922
  } else if (key.name === "return") {
891
- const labels = [...this.selectedIndexes].map((index) => {
892
- const choice = this.filteredChoices[index];
893
- return typeof choice === "string" ? choice : choice.label;
894
- });
895
- const values = [...this.selectedIndexes].map((index) => {
896
- const choice = this.filteredChoices[index];
897
- return typeof choice === "string" ? choice : choice.value;
898
- });
923
+ const { values, labels } = this.#selectedChoices();
899
924
  for (const validator of this.#validators) {
900
925
  const validationResult = validator.validate(values);
901
926
  if (isValid(validationResult) === false) {
@@ -923,7 +948,12 @@ var MultiselectPrompt = class extends AbstractPrompt {
923
948
  render();
924
949
  }
925
950
  }
926
- multiselect() {
951
+ async multiselect() {
952
+ if (this.skip) {
953
+ this.destroy();
954
+ const { values } = this.#selectedChoices();
955
+ return values;
956
+ }
927
957
  return new Promise((resolve, reject) => {
928
958
  const answer = this.agent.nextAnswers.shift();
929
959
  if (answer !== void 0) {
@@ -998,18 +1028,18 @@ var MultiselectPrompt = class extends AbstractPrompt {
998
1028
  };
999
1029
 
1000
1030
  // index.ts
1001
- async function question(message, options = {}) {
1031
+ function question(message, options = {}) {
1002
1032
  return new QuestionPrompt({ ...options, message }).question();
1003
1033
  }
1004
- async function select(message, options) {
1034
+ function select(message, options) {
1005
1035
  const selectPrompt = new SelectPrompt({ ...options, message });
1006
1036
  return selectPrompt.select();
1007
1037
  }
1008
- async function confirm(message, options = {}) {
1038
+ function confirm(message, options = {}) {
1009
1039
  const confirmPrompt = new ConfirmPrompt({ ...options, message });
1010
1040
  return confirmPrompt.confirm();
1011
1041
  }
1012
- async function multiselect(message, options) {
1042
+ function multiselect(message, options) {
1013
1043
  const multiselectPrompt = new MultiselectPrompt({ ...options, message });
1014
1044
  return multiselectPrompt.multiselect();
1015
1045
  }
package/dist/index.d.cts CHANGED
@@ -49,6 +49,7 @@ interface AbstractPromptOptions {
49
49
  stdin?: Stdin;
50
50
  stdout?: Stdout;
51
51
  message: string;
52
+ skip?: boolean;
52
53
  signal?: AbortSignal;
53
54
  }
54
55
 
@@ -68,8 +69,8 @@ interface ConfirmOptions extends AbstractPromptOptions {
68
69
  initial?: boolean;
69
70
  }
70
71
 
71
- interface MultiselectOptions extends AbstractPromptOptions {
72
- choices: (Choice | string)[];
72
+ interface MultiselectOptions<T extends string = string> extends AbstractPromptOptions {
73
+ choices: (Choice | T)[];
73
74
  maxVisible?: number;
74
75
  preSelectedChoices?: (Choice | string)[];
75
76
  validators?: PromptValidator[];
@@ -78,8 +79,8 @@ interface MultiselectOptions extends AbstractPromptOptions {
78
79
  showHint?: boolean;
79
80
  }
80
81
 
81
- interface SelectOptions extends AbstractPromptOptions {
82
- choices: (Choice | string)[];
82
+ interface SelectOptions<T extends string = string> extends AbstractPromptOptions {
83
+ choices: (Choice | T)[];
83
84
  maxVisible?: number;
84
85
  ignoreValues?: (string | number | boolean)[];
85
86
  validators?: PromptValidator[];
@@ -88,8 +89,8 @@ interface SelectOptions extends AbstractPromptOptions {
88
89
  }
89
90
 
90
91
  declare function question(message: string, options?: Omit<QuestionOptions, "message">): Promise<string>;
91
- declare function select(message: string, options: Omit<SelectOptions, "message">): Promise<string>;
92
+ declare function select<T extends string>(message: string, options: Omit<SelectOptions<T>, "message">): Promise<T>;
92
93
  declare function confirm(message: string, options?: Omit<ConfirmOptions, "message">): Promise<boolean>;
93
- declare function multiselect(message: string, options: Omit<MultiselectOptions, "message">): Promise<string[]>;
94
+ declare function multiselect<T extends string>(message: string, options: Omit<MultiselectOptions<T>, "message">): Promise<T[]>;
94
95
 
95
96
  export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, confirm, multiselect, question, required, select };
package/dist/index.d.ts CHANGED
@@ -49,6 +49,7 @@ interface AbstractPromptOptions {
49
49
  stdin?: Stdin;
50
50
  stdout?: Stdout;
51
51
  message: string;
52
+ skip?: boolean;
52
53
  signal?: AbortSignal;
53
54
  }
54
55
 
@@ -68,8 +69,8 @@ interface ConfirmOptions extends AbstractPromptOptions {
68
69
  initial?: boolean;
69
70
  }
70
71
 
71
- interface MultiselectOptions extends AbstractPromptOptions {
72
- choices: (Choice | string)[];
72
+ interface MultiselectOptions<T extends string = string> extends AbstractPromptOptions {
73
+ choices: (Choice | T)[];
73
74
  maxVisible?: number;
74
75
  preSelectedChoices?: (Choice | string)[];
75
76
  validators?: PromptValidator[];
@@ -78,8 +79,8 @@ interface MultiselectOptions extends AbstractPromptOptions {
78
79
  showHint?: boolean;
79
80
  }
80
81
 
81
- interface SelectOptions extends AbstractPromptOptions {
82
- choices: (Choice | string)[];
82
+ interface SelectOptions<T extends string = string> extends AbstractPromptOptions {
83
+ choices: (Choice | T)[];
83
84
  maxVisible?: number;
84
85
  ignoreValues?: (string | number | boolean)[];
85
86
  validators?: PromptValidator[];
@@ -88,8 +89,8 @@ interface SelectOptions extends AbstractPromptOptions {
88
89
  }
89
90
 
90
91
  declare function question(message: string, options?: Omit<QuestionOptions, "message">): Promise<string>;
91
- declare function select(message: string, options: Omit<SelectOptions, "message">): Promise<string>;
92
+ declare function select<T extends string>(message: string, options: Omit<SelectOptions<T>, "message">): Promise<T>;
92
93
  declare function confirm(message: string, options?: Omit<ConfirmOptions, "message">): Promise<boolean>;
93
- declare function multiselect(message: string, options: Omit<MultiselectOptions, "message">): Promise<string[]>;
94
+ declare function multiselect<T extends string>(message: string, options: Omit<MultiselectOptions<T>, "message">): Promise<T[]>;
94
95
 
95
96
  export { type AbstractPromptOptions, type Choice, type ConfirmOptions, type MultiselectOptions, PromptAgent, type PromptValidator, type QuestionOptions, type SelectOptions, confirm, multiselect, question, required, select };
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  // src/prompts/question.ts
2
- import { EOL as EOL2 } from "os";
3
- import { styleText as styleText2 } from "util";
2
+ import { EOL as EOL2 } from "node:os";
3
+ import { styleText as styleText2 } from "node:util";
4
4
  import wcwidth from "@topcli/wcwidth";
5
5
 
6
6
  // src/prompts/abstract.ts
7
- import { EOL } from "os";
8
- import { createInterface } from "readline";
9
- import { Writable } from "stream";
10
- import EventEmitter from "events";
7
+ import { EOL } from "node:os";
8
+ import readline from "node:readline";
9
+ import { Writable } from "node:stream";
10
+ import EventEmitter from "node:events";
11
11
 
12
12
  // src/utils.ts
13
- import process2 from "process";
13
+ import process2 from "node:process";
14
14
  var kAnsiRegex = ansiRegex();
15
15
  function ansiRegex({ onlyFirst = false } = {}) {
16
16
  const pattern = [
@@ -87,6 +87,7 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
87
87
  stdout;
88
88
  message;
89
89
  signal;
90
+ skip;
90
91
  history;
91
92
  agent;
92
93
  mute;
@@ -101,7 +102,8 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
101
102
  stdin: input = process.stdin,
102
103
  stdout: output = process.stdout,
103
104
  message,
104
- signal
105
+ signal,
106
+ skip = false
105
107
  } = options;
106
108
  if (typeof message !== "string") {
107
109
  throw new TypeError(`message must be string, ${typeof message} given.`);
@@ -116,13 +118,14 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
116
118
  this.stdout = output;
117
119
  this.message = message;
118
120
  this.signal = signal;
121
+ this.skip = skip;
119
122
  this.history = [];
120
123
  this.agent = PromptAgent.agent();
121
124
  this.mute = false;
122
125
  if (this.stdout.isTTY) {
123
126
  this.stdin.setRawMode(true);
124
127
  }
125
- this.rl = createInterface({
128
+ this.rl = readline.createInterface({
126
129
  input,
127
130
  output: new Writable({
128
131
  write: (chunk, encoding, callback) => {
@@ -173,7 +176,7 @@ var AbstractPrompt = class _AbstractPrompt extends EventEmitter {
173
176
  };
174
177
 
175
178
  // src/constants.ts
176
- import { styleText } from "util";
179
+ import { styleText } from "node:util";
177
180
  var kMainSymbols = {
178
181
  tick: "\u2714",
179
182
  cross: "\u2716",
@@ -299,7 +302,11 @@ var QuestionPrompt = class extends AbstractPrompt {
299
302
  this.answerBuffer = void 0;
300
303
  this.#writeAnswer();
301
304
  }
302
- question() {
305
+ async question() {
306
+ if (this.skip) {
307
+ this.destroy();
308
+ return this.defaultValue ?? "";
309
+ }
303
310
  return new Promise(async (resolve, reject) => {
304
311
  this.answer = this.agent.nextAnswers.shift();
305
312
  if (this.answer !== void 0) {
@@ -327,8 +334,8 @@ var QuestionPrompt = class extends AbstractPrompt {
327
334
  };
328
335
 
329
336
  // src/prompts/confirm.ts
330
- import { EOL as EOL3 } from "os";
331
- import { styleText as styleText3 } from "util";
337
+ import { EOL as EOL3 } from "node:os";
338
+ import { styleText as styleText3 } from "node:util";
332
339
  import wcwidth2 from "@topcli/wcwidth";
333
340
  var kToggleKeys = /* @__PURE__ */ new Set([
334
341
  "left",
@@ -376,7 +383,7 @@ var ConfirmPrompt = class extends AbstractPrompt {
376
383
  process.once("exit", this.#boundExitEvent);
377
384
  });
378
385
  }
379
- #onKeypress(resolve, value, key) {
386
+ #onKeypress(resolve, _value, key) {
380
387
  this.stdout.moveCursor(
381
388
  -this.stdout.columns,
382
389
  -Math.floor(wcwidth2(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns)
@@ -418,7 +425,11 @@ var ConfirmPrompt = class extends AbstractPrompt {
418
425
  this.stdout.clearScreenDown();
419
426
  this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${styleText3("bold", this.message)}${EOL3}`);
420
427
  }
421
- confirm() {
428
+ async confirm() {
429
+ if (this.skip) {
430
+ this.destroy();
431
+ return this.initial;
432
+ }
422
433
  return new Promise(async (resolve, reject) => {
423
434
  const answer = this.agent.nextAnswers.shift();
424
435
  if (answer !== void 0) {
@@ -447,8 +458,8 @@ var ConfirmPrompt = class extends AbstractPrompt {
447
458
  };
448
459
 
449
460
  // src/prompts/select.ts
450
- import { EOL as EOL4 } from "os";
451
- import { styleText as styleText4 } from "util";
461
+ import { EOL as EOL4 } from "node:os";
462
+ import { styleText as styleText4 } from "node:util";
452
463
  import wcwidth3 from "@topcli/wcwidth";
453
464
  var kRequiredChoiceProperties = ["label", "value"];
454
465
  var SelectPrompt = class extends AbstractPrompt {
@@ -612,7 +623,12 @@ var SelectPrompt = class extends AbstractPrompt {
612
623
  render();
613
624
  }
614
625
  }
615
- select() {
626
+ async select() {
627
+ if (this.skip) {
628
+ this.destroy();
629
+ const answer = this.options.choices[0];
630
+ return typeof answer === "string" ? answer : answer.value;
631
+ }
616
632
  return new Promise((resolve, reject) => {
617
633
  const answer = this.agent.nextAnswers.shift();
618
634
  if (answer !== void 0) {
@@ -682,8 +698,8 @@ var SelectPrompt = class extends AbstractPrompt {
682
698
  };
683
699
 
684
700
  // src/prompts/multiselect.ts
685
- import { EOL as EOL5 } from "os";
686
- import { styleText as styleText5 } from "util";
701
+ import { EOL as EOL5 } from "node:os";
702
+ import { styleText as styleText5 } from "node:util";
687
703
  import wcwidth4 from "@topcli/wcwidth";
688
704
  var kRequiredChoiceProperties2 = ["label", "value"];
689
705
  var MultiselectPrompt = class extends AbstractPrompt {
@@ -732,7 +748,7 @@ var MultiselectPrompt = class extends AbstractPrompt {
732
748
  constructor(options) {
733
749
  const {
734
750
  choices,
735
- preSelectedChoices,
751
+ preSelectedChoices = [],
736
752
  validators = [],
737
753
  showHint = true,
738
754
  ...baseOptions
@@ -756,9 +772,6 @@ var MultiselectPrompt = class extends AbstractPrompt {
756
772
  }
757
773
  }
758
774
  }
759
- if (!preSelectedChoices) {
760
- return;
761
- }
762
775
  for (const choice of preSelectedChoices) {
763
776
  const choiceIndex = this.filteredChoices.findIndex((item) => {
764
777
  if (typeof item === "string") {
@@ -823,6 +836,25 @@ var MultiselectPrompt = class extends AbstractPrompt {
823
836
  const formattedChoice = styleText5("yellow", choices);
824
837
  this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${EOL5}`);
825
838
  }
839
+ #selectedChoices() {
840
+ return [...this.selectedIndexes].reduce(
841
+ (acc, index) => {
842
+ const choice = this.filteredChoices[index];
843
+ if (typeof choice === "string") {
844
+ acc.values.push(choice);
845
+ acc.labels.push(choice);
846
+ } else {
847
+ acc.values.push(choice.value);
848
+ acc.labels.push(choice.label);
849
+ }
850
+ return acc;
851
+ },
852
+ {
853
+ values: [],
854
+ labels: []
855
+ }
856
+ );
857
+ }
826
858
  #onProcessExit() {
827
859
  this.stdin.off("keypress", this.#boundKeyPressEvent);
828
860
  this.stdout.moveCursor(-this.stdout.columns, 0);
@@ -847,14 +879,7 @@ var MultiselectPrompt = class extends AbstractPrompt {
847
879
  this.selectedIndexes = new Set([...this.selectedIndexes].filter((index) => index !== this.activeIndex));
848
880
  render();
849
881
  } else if (key.name === "return") {
850
- const labels = [...this.selectedIndexes].map((index) => {
851
- const choice = this.filteredChoices[index];
852
- return typeof choice === "string" ? choice : choice.label;
853
- });
854
- const values = [...this.selectedIndexes].map((index) => {
855
- const choice = this.filteredChoices[index];
856
- return typeof choice === "string" ? choice : choice.value;
857
- });
882
+ const { values, labels } = this.#selectedChoices();
858
883
  for (const validator of this.#validators) {
859
884
  const validationResult = validator.validate(values);
860
885
  if (isValid(validationResult) === false) {
@@ -882,7 +907,12 @@ var MultiselectPrompt = class extends AbstractPrompt {
882
907
  render();
883
908
  }
884
909
  }
885
- multiselect() {
910
+ async multiselect() {
911
+ if (this.skip) {
912
+ this.destroy();
913
+ const { values } = this.#selectedChoices();
914
+ return values;
915
+ }
886
916
  return new Promise((resolve, reject) => {
887
917
  const answer = this.agent.nextAnswers.shift();
888
918
  if (answer !== void 0) {
@@ -957,18 +987,18 @@ var MultiselectPrompt = class extends AbstractPrompt {
957
987
  };
958
988
 
959
989
  // index.ts
960
- async function question(message, options = {}) {
990
+ function question(message, options = {}) {
961
991
  return new QuestionPrompt({ ...options, message }).question();
962
992
  }
963
- async function select(message, options) {
993
+ function select(message, options) {
964
994
  const selectPrompt = new SelectPrompt({ ...options, message });
965
995
  return selectPrompt.select();
966
996
  }
967
- async function confirm(message, options = {}) {
997
+ function confirm(message, options = {}) {
968
998
  const confirmPrompt = new ConfirmPrompt({ ...options, message });
969
999
  return confirmPrompt.confirm();
970
1000
  }
971
- async function multiselect(message, options) {
1001
+ function multiselect(message, options) {
972
1002
  const multiselectPrompt = new MultiselectPrompt({ ...options, message });
973
1003
  return multiselectPrompt.multiselect();
974
1004
  }
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "@topcli/prompts",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Node.js user input library for command-line interfaces.",
5
5
  "scripts": {
6
6
  "build": "tsup index.ts --format cjs,esm --dts --clean",
7
7
  "prepublishOnly": "npm run build",
8
- "test": "glob -c \"tsx --no-warnings=ExperimentalWarning --loader=esmock --test\" \"./test/**/*.test.ts\"",
8
+ "test": "glob -c \"tsx --test\" \"./test/**/*.test.ts\"",
9
9
  "coverage": "c8 -r html npm run test",
10
- "lint": "eslint .",
10
+ "lint": "eslint src test",
11
11
  "lint:fix": "eslint . --fix"
12
12
  },
13
13
  "main": "./dist/index.js",
14
14
  "types": "./dist/index.d.ts",
15
15
  "exports": {
16
16
  ".": {
17
+ "types": "./dist/index.d.ts",
17
18
  "require": "./dist/index.cjs",
18
- "import": "./dist/index.js",
19
- "types": "./dist/index.d.ts"
19
+ "import": "./dist/index.js"
20
20
  }
21
21
  },
22
22
  "keywords": [
@@ -31,15 +31,14 @@
31
31
  "license": "ISC",
32
32
  "type": "module",
33
33
  "devDependencies": {
34
- "@openally/config.eslint": "^1.0.0",
34
+ "@openally/config.eslint": "^2.0.0",
35
35
  "@openally/config.typescript": "^1.0.3",
36
- "@types/node": "^22.3.0",
37
- "c8": "^10.1.2",
38
- "esmock": "^2.6.7",
36
+ "@types/node": "^22.10.5",
37
+ "c8": "^10.1.3",
39
38
  "glob": "^11.0.0",
40
- "tsup": "^8.2.4",
41
- "tsx": "^4.17.0",
42
- "typescript": "^5.5.4"
39
+ "tsup": "^8.3.5",
40
+ "tsx": "^4.19.2",
41
+ "typescript": "^5.7.2"
43
42
  },
44
43
  "dependencies": {
45
44
  "@topcli/wcwidth": "^1.0.1"