spawn-term 3.0.3 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/cjs/components/App.js +29 -63
  2. package/dist/cjs/components/App.js.map +1 -1
  3. package/dist/cjs/components/ErrorFooter.js +120 -0
  4. package/dist/cjs/components/ErrorFooter.js.map +1 -0
  5. package/dist/cjs/components/ExpandedOutput.js +0 -2
  6. package/dist/cjs/components/ExpandedOutput.js.map +1 -1
  7. package/dist/cjs/components/StatusBar.js +22 -33
  8. package/dist/cjs/components/StatusBar.js.map +1 -1
  9. package/dist/cjs/src/components/ErrorFooter.d.ts +11 -0
  10. package/dist/cjs/src/state/processStore.d.ts +9 -6
  11. package/dist/cjs/state/processStore.js +23 -20
  12. package/dist/cjs/state/processStore.js.map +1 -1
  13. package/dist/esm/components/App.js +29 -63
  14. package/dist/esm/components/App.js.map +1 -1
  15. package/dist/esm/components/ErrorFooter.js +95 -0
  16. package/dist/esm/components/ErrorFooter.js.map +1 -0
  17. package/dist/esm/components/ExpandedOutput.js +0 -2
  18. package/dist/esm/components/ExpandedOutput.js.map +1 -1
  19. package/dist/esm/components/StatusBar.js +22 -33
  20. package/dist/esm/components/StatusBar.js.map +1 -1
  21. package/dist/esm/src/components/ErrorFooter.d.ts +11 -0
  22. package/dist/esm/src/state/processStore.d.ts +9 -6
  23. package/dist/esm/state/processStore.js +19 -18
  24. package/dist/esm/state/processStore.js.map +1 -1
  25. package/package.json +1 -1
  26. package/dist/cjs/components/ErrorDetailModal.js +0 -115
  27. package/dist/cjs/components/ErrorDetailModal.js.map +0 -1
  28. package/dist/cjs/components/ErrorListModal.js +0 -135
  29. package/dist/cjs/components/ErrorListModal.js.map +0 -1
  30. package/dist/cjs/src/components/ErrorDetailModal.d.ts +0 -8
  31. package/dist/cjs/src/components/ErrorListModal.d.ts +0 -8
  32. package/dist/esm/components/ErrorDetailModal.js +0 -99
  33. package/dist/esm/components/ErrorDetailModal.js.map +0 -1
  34. package/dist/esm/components/ErrorListModal.js +0 -116
  35. package/dist/esm/components/ErrorListModal.js.map +0 -1
  36. package/dist/esm/src/components/ErrorDetailModal.d.ts +0 -8
  37. package/dist/esm/src/components/ErrorListModal.d.ts +0 -8
@@ -49,6 +49,10 @@ export class ProcessStore {
49
49
  id
50
50
  ];
51
51
  }
52
+ // Auto-expand error footer when all complete with errors (non-interactive only)
53
+ if (!this.isInteractive && this.isAllComplete() && this.getErrorCount() > 0) {
54
+ this.errorFooterExpanded = true;
55
+ }
52
56
  this.notify();
53
57
  }
54
58
  appendLines(id, newLines) {
@@ -67,8 +71,6 @@ export class ProcessStore {
67
71
  this.mode = mode;
68
72
  if (mode === 'interactive') {
69
73
  this.selectedIndex = 0;
70
- } else if (mode === 'errorList') {
71
- this.selectedErrorIndex = 0;
72
74
  }
73
75
  this.notify();
74
76
  }
@@ -101,23 +103,22 @@ export class ProcessStore {
101
103
  getSelectedProcess() {
102
104
  return this.processes[this.selectedIndex];
103
105
  }
104
- selectNextError() {
105
- const failed = this.getFailedProcesses();
106
- if (failed.length > 0) {
107
- this.selectedErrorIndex = (this.selectedErrorIndex + 1) % failed.length;
108
- this.notify();
109
- }
106
+ // Error footer methods (for non-interactive mode)
107
+ toggleErrorFooter() {
108
+ this.errorFooterExpanded = !this.errorFooterExpanded;
109
+ this.notify();
110
110
  }
111
- selectPrevError() {
112
- const failed = this.getFailedProcesses();
113
- if (failed.length > 0) {
114
- this.selectedErrorIndex = (this.selectedErrorIndex - 1 + failed.length) % failed.length;
111
+ expandErrorFooter() {
112
+ if (!this.errorFooterExpanded) {
113
+ this.errorFooterExpanded = true;
115
114
  this.notify();
116
115
  }
117
116
  }
118
- getSelectedError() {
119
- const failed = this.getFailedProcesses();
120
- return failed[this.selectedErrorIndex];
117
+ getErrorLines() {
118
+ return this.getFailedProcesses().map((p)=>({
119
+ processName: p.group || p.title,
120
+ lines: p.lines
121
+ }));
121
122
  }
122
123
  // Expansion methods
123
124
  toggleExpand() {
@@ -169,10 +170,10 @@ export class ProcessStore {
169
170
  this.exitCallback = null;
170
171
  this.mode = 'normal';
171
172
  this.selectedIndex = 0;
172
- this.selectedErrorIndex = 0;
173
173
  this.expandedId = null;
174
174
  this.scrollOffset = 0;
175
175
  this.listScrollOffset = 0;
176
+ this.errorFooterExpanded = false;
176
177
  this.header = undefined;
177
178
  }
178
179
  notify() {
@@ -189,10 +190,10 @@ export class ProcessStore {
189
190
  // UI state
190
191
  this.mode = 'normal';
191
192
  this.selectedIndex = 0;
192
- this.selectedErrorIndex = 0;
193
193
  this.expandedId = null;
194
194
  this.scrollOffset = 0;
195
195
  this.listScrollOffset = 0; // Viewport offset for process list
196
+ this.errorFooterExpanded = false; // For non-interactive error footer
196
197
  this.showStatusBar = false;
197
198
  this.isInteractive = false;
198
199
  // useSyncExternalStore API
@@ -226,10 +227,10 @@ export class ProcessStore {
226
227
  // UI state getters
227
228
  this.getMode = ()=>this.mode;
228
229
  this.getSelectedIndex = ()=>this.selectedIndex;
229
- this.getSelectedErrorIndex = ()=>this.selectedErrorIndex;
230
230
  this.getExpandedId = ()=>this.expandedId;
231
231
  this.getScrollOffset = ()=>this.scrollOffset;
232
232
  this.getListScrollOffset = ()=>this.listScrollOffset;
233
+ this.getErrorFooterExpanded = ()=>this.errorFooterExpanded;
233
234
  // Session-level getters (set at session creation, immutable)
234
235
  this.getHeader = ()=>this.header;
235
236
  this.getShowStatusBar = ()=>this.showStatusBar;
@@ -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 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":["DEFAULT_COLUMN_WIDTH","LineType","ProcessStore","addProcess","process","processes","notify","updateProcess","id","update","oldProcess","find","p","wasRunning","state","isNowComplete","map","completedIds","includes","appendLines","newLines","lines","concat","getProcess","setMode","mode","selectedIndex","selectedErrorIndex","selectNext","visibleCount","length","adjustListScroll","selectPrev","listScrollOffset","getSelectedProcess","selectNextError","failed","getFailedProcesses","selectPrevError","getSelectedError","toggleExpand","selected","expandedId","scrollOffset","collapse","scrollDown","maxVisible","maxOffset","Math","max","scrollUp","signalExit","callback","shouldExit","exitCallback","reset","header","undefined","listeners","forEach","l","options","Set","showStatusBar","isInteractive","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","getRunningCount","getMaxGroupLength","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","type","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getListScrollOffset","getHeader","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive"],"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';\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 expandedId: string | null = null;\n private scrollOffset = 0;\n private listScrollOffset = 0; // Viewport offset for process list\n private errorFooterExpanded = false; // For non-interactive error footer\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 getExpandedId = (): string | null => this.expandedId;\n getScrollOffset = (): number => this.scrollOffset;\n getListScrollOffset = (): number => this.listScrollOffset;\n getErrorFooterExpanded = (): boolean => this.errorFooterExpanded;\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 // Auto-expand error footer when all complete with errors (non-interactive only)\n if (!this.isInteractive && this.isAllComplete() && this.getErrorCount() > 0) {\n this.errorFooterExpanded = true;\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 }\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 // Error footer methods (for non-interactive mode)\n toggleErrorFooter(): void {\n this.errorFooterExpanded = !this.errorFooterExpanded;\n this.notify();\n }\n\n expandErrorFooter(): void {\n if (!this.errorFooterExpanded) {\n this.errorFooterExpanded = true;\n this.notify();\n }\n }\n\n getErrorLines(): Array<{ processName: string; lines: Line[] }> {\n return this.getFailedProcesses().map((p) => ({\n processName: p.group || p.title,\n lines: p.lines,\n }));\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.expandedId = null;\n this.scrollOffset = 0;\n this.listScrollOffset = 0;\n this.errorFooterExpanded = false;\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":["DEFAULT_COLUMN_WIDTH","LineType","ProcessStore","addProcess","process","processes","notify","updateProcess","id","update","oldProcess","find","p","wasRunning","state","isNowComplete","map","completedIds","includes","isInteractive","isAllComplete","getErrorCount","errorFooterExpanded","appendLines","newLines","lines","concat","getProcess","setMode","mode","selectedIndex","selectNext","visibleCount","length","adjustListScroll","selectPrev","listScrollOffset","getSelectedProcess","toggleErrorFooter","expandErrorFooter","getErrorLines","getFailedProcesses","processName","group","title","toggleExpand","selected","expandedId","scrollOffset","collapse","scrollDown","maxVisible","maxOffset","Math","max","scrollUp","signalExit","callback","shouldExit","exitCallback","reset","header","undefined","listeners","forEach","l","options","Set","showStatusBar","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","getRunningCount","getMaxGroupLength","getDoneCount","getErrorLineCount","reduce","total","type","stderr","getMode","getSelectedIndex","getExpandedId","getScrollOffset","getListScrollOffset","getErrorFooterExpanded","getHeader","getShowStatusBar","getIsInteractive","every","getShouldExit","getExitCallback","interactive"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawn-term",
3
- "version": "3.0.3",
3
+ "version": "3.0.5",
4
4
  "description": "Formats spawn with for terminal grouping",
5
5
  "keywords": [
6
6
  "spawn",
@@ -1,115 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "default", {
6
- enumerable: true,
7
- get: function() {
8
- return _default;
9
- }
10
- });
11
- var _jsxruntime = require("react/jsx-runtime");
12
- var _ink = require("ink");
13
- var _react = require("react");
14
- var _typests = require("../types.js");
15
- var _default = /*#__PURE__*/ (0, _react.memo)(function ErrorDetailModal(param) {
16
- var error = param.error, currentIndex = param.currentIndex, totalErrors = param.totalErrors;
17
- var stdout = (0, _ink.useStdout)().stdout;
18
- var width = (stdout === null || stdout === void 0 ? void 0 : stdout.columns) || 80;
19
- var borderH = '─'.repeat(width - 2);
20
- var title = " Error Detail (".concat(currentIndex + 1, "/").concat(totalErrors, ") ");
21
- var titleBorder = "┌".concat(title).concat(borderH.slice(title.length + 1), "┐");
22
- var name = error.group || error.title;
23
- var stderrLines = error.lines.filter(function(l) {
24
- return l.type === _typests.LineType.stderr;
25
- });
26
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
27
- flexDirection: "column",
28
- children: [
29
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
30
- children: titleBorder
31
- }),
32
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
33
- paddingX: 1,
34
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
35
- bold: true,
36
- children: name
37
- })
38
- }),
39
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
40
- paddingX: 1,
41
- children: [
42
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
43
- dimColor: true,
44
- children: "Command: "
45
- }),
46
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
47
- children: error.title
48
- })
49
- ]
50
- }),
51
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
52
- paddingX: 1,
53
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
54
- dimColor: true,
55
- children: '─'.repeat(width - 4)
56
- })
57
- }),
58
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
59
- paddingX: 1,
60
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
61
- dimColor: true,
62
- children: "stderr:"
63
- })
64
- }),
65
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
66
- flexDirection: "column",
67
- paddingX: 2,
68
- children: stderrLines.length === 0 ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
69
- dimColor: true,
70
- children: "(no stderr output)"
71
- }) : stderrLines.map(function(line, index) {
72
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
73
- color: "red",
74
- children: line.text
75
- }, "stderr-".concat(index, "-").concat(line.text.slice(0, 20)));
76
- })
77
- }),
78
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
79
- paddingX: 1,
80
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
81
- children: " "
82
- })
83
- }),
84
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
85
- children: [
86
- "├",
87
- borderH,
88
- "┤"
89
- ]
90
- }),
91
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
92
- paddingX: 1,
93
- justifyContent: "space-between",
94
- children: [
95
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
96
- dimColor: true,
97
- children: "[↑↓] prev/next error"
98
- }),
99
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
100
- dimColor: true,
101
- children: "[Esc] back to list"
102
- })
103
- ]
104
- }),
105
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
106
- children: [
107
- "└",
108
- borderH,
109
- "┘"
110
- ]
111
- })
112
- ]
113
- });
114
- });
115
- /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/ErrorDetailModal.tsx"],"sourcesContent":["import { Box, Text, useStdout } from 'ink';\nimport { memo } from 'react';\nimport type { ChildProcess } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Props = {\n error: ChildProcess;\n currentIndex: number;\n totalErrors: number;\n};\n\nexport default memo(function ErrorDetailModal({ error, currentIndex, totalErrors }: Props) {\n const { stdout } = useStdout();\n const width = stdout?.columns || 80;\n\n const borderH = '─'.repeat(width - 2);\n const title = ` Error Detail (${currentIndex + 1}/${totalErrors}) `;\n const titleBorder = `┌${title}${borderH.slice(title.length + 1)}┐`;\n\n const name = error.group || error.title;\n const stderrLines = error.lines.filter((l) => l.type === LineType.stderr);\n\n return (\n <Box flexDirection=\"column\">\n {/* Top border with title */}\n <Text>{titleBorder}</Text>\n\n {/* Process name */}\n <Box paddingX={1}>\n <Text bold>{name}</Text>\n </Box>\n\n {/* Command */}\n <Box paddingX={1}>\n <Text dimColor>Command: </Text>\n <Text>{error.title}</Text>\n </Box>\n\n {/* Separator */}\n <Box paddingX={1}>\n <Text dimColor>{'─'.repeat(width - 4)}</Text>\n </Box>\n\n {/* Error output */}\n <Box paddingX={1}>\n <Text dimColor>stderr:</Text>\n </Box>\n\n {/* Error lines in a box */}\n <Box flexDirection=\"column\" paddingX={2}>\n {stderrLines.length === 0 ? (\n <Text dimColor>(no stderr output)</Text>\n ) : (\n stderrLines.map((line, index) => (\n <Text key={`stderr-${index}-${line.text.slice(0, 20)}`} color=\"red\">\n {line.text}\n </Text>\n ))\n )}\n </Box>\n\n {/* Empty line for padding */}\n <Box paddingX={1}>\n <Text> </Text>\n </Box>\n\n {/* Bottom border with hints */}\n <Text>├{borderH}┤</Text>\n <Box paddingX={1} justifyContent=\"space-between\">\n <Text dimColor>[↑↓] prev/next error</Text>\n <Text dimColor>[Esc] back to list</Text>\n </Box>\n <Text>└{borderH}┘</Text>\n </Box>\n );\n});\n"],"names":["memo","ErrorDetailModal","error","currentIndex","totalErrors","stdout","useStdout","width","columns","borderH","repeat","title","titleBorder","slice","length","name","group","stderrLines","lines","filter","l","type","LineType","stderr","Box","flexDirection","Text","paddingX","bold","dimColor","map","line","index","color","text","justifyContent"],"mappings":";;;;+BAWA;;;eAAA;;;;mBAXqC;qBAChB;uBAEI;IAQzB,yBAAeA,IAAAA,WAAI,EAAC,SAASC,iBAAiB,KAA2C;QAAzCC,QAAF,MAAEA,OAAOC,eAAT,MAASA,cAAcC,cAAvB,MAAuBA;IACnE,IAAM,AAAEC,SAAWC,IAAAA,cAAS,IAApBD;IACR,IAAME,QAAQF,CAAAA,mBAAAA,6BAAAA,OAAQG,OAAO,KAAI;IAEjC,IAAMC,UAAU,IAAIC,MAAM,CAACH,QAAQ;IACnC,IAAMI,QAAQ,AAAC,kBAAqCP,OAApBD,eAAe,GAAE,KAAe,OAAZC,aAAY;IAChE,IAAMQ,cAAc,AAAC,IAAWH,OAARE,OAAwC,OAAhCF,QAAQI,KAAK,CAACF,MAAMG,MAAM,GAAG,IAAG;IAEhE,IAAMC,OAAOb,MAAMc,KAAK,IAAId,MAAMS,KAAK;IACvC,IAAMM,cAAcf,MAAMgB,KAAK,CAACC,MAAM,CAAC,SAACC;eAAMA,EAAEC,IAAI,KAAKC,iBAAQ,CAACC,MAAM;;IAExE,qBACE,sBAACC,QAAG;QAACC,eAAc;;0BAEjB,qBAACC,SAAI;0BAAEd;;0BAGP,qBAACY,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;oBAACE,IAAI;8BAAEb;;;0BAId,sBAACS,QAAG;gBAACG,UAAU;;kCACb,qBAACD,SAAI;wBAACG,QAAQ;kCAAC;;kCACf,qBAACH,SAAI;kCAAExB,MAAMS,KAAK;;;;0BAIpB,qBAACa,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;oBAACG,QAAQ;8BAAE,IAAInB,MAAM,CAACH,QAAQ;;;0BAIrC,qBAACiB,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;oBAACG,QAAQ;8BAAC;;;0BAIjB,qBAACL,QAAG;gBAACC,eAAc;gBAASE,UAAU;0BACnCV,YAAYH,MAAM,KAAK,kBACtB,qBAACY,SAAI;oBAACG,QAAQ;8BAAC;qBAEfZ,YAAYa,GAAG,CAAC,SAACC,MAAMC;yCACrB,qBAACN,SAAI;wBAAmDO,OAAM;kCAC3DF,KAAKG,IAAI;uBADD,AAAC,UAAkBH,OAATC,OAAM,KAA0B,OAAvBD,KAAKG,IAAI,CAACrB,KAAK,CAAC,GAAG;;;0BAQvD,qBAACW,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;8BAAC;;;0BAIR,sBAACA,SAAI;;oBAAC;oBAAEjB;oBAAQ;;;0BAChB,sBAACe,QAAG;gBAACG,UAAU;gBAAGQ,gBAAe;;kCAC/B,qBAACT,SAAI;wBAACG,QAAQ;kCAAC;;kCACf,qBAACH,SAAI;wBAACG,QAAQ;kCAAC;;;;0BAEjB,sBAACH,SAAI;;oBAAC;oBAAEjB;oBAAQ;;;;;AAGtB"}
@@ -1,135 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "default", {
6
- enumerable: true,
7
- get: function() {
8
- return _default;
9
- }
10
- });
11
- var _jsxruntime = require("react/jsx-runtime");
12
- var _ink = require("ink");
13
- var _react = require("react");
14
- var _figurests = /*#__PURE__*/ _interop_require_default(require("../lib/figures.js"));
15
- var _typests = require("../types.js");
16
- function _interop_require_default(obj) {
17
- return obj && obj.__esModule ? obj : {
18
- default: obj
19
- };
20
- }
21
- function truncate(str, maxLength) {
22
- if (str.length <= maxLength) return str;
23
- return "".concat(str.slice(0, maxLength - 1), "…");
24
- }
25
- function getErrorLineCount(process) {
26
- return process.lines.filter(function(l) {
27
- return l.type === _typests.LineType.stderr;
28
- }).length;
29
- }
30
- var _default = /*#__PURE__*/ (0, _react.memo)(function ErrorListModal(param) {
31
- var errors = param.errors, selectedIndex = param.selectedIndex, totalErrorLines = param.totalErrorLines;
32
- var stdout = (0, _ink.useStdout)().stdout;
33
- var width = (stdout === null || stdout === void 0 ? void 0 : stdout.columns) || 80;
34
- var innerWidth = width - 4; // 2 chars padding each side
35
- var borderH = '─'.repeat(width - 2);
36
- var title = ' Errors ';
37
- var titleBorder = "┌".concat(title).concat(borderH.slice(title.length + 1), "┐");
38
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
39
- flexDirection: "column",
40
- children: [
41
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
42
- children: titleBorder
43
- }),
44
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
45
- paddingX: 1,
46
- children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
47
- children: [
48
- errors.length,
49
- " process",
50
- errors.length !== 1 ? 'es' : '',
51
- " failed (",
52
- totalErrorLines,
53
- " error line",
54
- totalErrorLines !== 1 ? 's' : '',
55
- " total)"
56
- ]
57
- })
58
- }),
59
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
60
- paddingX: 1,
61
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
62
- children: " "
63
- })
64
- }),
65
- errors.map(function(error, index) {
66
- var isSelected = index === selectedIndex;
67
- var indicator = isSelected ? _figurests.default.pointer : ' ';
68
- var name = error.group || error.title;
69
- var lineCount = getErrorLineCount(error);
70
- var lineText = "".concat(lineCount, " line").concat(lineCount !== 1 ? 's' : '');
71
- // Calculate available space for name
72
- var prefixLen = 3; // indicator + space + space
73
- var suffixLen = lineText.length + 2; // space + lineText
74
- var maxNameLen = innerWidth - prefixLen - suffixLen;
75
- var truncatedName = truncate(name, maxNameLen);
76
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
77
- paddingX: 1,
78
- children: [
79
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
80
- color: isSelected ? 'cyan' : undefined,
81
- bold: isSelected,
82
- children: [
83
- indicator,
84
- " ",
85
- truncatedName
86
- ]
87
- }),
88
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
89
- flexGrow: 1
90
- }),
91
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
92
- dimColor: true,
93
- children: lineText
94
- })
95
- ]
96
- }, error.id);
97
- }),
98
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Box, {
99
- paddingX: 1,
100
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
101
- children: " "
102
- })
103
- }),
104
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
105
- children: [
106
- "├",
107
- borderH,
108
- "┤"
109
- ]
110
- }),
111
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
112
- paddingX: 1,
113
- justifyContent: "space-between",
114
- children: [
115
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
116
- dimColor: true,
117
- children: "[↑↓] navigate [Enter] view details"
118
- }),
119
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
120
- dimColor: true,
121
- children: "[Esc] close"
122
- })
123
- ]
124
- }),
125
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Text, {
126
- children: [
127
- "└",
128
- borderH,
129
- "┘"
130
- ]
131
- })
132
- ]
133
- });
134
- });
135
- /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/ErrorListModal.tsx"],"sourcesContent":["import { Box, Text, useStdout } from 'ink';\nimport { memo } from 'react';\nimport figures from '../lib/figures.ts';\nimport type { ChildProcess } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Props = {\n errors: ChildProcess[];\n selectedIndex: number;\n totalErrorLines: number;\n};\n\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return `${str.slice(0, maxLength - 1)}…`;\n}\n\nfunction getErrorLineCount(process: ChildProcess): number {\n return process.lines.filter((l) => l.type === LineType.stderr).length;\n}\n\nexport default memo(function ErrorListModal({ errors, selectedIndex, totalErrorLines }: Props) {\n const { stdout } = useStdout();\n const width = stdout?.columns || 80;\n const innerWidth = width - 4; // 2 chars padding each side\n\n const borderH = '─'.repeat(width - 2);\n const title = ' Errors ';\n const titleBorder = `┌${title}${borderH.slice(title.length + 1)}┐`;\n\n return (\n <Box flexDirection=\"column\">\n {/* Top border with title */}\n <Text>{titleBorder}</Text>\n\n {/* Summary */}\n <Box paddingX={1}>\n <Text>\n {errors.length} process{errors.length !== 1 ? 'es' : ''} failed ({totalErrorLines} error line\n {totalErrorLines !== 1 ? 's' : ''} total)\n </Text>\n </Box>\n\n {/* Empty line */}\n <Box paddingX={1}>\n <Text> </Text>\n </Box>\n\n {/* Error list */}\n {errors.map((error, index) => {\n const isSelected = index === selectedIndex;\n const indicator = isSelected ? figures.pointer : ' ';\n const name = error.group || error.title;\n const lineCount = getErrorLineCount(error);\n const lineText = `${lineCount} line${lineCount !== 1 ? 's' : ''}`;\n\n // Calculate available space for name\n const prefixLen = 3; // indicator + space + space\n const suffixLen = lineText.length + 2; // space + lineText\n const maxNameLen = innerWidth - prefixLen - suffixLen;\n const truncatedName = truncate(name, maxNameLen);\n\n return (\n <Box key={error.id} paddingX={1}>\n <Text color={isSelected ? 'cyan' : undefined} bold={isSelected}>\n {indicator} {truncatedName}\n </Text>\n <Box flexGrow={1} />\n <Text dimColor>{lineText}</Text>\n </Box>\n );\n })}\n\n {/* Empty line for padding */}\n <Box paddingX={1}>\n <Text> </Text>\n </Box>\n\n {/* Bottom border with hints */}\n <Text>├{borderH}┤</Text>\n <Box paddingX={1} justifyContent=\"space-between\">\n <Text dimColor>[↑↓] navigate [Enter] view details</Text>\n <Text dimColor>[Esc] close</Text>\n </Box>\n <Text>└{borderH}┘</Text>\n </Box>\n );\n});\n"],"names":["truncate","str","maxLength","length","slice","getErrorLineCount","process","lines","filter","l","type","LineType","stderr","memo","ErrorListModal","errors","selectedIndex","totalErrorLines","stdout","useStdout","width","columns","innerWidth","borderH","repeat","title","titleBorder","Box","flexDirection","Text","paddingX","map","error","index","isSelected","indicator","figures","pointer","name","group","lineCount","lineText","prefixLen","suffixLen","maxNameLen","truncatedName","color","undefined","bold","flexGrow","dimColor","id","justifyContent"],"mappings":";;;;+BAqBA;;;eAAA;;;;mBArBqC;qBAChB;gEACD;uBAEK;;;;;;AAQzB,SAASA,SAASC,GAAW,EAAEC,SAAiB;IAC9C,IAAID,IAAIE,MAAM,IAAID,WAAW,OAAOD;IACpC,OAAO,AAAC,GAA8B,OAA5BA,IAAIG,KAAK,CAAC,GAAGF,YAAY,IAAG;AACxC;AAEA,SAASG,kBAAkBC,OAAqB;IAC9C,OAAOA,QAAQC,KAAK,CAACC,MAAM,CAAC,SAACC;eAAMA,EAAEC,IAAI,KAAKC,iBAAQ,CAACC,MAAM;OAAET,MAAM;AACvE;IAEA,yBAAeU,IAAAA,WAAI,EAAC,SAASC,eAAe,KAAiD;QAA/CC,SAAF,MAAEA,QAAQC,gBAAV,MAAUA,eAAeC,kBAAzB,MAAyBA;IACnE,IAAM,AAAEC,SAAWC,IAAAA,cAAS,IAApBD;IACR,IAAME,QAAQF,CAAAA,mBAAAA,6BAAAA,OAAQG,OAAO,KAAI;IACjC,IAAMC,aAAaF,QAAQ,GAAG,4BAA4B;IAE1D,IAAMG,UAAU,IAAIC,MAAM,CAACJ,QAAQ;IACnC,IAAMK,QAAQ;IACd,IAAMC,cAAc,AAAC,IAAWH,OAARE,OAAwC,OAAhCF,QAAQnB,KAAK,CAACqB,MAAMtB,MAAM,GAAG,IAAG;IAEhE,qBACE,sBAACwB,QAAG;QAACC,eAAc;;0BAEjB,qBAACC,SAAI;0BAAEH;;0BAGP,qBAACC,QAAG;gBAACG,UAAU;0BACb,cAAA,sBAACD,SAAI;;wBACFd,OAAOZ,MAAM;wBAAC;wBAASY,OAAOZ,MAAM,KAAK,IAAI,OAAO;wBAAG;wBAAUc;wBAAgB;wBACjFA,oBAAoB,IAAI,MAAM;wBAAG;;;;0BAKtC,qBAACU,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;8BAAC;;;YAIPd,OAAOgB,GAAG,CAAC,SAACC,OAAOC;gBAClB,IAAMC,aAAaD,UAAUjB;gBAC7B,IAAMmB,YAAYD,aAAaE,kBAAO,CAACC,OAAO,GAAG;gBACjD,IAAMC,OAAON,MAAMO,KAAK,IAAIP,MAAMP,KAAK;gBACvC,IAAMe,YAAYnC,kBAAkB2B;gBACpC,IAAMS,WAAW,AAAC,GAAmBD,OAAjBA,WAAU,SAAkC,OAA3BA,cAAc,IAAI,MAAM;gBAE7D,qCAAqC;gBACrC,IAAME,YAAY,GAAG,4BAA4B;gBACjD,IAAMC,YAAYF,SAAStC,MAAM,GAAG,GAAG,mBAAmB;gBAC1D,IAAMyC,aAAatB,aAAaoB,YAAYC;gBAC5C,IAAME,gBAAgB7C,SAASsC,MAAMM;gBAErC,qBACE,sBAACjB,QAAG;oBAAgBG,UAAU;;sCAC5B,sBAACD,SAAI;4BAACiB,OAAOZ,aAAa,SAASa;4BAAWC,MAAMd;;gCACjDC;gCAAU;gCAAEU;;;sCAEf,qBAAClB,QAAG;4BAACsB,UAAU;;sCACf,qBAACpB,SAAI;4BAACqB,QAAQ;sCAAET;;;mBALRT,MAAMmB,EAAE;YAQtB;0BAGA,qBAACxB,QAAG;gBAACG,UAAU;0BACb,cAAA,qBAACD,SAAI;8BAAC;;;0BAIR,sBAACA,SAAI;;oBAAC;oBAAEN;oBAAQ;;;0BAChB,sBAACI,QAAG;gBAACG,UAAU;gBAAGsB,gBAAe;;kCAC/B,qBAACvB,SAAI;wBAACqB,QAAQ;kCAAC;;kCACf,qBAACrB,SAAI;wBAACqB,QAAQ;kCAAC;;;;0BAEjB,sBAACrB,SAAI;;oBAAC;oBAAEN;oBAAQ;;;;;AAGtB"}
@@ -1,8 +0,0 @@
1
- import type { ChildProcess } from '../types.js';
2
- type Props = {
3
- error: ChildProcess;
4
- currentIndex: number;
5
- totalErrors: number;
6
- };
7
- declare const _default: import("react").NamedExoticComponent<Props>;
8
- export default _default;
@@ -1,8 +0,0 @@
1
- import type { ChildProcess } from '../types.js';
2
- type Props = {
3
- errors: ChildProcess[];
4
- selectedIndex: number;
5
- totalErrorLines: number;
6
- };
7
- declare const _default: import("react").NamedExoticComponent<Props>;
8
- export default _default;
@@ -1,99 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text, useStdout } from 'ink';
3
- import { memo } from 'react';
4
- import { LineType } from '../types.js';
5
- export default /*#__PURE__*/ memo(function ErrorDetailModal({ error, currentIndex, totalErrors }) {
6
- const { stdout } = useStdout();
7
- const width = (stdout === null || stdout === void 0 ? void 0 : stdout.columns) || 80;
8
- const borderH = '─'.repeat(width - 2);
9
- const title = ` Error Detail (${currentIndex + 1}/${totalErrors}) `;
10
- const titleBorder = `┌${title}${borderH.slice(title.length + 1)}┐`;
11
- const name = error.group || error.title;
12
- const stderrLines = error.lines.filter((l)=>l.type === LineType.stderr);
13
- return /*#__PURE__*/ _jsxs(Box, {
14
- flexDirection: "column",
15
- children: [
16
- /*#__PURE__*/ _jsx(Text, {
17
- children: titleBorder
18
- }),
19
- /*#__PURE__*/ _jsx(Box, {
20
- paddingX: 1,
21
- children: /*#__PURE__*/ _jsx(Text, {
22
- bold: true,
23
- children: name
24
- })
25
- }),
26
- /*#__PURE__*/ _jsxs(Box, {
27
- paddingX: 1,
28
- children: [
29
- /*#__PURE__*/ _jsx(Text, {
30
- dimColor: true,
31
- children: "Command: "
32
- }),
33
- /*#__PURE__*/ _jsx(Text, {
34
- children: error.title
35
- })
36
- ]
37
- }),
38
- /*#__PURE__*/ _jsx(Box, {
39
- paddingX: 1,
40
- children: /*#__PURE__*/ _jsx(Text, {
41
- dimColor: true,
42
- children: '─'.repeat(width - 4)
43
- })
44
- }),
45
- /*#__PURE__*/ _jsx(Box, {
46
- paddingX: 1,
47
- children: /*#__PURE__*/ _jsx(Text, {
48
- dimColor: true,
49
- children: "stderr:"
50
- })
51
- }),
52
- /*#__PURE__*/ _jsx(Box, {
53
- flexDirection: "column",
54
- paddingX: 2,
55
- children: stderrLines.length === 0 ? /*#__PURE__*/ _jsx(Text, {
56
- dimColor: true,
57
- children: "(no stderr output)"
58
- }) : stderrLines.map((line, index)=>/*#__PURE__*/ _jsx(Text, {
59
- color: "red",
60
- children: line.text
61
- }, `stderr-${index}-${line.text.slice(0, 20)}`))
62
- }),
63
- /*#__PURE__*/ _jsx(Box, {
64
- paddingX: 1,
65
- children: /*#__PURE__*/ _jsx(Text, {
66
- children: " "
67
- })
68
- }),
69
- /*#__PURE__*/ _jsxs(Text, {
70
- children: [
71
- "├",
72
- borderH,
73
- "┤"
74
- ]
75
- }),
76
- /*#__PURE__*/ _jsxs(Box, {
77
- paddingX: 1,
78
- justifyContent: "space-between",
79
- children: [
80
- /*#__PURE__*/ _jsx(Text, {
81
- dimColor: true,
82
- children: "[↑↓] prev/next error"
83
- }),
84
- /*#__PURE__*/ _jsx(Text, {
85
- dimColor: true,
86
- children: "[Esc] back to list"
87
- })
88
- ]
89
- }),
90
- /*#__PURE__*/ _jsxs(Text, {
91
- children: [
92
- "└",
93
- borderH,
94
- "┘"
95
- ]
96
- })
97
- ]
98
- });
99
- });
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/ErrorDetailModal.tsx"],"sourcesContent":["import { Box, Text, useStdout } from 'ink';\nimport { memo } from 'react';\nimport type { ChildProcess } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Props = {\n error: ChildProcess;\n currentIndex: number;\n totalErrors: number;\n};\n\nexport default memo(function ErrorDetailModal({ error, currentIndex, totalErrors }: Props) {\n const { stdout } = useStdout();\n const width = stdout?.columns || 80;\n\n const borderH = '─'.repeat(width - 2);\n const title = ` Error Detail (${currentIndex + 1}/${totalErrors}) `;\n const titleBorder = `┌${title}${borderH.slice(title.length + 1)}┐`;\n\n const name = error.group || error.title;\n const stderrLines = error.lines.filter((l) => l.type === LineType.stderr);\n\n return (\n <Box flexDirection=\"column\">\n {/* Top border with title */}\n <Text>{titleBorder}</Text>\n\n {/* Process name */}\n <Box paddingX={1}>\n <Text bold>{name}</Text>\n </Box>\n\n {/* Command */}\n <Box paddingX={1}>\n <Text dimColor>Command: </Text>\n <Text>{error.title}</Text>\n </Box>\n\n {/* Separator */}\n <Box paddingX={1}>\n <Text dimColor>{'─'.repeat(width - 4)}</Text>\n </Box>\n\n {/* Error output */}\n <Box paddingX={1}>\n <Text dimColor>stderr:</Text>\n </Box>\n\n {/* Error lines in a box */}\n <Box flexDirection=\"column\" paddingX={2}>\n {stderrLines.length === 0 ? (\n <Text dimColor>(no stderr output)</Text>\n ) : (\n stderrLines.map((line, index) => (\n <Text key={`stderr-${index}-${line.text.slice(0, 20)}`} color=\"red\">\n {line.text}\n </Text>\n ))\n )}\n </Box>\n\n {/* Empty line for padding */}\n <Box paddingX={1}>\n <Text> </Text>\n </Box>\n\n {/* Bottom border with hints */}\n <Text>├{borderH}┤</Text>\n <Box paddingX={1} justifyContent=\"space-between\">\n <Text dimColor>[↑↓] prev/next error</Text>\n <Text dimColor>[Esc] back to list</Text>\n </Box>\n <Text>└{borderH}┘</Text>\n </Box>\n );\n});\n"],"names":["Box","Text","useStdout","memo","LineType","ErrorDetailModal","error","currentIndex","totalErrors","stdout","width","columns","borderH","repeat","title","titleBorder","slice","length","name","group","stderrLines","lines","filter","l","type","stderr","flexDirection","paddingX","bold","dimColor","map","line","index","color","text","justifyContent"],"mappings":";AAAA,SAASA,GAAG,EAAEC,IAAI,EAAEC,SAAS,QAAQ,MAAM;AAC3C,SAASC,IAAI,QAAQ,QAAQ;AAE7B,SAASC,QAAQ,QAAQ,cAAc;AAQvC,6BAAeD,KAAK,SAASE,iBAAiB,EAAEC,KAAK,EAAEC,YAAY,EAAEC,WAAW,EAAS;IACvF,MAAM,EAAEC,MAAM,EAAE,GAAGP;IACnB,MAAMQ,QAAQD,CAAAA,mBAAAA,6BAAAA,OAAQE,OAAO,KAAI;IAEjC,MAAMC,UAAU,IAAIC,MAAM,CAACH,QAAQ;IACnC,MAAMI,QAAQ,CAAC,eAAe,EAAEP,eAAe,EAAE,CAAC,EAAEC,YAAY,EAAE,CAAC;IACnE,MAAMO,cAAc,CAAC,CAAC,EAAED,QAAQF,QAAQI,KAAK,CAACF,MAAMG,MAAM,GAAG,GAAG,CAAC,CAAC;IAElE,MAAMC,OAAOZ,MAAMa,KAAK,IAAIb,MAAMQ,KAAK;IACvC,MAAMM,cAAcd,MAAMe,KAAK,CAACC,MAAM,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKpB,SAASqB,MAAM;IAExE,qBACE,MAACzB;QAAI0B,eAAc;;0BAEjB,KAACzB;0BAAMc;;0BAGP,KAACf;gBAAI2B,UAAU;0BACb,cAAA,KAAC1B;oBAAK2B,IAAI;8BAAEV;;;0BAId,MAAClB;gBAAI2B,UAAU;;kCACb,KAAC1B;wBAAK4B,QAAQ;kCAAC;;kCACf,KAAC5B;kCAAMK,MAAMQ,KAAK;;;;0BAIpB,KAACd;gBAAI2B,UAAU;0BACb,cAAA,KAAC1B;oBAAK4B,QAAQ;8BAAE,IAAIhB,MAAM,CAACH,QAAQ;;;0BAIrC,KAACV;gBAAI2B,UAAU;0BACb,cAAA,KAAC1B;oBAAK4B,QAAQ;8BAAC;;;0BAIjB,KAAC7B;gBAAI0B,eAAc;gBAASC,UAAU;0BACnCP,YAAYH,MAAM,KAAK,kBACtB,KAAChB;oBAAK4B,QAAQ;8BAAC;qBAEfT,YAAYU,GAAG,CAAC,CAACC,MAAMC,sBACrB,KAAC/B;wBAAuDgC,OAAM;kCAC3DF,KAAKG,IAAI;uBADD,CAAC,OAAO,EAAEF,MAAM,CAAC,EAAED,KAAKG,IAAI,CAAClB,KAAK,CAAC,GAAG,KAAK;;0BAQ5D,KAAChB;gBAAI2B,UAAU;0BACb,cAAA,KAAC1B;8BAAK;;;0BAIR,MAACA;;oBAAK;oBAAEW;oBAAQ;;;0BAChB,MAACZ;gBAAI2B,UAAU;gBAAGQ,gBAAe;;kCAC/B,KAAClC;wBAAK4B,QAAQ;kCAAC;;kCACf,KAAC5B;wBAAK4B,QAAQ;kCAAC;;;;0BAEjB,MAAC5B;;oBAAK;oBAAEW;oBAAQ;;;;;AAGtB,GAAG"}