@reliverse/rempts-core 1.6.1 → 2.3.2

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.
Files changed (155) hide show
  1. package/README.md +398 -102
  2. package/dist/cli.d.ts +32 -0
  3. package/dist/cli.js +731 -0
  4. package/dist/config-loader.d.ts +42 -0
  5. package/dist/config-loader.js +20 -0
  6. package/dist/config.d.ts +99 -0
  7. package/dist/config.js +188 -0
  8. package/dist/file-loader.d.ts +43 -0
  9. package/dist/file-loader.js +199 -0
  10. package/dist/global-flags.d.ts +36 -0
  11. package/dist/global-flags.js +36 -0
  12. package/dist/mod.d.ts +13 -0
  13. package/dist/mod.js +19 -0
  14. package/dist/parser.d.ts +6 -0
  15. package/dist/parser.js +137 -0
  16. package/dist/plugin/context.d.ts +13 -0
  17. package/dist/plugin/context.js +53 -0
  18. package/dist/plugin/create.d.ts +92 -0
  19. package/dist/plugin/create.js +61 -0
  20. package/dist/plugin/loader.d.ts +12 -0
  21. package/dist/plugin/loader.js +65 -0
  22. package/dist/plugin/manager.d.ts +53 -0
  23. package/dist/plugin/manager.js +135 -0
  24. package/dist/plugin/mod.d.ts +10 -0
  25. package/dist/plugin/mod.js +27 -0
  26. package/dist/plugin/store.d.ts +45 -0
  27. package/dist/plugin/store.js +60 -0
  28. package/dist/plugin/testing.d.ts +38 -0
  29. package/dist/plugin/testing.js +175 -0
  30. package/dist/plugin/types.d.ts +146 -0
  31. package/dist/tui/registry.d.ts +8 -0
  32. package/dist/tui/registry.js +10 -0
  33. package/dist/tui/types.d.ts +58 -0
  34. package/dist/tui/types.js +10 -0
  35. package/dist/types.d.ts +178 -0
  36. package/dist/types.js +25 -0
  37. package/dist/utils/logger.d.ts +10 -0
  38. package/dist/utils/logger.js +27 -0
  39. package/dist/utils/merge.d.ts +13 -0
  40. package/dist/utils/merge.js +25 -0
  41. package/dist/utils/mod.d.ts +6 -0
  42. package/dist/utils/mod.js +2 -0
  43. package/dist/utils/type-helpers.d.ts +41 -0
  44. package/dist/utils/type-helpers.js +0 -0
  45. package/dist/validation.d.ts +30 -0
  46. package/dist/validation.js +121 -0
  47. package/package.json +47 -44
  48. package/src/cli.ts +1049 -0
  49. package/src/config-loader.ts +71 -0
  50. package/src/config.ts +270 -0
  51. package/src/file-loader.ts +346 -0
  52. package/src/global-flags.ts +50 -0
  53. package/src/mod.ts +74 -0
  54. package/src/parser.ts +212 -0
  55. package/src/plugin/context.ts +88 -0
  56. package/src/plugin/create.ts +174 -0
  57. package/src/plugin/loader.ts +111 -0
  58. package/src/plugin/manager.ts +244 -0
  59. package/src/plugin/mod.ts +51 -0
  60. package/src/plugin/store.ts +124 -0
  61. package/src/plugin/testing.ts +236 -0
  62. package/src/plugin/types.ts +206 -0
  63. package/src/tui/registry.ts +22 -0
  64. package/src/tui/types.ts +79 -0
  65. package/src/types.ts +285 -0
  66. package/src/utils/logger.ts +43 -0
  67. package/src/utils/merge.ts +54 -0
  68. package/src/utils/mod.ts +7 -0
  69. package/src/utils/type-helpers.ts +151 -0
  70. package/src/validation.ts +177 -0
  71. package/LICENSE +0 -21
  72. package/bin/core-impl/anykey/anykey-mod.d.ts +0 -12
  73. package/bin/core-impl/anykey/anykey-mod.js +0 -125
  74. package/bin/core-impl/date/date.d.ts +0 -2
  75. package/bin/core-impl/date/date.js +0 -236
  76. package/bin/core-impl/editor/editor-mod.d.ts +0 -25
  77. package/bin/core-impl/editor/editor-mod.js +0 -896
  78. package/bin/core-impl/figures/figures-mod.d.ts +0 -233
  79. package/bin/core-impl/figures/figures-mod.js +0 -286
  80. package/bin/core-impl/figures/figures.test.d.ts +0 -1
  81. package/bin/core-impl/figures/figures.test.js +0 -474
  82. package/bin/core-impl/input/confirm-prompt.d.ts +0 -5
  83. package/bin/core-impl/input/confirm-prompt.js +0 -173
  84. package/bin/core-impl/input/input-prompt.d.ts +0 -16
  85. package/bin/core-impl/input/input-prompt.js +0 -370
  86. package/bin/core-impl/launcher/_parser.d.ts +0 -2
  87. package/bin/core-impl/launcher/_parser.js +0 -122
  88. package/bin/core-impl/launcher/_utils.d.ts +0 -8
  89. package/bin/core-impl/launcher/_utils.js +0 -29
  90. package/bin/core-impl/launcher/args.d.ts +0 -3
  91. package/bin/core-impl/launcher/args.js +0 -89
  92. package/bin/core-impl/launcher/command.d.ts +0 -8
  93. package/bin/core-impl/launcher/command.js +0 -68
  94. package/bin/core-impl/launcher/launcher-mod.d.ts +0 -8
  95. package/bin/core-impl/launcher/launcher-mod.js +0 -34
  96. package/bin/core-impl/launcher/usage.d.ts +0 -3
  97. package/bin/core-impl/launcher/usage.js +0 -104
  98. package/bin/core-impl/msg-fmt/colors.d.ts +0 -30
  99. package/bin/core-impl/msg-fmt/colors.js +0 -42
  100. package/bin/core-impl/msg-fmt/logger.d.ts +0 -17
  101. package/bin/core-impl/msg-fmt/logger.js +0 -106
  102. package/bin/core-impl/msg-fmt/mapping.d.ts +0 -3
  103. package/bin/core-impl/msg-fmt/mapping.js +0 -49
  104. package/bin/core-impl/msg-fmt/messages.d.ts +0 -35
  105. package/bin/core-impl/msg-fmt/messages.js +0 -314
  106. package/bin/core-impl/msg-fmt/terminal.d.ts +0 -15
  107. package/bin/core-impl/msg-fmt/terminal.js +0 -59
  108. package/bin/core-impl/msg-fmt/variants.d.ts +0 -11
  109. package/bin/core-impl/msg-fmt/variants.js +0 -52
  110. package/bin/core-impl/next-steps/next-steps.d.ts +0 -14
  111. package/bin/core-impl/next-steps/next-steps.js +0 -24
  112. package/bin/core-impl/number/number-mod.d.ts +0 -28
  113. package/bin/core-impl/number/number-mod.js +0 -197
  114. package/bin/core-impl/results/results.d.ts +0 -7
  115. package/bin/core-impl/results/results.js +0 -27
  116. package/bin/core-impl/select/multiselect-prompt.d.ts +0 -2
  117. package/bin/core-impl/select/multiselect-prompt.js +0 -341
  118. package/bin/core-impl/select/nummultiselect-prompt.d.ts +0 -6
  119. package/bin/core-impl/select/nummultiselect-prompt.js +0 -105
  120. package/bin/core-impl/select/numselect-prompt.d.ts +0 -7
  121. package/bin/core-impl/select/numselect-prompt.js +0 -115
  122. package/bin/core-impl/select/select-prompt.d.ts +0 -33
  123. package/bin/core-impl/select/select-prompt.js +0 -302
  124. package/bin/core-impl/select/toggle-prompt.d.ts +0 -5
  125. package/bin/core-impl/select/toggle-prompt.js +0 -208
  126. package/bin/core-impl/st-end/end.d.ts +0 -2
  127. package/bin/core-impl/st-end/end.js +0 -42
  128. package/bin/core-impl/st-end/start.d.ts +0 -17
  129. package/bin/core-impl/st-end/start.js +0 -66
  130. package/bin/core-impl/task/progress.d.ts +0 -2
  131. package/bin/core-impl/task/progress.js +0 -57
  132. package/bin/core-impl/task/spinner.d.ts +0 -15
  133. package/bin/core-impl/task/spinner.js +0 -110
  134. package/bin/core-impl/utils/colorize.d.ts +0 -2
  135. package/bin/core-impl/utils/colorize.js +0 -134
  136. package/bin/core-impl/utils/errors.d.ts +0 -1
  137. package/bin/core-impl/utils/errors.js +0 -15
  138. package/bin/core-impl/utils/prevent.d.ts +0 -10
  139. package/bin/core-impl/utils/prevent.js +0 -69
  140. package/bin/core-impl/utils/prompt-end.d.ts +0 -8
  141. package/bin/core-impl/utils/prompt-end.js +0 -33
  142. package/bin/core-impl/utils/stream-text.d.ts +0 -18
  143. package/bin/core-impl/utils/stream-text.js +0 -136
  144. package/bin/core-impl/utils/system.d.ts +0 -6
  145. package/bin/core-impl/utils/system.js +0 -7
  146. package/bin/core-impl/utils/validate.d.ts +0 -22
  147. package/bin/core-impl/utils/validate.js +0 -17
  148. package/bin/core-impl/visual/animate/animate.d.ts +0 -14
  149. package/bin/core-impl/visual/animate/animate.js +0 -64
  150. package/bin/core-impl/visual/ascii-art/ascii-art.d.ts +0 -6
  151. package/bin/core-impl/visual/ascii-art/ascii-art.js +0 -12
  152. package/bin/core-types.d.ts +0 -434
  153. package/bin/main.d.ts +0 -41
  154. package/bin/main.js +0 -96
  155. /package/{bin/core-types.js → dist/plugin/types.js} +0 -0
@@ -1,197 +0,0 @@
1
- import { stdin as input, stdout as output } from "node:process";
2
- import readline from "node:readline/promises";
3
- import { bar, msg } from "../msg-fmt/messages.js";
4
- import {
5
- deleteLastLine,
6
- deleteLastLines
7
- } from "../msg-fmt/terminal.js";
8
- function renderPromptUI(params) {
9
- const {
10
- title,
11
- hint,
12
- content,
13
- contentColor = "dim",
14
- contentTypography = "italic",
15
- contentVariant,
16
- titleColor = "cyan",
17
- titleTypography = "none",
18
- titleVariant,
19
- borderColor = "dim",
20
- userInput,
21
- errorMessage
22
- } = params;
23
- let lineCount = 0;
24
- const type = errorMessage !== "" ? "M_ERROR" : "M_GENERAL";
25
- const msgParams = {
26
- type,
27
- title,
28
- titleColor,
29
- titleTypography,
30
- titleVariant: titleVariant ?? "none",
31
- content: content ?? "",
32
- contentColor,
33
- contentTypography,
34
- contentVariant: contentVariant ?? "none",
35
- borderColor,
36
- hint: hint ?? "",
37
- errorMessage
38
- };
39
- msg(msgParams);
40
- lineCount++;
41
- if (userInput !== "") {
42
- msg({ type: "M_MIDDLE", title: ` ${userInput}` });
43
- lineCount++;
44
- }
45
- return lineCount;
46
- }
47
- export async function numberPrompt(opts) {
48
- const {
49
- title = "",
50
- hint,
51
- hintPlaceholderColor = "blue",
52
- validate,
53
- defaultValue,
54
- titleColor = "cyan",
55
- titleTypography = "none",
56
- titleVariant,
57
- content,
58
- contentColor = "dim",
59
- contentTypography = "italic",
60
- contentVariant,
61
- borderColor = "dim",
62
- hardcoded,
63
- endTitle = "",
64
- endTitleColor = "dim",
65
- border = true
66
- } = opts;
67
- const rl = readline.createInterface({ input, output });
68
- rl.on("SIGINT", () => {
69
- if (endTitle !== "") {
70
- msg({
71
- type: "M_END",
72
- title: endTitle,
73
- titleColor: endTitleColor,
74
- titleTypography,
75
- border,
76
- borderColor
77
- });
78
- }
79
- rl.close();
80
- process.exit(0);
81
- });
82
- let currentInput = hardcoded?.userInput || "";
83
- let errorMessage = hardcoded?.errorMessage || "";
84
- let isRerender = false;
85
- let lastLineCount = 0;
86
- const effectiveDefault = typeof defaultValue === "string" ? Number(defaultValue) : defaultValue;
87
- if (hardcoded?.userInput !== void 0) {
88
- renderPromptUI({
89
- title,
90
- hint,
91
- hintPlaceholderColor,
92
- content,
93
- contentColor,
94
- contentTypography,
95
- contentVariant,
96
- titleColor,
97
- titleTypography,
98
- titleVariant,
99
- borderColor,
100
- userInput: currentInput,
101
- errorMessage,
102
- border,
103
- isRerender
104
- });
105
- const num = Number(currentInput);
106
- if (Number.isNaN(num)) {
107
- throw new Error("Please enter a valid number.");
108
- }
109
- const validated = await validateInput(num, validate);
110
- if (validated.isValid) {
111
- msg({ type: "M_MIDDLE", title: ` ${num}` });
112
- msg({ type: "M_BAR", borderColor });
113
- rl.close();
114
- return num;
115
- }
116
- rl.close();
117
- throw new Error(validated.errorMessage || "Invalid input.");
118
- }
119
- while (true) {
120
- if (isRerender) {
121
- deleteLastLines(lastLineCount + 1);
122
- }
123
- lastLineCount = renderPromptUI({
124
- title,
125
- hint,
126
- hintPlaceholderColor,
127
- content,
128
- contentColor,
129
- contentTypography,
130
- contentVariant,
131
- titleColor,
132
- titleTypography,
133
- titleVariant,
134
- borderColor,
135
- userInput: currentInput,
136
- errorMessage,
137
- border,
138
- isRerender
139
- });
140
- const formattedBar = bar({ borderColor });
141
- const answerInput = await rl.question(`${formattedBar} `);
142
- isRerender = true;
143
- if (answerInput === null) {
144
- if (endTitle !== "") {
145
- msg({
146
- type: "M_END",
147
- title: endTitle,
148
- titleColor: endTitleColor,
149
- titleTypography,
150
- border,
151
- borderColor
152
- });
153
- }
154
- rl.close();
155
- process.exit(0);
156
- }
157
- currentInput = answerInput.trim();
158
- if (!currentInput && effectiveDefault !== void 0) {
159
- deleteLastLine();
160
- msg({ type: "M_MIDDLE", title: ` ${effectiveDefault}` });
161
- msg({ type: "M_BAR", borderColor });
162
- rl.close();
163
- return effectiveDefault;
164
- }
165
- const num = Number(currentInput);
166
- if (Number.isNaN(num)) {
167
- errorMessage = "Please enter a valid number.";
168
- continue;
169
- }
170
- const validated = await validateInput(num, validate);
171
- if (validated.isValid) {
172
- deleteLastLine();
173
- msg({ type: "M_MIDDLE", title: ` ${num}` });
174
- msg({ type: "M_BAR", borderColor });
175
- rl.close();
176
- return num;
177
- }
178
- errorMessage = validated.errorMessage;
179
- }
180
- }
181
- async function validateInput(input2, validate) {
182
- let isValid = true;
183
- let errorMessage = "";
184
- if (validate && isValid) {
185
- const validationResult = await validate(input2);
186
- if (validationResult === true || validationResult === void 0) {
187
- isValid = true;
188
- } else if (typeof validationResult === "string") {
189
- isValid = false;
190
- errorMessage = validationResult;
191
- } else {
192
- isValid = false;
193
- errorMessage = "Invalid input.";
194
- }
195
- }
196
- return { isValid, errorMessage };
197
- }
@@ -1,7 +0,0 @@
1
- export type ResultsType = {
2
- username: string;
3
- };
4
- export declare function resultPrompt({ results, inline, }: {
5
- results: ResultsType;
6
- inline?: boolean;
7
- }): Promise<void>;
@@ -1,27 +0,0 @@
1
- import { msg } from "../msg-fmt/messages.js";
2
- export async function resultPrompt({
3
- results,
4
- inline = true
5
- }) {
6
- const title = "Your input results:";
7
- if (inline) {
8
- const formattedResults = Object.entries(results).map(([key, value]) => `${key}: ${value}`).join(", ");
9
- msg({
10
- type: "M_INFO",
11
- title,
12
- content: formattedResults,
13
- titleColor: "cyan",
14
- contentColor: "dim",
15
- wrapContent: true
16
- });
17
- } else {
18
- const formattedResults = JSON.stringify(results, null, 2);
19
- msg({
20
- type: "M_INFO",
21
- title,
22
- content: formattedResults,
23
- titleColor: "cyan",
24
- contentColor: "dim"
25
- });
26
- }
27
- }
@@ -1,2 +0,0 @@
1
- import type { MultiselectPromptParams } from "../../core-types.js";
2
- export declare function multiselectPrompt<T extends string>(params: MultiselectPromptParams<T>): Promise<T[]>;
@@ -1,341 +0,0 @@
1
- import { re } from "@reliverse/relico";
2
- import { stdin as input, stdout as output } from "node:process";
3
- import readline from "node:readline";
4
- import { msg, symbols } from "../msg-fmt/messages.js";
5
- import { deleteLastLine } from "../msg-fmt/terminal.js";
6
- import { completePrompt } from "../utils/prompt-end.js";
7
- function isSelectOption(option) {
8
- return !("separator" in option);
9
- }
10
- function renderPromptUI(params) {
11
- const {
12
- title,
13
- content,
14
- options,
15
- pointer,
16
- selectedOptions,
17
- errorMessage,
18
- displayInstructions,
19
- instructions,
20
- allDisabled,
21
- titleColor,
22
- contentColor,
23
- contentTypography,
24
- debug,
25
- titleVariant,
26
- titleTypography,
27
- isRerender = false
28
- } = params;
29
- if (!isRerender) {
30
- msg({
31
- type: "M_NULL",
32
- title,
33
- titleColor,
34
- ...titleTypography ? { titleTypography } : {},
35
- ...titleVariant ? { titleVariant } : {}
36
- });
37
- if (content) {
38
- msg({
39
- type: "M_NULL",
40
- content,
41
- contentColor,
42
- contentTypography
43
- });
44
- }
45
- }
46
- let uiLineCount = 0;
47
- if (errorMessage) {
48
- msg({
49
- type: "M_NULL",
50
- title: `${re.redBright(symbols.step_error)} ${re.redBright(errorMessage)}`
51
- });
52
- uiLineCount++;
53
- } else if (allDisabled) {
54
- msg({ type: "M_NULL", title: re.redBright("All options are disabled.") });
55
- uiLineCount++;
56
- } else if (displayInstructions && !isRerender) {
57
- msg({ type: "M_NULL", title: re.blue(instructions) });
58
- uiLineCount++;
59
- }
60
- for (let index = 0; index < options.length; index++) {
61
- const option = options[index];
62
- if (!option) continue;
63
- if (!isSelectOption(option)) {
64
- const width = option.width ?? 20;
65
- const symbolKey = option.symbol ?? "line";
66
- const lineSymbol = symbolKey in symbols ? symbols[symbolKey] : "\u2500";
67
- msg({ type: "M_NULL", title: re.dim(lineSymbol.repeat(width)) });
68
- uiLineCount++;
69
- continue;
70
- }
71
- const isSelected = selectedOptions.has(index);
72
- const isHighlighted = index === pointer;
73
- const isDisabled = option.disabled;
74
- const checkbox = isSelected ? "[x]" : "[ ]";
75
- const prefix = isHighlighted ? re.yellow(re.reset("> ")) : " ";
76
- const labelColor = isDisabled ? re.dim(re.reset(option.label)) : isHighlighted ? re.reset(re.yellow(option.label)) : re.reset(option.label);
77
- const hint = option.hint ? re.reset(
78
- ` (${isDisabled ? re.dim(option.hint) : re.gray(option.hint)})`
79
- ) : "";
80
- const formattedCheckbox = isHighlighted ? re.yellow(checkbox) : checkbox;
81
- msg({
82
- type: "M_NULL",
83
- title: `${prefix}${formattedCheckbox} ${labelColor}${hint}`
84
- });
85
- uiLineCount++;
86
- }
87
- if (debug) {
88
- console.log({ optionsCount: options.length });
89
- }
90
- return uiLineCount;
91
- }
92
- export async function multiselectPrompt(params) {
93
- const {
94
- title = "",
95
- content = "",
96
- options,
97
- defaultValue = [],
98
- borderColor = "dim",
99
- titleColor = "cyan",
100
- titleTypography = "none",
101
- titleVariant,
102
- contentColor = "dim",
103
- contentTypography = "italic",
104
- border = true,
105
- endTitle = "",
106
- endTitleColor = "dim",
107
- debug = false,
108
- terminalWidth: customTerminalWidth = 90,
109
- displayInstructions = false,
110
- minSelect = 0,
111
- maxSelect,
112
- selectAll = false
113
- } = params;
114
- let pointer = defaultValue.length > 0 ? options.findIndex(
115
- (opt) => opt && isSelectOption(opt) && defaultValue.includes(opt.value) && !opt.disabled
116
- ) : 0;
117
- if (pointer === -1) {
118
- pointer = options.findIndex(
119
- (opt) => opt && isSelectOption(opt) && !opt.disabled
120
- );
121
- if (pointer === -1) {
122
- pointer = 0;
123
- }
124
- }
125
- const selectedOptions = new Set(
126
- selectAll ? options.map(
127
- (opt, index) => opt && isSelectOption(opt) && !opt.disabled ? index : -1
128
- ).filter((i) => i !== -1) : defaultValue.map(
129
- (val) => options.findIndex((o) => o && isSelectOption(o) && o.value === val)
130
- ).filter(
131
- (i) => i >= 0 && options[i] && isSelectOption(options[i]) && !options[i].disabled
132
- )
133
- );
134
- const rl = readline.createInterface({ input, output });
135
- readline.emitKeypressEvents(input, rl);
136
- if (typeof input.setRawMode === "function") {
137
- input.setRawMode(true);
138
- }
139
- let errorMessage = "";
140
- const allDisabled = options.filter(isSelectOption).every((option) => option.disabled);
141
- const instructions = "Use <\u2191/\u2193> to navigate, <Space> to toggle, <A> to toggle all";
142
- function toggleSelectAll() {
143
- const selectableIndexes = options.map((opt, i) => isSelectOption(opt) && !opt.disabled ? i : -1).filter((i) => i !== -1);
144
- const allSelected = selectableIndexes.every((i) => selectedOptions.has(i));
145
- if (allSelected) {
146
- for (const i of selectableIndexes) {
147
- selectedOptions.delete(i);
148
- }
149
- } else {
150
- for (const i of selectableIndexes) {
151
- selectedOptions.add(i);
152
- }
153
- }
154
- }
155
- function movePointerUp() {
156
- const originalPointer = pointer;
157
- do {
158
- pointer = (pointer - 1 + options.length) % options.length;
159
- const currentOption = options[pointer];
160
- if (currentOption && isSelectOption(currentOption) && !currentOption.disabled) {
161
- break;
162
- }
163
- } while (pointer !== originalPointer);
164
- errorMessage = "";
165
- }
166
- function movePointerDown() {
167
- const originalPointer = pointer;
168
- do {
169
- pointer = (pointer + 1) % options.length;
170
- const currentOption = options[pointer];
171
- if (currentOption && isSelectOption(currentOption) && !currentOption.disabled) {
172
- break;
173
- }
174
- } while (pointer !== originalPointer);
175
- errorMessage = "";
176
- }
177
- let lastUILineCount = 0;
178
- function renderOptions() {
179
- if (lastUILineCount > 0) {
180
- for (let i = 0; i < lastUILineCount; i++) {
181
- process.stdout.write("\x1B[1A\x1B[2K");
182
- }
183
- }
184
- lastUILineCount = renderPromptUI({
185
- title,
186
- content,
187
- options,
188
- pointer,
189
- selectedOptions,
190
- errorMessage,
191
- displayInstructions,
192
- instructions,
193
- allDisabled,
194
- titleColor,
195
- contentColor,
196
- contentTypography,
197
- debug,
198
- borderColor,
199
- titleVariant,
200
- titleTypography,
201
- terminalWidth: customTerminalWidth,
202
- resized: false,
203
- isRerender: true
204
- });
205
- }
206
- lastUILineCount = renderPromptUI({
207
- title,
208
- content,
209
- options,
210
- pointer,
211
- selectedOptions,
212
- errorMessage,
213
- displayInstructions,
214
- instructions,
215
- allDisabled,
216
- titleColor,
217
- contentColor,
218
- contentTypography,
219
- debug,
220
- borderColor,
221
- titleVariant,
222
- titleTypography,
223
- terminalWidth: customTerminalWidth,
224
- resized: false,
225
- isRerender: false
226
- });
227
- return new Promise((resolve) => {
228
- function cleanup(isCtrlC = false) {
229
- if (typeof input.setRawMode === "function") {
230
- input.setRawMode(false);
231
- }
232
- rl.close();
233
- input.removeListener("keypress", handleKeypress);
234
- if (isCtrlC) {
235
- process.exit(0);
236
- }
237
- }
238
- async function endPrompt(isCtrlC = false) {
239
- await completePrompt(
240
- "multiselect",
241
- isCtrlC,
242
- endTitle,
243
- endTitleColor,
244
- titleTypography,
245
- titleVariant ? titleVariant : void 0,
246
- border,
247
- borderColor,
248
- void 0,
249
- false
250
- );
251
- cleanup(isCtrlC);
252
- }
253
- async function confirmSelection() {
254
- const selectedCount = selectedOptions.size;
255
- if (selectedCount < minSelect) {
256
- deleteLastLine();
257
- errorMessage = `You must select at least ${minSelect} option${minSelect !== 1 ? "s" : ""}.`;
258
- renderOptions();
259
- return;
260
- }
261
- if (maxSelect !== void 0 && selectedCount > maxSelect) {
262
- deleteLastLine();
263
- errorMessage = `You can select at most ${maxSelect} option${maxSelect !== 1 ? "s" : ""}.`;
264
- renderOptions();
265
- return;
266
- }
267
- const selectedValues = Array.from(selectedOptions).filter((idx) => {
268
- const opt = options[idx];
269
- return opt && isSelectOption(opt) && !opt.disabled;
270
- }).map((idx) => {
271
- const opt = options[idx];
272
- return opt && isSelectOption(opt) ? opt.value : null;
273
- }).filter((val) => val !== null && val !== void 0);
274
- cleanup();
275
- resolve(selectedValues);
276
- deleteLastLine();
277
- await completePrompt(
278
- "multiselect",
279
- false,
280
- endTitle,
281
- endTitleColor,
282
- titleTypography,
283
- titleVariant ? titleVariant : void 0,
284
- border,
285
- borderColor,
286
- void 0,
287
- true
288
- );
289
- }
290
- function handleKeypress(_str, key) {
291
- if (allDisabled) {
292
- if (key.name === "c" && key.ctrl) {
293
- void endPrompt(true);
294
- return;
295
- }
296
- return;
297
- }
298
- switch (key.name) {
299
- case "up":
300
- case "k":
301
- movePointerUp();
302
- renderOptions();
303
- break;
304
- case "down":
305
- case "j":
306
- movePointerDown();
307
- renderOptions();
308
- break;
309
- case "space": {
310
- const currentOption = options[pointer];
311
- if (!currentOption || !isSelectOption(currentOption) || currentOption.disabled) {
312
- errorMessage = "This option is disabled";
313
- } else {
314
- if (selectedOptions.has(pointer)) {
315
- selectedOptions.delete(pointer);
316
- } else {
317
- selectedOptions.add(pointer);
318
- }
319
- errorMessage = "";
320
- }
321
- renderOptions();
322
- break;
323
- }
324
- case "return":
325
- void confirmSelection();
326
- break;
327
- case "c":
328
- if (key.ctrl) {
329
- void endPrompt(true);
330
- }
331
- break;
332
- case "a":
333
- toggleSelectAll();
334
- errorMessage = "";
335
- renderOptions();
336
- break;
337
- }
338
- }
339
- input.on("keypress", handleKeypress);
340
- });
341
- }
@@ -1,6 +0,0 @@
1
- import type { PromptOptions } from "../../core-types.js";
2
- type NumMultiSelectPromptOptions = PromptOptions & {
3
- defaultValue?: string[];
4
- };
5
- export declare function numMultiSelectPrompt(opts: NumMultiSelectPromptOptions): Promise<any>;
6
- export {};
@@ -1,105 +0,0 @@
1
- import { re } from "@reliverse/relico";
2
- import { stdin as input, stdout as output } from "node:process";
3
- import readline from "node:readline/promises";
4
- import { bar, fmt, msg } from "../msg-fmt/messages.js";
5
- import {
6
- countLines,
7
- deleteLastLine,
8
- deleteLastLines
9
- } from "../msg-fmt/terminal.js";
10
- export async function numMultiSelectPrompt(opts) {
11
- const {
12
- title = "",
13
- choices,
14
- defaultValue,
15
- titleColor = "cyan",
16
- titleTypography = "none",
17
- titleVariant,
18
- hint,
19
- hintPlaceholderColor = "blue",
20
- content,
21
- contentColor = "dim",
22
- contentTypography = "italic",
23
- contentVariant,
24
- borderColor = "dim",
25
- variantOptions
26
- } = opts;
27
- if (!choices || choices.length === 0) {
28
- throw new Error("Choices are required for multiselect prompt.");
29
- }
30
- const rl = readline.createInterface({ input, output });
31
- const formattedBar = bar({ borderColor });
32
- let linesToDelete = 0;
33
- let errorMessage = "";
34
- try {
35
- while (true) {
36
- if (linesToDelete > 0) {
37
- deleteLastLines(linesToDelete);
38
- }
39
- const { text: question } = fmt({
40
- hintPlaceholderColor,
41
- type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
42
- title: `${title}${defaultValue ? ` [Default: ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}]` : ""}`,
43
- titleColor,
44
- titleTypography,
45
- titleVariant: titleVariant ?? "none",
46
- content: content ?? "",
47
- contentColor: contentColor ?? "dim",
48
- contentTypography: contentTypography ?? "none",
49
- contentVariant: contentVariant ?? "none",
50
- borderColor,
51
- hint: hint ?? "",
52
- variantOptions: variantOptions ?? {},
53
- errorMessage
54
- });
55
- const choicesText = choices.map(
56
- (choice, index) => re.dim(
57
- `${formattedBar} ${index + 1}) ${choice.title}${choice.description ? ` - ${choice.description}` : ""}`
58
- )
59
- ).join("\n");
60
- const fullPrompt = `${question}
61
- ${choicesText}
62
- ${formattedBar} ${re.bold(re.blue(`Enter your choices (comma-separated numbers between 1-${choices.length})`))}:
63
- ${formattedBar} `;
64
- const { text: formattedPrompt } = fmt({
65
- hintPlaceholderColor,
66
- type: "M_NULL",
67
- title: fullPrompt
68
- });
69
- const questionLines = countLines(formattedPrompt);
70
- linesToDelete = questionLines + 1;
71
- const answer = (await rl.question(`${formattedPrompt} `)).trim();
72
- if (!answer && defaultValue !== void 0) {
73
- deleteLastLine();
74
- msg({
75
- type: "M_MIDDLE",
76
- title: ` ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}`,
77
- titleColor: "none"
78
- });
79
- msg({ type: "M_BAR", borderColor });
80
- return defaultValue;
81
- }
82
- const selections = answer.split(",").map((s) => s.trim());
83
- const invalidSelections = selections.filter((s) => {
84
- const num = Number(s);
85
- return Number.isNaN(num) || num < 1 || num > choices.length;
86
- });
87
- if (invalidSelections.length > 0) {
88
- errorMessage = `Invalid selections: ${invalidSelections.join(
89
- ", "
90
- )}. Please enter numbers between 1 and ${choices.length}.`;
91
- continue;
92
- }
93
- const selectedValues = selections.map((s) => choices[Number(s) - 1]?.id);
94
- const isValid = true;
95
- errorMessage = "";
96
- if (isValid) {
97
- rl.close();
98
- msg({ type: "M_BAR", borderColor });
99
- return selectedValues;
100
- }
101
- }
102
- } finally {
103
- rl.close();
104
- }
105
- }
@@ -1,7 +0,0 @@
1
- import type { PromptOptions } from "../../core-types.js";
2
- type NumSelectPromptOptions = PromptOptions & {
3
- inline?: boolean;
4
- defaultValue?: string;
5
- };
6
- export declare function numSelectPrompt(opts: NumSelectPromptOptions): Promise<any>;
7
- export {};