mepcli 0.6.1 → 1.0.0-beta.2

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 (113) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +512 -326
  3. package/dist/ansi.d.ts +8 -0
  4. package/dist/ansi.js +8 -0
  5. package/dist/base.d.ts +21 -0
  6. package/dist/base.js +57 -0
  7. package/dist/core.d.ts +48 -1
  8. package/dist/core.js +156 -0
  9. package/dist/data/licenses.d.ts +2 -0
  10. package/dist/data/licenses.js +109 -0
  11. package/dist/highlight.js +58 -26
  12. package/dist/index.d.ts +36 -0
  13. package/dist/index.js +36 -0
  14. package/dist/input.js +0 -3
  15. package/dist/prompts/box.d.ts +21 -0
  16. package/dist/prompts/box.js +192 -0
  17. package/dist/prompts/breadcrumb.d.ts +22 -0
  18. package/dist/prompts/breadcrumb.js +302 -0
  19. package/dist/prompts/byte.d.ts +13 -0
  20. package/dist/prompts/byte.js +159 -0
  21. package/dist/prompts/calculator.d.ts +16 -0
  22. package/dist/prompts/calculator.js +213 -0
  23. package/dist/prompts/calendar.js +0 -5
  24. package/dist/prompts/code.d.ts +2 -0
  25. package/dist/prompts/code.js +104 -70
  26. package/dist/prompts/connection-string.d.ts +18 -0
  27. package/dist/prompts/connection-string.js +97 -0
  28. package/dist/prompts/curl.d.ts +39 -0
  29. package/dist/prompts/curl.js +285 -0
  30. package/dist/prompts/data-inspector.d.ts +22 -0
  31. package/dist/prompts/data-inspector.js +256 -0
  32. package/dist/prompts/dependency.d.ts +16 -0
  33. package/dist/prompts/dependency.js +265 -0
  34. package/dist/prompts/dial.d.ts +10 -0
  35. package/dist/prompts/dial.js +110 -0
  36. package/dist/prompts/diff.d.ts +10 -0
  37. package/dist/prompts/diff.js +101 -0
  38. package/dist/prompts/draw.d.ts +20 -0
  39. package/dist/prompts/draw.js +188 -0
  40. package/dist/prompts/editor.js +0 -4
  41. package/dist/prompts/emoji.d.ts +18 -0
  42. package/dist/prompts/emoji.js +228 -0
  43. package/dist/prompts/exec.d.ts +13 -0
  44. package/dist/prompts/exec.js +83 -0
  45. package/dist/prompts/fuzzy.d.ts +12 -0
  46. package/dist/prompts/fuzzy.js +136 -0
  47. package/dist/prompts/gauge.d.ts +21 -0
  48. package/dist/prompts/gauge.js +130 -0
  49. package/dist/prompts/heatmap.d.ts +13 -0
  50. package/dist/prompts/heatmap.js +141 -0
  51. package/dist/prompts/ip.d.ts +11 -0
  52. package/dist/prompts/ip.js +118 -0
  53. package/dist/prompts/kanban.d.ts +17 -0
  54. package/dist/prompts/kanban.js +228 -0
  55. package/dist/prompts/keypress.js +0 -2
  56. package/dist/prompts/license.d.ts +9 -0
  57. package/dist/prompts/license.js +105 -0
  58. package/dist/prompts/map.d.ts +15 -0
  59. package/dist/prompts/map.js +199 -0
  60. package/dist/prompts/match.d.ts +19 -0
  61. package/dist/prompts/match.js +275 -0
  62. package/dist/prompts/miller.d.ts +15 -0
  63. package/dist/prompts/miller.js +221 -0
  64. package/dist/prompts/multi-column-select.d.ts +10 -0
  65. package/dist/prompts/multi-column-select.js +166 -0
  66. package/dist/prompts/number.js +0 -2
  67. package/dist/prompts/otp.d.ts +10 -0
  68. package/dist/prompts/otp.js +91 -0
  69. package/dist/prompts/pattern.d.ts +22 -0
  70. package/dist/prompts/pattern.js +249 -0
  71. package/dist/prompts/quiz-select.d.ts +10 -0
  72. package/dist/prompts/quiz-select.js +104 -0
  73. package/dist/prompts/quiz-text.d.ts +11 -0
  74. package/dist/prompts/quiz-text.js +82 -0
  75. package/dist/prompts/regex.d.ts +13 -0
  76. package/dist/prompts/regex.js +131 -0
  77. package/dist/prompts/region.d.ts +11 -0
  78. package/dist/prompts/region.js +164 -0
  79. package/dist/prompts/schedule.d.ts +18 -0
  80. package/dist/prompts/schedule.js +221 -0
  81. package/dist/prompts/scroll.d.ts +13 -0
  82. package/dist/prompts/scroll.js +152 -0
  83. package/dist/prompts/seat.d.ts +17 -0
  84. package/dist/prompts/seat.js +165 -0
  85. package/dist/prompts/select-range.d.ts +8 -0
  86. package/dist/prompts/select-range.js +136 -0
  87. package/dist/prompts/select.d.ts +9 -9
  88. package/dist/prompts/semver.d.ts +6 -0
  89. package/dist/prompts/semver.js +32 -0
  90. package/dist/prompts/shortcut.d.ts +9 -0
  91. package/dist/prompts/shortcut.js +135 -0
  92. package/dist/prompts/slot.d.ts +16 -0
  93. package/dist/prompts/slot.js +107 -0
  94. package/dist/prompts/snippet.js +0 -3
  95. package/dist/prompts/sort-grid.d.ts +16 -0
  96. package/dist/prompts/sort-grid.js +146 -0
  97. package/dist/prompts/sort.js +0 -1
  98. package/dist/prompts/spreadsheet.d.ts +21 -0
  99. package/dist/prompts/spreadsheet.js +239 -0
  100. package/dist/prompts/text.d.ts +9 -7
  101. package/dist/prompts/text.js +52 -0
  102. package/dist/prompts/time.d.ts +12 -0
  103. package/dist/prompts/time.js +202 -0
  104. package/dist/prompts/tree-select.d.ts +0 -1
  105. package/dist/prompts/tree-select.js +1 -5
  106. package/dist/symbols.d.ts +12 -0
  107. package/dist/symbols.js +14 -2
  108. package/dist/theme.js +10 -1
  109. package/dist/types.d.ts +264 -1
  110. package/dist/utils.d.ts +53 -0
  111. package/dist/utils.js +252 -0
  112. package/package.json +51 -47
  113. package/example.ts +0 -390
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataInspectorPrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ const utils_1 = require("../utils");
8
+ const symbols_1 = require("../symbols");
9
+ class DataInspectorPrompt extends base_1.Prompt {
10
+ constructor(options) {
11
+ super(options);
12
+ this.cursor = 0;
13
+ this.flatList = [];
14
+ this.expandedPaths = new Set();
15
+ this.scrollTop = 0;
16
+ this.pageSize = 15;
17
+ // Edit Mode State
18
+ this.editMode = false;
19
+ this.editBuffer = '';
20
+ this.rootData = options.data; // We mutate this directly
21
+ this.expandedPaths.add('root'); // Always expand root if it's an object
22
+ this.recalculateFlatList();
23
+ }
24
+ getType(value) {
25
+ if (value === null)
26
+ return 'null';
27
+ if (value === undefined)
28
+ return 'undefined';
29
+ if (Array.isArray(value))
30
+ return 'array';
31
+ if (value instanceof Date)
32
+ return 'date';
33
+ return typeof value;
34
+ }
35
+ recalculateFlatList() {
36
+ this.flatList = [];
37
+ this.traverse(this.rootData, 'root', 0, null, 'root');
38
+ }
39
+ traverse(data, key, depth, parentRef, currentPath) {
40
+ const type = this.getType(data);
41
+ const isLeaf = !['object', 'array'].includes(type) || data === null;
42
+ const node = {
43
+ key: String(key),
44
+ value: data,
45
+ type,
46
+ depth,
47
+ path: currentPath,
48
+ parentRef,
49
+ refKey: key,
50
+ isLeaf
51
+ };
52
+ this.flatList.push(node);
53
+ if (!isLeaf && this.expandedPaths.has(currentPath)) {
54
+ const keys = Object.keys(data);
55
+ keys.forEach(k => {
56
+ this.traverse(data[k], k, depth + 1, data, `${currentPath}.${k}`);
57
+ });
58
+ }
59
+ }
60
+ getValueColor(type) {
61
+ switch (type) {
62
+ case 'string': return ansi_1.ANSI.FG_GREEN;
63
+ case 'number': return ansi_1.ANSI.FG_YELLOW;
64
+ case 'boolean': return ansi_1.ANSI.FG_MAGENTA;
65
+ case 'null':
66
+ case 'undefined': return ansi_1.ANSI.FG_GRAY;
67
+ case 'date': return ansi_1.ANSI.FG_BLUE;
68
+ default: return ansi_1.ANSI.RESET;
69
+ }
70
+ }
71
+ formatValue(value, type) {
72
+ if (type === 'string')
73
+ return `"${value}"`;
74
+ if (type === 'date')
75
+ return value.toISOString();
76
+ if (type === 'array')
77
+ return `Array(${value.length})`;
78
+ if (type === 'object')
79
+ return `Object{${Object.keys(value).length}}`;
80
+ return String(value);
81
+ }
82
+ render(_firstRender) {
83
+ let output = `${theme_1.theme.success}?${ansi_1.ANSI.RESET} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
84
+ if (this.cursor < this.scrollTop) {
85
+ this.scrollTop = this.cursor;
86
+ }
87
+ else if (this.cursor >= this.scrollTop + this.pageSize) {
88
+ this.scrollTop = this.cursor - this.pageSize + 1;
89
+ }
90
+ const visible = this.flatList.slice(this.scrollTop, this.scrollTop + this.pageSize);
91
+ visible.forEach((node, index) => {
92
+ const actualIndex = this.scrollTop + index;
93
+ const isSelected = actualIndex === this.cursor;
94
+ // Indentation & Tree Lines
95
+ const indent = ' '.repeat(node.depth);
96
+ const prefix = isSelected ? `${theme_1.theme.main}${symbols_1.symbols.pointer} ` : ' ';
97
+ // Icon
98
+ let icon = '';
99
+ if (!node.isLeaf) {
100
+ icon = this.expandedPaths.has(node.path) ? '▾ ' : '▸ ';
101
+ }
102
+ else {
103
+ icon = '• '; // Leaf
104
+ }
105
+ // Key
106
+ let keyStr = node.key;
107
+ if (node.path === 'root')
108
+ keyStr = 'ROOT';
109
+ // Value Representation
110
+ let valueStr = '';
111
+ if (isSelected && this.editMode) {
112
+ // Editing View
113
+ valueStr = `${ansi_1.ANSI.BG_BLUE}${ansi_1.ANSI.FG_WHITE} ${this.editBuffer}_ ${ansi_1.ANSI.RESET}`;
114
+ }
115
+ else {
116
+ // Normal View
117
+ const color = this.getValueColor(node.type);
118
+ const formatted = this.formatValue(node.value, node.type);
119
+ valueStr = `${color}${formatted}${ansi_1.ANSI.RESET}`;
120
+ }
121
+ // Type Label (Right aligned or just dimmed next to key)
122
+ const typeLabel = `${ansi_1.ANSI.FG_GRAY}(${node.type})${ansi_1.ANSI.RESET}`;
123
+ let line = `${indent}${icon}${ansi_1.ANSI.BOLD}${keyStr}${ansi_1.ANSI.RESET}: ${valueStr} ${typeLabel}`;
124
+ if (isSelected && !this.editMode) {
125
+ line = `${theme_1.theme.main}${(0, utils_1.stripAnsi)(line)}${ansi_1.ANSI.RESET}`; // Highlight whole line
126
+ }
127
+ else if (isSelected && this.editMode) {
128
+ // In edit mode, we don't highlight the whole line, just the input box
129
+ line = `${indent}${icon}${ansi_1.ANSI.BOLD}${keyStr}${ansi_1.ANSI.RESET}: ${valueStr} ${typeLabel}`;
130
+ }
131
+ output += `${prefix}${line}\n`;
132
+ });
133
+ // Footer
134
+ if (this.editMode) {
135
+ output += `\n${theme_1.theme.main}EDIT MODE${ansi_1.ANSI.RESET} Enter: Save, Esc: Cancel`;
136
+ }
137
+ else {
138
+ output += `\n${theme_1.theme.muted}(Arrows: Nav, Space: Toggle, Enter: Edit/Submit)${ansi_1.ANSI.RESET}`;
139
+ }
140
+ this.renderFrame(output);
141
+ }
142
+ handleInput(char, key) {
143
+ if (this.editMode) {
144
+ this.handleEditInput(char, key);
145
+ return;
146
+ }
147
+ const node = this.flatList[this.cursor];
148
+ if (this.isUp(char)) {
149
+ this.cursor = (this.cursor - 1 + this.flatList.length) % this.flatList.length;
150
+ this.render(false);
151
+ return;
152
+ }
153
+ if (this.isDown(char)) {
154
+ this.cursor = (this.cursor + 1) % this.flatList.length;
155
+ this.render(false);
156
+ return;
157
+ }
158
+ // Expand/Collapse
159
+ if (char === ' ' || this.isRight(char) || this.isLeft(char)) {
160
+ if (!node.isLeaf) {
161
+ const isExpanded = this.expandedPaths.has(node.path);
162
+ if (this.isRight(char) && !isExpanded) {
163
+ this.expandedPaths.add(node.path);
164
+ }
165
+ else if (this.isLeft(char) && isExpanded) {
166
+ this.expandedPaths.delete(node.path);
167
+ }
168
+ else if (char === ' ') {
169
+ if (isExpanded)
170
+ this.expandedPaths.delete(node.path);
171
+ else
172
+ this.expandedPaths.add(node.path);
173
+ }
174
+ else if (this.isLeft(char) && !isExpanded && node.parentRef) {
175
+ // Jump to parent
176
+ // This requires finding parent index, but simplification: just do nothing or standard logic
177
+ }
178
+ this.recalculateFlatList();
179
+ this.render(false);
180
+ }
181
+ return;
182
+ }
183
+ // Enter: Edit or Submit
184
+ if (char === '\r' || char === '\n') {
185
+ if (node.path === 'root') {
186
+ this.submit(this.rootData);
187
+ return;
188
+ }
189
+ // Toggle Boolean immediately
190
+ if (node.type === 'boolean') {
191
+ const newVal = !node.value;
192
+ node.parentRef[node.refKey] = newVal;
193
+ this.recalculateFlatList(); // Value changed
194
+ this.render(false);
195
+ return;
196
+ }
197
+ // Enter Edit Mode for String/Number
198
+ if (['string', 'number'].includes(node.type)) {
199
+ this.editMode = true;
200
+ this.editBuffer = String(node.value);
201
+ this.render(false);
202
+ return;
203
+ }
204
+ this.submit(this.rootData);
205
+ }
206
+ }
207
+ handleEditInput(char, key) {
208
+ const node = this.flatList[this.cursor];
209
+ // Enter: Save
210
+ if (char === '\r' || char === '\n') {
211
+ let newValue = this.editBuffer;
212
+ if (node.type === 'number') {
213
+ newValue = Number(this.editBuffer);
214
+ if (isNaN(newValue))
215
+ newValue = 0; // Fallback
216
+ }
217
+ // Update Data
218
+ node.parentRef[node.refKey] = newValue;
219
+ this.editMode = false;
220
+ this.recalculateFlatList();
221
+ this.render(false);
222
+ return;
223
+ }
224
+ // Esc: Cancel
225
+ if (key[0] === 27 && key.length === 1) { // Standard ESC
226
+ this.editMode = false;
227
+ this.render(false);
228
+ return;
229
+ }
230
+ // Backspace
231
+ if (key.toString() === '\x7f' || char === '\b') {
232
+ this.editBuffer = this.editBuffer.slice(0, -1);
233
+ this.render(false);
234
+ return;
235
+ }
236
+ // Typing
237
+ if (char && char.length === 1 && char.charCodeAt(0) >= 32) {
238
+ this.editBuffer += char;
239
+ this.render(false);
240
+ }
241
+ }
242
+ handleMouse(event) {
243
+ if (this.editMode)
244
+ return; // Disable scroll in edit mode for now
245
+ if (event.action === 'scroll') {
246
+ if (event.scroll === 'up') {
247
+ this.cursor = (this.cursor - 1 + this.flatList.length) % this.flatList.length;
248
+ }
249
+ else if (event.scroll === 'down') {
250
+ this.cursor = (this.cursor + 1) % this.flatList.length;
251
+ }
252
+ this.render(false);
253
+ }
254
+ }
255
+ }
256
+ exports.DataInspectorPrompt = DataInspectorPrompt;
@@ -0,0 +1,16 @@
1
+ import { Prompt } from '../base';
2
+ import { DependencyOptions, MouseEvent } from '../types';
3
+ export declare class DependencyPrompt<V> extends Prompt<V[], DependencyOptions<V>> {
4
+ private selectedIndex;
5
+ private checkedState;
6
+ private errorMsg;
7
+ private warningMsg;
8
+ private scrollTop;
9
+ private readonly pageSize;
10
+ constructor(options: DependencyOptions<V>);
11
+ private resolveDependencies;
12
+ protected render(_firstRender: boolean): void;
13
+ protected handleMouse(event: MouseEvent): void;
14
+ protected handleInput(char: string): void;
15
+ private validateDependencies;
16
+ }
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DependencyPrompt = 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 DependencyPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.selectedIndex = 0;
12
+ this.errorMsg = '';
13
+ this.warningMsg = '';
14
+ // Pagination state
15
+ this.scrollTop = 0;
16
+ this.pageSize = 10;
17
+ // Initialize checked state from options (default selected)
18
+ // We also need to run initial validation/resolution
19
+ this.checkedState = options.choices.map(c => !!c.selected);
20
+ if (options.autoResolve !== false) {
21
+ // Run resolution for all initially selected items
22
+ this.checkedState.forEach((isChecked, i) => {
23
+ if (isChecked) {
24
+ this.resolveDependencies(i, true);
25
+ }
26
+ });
27
+ }
28
+ }
29
+ resolveDependencies(index, value) {
30
+ // If autoResolve is false, we don't do anything automatically,
31
+ // validation will handle it on submit.
32
+ if (this.options.autoResolve === false)
33
+ return;
34
+ const choices = this.options.choices;
35
+ const visited = new Set();
36
+ const queue = [];
37
+ queue.push({ idx: index, val: value });
38
+ // Process queue
39
+ let loops = 0;
40
+ while (queue.length > 0 && loops < 1000) { // Safety break
41
+ loops++;
42
+ const current = queue.shift();
43
+ if (visited.has(current.idx))
44
+ continue;
45
+ // Apply state
46
+ // Only if it changes state
47
+ if (this.checkedState[current.idx] !== current.val) {
48
+ this.checkedState[current.idx] = current.val;
49
+ if (current.reason) {
50
+ this.warningMsg = current.reason;
51
+ }
52
+ }
53
+ visited.add(current.idx);
54
+ const currentItem = choices[current.idx];
55
+ if (current.val) {
56
+ // Turning ON
57
+ // 1. Check Conflicts (Disable them)
58
+ if (currentItem.conflictsWith) {
59
+ currentItem.conflictsWith.forEach(conflictVal => {
60
+ const conflictIdx = choices.findIndex(c => c.value === conflictVal);
61
+ if (conflictIdx !== -1 && this.checkedState[conflictIdx]) {
62
+ queue.push({
63
+ idx: conflictIdx,
64
+ val: false,
65
+ reason: `Disabled ${choices[conflictIdx].title} due to conflict with ${currentItem.title}`
66
+ });
67
+ }
68
+ });
69
+ }
70
+ // 2. Check Dependencies (Enable them)
71
+ if (currentItem.dependsOn) {
72
+ currentItem.dependsOn.forEach(depVal => {
73
+ const depIdx = choices.findIndex(c => c.value === depVal);
74
+ if (depIdx !== -1 && !this.checkedState[depIdx]) {
75
+ queue.push({
76
+ idx: depIdx,
77
+ val: true,
78
+ reason: `Enabled ${choices[depIdx].title} because ${currentItem.title} requires it`
79
+ });
80
+ }
81
+ });
82
+ }
83
+ // 3. Check Triggers (Enable them)
84
+ if (currentItem.triggers) {
85
+ currentItem.triggers.forEach(trigVal => {
86
+ const trigIdx = choices.findIndex(c => c.value === trigVal);
87
+ if (trigIdx !== -1 && !this.checkedState[trigIdx]) {
88
+ queue.push({
89
+ idx: trigIdx,
90
+ val: true,
91
+ reason: `Triggered ${choices[trigIdx].title} from ${currentItem.title}`
92
+ });
93
+ }
94
+ });
95
+ }
96
+ }
97
+ else {
98
+ // Turning OFF
99
+ // Check if other ON items depend on this one. If so, disable them.
100
+ choices.forEach((other, otherIdx) => {
101
+ if (this.checkedState[otherIdx] && other.dependsOn && other.dependsOn.includes(currentItem.value)) {
102
+ queue.push({
103
+ idx: otherIdx,
104
+ val: false,
105
+ reason: `Disabled ${other.title} because it depends on ${currentItem.title}`
106
+ });
107
+ }
108
+ });
109
+ }
110
+ }
111
+ }
112
+ render(_firstRender) {
113
+ // Adjust Scroll Top
114
+ if (this.selectedIndex < this.scrollTop) {
115
+ this.scrollTop = this.selectedIndex;
116
+ }
117
+ else if (this.selectedIndex >= this.scrollTop + this.pageSize) {
118
+ this.scrollTop = this.selectedIndex - this.pageSize + 1;
119
+ }
120
+ if (this.options.choices.length <= this.pageSize) {
121
+ this.scrollTop = 0;
122
+ }
123
+ let output = '';
124
+ // Header
125
+ const icon = this.errorMsg ? `${theme_1.theme.error}${symbols_1.symbols.cross}` : `${theme_1.theme.success}?`;
126
+ output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} ${theme_1.theme.muted}(Space: toggle, Enter: submit)${ansi_1.ANSI.RESET}`;
127
+ // List
128
+ const choices = this.options.choices;
129
+ const visibleChoices = choices.slice(this.scrollTop, this.scrollTop + this.pageSize);
130
+ visibleChoices.forEach((choice, index) => {
131
+ const actualIndex = this.scrollTop + index;
132
+ output += '\n'; // New line for each item
133
+ const cursor = actualIndex === this.selectedIndex ? `${theme_1.theme.main}${symbols_1.symbols.pointer}${ansi_1.ANSI.RESET}` : ' ';
134
+ const isChecked = this.checkedState[actualIndex];
135
+ const checkbox = isChecked
136
+ ? `${theme_1.theme.success}${symbols_1.symbols.checked}${ansi_1.ANSI.RESET}`
137
+ : `${theme_1.theme.muted}${symbols_1.symbols.unchecked}${ansi_1.ANSI.RESET}`;
138
+ let title = actualIndex === this.selectedIndex
139
+ ? `${theme_1.theme.main}${choice.title}${ansi_1.ANSI.RESET}`
140
+ : choice.title;
141
+ // Add tags for relationships
142
+ if (choice.dependsOn && choice.dependsOn.length > 0) {
143
+ title += ` ${theme_1.theme.muted}[Req: ${choice.dependsOn.length}]${ansi_1.ANSI.RESET}`;
144
+ }
145
+ if (choice.conflictsWith && choice.conflictsWith.length > 0) {
146
+ title += ` ${theme_1.theme.error}[Con: ${choice.conflictsWith.length}]${ansi_1.ANSI.RESET}`;
147
+ }
148
+ output += `${cursor} ${checkbox} ${title}`;
149
+ });
150
+ if (this.errorMsg) {
151
+ output += `\n${theme_1.theme.error}>> ${this.errorMsg}${ansi_1.ANSI.RESET}`;
152
+ }
153
+ else if (this.warningMsg) {
154
+ output += `\n${theme_1.theme.main}>> ${this.warningMsg}${ansi_1.ANSI.RESET}`;
155
+ }
156
+ this.renderFrame(output);
157
+ }
158
+ handleMouse(event) {
159
+ if (event.action === 'scroll') {
160
+ if (event.scroll === 'up') {
161
+ this.selectedIndex = this.selectedIndex > 0 ? this.selectedIndex - 1 : this.options.choices.length - 1;
162
+ this.render(false);
163
+ }
164
+ else if (event.scroll === 'down') {
165
+ this.selectedIndex = this.selectedIndex < this.options.choices.length - 1 ? this.selectedIndex + 1 : 0;
166
+ this.render(false);
167
+ }
168
+ }
169
+ }
170
+ handleInput(char) {
171
+ if (char === '\r' || char === '\n') {
172
+ // Final Validation
173
+ const selectedCount = this.checkedState.filter(Boolean).length;
174
+ const { min = 0, max } = this.options;
175
+ if (selectedCount < min) {
176
+ this.errorMsg = `You must select at least ${min} options.`;
177
+ this.render(false);
178
+ return;
179
+ }
180
+ if (max && selectedCount > max) {
181
+ this.errorMsg = `You can only select up to ${max} options.`;
182
+ this.render(false);
183
+ return;
184
+ }
185
+ // Dependency Logic Check (if autoResolve was off, or double check)
186
+ // Even if autoResolve is on, we check for cycles or invalid states that might have slipped?
187
+ // Or just check if manual toggle left things broken (if autoResolve is OFF).
188
+ if (this.options.autoResolve === false) {
189
+ const invalid = this.validateDependencies();
190
+ if (invalid) {
191
+ this.errorMsg = invalid;
192
+ this.render(false);
193
+ return;
194
+ }
195
+ }
196
+ this.cleanup();
197
+ const results = this.options.choices
198
+ .filter((_, i) => this.checkedState[i])
199
+ .map(c => c.value);
200
+ this.submit(results);
201
+ return;
202
+ }
203
+ // Space Toggle
204
+ if (char === ' ') {
205
+ const currentChecked = this.checkedState[this.selectedIndex];
206
+ // Toggle
207
+ const newState = !currentChecked;
208
+ // Check Max limit before enabling
209
+ if (newState) {
210
+ const selectedCount = this.checkedState.filter(Boolean).length;
211
+ const { max } = this.options;
212
+ if (max && selectedCount >= max) {
213
+ this.errorMsg = `Max ${max} selections allowed.`;
214
+ this.render(false);
215
+ return;
216
+ }
217
+ }
218
+ this.errorMsg = '';
219
+ this.warningMsg = '';
220
+ if (this.options.autoResolve !== false) {
221
+ this.resolveDependencies(this.selectedIndex, newState);
222
+ }
223
+ else {
224
+ this.checkedState[this.selectedIndex] = newState;
225
+ }
226
+ this.render(false);
227
+ }
228
+ if (this.isUp(char)) { // Up
229
+ this.selectedIndex = this.selectedIndex > 0 ? this.selectedIndex - 1 : this.options.choices.length - 1;
230
+ this.render(false);
231
+ }
232
+ if (this.isDown(char)) { // Down
233
+ this.selectedIndex = this.selectedIndex < this.options.choices.length - 1 ? this.selectedIndex + 1 : 0;
234
+ this.render(false);
235
+ }
236
+ }
237
+ validateDependencies() {
238
+ const choices = this.options.choices;
239
+ for (let i = 0; i < choices.length; i++) {
240
+ if (!this.checkedState[i])
241
+ continue;
242
+ const item = choices[i];
243
+ // Check dependencies
244
+ if (item.dependsOn) {
245
+ for (const depVal of item.dependsOn) {
246
+ const depIdx = choices.findIndex(c => c.value === depVal);
247
+ if (depIdx === -1 || !this.checkedState[depIdx]) {
248
+ return `${item.title} requires ${depVal}`; // Should look up title for depVal ideally
249
+ }
250
+ }
251
+ }
252
+ // Check conflicts
253
+ if (item.conflictsWith) {
254
+ for (const conVal of item.conflictsWith) {
255
+ const conIdx = choices.findIndex(c => c.value === conVal);
256
+ if (conIdx !== -1 && this.checkedState[conIdx]) {
257
+ return `${item.title} conflicts with ${choices[conIdx].title}`;
258
+ }
259
+ }
260
+ }
261
+ }
262
+ return null;
263
+ }
264
+ }
265
+ exports.DependencyPrompt = DependencyPrompt;
@@ -0,0 +1,10 @@
1
+ import { Prompt } from '../base';
2
+ import { DialOptions, MouseEvent } from '../types';
3
+ export declare class DialPrompt extends Prompt<number, DialOptions> {
4
+ private currentValue;
5
+ constructor(options: DialOptions);
6
+ protected render(_firstRender: boolean): void;
7
+ protected handleInput(char: string, _key: Buffer): void;
8
+ protected handleMouse(event: MouseEvent): void;
9
+ private updateValue;
10
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DialPrompt = void 0;
4
+ const base_1 = require("../base");
5
+ const theme_1 = require("../theme");
6
+ const ansi_1 = require("../ansi");
7
+ class DialPrompt extends base_1.Prompt {
8
+ constructor(options) {
9
+ super(options);
10
+ this.currentValue = options.initial !== undefined ? options.initial : options.min;
11
+ // Clamp initial
12
+ if (this.currentValue < this.options.min)
13
+ this.currentValue = this.options.min;
14
+ if (this.currentValue > this.options.max)
15
+ this.currentValue = this.options.max;
16
+ }
17
+ render(_firstRender) {
18
+ // Round value for display if necessary
19
+ const displayValue = Math.round(this.currentValue * 100) / 100;
20
+ let output = `${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} ${theme_1.theme.main}${displayValue}${ansi_1.ANSI.RESET}\n`;
21
+ const radius = this.options.radius || 5;
22
+ // Adjust aspect ratio: terminal chars are ~2x taller than wide.
23
+ // So we multiply X by 2.
24
+ const centerX = radius * 2;
25
+ const centerY = radius;
26
+ const width = centerX * 2 + 1;
27
+ const height = centerY * 2 + 1;
28
+ // Initialize grid
29
+ const grid = [];
30
+ for (let y = 0; y < height; y++) {
31
+ const row = [];
32
+ for (let x = 0; x < width; x++) {
33
+ row.push(' ');
34
+ }
35
+ grid.push(row);
36
+ }
37
+ // Draw track (static circle arc)
38
+ // Knob usually goes from Bottom-Left (135 deg) to Bottom-Right (405 deg)
39
+ // 0 deg is Right. 90 deg is Down.
40
+ for (let a = 135; a <= 405; a += 10) {
41
+ const rad = a * Math.PI / 180;
42
+ const rX = Math.round(centerX + radius * Math.cos(rad) * 2);
43
+ const rY = Math.round(centerY + radius * Math.sin(rad));
44
+ if (rY >= 0 && rY < height && rX >= 0 && rX < width) {
45
+ grid[rY][rX] = `${ansi_1.ANSI.FG_GRAY}·${ansi_1.ANSI.RESET}`;
46
+ }
47
+ }
48
+ // Calculate Pointer Position
49
+ const totalRange = this.options.max - this.options.min;
50
+ // Avoid division by zero
51
+ const percent = totalRange === 0 ? 0 : (this.currentValue - this.options.min) / totalRange;
52
+ const angleDeg = 135 + (percent * 270);
53
+ const rad = angleDeg * Math.PI / 180;
54
+ const ptrX = Math.round(centerX + radius * Math.cos(rad) * 2);
55
+ const ptrY = Math.round(centerY + radius * Math.sin(rad));
56
+ if (ptrY >= 0 && ptrY < height && ptrX >= 0 && ptrX < width) {
57
+ grid[ptrY][ptrX] = `${theme_1.theme.main}${this.options.pointerSymbol || '●'}${ansi_1.ANSI.RESET}`;
58
+ }
59
+ // Draw Center Value (Optional - roughly centered)
60
+ // const valStr = displayValue.toString();
61
+ // const valX = centerX - Math.floor(valStr.length / 2);
62
+ // const valY = centerY;
63
+ // if (valY >= 0 && valY < height && valX >= 0 && valX + valStr.length <= width) {
64
+ // for (let i = 0; i < valStr.length; i++) {
65
+ // // grid[valY][valX + i] = valStr[i];
66
+ // }
67
+ // }
68
+ // Construct string
69
+ for (let y = 0; y < height; y++) {
70
+ output += ' ' + grid[y].join('') + '\n';
71
+ }
72
+ // Instructions
73
+ output += `\n${ansi_1.ANSI.FG_GRAY}(Arrows/Scroll to adjust, Enter to submit)${ansi_1.ANSI.RESET}`;
74
+ this.renderFrame(output);
75
+ }
76
+ handleInput(char, _key) {
77
+ const step = this.options.step || 1;
78
+ if (this.isLeft(char) || this.isDown(char)) {
79
+ this.updateValue(this.currentValue - step);
80
+ }
81
+ else if (this.isRight(char) || this.isUp(char)) {
82
+ this.updateValue(this.currentValue + step);
83
+ }
84
+ else if (char === '\r' || char === '\n') {
85
+ this.submit(this.currentValue);
86
+ }
87
+ }
88
+ handleMouse(event) {
89
+ const step = this.options.step || 1;
90
+ if (event.action === 'scroll') {
91
+ if (event.scroll === 'up') {
92
+ this.updateValue(this.currentValue + step);
93
+ }
94
+ else {
95
+ this.updateValue(this.currentValue - step);
96
+ }
97
+ }
98
+ }
99
+ updateValue(val) {
100
+ if (val < this.options.min)
101
+ val = this.options.min;
102
+ if (val > this.options.max)
103
+ val = this.options.max;
104
+ if (this.currentValue !== val) {
105
+ this.currentValue = val;
106
+ this.render(false);
107
+ }
108
+ }
109
+ }
110
+ exports.DialPrompt = DialPrompt;
@@ -0,0 +1,10 @@
1
+ import { Prompt } from '../base';
2
+ import { DiffOptions } from '../types';
3
+ export declare class DiffPrompt extends Prompt<string, DiffOptions> {
4
+ private activeAction;
5
+ private actions;
6
+ constructor(options: DiffOptions);
7
+ protected render(_firstRender: boolean): void;
8
+ protected handleInput(char: string, _key: Buffer): void;
9
+ private handleSubmit;
10
+ }