@aemonge-dev/pi-stardeck 0.7.0 → 0.7.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aemonge-dev/pi-stardeck",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "A Vim- and tmux-inspired command deck for Pi",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -421,7 +421,15 @@ function companionIconColor(text: string | undefined, active: boolean): string {
421
421
  : 'accent';
422
422
  }
423
423
 
424
- function extensionStatusCodes(state: HeaderDeckState, theme: Theme): string {
424
+ function identityCluster(
425
+ state: HeaderDeckState,
426
+ theme: Theme,
427
+ ): { text: string; trailingBare: boolean } {
428
+ // Line-1 corner identity: devbox lead chip, then the companion chips.
429
+ // Returns the assembled text plus whether the last chip is bare — bare
430
+ // chips keep the wide gap to their right (0.7.1 amendment: the major
431
+ // separator rides double-spaced after a bare trailing chip, matching
432
+ // the bare→bare chip spacing).
425
433
  const texts = new Map<string, string>();
426
434
  for (const item of state.piStatus?.nativeStatuses ?? []) {
427
435
  if (item.key === 'goal' || texts.has(item.key)) continue;
@@ -452,14 +460,14 @@ function extensionStatusCodes(state: HeaderDeckState, theme: Theme): string {
452
460
  ),
453
461
  });
454
462
  }
455
- let out = '';
456
- let previousBare = false;
463
+ let text = '';
464
+ let trailingBare = false;
457
465
  for (const part of parts) {
458
- out +=
459
- out === '' ? part.text : `${previousBare && part.bare ? ' ' : ' '}${part.text}`;
460
- previousBare = part.bare;
466
+ text +=
467
+ text === '' ? part.text : `${trailingBare && part.bare ? ' ' : ' '}${part.text}`;
468
+ trailingBare = part.bare;
461
469
  }
462
- return out;
470
+ return { text, trailingBare };
463
471
  }
464
472
 
465
473
  const BLOCKED_NOTICE = '\u26d4 blocked';
@@ -569,22 +577,26 @@ function deckCornerRight(
569
577
  nowMs = Date.now(),
570
578
  ): string {
571
579
  // Line 1 corner: the identity cluster (devbox lead, companion chips)
572
- // split from the machine group by one major separator. Machine segments
573
- // yield right-to-left (cost first) before the path truncates below a
574
- // 20-column floor; the identity cluster never drops (always-visible
575
- // contract).
576
- const identity = extensionStatusCodes(state, theme);
580
+ // split from the machine group by one major separator. A bare trailing
581
+ // chip keeps the wide gap before the separator (0.7.1 amendment);
582
+ // machine segments yield right-to-left (cost first) before the path
583
+ // truncates below a 20-column floor; the identity cluster never drops
584
+ // (always-visible contract).
585
+ const identity = identityCluster(state, theme);
577
586
  const segments = machineCornerSegments(state, theme, nowMs);
578
587
  const pathFloor = 20;
588
+ const cornerGap = identity.trailingBare ? ' ' : ' ';
579
589
  for (let keep = segments.length; keep >= 0; keep -= 1) {
580
590
  const tail = segments.slice(0, keep).join(` ${minorSeparator(theme)} `);
581
591
  const corner =
582
- tail === '' ? identity : `${identity} ${semanticSeparator(theme)} ${tail}`;
592
+ tail === ''
593
+ ? identity.text
594
+ : `${identity.text}${cornerGap}${semanticSeparator(theme)} ${tail}`;
583
595
  if (keep === 0 || width - visibleWidth(corner) - 1 >= pathFloor) {
584
596
  return corner;
585
597
  }
586
598
  }
587
- return identity;
599
+ return identity.text;
588
600
  }
589
601
 
590
602
  function modelGroupLeft(state: HeaderDeckState, theme: Theme): string {
@@ -802,12 +814,15 @@ export function renderHeaderDeck(
802
814
  // row's left end; the right end is notice-only. The machine group moved
803
815
  // to the line-1 corner, so notices can no longer starve machine
804
816
  // readings — the old wholesale yield is gone with the group itself.
817
+ // 0.7.1 amendment: a clean notice slot renders the dim `healthy`
818
+ // placeholder instead of trailing silence — it yields like a notice
819
+ // when the engine group needs the width.
805
820
  const engineGroup = telemetryRowLeft(state, theme);
806
821
  const noticeGroup = noticeTile(state, theme);
822
+ const rightGroup = noticeGroup !== '' ? noticeGroup : color(theme, 'dim', 'healthy');
807
823
  const telemetryRow =
808
- noticeGroup !== '' &&
809
- visibleWidth(engineGroup) + 1 + visibleWidth(noticeGroup) <= boundedWidth
810
- ? alignedSingleRow(engineGroup, noticeGroup, boundedWidth)
824
+ visibleWidth(engineGroup) + 1 + visibleWidth(rightGroup) <= boundedWidth
825
+ ? alignedSingleRow(engineGroup, rightGroup, boundedWidth)
811
826
  : fit(engineGroup, boundedWidth);
812
827
 
813
828
  // Band adjacency (Human-directed, accepted mockups; third 2.4