mepcli 0.2.1 → 0.2.6

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.
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ListPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ // --- Implementation: List Prompt ---
8
+ class ListPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.currentInput = '';
12
+ this.errorMsg = '';
13
+ this.value = options.initial || [];
14
+ }
15
+ render(firstRender) {
16
+ // Prepare content
17
+ const icon = this.errorMsg ? `${theme_1.theme.error}✖` : `${theme_1.theme.success}?`;
18
+ let mainLine = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
19
+ // Render Tags
20
+ if (this.value.length > 0) {
21
+ this.value.forEach((tag) => {
22
+ mainLine += `${theme_1.theme.main}[${tag}]${ansi_1.ANSI.RESET} `;
23
+ });
24
+ }
25
+ // Render Current Input
26
+ mainLine += `${this.currentInput}`;
27
+ let output = mainLine;
28
+ if (this.errorMsg) {
29
+ output += `\n${theme_1.theme.error}>> ${this.errorMsg}${ansi_1.ANSI.RESET}`;
30
+ }
31
+ // Use Double Buffering
32
+ this.renderFrame(output);
33
+ this.print(ansi_1.ANSI.SHOW_CURSOR);
34
+ // If we printed an error, the cursor is at the end of the error line.
35
+ // We need to move it back to the end of the input line.
36
+ if (this.errorMsg) {
37
+ // Move up one line (since error is always on the next line in this simple implementation)
38
+ this.print(ansi_1.ANSI.UP);
39
+ // Move to the correct column.
40
+ // We need to calculate visual length of mainLine to place cursor correctly.
41
+ // stripAnsi is available in base class now.
42
+ const visualLength = this.stripAnsi(mainLine).length;
43
+ this.print(ansi_1.ANSI.CURSOR_LEFT); // Go to start
44
+ if (visualLength > 0) {
45
+ this.print(`\x1b[${visualLength}C`);
46
+ }
47
+ }
48
+ }
49
+ handleInput(char) {
50
+ if (char === '\r' || char === '\n') {
51
+ if (this.currentInput.trim()) {
52
+ this.value.push(this.currentInput.trim());
53
+ this.currentInput = '';
54
+ this.errorMsg = '';
55
+ this.render(false);
56
+ }
57
+ else {
58
+ // Done if input is empty
59
+ if (this.options.validate) {
60
+ const result = this.options.validate(this.value);
61
+ if (result !== true) {
62
+ this.errorMsg = typeof result === 'string' ? result : 'Invalid input';
63
+ this.render(false);
64
+ return;
65
+ }
66
+ }
67
+ this.submit(this.value);
68
+ }
69
+ return;
70
+ }
71
+ if (char === '\u0008' || char === '\x7f') { // Backspace
72
+ if (this.currentInput.length > 0) {
73
+ this.currentInput = this.currentInput.slice(0, -1);
74
+ this.render(false);
75
+ }
76
+ else if (this.value.length > 0) {
77
+ this.value.pop();
78
+ this.render(false);
79
+ }
80
+ return;
81
+ }
82
+ if (!/^[\x00-\x1F]/.test(char) && !char.startsWith('\x1b')) {
83
+ this.currentInput += char;
84
+ this.render(false);
85
+ }
86
+ }
87
+ }
88
+ exports.ListPrompt = ListPrompt;
@@ -0,0 +1,14 @@
1
+ import { Prompt } from '../base';
2
+ import { MultiSelectOptions } from '../types';
3
+ export declare class MultiSelectPrompt extends Prompt<any[], MultiSelectOptions> {
4
+ private selectedIndex;
5
+ private checkedState;
6
+ private searchBuffer;
7
+ private scrollTop;
8
+ private readonly pageSize;
9
+ private errorMsg;
10
+ constructor(options: MultiSelectOptions);
11
+ private getFilteredChoices;
12
+ protected render(firstRender: boolean): void;
13
+ protected handleInput(char: string): void;
14
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MultiSelectPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ // --- Implementation: MultiSelect Prompt ---
8
+ class MultiSelectPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.selectedIndex = 0;
12
+ this.searchBuffer = '';
13
+ this.scrollTop = 0;
14
+ this.pageSize = 7;
15
+ this.errorMsg = '';
16
+ this.checkedState = options.choices.map(c => !!c.selected);
17
+ this.selectedIndex = 0;
18
+ }
19
+ getFilteredChoices() {
20
+ if (!this.searchBuffer)
21
+ return this.options.choices.map((c, i) => ({ ...c, originalIndex: i }));
22
+ return this.options.choices
23
+ .map((c, i) => ({ ...c, originalIndex: i }))
24
+ .filter(c => c.title.toLowerCase().includes(this.searchBuffer.toLowerCase()));
25
+ }
26
+ render(firstRender) {
27
+ let output = '';
28
+ const choices = this.getFilteredChoices();
29
+ // Adjust Scroll
30
+ if (this.selectedIndex < this.scrollTop) {
31
+ this.scrollTop = this.selectedIndex;
32
+ }
33
+ else if (this.selectedIndex >= this.scrollTop + this.pageSize) {
34
+ this.scrollTop = this.selectedIndex - this.pageSize + 1;
35
+ }
36
+ if (this.scrollTop > choices.length - 1) {
37
+ this.scrollTop = Math.max(0, choices.length - this.pageSize);
38
+ }
39
+ const icon = this.errorMsg ? `${theme_1.theme.error}✖` : `${theme_1.theme.success}?`;
40
+ const searchStr = this.searchBuffer ? ` ${theme_1.theme.muted}(Filter: ${this.searchBuffer})${ansi_1.ANSI.RESET}` : '';
41
+ output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}${searchStr}\n`;
42
+ if (choices.length === 0) {
43
+ output += ` ${theme_1.theme.muted}No results found${ansi_1.ANSI.RESET}`; // No newline at end
44
+ }
45
+ else {
46
+ const visible = choices.slice(this.scrollTop, this.scrollTop + this.pageSize);
47
+ visible.forEach((choice, index) => {
48
+ if (index > 0)
49
+ output += '\n';
50
+ const actualIndex = this.scrollTop + index;
51
+ const cursor = actualIndex === this.selectedIndex ? `${theme_1.theme.main}❯${ansi_1.ANSI.RESET}` : ' ';
52
+ const isChecked = this.checkedState[choice.originalIndex];
53
+ const checkbox = isChecked
54
+ ? `${theme_1.theme.success}◉${ansi_1.ANSI.RESET}`
55
+ : `${theme_1.theme.muted}◯${ansi_1.ANSI.RESET}`;
56
+ output += `${cursor} ${checkbox} ${choice.title}`;
57
+ });
58
+ }
59
+ if (this.errorMsg) {
60
+ output += `\n${theme_1.theme.error}>> ${this.errorMsg}${ansi_1.ANSI.RESET}`;
61
+ }
62
+ this.renderFrame(output);
63
+ }
64
+ handleInput(char) {
65
+ const choices = this.getFilteredChoices();
66
+ if (char === '\r' || char === '\n') {
67
+ const selectedCount = this.checkedState.filter(Boolean).length;
68
+ const { min = 0, max } = this.options;
69
+ if (selectedCount < min) {
70
+ this.errorMsg = `Select at least ${min}.`;
71
+ this.render(false);
72
+ return;
73
+ }
74
+ if (max && selectedCount > max) {
75
+ this.errorMsg = `Max ${max} allowed.`;
76
+ this.render(false);
77
+ return;
78
+ }
79
+ const results = this.options.choices
80
+ .filter((_, i) => this.checkedState[i])
81
+ .map(c => c.value);
82
+ this.submit(results);
83
+ return;
84
+ }
85
+ if (char === ' ') {
86
+ if (choices.length > 0) {
87
+ const choice = choices[this.selectedIndex];
88
+ const originalIndex = choice.originalIndex;
89
+ this.checkedState[originalIndex] = !this.checkedState[originalIndex];
90
+ this.render(false);
91
+ }
92
+ return;
93
+ }
94
+ if (this.isUp(char)) { // Up
95
+ if (choices.length > 0) {
96
+ this.selectedIndex = (this.selectedIndex - 1 + choices.length) % choices.length;
97
+ this.render(false);
98
+ }
99
+ return;
100
+ }
101
+ if (this.isDown(char)) { // Down
102
+ if (choices.length > 0) {
103
+ this.selectedIndex = (this.selectedIndex + 1) % choices.length;
104
+ this.render(false);
105
+ }
106
+ return;
107
+ }
108
+ if (char === '\u0008' || char === '\x7f') { // Backspace
109
+ if (this.searchBuffer.length > 0) {
110
+ this.searchBuffer = this.searchBuffer.slice(0, -1);
111
+ this.selectedIndex = 0;
112
+ this.render(false);
113
+ }
114
+ return;
115
+ }
116
+ if (!/^[\x00-\x1F]/.test(char) && !char.startsWith('\x1b')) {
117
+ this.searchBuffer += char;
118
+ this.selectedIndex = 0;
119
+ this.render(false);
120
+ }
121
+ }
122
+ }
123
+ exports.MultiSelectPrompt = MultiSelectPrompt;
@@ -0,0 +1,10 @@
1
+ import { Prompt } from '../base';
2
+ import { NumberOptions } from '../types';
3
+ export declare class NumberPrompt extends Prompt<number, NumberOptions> {
4
+ private stringValue;
5
+ private cursor;
6
+ private errorMsg;
7
+ constructor(options: NumberOptions);
8
+ protected render(firstRender: boolean): void;
9
+ protected handleInput(char: string): void;
10
+ }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NumberPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ // --- Implementation: Number Prompt ---
8
+ class NumberPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.stringValue = '';
12
+ this.cursor = 0;
13
+ this.errorMsg = '';
14
+ // We work with string for editing, but value property stores the parsed number ultimately
15
+ // Initialize stringValue from initial
16
+ this.stringValue = options.initial !== undefined ? options.initial.toString() : '';
17
+ this.cursor = this.stringValue.length;
18
+ }
19
+ render(firstRender) {
20
+ // Prepare content
21
+ const icon = this.errorMsg ? `${theme_1.theme.error}✖` : `${theme_1.theme.success}?`;
22
+ // Prefix
23
+ let output = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
24
+ // Value
25
+ output += `${theme_1.theme.main}${this.stringValue}${ansi_1.ANSI.RESET}`;
26
+ if (this.errorMsg) {
27
+ output += `\n${theme_1.theme.error}>> ${this.errorMsg}${ansi_1.ANSI.RESET}`;
28
+ }
29
+ this.renderFrame(output);
30
+ this.print(ansi_1.ANSI.SHOW_CURSOR);
31
+ // Restore cursor position
32
+ // If errorMsg, we are on the line below the input.
33
+ if (this.errorMsg) {
34
+ this.print(ansi_1.ANSI.UP);
35
+ }
36
+ // Calculate visual offset
37
+ const prefix = `${icon} ${theme_1.theme.title}${this.options.message} `;
38
+ const prefixLen = this.stripAnsi(prefix).length;
39
+ const targetCol = prefixLen + this.cursor;
40
+ this.print(ansi_1.ANSI.CURSOR_LEFT);
41
+ if (targetCol > 0) {
42
+ this.print(`\x1b[${targetCol}C`);
43
+ }
44
+ }
45
+ handleInput(char) {
46
+ // Enter
47
+ if (char === '\r' || char === '\n') {
48
+ const num = parseFloat(this.stringValue);
49
+ if (this.stringValue.trim() === '' || isNaN(num)) {
50
+ // Check if empty is allowed?
51
+ // If not required? Assuming required for number prompt usually
52
+ this.errorMsg = 'Please enter a valid number.';
53
+ this.render(false);
54
+ return;
55
+ }
56
+ if (this.options.min !== undefined && num < this.options.min) {
57
+ this.errorMsg = `Minimum value is ${this.options.min}`;
58
+ this.render(false);
59
+ return;
60
+ }
61
+ if (this.options.max !== undefined && num > this.options.max) {
62
+ this.errorMsg = `Maximum value is ${this.options.max}`;
63
+ this.render(false);
64
+ return;
65
+ }
66
+ this.submit(num);
67
+ return;
68
+ }
69
+ // Up Arrow (Increment)
70
+ if (this.isUp(char)) {
71
+ let num = parseFloat(this.stringValue) || 0;
72
+ num += (this.options.step ?? 1);
73
+ if (this.options.max !== undefined && num > this.options.max)
74
+ num = this.options.max;
75
+ // Round to avoid float errors
76
+ num = Math.round(num * 10000) / 10000;
77
+ this.stringValue = num.toString();
78
+ this.cursor = this.stringValue.length;
79
+ this.errorMsg = '';
80
+ this.render(false);
81
+ return;
82
+ }
83
+ // Down Arrow (Decrement)
84
+ if (this.isDown(char)) {
85
+ let num = parseFloat(this.stringValue) || 0;
86
+ num -= (this.options.step ?? 1);
87
+ if (this.options.min !== undefined && num < this.options.min)
88
+ num = this.options.min;
89
+ // Round to avoid float errors
90
+ num = Math.round(num * 10000) / 10000;
91
+ this.stringValue = num.toString();
92
+ this.cursor = this.stringValue.length;
93
+ this.errorMsg = '';
94
+ this.render(false);
95
+ return;
96
+ }
97
+ // Backspace
98
+ if (char === '\u0008' || char === '\x7f') {
99
+ if (this.cursor > 0) {
100
+ this.stringValue = this.stringValue.slice(0, this.cursor - 1) + this.stringValue.slice(this.cursor);
101
+ this.cursor--;
102
+ this.errorMsg = '';
103
+ this.render(false);
104
+ }
105
+ return;
106
+ }
107
+ // Arrow Left
108
+ if (this.isLeft(char)) {
109
+ if (this.cursor > 0) {
110
+ this.cursor--;
111
+ this.render(false);
112
+ }
113
+ return;
114
+ }
115
+ // Arrow Right
116
+ if (this.isRight(char)) {
117
+ if (this.cursor < this.stringValue.length) {
118
+ this.cursor++;
119
+ this.render(false);
120
+ }
121
+ return;
122
+ }
123
+ // Numeric Input (and . and -)
124
+ if (/^[0-9.\-]+$/.test(char)) {
125
+ // Allow if it looks like a number part
126
+ this.stringValue = this.stringValue.slice(0, this.cursor) + char + this.stringValue.slice(this.cursor);
127
+ this.cursor += char.length;
128
+ this.errorMsg = '';
129
+ this.render(false);
130
+ }
131
+ }
132
+ }
133
+ exports.NumberPrompt = NumberPrompt;
@@ -0,0 +1,14 @@
1
+ import { Prompt } from '../base';
2
+ import { SelectOptions } from '../types';
3
+ export declare class SelectPrompt extends Prompt<any, SelectOptions> {
4
+ private selectedIndex;
5
+ private searchBuffer;
6
+ private scrollTop;
7
+ private readonly pageSize;
8
+ constructor(options: SelectOptions);
9
+ private isSeparator;
10
+ private findNextSelectableIndex;
11
+ private getFilteredChoices;
12
+ protected render(firstRender: boolean): void;
13
+ protected handleInput(char: string): void;
14
+ }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ // --- Implementation: Select Prompt ---
8
+ class SelectPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.selectedIndex = 0;
12
+ this.searchBuffer = '';
13
+ this.scrollTop = 0;
14
+ this.pageSize = 7;
15
+ // Find first non-separator index
16
+ this.selectedIndex = this.findNextSelectableIndex(-1, 1);
17
+ }
18
+ isSeparator(item) {
19
+ return item && item.separator === true;
20
+ }
21
+ findNextSelectableIndex(currentIndex, direction) {
22
+ let nextIndex = currentIndex + direction;
23
+ const choices = this.getFilteredChoices();
24
+ // Loop around logic
25
+ if (nextIndex < 0)
26
+ nextIndex = choices.length - 1;
27
+ if (nextIndex >= choices.length)
28
+ nextIndex = 0;
29
+ if (choices.length === 0)
30
+ return 0;
31
+ // Safety check to prevent infinite loop if all are separators (shouldn't happen in practice)
32
+ let count = 0;
33
+ while (this.isSeparator(choices[nextIndex]) && count < choices.length) {
34
+ nextIndex += direction;
35
+ if (nextIndex < 0)
36
+ nextIndex = choices.length - 1;
37
+ if (nextIndex >= choices.length)
38
+ nextIndex = 0;
39
+ count++;
40
+ }
41
+ return nextIndex;
42
+ }
43
+ getFilteredChoices() {
44
+ if (!this.searchBuffer)
45
+ return this.options.choices;
46
+ return this.options.choices.filter(c => {
47
+ if (this.isSeparator(c))
48
+ return false; // Hide separators when searching
49
+ return c.title.toLowerCase().includes(this.searchBuffer.toLowerCase());
50
+ });
51
+ }
52
+ render(firstRender) {
53
+ let output = '';
54
+ const choices = this.getFilteredChoices();
55
+ // Adjust Scroll Top
56
+ if (this.selectedIndex < this.scrollTop) {
57
+ this.scrollTop = this.selectedIndex;
58
+ }
59
+ else if (this.selectedIndex >= this.scrollTop + this.pageSize) {
60
+ this.scrollTop = this.selectedIndex - this.pageSize + 1;
61
+ }
62
+ // Handle Filtering Edge Case: if list shrinks, scrollTop might be too high
63
+ if (this.scrollTop > choices.length - 1) {
64
+ this.scrollTop = Math.max(0, choices.length - this.pageSize);
65
+ }
66
+ // Header
67
+ const searchStr = this.searchBuffer ? ` ${theme_1.theme.muted}(Filter: ${this.searchBuffer})${ansi_1.ANSI.RESET}` : '';
68
+ // Note: We avoid ERASE_LINE here because renderFrame handles full redraw
69
+ output += `${theme_1.theme.success}?${ansi_1.ANSI.RESET} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}${searchStr}\n`;
70
+ if (choices.length === 0) {
71
+ output += ` ${theme_1.theme.muted}No results found${ansi_1.ANSI.RESET}`;
72
+ // We can omit newline at the very end if we want, but usually it's better to be consistent.
73
+ // renderFrame adds newline via truncate logic? No, it joins.
74
+ // So if I want a line break, I must add it.
75
+ }
76
+ else {
77
+ const visibleChoices = choices.slice(this.scrollTop, this.scrollTop + this.pageSize);
78
+ visibleChoices.forEach((choice, index) => {
79
+ const actualIndex = this.scrollTop + index;
80
+ if (index > 0)
81
+ output += '\n'; // Separator between items
82
+ if (this.isSeparator(choice)) {
83
+ output += ` ${ansi_1.ANSI.DIM}${choice.text || '────────'}${ansi_1.ANSI.RESET}`;
84
+ }
85
+ else {
86
+ if (actualIndex === this.selectedIndex) {
87
+ output += `${theme_1.theme.main}❯ ${choice.title}${ansi_1.ANSI.RESET}`;
88
+ }
89
+ else {
90
+ output += ` ${choice.title}`;
91
+ }
92
+ }
93
+ });
94
+ }
95
+ // No manual printing. Pass to renderFrame.
96
+ this.renderFrame(output);
97
+ }
98
+ handleInput(char) {
99
+ const choices = this.getFilteredChoices();
100
+ if (char === '\r' || char === '\n') {
101
+ if (choices.length === 0) {
102
+ this.searchBuffer = '';
103
+ this.selectedIndex = this.findNextSelectableIndex(-1, 1);
104
+ this.render(false);
105
+ return;
106
+ }
107
+ if (this.isSeparator(choices[this.selectedIndex]))
108
+ return;
109
+ this.cleanup();
110
+ // Cursor is shown by cleanup
111
+ if (this._resolve)
112
+ this._resolve(choices[this.selectedIndex].value);
113
+ return;
114
+ }
115
+ if (this.isUp(char)) { // Up
116
+ if (choices.length > 0) {
117
+ this.selectedIndex = this.findNextSelectableIndex(this.selectedIndex, -1);
118
+ this.render(false);
119
+ }
120
+ return;
121
+ }
122
+ if (this.isDown(char)) { // Down
123
+ if (choices.length > 0) {
124
+ this.selectedIndex = this.findNextSelectableIndex(this.selectedIndex, 1);
125
+ this.render(false);
126
+ }
127
+ return;
128
+ }
129
+ // Backspace
130
+ if (char === '\u0008' || char === '\x7f') {
131
+ if (this.searchBuffer.length > 0) {
132
+ this.searchBuffer = this.searchBuffer.slice(0, -1);
133
+ this.selectedIndex = 0; // Reset selection
134
+ this.selectedIndex = this.findNextSelectableIndex(-1, 1);
135
+ this.render(false);
136
+ }
137
+ return;
138
+ }
139
+ // Typing
140
+ if (char.length === 1 && !/^[\x00-\x1F]/.test(char)) {
141
+ this.searchBuffer += char;
142
+ this.selectedIndex = 0; // Reset selection
143
+ this.selectedIndex = this.findNextSelectableIndex(-1, 1);
144
+ this.render(false);
145
+ }
146
+ }
147
+ }
148
+ exports.SelectPrompt = SelectPrompt;
@@ -0,0 +1,7 @@
1
+ import { Prompt } from '../base';
2
+ import { SliderOptions } from '../types';
3
+ export declare class SliderPrompt extends Prompt<number, SliderOptions> {
4
+ constructor(options: SliderOptions);
5
+ protected render(firstRender: boolean): void;
6
+ protected handleInput(char: string): void;
7
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SliderPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ // --- Implementation: Slider Prompt ---
8
+ class SliderPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.value = options.initial ?? options.min;
12
+ }
13
+ render(firstRender) {
14
+ const width = 20;
15
+ const range = this.options.max - this.options.min;
16
+ const ratio = (this.value - this.options.min) / range;
17
+ const pos = Math.round(ratio * width);
18
+ let bar = '';
19
+ for (let i = 0; i <= width; i++) {
20
+ if (i === pos)
21
+ bar += `${theme_1.theme.main}O${ansi_1.ANSI.RESET}`;
22
+ else
23
+ bar += '─';
24
+ }
25
+ const unit = this.options.unit || '';
26
+ const output = `${theme_1.theme.success}?${ansi_1.ANSI.RESET} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} [${bar}] ${this.value}${unit}`;
27
+ this.renderFrame(output);
28
+ }
29
+ handleInput(char) {
30
+ if (char === '\r' || char === '\n') {
31
+ this.submit(this.value);
32
+ return;
33
+ }
34
+ const step = this.options.step || 1;
35
+ if (this.isLeft(char)) { // Left
36
+ this.value = Math.max(this.options.min, this.value - step);
37
+ // Round to avoid float errors
38
+ this.value = Math.round(this.value * 10000) / 10000;
39
+ this.render(false);
40
+ }
41
+ if (this.isRight(char)) { // Right
42
+ this.value = Math.min(this.options.max, this.value + step);
43
+ // Round to avoid float errors
44
+ this.value = Math.round(this.value * 10000) / 10000;
45
+ this.render(false);
46
+ }
47
+ }
48
+ }
49
+ exports.SliderPrompt = SliderPrompt;
@@ -0,0 +1,13 @@
1
+ import { Prompt } from '../base';
2
+ import { TextOptions } from '../types';
3
+ export declare class TextPrompt extends Prompt<string, TextOptions> {
4
+ private errorMsg;
5
+ private cursor;
6
+ private hasTyped;
7
+ private segments;
8
+ constructor(options: TextOptions);
9
+ protected render(firstRender: boolean): void;
10
+ private getSegmentWidth;
11
+ protected handleInput(char: string): void;
12
+ private validateAndSubmit;
13
+ }