cli-menu-kit 0.2.0 → 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 (45) hide show
  1. package/dist/components/display/header.d.ts +40 -0
  2. package/dist/components/display/header.js +331 -18
  3. package/dist/components/display/headers.d.ts +1 -0
  4. package/dist/components/display/headers.js +15 -5
  5. package/dist/components/display/index.d.ts +1 -1
  6. package/dist/components/display/index.js +3 -1
  7. package/dist/components/display/messages.js +5 -5
  8. package/dist/components/display/progress.d.ts +17 -0
  9. package/dist/components/display/progress.js +18 -0
  10. package/dist/components/display/summary.js +72 -10
  11. package/dist/components/display/table.d.ts +2 -0
  12. package/dist/components/display/table.js +7 -6
  13. package/dist/components/inputs/language-input.js +8 -5
  14. package/dist/components/inputs/number-input.js +19 -14
  15. package/dist/components/inputs/text-input.js +50 -13
  16. package/dist/components/menus/boolean-menu.js +33 -20
  17. package/dist/components/menus/checkbox-menu.js +5 -2
  18. package/dist/components/menus/checkbox-table-menu.js +12 -9
  19. package/dist/components/menus/radio-menu-split.d.ts +1 -0
  20. package/dist/components/menus/radio-menu-split.js +26 -16
  21. package/dist/components/menus/radio-menu.js +67 -38
  22. package/dist/components.js +3 -3
  23. package/dist/config/index.d.ts +5 -0
  24. package/dist/config/index.js +21 -0
  25. package/dist/config/language-config.d.ts +73 -0
  26. package/dist/config/language-config.js +157 -0
  27. package/dist/config/user-config.d.ts +83 -0
  28. package/dist/config/user-config.js +185 -0
  29. package/dist/core/colors.d.ts +24 -18
  30. package/dist/core/colors.js +74 -7
  31. package/dist/core/renderer.js +26 -18
  32. package/dist/core/terminal.d.ts +13 -0
  33. package/dist/core/terminal.js +87 -0
  34. package/dist/features/commands.js +23 -22
  35. package/dist/index.d.ts +3 -1
  36. package/dist/index.js +21 -2
  37. package/dist/layout.d.ts +50 -51
  38. package/dist/layout.js +69 -117
  39. package/dist/page-layout.d.ts +31 -0
  40. package/dist/page-layout.js +46 -7
  41. package/dist/types/input.types.d.ts +8 -0
  42. package/dist/types/layout.types.d.ts +56 -0
  43. package/dist/types/layout.types.js +36 -0
  44. package/dist/types/menu.types.d.ts +4 -0
  45. package/package.json +4 -1
@@ -10,14 +10,34 @@
10
10
  */
11
11
  export interface HeaderConfig {
12
12
  type: 'simple' | 'section' | 'full' | 'none';
13
+ topBlankLines?: number;
13
14
  text?: string;
14
15
  width?: number;
15
16
  asciiArt?: string[];
17
+ figletText?: string;
18
+ figletFont?: string;
19
+ figletSize?: 'small' | 'medium' | 'large';
20
+ figletScale?: number;
21
+ boxWidth?: number;
22
+ showBoxBorder?: boolean;
23
+ fillBox?: boolean;
24
+ fillBoxColor?: string;
25
+ fillBoxGradientStart?: string;
26
+ fillBoxGradientEnd?: string;
16
27
  title?: string;
28
+ titleColor?: string;
29
+ titleGradientStart?: string;
30
+ titleGradientEnd?: string;
17
31
  description?: string;
32
+ descriptionColor?: string;
33
+ descriptionGradientStart?: string;
34
+ descriptionGradientEnd?: string;
35
+ asciiArtColor?: string;
18
36
  version?: string;
19
37
  url?: string;
20
38
  menuTitle?: string;
39
+ asciiArtGradientStart?: string;
40
+ asciiArtGradientEnd?: string;
21
41
  }
22
42
  /**
23
43
  * Main Area configuration
@@ -29,6 +49,8 @@ export interface MainAreaConfig {
29
49
  allowLetterKeys?: boolean;
30
50
  allowNumberKeys?: boolean;
31
51
  preserveOnSelect?: boolean;
52
+ preserveOnExit?: boolean;
53
+ onExit?: () => void;
32
54
  };
33
55
  render?: () => void | Promise<void>;
34
56
  }
@@ -41,16 +63,25 @@ export interface FooterConfig {
41
63
  allowLetterKeys?: boolean;
42
64
  allowNumberKeys?: boolean;
43
65
  preserveOnSelect?: boolean;
66
+ preserveOnExit?: boolean;
67
+ onExit?: () => void;
44
68
  };
45
69
  ask?: {
46
70
  question: string;
71
+ helperText?: string;
47
72
  defaultValue?: boolean;
48
73
  horizontal?: boolean;
74
+ preserveOnSelect?: boolean;
75
+ preserveOnExit?: boolean;
76
+ onExit?: () => void;
49
77
  };
50
78
  input?: {
51
79
  prompt: string;
52
80
  defaultValue?: string;
53
81
  allowEmpty?: boolean;
82
+ lang?: 'zh' | 'en';
83
+ preserveOnExit?: boolean;
84
+ onExit?: () => void;
54
85
  };
55
86
  hints?: string[];
56
87
  }
@@ -18,6 +18,10 @@ function renderHeaderSection(config) {
18
18
  if (!config || config.type === 'none') {
19
19
  return;
20
20
  }
21
+ const topBlankLines = Math.max(0, config.topBlankLines ?? 0);
22
+ for (let i = 0; i < topBlankLines; i += 1) {
23
+ console.log('');
24
+ }
21
25
  if (config.type === 'simple' && config.text) {
22
26
  (0, headers_js_1.renderSimpleHeader)(config.text);
23
27
  }
@@ -30,11 +34,30 @@ function renderHeaderSection(config) {
30
34
  // Render full header WITHOUT menuTitle
31
35
  (0, header_js_1.renderHeader)({
32
36
  asciiArt: config.asciiArt || [],
37
+ figletText: config.figletText,
38
+ figletFont: config.figletFont,
39
+ figletSize: config.figletSize,
40
+ figletScale: config.figletScale,
33
41
  title: config.title || '',
42
+ titleColor: config.titleColor,
43
+ titleGradientStart: config.titleGradientStart,
44
+ titleGradientEnd: config.titleGradientEnd,
34
45
  description: config.description,
46
+ descriptionColor: config.descriptionColor,
47
+ descriptionGradientStart: config.descriptionGradientStart,
48
+ descriptionGradientEnd: config.descriptionGradientEnd,
35
49
  version: config.version,
36
50
  url: config.url,
37
- menuTitle: undefined // Don't render menuTitle in header
51
+ menuTitle: undefined, // Don't render menuTitle in header
52
+ boxWidth: config.boxWidth,
53
+ showBoxBorder: config.showBoxBorder,
54
+ fillBox: config.fillBox,
55
+ fillBoxColor: config.fillBoxColor,
56
+ fillBoxGradientStart: config.fillBoxGradientStart,
57
+ fillBoxGradientEnd: config.fillBoxGradientEnd,
58
+ asciiArtGradientStart: config.asciiArtGradientStart,
59
+ asciiArtGradientEnd: config.asciiArtGradientEnd,
60
+ asciiArtColor: config.asciiArtColor
38
61
  });
39
62
  }
40
63
  }
@@ -57,7 +80,9 @@ async function renderMainArea(config, hints) {
57
80
  options: config.menu.options,
58
81
  allowLetterKeys: config.menu.allowLetterKeys ?? true,
59
82
  allowNumberKeys: config.menu.allowNumberKeys ?? true,
60
- preserveOnSelect: config.menu.preserveOnSelect ?? true
83
+ preserveOnSelect: config.menu.preserveOnSelect ?? true,
84
+ preserveOnExit: config.menu.preserveOnExit ?? config.menu.preserveOnSelect ?? false,
85
+ onExit: config.menu.onExit
61
86
  }, hints); // Pass hints as second parameter
62
87
  return result;
63
88
  }
@@ -82,7 +107,9 @@ async function renderFooterSection(config, hints) {
82
107
  options: config.menu.options,
83
108
  allowLetterKeys: config.menu.allowLetterKeys ?? true,
84
109
  allowNumberKeys: config.menu.allowNumberKeys ?? true,
85
- preserveOnSelect: config.menu.preserveOnSelect ?? true
110
+ preserveOnSelect: config.menu.preserveOnSelect ?? true,
111
+ preserveOnExit: config.menu.preserveOnExit ?? config.menu.preserveOnSelect ?? false,
112
+ onExit: config.menu.onExit
86
113
  }, hints || config.hints);
87
114
  }
88
115
  // 2. Input (if present)
@@ -90,14 +117,23 @@ async function renderFooterSection(config, hints) {
90
117
  result = await api_js_1.inputAPI.text({
91
118
  prompt: config.input.prompt,
92
119
  defaultValue: config.input.defaultValue,
93
- allowEmpty: config.input.allowEmpty ?? false
120
+ allowEmpty: config.input.allowEmpty ?? false,
121
+ lang: config.input.lang,
122
+ preserveOnExit: config.input.preserveOnExit,
123
+ onExit: config.input.onExit
94
124
  });
95
125
  }
96
126
  // 3. Ask (if present)
97
127
  else if (config.ask) {
98
- const askResult = config.ask.horizontal
99
- ? await api_js_1.menuAPI.booleanH(config.ask.question, config.ask.defaultValue ?? false)
100
- : await api_js_1.menuAPI.booleanV(config.ask.question, config.ask.defaultValue ?? false);
128
+ const askResult = await api_js_1.menuAPI.boolean({
129
+ question: config.ask.question,
130
+ helperText: config.ask.helperText,
131
+ defaultValue: config.ask.defaultValue ?? false,
132
+ orientation: config.ask.horizontal ? 'horizontal' : 'vertical',
133
+ preserveOnSelect: config.ask.preserveOnSelect ?? false,
134
+ preserveOnExit: config.ask.preserveOnExit ?? config.ask.preserveOnSelect ?? false,
135
+ onExit: config.ask.onExit
136
+ });
101
137
  result = askResult;
102
138
  }
103
139
  return result;
@@ -143,6 +179,9 @@ async function renderPage(config) {
143
179
  }
144
180
  else if (config.mainArea.render) {
145
181
  await config.mainArea.render();
182
+ // Add newline after custom render to separate from footer menu
183
+ // This ensures the escape codes from initTerminal don't interfere
184
+ console.log('');
146
185
  }
147
186
  // Render footer with hints
148
187
  const footerResult = await renderFooterSection(config.footer, config.footer.hints);
@@ -5,6 +5,8 @@
5
5
  * Base input configuration
6
6
  */
7
7
  export interface BaseInputConfig {
8
+ /** UI language (default: current i18n language) */
9
+ lang?: 'zh' | 'en';
8
10
  /** Input prompt text */
9
11
  prompt: string;
10
12
  /** Default value */
@@ -15,6 +17,8 @@ export interface BaseInputConfig {
15
17
  errorMessage?: string;
16
18
  /** Goodbye message function */
17
19
  onExit?: () => void;
20
+ /** Keep current input rendered on Ctrl+C exit instead of clearing (default: false) */
21
+ preserveOnExit?: boolean;
18
22
  }
19
23
  /**
20
24
  * Text input configuration
@@ -58,6 +62,8 @@ export interface LanguageSelectorConfig {
58
62
  prompt?: string;
59
63
  /** Goodbye message function */
60
64
  onExit?: () => void;
65
+ /** Keep current selector rendered on Ctrl+C exit instead of clearing (default: false) */
66
+ preserveOnExit?: boolean;
61
67
  }
62
68
  /**
63
69
  * Modify field configuration
@@ -75,6 +81,8 @@ export interface ModifyFieldConfig {
75
81
  validate?: (value: string) => boolean | string;
76
82
  /** Goodbye message function */
77
83
  onExit?: () => void;
84
+ /** Keep current prompt rendered on Ctrl+C exit instead of clearing (default: false) */
85
+ preserveOnExit?: boolean;
78
86
  }
79
87
  /**
80
88
  * Input result types
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Layout system types for CLI Menu Kit
3
+ * Defines how components are composed and rendered
4
+ */
5
+ /**
6
+ * Layout element types that can be arranged
7
+ */
8
+ export type LayoutElement = 'header' | 'options' | 'input' | 'hints' | 'progress';
9
+ /**
10
+ * Visibility configuration for layout elements
11
+ */
12
+ export interface LayoutVisibility {
13
+ header?: boolean;
14
+ input?: boolean;
15
+ hints?: boolean;
16
+ progress?: boolean;
17
+ }
18
+ /**
19
+ * Spacing configuration for layout elements
20
+ * Values represent number of blank lines
21
+ */
22
+ export interface LayoutSpacing {
23
+ beforeHeader?: number;
24
+ afterHeader?: number;
25
+ beforeOptions?: number;
26
+ afterOptions?: number;
27
+ beforeInput?: number;
28
+ afterInput?: number;
29
+ beforeHints?: number;
30
+ beforeProgress?: number;
31
+ afterProgress?: number;
32
+ }
33
+ /**
34
+ * Complete menu layout configuration
35
+ */
36
+ export interface MenuLayout {
37
+ /** Order in which elements are rendered */
38
+ order: LayoutElement[];
39
+ /** Which elements are visible */
40
+ visible: LayoutVisibility;
41
+ /** Spacing between elements */
42
+ spacing?: LayoutSpacing;
43
+ }
44
+ /**
45
+ * Preset layout configurations
46
+ */
47
+ export declare const LAYOUT_PRESETS: {
48
+ /** Main menu with header */
49
+ MAIN_MENU: MenuLayout;
50
+ /** Sub menu without header */
51
+ SUB_MENU: MenuLayout;
52
+ /** Wizard step with progress indicator */
53
+ WIZARD_STEP: MenuLayout;
54
+ /** Minimal layout (options only) */
55
+ MINIMAL: MenuLayout;
56
+ };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * Layout system types for CLI Menu Kit
4
+ * Defines how components are composed and rendered
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.LAYOUT_PRESETS = void 0;
8
+ /**
9
+ * Preset layout configurations
10
+ */
11
+ exports.LAYOUT_PRESETS = {
12
+ /** Main menu with header */
13
+ MAIN_MENU: {
14
+ order: ['header', 'options', 'input', 'hints'],
15
+ visible: { header: true, input: true, hints: true },
16
+ spacing: { afterHeader: 1, afterOptions: 1, beforeHints: 1 }
17
+ },
18
+ /** Sub menu without header */
19
+ SUB_MENU: {
20
+ order: ['options', 'input', 'hints'],
21
+ visible: { header: false, input: true, hints: true },
22
+ spacing: { afterOptions: 1, beforeHints: 1 }
23
+ },
24
+ /** Wizard step with progress indicator */
25
+ WIZARD_STEP: {
26
+ order: ['header', 'progress', 'options', 'input', 'hints'],
27
+ visible: { header: true, progress: true, input: true, hints: true },
28
+ spacing: { afterHeader: 1, afterProgress: 1, afterOptions: 1, beforeHints: 1 }
29
+ },
30
+ /** Minimal layout (options only) */
31
+ MINIMAL: {
32
+ order: ['options'],
33
+ visible: { header: false, input: false, hints: false },
34
+ spacing: {}
35
+ }
36
+ };
@@ -27,6 +27,8 @@ export interface BaseMenuConfig {
27
27
  separatorWidth?: number;
28
28
  /** Keep menu rendered after selection instead of clearing (default: false) */
29
29
  preserveOnSelect?: boolean;
30
+ /** Keep current menu rendered on Ctrl+C exit instead of clearing (default: false) */
31
+ preserveOnExit?: boolean;
30
32
  }
31
33
  /**
32
34
  * Radio menu (single-select) configuration
@@ -64,6 +66,8 @@ export interface CheckboxMenuConfig extends BaseMenuConfig {
64
66
  export interface BooleanMenuConfig extends BaseMenuConfig {
65
67
  /** Question text */
66
68
  question: string;
69
+ /** Optional helper text rendered on the next line */
70
+ helperText?: string;
67
71
  /** Default value */
68
72
  defaultValue?: boolean;
69
73
  /** Yes text */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-menu-kit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A lightweight, customizable CLI menu system with keyboard shortcuts and real-time rendering",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,5 +31,8 @@
31
31
  },
32
32
  "engines": {
33
33
  "node": ">=14.0.0"
34
+ },
35
+ "dependencies": {
36
+ "figlet": "^1.10.0"
34
37
  }
35
38
  }