project-compass 3.2.0 β†’ 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +35 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "Ink-based project explorer that detects local repos and lets you build/test/run them without memorizing commands.",
5
5
  "main": "src/cli.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -147,6 +147,24 @@ const Studio = memo(() => {
147
147
  );
148
148
  });
149
149
 
150
+ const TaskManager = memo(({tasks, activeTaskId, renameMode, renameInput, renameCursor}) => {
151
+ return create(
152
+ Box,
153
+ {flexDirection: 'column', borderStyle: 'round', borderColor: 'yellow', padding: 1},
154
+ create(Text, {bold: true, color: 'yellow'}, 'πŸ›°οΈ Task Manager | Background Processes'),
155
+ create(Text, {dimColor: true, marginBottom: 1}, 'Up/Down: focus, Shift+K: Kill/Delete, Shift+R: Rename'),
156
+ ...tasks.map(t => create(
157
+ Box,
158
+ {key: t.id, marginBottom: 0, flexDirection: 'column'},
159
+ t.id === activeTaskId && renameMode
160
+ ? create(Box, {flexDirection: 'row'}, create(Text, {color: 'cyan'}, 'β†’ Rename to: '), create(CursorText, {value: renameInput, cursorIndex: renameCursor}))
161
+ : create(Text, {color: t.id === activeTaskId ? 'cyan' : 'white', bold: t.id === activeTaskId}, `${t.id === activeTaskId ? 'β†’' : ' '} [${t.status.toUpperCase()}] ${t.name}`)
162
+ )),
163
+ !tasks.length && create(Text, {dimColor: true}, 'No active or background tasks.'),
164
+ create(Text, {marginTop: 1, dimColor: true}, 'Press Enter or Shift+T to return to Navigator.')
165
+ );
166
+ });
167
+
150
168
  function CursorText({value, cursorIndex, active = true}) {
151
169
  const before = value.slice(0, cursorIndex);
152
170
  const charAt = value[cursorIndex] || ' ';
@@ -305,8 +323,8 @@ function Compass({rootPath, initialView = 'navigator'}) {
305
323
  const exportPath = path.resolve(process.cwd(), `compass-${activeTask.id}.txt`);
306
324
  fs.writeFileSync(exportPath, activeTask.logs.join('\n'));
307
325
  addLogToTask(activeTaskId, kleur.green(`βœ“ Logs exported to ${exportPath}`));
308
- } catch (err) {
309
- addLogToTask(activeTaskId, kleur.red(`βœ— Export failed: ${err.message}`));
326
+ } catch {
327
+ addLogToTask(activeTaskId, kleur.red('βœ— Export failed'));
310
328
  }
311
329
  }, [activeTask, activeTaskId, addLogToTask]);
312
330
 
@@ -490,36 +508,12 @@ function Compass({rootPath, initialView = 'navigator'}) {
490
508
  }
491
509
  });
492
510
 
493
- const projectCountLabel = `${projects.length} project${projects.length === 1 ? '' : 's'}`;
511
+ const projectCountLabel = useMemo(() => `${projects.length} project${projects.length === 1 ? '' : 's'}`, [projects.length]);
494
512
  const toggleHint = config.showHelpCards ? 'Shift+H hide help' : 'Shift+H show help';
495
513
  const statusHint = activeTask ? `[${activeTask.status.toUpperCase()}] ${activeTask.name}` : 'Idle Navigator';
496
514
  const orbitHint = mainView === 'tasks' ? 'Tasks View' : `Orbit: ${tasks.length} tasks`;
497
515
  const artHint = config.showArtBoard ? 'Shift+B hide art' : 'Shift+B show art';
498
516
 
499
- if (quitConfirm) {
500
- return create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'red', padding: 1}, create(Text, {bold: true, color: 'red'}, '⚠️ Confirm Exit'), create(Text, null, `There are ${tasks.filter(t=>t.status==='running').length} tasks still running in the background.`), create(Text, null, 'Are you sure you want to quit and stop all processes?'), create(Text, {marginTop: 1}, kleur.bold('Y') + ' to Quit, ' + kleur.bold('N') + ' to Cancel'));
501
- }
502
-
503
- if (mainView === 'studio') return create(Studio);
504
-
505
- if (mainView === 'tasks') {
506
- return create(
507
- Box,
508
- {flexDirection: 'column', borderStyle: 'round', borderColor: 'yellow', padding: 1},
509
- create(Text, {bold: true, color: 'yellow'}, 'πŸ›°οΈ Task Manager | Background Processes'),
510
- create(Text, {dimColor: true, marginBottom: 1}, 'Up/Down: focus, Shift+K: Kill/Delete, Shift+R: Rename'),
511
- ...tasks.map(t => create(
512
- Box,
513
- {key: t.id, marginBottom: 0, flexDirection: 'column'},
514
- t.id === activeTaskId && renameMode
515
- ? create(Box, {flexDirection: 'row'}, create(Text, {color: 'cyan'}, 'β†’ Rename to: '), create(CursorText, {value: renameInput, cursorIndex: renameCursor}))
516
- : create(Text, {color: t.id === activeTaskId ? 'cyan' : 'white', bold: t.id === activeTaskId}, `${t.id === activeTaskId ? 'β†’' : ' '} [${t.status.toUpperCase()}] ${t.name}`)
517
- )),
518
- !tasks.length && create(Text, {dimColor: true}, 'No active or background tasks.'),
519
- create(Text, {marginTop: 1, dimColor: true}, 'Press Enter or Shift+T to return to Navigator.')
520
- );
521
- }
522
-
523
517
  const projectRows = useMemo(() => {
524
518
  if (loading) return [create(Text, {key: 'scanning', dimColor: true}, 'Scanning projects…')];
525
519
  if (error) return [create(Text, {key: 'error', color: 'red'}, `Unable to scan: ${error}`)];
@@ -582,25 +576,26 @@ function Compass({rootPath, initialView = 'navigator'}) {
582
576
  const artTileNodes = useMemo(() => [
583
577
  {label: 'Pulse', detail: projectCountLabel, accent: 'magenta', icon: '●', subtext: `Workspace Β· ${path.basename(rootPath) || rootPath}`},
584
578
  {label: 'Focus', detail: selectedProject?.name || 'Selection', accent: 'cyan', icon: 'β—†', subtext: `${selectedProject?.type || 'Stack'}`},
585
- {label: 'Orbit', detail: `${tasks.length} active tasks`, accent: 'yellow', icon: 'β– ', subtext: running ? 'Busy streaming...' : 'Idle'}
579
+ {label: 'Orbit', detail: `${tasks.length} tasks`, accent: 'yellow', icon: 'β– ', subtext: running ? 'Busy streaming...' : 'Idle'}
586
580
  ].map(tile => create(Box, {key: tile.label, flexDirection: 'column', padding: 1, marginRight: 1, borderStyle: 'single', borderColor: tile.accent, minWidth: 24},
587
581
  create(Text, {color: tile.accent, bold: true}, `${tile.icon} ${tile.label}`),
588
582
  create(Text, {bold: true}, tile.detail),
589
583
  create(Text, {dimColor: true}, tile.subtext)
590
584
  )), [projectCountLabel, rootPath, selectedProject, tasks.length, running]);
591
585
 
592
- const artBoard = config.showArtBoard ? create(Box, {flexDirection: 'column', marginTop: 1, borderStyle: 'round', borderColor: 'gray', padding: 1},
593
- create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {color: 'magenta', bold: true}, 'Art-coded build atlas'), create(Text, {dimColor: true}, 'press ? for overlay help')),
594
- create(Box, {flexDirection: 'row', marginTop: 1}, ...ART_CHARS.map((char, i) => create(Text, {key: i, color: ART_COLORS[i % ART_COLORS.length]}, char.repeat(2)))),
595
- create(Box, {flexDirection: 'row', marginTop: 1}, ...artTileNodes)
596
- ) : null;
597
-
598
586
  const helpCards = [
599
587
  {label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
600
588
  {label: 'Commands', color: 'cyan', body: ['B / T / R build/test/run', '1-9 run detail commands', 'Shift+L rerun last command', 'Shift+X clear / Shift+E export']},
601
- {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+C custom / Shift+Q quit']}
589
+ {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
602
590
  ];
603
591
 
592
+ if (quitConfirm) {
593
+ return create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'red', padding: 1}, create(Text, {bold: true, color: 'red'}, '⚠️ Confirm Exit'), create(Text, null, `There are ${tasks.filter(t=>t.status==='running').length} tasks still running in the background.`), create(Text, null, 'Are you sure you want to quit and stop all processes?'), create(Text, {marginTop: 1}, kleur.bold('Y') + ' to Quit, ' + kleur.bold('N') + ' to Cancel'));
594
+ }
595
+
596
+ if (mainView === 'studio') return create(Studio);
597
+ if (mainView === 'tasks') return create(TaskManager, {tasks, activeTaskId, renameMode, renameInput, renameCursor});
598
+
604
599
  return create(Box, {flexDirection: 'column', padding: 1},
605
600
  create(Box, {justifyContent: 'space-between'},
606
601
  create(Box, {flexDirection: 'column'}, create(Text, {color: 'magenta', bold: true}, 'Project Compass'), create(Text, {dimColor: true}, `${projectCountLabel} detected in ${rootPath}`)),
@@ -609,7 +604,11 @@ function Compass({rootPath, initialView = 'navigator'}) {
609
604
  create(Text, {dimColor: true}, `${toggleHint} Β· ${orbitHint} Β· ${artHint} Β· Shift+Q: Quit`)
610
605
  )
611
606
  ),
612
- artBoard,
607
+ config.showArtBoard && create(Box, {flexDirection: 'column', marginTop: 1, borderStyle: 'round', borderColor: 'gray', padding: 1},
608
+ create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {color: 'magenta', bold: true}, 'Art-coded build atlas'), create(Text, {dimColor: true}, 'press ? for overlay help')),
609
+ create(Box, {flexDirection: 'row', marginTop: 1}, ...ART_CHARS.map((char, i) => create(Text, {key: i, color: ART_COLORS[i % ART_COLORS.length]}, char.repeat(2)))),
610
+ create(Box, {flexDirection: 'row', marginTop: 1}, ...artTileNodes)
611
+ ),
613
612
  create(Box, {marginTop: 1, flexDirection: 'row', alignItems: 'stretch', width: '100%', flexWrap: 'wrap'},
614
613
  create(Box, {flexGrow: 1, flexBasis: 0, minWidth: PROJECTS_MIN_WIDTH, marginRight: 1, borderStyle: 'round', borderColor: 'magenta', padding: 1}, create(Text, {bold: true, color: 'magenta'}, 'Projects'), create(Box, {flexDirection: 'column', marginTop: 1}, ...projectRows)),
615
614
  create(Box, {flexGrow: 1.3, flexBasis: 0, minWidth: DETAILS_MIN_WIDTH, borderStyle: 'round', borderColor: 'cyan', padding: 1, flexDirection: 'column'}, create(Text, {bold: true, color: 'cyan'}, 'Details'), ...detailContent)