cli-menu-kit 0.1.19 → 0.1.21

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.
@@ -10,6 +10,30 @@ exports.createSimpleSummary = createSimpleSummary;
10
10
  const terminal_js_1 = require("../../core/terminal.js");
11
11
  const colors_js_1 = require("../../core/colors.js");
12
12
  const terminal_js_2 = require("../../core/terminal.js");
13
+ /**
14
+ * Wrap text to fit within a specific width
15
+ */
16
+ function wrapText(text, maxWidth) {
17
+ const words = text.split(' ');
18
+ const lines = [];
19
+ let currentLine = '';
20
+ for (const word of words) {
21
+ const testLine = currentLine ? `${currentLine} ${word}` : word;
22
+ if (testLine.length <= maxWidth) {
23
+ currentLine = testLine;
24
+ }
25
+ else {
26
+ if (currentLine) {
27
+ lines.push(currentLine);
28
+ }
29
+ currentLine = word;
30
+ }
31
+ }
32
+ if (currentLine) {
33
+ lines.push(currentLine);
34
+ }
35
+ return lines;
36
+ }
13
37
  /**
14
38
  * Render a summary table
15
39
  * @param config - Summary table configuration
@@ -17,7 +41,8 @@ const terminal_js_2 = require("../../core/terminal.js");
17
41
  function renderSummaryTable(config) {
18
42
  const { title, sections, width } = config;
19
43
  const termWidth = (0, terminal_js_2.getTerminalWidth)();
20
- const boxWidth = width || Math.min(termWidth - 4, 60);
44
+ // Use full terminal width minus padding, or specified width
45
+ const boxWidth = width || Math.max(60, termWidth - 4);
21
46
  // Calculate content width (excluding borders and padding)
22
47
  const contentWidth = boxWidth - 4;
23
48
  // Top border
@@ -42,11 +67,33 @@ function renderSummaryTable(config) {
42
67
  }
43
68
  // Section items
44
69
  section.items.forEach(item => {
45
- const itemLine = ` ${item.key}:${' '.repeat(Math.max(1, 15 - item.key.length))}${item.value}`;
46
- // Remove ANSI codes for length calculation
47
- const plainItemLine = itemLine.replace(/\x1b\[[0-9;]*m/g, '');
48
- const remainingSpace = boxWidth - plainItemLine.length - 2;
49
- (0, terminal_js_1.writeLine)(`│${itemLine}${' '.repeat(Math.max(0, remainingSpace))}│`);
70
+ const keyPadding = 15;
71
+ const valueMaxWidth = contentWidth - keyPadding - 2; // 2 for leading spaces
72
+ // Check if value needs wrapping
73
+ const plainValue = item.value.replace(/\x1b\[[0-9;]*m/g, '');
74
+ if (plainValue.length > valueMaxWidth) {
75
+ // Wrap the value
76
+ const wrappedLines = wrapText(plainValue, valueMaxWidth);
77
+ // First line with key
78
+ const firstLine = ` ${item.key}:${' '.repeat(Math.max(1, keyPadding - item.key.length))}${wrappedLines[0]}`;
79
+ const plainFirstLine = firstLine.replace(/\x1b\[[0-9;]*m/g, '');
80
+ const remainingSpace = boxWidth - plainFirstLine.length - 2;
81
+ (0, terminal_js_1.writeLine)(`│${firstLine}${' '.repeat(Math.max(0, remainingSpace))}│`);
82
+ // Subsequent lines with indentation
83
+ for (let i = 1; i < wrappedLines.length; i++) {
84
+ const continuationLine = ` ${' '.repeat(keyPadding)}${wrappedLines[i]}`;
85
+ const plainContinuationLine = continuationLine.replace(/\x1b\[[0-9;]*m/g, '');
86
+ const contRemainingSpace = boxWidth - plainContinuationLine.length - 2;
87
+ (0, terminal_js_1.writeLine)(`│${continuationLine}${' '.repeat(Math.max(0, contRemainingSpace))}│`);
88
+ }
89
+ }
90
+ else {
91
+ // No wrapping needed
92
+ const itemLine = ` ${item.key}:${' '.repeat(Math.max(1, keyPadding - item.key.length))}${item.value}`;
93
+ const plainItemLine = itemLine.replace(/\x1b\[[0-9;]*m/g, '');
94
+ const remainingSpace = boxWidth - plainItemLine.length - 2;
95
+ (0, terminal_js_1.writeLine)(`│${itemLine}${' '.repeat(Math.max(0, remainingSpace))}│`);
96
+ }
50
97
  });
51
98
  // Add spacing between sections (except after last section)
52
99
  if (sectionIndex < sections.length - 1) {
@@ -89,6 +89,8 @@ async function showRadioMenu(config) {
89
89
  selectableIndices.push(index);
90
90
  }
91
91
  });
92
+ // Use MINIMAL layout for single-option menus
93
+ const effectiveLayout = selectableIndices.length === 1 ? layout_types_js_1.LAYOUT_PRESETS.MINIMAL : layout;
92
94
  // Ensure selectedIndex points to a selectable option
93
95
  if (!selectableIndices.includes(selectedIndex)) {
94
96
  selectedIndex = selectableIndices[0] || 0;
@@ -114,16 +116,16 @@ async function showRadioMenu(config) {
114
116
  (0, terminal_js_1.clearMenu)(state);
115
117
  let lineCount = 0;
116
118
  // Render based on layout order
117
- layout.order.forEach(element => {
119
+ effectiveLayout.order.forEach(element => {
118
120
  // Add spacing before element
119
121
  const spacingKey = `before${element.charAt(0).toUpperCase() + element.slice(1)}`;
120
- if (layout.spacing?.[spacingKey]) {
121
- (0, renderer_js_1.renderBlankLines)(layout.spacing[spacingKey]);
122
- lineCount += layout.spacing[spacingKey];
122
+ if (effectiveLayout.spacing?.[spacingKey]) {
123
+ (0, renderer_js_1.renderBlankLines)(effectiveLayout.spacing[spacingKey]);
124
+ lineCount += effectiveLayout.spacing[spacingKey];
123
125
  }
124
126
  switch (element) {
125
127
  case 'header':
126
- if (layout.visible.header && title) {
128
+ if (effectiveLayout.visible.header && title) {
127
129
  (0, renderer_js_1.renderHeader)(` ${title}`, colors_js_1.colors.cyan);
128
130
  lineCount++;
129
131
  }
@@ -156,7 +158,7 @@ async function showRadioMenu(config) {
156
158
  });
157
159
  break;
158
160
  case 'input':
159
- if (layout.visible.input) {
161
+ if (effectiveLayout.visible.input) {
160
162
  // Calculate display value (current selection number)
161
163
  let displayValue = '';
162
164
  const currentItem = optionData[selectedIndex];
@@ -174,7 +176,7 @@ async function showRadioMenu(config) {
174
176
  }
175
177
  break;
176
178
  case 'hints':
177
- if (layout.visible.hints && displayHints.length > 0) {
179
+ if (effectiveLayout.visible.hints && displayHints.length > 0) {
178
180
  (0, renderer_js_1.renderHints)(displayHints);
179
181
  lineCount++;
180
182
  }
@@ -182,9 +184,9 @@ async function showRadioMenu(config) {
182
184
  }
183
185
  // Add spacing after element
184
186
  const afterSpacingKey = `after${element.charAt(0).toUpperCase() + element.slice(1)}`;
185
- if (layout.spacing?.[afterSpacingKey]) {
186
- (0, renderer_js_1.renderBlankLines)(layout.spacing[afterSpacingKey]);
187
- lineCount += layout.spacing[afterSpacingKey];
187
+ if (effectiveLayout.spacing?.[afterSpacingKey]) {
188
+ (0, renderer_js_1.renderBlankLines)(effectiveLayout.spacing[afterSpacingKey]);
189
+ lineCount += effectiveLayout.spacing[afterSpacingKey];
188
190
  }
189
191
  });
190
192
  state.renderedLines = lineCount;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-menu-kit",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
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",