project-compass 3.4.3 → 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 +1 -1
- package/src/cli.js +14 -15
- package/src/components/ProjectArchitect.js +67 -40
- package/src/components/Studio.js +2 -3
package/package.json
CHANGED
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
|
}
|
|
@@ -455,10 +450,12 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
455
450
|
return;
|
|
456
451
|
}
|
|
457
452
|
if (viewMode === 'detail' && normalizedInput && detailShortcutMap.has(normalizedInput)) {
|
|
458
|
-
if (
|
|
453
|
+
if (!isNaN(parseInt(normalizedInput))) {
|
|
459
454
|
runProjectCommand(detailShortcutMap.get(normalizedInput), selectedProject);
|
|
460
455
|
return;
|
|
461
|
-
}
|
|
456
|
+
}
|
|
457
|
+
const reserved = ['a', 'p', 'n', 'x', 'e', 'd', 'b', 't', 'q', 'h', 's', 'l', 'c'];
|
|
458
|
+
if (key.shift && !reserved.includes(normalizedInput)) {
|
|
462
459
|
runProjectCommand(detailShortcutMap.get(normalizedInput), selectedProject);
|
|
463
460
|
return;
|
|
464
461
|
}
|
|
@@ -540,6 +537,12 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
540
537
|
create(Text, {dimColor: true}, tile.subtext)
|
|
541
538
|
)), [projectCountLabel, rootPath, selectedProject, tasks.length, running]);
|
|
542
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
|
+
|
|
543
546
|
if (quitConfirm) {
|
|
544
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'));
|
|
545
548
|
}
|
|
@@ -547,7 +550,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
547
550
|
if (mainView === 'studio') return create(Studio);
|
|
548
551
|
if (mainView === 'tasks') return create(TaskManager, {tasks, activeTaskId, setActiveTaskId, renameMode, renameInput, renameCursor, CursorText});
|
|
549
552
|
if (mainView === 'registry') return create(PackageRegistry, {selectedProject, onRunCommand: runProjectCommand, CursorText});
|
|
550
|
-
if (mainView === 'architect') return create(ProjectArchitect, {onRunCommand: runProjectCommand, CursorText});
|
|
553
|
+
if (mainView === 'architect') return create(ProjectArchitect, {rootPath, onRunCommand: runProjectCommand, CursorText, onReturn: () => setMainView('navigator')});
|
|
551
554
|
|
|
552
555
|
return create(Box, {flexDirection: 'column', padding: 1},
|
|
553
556
|
create(Box, {justifyContent: 'space-between'},
|
|
@@ -570,13 +573,9 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
570
573
|
create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {bold: true, color: 'yellow'}, `Output: ${activeTask?.name || 'None'}`), create(Text, {dimColor: true}, logOffset ? `Scrolled ${logOffset} lines` : 'Live log view')),
|
|
571
574
|
create(OutputPanel, {activeTask, logOffset}),
|
|
572
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`)),
|
|
573
|
-
create(Box, {marginTop: 1, flexDirection: 'row', borderStyle: 'round', borderColor: running ? 'green' : 'gray', paddingX: 1}, create(Text, {bold: true, color: 'green'}, 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
|
+
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})))
|
|
574
577
|
),
|
|
575
|
-
config.showHelpCards && create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'},
|
|
576
|
-
{label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
|
|
577
|
-
{label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
|
|
578
|
-
{label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
|
|
579
|
-
].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))))),
|
|
580
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(', ')}`))),
|
|
581
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.'))
|
|
582
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('
|
|
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 (
|
|
33
|
+
if (step === 'path') {
|
|
34
|
+
setStep('name');
|
|
35
|
+
setCursor(0);
|
|
36
|
+
} else if (name.trim()) {
|
|
32
37
|
const f = frameworks[selectedIdx];
|
|
33
|
-
onRunCommand({
|
|
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) {
|
|
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
|
-
|
|
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(
|
|
64
|
+
if (key.rightArrow) { setCursor(c => Math.min(val.length, c + 1)); return; }
|
|
48
65
|
if (inputStr) {
|
|
49
|
-
|
|
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 |
|
|
59
|
-
create(Text, {dimColor: true, marginBottom: 1}, '
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
package/src/components/Studio.js
CHANGED
|
@@ -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,
|
|
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
|
});
|