mepcli 0.2.0 → 0.2.5

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/README.md CHANGED
@@ -1,13 +1,13 @@
1
- # Mep: Minimalist CLI Prompt
1
+ # Mep
2
2
 
3
3
  **Mep** is a minimalist and zero-dependency library for creating interactive command-line prompts in Node.js. It focuses on simplicity, modern design, and robust input handling, including support for cursor movement and input validation.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - **Zero Dependency:** Keeps your project clean and fast.
8
- - **Full-Featured Prompts:** Includes `text`, `password`, `select`, ch`eckbox, and `confirm`.
9
- - **Responsive Input:** Supports cursor movement (Left/Right) and character insertion/deletion in `text` and `password` prompts.
10
- - **Validation:** Built-in support for input validation with custom error messages.
8
+ - **Comprehensive Prompts:** Includes `text`, `password`, `select`, `checkbox`, `confirm`, `number`, `toggle`, `list`, `slider`, `date`, `file`, and `multiSelect`.
9
+ - **Responsive Input:** Supports cursor movement (Left/Right) and character insertion/deletion in text-based prompts.
10
+ - **Validation:** Built-in support for input validation (sync and async) with custom error messages.
11
11
  - **Elegant Look:** Uses ANSI colors for a clean, modern CLI experience.
12
12
 
13
13
  ## Installation
@@ -21,31 +21,75 @@ yarn add mepcli
21
21
  ## Usage Example
22
22
 
23
23
  Mep provides a static class facade, `MepCLI`, for all interactions.
24
- ```javascript
24
+
25
+ ```typescript
25
26
  import { MepCLI } from 'mepcli';
26
27
 
27
- async function setup() {
28
- // Text input with validation and cursor support
29
- const projectName = await MepCLI.text({
30
- message: "Enter the project name:",
31
- validate: (v) => v.length > 5 || "Must be longer than 5 chars",
28
+ async function main() {
29
+ // Text input with validation
30
+ const name = await MepCLI.text({
31
+ message: "Enter your name:",
32
+ placeholder: "John Doe",
33
+ validate: (v) => v.length > 0 || "Name cannot be empty"
34
+ });
35
+
36
+ // Number input
37
+ const age = await MepCLI.number({
38
+ message: "How old are you?",
39
+ min: 1,
40
+ max: 120
41
+ });
42
+
43
+ // Toggle (Switch)
44
+ const newsletter = await MepCLI.toggle({
45
+ message: "Subscribe to newsletter?",
46
+ initial: true
32
47
  });
33
48
 
34
49
  // Select menu
35
- const choice = await MepCLI.select({
36
- message: "Choose an option:",
50
+ const lang = await MepCLI.select({
51
+ message: "Preferred Language:",
52
+ choices: [
53
+ { title: "JavaScript", value: "js" },
54
+ { title: "TypeScript", value: "ts" },
55
+ { title: "Python", value: "py" }
56
+ ]
57
+ });
58
+
59
+ // Checkbox (Multiple choice)
60
+ const tools = await MepCLI.checkbox({
61
+ message: "Select tools:",
37
62
  choices: [
38
- { title: "Option A", value: 1 },
39
- { title: "Option B", value: 2 }
63
+ { title: "ESLint", value: "eslint" },
64
+ { title: "Prettier", value: "prettier", selected: true },
65
+ { title: "Jest", value: "jest" }
40
66
  ]
41
67
  });
42
68
 
43
- console.log(`\nProject: ${projectName}, Selected: ${choice}`);
69
+ console.log({ name, age, newsletter, lang, tools });
44
70
  }
45
71
 
46
- setup();
72
+ main();
47
73
  ```
48
74
 
75
+ ## API Reference
76
+
77
+ ### MepCLI
78
+
79
+ * `text(options)` - Single line or multiline text input.
80
+ * `password(options)` - Masked text input.
81
+ * `number(options)` - Numeric input with increment/decrement support.
82
+ * `confirm(options)` - Yes/No question.
83
+ * `toggle(options)` - On/Off switch.
84
+ * `select(options)` - Single item selection from a list.
85
+ * `multiSelect(options)` - Multiple item selection with filtering.
86
+ * `checkbox(options)` - Classic checkbox selection.
87
+ * `list(options)` - Enter a list of tags/strings.
88
+ * `slider(options)` - Select a number within a range using a visual slider.
89
+ * `date(options)` - Date and time picker.
90
+ * `file(options)` - File system navigator and selector.
91
+ * `spin(message, promise)` - Display a spinner while waiting for a promise.
92
+
49
93
  ## License
50
94
 
51
- This project is under the **MIT License**.
95
+ This project is under the **MIT License**.
package/dist/ansi.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare const ANSI: {
7
7
  BOLD: string;
8
8
  DIM: string;
9
9
  ITALIC: string;
10
+ UNDERLINE: string;
10
11
  FG_GREEN: string;
11
12
  FG_CYAN: string;
12
13
  FG_YELLOW: string;
@@ -14,6 +15,7 @@ export declare const ANSI: {
14
15
  FG_GRAY: string;
15
16
  FG_WHITE: string;
16
17
  ERASE_LINE: string;
18
+ ERASE_DOWN: string;
17
19
  CURSOR_LEFT: string;
18
20
  HIDE_CURSOR: string;
19
21
  SHOW_CURSOR: string;
package/dist/ansi.js CHANGED
@@ -10,6 +10,7 @@ exports.ANSI = {
10
10
  BOLD: '\x1b[1m',
11
11
  DIM: '\x1b[2m',
12
12
  ITALIC: '\x1b[3m',
13
+ UNDERLINE: '\x1b[4m',
13
14
  // Colors
14
15
  FG_GREEN: '\x1b[32m',
15
16
  FG_CYAN: '\x1b[36m',
@@ -19,6 +20,7 @@ exports.ANSI = {
19
20
  FG_WHITE: '\x1b[37m',
20
21
  // Cursor & Erasing
21
22
  ERASE_LINE: '\x1b[2K', // Clear current line
23
+ ERASE_DOWN: '\x1b[J', // Clear from cursor to end of screen
22
24
  CURSOR_LEFT: '\x1b[1000D', // Move cursor to start of line
23
25
  HIDE_CURSOR: '\x1b[?25l',
24
26
  SHOW_CURSOR: '\x1b[?25h',
package/dist/base.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Abstract base class for all prompts.
3
+ * Handles common logic like stdin management, raw mode, and cleanup
4
+ * to enforce DRY (Don't Repeat Yourself) principles.
5
+ */
6
+ export declare abstract class Prompt<T, O> {
7
+ protected options: O;
8
+ protected value: any;
9
+ protected stdin: NodeJS.ReadStream;
10
+ protected stdout: NodeJS.WriteStream;
11
+ private _resolve?;
12
+ private _reject?;
13
+ private _onDataHandler?;
14
+ constructor(options: O);
15
+ /**
16
+ * Renders the UI. Must be implemented by subclasses.
17
+ * @param firstRender Indicates if this is the initial render.
18
+ */
19
+ protected abstract render(firstRender: boolean): void;
20
+ /**
21
+ * Handles specific key inputs. Must be implemented by subclasses.
22
+ * @param char The string representation of the key.
23
+ * @param key The raw buffer.
24
+ */
25
+ protected abstract handleInput(char: string, key: Buffer): void;
26
+ protected print(text: string): void;
27
+ /**
28
+ * Starts the prompt interaction.
29
+ * Sets up raw mode and listeners, returning a Promise.
30
+ */
31
+ run(): Promise<T>;
32
+ /**
33
+ * Cleans up listeners and restores stdin state.
34
+ */
35
+ protected cleanup(): void;
36
+ /**
37
+ * Submits the final value and resolves the promise.
38
+ */
39
+ protected submit(result: T): void;
40
+ protected isUp(char: string): boolean;
41
+ protected isDown(char: string): boolean;
42
+ protected isRight(char: string): boolean;
43
+ protected isLeft(char: string): boolean;
44
+ }
package/dist/base.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Prompt = void 0;
4
+ const ansi_1 = require("./ansi");
5
+ /**
6
+ * Abstract base class for all prompts.
7
+ * Handles common logic like stdin management, raw mode, and cleanup
8
+ * to enforce DRY (Don't Repeat Yourself) principles.
9
+ */
10
+ class Prompt {
11
+ constructor(options) {
12
+ this.options = options;
13
+ this.stdin = process.stdin;
14
+ this.stdout = process.stdout;
15
+ }
16
+ print(text) {
17
+ this.stdout.write(text);
18
+ }
19
+ /**
20
+ * Starts the prompt interaction.
21
+ * Sets up raw mode and listeners, returning a Promise.
22
+ */
23
+ run() {
24
+ return new Promise((resolve, reject) => {
25
+ this._resolve = resolve;
26
+ this._reject = reject;
27
+ if (typeof this.stdin.setRawMode === 'function') {
28
+ this.stdin.setRawMode(true);
29
+ }
30
+ this.stdin.resume();
31
+ this.stdin.setEncoding('utf8');
32
+ // Initial render: Default to hidden cursor (good for menus)
33
+ // Subclasses like TextPrompt will explicitly show it if needed.
34
+ this.print(ansi_1.ANSI.HIDE_CURSOR);
35
+ this.render(true);
36
+ this._onDataHandler = (buffer) => {
37
+ const char = buffer.toString();
38
+ // Global Exit Handler (Ctrl+C)
39
+ if (char === '\u0003') {
40
+ this.cleanup();
41
+ this.print(ansi_1.ANSI.SHOW_CURSOR + '\n');
42
+ if (this._reject)
43
+ this._reject(new Error('User force closed'));
44
+ return;
45
+ }
46
+ this.handleInput(char, buffer);
47
+ };
48
+ this.stdin.on('data', this._onDataHandler);
49
+ });
50
+ }
51
+ /**
52
+ * Cleans up listeners and restores stdin state.
53
+ */
54
+ cleanup() {
55
+ if (this._onDataHandler) {
56
+ this.stdin.removeListener('data', this._onDataHandler);
57
+ }
58
+ if (typeof this.stdin.setRawMode === 'function') {
59
+ this.stdin.setRawMode(false);
60
+ }
61
+ this.stdin.pause();
62
+ this.print(ansi_1.ANSI.SHOW_CURSOR);
63
+ }
64
+ /**
65
+ * Submits the final value and resolves the promise.
66
+ */
67
+ submit(result) {
68
+ this.cleanup();
69
+ this.print('\n');
70
+ if (this._resolve)
71
+ this._resolve(result);
72
+ }
73
+ // Helper to check for arrow keys including application mode
74
+ isUp(char) {
75
+ return char === '\u001b[A' || char === '\u001bOA';
76
+ }
77
+ isDown(char) {
78
+ return char === '\u001b[B' || char === '\u001bOB';
79
+ }
80
+ isRight(char) {
81
+ return char === '\u001b[C' || char === '\u001bOC';
82
+ }
83
+ isLeft(char) {
84
+ return char === '\u001b[D' || char === '\u001bOD';
85
+ }
86
+ }
87
+ exports.Prompt = Prompt;
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TextOptions, SelectOptions, ConfirmOptions, CheckboxOptions, ThemeConfig, NumberOptions, ToggleOptions } from './types';
1
+ import { TextOptions, SelectOptions, ConfirmOptions, CheckboxOptions, ThemeConfig, NumberOptions, ToggleOptions, ListOptions, SliderOptions, DateOptions, FileOptions, MultiSelectOptions } from './types';
2
2
  /**
3
3
  * Public Facade for MepCLI
4
4
  */
@@ -15,4 +15,9 @@ export declare class MepCLI {
15
15
  static password(options: TextOptions): Promise<string>;
16
16
  static number(options: NumberOptions): Promise<number>;
17
17
  static toggle(options: ToggleOptions): Promise<boolean>;
18
+ static list(options: ListOptions): Promise<string[]>;
19
+ static slider(options: SliderOptions): Promise<number>;
20
+ static date(options: DateOptions): Promise<Date>;
21
+ static file(options: FileOptions): Promise<string>;
22
+ static multiSelect(options: MultiSelectOptions): Promise<any[]>;
18
23
  }