mepcli 0.2.7 → 0.4.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/README.md +25 -3
- package/dist/ansi.d.ts +3 -0
- package/dist/ansi.js +4 -0
- package/dist/base.d.ts +11 -0
- package/dist/base.js +38 -157
- package/dist/core.d.ts +2 -1
- package/dist/core.js +8 -3
- package/dist/input.d.ts +1 -0
- package/dist/input.js +62 -8
- package/dist/prompts/checkbox.d.ts +2 -1
- package/dist/prompts/checkbox.js +19 -4
- package/dist/prompts/confirm.d.ts +2 -1
- package/dist/prompts/confirm.js +6 -0
- package/dist/prompts/date.d.ts +3 -1
- package/dist/prompts/date.js +64 -32
- package/dist/prompts/file.js +3 -2
- package/dist/prompts/list.js +2 -1
- package/dist/prompts/multi-select.d.ts +2 -1
- package/dist/prompts/multi-select.js +20 -4
- package/dist/prompts/number.d.ts +2 -1
- package/dist/prompts/number.js +24 -1
- package/dist/prompts/rating.d.ts +8 -0
- package/dist/prompts/rating.js +78 -0
- package/dist/prompts/select.d.ts +2 -1
- package/dist/prompts/select.js +18 -2
- package/dist/prompts/slider.d.ts +2 -1
- package/dist/prompts/slider.js +16 -1
- package/dist/prompts/text.js +2 -32
- package/dist/prompts/toggle.d.ts +2 -1
- package/dist/prompts/toggle.js +6 -0
- package/dist/symbols.d.ts +21 -0
- package/dist/symbols.js +29 -0
- package/dist/types.d.ts +14 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +38 -7
- package/example.ts +14 -5
- package/package.json +4 -4
package/dist/prompts/date.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.DatePrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: Date Prompt ---
|
|
8
9
|
class DatePrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -26,7 +27,7 @@ class DatePrompt extends base_1.Prompt {
|
|
|
26
27
|
return `${theme_1.theme.main}${ansi_1.ANSI.UNDERLINE}${val}${ansi_1.ANSI.RESET}`;
|
|
27
28
|
return val;
|
|
28
29
|
});
|
|
29
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
30
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
30
31
|
const dateStr = `${display[0]}-${display[1]}-${display[2]} ${display[3]}:${display[4]}`;
|
|
31
32
|
let output = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} ${dateStr} ${theme_1.theme.muted}(Use arrows or type)${ansi_1.ANSI.RESET}`;
|
|
32
33
|
if (this.errorMsg) {
|
|
@@ -36,6 +37,18 @@ class DatePrompt extends base_1.Prompt {
|
|
|
36
37
|
}
|
|
37
38
|
handleInput(char) {
|
|
38
39
|
if (char === '\r' || char === '\n') {
|
|
40
|
+
// Min constraint check
|
|
41
|
+
if (this.options.min && this.value < this.options.min) {
|
|
42
|
+
this.errorMsg = 'Date cannot be before minimum allowed.';
|
|
43
|
+
this.render(false);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Max constraint check
|
|
47
|
+
if (this.options.max && this.value > this.options.max) {
|
|
48
|
+
this.errorMsg = 'Date cannot be after maximum allowed.';
|
|
49
|
+
this.render(false);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
39
52
|
this.submit(this.value);
|
|
40
53
|
return;
|
|
41
54
|
}
|
|
@@ -88,7 +101,16 @@ class DatePrompt extends base_1.Prompt {
|
|
|
88
101
|
else if (this.selectedField === 4)
|
|
89
102
|
d.setMinutes(Math.max(0, Math.min(59, finalVal)));
|
|
90
103
|
this.value = d;
|
|
91
|
-
|
|
104
|
+
// Check immediately after updating the value to display an error message (but still allow further input)
|
|
105
|
+
if (this.options.min && this.value < this.options.min) {
|
|
106
|
+
this.errorMsg = 'Warning: Date is before minimum.';
|
|
107
|
+
}
|
|
108
|
+
else if (this.options.max && this.value > this.options.max) {
|
|
109
|
+
this.errorMsg = 'Warning: Date is after maximum.';
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.errorMsg = '';
|
|
113
|
+
}
|
|
92
114
|
this.render(false);
|
|
93
115
|
return;
|
|
94
116
|
}
|
|
@@ -98,39 +120,49 @@ class DatePrompt extends base_1.Prompt {
|
|
|
98
120
|
if (isUp || isDown) {
|
|
99
121
|
this.inputBuffer = ''; // Reset buffer on arrow move
|
|
100
122
|
const dir = isUp ? 1 : -1;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
break;
|
|
109
|
-
case 2:
|
|
110
|
-
d.setDate(d.getDate() + dir);
|
|
111
|
-
break;
|
|
112
|
-
case 3:
|
|
113
|
-
d.setHours(d.getHours() + dir);
|
|
114
|
-
break;
|
|
115
|
-
case 4:
|
|
116
|
-
d.setMinutes(d.getMinutes() + dir);
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
let valid = true;
|
|
120
|
-
if (this.options.min && d < this.options.min) {
|
|
121
|
-
this.errorMsg = 'Date cannot be before minimum allowed.';
|
|
122
|
-
valid = false;
|
|
123
|
-
}
|
|
124
|
-
if (this.options.max && d > this.options.max) {
|
|
125
|
-
this.errorMsg = 'Date cannot be after maximum allowed.';
|
|
126
|
-
valid = false;
|
|
123
|
+
this.adjustDate(dir);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
handleMouse(event) {
|
|
127
|
+
if (event.action === 'scroll') {
|
|
128
|
+
if (event.scroll === 'up') {
|
|
129
|
+
this.adjustDate(1);
|
|
127
130
|
}
|
|
128
|
-
if (
|
|
129
|
-
this.
|
|
130
|
-
this.errorMsg = '';
|
|
131
|
+
else if (event.scroll === 'down') {
|
|
132
|
+
this.adjustDate(-1);
|
|
131
133
|
}
|
|
132
|
-
this.render(false);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
136
|
+
adjustDate(dir) {
|
|
137
|
+
const d = new Date(this.value);
|
|
138
|
+
switch (this.selectedField) {
|
|
139
|
+
case 0:
|
|
140
|
+
d.setFullYear(d.getFullYear() + dir);
|
|
141
|
+
break;
|
|
142
|
+
case 1:
|
|
143
|
+
d.setMonth(d.getMonth() + dir);
|
|
144
|
+
break;
|
|
145
|
+
case 2:
|
|
146
|
+
d.setDate(d.getDate() + dir);
|
|
147
|
+
break;
|
|
148
|
+
case 3:
|
|
149
|
+
d.setHours(d.getHours() + dir);
|
|
150
|
+
break;
|
|
151
|
+
case 4:
|
|
152
|
+
d.setMinutes(d.getMinutes() + dir);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
this.value = d;
|
|
156
|
+
if (this.options.min && this.value < this.options.min) {
|
|
157
|
+
this.errorMsg = 'Date cannot be before minimum allowed.';
|
|
158
|
+
}
|
|
159
|
+
else if (this.options.max && this.value > this.options.max) {
|
|
160
|
+
this.errorMsg = 'Date cannot be after maximum allowed.';
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
this.errorMsg = '';
|
|
164
|
+
}
|
|
165
|
+
this.render(false);
|
|
166
|
+
}
|
|
135
167
|
}
|
|
136
168
|
exports.DatePrompt = DatePrompt;
|
package/dist/prompts/file.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.FilePrompt = void 0;
|
|
|
37
37
|
const ansi_1 = require("../ansi");
|
|
38
38
|
const base_1 = require("../base");
|
|
39
39
|
const theme_1 = require("../theme");
|
|
40
|
+
const symbols_1 = require("../symbols");
|
|
40
41
|
const fs = __importStar(require("fs"));
|
|
41
42
|
const path = __importStar(require("path"));
|
|
42
43
|
// --- Implementation: File Prompt ---
|
|
@@ -96,7 +97,7 @@ class FilePrompt extends base_1.Prompt {
|
|
|
96
97
|
}
|
|
97
98
|
render(firstRender) {
|
|
98
99
|
// Construct string
|
|
99
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
100
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
100
101
|
let output = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} ${this.input}`;
|
|
101
102
|
// Suggestions
|
|
102
103
|
if (this.suggestions.length > 0) {
|
|
@@ -107,7 +108,7 @@ class FilePrompt extends base_1.Prompt {
|
|
|
107
108
|
if (i > 0)
|
|
108
109
|
output += '\n';
|
|
109
110
|
if (i === this.selectedSuggestion) {
|
|
110
|
-
output += `${theme_1.theme.main}
|
|
111
|
+
output += `${theme_1.theme.main}${symbols_1.symbols.pointer} ${s}${ansi_1.ANSI.RESET}`;
|
|
111
112
|
}
|
|
112
113
|
else {
|
|
113
114
|
output += ` ${s}`;
|
package/dist/prompts/list.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.ListPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: List Prompt ---
|
|
8
9
|
class ListPrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -14,7 +15,7 @@ class ListPrompt extends base_1.Prompt {
|
|
|
14
15
|
}
|
|
15
16
|
render(firstRender) {
|
|
16
17
|
// Prepare content
|
|
17
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
18
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
18
19
|
let mainLine = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
|
|
19
20
|
// Render Tags
|
|
20
21
|
if (this.value.length > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { MultiSelectOptions } from '../types';
|
|
2
|
+
import { MultiSelectOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class MultiSelectPrompt<V> extends Prompt<any[], MultiSelectOptions<V>> {
|
|
4
4
|
private selectedIndex;
|
|
5
5
|
private checkedState;
|
|
@@ -11,4 +11,5 @@ export declare class MultiSelectPrompt<V> extends Prompt<any[], MultiSelectOptio
|
|
|
11
11
|
private getFilteredChoices;
|
|
12
12
|
protected render(firstRender: boolean): void;
|
|
13
13
|
protected handleInput(char: string): void;
|
|
14
|
+
protected handleMouse(event: MouseEvent): void;
|
|
14
15
|
}
|
|
@@ -4,6 +4,7 @@ exports.MultiSelectPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: MultiSelect Prompt ---
|
|
8
9
|
class MultiSelectPrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -36,7 +37,7 @@ class MultiSelectPrompt extends base_1.Prompt {
|
|
|
36
37
|
if (this.scrollTop > choices.length - 1) {
|
|
37
38
|
this.scrollTop = Math.max(0, choices.length - this.pageSize);
|
|
38
39
|
}
|
|
39
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
40
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
40
41
|
const searchStr = this.searchBuffer ? ` ${theme_1.theme.muted}(Filter: ${this.searchBuffer})${ansi_1.ANSI.RESET}` : '';
|
|
41
42
|
output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}${searchStr}\n`;
|
|
42
43
|
if (choices.length === 0) {
|
|
@@ -48,11 +49,11 @@ class MultiSelectPrompt extends base_1.Prompt {
|
|
|
48
49
|
if (index > 0)
|
|
49
50
|
output += '\n';
|
|
50
51
|
const actualIndex = this.scrollTop + index;
|
|
51
|
-
const cursor = actualIndex === this.selectedIndex ? `${theme_1.theme.main}
|
|
52
|
+
const cursor = actualIndex === this.selectedIndex ? `${theme_1.theme.main}${symbols_1.symbols.pointer}${ansi_1.ANSI.RESET}` : ' ';
|
|
52
53
|
const isChecked = this.checkedState[choice.originalIndex];
|
|
53
54
|
const checkbox = isChecked
|
|
54
|
-
? `${theme_1.theme.success}
|
|
55
|
-
: `${theme_1.theme.muted}
|
|
55
|
+
? `${theme_1.theme.success}${symbols_1.symbols.checked}${ansi_1.ANSI.RESET}`
|
|
56
|
+
: `${theme_1.theme.muted}${symbols_1.symbols.unchecked}${ansi_1.ANSI.RESET}`;
|
|
56
57
|
output += `${cursor} ${checkbox} ${choice.title}`;
|
|
57
58
|
});
|
|
58
59
|
}
|
|
@@ -119,5 +120,20 @@ class MultiSelectPrompt extends base_1.Prompt {
|
|
|
119
120
|
this.render(false);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
123
|
+
handleMouse(event) {
|
|
124
|
+
const choices = this.getFilteredChoices();
|
|
125
|
+
if (choices.length === 0)
|
|
126
|
+
return;
|
|
127
|
+
if (event.action === 'scroll') {
|
|
128
|
+
if (event.scroll === 'up') {
|
|
129
|
+
this.selectedIndex = (this.selectedIndex - 1 + choices.length) % choices.length;
|
|
130
|
+
this.render(false);
|
|
131
|
+
}
|
|
132
|
+
else if (event.scroll === 'down') {
|
|
133
|
+
this.selectedIndex = (this.selectedIndex + 1) % choices.length;
|
|
134
|
+
this.render(false);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
122
138
|
}
|
|
123
139
|
exports.MultiSelectPrompt = MultiSelectPrompt;
|
package/dist/prompts/number.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { NumberOptions } from '../types';
|
|
2
|
+
import { NumberOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class NumberPrompt extends Prompt<number, NumberOptions> {
|
|
4
4
|
private stringValue;
|
|
5
5
|
private cursor;
|
|
@@ -7,4 +7,5 @@ export declare class NumberPrompt extends Prompt<number, NumberOptions> {
|
|
|
7
7
|
constructor(options: NumberOptions);
|
|
8
8
|
protected render(firstRender: boolean): void;
|
|
9
9
|
protected handleInput(char: string): void;
|
|
10
|
+
protected handleMouse(event: MouseEvent): void;
|
|
10
11
|
}
|
package/dist/prompts/number.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.NumberPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: Number Prompt ---
|
|
8
9
|
class NumberPrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -18,7 +19,7 @@ class NumberPrompt extends base_1.Prompt {
|
|
|
18
19
|
}
|
|
19
20
|
render(firstRender) {
|
|
20
21
|
// Prepare content
|
|
21
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
22
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
22
23
|
// Prefix
|
|
23
24
|
let output = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
|
|
24
25
|
// Value
|
|
@@ -129,5 +130,27 @@ class NumberPrompt extends base_1.Prompt {
|
|
|
129
130
|
this.render(false);
|
|
130
131
|
}
|
|
131
132
|
}
|
|
133
|
+
handleMouse(event) {
|
|
134
|
+
if (event.action === 'scroll') {
|
|
135
|
+
let num = parseFloat(this.stringValue) || 0;
|
|
136
|
+
const step = this.options.step ?? 1;
|
|
137
|
+
if (event.scroll === 'up') {
|
|
138
|
+
num += step;
|
|
139
|
+
if (this.options.max !== undefined && num > this.options.max)
|
|
140
|
+
num = this.options.max;
|
|
141
|
+
}
|
|
142
|
+
else if (event.scroll === 'down') {
|
|
143
|
+
num -= step;
|
|
144
|
+
if (this.options.min !== undefined && num < this.options.min)
|
|
145
|
+
num = this.options.min;
|
|
146
|
+
}
|
|
147
|
+
// Round to avoid float errors
|
|
148
|
+
num = Math.round(num * 10000) / 10000;
|
|
149
|
+
this.stringValue = num.toString();
|
|
150
|
+
this.cursor = this.stringValue.length;
|
|
151
|
+
this.errorMsg = '';
|
|
152
|
+
this.render(false);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
132
155
|
}
|
|
133
156
|
exports.NumberPrompt = NumberPrompt;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { RatingOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class RatingPrompt extends Prompt<number, RatingOptions> {
|
|
4
|
+
constructor(options: RatingOptions);
|
|
5
|
+
protected render(firstRender: boolean): void;
|
|
6
|
+
protected handleInput(char: string): void;
|
|
7
|
+
protected handleMouse(event: MouseEvent): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RatingPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
8
|
+
class RatingPrompt extends base_1.Prompt {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
// Default to min if initial is not provided
|
|
12
|
+
this.value = options.initial ?? (options.min || 1);
|
|
13
|
+
}
|
|
14
|
+
render(firstRender) {
|
|
15
|
+
const min = this.options.min || 1;
|
|
16
|
+
const max = this.options.max || 5;
|
|
17
|
+
// Render stars
|
|
18
|
+
let stars = '';
|
|
19
|
+
for (let i = min; i <= max; i++) {
|
|
20
|
+
if (i <= this.value) {
|
|
21
|
+
stars += `${theme_1.theme.success}${symbols_1.symbols.star}${ansi_1.ANSI.RESET} `;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
stars += `${theme_1.theme.muted}${symbols_1.symbols.starEmpty}${ansi_1.ANSI.RESET} `;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
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} ${stars}`;
|
|
28
|
+
this.renderFrame(output);
|
|
29
|
+
}
|
|
30
|
+
handleInput(char) {
|
|
31
|
+
const min = this.options.min || 1;
|
|
32
|
+
const max = this.options.max || 5;
|
|
33
|
+
if (char === '\r' || char === '\n') {
|
|
34
|
+
this.submit(this.value);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Arrow keys
|
|
38
|
+
if (this.isLeft(char) || this.isDown(char)) { // Left/Down decreases
|
|
39
|
+
if (this.value > min) {
|
|
40
|
+
this.value--;
|
|
41
|
+
this.render(false);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (this.isRight(char) || this.isUp(char)) { // Right/Up increases
|
|
45
|
+
if (this.value < max) {
|
|
46
|
+
this.value++;
|
|
47
|
+
this.render(false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Number keys (1-9)
|
|
51
|
+
const num = parseInt(char);
|
|
52
|
+
if (!isNaN(num)) {
|
|
53
|
+
if (num >= min && num <= max) {
|
|
54
|
+
this.value = num;
|
|
55
|
+
this.render(false);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
handleMouse(event) {
|
|
60
|
+
const min = this.options.min || 1;
|
|
61
|
+
const max = this.options.max || 5;
|
|
62
|
+
if (event.action === 'scroll') {
|
|
63
|
+
if (event.scroll === 'up') {
|
|
64
|
+
if (this.value < max) {
|
|
65
|
+
this.value++;
|
|
66
|
+
this.render(false);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (event.scroll === 'down') {
|
|
70
|
+
if (this.value > min) {
|
|
71
|
+
this.value--;
|
|
72
|
+
this.render(false);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.RatingPrompt = RatingPrompt;
|
package/dist/prompts/select.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { SelectOptions } from '../types';
|
|
2
|
+
import { SelectOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class SelectPrompt<V> extends Prompt<any, SelectOptions<V>> {
|
|
4
4
|
private selectedIndex;
|
|
5
5
|
private searchBuffer;
|
|
@@ -11,4 +11,5 @@ export declare class SelectPrompt<V> extends Prompt<any, SelectOptions<V>> {
|
|
|
11
11
|
private getFilteredChoices;
|
|
12
12
|
protected render(firstRender: boolean): void;
|
|
13
13
|
protected handleInput(char: string): void;
|
|
14
|
+
protected handleMouse(event: MouseEvent): void;
|
|
14
15
|
}
|
package/dist/prompts/select.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.SelectPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: Select Prompt ---
|
|
8
9
|
class SelectPrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -80,11 +81,11 @@ class SelectPrompt extends base_1.Prompt {
|
|
|
80
81
|
if (index > 0)
|
|
81
82
|
output += '\n'; // Separator between items
|
|
82
83
|
if (this.isSeparator(choice)) {
|
|
83
|
-
output += ` ${ansi_1.ANSI.DIM}${choice.text ||
|
|
84
|
+
output += ` ${ansi_1.ANSI.DIM}${choice.text || symbols_1.symbols.line.repeat(8)}${ansi_1.ANSI.RESET}`;
|
|
84
85
|
}
|
|
85
86
|
else {
|
|
86
87
|
if (actualIndex === this.selectedIndex) {
|
|
87
|
-
output += `${theme_1.theme.main}
|
|
88
|
+
output += `${theme_1.theme.main}${symbols_1.symbols.pointer} ${choice.title}${ansi_1.ANSI.RESET}`;
|
|
88
89
|
}
|
|
89
90
|
else {
|
|
90
91
|
output += ` ${choice.title}`;
|
|
@@ -144,5 +145,20 @@ class SelectPrompt extends base_1.Prompt {
|
|
|
144
145
|
this.render(false);
|
|
145
146
|
}
|
|
146
147
|
}
|
|
148
|
+
handleMouse(event) {
|
|
149
|
+
const choices = this.getFilteredChoices();
|
|
150
|
+
if (choices.length === 0)
|
|
151
|
+
return;
|
|
152
|
+
if (event.action === 'scroll') {
|
|
153
|
+
if (event.scroll === 'up') {
|
|
154
|
+
this.selectedIndex = this.findNextSelectableIndex(this.selectedIndex, -1);
|
|
155
|
+
this.render(false);
|
|
156
|
+
}
|
|
157
|
+
else if (event.scroll === 'down') {
|
|
158
|
+
this.selectedIndex = this.findNextSelectableIndex(this.selectedIndex, 1);
|
|
159
|
+
this.render(false);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
147
163
|
}
|
|
148
164
|
exports.SelectPrompt = SelectPrompt;
|
package/dist/prompts/slider.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { SliderOptions } from '../types';
|
|
2
|
+
import { SliderOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class SliderPrompt extends Prompt<number, SliderOptions> {
|
|
4
4
|
constructor(options: SliderOptions);
|
|
5
5
|
protected render(firstRender: boolean): void;
|
|
6
6
|
protected handleInput(char: string): void;
|
|
7
|
+
protected handleMouse(event: MouseEvent): void;
|
|
7
8
|
}
|
package/dist/prompts/slider.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.SliderPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
// --- Implementation: Slider Prompt ---
|
|
8
9
|
class SliderPrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
@@ -20,7 +21,7 @@ class SliderPrompt extends base_1.Prompt {
|
|
|
20
21
|
if (i === pos)
|
|
21
22
|
bar += `${theme_1.theme.main}O${ansi_1.ANSI.RESET}`;
|
|
22
23
|
else
|
|
23
|
-
bar +=
|
|
24
|
+
bar += symbols_1.symbols.line;
|
|
24
25
|
}
|
|
25
26
|
const unit = this.options.unit || '';
|
|
26
27
|
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}`;
|
|
@@ -45,5 +46,19 @@ class SliderPrompt extends base_1.Prompt {
|
|
|
45
46
|
this.render(false);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
handleMouse(event) {
|
|
50
|
+
if (event.action === 'scroll') {
|
|
51
|
+
const step = this.options.step || 1;
|
|
52
|
+
if (event.scroll === 'up') { // Scroll Up -> Increase
|
|
53
|
+
this.value = Math.min(this.options.max, this.value + step);
|
|
54
|
+
}
|
|
55
|
+
if (event.scroll === 'down') { // Scroll Down -> Decrease
|
|
56
|
+
this.value = Math.max(this.options.min, this.value - step);
|
|
57
|
+
}
|
|
58
|
+
// Round to avoid float errors
|
|
59
|
+
this.value = Math.round(this.value * 10000) / 10000;
|
|
60
|
+
this.render(false);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
48
63
|
}
|
|
49
64
|
exports.SliderPrompt = SliderPrompt;
|
package/dist/prompts/text.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.TextPrompt = void 0;
|
|
|
4
4
|
const ansi_1 = require("../ansi");
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
7
8
|
const utils_1 = require("../utils");
|
|
8
9
|
// --- Implementation: Text Prompt ---
|
|
9
10
|
class TextPrompt extends base_1.Prompt {
|
|
@@ -23,7 +24,7 @@ class TextPrompt extends base_1.Prompt {
|
|
|
23
24
|
// Calculate available width
|
|
24
25
|
const cols = process.stdout.columns || 80;
|
|
25
26
|
// 1. Prepare Prompt Label
|
|
26
|
-
const icon = this.errorMsg ? `${theme_1.theme.error}
|
|
27
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
|
|
27
28
|
const hint = this.options.multiline ? ` ${theme_1.theme.muted}(Press Ctrl+D to submit)${ansi_1.ANSI.RESET}` : '';
|
|
28
29
|
const prefix = `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}${hint} `;
|
|
29
30
|
// We need visual length of prefix to calculate available space for input on the first line
|
|
@@ -76,41 +77,10 @@ class TextPrompt extends base_1.Prompt {
|
|
|
76
77
|
visualColIndex = 0;
|
|
77
78
|
}
|
|
78
79
|
else {
|
|
79
|
-
// Calculate width of this segment?
|
|
80
|
-
// No, for simple text editor logic we often assume 1 char = 1 pos unless we do full layout.
|
|
81
|
-
// But here we want correct cursor placement over wide chars.
|
|
82
|
-
// So we should sum width.
|
|
83
|
-
// However, standard terminals handle wide chars by advancing cursor 2 spots.
|
|
84
|
-
// So we just need to sum the string length of the segment?
|
|
85
|
-
// Or 2 if it's wide?
|
|
86
|
-
// Standard terminal behavior:
|
|
87
|
-
// If I write an Emoji (2 cols), the cursor advances 2 cols.
|
|
88
|
-
// So visualColIndex should track stringWidth(seg).
|
|
89
|
-
// But if isPassword, it's '*'. Width 1.
|
|
90
80
|
if (this.options.isPassword) {
|
|
91
81
|
visualColIndex += 1;
|
|
92
82
|
}
|
|
93
83
|
else {
|
|
94
|
-
// Use our helper? Or just length?
|
|
95
|
-
// If we used stringWidth, it would be accurate.
|
|
96
|
-
// But we don't have access to stringWidth here easily unless we import it again (we did in base).
|
|
97
|
-
// Let's assume segment.length for now (byte length),
|
|
98
|
-
// because `\x1b[<N>C` moves N COLUMNS? No, N characters?
|
|
99
|
-
// ANSI `CUB` / `CUF` moves N *columns* usually?
|
|
100
|
-
// "The Cursor Forward (CUF) sequence moves the cursor forward by n columns."
|
|
101
|
-
// So if we have an emoji (2 cols), we need to move past it.
|
|
102
|
-
// If we print an emoji, cursor is at +2.
|
|
103
|
-
// Wait, if we use `renderFrame`, we rewrite everything.
|
|
104
|
-
// Then we calculate where to put the cursor.
|
|
105
|
-
// If line is "A <Emoji> B".
|
|
106
|
-
// Output: "A <Emoji> B".
|
|
107
|
-
// If cursor is after Emoji.
|
|
108
|
-
// We need to be at position: width("A") + width("<Emoji>").
|
|
109
|
-
// = 1 + 2 = 3.
|
|
110
|
-
// So `visualColIndex` should use `stringWidth(seg)`.
|
|
111
|
-
// But I didn't export `stringWidth` from `utils.ts` in the last step?
|
|
112
|
-
// Checking `src/utils.ts`... I did export it.
|
|
113
|
-
// But I need to import it here.
|
|
114
84
|
visualColIndex += this.options.isPassword ? 1 : this.getSegmentWidth(seg);
|
|
115
85
|
}
|
|
116
86
|
}
|
package/dist/prompts/toggle.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Prompt } from '../base';
|
|
2
|
-
import { ToggleOptions } from '../types';
|
|
2
|
+
import { ToggleOptions, MouseEvent } from '../types';
|
|
3
3
|
export declare class TogglePrompt extends Prompt<boolean, ToggleOptions> {
|
|
4
4
|
constructor(options: ToggleOptions);
|
|
5
5
|
protected render(firstRender: boolean): void;
|
|
6
6
|
protected handleInput(char: string): void;
|
|
7
|
+
protected handleMouse(event: MouseEvent): void;
|
|
7
8
|
}
|
package/dist/prompts/toggle.js
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface SymbolDefinition {
|
|
2
|
+
/** Used for success messages or valid states */
|
|
3
|
+
tick: string;
|
|
4
|
+
/** Used for error messages or invalid states */
|
|
5
|
+
cross: string;
|
|
6
|
+
/** Used to point to the current selection */
|
|
7
|
+
pointer: string;
|
|
8
|
+
/** Used for separators or sliders */
|
|
9
|
+
line: string;
|
|
10
|
+
/** Used for checked state in checkboxes/radio */
|
|
11
|
+
checked: string;
|
|
12
|
+
/** Used for unchecked state in checkboxes/radio */
|
|
13
|
+
unchecked: string;
|
|
14
|
+
/** Animation frames for the spinner */
|
|
15
|
+
spinner: string[];
|
|
16
|
+
/** Star symbol for rating */
|
|
17
|
+
star: string;
|
|
18
|
+
/** Empty star symbol for rating */
|
|
19
|
+
starEmpty: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const symbols: SymbolDefinition;
|
package/dist/symbols.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.symbols = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const UnicodeSymbols = {
|
|
6
|
+
tick: '✔',
|
|
7
|
+
cross: '✖',
|
|
8
|
+
pointer: '❯',
|
|
9
|
+
line: '─',
|
|
10
|
+
checked: '◉',
|
|
11
|
+
unchecked: '◯',
|
|
12
|
+
spinner: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
|
|
13
|
+
star: '★',
|
|
14
|
+
starEmpty: '☆'
|
|
15
|
+
};
|
|
16
|
+
const AsciiSymbols = {
|
|
17
|
+
tick: '+',
|
|
18
|
+
cross: 'x',
|
|
19
|
+
pointer: '>',
|
|
20
|
+
line: '-',
|
|
21
|
+
checked: '[x]',
|
|
22
|
+
unchecked: '[ ]',
|
|
23
|
+
spinner: ['|', '/', '-', '\\'],
|
|
24
|
+
star: '*',
|
|
25
|
+
starEmpty: ' '
|
|
26
|
+
};
|
|
27
|
+
const capabilities = (0, utils_1.detectCapabilities)();
|
|
28
|
+
const useUnicode = capabilities.hasUnicode && process.env.MEP_NO_UNICODE !== '1';
|
|
29
|
+
exports.symbols = useUnicode ? UnicodeSymbols : AsciiSymbols;
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,15 @@ export interface ThemeConfig {
|
|
|
10
10
|
}
|
|
11
11
|
export interface BaseOptions {
|
|
12
12
|
message: string;
|
|
13
|
+
mouse?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface MouseEvent {
|
|
16
|
+
name: 'mouse';
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
button: number;
|
|
20
|
+
action: 'press' | 'release' | 'move' | 'scroll';
|
|
21
|
+
scroll?: 'up' | 'down';
|
|
13
22
|
}
|
|
14
23
|
export interface TextOptions extends BaseOptions {
|
|
15
24
|
placeholder?: string;
|
|
@@ -65,6 +74,11 @@ export interface SliderOptions extends BaseOptions {
|
|
|
65
74
|
step?: number;
|
|
66
75
|
unit?: string;
|
|
67
76
|
}
|
|
77
|
+
export interface RatingOptions extends BaseOptions {
|
|
78
|
+
min?: number;
|
|
79
|
+
max?: number;
|
|
80
|
+
initial?: number;
|
|
81
|
+
}
|
|
68
82
|
export interface DateOptions extends BaseOptions {
|
|
69
83
|
initial?: Date;
|
|
70
84
|
min?: Date;
|