@reliverse/rempts-core 1.6.1

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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/bin/core-impl/anykey/anykey-mod.d.ts +12 -0
  4. package/bin/core-impl/anykey/anykey-mod.js +125 -0
  5. package/bin/core-impl/date/date.d.ts +2 -0
  6. package/bin/core-impl/date/date.js +236 -0
  7. package/bin/core-impl/editor/editor-mod.d.ts +25 -0
  8. package/bin/core-impl/editor/editor-mod.js +896 -0
  9. package/bin/core-impl/figures/figures-mod.d.ts +233 -0
  10. package/bin/core-impl/figures/figures-mod.js +286 -0
  11. package/bin/core-impl/figures/figures.test.d.ts +1 -0
  12. package/bin/core-impl/figures/figures.test.js +474 -0
  13. package/bin/core-impl/input/confirm-prompt.d.ts +5 -0
  14. package/bin/core-impl/input/confirm-prompt.js +173 -0
  15. package/bin/core-impl/input/input-prompt.d.ts +16 -0
  16. package/bin/core-impl/input/input-prompt.js +370 -0
  17. package/bin/core-impl/launcher/_parser.d.ts +2 -0
  18. package/bin/core-impl/launcher/_parser.js +122 -0
  19. package/bin/core-impl/launcher/_utils.d.ts +8 -0
  20. package/bin/core-impl/launcher/_utils.js +29 -0
  21. package/bin/core-impl/launcher/args.d.ts +3 -0
  22. package/bin/core-impl/launcher/args.js +89 -0
  23. package/bin/core-impl/launcher/command.d.ts +8 -0
  24. package/bin/core-impl/launcher/command.js +68 -0
  25. package/bin/core-impl/launcher/launcher-mod.d.ts +8 -0
  26. package/bin/core-impl/launcher/launcher-mod.js +34 -0
  27. package/bin/core-impl/launcher/usage.d.ts +3 -0
  28. package/bin/core-impl/launcher/usage.js +104 -0
  29. package/bin/core-impl/msg-fmt/colors.d.ts +30 -0
  30. package/bin/core-impl/msg-fmt/colors.js +42 -0
  31. package/bin/core-impl/msg-fmt/logger.d.ts +17 -0
  32. package/bin/core-impl/msg-fmt/logger.js +106 -0
  33. package/bin/core-impl/msg-fmt/mapping.d.ts +3 -0
  34. package/bin/core-impl/msg-fmt/mapping.js +49 -0
  35. package/bin/core-impl/msg-fmt/messages.d.ts +35 -0
  36. package/bin/core-impl/msg-fmt/messages.js +314 -0
  37. package/bin/core-impl/msg-fmt/terminal.d.ts +15 -0
  38. package/bin/core-impl/msg-fmt/terminal.js +59 -0
  39. package/bin/core-impl/msg-fmt/variants.d.ts +11 -0
  40. package/bin/core-impl/msg-fmt/variants.js +52 -0
  41. package/bin/core-impl/next-steps/next-steps.d.ts +14 -0
  42. package/bin/core-impl/next-steps/next-steps.js +24 -0
  43. package/bin/core-impl/number/number-mod.d.ts +28 -0
  44. package/bin/core-impl/number/number-mod.js +197 -0
  45. package/bin/core-impl/results/results.d.ts +7 -0
  46. package/bin/core-impl/results/results.js +27 -0
  47. package/bin/core-impl/select/multiselect-prompt.d.ts +2 -0
  48. package/bin/core-impl/select/multiselect-prompt.js +341 -0
  49. package/bin/core-impl/select/nummultiselect-prompt.d.ts +6 -0
  50. package/bin/core-impl/select/nummultiselect-prompt.js +105 -0
  51. package/bin/core-impl/select/numselect-prompt.d.ts +7 -0
  52. package/bin/core-impl/select/numselect-prompt.js +115 -0
  53. package/bin/core-impl/select/select-prompt.d.ts +33 -0
  54. package/bin/core-impl/select/select-prompt.js +302 -0
  55. package/bin/core-impl/select/toggle-prompt.d.ts +5 -0
  56. package/bin/core-impl/select/toggle-prompt.js +208 -0
  57. package/bin/core-impl/st-end/end.d.ts +2 -0
  58. package/bin/core-impl/st-end/end.js +42 -0
  59. package/bin/core-impl/st-end/start.d.ts +17 -0
  60. package/bin/core-impl/st-end/start.js +66 -0
  61. package/bin/core-impl/task/progress.d.ts +2 -0
  62. package/bin/core-impl/task/progress.js +57 -0
  63. package/bin/core-impl/task/spinner.d.ts +15 -0
  64. package/bin/core-impl/task/spinner.js +110 -0
  65. package/bin/core-impl/utils/colorize.d.ts +2 -0
  66. package/bin/core-impl/utils/colorize.js +134 -0
  67. package/bin/core-impl/utils/errors.d.ts +1 -0
  68. package/bin/core-impl/utils/errors.js +15 -0
  69. package/bin/core-impl/utils/prevent.d.ts +10 -0
  70. package/bin/core-impl/utils/prevent.js +69 -0
  71. package/bin/core-impl/utils/prompt-end.d.ts +8 -0
  72. package/bin/core-impl/utils/prompt-end.js +33 -0
  73. package/bin/core-impl/utils/stream-text.d.ts +18 -0
  74. package/bin/core-impl/utils/stream-text.js +136 -0
  75. package/bin/core-impl/utils/system.d.ts +6 -0
  76. package/bin/core-impl/utils/system.js +7 -0
  77. package/bin/core-impl/utils/validate.d.ts +22 -0
  78. package/bin/core-impl/utils/validate.js +17 -0
  79. package/bin/core-impl/visual/animate/animate.d.ts +14 -0
  80. package/bin/core-impl/visual/animate/animate.js +64 -0
  81. package/bin/core-impl/visual/ascii-art/ascii-art.d.ts +6 -0
  82. package/bin/core-impl/visual/ascii-art/ascii-art.js +12 -0
  83. package/bin/core-types.d.ts +434 -0
  84. package/bin/core-types.js +0 -0
  85. package/bin/main.d.ts +41 -0
  86. package/bin/main.js +96 -0
  87. package/package.json +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2025 blefnk Nazar Kornienko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @reliverse/prompts
2
+
3
+ [💖 GitHub Sponsors](https://github.com/sponsors/blefnk) • [💬 Discord](https://discord.gg/3GawfWfAPe) • [📦 NPM](https://npmjs.com/package/@reliverse/prompts) • [📚 Docs](https://docs.reliverse.org/reliverse/prompts) • [✨ GitHub](https://github.com/reliverse/prompts)
4
+
5
+ **@reliverse/prompts** is your modern, type-safe toolkit for building delightful CLI experiences. It's fast, flexible, and built with developer joy in mind. Forget the clutter — this is how CLI should feel.
6
+
7
+ ## ⚡ Why It Rocks
8
+
9
+ - ✨ **TypeScript-first** — fully typed prompts and helpers, with great DX
10
+ - 🔧 **Flexible Prompt Types** — input, password, select, multiselect, confirm, toggle, number, spinner, and more
11
+ - 🧠 **Smart validation** — works with Zod, TypeBox, or your own validators
12
+ - 🌈 **Accessible & Adaptive** — meets WCAG AA, handles terminal resizing & color contrast
13
+ - 🧯 **Crash-resistant** — gracefully exits on Ctrl+C or unexpected input
14
+ - 🎨 **Custom theming** — make it match your CLI style
15
+ - 🚀 **Zero boilerplate** — focus on the logic, not the wiring
16
+
17
+ ## 🛠️ Install
18
+
19
+ ```bash
20
+ bun add @reliverse/prompts
21
+ # or npm, pnpm, yarn
22
+ ```
23
+
24
+ Make sure you have [Bun](https://bun.sh), [Node.js](https://nodejs.org), and [Git](https://git-scm.com/downloads) installed.
25
+
26
+ ## 🧪 Try It Out (Playground Mode)
27
+
28
+ Wanna test drive before integrating? Clone the repo and run:
29
+
30
+ ```bash
31
+ git clone https://github.com/reliverse/prompts.git
32
+ cd prompts
33
+ bun i
34
+ bun dev
35
+ ```
36
+
37
+ Then open `examples/launcher.ts` and explore different prompts.
38
+
39
+ ![example](./examples/main.png)
40
+
41
+ ## 🧩 Example Usage
42
+
43
+ ```ts
44
+ import {
45
+ startPrompt, // Initialize prompt session (optional)
46
+ inputPrompt, // Ask for user input
47
+ } from "@reliverse/prompts";
48
+
49
+ await startPrompt({
50
+ clearConsole: true,
51
+ titleColor: "inverse",
52
+ packageName: "@reliverse/cli",
53
+ packageVersion: "1.0.0",
54
+ });
55
+
56
+ const username = await inputPrompt({
57
+ id: "username",
58
+ title: "Welcome!",
59
+ content: "What's your name?",
60
+ });
61
+
62
+ console.log(`Hey there, ${username}!`);
63
+ ```
64
+
65
+ > 🔎 You can also use `selectPrompt`, `multiselectPrompt`, `confirmPrompt`, `numberPrompt`, `spinnerPrompt`, and more.
66
+
67
+ ## 🧠 Bonus Goodies
68
+
69
+ - ⚙️ **Built-in argument parsing** — parse CLI args without a separate lib
70
+ - 🧪 **Unit-test friendly** — prompts can be mocked/stubbed
71
+ - 📚 **Minimal API surface** — easy to learn, hard to outgrow
72
+ - 💅 **Custom styles** — tweak colors, formats, and transitions
73
+
74
+ ## 🔍 Why not Inquirer or Clack?
75
+
76
+ While we love other tools, `@reliverse/prompts` was built for:
77
+
78
+ - Dev-first ergonomics
79
+ - Fully typed workflows
80
+ - Configurable theming
81
+ - Better crash handling & UX polish
82
+
83
+ [See feature comparison →](https://docs.reliverse.org/reliverse/prompts/#prompts-library-comparison)
84
+
85
+ ## 💡 Contributing
86
+
87
+ Wanna improve prompts or add something cool? PRs welcome!
88
+ This project favors functional programming over OOP — no classes, just clean, composable logic.
89
+
90
+ Open a PR or discussion on [GitHub](https://github.com/reliverse/prompts).
91
+
92
+ ## 🙏 Shoutout
93
+
94
+ This wouldn't exist without these gems:
95
+
96
+ - [sboudrias/inquirer.js](https://github.com/sboudrias/inquirer.js)
97
+ - [unjs/citty](https://github.com/unjs/citty)
98
+ - [lukeed/mri](https://github.com/lukeed/mri)
99
+
100
+ ## 📄 License
101
+
102
+ 💖 MIT © 2025 [blefnk Nazar Kornienko](https://github.com/blefnk)
@@ -0,0 +1,12 @@
1
+ import type { ColorName } from "../../core-types.js";
2
+ type Options = {
3
+ ctrlC?: number | false | "reject";
4
+ preserveLog?: boolean;
5
+ hideMessage?: boolean;
6
+ shouldStream?: boolean;
7
+ streamDelay?: number;
8
+ color?: ColorName;
9
+ placeholderColor?: ColorName;
10
+ };
11
+ export declare function anykeyPrompt(message?: string, options?: Options): Promise<void>;
12
+ export {};
@@ -0,0 +1,125 @@
1
+ import logUpdate from "log-update";
2
+ import { cursor } from "sisteransi";
3
+ import { fmt } from "../msg-fmt/messages.js";
4
+ import { endPrompt } from "../st-end/end.js";
5
+ import { streamText } from "../utils/stream-text.js";
6
+ const DEFAULT_MESSAGE = "Press any key to continue...";
7
+ const CTRL_C_CODE = 3;
8
+ const terminal = {
9
+ /**
10
+ * Move cursor to start of line
11
+ */
12
+ moveToStart: () => process.stdout.write("\r"),
13
+ /**
14
+ * Clear current line and move cursor up
15
+ */
16
+ clearLineAndMoveUp: () => process.stdout.write("\x1B[1A\x1B[2K"),
17
+ /**
18
+ * Clear multiple lines above current position
19
+ */
20
+ clearLines: (count) => {
21
+ terminal.moveToStart();
22
+ process.stdout.write("\x1B[2K");
23
+ for (let i = 0; i < count; i++) {
24
+ terminal.clearLineAndMoveUp();
25
+ }
26
+ }
27
+ };
28
+ export async function anykeyPrompt(message = DEFAULT_MESSAGE, options = {}) {
29
+ const {
30
+ ctrlC = 1,
31
+ preserveLog = false,
32
+ hideMessage = false,
33
+ shouldStream = false,
34
+ streamDelay = 20,
35
+ color = "dim",
36
+ placeholderColor = "gray"
37
+ } = options;
38
+ if (message) {
39
+ if (!shouldStream) {
40
+ const { text } = fmt({
41
+ hintPlaceholderColor: placeholderColor,
42
+ type: "M_GENERAL",
43
+ title: message,
44
+ titleColor: color,
45
+ dontRemoveBar: true
46
+ });
47
+ message = text;
48
+ }
49
+ }
50
+ if (message && !hideMessage) {
51
+ if (shouldStream) {
52
+ await streamText({
53
+ text: `\u25C6 ${message}`,
54
+ delay: streamDelay,
55
+ newline: false,
56
+ clearLine: true,
57
+ color
58
+ });
59
+ const lineCount = message.split("\n").length;
60
+ terminal.clearLines(lineCount);
61
+ const { text } = fmt({
62
+ hintPlaceholderColor: placeholderColor,
63
+ type: "M_GENERAL",
64
+ title: message,
65
+ titleColor: color,
66
+ dontRemoveBar: true
67
+ });
68
+ terminal.moveToStart();
69
+ logUpdate(text);
70
+ } else {
71
+ logUpdate(message);
72
+ }
73
+ }
74
+ return new Promise((resolve, reject) => {
75
+ const cleanup = () => {
76
+ process.stdin.removeListener("data", handler);
77
+ if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
78
+ process.stdin.setRawMode(false);
79
+ }
80
+ process.stdin.pause();
81
+ process.stdout.write(cursor.show);
82
+ };
83
+ const handleCtrlC = () => {
84
+ cleanup();
85
+ void endPrompt({
86
+ title: "\u270B User pressed Ctrl+C, exiting...",
87
+ titleAnimation: "pulse",
88
+ titleColor: "redBright",
89
+ titleTypography: "bold",
90
+ endTitleColor: "redBright",
91
+ titleAnimationDelay: 400
92
+ }).then(() => {
93
+ if (ctrlC === "reject") {
94
+ reject(new Error("User pressed CTRL+C"));
95
+ } else if (ctrlC === false) {
96
+ resolve();
97
+ } else if (typeof ctrlC === "number") {
98
+ process.exit(0);
99
+ } else {
100
+ throw new TypeError("Invalid ctrlC option");
101
+ }
102
+ }).catch(reject);
103
+ };
104
+ const handler = (buffer) => {
105
+ cleanup();
106
+ if (message && !preserveLog) {
107
+ logUpdate.clear();
108
+ } else {
109
+ logUpdate.done();
110
+ process.stdout.write("\n");
111
+ }
112
+ const [firstByte] = buffer;
113
+ if (firstByte === CTRL_C_CODE) {
114
+ handleCtrlC();
115
+ } else {
116
+ resolve();
117
+ }
118
+ };
119
+ process.stdin.resume();
120
+ if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
121
+ process.stdin.setRawMode(true);
122
+ }
123
+ process.stdin.once("data", handler);
124
+ });
125
+ }
@@ -0,0 +1,2 @@
1
+ import type { DatePromptOptions } from "../../core-types.js";
2
+ export declare function datePrompt(opts: DatePromptOptions): Promise<string>;
@@ -0,0 +1,236 @@
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 {
5
+ buildRegExp,
6
+ digit,
7
+ endOfString,
8
+ repeat,
9
+ startOfString
10
+ } from "ts-regex-builder";
11
+ import { fmt, msg, symbols } from "../msg-fmt/messages.js";
12
+ import {
13
+ countLines,
14
+ deleteLastLine,
15
+ deleteLastLines
16
+ } from "../msg-fmt/terminal.js";
17
+ const twoDigits = repeat(digit, 2);
18
+ const fourDigits = repeat(digit, 4);
19
+ const separatorDot = ".";
20
+ const separatorSlash = "/";
21
+ const regexDDMMYYYY = buildRegExp([
22
+ startOfString,
23
+ twoDigits,
24
+ // DD
25
+ separatorDot,
26
+ twoDigits,
27
+ // MM
28
+ separatorDot,
29
+ fourDigits,
30
+ // YYYY
31
+ endOfString
32
+ ]);
33
+ const regexMMDDYYYY = buildRegExp([
34
+ startOfString,
35
+ twoDigits,
36
+ // MM
37
+ separatorSlash,
38
+ twoDigits,
39
+ // DD
40
+ separatorSlash,
41
+ fourDigits,
42
+ // YYYY
43
+ endOfString
44
+ ]);
45
+ const regexYYYYMMDD = buildRegExp([
46
+ startOfString,
47
+ fourDigits,
48
+ // YYYY
49
+ separatorDot,
50
+ twoDigits,
51
+ // MM
52
+ separatorDot,
53
+ twoDigits,
54
+ // DD
55
+ endOfString
56
+ ]);
57
+ export async function datePrompt(opts) {
58
+ const {
59
+ title = "",
60
+ dateFormat,
61
+ dateKind,
62
+ hint,
63
+ hintPlaceholderColor = "blue",
64
+ validate,
65
+ defaultValue = "",
66
+ titleColor = "cyan",
67
+ titleTypography = "none",
68
+ titleVariant,
69
+ content,
70
+ contentColor = "dim",
71
+ contentTypography = "italic",
72
+ contentVariant,
73
+ borderColor = "dim",
74
+ variantOptions,
75
+ endTitle = "",
76
+ endTitleColor = "dim",
77
+ border = true
78
+ } = opts;
79
+ const rl = readline.createInterface({ input, output });
80
+ rl.on("SIGINT", () => {
81
+ rl.close();
82
+ if (endTitle !== "") {
83
+ msg({
84
+ type: "M_END",
85
+ title: endTitle,
86
+ titleColor: endTitleColor,
87
+ titleTypography,
88
+ border,
89
+ borderColor
90
+ });
91
+ }
92
+ process.exit(0);
93
+ });
94
+ let linesToDelete = 0;
95
+ let errorMessage = "";
96
+ try {
97
+ while (true) {
98
+ if (linesToDelete > 0) {
99
+ deleteLastLines(linesToDelete);
100
+ linesToDelete = 0;
101
+ }
102
+ const { text: questionText } = fmt({
103
+ type: errorMessage !== "" ? "M_ERROR_NULL" : "M_GENERAL_NULL",
104
+ title: `${title} [${dateFormat}]`,
105
+ titleColor,
106
+ titleTypography,
107
+ titleVariant,
108
+ content,
109
+ contentColor,
110
+ contentTypography,
111
+ contentVariant,
112
+ borderColor,
113
+ hint: `${hint ? `${hint} ` : ""}${defaultValue ? `Default: ${defaultValue}` : ""}`,
114
+ hintPlaceholderColor,
115
+ variantOptions,
116
+ errorMessage
117
+ });
118
+ const questionLines = countLines(questionText);
119
+ linesToDelete = questionLines + 1;
120
+ msg({
121
+ type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
122
+ title: questionText
123
+ });
124
+ if (errorMessage !== "") {
125
+ deleteLastLine();
126
+ deleteLastLine();
127
+ }
128
+ const answerInput = await rl.question(`${re.dim(symbols.middle)} `);
129
+ if (answerInput === null) {
130
+ rl.close();
131
+ if (endTitle !== "") {
132
+ msg({
133
+ type: "M_END",
134
+ title: endTitle,
135
+ titleColor: endTitleColor,
136
+ titleTypography,
137
+ border,
138
+ borderColor
139
+ });
140
+ }
141
+ process.exit(0);
142
+ }
143
+ const answer = answerInput.trim() || defaultValue;
144
+ if (errorMessage !== "") {
145
+ deleteLastLine();
146
+ }
147
+ deleteLastLine();
148
+ msg({
149
+ type: "M_MIDDLE",
150
+ title: ` ${answer}`,
151
+ titleColor: "none"
152
+ });
153
+ if (!(regexDDMMYYYY.test(answer) || regexMMDDYYYY.test(answer) || regexYYYYMMDD.test(answer))) {
154
+ if (errorMessage !== "") {
155
+ deleteLastLine();
156
+ deleteLastLine();
157
+ }
158
+ errorMessage = `Please enter a valid date in ${dateFormat} format.`;
159
+ msg({ type: "M_ERROR", title: errorMessage });
160
+ linesToDelete = countLines(errorMessage) + 1;
161
+ continue;
162
+ }
163
+ let matchedFormat = null;
164
+ if (regexDDMMYYYY.test(answer)) {
165
+ matchedFormat = "DD.MM.YYYY";
166
+ } else if (regexMMDDYYYY.test(answer)) {
167
+ matchedFormat = "MM/DD/YYYY";
168
+ } else if (regexYYYYMMDD.test(answer)) {
169
+ matchedFormat = "YYYY.MM.DD";
170
+ }
171
+ if (dateKind === "birthday" && matchedFormat) {
172
+ const parts = answer.split(/[./-]/);
173
+ let date;
174
+ if (matchedFormat === "DD.MM.YYYY") {
175
+ date = new Date(
176
+ Number(parts[2]),
177
+ Number(parts[1]) - 1,
178
+ Number(parts[0])
179
+ );
180
+ } else if (matchedFormat === "MM/DD/YYYY") {
181
+ date = new Date(
182
+ Number(parts[2]),
183
+ Number(parts[0]) - 1,
184
+ Number(parts[1])
185
+ );
186
+ } else if (matchedFormat === "YYYY.MM.DD") {
187
+ date = new Date(
188
+ Number(parts[0]),
189
+ Number(parts[1]) - 1,
190
+ Number(parts[2])
191
+ );
192
+ } else {
193
+ date = new Date(answer);
194
+ }
195
+ if (Number.isNaN(date.getTime()) || date.getFullYear() < 1900 || date > /* @__PURE__ */ new Date()) {
196
+ errorMessage = "Please enter a valid birthday date (e.g., 14.09.1999).";
197
+ msg({ type: "M_ERROR", title: errorMessage });
198
+ linesToDelete = countLines(errorMessage) + 1;
199
+ continue;
200
+ }
201
+ }
202
+ let isValid = true;
203
+ let gotError = false;
204
+ if (errorMessage !== "") {
205
+ gotError = true;
206
+ }
207
+ errorMessage = "";
208
+ if (validate && isValid) {
209
+ const validation = await validate(answer);
210
+ if (validation !== true) {
211
+ isValid = false;
212
+ errorMessage = typeof validation === "string" ? validation : "Invalid input.";
213
+ msg({ type: "M_ERROR", title: errorMessage });
214
+ gotError = true;
215
+ linesToDelete = countLines(errorMessage) + 1;
216
+ continue;
217
+ }
218
+ }
219
+ if (isValid) {
220
+ if (gotError) {
221
+ deleteLastLine();
222
+ deleteLastLine();
223
+ msg({ type: "M_MIDDLE", title: ` ${answer}` });
224
+ }
225
+ msg({
226
+ type: "M_BAR",
227
+ borderColor
228
+ });
229
+ rl.close();
230
+ return answer;
231
+ }
232
+ }
233
+ } finally {
234
+ rl.close();
235
+ }
236
+ }
@@ -0,0 +1,25 @@
1
+ import type { EditorExitResult } from "../../core-types.js";
2
+ type EditorConfig = {
3
+ syntaxHighlighting?: boolean;
4
+ theme?: "auto" | "light" | "dark";
5
+ defaultAllowSaveAs?: boolean;
6
+ defaultAllowOpen?: boolean;
7
+ defaultAutoCloseOnSave?: boolean;
8
+ defaultReturnContentOnSave?: boolean;
9
+ [key: string]: any;
10
+ };
11
+ type EditorOptions = {
12
+ filename?: string | null;
13
+ initialContent?: string | null;
14
+ onSave?: (content: string, filename: string | null) => Promise<string | boolean | undefined> | string | boolean | undefined;
15
+ onExit?: (content: string | null, saved: boolean, filename: string | null) => Promise<void> | void;
16
+ configOverrides?: Partial<EditorConfig>;
17
+ allowSaveAs?: boolean;
18
+ allowOpen?: boolean;
19
+ autoCloseOnSave?: boolean;
20
+ returnContentOnSave?: boolean;
21
+ mode?: string;
22
+ cwd?: string;
23
+ };
24
+ export declare function startEditor(options?: EditorOptions): Promise<EditorExitResult>;
25
+ export {};