project-compass 2.5.0 → 2.5.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 +33 -33
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "2.5.0",
3
+ "version": "2.5.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
@@ -366,11 +366,11 @@ function Compass({rootPath, initialView = 'navigator'}) {
366
366
  }
367
367
 
368
368
  if (key.shift && key.upArrow) {
369
- scrollLogs(-1);
369
+ scrollLogs(1);
370
370
  return;
371
371
  }
372
372
  if (key.shift && key.downArrow) {
373
- scrollLogs(1);
373
+ scrollLogs(-1);
374
374
  return;
375
375
  }
376
376
 
@@ -418,21 +418,18 @@ function Compass({rootPath, initialView = 'navigator'}) {
418
418
  }
419
419
  });
420
420
 
421
- if (mainView === 'studio') {
422
- return create(Studio);
423
- }
424
-
425
- const projectRows = [];
421
+ const projectCountLabel = `${projects.length} project${projects.length === 1 ? '' : 's'}`;
422
+ const projectRows = [];
426
423
  if (loading) {
427
- projectRows.push(create(Text, {dimColor: true}, 'Scanning projects…'));
424
+ projectRows.push(create(Text, {key: 'scanning', dimColor: true}, 'Scanning projects…'));
428
425
  }
429
426
  if (error) {
430
- projectRows.push(create(Text, {color: 'red'}, `Unable to scan: ${error}`));
427
+ projectRows.push(create(Text, {key: 'error', color: 'red'}, `Unable to scan: ${error}`));
431
428
  }
432
429
  if (!loading && !error && projects.length === 0) {
433
- projectRows.push(create(Text, {dimColor: true}, 'No recognizable project manifests found.'));
430
+ projectRows.push(create(Text, {key: 'empty', dimColor: true}, 'No recognizable project manifests found.'));
434
431
  }
435
- if (!loading) {
432
+ if (!loading && mainView === 'navigator') {
436
433
  projects.forEach((project, index) => {
437
434
  const isSelected = index === selectedIndex;
438
435
  const frameworkBadges = (project.frameworks || []).map((frame) => `${frame.icon} ${frame.name}`).join(', ');
@@ -466,59 +463,58 @@ const projectRows = [];
466
463
  detailContent.push(
467
464
  create(
468
465
  Box,
469
- {flexDirection: 'row'},
466
+ {key: 'title-row', flexDirection: 'row'},
470
467
  create(Text, {color: 'cyan', bold: true}, `${selectedProject.icon} ${selectedProject.name}`),
471
468
  selectedProject.missingBinaries && selectedProject.missingBinaries.length > 0 && create(Text, {color: 'red', bold: true}, ' ⚠️ MISSING RUNTIME')
472
469
  ),
473
- create(Text, {dimColor: true}, `${selectedProject.type} · ${selectedProject.manifest || 'detected manifest'}`),
474
- create(Text, {dimColor: true}, `Location: ${path.relative(rootPath, selectedProject.path) || '.'}`)
470
+ create(Text, {key: 'manifest', dimColor: true}, `${selectedProject.type} · ${selectedProject.manifest || 'detected manifest'}`),
471
+ create(Text, {key: 'loc', dimColor: true}, `Location: ${path.relative(rootPath, selectedProject.path) || '.'}`)
475
472
  );
476
473
  if (selectedProject.description) {
477
- detailContent.push(create(Text, null, selectedProject.description));
474
+ detailContent.push(create(Text, {key: 'desc'}, selectedProject.description));
478
475
  }
479
476
  const frameworks = (selectedProject.frameworks || []).map((lib) => `${lib.icon} ${lib.name}`).join(', ');
480
477
  if (frameworks) {
481
- detailContent.push(create(Text, {dimColor: true}, `Frameworks: ${frameworks}`));
478
+ detailContent.push(create(Text, {key: 'frames', dimColor: true}, `Frameworks: ${frameworks}`));
482
479
  }
483
480
  if (selectedProject.extra?.scripts && selectedProject.extra.scripts.length) {
484
- detailContent.push(create(Text, {dimColor: true}, `Scripts: ${selectedProject.extra.scripts.join(', ')}`));
481
+ detailContent.push(create(Text, {key: 'scripts', dimColor: true}, `Scripts: ${selectedProject.extra.scripts.join(', ')}`));
485
482
  }
486
483
 
487
484
  if (selectedProject.missingBinaries && selectedProject.missingBinaries.length > 0) {
488
485
  detailContent.push(
489
- create(Text, {color: 'red', bold: true, marginTop: 1}, 'MISSING BINARIES:'),
490
- create(Text, {color: 'red'}, `Please install: ${selectedProject.missingBinaries.join(', ')}`),
491
- create(Text, {dimColor: true}, 'Project commands may fail until these are in your PATH.')
486
+ create(Text, {key: 'missing-title', color: 'red', bold: true, marginTop: 1}, 'MISSING BINARIES:'),
487
+ create(Text, {key: 'missing-list', color: 'red'}, `Please install: ${selectedProject.missingBinaries.join(', ')}`),
488
+ create(Text, {key: 'missing-hint', dimColor: true}, 'Project commands may fail until these are in your PATH.')
492
489
  );
493
490
  }
494
491
 
495
- detailContent.push(create(Text, {dimColor: true, marginTop: 1}, `Custom commands stored in ${CONFIG_PATH}`));
496
- detailContent.push(create(Text, {dimColor: true, marginBottom: 1}, `Extend frameworks via ${PLUGIN_FILE}`));
497
- detailContent.push(create(Text, {bold: true, marginTop: 1}, 'Commands'));
492
+ detailContent.push(create(Text, {key: 'config-path', dimColor: true, marginTop: 1}, `Custom commands stored in ${CONFIG_PATH}`));
493
+ detailContent.push(create(Text, {key: 'plugin-path', dimColor: true, marginBottom: 1}, `Extend frameworks via ${PLUGIN_FILE}`));
494
+ detailContent.push(create(Text, {key: 'cmd-header', bold: true, marginTop: 1}, 'Commands'));
498
495
  detailedIndexed.forEach((command) => {
499
496
  detailContent.push(
500
497
  create(Text, {key: `detail-${command.shortcut}-${command.label}`}, `${command.shortcut}. ${command.label} ${command.source === 'custom' ? kleur.magenta('(custom)') : command.source === 'framework' ? kleur.cyan('(framework)') : command.source === 'plugin' ? kleur.green('(plugin)') : ''}`)
501
498
  );
502
- detailContent.push(create(Text, {dimColor: true}, ` ↳ ${command.command.join(' ')}`));
499
+ detailContent.push(create(Text, {key: `detail-line-${command.shortcut}-${command.label}`, dimColor: true}, ` ↳ ${command.command.join(' ')}`));
503
500
  });
504
501
  if (!detailedIndexed.length) {
505
- detailContent.push(create(Text, {dimColor: true}, 'No built-in commands yet. Add a custom command with Shift+C.'));
502
+ detailContent.push(create(Text, {key: 'no-cmds', dimColor: true}, 'No built-in commands yet. Add a custom command with Shift+C.'));
506
503
  }
507
504
  const setupHints = selectedProject.extra?.setupHints || [];
508
505
  if (setupHints.length) {
509
- detailContent.push(create(Text, {dimColor: true, marginTop: 1}, 'Setup hints:'));
510
- setupHints.forEach((hint) => detailContent.push(create(Text, {dimColor: true}, ` • ${hint}`)));
506
+ detailContent.push(create(Text, {key: 'setup-header', dimColor: true, marginTop: 1}, 'Setup hints:'));
507
+ setupHints.forEach((hint, hidx) => detailContent.push(create(Text, {key: `hint-${hidx}`, dimColor: true}, ` • ${hint}`)));
511
508
  }
512
- detailContent.push(create(Text, {dimColor: true}, 'Press Shift+C → label|cmd to save custom actions, Enter to close detail view.'));
509
+ detailContent.push(create(Text, {key: 'hint-line', dimColor: true}, 'Press Shift+C → label|cmd to save custom actions, Enter to close detail view.'));
513
510
  } else {
514
- detailContent.push(create(Text, {dimColor: true}, 'Press Enter on a project to reveal details (icons, commands, frameworks, custom actions).'));
511
+ detailContent.push(create(Text, {key: 'enter-hint', dimColor: true}, 'Press Enter on a project to reveal details (icons, commands, frameworks, custom actions).'));
515
512
  }
516
513
 
517
514
  if (customMode) {
518
- detailContent.push(create(Text, {color: 'cyan'}, `Type label|cmd (Enter to save, Esc to cancel): ${customInput}`));
515
+ detailContent.push(create(Text, {key: 'custom-input', color: 'cyan'}, `Type label|cmd (Enter to save, Esc to cancel): ${customInput}`));
519
516
  }
520
517
 
521
- const projectCountLabel = `${projects.length} project${projects.length === 1 ? '' : 's'}`;
522
518
  const artTileNodes = useMemo(() => {
523
519
  const selectedName = selectedProject?.name || 'Awaiting selection';
524
520
  const selectedType = selectedProject?.type || 'Unknown stack';
@@ -602,7 +598,7 @@ const projectRows = [];
602
598
  const visibleLogs = logLines.slice(logWindowStart, logWindowEnd);
603
599
  const logNodes = visibleLogs.length
604
600
  ? visibleLogs.map((line, index) => create(Text, {key: index}, line))
605
- : [create(Text, {dimColor: true}, 'Logs will appear here once you run a command.')];
601
+ : [create(Text, {key: 'no-logs', dimColor: true}, 'Logs will appear here once you run a command.')];
606
602
 
607
603
  const helpCards = [
608
604
  {
@@ -662,7 +658,7 @@ const projectRows = [];
662
658
  )
663
659
  )
664
660
  )
665
- : create(Text, {dimColor: true, marginTop: 1}, 'Help cards hidden · press Shift+H to show navigation, command flow, and recent runs.');
661
+ : create(Text, {key: 'help-hint', dimColor: true, marginTop: 1}, 'Help cards hidden · press Shift+H to show navigation, command flow, and recent runs.');
666
662
 
667
663
  const structureGuide = showStructureGuide
668
664
  ? create(
@@ -701,6 +697,10 @@ const projectRows = [];
701
697
  )
702
698
  : null;
703
699
 
700
+ if (mainView === 'studio') {
701
+ return create(Studio);
702
+ }
703
+
704
704
  const toggleHint = showHelpCards ? 'Shift+H hides the help cards' : 'Shift+H shows the help cards';
705
705
  const headerHint = viewMode === 'detail'
706
706
  ? `Detail mode · 1-${Math.max(detailedIndexed.length, 1)} to execute, Shift+C: add custom commands, Enter: back to list, Shift+Q: quit · ${toggleHint}, Shift+S toggles structure guide`