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.
Files changed (78) hide show
  1. package/dist/api.d.ts +23 -5
  2. package/dist/api.js +16 -4
  3. package/dist/component-factories.d.ts +59 -0
  4. package/dist/component-factories.js +141 -0
  5. package/dist/components/display/header-v2.d.ts +13 -0
  6. package/dist/components/display/header-v2.js +43 -0
  7. package/dist/components/display/header.d.ts +40 -0
  8. package/dist/components/display/header.js +331 -18
  9. package/dist/components/display/headers.d.ts +1 -0
  10. package/dist/components/display/headers.js +15 -5
  11. package/dist/components/display/hints-v2.d.ts +10 -0
  12. package/dist/components/display/hints-v2.js +34 -0
  13. package/dist/components/display/hints.d.ts +56 -0
  14. package/dist/components/display/hints.js +81 -0
  15. package/dist/components/display/index.d.ts +4 -1
  16. package/dist/components/display/index.js +17 -1
  17. package/dist/components/display/input-prompt.d.ts +35 -0
  18. package/dist/components/display/input-prompt.js +36 -0
  19. package/dist/components/display/list.d.ts +49 -0
  20. package/dist/components/display/list.js +86 -0
  21. package/dist/components/display/messages.js +5 -5
  22. package/dist/components/display/progress.d.ts +17 -0
  23. package/dist/components/display/progress.js +18 -0
  24. package/dist/components/display/summary.js +72 -10
  25. package/dist/components/display/table.d.ts +44 -0
  26. package/dist/components/display/table.js +108 -0
  27. package/dist/components/inputs/language-input.js +8 -5
  28. package/dist/components/inputs/number-input.js +19 -14
  29. package/dist/components/inputs/text-input.js +50 -13
  30. package/dist/components/menus/boolean-menu.js +34 -20
  31. package/dist/components/menus/checkbox-menu.d.ts +2 -1
  32. package/dist/components/menus/checkbox-menu.js +35 -61
  33. package/dist/components/menus/checkbox-table-menu.d.ts +12 -0
  34. package/dist/components/menus/checkbox-table-menu.js +398 -0
  35. package/dist/components/menus/index.d.ts +1 -0
  36. package/dist/components/menus/index.js +3 -1
  37. package/dist/components/menus/radio-menu-split.d.ts +34 -0
  38. package/dist/components/menus/radio-menu-split.js +258 -0
  39. package/dist/components/menus/radio-menu-v2.d.ts +11 -0
  40. package/dist/components/menus/radio-menu-v2.js +150 -0
  41. package/dist/components/menus/radio-menu.d.ts +2 -1
  42. package/dist/components/menus/radio-menu.js +100 -134
  43. package/dist/components.js +3 -3
  44. package/dist/config/index.d.ts +5 -0
  45. package/dist/config/index.js +21 -0
  46. package/dist/config/language-config.d.ts +73 -0
  47. package/dist/config/language-config.js +157 -0
  48. package/dist/config/user-config.d.ts +83 -0
  49. package/dist/config/user-config.js +185 -0
  50. package/dist/core/colors.d.ts +24 -18
  51. package/dist/core/colors.js +74 -7
  52. package/dist/core/hint-manager.d.ts +29 -0
  53. package/dist/core/hint-manager.js +65 -0
  54. package/dist/core/renderer.d.ts +2 -1
  55. package/dist/core/renderer.js +46 -22
  56. package/dist/core/screen-manager.d.ts +54 -0
  57. package/dist/core/screen-manager.js +119 -0
  58. package/dist/core/state-manager.d.ts +27 -0
  59. package/dist/core/state-manager.js +56 -0
  60. package/dist/core/terminal.d.ts +17 -1
  61. package/dist/core/terminal.js +124 -4
  62. package/dist/core/virtual-scroll.d.ts +65 -0
  63. package/dist/core/virtual-scroll.js +120 -0
  64. package/dist/features/commands.js +23 -22
  65. package/dist/i18n/languages/en.js +4 -1
  66. package/dist/i18n/languages/zh.js +4 -1
  67. package/dist/i18n/registry.d.ts +4 -3
  68. package/dist/i18n/registry.js +12 -4
  69. package/dist/i18n/types.d.ts +3 -0
  70. package/dist/index.d.ts +7 -4
  71. package/dist/index.js +49 -4
  72. package/dist/layout.d.ts +67 -0
  73. package/dist/layout.js +86 -0
  74. package/dist/page-layout.d.ts +123 -0
  75. package/dist/page-layout.js +195 -0
  76. package/dist/types/input.types.d.ts +8 -0
  77. package/dist/types/menu.types.d.ts +61 -5
  78. 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
- * Generate hints based on menu configuration and actual options
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
- // Check if there are actually number-prefixed options
26
- if (allowNumberKeys) {
27
- const hasNumberOptions = options.some(opt => {
28
- if (typeof opt === 'string') {
29
- return /^\d+\./.test(opt);
30
- }
31
- return false;
32
- });
33
- if (hasNumberOptions) {
34
- hints.push((0, registry_js_1.t)('hints.numbers'));
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
- // Check if there are actually letter-prefixed options
38
- if (allowLetterKeys) {
39
- const hasLetterOptions = options.some(opt => {
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
- hints.push((0, registry_js_1.t)('hints.enter'));
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, hints, layout = layout_types_js_1.LAYOUT_PRESETS.MAIN_MENU, defaultIndex = 0, allowNumberKeys = true, allowLetterKeys = false, separatorWidth = 30, onExit, preserveOnSelect = false } = config;
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
- // Render based on layout order
119
- effectiveLayout.order.forEach(element => {
120
- // Add spacing before element
121
- const spacingKey = `before${element.charAt(0).toUpperCase() + element.slice(1)}`;
122
- if (effectiveLayout.spacing?.[spacingKey]) {
123
- (0, renderer_js_1.renderBlankLines)(effectiveLayout.spacing[spacingKey]);
124
- lineCount += effectiveLayout.spacing[spacingKey];
125
- }
126
- switch (element) {
127
- case 'header':
128
- if (effectiveLayout.visible.header && title) {
129
- (0, renderer_js_1.renderHeader)(` ${title}`, colors_js_1.colors.cyan);
130
- lineCount++;
131
- }
132
- break;
133
- case 'options':
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
- // Add spacing after element
186
- const afterSpacingKey = `after${element.charAt(0).toUpperCase() + element.slice(1)}`;
187
- if (effectiveLayout.spacing?.[afterSpacingKey]) {
188
- (0, renderer_js_1.renderBlankLines)(effectiveLayout.spacing[afterSpacingKey]);
189
- lineCount += effectiveLayout.spacing[afterSpacingKey];
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
- (0, terminal_js_1.clearMenu)(state);
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('\n👋 再见!');
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 selectedOption = options[selectedIndex];
223
- let value;
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.value.match(/^([a-zA-Z])\./i);
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) {
@@ -33,8 +33,8 @@ const colorCodes = {
33
33
  };
34
34
  // Theme colors
35
35
  exports.theme = {
36
- active: `${colorCodes.bright}${exports.colors.cyan}`, // Selected item - bright cyan
37
- primary: exports.colors.cyan, // Standard - cyan (numbers, separators)
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.blue },
49
+ info: { icon: 'ℹ', color: exports.colors.reset },
50
50
  };
51
51
  /**
52
52
  * Format section title with separator
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Configuration module exports
3
+ */
4
+ export * from './user-config';
5
+ export * from './language-config';
@@ -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 {};