4runr-os 1.0.80 → 1.0.81
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/ui/v3/section1/index.d.ts +19 -0
- package/dist/ui/v3/section1/index.d.ts.map +1 -0
- package/dist/ui/v3/section1/index.js +174 -0
- package/dist/ui/v3/section1/index.js.map +1 -0
- package/dist/ui/v3/section1/runtime/commandLine.d.ts +49 -0
- package/dist/ui/v3/section1/runtime/commandLine.d.ts.map +1 -0
- package/dist/ui/v3/section1/runtime/commandLine.js +160 -0
- package/dist/ui/v3/section1/runtime/commandLine.js.map +1 -0
- package/dist/ui/v3/section1/runtime/focusLock.d.ts +24 -0
- package/dist/ui/v3/section1/runtime/focusLock.d.ts.map +1 -0
- package/dist/ui/v3/section1/runtime/focusLock.js +44 -0
- package/dist/ui/v3/section1/runtime/focusLock.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Section 1 - Command Line is the Only Input
|
|
4
|
+
*
|
|
5
|
+
* Clean implementation that fixes:
|
|
6
|
+
* - "typing 4x" → typing appears exactly once
|
|
7
|
+
* - Cursor offset → cursor aligned immediately after prompt
|
|
8
|
+
* - Focus leaks → focus locked to command input
|
|
9
|
+
*
|
|
10
|
+
* Layout: 3 widgets at bottom
|
|
11
|
+
* - Label box: "4runr> " (read-only)
|
|
12
|
+
* - Input textbox: only focusable + only writable
|
|
13
|
+
* - Status strip: read-only status info
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Start Section 1 runtime
|
|
17
|
+
*/
|
|
18
|
+
export declare function startSection1(): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/section1/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAsGH;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAgFnD"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Section 1 - Command Line is the Only Input
|
|
4
|
+
*
|
|
5
|
+
* Clean implementation that fixes:
|
|
6
|
+
* - "typing 4x" → typing appears exactly once
|
|
7
|
+
* - Cursor offset → cursor aligned immediately after prompt
|
|
8
|
+
* - Focus leaks → focus locked to command input
|
|
9
|
+
*
|
|
10
|
+
* Layout: 3 widgets at bottom
|
|
11
|
+
* - Label box: "4runr> " (read-only)
|
|
12
|
+
* - Input textbox: only focusable + only writable
|
|
13
|
+
* - Status strip: read-only status info
|
|
14
|
+
*/
|
|
15
|
+
import blessed from 'neo-blessed';
|
|
16
|
+
import { createScreen } from '../section0/runtime/createScreen.js';
|
|
17
|
+
import { initializeLifecycle } from '../section0/runtime/lifecycle.js';
|
|
18
|
+
import { computePhase1Layout } from '../ui/layout/phase1Layout.js';
|
|
19
|
+
import { createCommandLineWidgets, focusCommandInput, attachCommandLineHandlers, updateStatusStrip } from './runtime/commandLine.js';
|
|
20
|
+
import { lockAllPanelsFocus, overrideTabNavigation } from './runtime/focusLock.js';
|
|
21
|
+
const blessedLib = blessed;
|
|
22
|
+
let screen = null;
|
|
23
|
+
let panels = [];
|
|
24
|
+
let commandLineWidgets = null;
|
|
25
|
+
// Command history
|
|
26
|
+
const commandHistory = [];
|
|
27
|
+
let historyIndex = -1;
|
|
28
|
+
/**
|
|
29
|
+
* Create all panels (read-only, non-focusable)
|
|
30
|
+
*/
|
|
31
|
+
function createPanels(screen, layout) {
|
|
32
|
+
if (!layout)
|
|
33
|
+
return [];
|
|
34
|
+
const panelNames = ['POSTURE', 'RESOURCES', 'ASSETS', 'OPERATIONS', 'NETWORK', 'CAPABILITIES'];
|
|
35
|
+
const panelRects = [
|
|
36
|
+
layout.posture,
|
|
37
|
+
layout.resources,
|
|
38
|
+
layout.assets,
|
|
39
|
+
layout.operations,
|
|
40
|
+
layout.network,
|
|
41
|
+
layout.capabilities,
|
|
42
|
+
];
|
|
43
|
+
const createdPanels = [];
|
|
44
|
+
for (let i = 0; i < panelNames.length; i++) {
|
|
45
|
+
const rect = panelRects[i];
|
|
46
|
+
const name = panelNames[i];
|
|
47
|
+
const panel = blessedLib.box({
|
|
48
|
+
top: rect.top,
|
|
49
|
+
left: rect.left,
|
|
50
|
+
width: rect.width,
|
|
51
|
+
height: rect.height,
|
|
52
|
+
border: { type: 'line' },
|
|
53
|
+
tags: true,
|
|
54
|
+
content: `\n ${name} Panel\n\n Content will appear here...`,
|
|
55
|
+
style: {
|
|
56
|
+
border: { fg: 'cyan' },
|
|
57
|
+
fg: 'white',
|
|
58
|
+
},
|
|
59
|
+
// All panels are non-focusable (will be locked by focusLock)
|
|
60
|
+
focusable: false,
|
|
61
|
+
keyable: false,
|
|
62
|
+
mouse: false,
|
|
63
|
+
clickable: false,
|
|
64
|
+
keys: false,
|
|
65
|
+
input: false,
|
|
66
|
+
});
|
|
67
|
+
panel.setLabel(` {cyan-fg}${name}{/}`);
|
|
68
|
+
screen.append(panel);
|
|
69
|
+
createdPanels.push(panel);
|
|
70
|
+
}
|
|
71
|
+
return createdPanels;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Handle command submission
|
|
75
|
+
*/
|
|
76
|
+
function handleCommandSubmit(value) {
|
|
77
|
+
// Add to history
|
|
78
|
+
if (value.trim()) {
|
|
79
|
+
commandHistory.push(value);
|
|
80
|
+
if (commandHistory.length > 100) {
|
|
81
|
+
commandHistory.shift(); // Keep last 100
|
|
82
|
+
}
|
|
83
|
+
historyIndex = -1; // Reset history index
|
|
84
|
+
}
|
|
85
|
+
// TODO: Route command (will be implemented in Section 2)
|
|
86
|
+
// For now, just log to operations panel
|
|
87
|
+
const operationsPanel = panels[3]; // OPERATIONS is index 3
|
|
88
|
+
if (operationsPanel) {
|
|
89
|
+
const timestamp = new Date().toISOString();
|
|
90
|
+
const newLine = `[${timestamp}] Command: ${value}`;
|
|
91
|
+
// Get existing content via getContent() or track separately
|
|
92
|
+
const existingContent = operationsPanel.content || '';
|
|
93
|
+
operationsPanel.setContent(existingContent + '\n' + newLine);
|
|
94
|
+
}
|
|
95
|
+
// Update status strip
|
|
96
|
+
if (commandLineWidgets) {
|
|
97
|
+
updateStatusStrip(commandLineWidgets, `MODE: LOCAL | LAST: ${value.substring(0, 20)} | POSTURE: OK`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Start Section 1 runtime
|
|
102
|
+
*/
|
|
103
|
+
export async function startSection1() {
|
|
104
|
+
// Suppress console.log during TUI
|
|
105
|
+
const originalLog = console.log;
|
|
106
|
+
console.log = () => { };
|
|
107
|
+
try {
|
|
108
|
+
// Create screen (from Section 0)
|
|
109
|
+
screen = createScreen();
|
|
110
|
+
if (!screen) {
|
|
111
|
+
throw new Error('Failed to create screen');
|
|
112
|
+
}
|
|
113
|
+
// Initialize lifecycle (exit handlers from Section 0)
|
|
114
|
+
initializeLifecycle(screen);
|
|
115
|
+
// Compute layout
|
|
116
|
+
const layoutResult = computePhase1Layout(screen.width, screen.height);
|
|
117
|
+
if (!layoutResult.ok || !layoutResult.layout) {
|
|
118
|
+
throw new Error(layoutResult.errorMessage || 'Failed to compute layout');
|
|
119
|
+
}
|
|
120
|
+
const layout = layoutResult.layout;
|
|
121
|
+
// Create panels (read-only)
|
|
122
|
+
panels = createPanels(screen, layout);
|
|
123
|
+
// Create command line widgets (3 widgets: label, input, status)
|
|
124
|
+
const commandLineRect = layout.commandLine;
|
|
125
|
+
commandLineWidgets = createCommandLineWidgets(screen, commandLineRect.top, commandLineRect.left, commandLineRect.width, 1 // Height is 1 for single-line input
|
|
126
|
+
);
|
|
127
|
+
// Lock focus on all panels (they redirect clicks to input)
|
|
128
|
+
lockAllPanelsFocus(panels, () => {
|
|
129
|
+
if (commandLineWidgets) {
|
|
130
|
+
focusCommandInput(commandLineWidgets, 'panel-click');
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Override Tab navigation to refocus input
|
|
134
|
+
overrideTabNavigation(screen, () => {
|
|
135
|
+
if (commandLineWidgets) {
|
|
136
|
+
focusCommandInput(commandLineWidgets, 'tab');
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// Attach command line handlers (deduplicated)
|
|
140
|
+
attachCommandLineHandlers(screen, commandLineWidgets, handleCommandSubmit);
|
|
141
|
+
// Initial focus (once on startup, after render)
|
|
142
|
+
// Use setImmediate to ensure focus happens after initial render
|
|
143
|
+
setImmediate(() => {
|
|
144
|
+
if (commandLineWidgets) {
|
|
145
|
+
focusCommandInput(commandLineWidgets, 'startup');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
// Initial render
|
|
149
|
+
screen.render();
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// Restore console.error for error output
|
|
153
|
+
console.error = originalLog;
|
|
154
|
+
console.error('FATAL: Section 1 failed:', error);
|
|
155
|
+
// Ensure terminal is restored
|
|
156
|
+
if (process.stdout.isTTY) {
|
|
157
|
+
process.stdout.write('\x1b[?25h');
|
|
158
|
+
process.stdout.write('\x1b[?1049l');
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// If run directly (not imported), start the TUI
|
|
164
|
+
const scriptPath = process.argv[1]?.replace(/\\/g, '/') || '';
|
|
165
|
+
const isMainModule = scriptPath.includes('section1/index.js') ||
|
|
166
|
+
scriptPath.includes('section1/index.ts') ||
|
|
167
|
+
import.meta.url.includes('section1/index');
|
|
168
|
+
if (isMainModule) {
|
|
169
|
+
startSection1().catch((error) => {
|
|
170
|
+
console.error('FATAL: Section 1 failed:', error);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ui/v3/section1/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,OAAO,MAAM,aAAa,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACrI,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAGnF,MAAM,UAAU,GAAG,OAAc,CAAC;AAElC,IAAI,MAAM,GAA0B,IAAI,CAAC;AACzC,IAAI,MAAM,GAAkB,EAAE,CAAC;AAC/B,IAAI,kBAAkB,GAA8B,IAAI,CAAC;AAEzD,kBAAkB;AAClB,MAAM,cAAc,GAAa,EAAE,CAAC;AACpC,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;AAEtB;;GAEG;AACH,SAAS,YAAY,CAAC,MAAsB,EAAE,MAAwD;IACpG,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAC/F,MAAM,UAAU,GAAG;QACjB,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,SAAS;QAChB,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,UAAU;QACjB,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,YAAY;KACpB,CAAC;IAEF,MAAM,aAAa,GAAkB,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAE3B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC;YAC3B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YACxB,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,MAAM,IAAI,wCAAwC;YAC3D,KAAK,EAAE;gBACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;gBACtB,EAAE,EAAE,OAAO;aACZ;YACD,6DAA6D;YAC7D,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,KAAK;SACb,CAAgB,CAAC;QAElB,KAAK,CAAC,QAAQ,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,KAAa;IACxC,iBAAiB;IACjB,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACjB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,cAAc,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAChC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB;QAC1C,CAAC;QACD,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB;IAC3C,CAAC;IAED,yDAAyD;IACzD,wCAAwC;IACxC,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;IAC3D,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,SAAS,cAAc,KAAK,EAAE,CAAC;QACnD,4DAA4D;QAC5D,MAAM,eAAe,GAAI,eAAuB,CAAC,OAAO,IAAI,EAAE,CAAC;QAC/D,eAAe,CAAC,UAAU,CAAC,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,sBAAsB;IACtB,IAAI,kBAAkB,EAAE,CAAC;QACvB,iBAAiB,CAAC,kBAAkB,EAAE,uBAAuB,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,kCAAkC;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAChC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IAEvB,IAAI,CAAC;QACH,iCAAiC;QACjC,MAAM,GAAG,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,sDAAsD;QACtD,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAE5B,iBAAiB;QACjB,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtE,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,YAAY,IAAI,0BAA0B,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;QAEnC,4BAA4B;QAC5B,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEtC,gEAAgE;QAChE,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,CAAC;QAC3C,kBAAkB,GAAG,wBAAwB,CAC3C,MAAM,EACN,eAAe,CAAC,GAAG,EACnB,eAAe,CAAC,IAAI,EACpB,eAAe,CAAC,KAAK,EACrB,CAAC,CAAC,oCAAoC;SACvC,CAAC;QAEF,2DAA2D;QAC3D,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE;YAC9B,IAAI,kBAAkB,EAAE,CAAC;gBACvB,iBAAiB,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;YACvD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,2CAA2C;QAC3C,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE;YACjC,IAAI,kBAAkB,EAAE,CAAC;gBACvB,iBAAiB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8CAA8C;QAC9C,yBAAyB,CACvB,MAAM,EACN,kBAAkB,EAClB,mBAAmB,CACpB,CAAC;QAEF,gDAAgD;QAChD,gEAAgE;QAChE,YAAY,CAAC,GAAG,EAAE;YAChB,IAAI,kBAAkB,EAAE,CAAC;gBACvB,iBAAiB,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;YACnD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,iBAAiB;QACjB,MAAM,CAAC,MAAM,EAAE,CAAC;IAElB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yCAAyC;QACzC,OAAO,CAAC,KAAK,GAAI,WAAmB,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QAEjD,8BAA8B;QAC9B,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;AAC9D,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IACxC,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IACxC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAEhE,IAAI,YAAY,EAAE,CAAC;IACjB,aAAa,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9B,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section 1 - Command Line Input System
|
|
3
|
+
*
|
|
4
|
+
* Clean implementation with:
|
|
5
|
+
* - 3 widgets: Label box, Input textbox, Status strip
|
|
6
|
+
* - Only textbox is focusable
|
|
7
|
+
* - Deduplicated handler registration
|
|
8
|
+
* - Proper cursor alignment
|
|
9
|
+
* - Focus lock
|
|
10
|
+
*/
|
|
11
|
+
import type { Widgets } from 'neo-blessed';
|
|
12
|
+
export interface CommandLineWidgets {
|
|
13
|
+
labelBox: Widgets.Box;
|
|
14
|
+
inputTextbox: Widgets.Textbox;
|
|
15
|
+
statusStrip: Widgets.Box;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create the three command line widgets
|
|
19
|
+
*
|
|
20
|
+
* Layout:
|
|
21
|
+
* [Label Box: "4runr> "] [Input Textbox] [Status Strip]
|
|
22
|
+
*/
|
|
23
|
+
export declare function createCommandLineWidgets(screen: Widgets.Screen, top: number, left: number, width: number, height: number): CommandLineWidgets;
|
|
24
|
+
/**
|
|
25
|
+
* Focus command input (without creating refocus loops)
|
|
26
|
+
*
|
|
27
|
+
* Rules:
|
|
28
|
+
* - Call only: once on startup, after submit, after command handling
|
|
29
|
+
* - Do NOT call inside: screen.on("render"), periodic loops, panel renders
|
|
30
|
+
*/
|
|
31
|
+
export declare function focusCommandInput(widgets: CommandLineWidgets, reason?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Attach command line handlers (deduplicated)
|
|
34
|
+
*
|
|
35
|
+
* Rules:
|
|
36
|
+
* - Attach exactly once (guarded)
|
|
37
|
+
* - Use textbox events only for typing + Enter submission
|
|
38
|
+
* - Use screen keys only for global exit shortcuts (q, Ctrl+C)
|
|
39
|
+
*/
|
|
40
|
+
export declare function attachCommandLineHandlers(screen: Widgets.Screen, widgets: CommandLineWidgets, onSubmit: (value: string) => void, onCancel?: () => void): void;
|
|
41
|
+
/**
|
|
42
|
+
* Update status strip content
|
|
43
|
+
*/
|
|
44
|
+
export declare function updateStatusStrip(widgets: CommandLineWidgets, content: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Reset handler attachment guard (for testing)
|
|
47
|
+
*/
|
|
48
|
+
export declare function resetCommandLineHandlers(): void;
|
|
49
|
+
//# sourceMappingURL=commandLine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandLine.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/section1/runtime/commandLine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC;CAC1B;AASD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,kBAAkB,CAmEpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,kBAAkB,EAC3B,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CASN;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,IAAI,CAyCN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,GACd,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section 1 - Command Line Input System
|
|
3
|
+
*
|
|
4
|
+
* Clean implementation with:
|
|
5
|
+
* - 3 widgets: Label box, Input textbox, Status strip
|
|
6
|
+
* - Only textbox is focusable
|
|
7
|
+
* - Deduplicated handler registration
|
|
8
|
+
* - Proper cursor alignment
|
|
9
|
+
* - Focus lock
|
|
10
|
+
*/
|
|
11
|
+
import blessed from 'neo-blessed';
|
|
12
|
+
const blessedLib = blessed;
|
|
13
|
+
const PROMPT = '4runr> ';
|
|
14
|
+
const PROMPT_WIDTH = PROMPT.length;
|
|
15
|
+
const GAP = 1; // Gap between label and input
|
|
16
|
+
// Guard to prevent duplicate handler attachment
|
|
17
|
+
let commandHandlersAttached = false;
|
|
18
|
+
/**
|
|
19
|
+
* Create the three command line widgets
|
|
20
|
+
*
|
|
21
|
+
* Layout:
|
|
22
|
+
* [Label Box: "4runr> "] [Input Textbox] [Status Strip]
|
|
23
|
+
*/
|
|
24
|
+
export function createCommandLineWidgets(screen, top, left, width, height) {
|
|
25
|
+
// Calculate widths
|
|
26
|
+
const statusWidth = 40; // Fixed width for status strip
|
|
27
|
+
const inputWidth = width - PROMPT_WIDTH - GAP - statusWidth - GAP;
|
|
28
|
+
// 1. Label box (read-only, non-focusable)
|
|
29
|
+
const labelBox = blessedLib.box({
|
|
30
|
+
top,
|
|
31
|
+
left,
|
|
32
|
+
width: PROMPT_WIDTH,
|
|
33
|
+
height: 1,
|
|
34
|
+
content: PROMPT,
|
|
35
|
+
tags: false, // No tags to avoid width issues
|
|
36
|
+
mouse: false,
|
|
37
|
+
keys: false,
|
|
38
|
+
focusable: false,
|
|
39
|
+
clickable: false,
|
|
40
|
+
});
|
|
41
|
+
// 2. Input textbox (only focusable + only writable)
|
|
42
|
+
const inputTextbox = blessedLib.textbox({
|
|
43
|
+
top,
|
|
44
|
+
left: left + PROMPT_WIDTH + GAP,
|
|
45
|
+
width: inputWidth,
|
|
46
|
+
height: 1,
|
|
47
|
+
inputOnFocus: true,
|
|
48
|
+
keys: true,
|
|
49
|
+
mouse: true,
|
|
50
|
+
censor: false,
|
|
51
|
+
padding: {
|
|
52
|
+
left: 0,
|
|
53
|
+
right: 0,
|
|
54
|
+
top: 0,
|
|
55
|
+
bottom: 0,
|
|
56
|
+
},
|
|
57
|
+
style: {
|
|
58
|
+
fg: 'white',
|
|
59
|
+
focus: {
|
|
60
|
+
fg: 'white',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
// 3. Status strip (read-only, non-focusable)
|
|
65
|
+
const statusStrip = blessedLib.box({
|
|
66
|
+
top,
|
|
67
|
+
left: left + PROMPT_WIDTH + GAP + inputWidth + GAP,
|
|
68
|
+
width: statusWidth,
|
|
69
|
+
height: 1,
|
|
70
|
+
content: 'MODE: LOCAL | CONNECT: ... | POSTURE: ...',
|
|
71
|
+
tags: false,
|
|
72
|
+
mouse: false,
|
|
73
|
+
keys: false,
|
|
74
|
+
focusable: false,
|
|
75
|
+
clickable: false,
|
|
76
|
+
});
|
|
77
|
+
// Append to screen
|
|
78
|
+
screen.append(labelBox);
|
|
79
|
+
screen.append(inputTextbox);
|
|
80
|
+
screen.append(statusStrip);
|
|
81
|
+
return {
|
|
82
|
+
labelBox,
|
|
83
|
+
inputTextbox,
|
|
84
|
+
statusStrip,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Focus command input (without creating refocus loops)
|
|
89
|
+
*
|
|
90
|
+
* Rules:
|
|
91
|
+
* - Call only: once on startup, after submit, after command handling
|
|
92
|
+
* - Do NOT call inside: screen.on("render"), periodic loops, panel renders
|
|
93
|
+
*/
|
|
94
|
+
export function focusCommandInput(widgets, reason) {
|
|
95
|
+
// Use setImmediate to ensure focus happens after current render cycle
|
|
96
|
+
setImmediate(() => {
|
|
97
|
+
try {
|
|
98
|
+
widgets.inputTextbox.focus();
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
// Ignore focus errors (widget might be destroyed)
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Attach command line handlers (deduplicated)
|
|
107
|
+
*
|
|
108
|
+
* Rules:
|
|
109
|
+
* - Attach exactly once (guarded)
|
|
110
|
+
* - Use textbox events only for typing + Enter submission
|
|
111
|
+
* - Use screen keys only for global exit shortcuts (q, Ctrl+C)
|
|
112
|
+
*/
|
|
113
|
+
export function attachCommandLineHandlers(screen, widgets, onSubmit, onCancel) {
|
|
114
|
+
// Guard: ensure handlers attach exactly once
|
|
115
|
+
if (commandHandlersAttached) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
commandHandlersAttached = true;
|
|
119
|
+
const { inputTextbox } = widgets;
|
|
120
|
+
// Single submit handler (textbox.on("submit"))
|
|
121
|
+
inputTextbox.on('submit', (value) => {
|
|
122
|
+
const trimmed = value.trim();
|
|
123
|
+
if (trimmed) {
|
|
124
|
+
onSubmit(trimmed);
|
|
125
|
+
}
|
|
126
|
+
// Clear input
|
|
127
|
+
inputTextbox.clearValue();
|
|
128
|
+
// Refocus (after submit)
|
|
129
|
+
focusCommandInput(widgets, 'submit');
|
|
130
|
+
});
|
|
131
|
+
// Optional cancel handler
|
|
132
|
+
if (onCancel) {
|
|
133
|
+
inputTextbox.on('cancel', () => {
|
|
134
|
+
inputTextbox.clearValue();
|
|
135
|
+
onCancel();
|
|
136
|
+
focusCommandInput(widgets, 'cancel');
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// Handle Escape key to clear input
|
|
140
|
+
inputTextbox.key('escape', () => {
|
|
141
|
+
inputTextbox.clearValue();
|
|
142
|
+
focusCommandInput(widgets, 'escape');
|
|
143
|
+
});
|
|
144
|
+
// Do NOT attach screen-level keypress handlers for typing
|
|
145
|
+
// The textbox handles all typing automatically
|
|
146
|
+
// Only use screen keys for global shortcuts (already handled in Section 0)
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Update status strip content
|
|
150
|
+
*/
|
|
151
|
+
export function updateStatusStrip(widgets, content) {
|
|
152
|
+
widgets.statusStrip.setContent(content);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Reset handler attachment guard (for testing)
|
|
156
|
+
*/
|
|
157
|
+
export function resetCommandLineHandlers() {
|
|
158
|
+
commandHandlersAttached = false;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=commandLine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandLine.js","sourceRoot":"","sources":["../../../../../src/ui/v3/section1/runtime/commandLine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section 1 - Focus Lock
|
|
3
|
+
*
|
|
4
|
+
* Ensures focus never leaves the command input
|
|
5
|
+
* - Panels are non-focusable
|
|
6
|
+
* - Clicking panels refocuses input
|
|
7
|
+
* - Tab navigation is disabled or overridden
|
|
8
|
+
*/
|
|
9
|
+
import type { Widgets } from 'neo-blessed';
|
|
10
|
+
/**
|
|
11
|
+
* Apply focus lock to a panel widget
|
|
12
|
+
*
|
|
13
|
+
* Makes the panel non-focusable and redirects clicks to command input
|
|
14
|
+
*/
|
|
15
|
+
export declare function lockPanelFocus(panel: Widgets.Box, refocusInput: () => void): void;
|
|
16
|
+
/**
|
|
17
|
+
* Lock focus on all panels
|
|
18
|
+
*/
|
|
19
|
+
export declare function lockAllPanelsFocus(panels: Widgets.Box[], refocusInput: () => void): void;
|
|
20
|
+
/**
|
|
21
|
+
* Override Tab key to refocus input instead of moving focus
|
|
22
|
+
*/
|
|
23
|
+
export declare function overrideTabNavigation(screen: Widgets.Screen, refocusInput: () => void): void;
|
|
24
|
+
//# sourceMappingURL=focusLock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusLock.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/section1/runtime/focusLock.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,CAAC,GAAG,EAClB,YAAY,EAAE,MAAM,IAAI,GACvB,IAAI,CAcN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EACrB,YAAY,EAAE,MAAM,IAAI,GACvB,IAAI,CAIN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,YAAY,EAAE,MAAM,IAAI,GACvB,IAAI,CAIN"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section 1 - Focus Lock
|
|
3
|
+
*
|
|
4
|
+
* Ensures focus never leaves the command input
|
|
5
|
+
* - Panels are non-focusable
|
|
6
|
+
* - Clicking panels refocuses input
|
|
7
|
+
* - Tab navigation is disabled or overridden
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Apply focus lock to a panel widget
|
|
11
|
+
*
|
|
12
|
+
* Makes the panel non-focusable and redirects clicks to command input
|
|
13
|
+
*/
|
|
14
|
+
export function lockPanelFocus(panel, refocusInput) {
|
|
15
|
+
// Make panel non-focusable
|
|
16
|
+
panel.focusable = false;
|
|
17
|
+
panel.keyable = false;
|
|
18
|
+
panel.mouse = false;
|
|
19
|
+
panel.clickable = false;
|
|
20
|
+
panel.keys = false;
|
|
21
|
+
panel.input = false;
|
|
22
|
+
panel.inputOnFocus = false;
|
|
23
|
+
// If mouse is needed for future drilldowns, redirect clicks to refocus input
|
|
24
|
+
panel.on('click', () => {
|
|
25
|
+
refocusInput();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Lock focus on all panels
|
|
30
|
+
*/
|
|
31
|
+
export function lockAllPanelsFocus(panels, refocusInput) {
|
|
32
|
+
for (const panel of panels) {
|
|
33
|
+
lockPanelFocus(panel, refocusInput);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Override Tab key to refocus input instead of moving focus
|
|
38
|
+
*/
|
|
39
|
+
export function overrideTabNavigation(screen, refocusInput) {
|
|
40
|
+
screen.key('tab', () => {
|
|
41
|
+
refocusInput();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=focusLock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusLock.js","sourceRoot":"","sources":["../../../../../src/ui/v3/section1/runtime/focusLock.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAkB,EAClB,YAAwB;IAExB,2BAA2B;IAC1B,KAAa,CAAC,SAAS,GAAG,KAAK,CAAC;IAChC,KAAa,CAAC,OAAO,GAAG,KAAK,CAAC;IAC9B,KAAa,CAAC,KAAK,GAAG,KAAK,CAAC;IAC5B,KAAa,CAAC,SAAS,GAAG,KAAK,CAAC;IAChC,KAAa,CAAC,IAAI,GAAG,KAAK,CAAC;IAC3B,KAAa,CAAC,KAAK,GAAG,KAAK,CAAC;IAC5B,KAAa,CAAC,YAAY,GAAG,KAAK,CAAC;IAEpC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAqB,EACrB,YAAwB;IAExB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,cAAc,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAsB,EACtB,YAAwB;IAExB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE;QACrB,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC"}
|