cli-menu-kit 0.1.26 → 0.2.1
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/dist/api.d.ts +23 -5
- package/dist/api.js +16 -4
- package/dist/component-factories.d.ts +59 -0
- package/dist/component-factories.js +141 -0
- package/dist/components/display/header-v2.d.ts +13 -0
- package/dist/components/display/header-v2.js +43 -0
- package/dist/components/display/header.d.ts +40 -0
- package/dist/components/display/header.js +331 -18
- package/dist/components/display/headers.d.ts +1 -0
- package/dist/components/display/headers.js +15 -5
- package/dist/components/display/hints-v2.d.ts +10 -0
- package/dist/components/display/hints-v2.js +34 -0
- package/dist/components/display/hints.d.ts +56 -0
- package/dist/components/display/hints.js +81 -0
- package/dist/components/display/index.d.ts +4 -1
- package/dist/components/display/index.js +17 -1
- package/dist/components/display/input-prompt.d.ts +35 -0
- package/dist/components/display/input-prompt.js +36 -0
- package/dist/components/display/list.d.ts +49 -0
- package/dist/components/display/list.js +86 -0
- package/dist/components/display/messages.js +5 -5
- package/dist/components/display/progress.d.ts +17 -0
- package/dist/components/display/progress.js +18 -0
- package/dist/components/display/summary.js +72 -10
- package/dist/components/display/table.d.ts +44 -0
- package/dist/components/display/table.js +108 -0
- package/dist/components/inputs/language-input.js +8 -5
- package/dist/components/inputs/number-input.js +19 -14
- package/dist/components/inputs/text-input.js +50 -13
- package/dist/components/menus/boolean-menu.js +34 -20
- package/dist/components/menus/checkbox-menu.d.ts +2 -1
- package/dist/components/menus/checkbox-menu.js +35 -61
- package/dist/components/menus/checkbox-table-menu.d.ts +12 -0
- package/dist/components/menus/checkbox-table-menu.js +398 -0
- package/dist/components/menus/index.d.ts +1 -0
- package/dist/components/menus/index.js +3 -1
- package/dist/components/menus/radio-menu-split.d.ts +34 -0
- package/dist/components/menus/radio-menu-split.js +258 -0
- package/dist/components/menus/radio-menu-v2.d.ts +11 -0
- package/dist/components/menus/radio-menu-v2.js +150 -0
- package/dist/components/menus/radio-menu.d.ts +2 -1
- package/dist/components/menus/radio-menu.js +100 -134
- package/dist/components.js +3 -3
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +21 -0
- package/dist/config/language-config.d.ts +73 -0
- package/dist/config/language-config.js +157 -0
- package/dist/config/user-config.d.ts +83 -0
- package/dist/config/user-config.js +185 -0
- package/dist/core/colors.d.ts +24 -18
- package/dist/core/colors.js +74 -7
- package/dist/core/hint-manager.d.ts +29 -0
- package/dist/core/hint-manager.js +65 -0
- package/dist/core/renderer.d.ts +2 -1
- package/dist/core/renderer.js +46 -22
- package/dist/core/screen-manager.d.ts +54 -0
- package/dist/core/screen-manager.js +119 -0
- package/dist/core/state-manager.d.ts +27 -0
- package/dist/core/state-manager.js +56 -0
- package/dist/core/terminal.d.ts +17 -1
- package/dist/core/terminal.js +124 -4
- package/dist/core/virtual-scroll.d.ts +65 -0
- package/dist/core/virtual-scroll.js +120 -0
- package/dist/features/commands.js +23 -22
- package/dist/i18n/languages/en.js +4 -1
- package/dist/i18n/languages/zh.js +4 -1
- package/dist/i18n/registry.d.ts +4 -3
- package/dist/i18n/registry.js +12 -4
- package/dist/i18n/types.d.ts +3 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +49 -4
- package/dist/layout.d.ts +67 -0
- package/dist/layout.js +86 -0
- package/dist/page-layout.d.ts +123 -0
- package/dist/page-layout.js +195 -0
- package/dist/types/input.types.d.ts +8 -0
- package/dist/types/menu.types.d.ts +61 -5
- package/package.json +4 -1
|
@@ -5,61 +5,47 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.showRadioMenu = showRadioMenu;
|
|
8
|
-
const layout_types_js_1 = require("../../types/layout.types.js");
|
|
9
8
|
const terminal_js_1 = require("../../core/terminal.js");
|
|
10
9
|
const keyboard_js_1 = require("../../core/keyboard.js");
|
|
11
10
|
const renderer_js_1 = require("../../core/renderer.js");
|
|
11
|
+
const renderer_js_2 = require("../../core/renderer.js");
|
|
12
12
|
const colors_js_1 = require("../../core/colors.js");
|
|
13
13
|
const registry_js_1 = require("../../i18n/registry.js");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function generateHints(options, allowNumberKeys, allowLetterKeys) {
|
|
18
|
-
const hints = [];
|
|
19
|
-
// Count selectable options
|
|
20
|
-
const selectableCount = options.filter(opt => !(typeof opt === 'object' && 'type' in opt && opt.type === 'separator')).length;
|
|
21
|
-
// Only show arrow hints if there are multiple options
|
|
22
|
-
if (selectableCount > 1) {
|
|
23
|
-
hints.push((0, registry_js_1.t)('hints.arrows'));
|
|
14
|
+
function buildSectionLabelText(label, width) {
|
|
15
|
+
if (!label) {
|
|
16
|
+
return '';
|
|
24
17
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
const labelWithPadding = ` ${label} `;
|
|
19
|
+
const dashesTotal = Math.max(0, width - labelWithPadding.length);
|
|
20
|
+
const dashesLeft = Math.floor(dashesTotal / 2);
|
|
21
|
+
const dashesRight = dashesTotal - dashesLeft;
|
|
22
|
+
return ` ${'─'.repeat(dashesLeft)}${labelWithPadding}${'─'.repeat(dashesRight)}`;
|
|
23
|
+
}
|
|
24
|
+
function buildOptionRenderText(text, isHighlighted, prefix) {
|
|
25
|
+
const parts = text.split(' - ');
|
|
26
|
+
const mainText = parts[0] || '';
|
|
27
|
+
const description = parts.length > 1 ? parts.slice(1).join(' - ') : '';
|
|
28
|
+
let line = isHighlighted ? '❯ ' : ' ';
|
|
29
|
+
if (prefix) {
|
|
30
|
+
line += prefix;
|
|
36
31
|
}
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
if (typeof opt === 'string') {
|
|
41
|
-
return /^[a-zA-Z]\./.test(opt);
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
44
|
-
});
|
|
45
|
-
if (hasLetterOptions) {
|
|
46
|
-
hints.push((0, registry_js_1.t)('hints.letters'));
|
|
47
|
-
}
|
|
32
|
+
line += mainText;
|
|
33
|
+
if (description) {
|
|
34
|
+
line += ` - ${description}`;
|
|
48
35
|
}
|
|
49
|
-
|
|
50
|
-
return hints;
|
|
36
|
+
return line;
|
|
51
37
|
}
|
|
52
38
|
/**
|
|
53
39
|
* Show a radio menu (single-select)
|
|
54
40
|
* @param config - Menu configuration
|
|
41
|
+
* @param hints - Optional hints to display at the bottom (for Page Layout use)
|
|
55
42
|
* @returns Promise resolving to selected option
|
|
56
43
|
*/
|
|
57
|
-
async function showRadioMenu(config) {
|
|
58
|
-
const { options, title, prompt,
|
|
44
|
+
async function showRadioMenu(config, hints) {
|
|
45
|
+
const { options, title, prompt, defaultIndex = 0, allowNumberKeys = true, allowLetterKeys = false, separatorWidth = 30, onExit, preserveOnSelect = false } = config;
|
|
46
|
+
const preserveOnExit = config.preserveOnExit ?? preserveOnSelect;
|
|
59
47
|
// Use i18n for default prompt if not provided
|
|
60
48
|
const displayPrompt = prompt || (0, registry_js_1.t)('menus.selectPrompt');
|
|
61
|
-
// Generate hints dynamically if not provided
|
|
62
|
-
const displayHints = hints || generateHints(options, allowNumberKeys, allowLetterKeys);
|
|
63
49
|
// Validate options
|
|
64
50
|
if (!options || options.length === 0) {
|
|
65
51
|
throw new Error('RadioMenu requires at least one option');
|
|
@@ -72,25 +58,27 @@ async function showRadioMenu(config) {
|
|
|
72
58
|
const optionData = [];
|
|
73
59
|
options.forEach((opt, index) => {
|
|
74
60
|
if (typeof opt === 'object' && 'type' in opt && opt.type === 'separator') {
|
|
75
|
-
optionData.push({ value: '', isSeparator: true, label: opt.label });
|
|
61
|
+
optionData.push({ display: '', value: '', isSeparator: true, label: opt.label });
|
|
76
62
|
}
|
|
77
63
|
else {
|
|
64
|
+
let display;
|
|
78
65
|
let value;
|
|
79
66
|
if (typeof opt === 'string') {
|
|
67
|
+
display = opt;
|
|
80
68
|
value = opt;
|
|
81
69
|
}
|
|
82
70
|
else if ('value' in opt) {
|
|
71
|
+
display = opt.label ?? String(opt.value ?? '');
|
|
83
72
|
value = opt.value ?? opt.label ?? '';
|
|
84
73
|
}
|
|
85
74
|
else {
|
|
75
|
+
display = opt.label ?? '';
|
|
86
76
|
value = opt.label ?? '';
|
|
87
77
|
}
|
|
88
|
-
optionData.push({ value, isSeparator: false });
|
|
78
|
+
optionData.push({ display, value, isSeparator: false });
|
|
89
79
|
selectableIndices.push(index);
|
|
90
80
|
}
|
|
91
81
|
});
|
|
92
|
-
// Use MINIMAL layout for single-option menus
|
|
93
|
-
const effectiveLayout = selectableIndices.length === 1 ? layout_types_js_1.LAYOUT_PRESETS.MINIMAL : layout;
|
|
94
82
|
// Ensure selectedIndex points to a selectable option
|
|
95
83
|
if (!selectableIndices.includes(selectedIndex)) {
|
|
96
84
|
selectedIndex = selectableIndices[0] || 0;
|
|
@@ -115,80 +103,71 @@ async function showRadioMenu(config) {
|
|
|
115
103
|
const render = () => {
|
|
116
104
|
(0, terminal_js_1.clearMenu)(state);
|
|
117
105
|
let lineCount = 0;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
optionData.forEach((item, index) => {
|
|
135
|
-
if (item.isSeparator) {
|
|
136
|
-
// Render section label with configured width
|
|
137
|
-
(0, renderer_js_1.renderSectionLabel)(item.label, separatorWidth);
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
// Check if option starts with a number or letter prefix
|
|
141
|
-
const numberMatch = item.value.match(/^(\d+)\.\s*/);
|
|
142
|
-
const letterMatch = item.value.match(/^([a-zA-Z])\.\s*/);
|
|
143
|
-
// Don't add prefix if option already has number or letter prefix
|
|
144
|
-
const prefix = (numberMatch || letterMatch) ? '' : `${selectableIndices.indexOf(index) + 1}. `;
|
|
145
|
-
// Check if this is an Exit option (contains "Exit" or "Quit")
|
|
146
|
-
const isExitOption = /\b(exit|quit)\b/i.test(item.value);
|
|
147
|
-
const displayValue = isExitOption ? `${colors_js_1.uiColors.error}${item.value}${colors_js_1.colors.reset}` : item.value;
|
|
148
|
-
// For radio menus, don't show selection indicator (pass undefined instead of false)
|
|
149
|
-
(0, renderer_js_1.renderOption)(displayValue, undefined, index === selectedIndex, prefix);
|
|
150
|
-
// Add blank line after last item before next separator
|
|
151
|
-
const nextIndex = index + 1;
|
|
152
|
-
if (nextIndex < optionData.length && optionData[nextIndex].isSeparator) {
|
|
153
|
-
(0, terminal_js_1.writeLine)('');
|
|
154
|
-
lineCount++; // Count the blank line
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
lineCount++;
|
|
158
|
-
});
|
|
159
|
-
break;
|
|
160
|
-
case 'input':
|
|
161
|
-
if (effectiveLayout.visible.input) {
|
|
162
|
-
// Calculate display value (current selection number)
|
|
163
|
-
let displayValue = '';
|
|
164
|
-
const currentItem = optionData[selectedIndex];
|
|
165
|
-
if (currentItem && !currentItem.isSeparator) {
|
|
166
|
-
const match = currentItem.value.match(/^([^.]+)\./);
|
|
167
|
-
if (match) {
|
|
168
|
-
displayValue = match[1];
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
displayValue = String(selectableIndices.indexOf(selectedIndex) + 1);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
(0, renderer_js_1.renderInputPrompt)(displayPrompt, displayValue);
|
|
175
|
-
lineCount++;
|
|
176
|
-
}
|
|
177
|
-
break;
|
|
178
|
-
case 'hints':
|
|
179
|
-
if (effectiveLayout.visible.hints && displayHints.length > 0) {
|
|
180
|
-
(0, renderer_js_1.renderHints)(displayHints);
|
|
181
|
-
lineCount++;
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
106
|
+
const addVisualLines = (text) => {
|
|
107
|
+
lineCount += (0, terminal_js_1.countVisualLines)(text);
|
|
108
|
+
};
|
|
109
|
+
// Render title if provided
|
|
110
|
+
if (title) {
|
|
111
|
+
(0, renderer_js_1.renderHeader)(` ${title}`, colors_js_1.uiColors.primary);
|
|
112
|
+
addVisualLines(` ${title}`);
|
|
113
|
+
(0, renderer_js_1.renderBlankLines)(1);
|
|
114
|
+
addVisualLines('');
|
|
115
|
+
}
|
|
116
|
+
// Render options
|
|
117
|
+
optionData.forEach((item, index) => {
|
|
118
|
+
if (item.isSeparator) {
|
|
119
|
+
// Render section label with configured width
|
|
120
|
+
(0, renderer_js_1.renderSectionLabel)(item.label, separatorWidth);
|
|
121
|
+
addVisualLines(buildSectionLabelText(item.label, separatorWidth));
|
|
184
122
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
123
|
+
else {
|
|
124
|
+
// Check if option starts with a number or letter prefix
|
|
125
|
+
const numberMatch = item.display.match(/^(\d+)\.\s*/);
|
|
126
|
+
const letterMatch = item.display.match(/^([a-zA-Z])\.\s*/);
|
|
127
|
+
// Don't add prefix if option already has number or letter prefix
|
|
128
|
+
const prefix = (numberMatch || letterMatch) ? '' : `${selectableIndices.indexOf(index) + 1}. `;
|
|
129
|
+
// Check if this is an Exit option (contains "Exit", "Quit", or Chinese "退出")
|
|
130
|
+
// Keep unselected exit entries in error color, but let selected row use normal highlight style.
|
|
131
|
+
const isExitOption = /\b(exit|quit)\b|退出/i.test(item.display);
|
|
132
|
+
const isCurrent = index === selectedIndex;
|
|
133
|
+
const displayValue = isExitOption && !isCurrent
|
|
134
|
+
? `${colors_js_1.uiColors.error}${item.display}${colors_js_1.colors.reset}`
|
|
135
|
+
: item.display;
|
|
136
|
+
// For radio menus, don't show selection indicator (pass undefined instead of false)
|
|
137
|
+
(0, renderer_js_1.renderOption)(displayValue, undefined, isCurrent, prefix);
|
|
138
|
+
addVisualLines(buildOptionRenderText(displayValue, isCurrent, prefix));
|
|
139
|
+
// Add blank line after last item before next separator
|
|
140
|
+
const nextIndex = index + 1;
|
|
141
|
+
if (nextIndex < optionData.length && optionData[nextIndex].isSeparator) {
|
|
142
|
+
(0, terminal_js_1.writeLine)('');
|
|
143
|
+
addVisualLines('');
|
|
144
|
+
}
|
|
190
145
|
}
|
|
191
146
|
});
|
|
147
|
+
// Render input prompt
|
|
148
|
+
(0, renderer_js_1.renderBlankLines)(1);
|
|
149
|
+
addVisualLines('');
|
|
150
|
+
// Calculate display value (current selection number)
|
|
151
|
+
let displayValue = '';
|
|
152
|
+
const currentItem = optionData[selectedIndex];
|
|
153
|
+
if (currentItem && !currentItem.isSeparator) {
|
|
154
|
+
const match = currentItem.display.match(/^([^.]+)\./);
|
|
155
|
+
if (match) {
|
|
156
|
+
displayValue = match[1];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
displayValue = String(selectableIndices.indexOf(selectedIndex) + 1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
(0, renderer_js_1.renderInputPrompt)(displayPrompt, displayValue);
|
|
163
|
+
addVisualLines(` ${displayPrompt} ${displayValue}`);
|
|
164
|
+
// Render hints if provided (for Page Layout footer)
|
|
165
|
+
if (hints && hints.length > 0) {
|
|
166
|
+
(0, renderer_js_1.renderBlankLines)(1);
|
|
167
|
+
addVisualLines('');
|
|
168
|
+
(0, renderer_js_2.renderHints)(hints);
|
|
169
|
+
addVisualLines(` ${hints.join(' • ')}`);
|
|
170
|
+
}
|
|
192
171
|
state.renderedLines = lineCount;
|
|
193
172
|
};
|
|
194
173
|
// Initial render
|
|
@@ -199,13 +178,15 @@ async function showRadioMenu(config) {
|
|
|
199
178
|
// Handle Ctrl+C
|
|
200
179
|
if ((0, keyboard_js_1.isCtrlC)(key)) {
|
|
201
180
|
state.stdin.removeListener('data', onData);
|
|
202
|
-
|
|
181
|
+
if (!preserveOnExit) {
|
|
182
|
+
(0, terminal_js_1.clearMenu)(state);
|
|
183
|
+
}
|
|
203
184
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
204
185
|
if (onExit) {
|
|
205
186
|
onExit();
|
|
206
187
|
}
|
|
207
188
|
else {
|
|
208
|
-
console.log(
|
|
189
|
+
console.log(`\n${(0, registry_js_1.t)('messages.goodbye')}`);
|
|
209
190
|
}
|
|
210
191
|
process.exit(0);
|
|
211
192
|
}
|
|
@@ -215,24 +196,9 @@ async function showRadioMenu(config) {
|
|
|
215
196
|
if (!preserveOnSelect) {
|
|
216
197
|
(0, terminal_js_1.clearMenu)(state);
|
|
217
198
|
}
|
|
218
|
-
else {
|
|
219
|
-
(0, terminal_js_1.writeLine)('');
|
|
220
|
-
}
|
|
221
199
|
(0, terminal_js_1.restoreTerminal)(state);
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
if (typeof selectedOption === 'string') {
|
|
225
|
-
value = selectedOption;
|
|
226
|
-
}
|
|
227
|
-
else if ('type' in selectedOption && selectedOption.type === 'separator') {
|
|
228
|
-
value = '';
|
|
229
|
-
}
|
|
230
|
-
else if ('value' in selectedOption) {
|
|
231
|
-
value = selectedOption.value ?? selectedOption.label ?? '';
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
value = selectedOption.label ?? '';
|
|
235
|
-
}
|
|
200
|
+
const selectedItem = optionData[selectedIndex];
|
|
201
|
+
const value = selectedItem && !selectedItem.isSeparator ? selectedItem.value : '';
|
|
236
202
|
resolve({
|
|
237
203
|
index: selectedIndex,
|
|
238
204
|
value
|
|
@@ -266,7 +232,7 @@ async function showRadioMenu(config) {
|
|
|
266
232
|
const item = optionData[idx];
|
|
267
233
|
if (item.isSeparator)
|
|
268
234
|
return false;
|
|
269
|
-
const match = item.
|
|
235
|
+
const match = item.display.match(/^([a-zA-Z])\./i);
|
|
270
236
|
return match && match[1].toLowerCase() === letter;
|
|
271
237
|
});
|
|
272
238
|
if (index !== undefined) {
|
package/dist/components.js
CHANGED
|
@@ -33,8 +33,8 @@ const colorCodes = {
|
|
|
33
33
|
};
|
|
34
34
|
// Theme colors
|
|
35
35
|
exports.theme = {
|
|
36
|
-
active: `${colorCodes.bright}${exports.colors.
|
|
37
|
-
primary: exports.colors.
|
|
36
|
+
active: `${colorCodes.bright}${exports.colors.reset}`, // Selected item - bright default
|
|
37
|
+
primary: exports.colors.reset, // Standard text color
|
|
38
38
|
title: exports.colors.reset, // Title - white (menu titles)
|
|
39
39
|
muted: exports.colors.gray, // Auxiliary - gray (descriptions, hints)
|
|
40
40
|
success: exports.colors.green, // Success - green
|
|
@@ -46,7 +46,7 @@ exports.symbols = {
|
|
|
46
46
|
success: { icon: '✓', color: exports.colors.green },
|
|
47
47
|
error: { icon: 'x', color: exports.colors.red },
|
|
48
48
|
warning: { icon: '!', color: exports.colors.yellow },
|
|
49
|
-
info: { icon: 'ℹ', color: exports.colors.
|
|
49
|
+
info: { icon: 'ℹ', color: exports.colors.reset },
|
|
50
50
|
};
|
|
51
51
|
/**
|
|
52
52
|
* Format section title with separator
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration module exports
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./user-config"), exports);
|
|
21
|
+
__exportStar(require("./language-config"), exports);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Configuration System
|
|
3
|
+
* Supports dynamic language loading from JSON
|
|
4
|
+
*/
|
|
5
|
+
export interface LanguageConfig {
|
|
6
|
+
code: string;
|
|
7
|
+
cliCode?: string;
|
|
8
|
+
label: string;
|
|
9
|
+
nativeLabel: string;
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
export interface LanguagesConfig {
|
|
13
|
+
default: string;
|
|
14
|
+
languages: LanguageConfig[];
|
|
15
|
+
}
|
|
16
|
+
declare class LanguageManager {
|
|
17
|
+
private config;
|
|
18
|
+
private languageMap;
|
|
19
|
+
constructor(config: LanguagesConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Get all supported languages
|
|
22
|
+
*/
|
|
23
|
+
getLanguages(): LanguageConfig[];
|
|
24
|
+
/**
|
|
25
|
+
* Get language config by code
|
|
26
|
+
*/
|
|
27
|
+
getLanguage(code: string): LanguageConfig | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Get default language code
|
|
30
|
+
*/
|
|
31
|
+
getDefaultLanguage(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Get CLI language code
|
|
34
|
+
*/
|
|
35
|
+
getCLICode(code: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Check if language is supported
|
|
38
|
+
*/
|
|
39
|
+
isSupported(code: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Get all language codes
|
|
42
|
+
*/
|
|
43
|
+
getLanguageCodes(): string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Initialize language manager from config
|
|
47
|
+
*/
|
|
48
|
+
export declare function initLanguages(config: LanguagesConfig): LanguageManager;
|
|
49
|
+
/**
|
|
50
|
+
* Load languages from JSON file
|
|
51
|
+
*/
|
|
52
|
+
export declare function loadLanguagesFromFile(filePath: string): LanguageManager;
|
|
53
|
+
/**
|
|
54
|
+
* Get global language manager
|
|
55
|
+
*/
|
|
56
|
+
export declare function getLanguageManager(): LanguageManager;
|
|
57
|
+
/**
|
|
58
|
+
* Get all supported languages
|
|
59
|
+
*/
|
|
60
|
+
export declare function getSupportedLanguages(): LanguageConfig[];
|
|
61
|
+
/**
|
|
62
|
+
* Get language config
|
|
63
|
+
*/
|
|
64
|
+
export declare function getLanguageConfig(code: string): LanguageConfig | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get default language
|
|
67
|
+
*/
|
|
68
|
+
export declare function getDefaultLanguage(): string;
|
|
69
|
+
/**
|
|
70
|
+
* Get CLI language code
|
|
71
|
+
*/
|
|
72
|
+
export declare function getCLILanguageCode(code: string): string;
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Language Configuration System
|
|
4
|
+
* Supports dynamic language loading from JSON
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.initLanguages = initLanguages;
|
|
41
|
+
exports.loadLanguagesFromFile = loadLanguagesFromFile;
|
|
42
|
+
exports.getLanguageManager = getLanguageManager;
|
|
43
|
+
exports.getSupportedLanguages = getSupportedLanguages;
|
|
44
|
+
exports.getLanguageConfig = getLanguageConfig;
|
|
45
|
+
exports.getDefaultLanguage = getDefaultLanguage;
|
|
46
|
+
exports.getCLILanguageCode = getCLILanguageCode;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
class LanguageManager {
|
|
49
|
+
constructor(config) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.languageMap = new Map();
|
|
52
|
+
// Build language map
|
|
53
|
+
for (const lang of config.languages) {
|
|
54
|
+
this.languageMap.set(lang.code, lang);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get all supported languages
|
|
59
|
+
*/
|
|
60
|
+
getLanguages() {
|
|
61
|
+
return this.config.languages;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get language config by code
|
|
65
|
+
*/
|
|
66
|
+
getLanguage(code) {
|
|
67
|
+
return this.languageMap.get(code);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get default language code
|
|
71
|
+
*/
|
|
72
|
+
getDefaultLanguage() {
|
|
73
|
+
return this.config.default;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get CLI language code
|
|
77
|
+
*/
|
|
78
|
+
getCLICode(code) {
|
|
79
|
+
const lang = this.getLanguage(code);
|
|
80
|
+
return lang?.cliCode || lang?.code || this.getDefaultLanguage();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if language is supported
|
|
84
|
+
*/
|
|
85
|
+
isSupported(code) {
|
|
86
|
+
return this.languageMap.has(code);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get all language codes
|
|
90
|
+
*/
|
|
91
|
+
getLanguageCodes() {
|
|
92
|
+
return Array.from(this.languageMap.keys());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Global language manager
|
|
96
|
+
let globalLanguageManager = null;
|
|
97
|
+
/**
|
|
98
|
+
* Initialize language manager from config
|
|
99
|
+
*/
|
|
100
|
+
function initLanguages(config) {
|
|
101
|
+
globalLanguageManager = new LanguageManager(config);
|
|
102
|
+
return globalLanguageManager;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Load languages from JSON file
|
|
106
|
+
*/
|
|
107
|
+
function loadLanguagesFromFile(filePath) {
|
|
108
|
+
try {
|
|
109
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
110
|
+
const config = JSON.parse(content);
|
|
111
|
+
return initLanguages(config);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error('Failed to load languages config:', error);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get global language manager
|
|
120
|
+
*/
|
|
121
|
+
function getLanguageManager() {
|
|
122
|
+
if (!globalLanguageManager) {
|
|
123
|
+
// Return default manager if not initialized
|
|
124
|
+
return new LanguageManager({
|
|
125
|
+
default: 'en',
|
|
126
|
+
languages: [
|
|
127
|
+
{ code: 'en', label: 'English', nativeLabel: 'English' },
|
|
128
|
+
{ code: 'zh', label: 'Chinese', nativeLabel: '中文' }
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return globalLanguageManager;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get all supported languages
|
|
136
|
+
*/
|
|
137
|
+
function getSupportedLanguages() {
|
|
138
|
+
return getLanguageManager().getLanguages();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get language config
|
|
142
|
+
*/
|
|
143
|
+
function getLanguageConfig(code) {
|
|
144
|
+
return getLanguageManager().getLanguage(code);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get default language
|
|
148
|
+
*/
|
|
149
|
+
function getDefaultLanguage() {
|
|
150
|
+
return getLanguageManager().getDefaultLanguage();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get CLI language code
|
|
154
|
+
*/
|
|
155
|
+
function getCLILanguageCode(code) {
|
|
156
|
+
return getLanguageManager().getCLICode(code);
|
|
157
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Configuration System for CLI Menu Kit
|
|
3
|
+
* Provides persistent user preferences
|
|
4
|
+
*/
|
|
5
|
+
export interface UserConfig {
|
|
6
|
+
language?: string;
|
|
7
|
+
theme?: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export interface ConfigOptions {
|
|
11
|
+
appName: string;
|
|
12
|
+
configFileName?: string;
|
|
13
|
+
defaults?: UserConfig;
|
|
14
|
+
}
|
|
15
|
+
declare class ConfigManager {
|
|
16
|
+
private appName;
|
|
17
|
+
private configFileName;
|
|
18
|
+
private defaults;
|
|
19
|
+
private configDir;
|
|
20
|
+
private configPath;
|
|
21
|
+
constructor(options: ConfigOptions);
|
|
22
|
+
/**
|
|
23
|
+
* Ensure config directory exists
|
|
24
|
+
*/
|
|
25
|
+
private ensureConfigDir;
|
|
26
|
+
/**
|
|
27
|
+
* Load configuration
|
|
28
|
+
*/
|
|
29
|
+
load(): UserConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Save configuration
|
|
32
|
+
*/
|
|
33
|
+
save(config: Partial<UserConfig>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get a specific config value
|
|
36
|
+
*/
|
|
37
|
+
get<K extends keyof UserConfig>(key: K): UserConfig[K];
|
|
38
|
+
/**
|
|
39
|
+
* Set a specific config value
|
|
40
|
+
*/
|
|
41
|
+
set<K extends keyof UserConfig>(key: K, value: UserConfig[K]): void;
|
|
42
|
+
/**
|
|
43
|
+
* Reset configuration to defaults
|
|
44
|
+
*/
|
|
45
|
+
reset(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get config file path
|
|
48
|
+
*/
|
|
49
|
+
getConfigPath(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Get config directory path
|
|
52
|
+
*/
|
|
53
|
+
getConfigDir(): string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Initialize config manager
|
|
57
|
+
*/
|
|
58
|
+
export declare function initConfig(options: ConfigOptions): ConfigManager;
|
|
59
|
+
/**
|
|
60
|
+
* Get global config manager
|
|
61
|
+
*/
|
|
62
|
+
export declare function getConfigManager(): ConfigManager;
|
|
63
|
+
/**
|
|
64
|
+
* Load configuration
|
|
65
|
+
*/
|
|
66
|
+
export declare function loadConfig(): UserConfig;
|
|
67
|
+
/**
|
|
68
|
+
* Save configuration
|
|
69
|
+
*/
|
|
70
|
+
export declare function saveConfig(config: Partial<UserConfig>): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get config value
|
|
73
|
+
*/
|
|
74
|
+
export declare function getConfig<K extends keyof UserConfig>(key: K): UserConfig[K];
|
|
75
|
+
/**
|
|
76
|
+
* Set config value
|
|
77
|
+
*/
|
|
78
|
+
export declare function setConfig<K extends keyof UserConfig>(key: K, value: UserConfig[K]): void;
|
|
79
|
+
/**
|
|
80
|
+
* Reset configuration
|
|
81
|
+
*/
|
|
82
|
+
export declare function resetConfig(): void;
|
|
83
|
+
export {};
|