project-compass 3.4.4 → 3.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "3.4.4",
3
+ "version": "3.5.0",
4
4
  "description": "Futuristic project navigator and runner for Node, Python, Rust, and Go",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -399,7 +399,6 @@ function Compass({rootPath, initialView = 'navigator'}) {
399
399
  }
400
400
 
401
401
  if (mainView === 'registry' || mainView === 'architect') {
402
- // Inputs handled inside components
403
402
  return;
404
403
  }
405
404
 
@@ -438,11 +437,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
438
437
  setViewMode((prev) => (prev === 'detail' ? 'list' : 'detail'));
439
438
  return;
440
439
  }
441
- if (shiftCombo('q')) {
442
- if (hasRunningTasks) setQuitConfirm(true); else exit();
443
- return;
444
- }
445
- if (isCtrlC) {
440
+ if (shiftCombo('q') || isCtrlC) {
446
441
  if (hasRunningTasks) setQuitConfirm(true); else exit();
447
442
  return;
448
443
  }
@@ -542,14 +537,20 @@ function Compass({rootPath, initialView = 'navigator'}) {
542
537
  create(Text, {dimColor: true}, tile.subtext)
543
538
  )), [projectCountLabel, rootPath, selectedProject, tasks.length, running]);
544
539
 
540
+ const helpCards = useMemo(() => [
541
+ {label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
542
+ {label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
543
+ {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
544
+ ], []);
545
+
545
546
  if (quitConfirm) {
546
547
  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'));
547
548
  }
548
549
 
549
550
  if (mainView === 'studio') return create(Studio);
550
- if (mainView === 'tasks') return create(TaskManager, {tasks, activeTaskId, renameMode, renameInput, renameCursor, CursorText});
551
+ if (mainView === 'tasks') return create(TaskManager, {tasks, activeTaskId, setActiveTaskId, renameMode, renameInput, renameCursor, CursorText});
551
552
  if (mainView === 'registry') return create(PackageRegistry, {selectedProject, onRunCommand: runProjectCommand, CursorText});
552
- if (mainView === 'architect') return create(ProjectArchitect, {onRunCommand: runProjectCommand, CursorText});
553
+ if (mainView === 'architect') return create(ProjectArchitect, {rootPath, onRunCommand: runProjectCommand, CursorText, onReturn: () => setMainView('navigator')});
553
554
 
554
555
  return create(Box, {flexDirection: 'column', padding: 1},
555
556
  create(Box, {justifyContent: 'space-between'},
@@ -574,11 +575,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
574
575
  create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {dimColor: true}, running ? 'Type to feed stdin; Enter: submit.' : 'Run a command or press Shift+T to switch tasks.'), create(Text, {dimColor: true}, `${toggleHint}, Shift+S: Structure Guide`)),
575
576
  create(Box, {marginTop: 1, flexDirection: 'row', borderStyle: 'round', borderColor: running ? 'green' : 'gray', paddingX: 1}, create(Text, {bold: true, color: running ? 'green' : 'white'}, running ? ' Stdin buffer ' : ' Input ready '), create(Box, {marginLeft: 1}, create(CursorText, {value: stdinBuffer || (running ? '' : 'Start a command to feed stdin'), cursorIndex: stdinCursor, active: running})))
576
577
  ),
577
- config.showHelpCards && create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, [
578
- {label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
579
- {label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
580
- {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
581
- ].map((card, idx) => create(Box, {key: card.label, flexGrow: 1, flexBasis: 0, minWidth: HELP_CARD_MIN_WIDTH, marginRight: idx < 2 ? 1 : 0, marginBottom: 1, borderStyle: 'round', borderColor: card.color, padding: 1, flexDirection: 'column'}, create(Text, {color: card.color, bold: true, marginBottom: 1}, card.label), ...card.body.map((line, lidx) => create(Text, {key: lidx, dimColor: card.color === 'yellow'}, line))))),
578
+ config.showHelpCards && create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, helpCards.map((card, idx) => create(Box, {key: card.label, flexGrow: 1, flexBasis: 0, minWidth: HELP_CARD_MIN_WIDTH, marginRight: idx < 2 ? 1 : 0, marginBottom: 1, borderStyle: 'round', borderColor: card.color, padding: 1, flexDirection: 'column'}, create(Text, {color: card.color, bold: true, marginBottom: 1}, card.label), ...card.body.map((line, lidx) => create(Text, {key: lidx, dimColor: card.color === 'yellow'}, line))))),
582
579
  config.showStructureGuide && create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'blue', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Structure guide · press Shift+S to hide'), ...SCHEMA_GUIDE.map(e => create(Text, {key: e.type, dimColor: true}, `• ${e.icon} ${e.label}: ${e.files.join(', ')}`))),
583
580
  showHelp && create(Box, {flexDirection: 'column', borderStyle: 'double', borderColor: 'cyan', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Help overlay'), create(Text, null, 'Shift+↑/↓ scrolls logs; Shift+X clears; Shift+E exports; Shift+A Studio; Shift+T Tasks; Shift+D Detach; Shift+B Toggle Art Board; Shift+P Packages; Shift+N Creator.'))
584
581
  );
@@ -1,52 +1,69 @@
1
1
  import React, {useState, memo} from 'react';
2
2
  import {Box, Text, useInput} from 'ink';
3
+ import path from 'path';
3
4
 
4
5
  const create = React.createElement;
5
6
 
6
- const ProjectArchitect = memo(({onRunCommand, CursorText}) => {
7
- const [step, setStep] = useState('framework'); // framework | name
7
+ const ProjectArchitect = memo(({rootPath, onRunCommand, CursorText, onReturn}) => {
8
+ const [step, setStep] = useState('framework'); // framework | path | name
8
9
  const [selectedIdx, setSelectedIdx] = useState(0);
10
+ const [targetPath, setTargetPath] = useState(rootPath);
9
11
  const [name, setName] = useState('');
10
12
  const [cursor, setCursor] = useState(0);
11
13
 
12
14
  const frameworks = [
13
- {name: 'Next.js', cmd: (n) => ['npx', 'create-next-app@latest', n]},
14
- {name: 'React (Vite)', cmd: (n) => ['npm', 'create', 'vite@latest', n, '--', '--template', 'react']},
15
- {name: 'Vue (Vite)', cmd: (n) => ['npm', 'create', 'vite@latest', n, '--', '--template', 'vue']},
16
- {name: 'Rust (Binary)', cmd: (n) => ['cargo', 'new', n]},
17
- {name: 'Python (Basic)', cmd: (n) => ['mkdir', n]},
18
- {name: 'Go Module', cmd: (n) => ['mkdir', n, '&&', 'cd', n, '&&', 'go', 'mod', 'init', n]}
15
+ {name: 'Next.js', cmd: (p, n) => ['npx', 'create-next-app@latest', path.join(p, n)]},
16
+ {name: 'React (Vite)', cmd: (p, n) => ['npm', 'create', 'vite@latest', path.join(p, n), '--', '--template', 'react']},
17
+ {name: 'Vue (Vite)', cmd: (p, n) => ['npm', 'create', 'vite@latest', path.join(p, n), '--', '--template', 'vue']},
18
+ {name: 'Rust (Binary)', cmd: (p, n) => ['cargo', 'new', path.join(p, n)]},
19
+ {name: 'Python (Basic)', cmd: (p, n) => ['mkdir', '-p', path.join(p, n)]},
20
+ {name: 'Go Module', cmd: (p, n) => ['mkdir', '-p', path.join(p, n), '&&', 'cd', path.join(p, n), '&&', 'go', 'mod', 'init', n]}
19
21
  ];
20
22
 
21
23
  useInput((inputStr, key) => {
22
24
  if (step === 'framework') {
23
25
  if (key.upArrow) setSelectedIdx(prev => (prev - 1 + frameworks.length) % frameworks.length);
24
26
  if (key.downArrow) setSelectedIdx(prev => (prev + 1) % frameworks.length);
25
- if (key.return) setStep('name');
27
+ if (key.return) setStep('path');
26
28
  return;
27
29
  }
28
30
 
29
- if (step === 'name') {
31
+ if (step === 'path' || step === 'name') {
30
32
  if (key.return) {
31
- if (name.trim()) {
33
+ if (step === 'path') {
34
+ setStep('name');
35
+ setCursor(0);
36
+ } else if (name.trim()) {
32
37
  const f = frameworks[selectedIdx];
33
- onRunCommand({label: `Create ${f.name} project: ${name}`, command: f.cmd(name.trim())});
38
+ onRunCommand({
39
+ label: `Scaffold ${f.name}: ${name}`,
40
+ command: f.cmd(targetPath, name.trim())
41
+ });
42
+ onReturn();
34
43
  }
35
- setStep('framework'); setName(''); setCursor(0);
36
44
  return;
37
45
  }
38
- if (key.escape) { setStep('framework'); setName(''); setCursor(0); return; }
46
+ if (key.escape) {
47
+ if (step === 'name') setStep('path');
48
+ else setStep('framework');
49
+ setCursor(0);
50
+ return;
51
+ }
52
+
53
+ const val = step === 'path' ? targetPath : name;
54
+ const setVal = step === 'path' ? setTargetPath : setName;
55
+
39
56
  if (key.backspace || key.delete) {
40
57
  if (cursor > 0) {
41
- setName(prev => prev.slice(0, cursor - 1) + prev.slice(cursor));
58
+ setVal(prev => prev.slice(0, cursor - 1) + prev.slice(cursor));
42
59
  setCursor(c => Math.max(0, c - 1));
43
60
  }
44
61
  return;
45
62
  }
46
63
  if (key.leftArrow) { setCursor(c => Math.max(0, c - 1)); return; }
47
- if (key.rightArrow) { setCursor(c => Math.min(name.length, c + 1)); return; }
64
+ if (key.rightArrow) { setCursor(c => Math.min(val.length, c + 1)); return; }
48
65
  if (inputStr) {
49
- setName(prev => prev.slice(0, cursor) + inputStr + prev.slice(cursor));
66
+ setVal(prev => prev.slice(0, cursor) + inputStr + prev.slice(cursor));
50
67
  setCursor(c => c + inputStr.length);
51
68
  }
52
69
  }
@@ -54,29 +71,39 @@ const ProjectArchitect = memo(({onRunCommand, CursorText}) => {
54
71
 
55
72
  return create(
56
73
  Box,
57
- {flexDirection: 'column', borderStyle: 'round', borderColor: 'cyan', padding: 1},
58
- create(Text, {bold: true, color: 'cyan'}, '🏗️ Project Architect | Generator'),
59
- create(Text, {dimColor: true, marginBottom: 1}, 'Create new projects from industry-standard templates.'),
60
- step === 'framework'
61
- ? create(
62
- Box,
63
- {flexDirection: 'column'},
64
- create(Text, {bold: true}, 'Select Framework:'),
65
- ...frameworks.map((f, i) => create(Text, {key: f.name, color: i === selectedIdx ? 'cyan' : 'white'}, `${i === selectedIdx ? '→' : ' '} ${f.name}`)),
66
- create(Text, {dimColor: true, marginTop: 1}, 'Enter: Pick Framework, Shift+N: Return to Navigator.')
67
- )
68
- : create(
69
- Box,
70
- {flexDirection: 'column'},
71
- create(Text, {bold: true, color: 'cyan'}, 'PROJECT NAME'),
72
- create(
73
- Box,
74
- {flexDirection: 'row'},
75
- create(Text, null, 'Enter name: '),
76
- create(CursorText, {value: name, cursorIndex: cursor})
77
- ),
78
- create(Text, {dimColor: true, marginTop: 1}, 'Enter: Create Project, Esc: Back to Frameworks')
79
- )
74
+ {flexDirection: 'column', borderStyle: 'round', borderColor: 'cyan', padding: 1, width: '100%'},
75
+ create(Text, {bold: true, color: 'cyan'}, '🏗️ Project Architect | Scaffold New Workspace'),
76
+ create(Text, {dimColor: true, marginBottom: 1}, 'Generator will run in the background via Orbit.'),
77
+
78
+ step === 'framework' && create(
79
+ Box,
80
+ {flexDirection: 'column'},
81
+ create(Text, {bold: true, marginBottom: 1}, 'Step 1: Select Template'),
82
+ ...frameworks.map((f, i) => create(Text, {key: f.name, color: i === selectedIdx ? 'cyan' : 'white'}, `${i === selectedIdx ? '→' : ' '} ${f.name}`)),
83
+ create(Text, {dimColor: true, marginTop: 1}, 'Enter: Confirm Template, Shift+N: Exit')
84
+ ),
85
+
86
+ step === 'path' && create(
87
+ Box,
88
+ {flexDirection: 'column'},
89
+ create(Text, {bold: true, color: 'yellow', marginBottom: 1}, `Step 2: Target Directory [${frameworks[selectedIdx].name}]`),
90
+ create(Box, {flexDirection: 'row'},
91
+ create(Text, null, 'Root Path: '),
92
+ create(CursorText, {value: targetPath, cursorIndex: cursor})
93
+ ),
94
+ create(Text, {dimColor: true, marginTop: 1}, 'Enter: Confirm Path, Esc: Back')
95
+ ),
96
+
97
+ step === 'name' && create(
98
+ Box,
99
+ {flexDirection: 'column'},
100
+ create(Text, {bold: true, color: 'green', marginBottom: 1}, `Step 3: Project Name`),
101
+ create(Box, {flexDirection: 'row'},
102
+ create(Text, null, 'Name: '),
103
+ create(CursorText, {value: name, cursorIndex: cursor})
104
+ ),
105
+ create(Text, {dimColor: true, marginTop: 1}, 'Enter: Create Project, Esc: Back')
106
+ )
80
107
  );
81
108
  });
82
109
 
@@ -42,7 +42,7 @@ const Studio = memo(() => {
42
42
 
43
43
  return create(
44
44
  Box,
45
- {flexDirection: 'column', borderStyle: 'double', borderColor: 'blue', padding: 1},
45
+ {flexDirection: 'column', borderStyle: 'double', borderColor: 'blue', padding: 1, width: '100%'},
46
46
  create(Text, {bold: true, color: 'blue'}, '💎 Omni-Studio | Environment Intelligence'),
47
47
  create(Text, {dimColor: true, marginBottom: 1}, 'Overview of installed languages and build tools.'),
48
48
  loading
@@ -56,8 +56,7 @@ const Studio = memo(() => {
56
56
  create(Text, {width: 20, color: r.status === 'ok' ? 'green' : 'red'}, `${r.status === 'ok' ? '✓' : '✗'} ${r.name}`),
57
57
  create(Text, {dimColor: r.status !== 'ok'}, `: ${r.version}`)
58
58
  )),
59
- create(Text, {marginTop: 1, color: 'yellow'}, '🛠️ Interactive Project Creator coming soon in v3.0'),
60
- create(Text, {dimColor: true}, 'Press Shift+A to return to Navigator.')
59
+ create(Text, {marginTop: 1, dimColor: true}, 'Press Shift+A to return to Navigator.')
61
60
  )
62
61
  );
63
62
  });