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.
@@ -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}✖` : `${theme_1.theme.success}?`;
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
- this.errorMsg = '';
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
- const d = new Date(this.value);
102
- switch (this.selectedField) {
103
- case 0:
104
- d.setFullYear(d.getFullYear() + dir);
105
- break;
106
- case 1:
107
- d.setMonth(d.getMonth() + dir);
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 (valid) {
129
- this.value = d;
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;
@@ -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}✖` : `${theme_1.theme.success}?`;
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} ${s}${ansi_1.ANSI.RESET}`;
111
+ output += `${theme_1.theme.main}${symbols_1.symbols.pointer} ${s}${ansi_1.ANSI.RESET}`;
111
112
  }
112
113
  else {
113
114
  output += ` ${s}`;
@@ -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}✖` : `${theme_1.theme.success}?`;
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}✖` : `${theme_1.theme.success}?`;
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}❯${ansi_1.ANSI.RESET}` : ' ';
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}◉${ansi_1.ANSI.RESET}`
55
- : `${theme_1.theme.muted}◯${ansi_1.ANSI.RESET}`;
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;
@@ -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
  }
@@ -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}✖` : `${theme_1.theme.success}?`;
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;
@@ -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
  }
@@ -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 || '────────'}${ansi_1.ANSI.RESET}`;
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} ${choice.title}${ansi_1.ANSI.RESET}`;
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;
@@ -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
  }
@@ -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;
@@ -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}✖` : `${theme_1.theme.success}?`;
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
  }
@@ -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
  }
@@ -37,5 +37,11 @@ class TogglePrompt extends base_1.Prompt {
37
37
  this.render(false);
38
38
  }
39
39
  }
40
+ handleMouse(event) {
41
+ if (event.action === 'scroll') {
42
+ this.value = !this.value;
43
+ this.render(false);
44
+ }
45
+ }
40
46
  }
41
47
  exports.TogglePrompt = TogglePrompt;
@@ -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;
@@ -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;