spawn-term 3.0.0 → 3.0.2
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/cjs/components/App.js +25 -6
- package/dist/cjs/components/App.js.map +1 -1
- package/dist/cjs/components/ChildProcess.js +2 -17
- package/dist/cjs/components/ChildProcess.js.map +1 -1
- package/dist/cjs/components/CompactProcessLine.js +27 -36
- package/dist/cjs/components/CompactProcessLine.js.map +1 -1
- package/dist/cjs/components/StatusBar.js +4 -19
- package/dist/cjs/components/StatusBar.js.map +1 -1
- package/dist/cjs/constants.js +18 -0
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/lib/clipText.js +56 -0
- package/dist/cjs/lib/clipText.js.map +1 -0
- package/dist/cjs/session.js +43 -10
- package/dist/cjs/session.js.map +1 -1
- package/dist/cjs/src/constants.d.ts +4 -0
- package/dist/cjs/src/lib/clipText.d.ts +9 -0
- package/dist/cjs/src/state/processStore.d.ts +5 -2
- package/dist/cjs/state/processStore.js +20 -2
- package/dist/cjs/state/processStore.js.map +1 -1
- package/dist/esm/components/App.js +30 -9
- package/dist/esm/components/App.js.map +1 -1
- package/dist/esm/components/ChildProcess.js +1 -16
- package/dist/esm/components/ChildProcess.js.map +1 -1
- package/dist/esm/components/CompactProcessLine.js +26 -35
- package/dist/esm/components/CompactProcessLine.js.map +1 -1
- package/dist/esm/components/StatusBar.js +3 -18
- package/dist/esm/components/StatusBar.js.map +1 -1
- package/dist/esm/constants.js +16 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/lib/clipText.js +37 -0
- package/dist/esm/lib/clipText.js.map +1 -0
- package/dist/esm/session.js +38 -8
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/src/constants.d.ts +4 -0
- package/dist/esm/src/lib/clipText.d.ts +9 -0
- package/dist/esm/src/state/processStore.d.ts +5 -2
- package/dist/esm/state/processStore.js +18 -2
- package/dist/esm/state/processStore.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/session.js
CHANGED
|
@@ -109,6 +109,8 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
109
109
|
this.closed = false;
|
|
110
110
|
this.waitCallbacks = [];
|
|
111
111
|
this.store = new _processStorets.ProcessStore(options);
|
|
112
|
+
var _options_interactive;
|
|
113
|
+
this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
|
|
112
114
|
// Render Ink app immediately
|
|
113
115
|
this.inkApp = (0, _ink.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_Appts.default, {
|
|
114
116
|
store: this.store
|
|
@@ -244,25 +246,52 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
244
246
|
this.cleanup();
|
|
245
247
|
};
|
|
246
248
|
_proto.waitAndClose = function waitAndClose(callback) {
|
|
249
|
+
var _this = this;
|
|
247
250
|
if (this.closed) {
|
|
248
251
|
callback === null || callback === void 0 ? void 0 : callback();
|
|
249
252
|
return;
|
|
250
253
|
}
|
|
254
|
+
if (callback) this.waitCallbacks.push(callback);
|
|
251
255
|
if (this.runningCount === 0) {
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
256
|
+
if (this.isInteractive) {
|
|
257
|
+
// In interactive mode, wait for user to quit (press 'q')
|
|
258
|
+
var unsubscribe = this.store.subscribe(function() {
|
|
259
|
+
if (_this.store.getShouldExit()) {
|
|
260
|
+
unsubscribe();
|
|
261
|
+
_this.closeAndCallWaitCallbacks();
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
this.closeAndCallWaitCallbacks();
|
|
266
|
+
}
|
|
257
267
|
}
|
|
268
|
+
// If runningCount > 0, will close when it hits 0 in onProcessComplete
|
|
258
269
|
};
|
|
259
270
|
_proto.onProcessComplete = function onProcessComplete() {
|
|
271
|
+
var _this = this;
|
|
260
272
|
this.runningCount--;
|
|
261
273
|
if (this.runningCount === 0 && this.waitCallbacks.length > 0) {
|
|
262
|
-
this.
|
|
274
|
+
if (this.isInteractive) {
|
|
275
|
+
// In interactive mode, wait for user to quit (press 'q')
|
|
276
|
+
var unsubscribe = this.store.subscribe(function() {
|
|
277
|
+
if (_this.store.getShouldExit()) {
|
|
278
|
+
unsubscribe();
|
|
279
|
+
_this.closeAndCallWaitCallbacks();
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
this.closeAndCallWaitCallbacks();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
_proto.closeAndCallWaitCallbacks = function closeAndCallWaitCallbacks() {
|
|
288
|
+
var _this = this;
|
|
289
|
+
if (this.closed) return;
|
|
290
|
+
this.closed = true;
|
|
291
|
+
this.cleanup(function() {
|
|
263
292
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
264
293
|
try {
|
|
265
|
-
for(var _iterator =
|
|
294
|
+
for(var _iterator = _this.waitCallbacks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
266
295
|
var cb = _step.value;
|
|
267
296
|
cb();
|
|
268
297
|
}
|
|
@@ -280,10 +309,10 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
280
309
|
}
|
|
281
310
|
}
|
|
282
311
|
}
|
|
283
|
-
|
|
284
|
-
}
|
|
312
|
+
_this.waitCallbacks = [];
|
|
313
|
+
});
|
|
285
314
|
};
|
|
286
|
-
_proto.cleanup = function cleanup() {
|
|
315
|
+
_proto.cleanup = function cleanup(onComplete) {
|
|
287
316
|
var _this = this;
|
|
288
317
|
// Signal exit to React component
|
|
289
318
|
this.store.signalExit(function() {
|
|
@@ -295,11 +324,15 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
295
324
|
this.inkApp.waitUntilExit().then(function() {
|
|
296
325
|
var cb = _this.store.getExitCallback();
|
|
297
326
|
cb === null || cb === void 0 ? void 0 : cb();
|
|
327
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
298
328
|
}).catch(function() {
|
|
299
329
|
var cb = _this.store.getExitCallback();
|
|
300
330
|
cb === null || cb === void 0 ? void 0 : cb();
|
|
331
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
301
332
|
});
|
|
302
333
|
this.inkApp = null;
|
|
334
|
+
} else {
|
|
335
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
303
336
|
}
|
|
304
337
|
};
|
|
305
338
|
return SessionImpl;
|
package/dist/cjs/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/session.tsx"],"sourcesContent":["import spawn, { crossSpawn, type SpawnResult } from 'cross-spawn-cb';\nimport crypto from 'crypto';\nimport { render } from 'ink';\nimport oo from 'on-one';\nimport Queue from 'queue-cb';\n\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport addLines from './lib/addLines.ts';\nimport concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } from './types.ts';\nimport { LineType } from './types.ts';\n\nexport interface Session {\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;\n close(): void;\n waitAndClose(callback?: () => void): void;\n}\n\nclass SessionImpl implements Session {\n private store: ProcessStore;\n private inkApp: ReturnType<typeof render> | null = null;\n private runningCount = 0;\n private closed = false;\n private waitCallbacks: (() => void)[] = [];\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n\n // Render Ink app immediately\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: true,\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void {\n if (this.closed) {\n throw new Error('Session is closed');\n }\n\n const { encoding, stdio, ...csOptions } = spawnOptions;\n\n if (stdio === 'inherit') {\n this.runningCount++;\n const id = crypto.randomUUID();\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof addLines> | null, stderr: null as ReturnType<typeof addLines> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stdout, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stderr, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n this.store.updateProcess(id, { state: err ? 'error' : 'success' });\n\n this.onProcessComplete();\n err ? callback(err) : callback(null, res);\n });\n } else {\n // Non-inherit mode: collect output but don't display in UI\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof concatWritable> | null, stderr: null as ReturnType<typeof concatWritable> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = concatWritable((output) => {\n (outputs.stdout as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = concatWritable((output) => {\n (outputs.stderr as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n err ? callback(err) : callback(null, res);\n });\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup();\n }\n\n waitAndClose(callback?: () => void): void {\n if (this.closed) {\n callback?.();\n return;\n }\n\n if (this.runningCount === 0) {\n this.close();\n callback?.();\n } else {\n if (callback) this.waitCallbacks.push(callback);\n // Will close when runningCount hits 0\n }\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n this.close();\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n }\n }\n\n private cleanup(): void {\n // Signal exit to React component\n this.store.signalExit(() => {\n this.store.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n });\n\n // Wait for Ink to finish\n if (this.inkApp) {\n this.inkApp\n .waitUntilExit()\n .then(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n });\n this.inkApp = null;\n }\n }\n}\n\nexport function createSession(options: SessionOptions = {}): Session {\n return new SessionImpl(options);\n}\n"],"names":["createSession","SessionImpl","options","inkApp","runningCount","closed","waitCallbacks","store","ProcessStore","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","id","crypto","randomUUID","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","cp","crossSpawn","outputs","stdout","stderr","queue","Queue","addLines","appendLines","map","text","type","LineType","defer","oo","bind","pipe","worker","await","err","res","output","updateProcess","onProcessComplete","concatWritable","toString","close","cleanup","waitAndClose","push","length","cb","signalExit","reset","process","write","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/session.tsx"],"sourcesContent":["import spawn, { crossSpawn, type SpawnResult } from 'cross-spawn-cb';\nimport crypto from 'crypto';\nimport { render } from 'ink';\nimport oo from 'on-one';\nimport Queue from 'queue-cb';\n\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport addLines from './lib/addLines.ts';\nimport concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } from './types.ts';\nimport { LineType } from './types.ts';\n\nexport interface Session {\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;\n close(): void;\n waitAndClose(callback?: () => void): void;\n}\n\nclass SessionImpl implements Session {\n private store: ProcessStore;\n private inkApp: ReturnType<typeof render> | null = null;\n private runningCount = 0;\n private closed = false;\n private waitCallbacks: (() => void)[] = [];\n private isInteractive: boolean;\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n this.isInteractive = options.interactive ?? false;\n\n // Render Ink app immediately\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: true,\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void {\n if (this.closed) {\n throw new Error('Session is closed');\n }\n\n const { encoding, stdio, ...csOptions } = spawnOptions;\n\n if (stdio === 'inherit') {\n this.runningCount++;\n const id = crypto.randomUUID();\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof addLines> | null, stderr: null as ReturnType<typeof addLines> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stdout, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stderr, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n this.store.updateProcess(id, { state: err ? 'error' : 'success' });\n\n this.onProcessComplete();\n err ? callback(err) : callback(null, res);\n });\n } else {\n // Non-inherit mode: collect output but don't display in UI\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof concatWritable> | null, stderr: null as ReturnType<typeof concatWritable> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = concatWritable((output) => {\n (outputs.stdout as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = concatWritable((output) => {\n (outputs.stderr as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n err ? callback(err) : callback(null, res);\n });\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup();\n }\n\n waitAndClose(callback?: () => void): void {\n if (this.closed) {\n callback?.();\n return;\n }\n\n if (callback) this.waitCallbacks.push(callback);\n\n if (this.runningCount === 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n // If runningCount > 0, will close when it hits 0 in onProcessComplete\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n }\n\n private closeAndCallWaitCallbacks(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup(() => {\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n });\n }\n\n private cleanup(onComplete?: () => void): void {\n // Signal exit to React component\n this.store.signalExit(() => {\n this.store.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n });\n\n // Wait for Ink to finish\n if (this.inkApp) {\n this.inkApp\n .waitUntilExit()\n .then(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n });\n this.inkApp = null;\n } else {\n onComplete?.();\n }\n }\n}\n\nexport function createSession(options: SessionOptions = {}): Session {\n return new SessionImpl(options);\n}\n"],"names":["createSession","SessionImpl","options","inkApp","runningCount","closed","waitCallbacks","store","ProcessStore","isInteractive","interactive","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","id","crypto","randomUUID","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","cp","crossSpawn","outputs","stdout","stderr","queue","Queue","addLines","appendLines","map","text","type","LineType","defer","oo","bind","pipe","worker","await","err","res","output","updateProcess","onProcessComplete","concatWritable","toString","close","cleanup","waitAndClose","push","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","process","write","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
|
|
@@ -5,3 +5,7 @@ export declare const BATCH_MAX_LINES = 20;
|
|
|
5
5
|
export declare const BATCH_MAX_WAIT_MS = 50;
|
|
6
6
|
export declare const DEFAULT_MAX_FPS = 20;
|
|
7
7
|
export declare const EXPANDED_MAX_VISIBLE_LINES = 10;
|
|
8
|
+
export declare const SPINNER: {
|
|
9
|
+
interval: number;
|
|
10
|
+
frames: string[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the visible length of a string, ignoring ANSI escape codes.
|
|
3
|
+
*/
|
|
4
|
+
export declare function visibleLength(str: string): number;
|
|
5
|
+
/**
|
|
6
|
+
* Clip text to a maximum visible width, accounting for ANSI escape codes.
|
|
7
|
+
* Adds ellipsis (…) if truncated.
|
|
8
|
+
*/
|
|
9
|
+
export declare function clipText(str: string, maxWidth: number): string;
|
|
@@ -12,6 +12,7 @@ export declare class ProcessStore {
|
|
|
12
12
|
private selectedErrorIndex;
|
|
13
13
|
private expandedId;
|
|
14
14
|
private scrollOffset;
|
|
15
|
+
private listScrollOffset;
|
|
15
16
|
private header;
|
|
16
17
|
private showStatusBar;
|
|
17
18
|
private isInteractive;
|
|
@@ -31,6 +32,7 @@ export declare class ProcessStore {
|
|
|
31
32
|
getSelectedErrorIndex: () => number;
|
|
32
33
|
getExpandedId: () => string | null;
|
|
33
34
|
getScrollOffset: () => number;
|
|
35
|
+
getListScrollOffset: () => number;
|
|
34
36
|
getHeader: () => string | undefined;
|
|
35
37
|
getShowStatusBar: () => boolean;
|
|
36
38
|
getIsInteractive: () => boolean;
|
|
@@ -40,8 +42,9 @@ export declare class ProcessStore {
|
|
|
40
42
|
appendLines(id: string, newLines: Line[]): void;
|
|
41
43
|
getProcess(id: string): ChildProcess | undefined;
|
|
42
44
|
setMode(mode: Mode): void;
|
|
43
|
-
selectNext(): void;
|
|
44
|
-
selectPrev(): void;
|
|
45
|
+
selectNext(visibleCount?: number): void;
|
|
46
|
+
selectPrev(visibleCount?: number): void;
|
|
47
|
+
private adjustListScroll;
|
|
45
48
|
getSelectedProcess(): ChildProcess | undefined;
|
|
46
49
|
selectNextError(): void;
|
|
47
50
|
selectPrevError(): void;
|
|
@@ -85,6 +85,7 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
85
85
|
this.selectedErrorIndex = 0;
|
|
86
86
|
this.expandedId = null;
|
|
87
87
|
this.scrollOffset = 0;
|
|
88
|
+
this.listScrollOffset = 0; // Viewport offset for process list
|
|
88
89
|
this.showStatusBar = false;
|
|
89
90
|
this.isInteractive = false;
|
|
90
91
|
// useSyncExternalStore API
|
|
@@ -166,6 +167,9 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
166
167
|
this.getScrollOffset = function() {
|
|
167
168
|
return _this.scrollOffset;
|
|
168
169
|
};
|
|
170
|
+
this.getListScrollOffset = function() {
|
|
171
|
+
return _this.listScrollOffset;
|
|
172
|
+
};
|
|
169
173
|
// Session-level getters (set at session creation, immutable)
|
|
170
174
|
this.getHeader = function() {
|
|
171
175
|
return _this.header;
|
|
@@ -244,18 +248,31 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
244
248
|
this.notify();
|
|
245
249
|
};
|
|
246
250
|
// Interactive mode navigation
|
|
247
|
-
_proto.selectNext = function selectNext() {
|
|
251
|
+
_proto.selectNext = function selectNext(visibleCount) {
|
|
248
252
|
if (this.processes.length > 0) {
|
|
249
253
|
this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;
|
|
254
|
+
this.adjustListScroll(visibleCount);
|
|
250
255
|
this.notify();
|
|
251
256
|
}
|
|
252
257
|
};
|
|
253
|
-
_proto.selectPrev = function selectPrev() {
|
|
258
|
+
_proto.selectPrev = function selectPrev(visibleCount) {
|
|
254
259
|
if (this.processes.length > 0) {
|
|
255
260
|
this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;
|
|
261
|
+
this.adjustListScroll(visibleCount);
|
|
256
262
|
this.notify();
|
|
257
263
|
}
|
|
258
264
|
};
|
|
265
|
+
_proto.adjustListScroll = function adjustListScroll(visibleCount) {
|
|
266
|
+
if (!visibleCount || visibleCount <= 0) return;
|
|
267
|
+
// Ensure selected item is visible in viewport
|
|
268
|
+
if (this.selectedIndex < this.listScrollOffset) {
|
|
269
|
+
// Selected is above viewport - scroll up
|
|
270
|
+
this.listScrollOffset = this.selectedIndex;
|
|
271
|
+
} else if (this.selectedIndex >= this.listScrollOffset + visibleCount) {
|
|
272
|
+
// Selected is below viewport - scroll down
|
|
273
|
+
this.listScrollOffset = this.selectedIndex - visibleCount + 1;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
259
276
|
_proto.getSelectedProcess = function getSelectedProcess() {
|
|
260
277
|
return this.processes[this.selectedIndex];
|
|
261
278
|
};
|
|
@@ -330,6 +347,7 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
330
347
|
this.selectedErrorIndex = 0;
|
|
331
348
|
this.expandedId = null;
|
|
332
349
|
this.scrollOffset = 0;
|
|
350
|
+
this.listScrollOffset = 0;
|
|
333
351
|
this.header = undefined;
|
|
334
352
|
};
|
|
335
353
|
_proto.notify = function notify() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/processStore.ts"],"sourcesContent":["import { DEFAULT_COLUMN_WIDTH } from '../constants.ts';\nimport type { ChildProcess, Line, SessionOptions } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';\n\nexport class ProcessStore {\n private processes: ChildProcess[] = [];\n private completedIds: string[] = []; // Track completion order\n private listeners = new Set<Listener>();\n private shouldExit = false;\n private exitCallback: (() => void) | null = null;\n\n // UI state\n private mode: Mode = 'normal';\n private selectedIndex = 0;\n private selectedErrorIndex = 0;\n private expandedId: string | null = null;\n private scrollOffset = 0;\n\n // Session-level display settings (set once at session creation)\n private header: string | undefined;\n private showStatusBar = false;\n private isInteractive = false;\n\n constructor(options: SessionOptions = {}) {\n this.header = options.header;\n this.showStatusBar = options.showStatusBar ?? false;\n this.isInteractive = options.interactive ?? false;\n }\n\n // useSyncExternalStore API\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n getSnapshot = (): ChildProcess[] => this.processes;\n\n // Filtered getters\n getRunningProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'running');\n };\n\n getCompletedProcesses = (): ChildProcess[] => {\n // Return in completion order\n return this.completedIds.map((id) => this.processes.find((p) => p.id === id)).filter((p): p is ChildProcess => p !== undefined);\n };\n\n getFailedProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'error');\n };\n\n // Counts\n getRunningCount = (): number => this.processes.filter((p) => p.state === 'running').length;\n getMaxGroupLength = (): number => {\n if (this.processes.length === 0) return DEFAULT_COLUMN_WIDTH;\n return Math.max(...this.processes.map((p) => (p.group || p.title).length));\n };\n getDoneCount = (): number => this.processes.filter((p) => p.state !== 'running').length;\n getErrorCount = (): number => this.processes.filter((p) => p.state === 'error').length;\n getErrorLineCount = (): number => {\n return this.processes.filter((p) => p.state === 'error').reduce((total, p) => total + p.lines.filter((l) => l.type === LineType.stderr).length, 0);\n };\n\n // UI state getters\n getMode = (): Mode => this.mode;\n getSelectedIndex = (): number => this.selectedIndex;\n getSelectedErrorIndex = (): number => this.selectedErrorIndex;\n getExpandedId = (): string | null => this.expandedId;\n getScrollOffset = (): number => this.scrollOffset;\n // Session-level getters (set at session creation, immutable)\n getHeader = (): string | undefined => this.header;\n getShowStatusBar = (): boolean => this.showStatusBar;\n getIsInteractive = (): boolean => this.isInteractive;\n isAllComplete = (): boolean => this.processes.length > 0 && this.processes.every((p) => p.state !== 'running');\n\n // Mutations - Ink handles render throttling at 30 FPS\n addProcess(process: ChildProcess): void {\n this.processes = [...this.processes, process];\n this.notify();\n }\n\n updateProcess(id: string, update: Partial<ChildProcess>): void {\n const oldProcess = this.processes.find((p) => p.id === id);\n const wasRunning = oldProcess?.state === 'running';\n const isNowComplete = update.state && update.state !== 'running';\n\n this.processes = this.processes.map((p) => (p.id === id ? { ...p, ...update } : p));\n\n // Track completion order\n if (wasRunning && isNowComplete && !this.completedIds.includes(id)) {\n this.completedIds = [...this.completedIds, id];\n }\n\n this.notify();\n }\n\n appendLines(id: string, newLines: Line[]): void {\n const process = this.processes.find((p) => p.id === id);\n if (process) {\n this.updateProcess(id, { lines: process.lines.concat(newLines) });\n }\n }\n\n getProcess(id: string): ChildProcess | undefined {\n return this.processes.find((p) => p.id === id);\n }\n\n // UI state mutations\n setMode(mode: Mode): void {\n this.mode = mode;\n if (mode === 'interactive') {\n this.selectedIndex = 0;\n } else if (mode === 'errorList') {\n this.selectedErrorIndex = 0;\n }\n this.notify();\n }\n\n // Interactive mode navigation\n selectNext(): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;\n this.notify();\n }\n }\n\n selectPrev(): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;\n this.notify();\n }\n }\n\n getSelectedProcess(): ChildProcess | undefined {\n return this.processes[this.selectedIndex];\n }\n\n selectNextError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex + 1) % failed.length;\n this.notify();\n }\n }\n\n selectPrevError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex - 1 + failed.length) % failed.length;\n this.notify();\n }\n }\n\n getSelectedError(): ChildProcess | undefined {\n const failed = this.getFailedProcesses();\n return failed[this.selectedErrorIndex];\n }\n\n // Expansion methods\n toggleExpand(): void {\n const selected = this.getSelectedProcess();\n if (!selected) return;\n\n if (this.expandedId === selected.id) {\n // Collapse\n this.expandedId = null;\n this.scrollOffset = 0;\n } else {\n // Expand\n this.expandedId = selected.id;\n this.scrollOffset = 0;\n }\n this.notify();\n }\n\n collapse(): void {\n this.expandedId = null;\n this.scrollOffset = 0;\n this.notify();\n }\n\n scrollDown(maxVisible: number): void {\n if (!this.expandedId) return;\n const process = this.getProcess(this.expandedId);\n if (!process) return;\n\n const maxOffset = Math.max(0, process.lines.length - maxVisible);\n if (this.scrollOffset < maxOffset) {\n this.scrollOffset++;\n this.notify();\n }\n }\n\n scrollUp(): void {\n if (!this.expandedId) return;\n if (this.scrollOffset > 0) {\n this.scrollOffset--;\n this.notify();\n }\n }\n\n // Exit signaling\n signalExit(callback: () => void): void {\n this.shouldExit = true;\n this.exitCallback = callback;\n this.notify();\n }\n\n getShouldExit = (): boolean => this.shouldExit;\n getExitCallback = (): (() => void) | null => this.exitCallback;\n\n reset(): void {\n this.processes = [];\n this.completedIds = [];\n this.shouldExit = false;\n this.exitCallback = null;\n this.mode = 'normal';\n this.selectedIndex = 0;\n this.selectedErrorIndex = 0;\n this.expandedId = null;\n this.scrollOffset = 0;\n this.header = undefined;\n }\n\n private notify(): void {\n this.listeners.forEach((l) => {\n l();\n });\n }\n}\n\n// Note: No global singleton - session creates its own store instance\n"],"names":["ProcessStore","options","processes","completedIds","listeners","Set","shouldExit","exitCallback","mode","selectedIndex","selectedErrorIndex","expandedId","scrollOffset","showStatusBar","isInteractive","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","p","state","getCompletedProcesses","map","id","find","undefined","getFailedProcesses","getRunningCount","length","getMaxGroupLength","Math","DEFAULT_COLUMN_WIDTH","max","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","lines","l","type","LineType","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getHeader","header","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive","addProcess","process","notify","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","concat","getProcess","setMode","selectNext","selectPrev","getSelectedProcess","selectNextError","failed","selectPrevError","getSelectedError","toggleExpand","selected","collapse","scrollDown","maxVisible","maxOffset","scrollUp","signalExit","callback","reset","forEach"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/processStore.ts"],"sourcesContent":["import { DEFAULT_COLUMN_WIDTH } from '../constants.ts';\nimport type { ChildProcess, Line, SessionOptions } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';\n\nexport class ProcessStore {\n private processes: ChildProcess[] = [];\n private completedIds: string[] = []; // Track completion order\n private listeners = new Set<Listener>();\n private shouldExit = false;\n private exitCallback: (() => void) | null = null;\n\n // UI state\n private mode: Mode = 'normal';\n private selectedIndex = 0;\n private selectedErrorIndex = 0;\n private expandedId: string | null = null;\n private scrollOffset = 0;\n private listScrollOffset = 0; // Viewport offset for process list\n\n // Session-level display settings (set once at session creation)\n private header: string | undefined;\n private showStatusBar = false;\n private isInteractive = false;\n\n constructor(options: SessionOptions = {}) {\n this.header = options.header;\n this.showStatusBar = options.showStatusBar ?? false;\n this.isInteractive = options.interactive ?? false;\n }\n\n // useSyncExternalStore API\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n getSnapshot = (): ChildProcess[] => this.processes;\n\n // Filtered getters\n getRunningProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'running');\n };\n\n getCompletedProcesses = (): ChildProcess[] => {\n // Return in completion order\n return this.completedIds.map((id) => this.processes.find((p) => p.id === id)).filter((p): p is ChildProcess => p !== undefined);\n };\n\n getFailedProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'error');\n };\n\n // Counts\n getRunningCount = (): number => this.processes.filter((p) => p.state === 'running').length;\n getMaxGroupLength = (): number => {\n if (this.processes.length === 0) return DEFAULT_COLUMN_WIDTH;\n return Math.max(...this.processes.map((p) => (p.group || p.title).length));\n };\n getDoneCount = (): number => this.processes.filter((p) => p.state !== 'running').length;\n getErrorCount = (): number => this.processes.filter((p) => p.state === 'error').length;\n getErrorLineCount = (): number => {\n return this.processes.filter((p) => p.state === 'error').reduce((total, p) => total + p.lines.filter((l) => l.type === LineType.stderr).length, 0);\n };\n\n // UI state getters\n getMode = (): Mode => this.mode;\n getSelectedIndex = (): number => this.selectedIndex;\n getSelectedErrorIndex = (): number => this.selectedErrorIndex;\n getExpandedId = (): string | null => this.expandedId;\n getScrollOffset = (): number => this.scrollOffset;\n getListScrollOffset = (): number => this.listScrollOffset;\n // Session-level getters (set at session creation, immutable)\n getHeader = (): string | undefined => this.header;\n getShowStatusBar = (): boolean => this.showStatusBar;\n getIsInteractive = (): boolean => this.isInteractive;\n isAllComplete = (): boolean => this.processes.length > 0 && this.processes.every((p) => p.state !== 'running');\n\n // Mutations - Ink handles render throttling at 30 FPS\n addProcess(process: ChildProcess): void {\n this.processes = [...this.processes, process];\n this.notify();\n }\n\n updateProcess(id: string, update: Partial<ChildProcess>): void {\n const oldProcess = this.processes.find((p) => p.id === id);\n const wasRunning = oldProcess?.state === 'running';\n const isNowComplete = update.state && update.state !== 'running';\n\n this.processes = this.processes.map((p) => (p.id === id ? { ...p, ...update } : p));\n\n // Track completion order\n if (wasRunning && isNowComplete && !this.completedIds.includes(id)) {\n this.completedIds = [...this.completedIds, id];\n }\n\n this.notify();\n }\n\n appendLines(id: string, newLines: Line[]): void {\n const process = this.processes.find((p) => p.id === id);\n if (process) {\n this.updateProcess(id, { lines: process.lines.concat(newLines) });\n }\n }\n\n getProcess(id: string): ChildProcess | undefined {\n return this.processes.find((p) => p.id === id);\n }\n\n // UI state mutations\n setMode(mode: Mode): void {\n this.mode = mode;\n if (mode === 'interactive') {\n this.selectedIndex = 0;\n } else if (mode === 'errorList') {\n this.selectedErrorIndex = 0;\n }\n this.notify();\n }\n\n // Interactive mode navigation\n selectNext(visibleCount?: number): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;\n this.adjustListScroll(visibleCount);\n this.notify();\n }\n }\n\n selectPrev(visibleCount?: number): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;\n this.adjustListScroll(visibleCount);\n this.notify();\n }\n }\n\n private adjustListScroll(visibleCount?: number): void {\n if (!visibleCount || visibleCount <= 0) return;\n\n // Ensure selected item is visible in viewport\n if (this.selectedIndex < this.listScrollOffset) {\n // Selected is above viewport - scroll up\n this.listScrollOffset = this.selectedIndex;\n } else if (this.selectedIndex >= this.listScrollOffset + visibleCount) {\n // Selected is below viewport - scroll down\n this.listScrollOffset = this.selectedIndex - visibleCount + 1;\n }\n }\n\n getSelectedProcess(): ChildProcess | undefined {\n return this.processes[this.selectedIndex];\n }\n\n selectNextError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex + 1) % failed.length;\n this.notify();\n }\n }\n\n selectPrevError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex - 1 + failed.length) % failed.length;\n this.notify();\n }\n }\n\n getSelectedError(): ChildProcess | undefined {\n const failed = this.getFailedProcesses();\n return failed[this.selectedErrorIndex];\n }\n\n // Expansion methods\n toggleExpand(): void {\n const selected = this.getSelectedProcess();\n if (!selected) return;\n\n if (this.expandedId === selected.id) {\n // Collapse\n this.expandedId = null;\n this.scrollOffset = 0;\n } else {\n // Expand\n this.expandedId = selected.id;\n this.scrollOffset = 0;\n }\n this.notify();\n }\n\n collapse(): void {\n this.expandedId = null;\n this.scrollOffset = 0;\n this.notify();\n }\n\n scrollDown(maxVisible: number): void {\n if (!this.expandedId) return;\n const process = this.getProcess(this.expandedId);\n if (!process) return;\n\n const maxOffset = Math.max(0, process.lines.length - maxVisible);\n if (this.scrollOffset < maxOffset) {\n this.scrollOffset++;\n this.notify();\n }\n }\n\n scrollUp(): void {\n if (!this.expandedId) return;\n if (this.scrollOffset > 0) {\n this.scrollOffset--;\n this.notify();\n }\n }\n\n // Exit signaling\n signalExit(callback: () => void): void {\n this.shouldExit = true;\n this.exitCallback = callback;\n this.notify();\n }\n\n getShouldExit = (): boolean => this.shouldExit;\n getExitCallback = (): (() => void) | null => this.exitCallback;\n\n reset(): void {\n this.processes = [];\n this.completedIds = [];\n this.shouldExit = false;\n this.exitCallback = null;\n this.mode = 'normal';\n this.selectedIndex = 0;\n this.selectedErrorIndex = 0;\n this.expandedId = null;\n this.scrollOffset = 0;\n this.listScrollOffset = 0;\n this.header = undefined;\n }\n\n private notify(): void {\n this.listeners.forEach((l) => {\n l();\n });\n }\n}\n\n// Note: No global singleton - session creates its own store instance\n"],"names":["ProcessStore","options","processes","completedIds","listeners","Set","shouldExit","exitCallback","mode","selectedIndex","selectedErrorIndex","expandedId","scrollOffset","listScrollOffset","showStatusBar","isInteractive","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","p","state","getCompletedProcesses","map","id","find","undefined","getFailedProcesses","getRunningCount","length","getMaxGroupLength","Math","DEFAULT_COLUMN_WIDTH","max","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","lines","l","type","LineType","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getListScrollOffset","getHeader","header","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive","addProcess","process","notify","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","concat","getProcess","setMode","selectNext","visibleCount","adjustListScroll","selectPrev","getSelectedProcess","selectNextError","failed","selectPrevError","getSelectedError","toggleExpand","selected","collapse","scrollDown","maxVisible","maxOffset","scrollUp","signalExit","callback","reset","forEach"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text, useApp, useInput, useStdin } from 'ink';
|
|
3
|
-
import { useEffect, useSyncExternalStore } from 'react';
|
|
2
|
+
import { Box, Text, useApp, useInput, useStdin, useStdout } from 'ink';
|
|
3
|
+
import { useEffect, useMemo, useSyncExternalStore } from 'react';
|
|
4
4
|
import { EXPANDED_MAX_VISIBLE_LINES } from '../constants.js';
|
|
5
5
|
import { StoreContext } from '../state/StoreContext.js';
|
|
6
6
|
import CompactProcessLine from './CompactProcessLine.js';
|
|
@@ -12,6 +12,8 @@ import StatusBar from './StatusBar.js';
|
|
|
12
12
|
function AppContent({ store }) {
|
|
13
13
|
const { exit } = useApp();
|
|
14
14
|
const { isRawModeSupported } = useStdin();
|
|
15
|
+
const { stdout } = useStdout();
|
|
16
|
+
const terminalHeight = (stdout === null || stdout === void 0 ? void 0 : stdout.rows) || 24;
|
|
15
17
|
// Subscribe to store state
|
|
16
18
|
const processes = useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
17
19
|
const shouldExit = useSyncExternalStore(store.subscribe, store.getShouldExit);
|
|
@@ -20,10 +22,14 @@ function AppContent({ store }) {
|
|
|
20
22
|
const selectedErrorIndex = useSyncExternalStore(store.subscribe, store.getSelectedErrorIndex);
|
|
21
23
|
const expandedId = useSyncExternalStore(store.subscribe, store.getExpandedId);
|
|
22
24
|
const scrollOffset = useSyncExternalStore(store.subscribe, store.getScrollOffset);
|
|
25
|
+
const listScrollOffset = useSyncExternalStore(store.subscribe, store.getListScrollOffset);
|
|
23
26
|
// Subscribed state that triggers re-renders
|
|
24
27
|
const header = useSyncExternalStore(store.subscribe, store.getHeader);
|
|
25
28
|
const showStatusBar = useSyncExternalStore(store.subscribe, store.getShowStatusBar);
|
|
26
29
|
const isInteractive = useSyncExternalStore(store.subscribe, store.getIsInteractive);
|
|
30
|
+
// Calculate visible process count (reserve lines for header, divider, status bar)
|
|
31
|
+
const reservedLines = (header ? 2 : 0) + (showStatusBar ? 2 : 0);
|
|
32
|
+
const visibleProcessCount = Math.max(1, terminalHeight - reservedLines);
|
|
27
33
|
// Derived state (computed from processes which is already subscribed)
|
|
28
34
|
const failedProcesses = store.getFailedProcesses();
|
|
29
35
|
const runningCount = store.getRunningCount();
|
|
@@ -70,25 +76,25 @@ function AppContent({ store }) {
|
|
|
70
76
|
if (expandedId) {
|
|
71
77
|
store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);
|
|
72
78
|
} else {
|
|
73
|
-
store.selectNext();
|
|
79
|
+
store.selectNext(visibleProcessCount);
|
|
74
80
|
}
|
|
75
81
|
} else if (key.upArrow) {
|
|
76
82
|
if (expandedId) {
|
|
77
83
|
store.scrollUp();
|
|
78
84
|
} else {
|
|
79
|
-
store.selectPrev();
|
|
85
|
+
store.selectPrev(visibleProcessCount);
|
|
80
86
|
}
|
|
81
87
|
} else if (input === 'j') {
|
|
82
88
|
if (expandedId) {
|
|
83
89
|
store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);
|
|
84
90
|
} else {
|
|
85
|
-
store.selectNext();
|
|
91
|
+
store.selectNext(visibleProcessCount);
|
|
86
92
|
}
|
|
87
93
|
} else if (input === 'k') {
|
|
88
94
|
if (expandedId) {
|
|
89
95
|
store.scrollUp();
|
|
90
96
|
} else {
|
|
91
|
-
store.selectPrev();
|
|
97
|
+
store.selectPrev(visibleProcessCount);
|
|
92
98
|
}
|
|
93
99
|
} else if (input === 'e' && errorCount > 0) {
|
|
94
100
|
store.setMode('errorList');
|
|
@@ -115,6 +121,18 @@ function AppContent({ store }) {
|
|
|
115
121
|
}, {
|
|
116
122
|
isActive: isRawModeSupported === true
|
|
117
123
|
});
|
|
124
|
+
// Slice processes to visible viewport in interactive mode (must be before early returns)
|
|
125
|
+
const visibleProcesses = useMemo(()=>{
|
|
126
|
+
if (mode === 'interactive') {
|
|
127
|
+
return processes.slice(listScrollOffset, listScrollOffset + visibleProcessCount);
|
|
128
|
+
}
|
|
129
|
+
return processes;
|
|
130
|
+
}, [
|
|
131
|
+
processes,
|
|
132
|
+
mode,
|
|
133
|
+
listScrollOffset,
|
|
134
|
+
visibleProcessCount
|
|
135
|
+
]);
|
|
118
136
|
// Error list modal
|
|
119
137
|
if (mode === 'errorList') {
|
|
120
138
|
return /*#__PURE__*/ _jsx(ErrorListModal, {
|
|
@@ -149,19 +167,22 @@ function AppContent({ store }) {
|
|
|
149
167
|
/*#__PURE__*/ _jsx(Divider, {})
|
|
150
168
|
]
|
|
151
169
|
}),
|
|
152
|
-
|
|
170
|
+
visibleProcesses.map((item)=>{
|
|
171
|
+
const originalIndex = processes.indexOf(item);
|
|
172
|
+
return /*#__PURE__*/ _jsxs(Box, {
|
|
153
173
|
flexDirection: "column",
|
|
154
174
|
children: [
|
|
155
175
|
/*#__PURE__*/ _jsx(CompactProcessLine, {
|
|
156
176
|
item: item,
|
|
157
|
-
isSelected: showSelection &&
|
|
177
|
+
isSelected: showSelection && originalIndex === selectedIndex
|
|
158
178
|
}),
|
|
159
179
|
expandedId === item.id && /*#__PURE__*/ _jsx(ExpandedOutput, {
|
|
160
180
|
lines: item.lines,
|
|
161
181
|
scrollOffset: scrollOffset
|
|
162
182
|
})
|
|
163
183
|
]
|
|
164
|
-
}, item.id)
|
|
184
|
+
}, item.id);
|
|
185
|
+
}),
|
|
165
186
|
showStatusBar && processes.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
166
187
|
children: [
|
|
167
188
|
/*#__PURE__*/ _jsx(Divider, {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/App.tsx"],"sourcesContent":["import { Box, Text, useApp, useInput, useStdin } from 'ink';\nimport { useEffect, useSyncExternalStore } from 'react';\nimport { EXPANDED_MAX_VISIBLE_LINES } from '../constants.ts';\nimport type { ProcessStore } from '../state/processStore.ts';\nimport { StoreContext } from '../state/StoreContext.ts';\nimport CompactProcessLine from './CompactProcessLine.ts';\nimport Divider from './Divider.ts';\nimport ErrorDetailModal from './ErrorDetailModal.ts';\nimport ErrorListModal from './ErrorListModal.ts';\nimport ExpandedOutput from './ExpandedOutput.ts';\nimport StatusBar from './StatusBar.ts';\n\ninterface AppProps {\n store: ProcessStore;\n}\n\nfunction AppContent({ store }: AppProps): React.JSX.Element {\n const { exit } = useApp();\n const { isRawModeSupported } = useStdin();\n\n // Subscribe to store state\n const processes = useSyncExternalStore(store.subscribe, store.getSnapshot);\n const shouldExit = useSyncExternalStore(store.subscribe, store.getShouldExit);\n const mode = useSyncExternalStore(store.subscribe, store.getMode);\n const selectedIndex = useSyncExternalStore(store.subscribe, store.getSelectedIndex);\n const selectedErrorIndex = useSyncExternalStore(store.subscribe, store.getSelectedErrorIndex);\n const expandedId = useSyncExternalStore(store.subscribe, store.getExpandedId);\n const scrollOffset = useSyncExternalStore(store.subscribe, store.getScrollOffset);\n\n // Subscribed state that triggers re-renders\n const header = useSyncExternalStore(store.subscribe, store.getHeader);\n const showStatusBar = useSyncExternalStore(store.subscribe, store.getShowStatusBar);\n const isInteractive = useSyncExternalStore(store.subscribe, store.getIsInteractive);\n\n // Derived state (computed from processes which is already subscribed)\n const failedProcesses = store.getFailedProcesses();\n const runningCount = store.getRunningCount();\n const doneCount = store.getDoneCount();\n const errorCount = store.getErrorCount();\n const errorLineCount = store.getErrorLineCount();\n const isAllComplete = store.isAllComplete();\n\n // Handle exit signal\n useEffect(() => {\n if (shouldExit) {\n exit();\n }\n }, [shouldExit, exit]);\n\n // Auto-enter interactive mode when all complete and interactive flag is set\n useEffect(() => {\n if (isAllComplete && isInteractive && mode === 'normal') {\n store.setMode('interactive');\n }\n }, [isAllComplete, isInteractive, mode, store]);\n\n // Keyboard handling (only active when raw mode is supported)\n useInput(\n (input, key) => {\n if (mode === 'normal') {\n if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'interactive') {\n if (input === 'q' || key.escape) {\n if (expandedId) {\n store.collapse();\n } else {\n store.signalExit(() => {});\n }\n } else if (key.return) {\n store.toggleExpand();\n } else if (key.downArrow) {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext();\n }\n } else if (key.upArrow) {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev();\n }\n } else if (input === 'j') {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext();\n }\n } else if (input === 'k') {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev();\n }\n } else if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'errorList') {\n if (key.escape) {\n store.setMode(isInteractive ? 'interactive' : 'normal');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n } else if (key.return) {\n store.setMode('errorDetail');\n }\n } else if (mode === 'errorDetail') {\n if (key.escape) {\n store.setMode('errorList');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n }\n }\n },\n { isActive: isRawModeSupported === true }\n );\n\n // Error list modal\n if (mode === 'errorList') {\n return <ErrorListModal errors={failedProcesses} selectedIndex={selectedErrorIndex} totalErrorLines={errorLineCount} />;\n }\n\n // Error detail modal\n if (mode === 'errorDetail') {\n const selectedError = store.getSelectedError();\n if (selectedError) {\n return <ErrorDetailModal error={selectedError} currentIndex={selectedErrorIndex} totalErrors={failedProcesses.length} />;\n }\n // Fallback if no error selected\n store.setMode('errorList');\n }\n\n // Normal/Interactive view - render in original registration order\n const showSelection = mode === 'interactive';\n return (\n <Box flexDirection=\"column\">\n {/* Header */}\n {header && (\n <>\n <Text>{header}</Text>\n <Divider />\n </>\n )}\n\n {/* All processes in registration order */}\n {processes.map((item, index) => (\n <Box key={item.id} flexDirection=\"column\">\n <CompactProcessLine item={item} isSelected={showSelection && index === selectedIndex} />\n {expandedId === item.id && <ExpandedOutput lines={item.lines} scrollOffset={scrollOffset} />}\n </Box>\n ))}\n\n {/* Status bar */}\n {showStatusBar && processes.length > 0 && (\n <>\n <Divider />\n <StatusBar running={runningCount} done={doneCount} errors={errorCount} errorLines={errorLineCount} />\n </>\n )}\n </Box>\n );\n}\n\n// Wrapper component that provides store context\nexport default function App({ store }: AppProps): React.JSX.Element {\n return (\n <StoreContext.Provider value={store}>\n <AppContent store={store} />\n </StoreContext.Provider>\n );\n}\n"],"names":["Box","Text","useApp","useInput","useStdin","useEffect","useSyncExternalStore","EXPANDED_MAX_VISIBLE_LINES","StoreContext","CompactProcessLine","Divider","ErrorDetailModal","ErrorListModal","ExpandedOutput","StatusBar","AppContent","store","exit","isRawModeSupported","processes","subscribe","getSnapshot","shouldExit","getShouldExit","mode","getMode","selectedIndex","getSelectedIndex","selectedErrorIndex","getSelectedErrorIndex","expandedId","getExpandedId","scrollOffset","getScrollOffset","header","getHeader","showStatusBar","getShowStatusBar","isInteractive","getIsInteractive","failedProcesses","getFailedProcesses","runningCount","getRunningCount","doneCount","getDoneCount","errorCount","getErrorCount","errorLineCount","getErrorLineCount","isAllComplete","setMode","input","key","escape","collapse","signalExit","return","toggleExpand","downArrow","scrollDown","selectNext","upArrow","scrollUp","selectPrev","selectNextError","selectPrevError","isActive","errors","totalErrorLines","selectedError","getSelectedError","error","currentIndex","totalErrors","length","showSelection","flexDirection","map","item","index","isSelected","id","lines","running","done","errorLines","App","Provider","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/App.tsx"],"sourcesContent":["import { Box, Text, useApp, useInput, useStdin, useStdout } from 'ink';\nimport { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { EXPANDED_MAX_VISIBLE_LINES } from '../constants.ts';\nimport type { ProcessStore } from '../state/processStore.ts';\nimport { StoreContext } from '../state/StoreContext.ts';\nimport CompactProcessLine from './CompactProcessLine.ts';\nimport Divider from './Divider.ts';\nimport ErrorDetailModal from './ErrorDetailModal.ts';\nimport ErrorListModal from './ErrorListModal.ts';\nimport ExpandedOutput from './ExpandedOutput.ts';\nimport StatusBar from './StatusBar.ts';\n\ninterface AppProps {\n store: ProcessStore;\n}\n\nfunction AppContent({ store }: AppProps): React.JSX.Element {\n const { exit } = useApp();\n const { isRawModeSupported } = useStdin();\n const { stdout } = useStdout();\n const terminalHeight = stdout?.rows || 24;\n\n // Subscribe to store state\n const processes = useSyncExternalStore(store.subscribe, store.getSnapshot);\n const shouldExit = useSyncExternalStore(store.subscribe, store.getShouldExit);\n const mode = useSyncExternalStore(store.subscribe, store.getMode);\n const selectedIndex = useSyncExternalStore(store.subscribe, store.getSelectedIndex);\n const selectedErrorIndex = useSyncExternalStore(store.subscribe, store.getSelectedErrorIndex);\n const expandedId = useSyncExternalStore(store.subscribe, store.getExpandedId);\n const scrollOffset = useSyncExternalStore(store.subscribe, store.getScrollOffset);\n const listScrollOffset = useSyncExternalStore(store.subscribe, store.getListScrollOffset);\n\n // Subscribed state that triggers re-renders\n const header = useSyncExternalStore(store.subscribe, store.getHeader);\n const showStatusBar = useSyncExternalStore(store.subscribe, store.getShowStatusBar);\n const isInteractive = useSyncExternalStore(store.subscribe, store.getIsInteractive);\n\n // Calculate visible process count (reserve lines for header, divider, status bar)\n const reservedLines = (header ? 2 : 0) + (showStatusBar ? 2 : 0);\n const visibleProcessCount = Math.max(1, terminalHeight - reservedLines);\n\n // Derived state (computed from processes which is already subscribed)\n const failedProcesses = store.getFailedProcesses();\n const runningCount = store.getRunningCount();\n const doneCount = store.getDoneCount();\n const errorCount = store.getErrorCount();\n const errorLineCount = store.getErrorLineCount();\n const isAllComplete = store.isAllComplete();\n\n // Handle exit signal\n useEffect(() => {\n if (shouldExit) {\n exit();\n }\n }, [shouldExit, exit]);\n\n // Auto-enter interactive mode when all complete and interactive flag is set\n useEffect(() => {\n if (isAllComplete && isInteractive && mode === 'normal') {\n store.setMode('interactive');\n }\n }, [isAllComplete, isInteractive, mode, store]);\n\n // Keyboard handling (only active when raw mode is supported)\n useInput(\n (input, key) => {\n if (mode === 'normal') {\n if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'interactive') {\n if (input === 'q' || key.escape) {\n if (expandedId) {\n store.collapse();\n } else {\n store.signalExit(() => {});\n }\n } else if (key.return) {\n store.toggleExpand();\n } else if (key.downArrow) {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext(visibleProcessCount);\n }\n } else if (key.upArrow) {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev(visibleProcessCount);\n }\n } else if (input === 'j') {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext(visibleProcessCount);\n }\n } else if (input === 'k') {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev(visibleProcessCount);\n }\n } else if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'errorList') {\n if (key.escape) {\n store.setMode(isInteractive ? 'interactive' : 'normal');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n } else if (key.return) {\n store.setMode('errorDetail');\n }\n } else if (mode === 'errorDetail') {\n if (key.escape) {\n store.setMode('errorList');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n }\n }\n },\n { isActive: isRawModeSupported === true }\n );\n\n // Slice processes to visible viewport in interactive mode (must be before early returns)\n const visibleProcesses = useMemo(() => {\n if (mode === 'interactive') {\n return processes.slice(listScrollOffset, listScrollOffset + visibleProcessCount);\n }\n return processes;\n }, [processes, mode, listScrollOffset, visibleProcessCount]);\n\n // Error list modal\n if (mode === 'errorList') {\n return <ErrorListModal errors={failedProcesses} selectedIndex={selectedErrorIndex} totalErrorLines={errorLineCount} />;\n }\n\n // Error detail modal\n if (mode === 'errorDetail') {\n const selectedError = store.getSelectedError();\n if (selectedError) {\n return <ErrorDetailModal error={selectedError} currentIndex={selectedErrorIndex} totalErrors={failedProcesses.length} />;\n }\n // Fallback if no error selected\n store.setMode('errorList');\n }\n\n // Normal/Interactive view - render in original registration order\n const showSelection = mode === 'interactive';\n\n return (\n <Box flexDirection=\"column\">\n {/* Header */}\n {header && (\n <>\n <Text>{header}</Text>\n <Divider />\n </>\n )}\n\n {/* Visible processes */}\n {visibleProcesses.map((item) => {\n const originalIndex = processes.indexOf(item);\n return (\n <Box key={item.id} flexDirection=\"column\">\n <CompactProcessLine item={item} isSelected={showSelection && originalIndex === selectedIndex} />\n {expandedId === item.id && <ExpandedOutput lines={item.lines} scrollOffset={scrollOffset} />}\n </Box>\n );\n })}\n\n {/* Status bar */}\n {showStatusBar && processes.length > 0 && (\n <>\n <Divider />\n <StatusBar running={runningCount} done={doneCount} errors={errorCount} errorLines={errorLineCount} />\n </>\n )}\n </Box>\n );\n}\n\n// Wrapper component that provides store context\nexport default function App({ store }: AppProps): React.JSX.Element {\n return (\n <StoreContext.Provider value={store}>\n <AppContent store={store} />\n </StoreContext.Provider>\n );\n}\n"],"names":["Box","Text","useApp","useInput","useStdin","useStdout","useEffect","useMemo","useSyncExternalStore","EXPANDED_MAX_VISIBLE_LINES","StoreContext","CompactProcessLine","Divider","ErrorDetailModal","ErrorListModal","ExpandedOutput","StatusBar","AppContent","store","exit","isRawModeSupported","stdout","terminalHeight","rows","processes","subscribe","getSnapshot","shouldExit","getShouldExit","mode","getMode","selectedIndex","getSelectedIndex","selectedErrorIndex","getSelectedErrorIndex","expandedId","getExpandedId","scrollOffset","getScrollOffset","listScrollOffset","getListScrollOffset","header","getHeader","showStatusBar","getShowStatusBar","isInteractive","getIsInteractive","reservedLines","visibleProcessCount","Math","max","failedProcesses","getFailedProcesses","runningCount","getRunningCount","doneCount","getDoneCount","errorCount","getErrorCount","errorLineCount","getErrorLineCount","isAllComplete","setMode","input","key","escape","collapse","signalExit","return","toggleExpand","downArrow","scrollDown","selectNext","upArrow","scrollUp","selectPrev","selectNextError","selectPrevError","isActive","visibleProcesses","slice","errors","totalErrorLines","selectedError","getSelectedError","error","currentIndex","totalErrors","length","showSelection","flexDirection","map","item","originalIndex","indexOf","isSelected","id","lines","running","done","errorLines","App","Provider","value"],"mappings":";AAAA,SAASA,GAAG,EAAEC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,SAAS,QAAQ,MAAM;AACvE,SAASC,SAAS,EAAEC,OAAO,EAAEC,oBAAoB,QAAQ,QAAQ;AACjE,SAASC,0BAA0B,QAAQ,kBAAkB;AAE7D,SAASC,YAAY,QAAQ,2BAA2B;AACxD,OAAOC,wBAAwB,0BAA0B;AACzD,OAAOC,aAAa,eAAe;AACnC,OAAOC,sBAAsB,wBAAwB;AACrD,OAAOC,oBAAoB,sBAAsB;AACjD,OAAOC,oBAAoB,sBAAsB;AACjD,OAAOC,eAAe,iBAAiB;AAMvC,SAASC,WAAW,EAAEC,KAAK,EAAY;IACrC,MAAM,EAAEC,IAAI,EAAE,GAAGjB;IACjB,MAAM,EAAEkB,kBAAkB,EAAE,GAAGhB;IAC/B,MAAM,EAAEiB,MAAM,EAAE,GAAGhB;IACnB,MAAMiB,iBAAiBD,CAAAA,mBAAAA,6BAAAA,OAAQE,IAAI,KAAI;IAEvC,2BAA2B;IAC3B,MAAMC,YAAYhB,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMQ,WAAW;IACzE,MAAMC,aAAanB,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMU,aAAa;IAC5E,MAAMC,OAAOrB,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMY,OAAO;IAChE,MAAMC,gBAAgBvB,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMc,gBAAgB;IAClF,MAAMC,qBAAqBzB,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMgB,qBAAqB;IAC5F,MAAMC,aAAa3B,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMkB,aAAa;IAC5E,MAAMC,eAAe7B,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMoB,eAAe;IAChF,MAAMC,mBAAmB/B,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMsB,mBAAmB;IAExF,4CAA4C;IAC5C,MAAMC,SAASjC,qBAAqBU,MAAMO,SAAS,EAAEP,MAAMwB,SAAS;IACpE,MAAMC,gBAAgBnC,qBAAqBU,MAAMO,SAAS,EAAEP,MAAM0B,gBAAgB;IAClF,MAAMC,gBAAgBrC,qBAAqBU,MAAMO,SAAS,EAAEP,MAAM4B,gBAAgB;IAElF,kFAAkF;IAClF,MAAMC,gBAAgB,AAACN,CAAAA,SAAS,IAAI,CAAA,IAAME,CAAAA,gBAAgB,IAAI,CAAA;IAC9D,MAAMK,sBAAsBC,KAAKC,GAAG,CAAC,GAAG5B,iBAAiByB;IAEzD,sEAAsE;IACtE,MAAMI,kBAAkBjC,MAAMkC,kBAAkB;IAChD,MAAMC,eAAenC,MAAMoC,eAAe;IAC1C,MAAMC,YAAYrC,MAAMsC,YAAY;IACpC,MAAMC,aAAavC,MAAMwC,aAAa;IACtC,MAAMC,iBAAiBzC,MAAM0C,iBAAiB;IAC9C,MAAMC,gBAAgB3C,MAAM2C,aAAa;IAEzC,qBAAqB;IACrBvD,UAAU;QACR,IAAIqB,YAAY;YACdR;QACF;IACF,GAAG;QAACQ;QAAYR;KAAK;IAErB,4EAA4E;IAC5Eb,UAAU;QACR,IAAIuD,iBAAiBhB,iBAAiBhB,SAAS,UAAU;YACvDX,MAAM4C,OAAO,CAAC;QAChB;IACF,GAAG;QAACD;QAAehB;QAAehB;QAAMX;KAAM;IAE9C,6DAA6D;IAC7Df,SACE,CAAC4D,OAAOC;QACN,IAAInC,SAAS,UAAU;YACrB,IAAIkC,UAAU,OAAON,aAAa,GAAG;gBACnCvC,MAAM4C,OAAO,CAAC;YAChB;QACF,OAAO,IAAIjC,SAAS,eAAe;YACjC,IAAIkC,UAAU,OAAOC,IAAIC,MAAM,EAAE;gBAC/B,IAAI9B,YAAY;oBACdjB,MAAMgD,QAAQ;gBAChB,OAAO;oBACLhD,MAAMiD,UAAU,CAAC,KAAO;gBAC1B;YACF,OAAO,IAAIH,IAAII,MAAM,EAAE;gBACrBlD,MAAMmD,YAAY;YACpB,OAAO,IAAIL,IAAIM,SAAS,EAAE;gBACxB,IAAInC,YAAY;oBACdjB,MAAMqD,UAAU,CAAC9D;gBACnB,OAAO;oBACLS,MAAMsD,UAAU,CAACxB;gBACnB;YACF,OAAO,IAAIgB,IAAIS,OAAO,EAAE;gBACtB,IAAItC,YAAY;oBACdjB,MAAMwD,QAAQ;gBAChB,OAAO;oBACLxD,MAAMyD,UAAU,CAAC3B;gBACnB;YACF,OAAO,IAAIe,UAAU,KAAK;gBACxB,IAAI5B,YAAY;oBACdjB,MAAMqD,UAAU,CAAC9D;gBACnB,OAAO;oBACLS,MAAMsD,UAAU,CAACxB;gBACnB;YACF,OAAO,IAAIe,UAAU,KAAK;gBACxB,IAAI5B,YAAY;oBACdjB,MAAMwD,QAAQ;gBAChB,OAAO;oBACLxD,MAAMyD,UAAU,CAAC3B;gBACnB;YACF,OAAO,IAAIe,UAAU,OAAON,aAAa,GAAG;gBAC1CvC,MAAM4C,OAAO,CAAC;YAChB;QACF,OAAO,IAAIjC,SAAS,aAAa;YAC/B,IAAImC,IAAIC,MAAM,EAAE;gBACd/C,MAAM4C,OAAO,CAACjB,gBAAgB,gBAAgB;YAChD,OAAO,IAAImB,IAAIM,SAAS,EAAE;gBACxBpD,MAAM0D,eAAe;YACvB,OAAO,IAAIZ,IAAIS,OAAO,EAAE;gBACtBvD,MAAM2D,eAAe;YACvB,OAAO,IAAIb,IAAII,MAAM,EAAE;gBACrBlD,MAAM4C,OAAO,CAAC;YAChB;QACF,OAAO,IAAIjC,SAAS,eAAe;YACjC,IAAImC,IAAIC,MAAM,EAAE;gBACd/C,MAAM4C,OAAO,CAAC;YAChB,OAAO,IAAIE,IAAIM,SAAS,EAAE;gBACxBpD,MAAM0D,eAAe;YACvB,OAAO,IAAIZ,IAAIS,OAAO,EAAE;gBACtBvD,MAAM2D,eAAe;YACvB;QACF;IACF,GACA;QAAEC,UAAU1D,uBAAuB;IAAK;IAG1C,yFAAyF;IACzF,MAAM2D,mBAAmBxE,QAAQ;QAC/B,IAAIsB,SAAS,eAAe;YAC1B,OAAOL,UAAUwD,KAAK,CAACzC,kBAAkBA,mBAAmBS;QAC9D;QACA,OAAOxB;IACT,GAAG;QAACA;QAAWK;QAAMU;QAAkBS;KAAoB;IAE3D,mBAAmB;IACnB,IAAInB,SAAS,aAAa;QACxB,qBAAO,KAACf;YAAemE,QAAQ9B;YAAiBpB,eAAeE;YAAoBiD,iBAAiBvB;;IACtG;IAEA,qBAAqB;IACrB,IAAI9B,SAAS,eAAe;QAC1B,MAAMsD,gBAAgBjE,MAAMkE,gBAAgB;QAC5C,IAAID,eAAe;YACjB,qBAAO,KAACtE;gBAAiBwE,OAAOF;gBAAeG,cAAcrD;gBAAoBsD,aAAapC,gBAAgBqC,MAAM;;QACtH;QACA,gCAAgC;QAChCtE,MAAM4C,OAAO,CAAC;IAChB;IAEA,kEAAkE;IAClE,MAAM2B,gBAAgB5D,SAAS;IAE/B,qBACE,MAAC7B;QAAI0F,eAAc;;YAEhBjD,wBACC;;kCACE,KAACxC;kCAAMwC;;kCACP,KAAC7B;;;YAKJmE,iBAAiBY,GAAG,CAAC,CAACC;gBACrB,MAAMC,gBAAgBrE,UAAUsE,OAAO,CAACF;gBACxC,qBACE,MAAC5F;oBAAkB0F,eAAc;;sCAC/B,KAAC/E;4BAAmBiF,MAAMA;4BAAMG,YAAYN,iBAAiBI,kBAAkB9D;;wBAC9EI,eAAeyD,KAAKI,EAAE,kBAAI,KAACjF;4BAAekF,OAAOL,KAAKK,KAAK;4BAAE5D,cAAcA;;;mBAFpEuD,KAAKI,EAAE;YAKrB;YAGCrD,iBAAiBnB,UAAUgE,MAAM,GAAG,mBACnC;;kCACE,KAAC5E;kCACD,KAACI;wBAAUkF,SAAS7C;wBAAc8C,MAAM5C;wBAAW0B,QAAQxB;wBAAY2C,YAAYzC;;;;;;AAK7F;AAEA,gDAAgD;AAChD,eAAe,SAAS0C,IAAI,EAAEnF,KAAK,EAAY;IAC7C,qBACE,KAACR,aAAa4F,QAAQ;QAACC,OAAOrF;kBAC5B,cAAA,KAACD;YAAWC,OAAOA;;;AAGzB"}
|
|
@@ -29,6 +29,7 @@ function _object_spread(target) {
|
|
|
29
29
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
30
30
|
import { Box, Text } from 'ink';
|
|
31
31
|
import { memo, useMemo } from 'react';
|
|
32
|
+
import { SPINNER } from '../constants.js';
|
|
32
33
|
import ansiRegex from '../lib/ansiRegex.js';
|
|
33
34
|
import figures from '../lib/figures.js';
|
|
34
35
|
import { LineType } from '../types.js';
|
|
@@ -38,22 +39,6 @@ const BLANK_LINE = {
|
|
|
38
39
|
type: LineType.stdout,
|
|
39
40
|
text: ''
|
|
40
41
|
};
|
|
41
|
-
// From: https://github.com/sindresorhus/cli-spinners/blob/00de8fbeee16fa49502fa4f687449f70f2c8ca2c/spinners.json#L2
|
|
42
|
-
const SPINNER = {
|
|
43
|
-
interval: 80,
|
|
44
|
-
frames: [
|
|
45
|
-
'⠋',
|
|
46
|
-
'⠙',
|
|
47
|
-
'⠹',
|
|
48
|
-
'⠸',
|
|
49
|
-
'⠼',
|
|
50
|
-
'⠴',
|
|
51
|
-
'⠦',
|
|
52
|
-
'⠧',
|
|
53
|
-
'⠇',
|
|
54
|
-
'⠏'
|
|
55
|
-
]
|
|
56
|
-
};
|
|
57
42
|
const ICONS = {
|
|
58
43
|
error: /*#__PURE__*/ _jsx(Text, {
|
|
59
44
|
color: "red",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/ChildProcess.tsx"],"sourcesContent":["import { Box, Text } from 'ink';\nimport { memo, useMemo } from 'react';\nimport ansiRegex from '../lib/ansiRegex.ts';\nimport figures from '../lib/figures.ts';\nimport type { ChildProcess as ChildProcessT, Line, State } from '../types.ts';\nimport { LineType } from '../types.ts';\nimport Spinner from './Spinner.ts';\n\nconst REGEX_ANSI = ansiRegex();\nconst BLANK_LINE = { type: LineType.stdout, text: '' };\n\
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/ChildProcess.tsx"],"sourcesContent":["import { Box, Text } from 'ink';\nimport { memo, useMemo } from 'react';\nimport { SPINNER } from '../constants.ts';\nimport ansiRegex from '../lib/ansiRegex.ts';\nimport figures from '../lib/figures.ts';\nimport type { ChildProcess as ChildProcessT, Line, State } from '../types.ts';\nimport { LineType } from '../types.ts';\nimport Spinner from './Spinner.ts';\n\nconst REGEX_ANSI = ansiRegex();\nconst BLANK_LINE = { type: LineType.stdout, text: '' };\n\nconst ICONS = {\n error: <Text color=\"red\">{figures.cross}</Text>,\n success: <Text color=\"green\">{figures.tick}</Text>,\n running: <Spinner {...SPINNER} />,\n};\n\ntype ItemProps = {\n item: ChildProcessT;\n};\n\ntype HeaderProps = {\n group?: string;\n title: string;\n state: State;\n};\n\nconst Header = memo(\n function Header({ group, title, state }: HeaderProps) {\n const icon = ICONS[state];\n\n return (\n <Box>\n {icon}\n {group && <Text bold>{`${group}${figures.pointer} `}</Text>}\n <Text>{title}</Text>\n </Box>\n );\n },\n (a, b) => a.group === b.group && a.title === b.title && a.state === b.state\n);\n\ntype RunningSummaryProps = {\n line: Line;\n};\n\nconst RunningSummary = memo(function RunningSummary({ line }: RunningSummaryProps) {\n return (\n <Box marginLeft={2}>\n <Text color=\"gray\">{line.text.replace(REGEX_ANSI, '')}</Text>\n </Box>\n );\n});\n\ntype LinesProps = {\n lines: Line[];\n};\n\nconst renderLine = (line, index) => {\n return (\n <Box key={index} minHeight={1}>\n <Text>{line.text}</Text>\n </Box>\n );\n};\n\nconst Lines = memo(function Lines({ lines }: LinesProps) {\n return (\n <Box flexDirection=\"column\" marginLeft={2}>\n {lines.map(renderLine)}\n </Box>\n );\n});\n\nconst Expanded = memo(function Expanded({ item }: ItemProps) {\n const { lines } = item;\n\n return (\n <Box flexDirection=\"column\">\n <Header group={item.group} title={item.title} state={item.state} />\n <Lines lines={lines} />\n </Box>\n );\n});\n\nconst Contracted = memo(function Contracted({ item }: ItemProps) {\n const { state, lines } = item;\n\n // remove ansi codes when displaying single lines\n const errors = useMemo(() => lines.filter((line) => line.type === LineType.stderr), [lines]);\n const summary = useMemo(() => lines.filter((line) => line.text.length > 0 && errors.indexOf(line) < 0).pop(), [lines, errors]);\n\n return (\n <Box flexDirection=\"column\">\n <Header group={item.group} title={item.title} state={item.state} />\n {state === 'running' && <RunningSummary line={summary || BLANK_LINE} />}\n {errors.length > 0 && <Lines lines={errors} />}\n </Box>\n );\n});\n\nexport default memo(function ChildProcess({ item }: ItemProps) {\n const { expanded } = item;\n return expanded ? <Expanded item={item} /> : <Contracted item={item} />;\n});\n"],"names":["Box","Text","memo","useMemo","SPINNER","ansiRegex","figures","LineType","Spinner","REGEX_ANSI","BLANK_LINE","type","stdout","text","ICONS","error","color","cross","success","tick","running","Header","group","title","state","icon","bold","pointer","a","b","RunningSummary","line","marginLeft","replace","renderLine","index","minHeight","Lines","lines","flexDirection","map","Expanded","item","Contracted","errors","filter","stderr","summary","length","indexOf","pop","ChildProcess","expanded"],"mappings":"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"}
|