tmux-ide 2.9.0-beta.37 → 2.9.0-beta.38

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/bin/cli.js CHANGED
@@ -11279,7 +11279,7 @@ var require_package = __commonJS({
11279
11279
  "package.json"(exports, module) {
11280
11280
  module.exports = {
11281
11281
  name: "tmux-ide",
11282
- version: "2.9.0-beta.37",
11282
+ version: "2.9.0-beta.38",
11283
11283
  description: "A visual, agent-aware IDE for any tmux session, with optional workspace presets",
11284
11284
  type: "module",
11285
11285
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-ide",
3
- "version": "2.9.0-beta.37",
3
+ "version": "2.9.0-beta.38",
4
4
  "description": "A visual, agent-aware IDE for any tmux session, with optional workspace presets",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,6 +6,7 @@ import { fleetConnectionMessage, } from "@tmux-ide/daemon-client/fleet-connectio
6
6
  import { terminalAgentStatusLabel } from "./application-terminal-workspace-policy.js";
7
7
  import { For, Show, createEffect, createMemo, createSignal, } from "solid-js";
8
8
  import { clipTerminal, friendlySessionLabel } from "../terminal-text.js";
9
+ import { KeyHint } from "../ui/key-hint.jsx";
9
10
  import { NavigationRow } from "../ui/navigation-row.jsx";
10
11
  import { Surface } from "../ui/surface.jsx";
11
12
  import { useKeyboardRoute } from "../ui/keyboard-router.jsx";
@@ -302,10 +303,14 @@ export function ApplicationMachineSidebar(props) {
302
303
  return true;
303
304
  });
304
305
  return (<Surface id="application-machine-sidebar" theme={props.theme} variant="panel" width={props.width} height={props.height} flexShrink={0} flexDirection="column" overflow="hidden">
305
- <text height={1} fg={props.theme.roles.text.secondary}>
306
- {" "}
307
- {props.model.tabs?.().length ? "Machines · F9 tabs · ?" : "Machines · ? help"}
308
- </text>
306
+ <box height={1} flexShrink={0} flexDirection="row" overflow="hidden">
307
+ <text fg={props.theme.roles.text.secondary}>{" Machines"}</text>
308
+ <box flexGrow={1}/>
309
+ <Show when={props.model.tabs?.().length && props.width >= 28}>
310
+ <KeyHint theme={props.theme} keys="F9" label="Tabs" quiet/>
311
+ </Show>
312
+ <KeyHint theme={props.theme} keys="?" label={props.width >= 20 ? "Help" : undefined} quiet button onPress={() => setShowHelp(!showHelp())}/>
313
+ </box>
309
314
  <For each={visibleTabs()}>
310
315
  {(tab) => (<box height={1} flexDirection="row">
311
316
  <NavigationRow theme={props.theme} width={Math.max(1, props.width - 4)} id={`fleet-tab:${tab.key}`} label={`${tab.hostLabel} / ${tab.label}`} marker={tab.active ? "●" : "○"} detail={tab.available ? "" : "offline"} focused={false} onActivate={() => props.model.onOpenTab?.(tab.key)}/>
@@ -417,10 +422,10 @@ export function ApplicationMachineSidebar(props) {
417
422
  </text>
418
423
  </Show>
419
424
  <Show when={props.model.onOpenSwitcher}>
420
- <NavigationRow theme={props.theme} id="machine:switcher" label="Sessions" detail="F6" marker=" " width={props.width} onActivate={() => props.model.onOpenSwitcher?.()}/>
425
+ <KeyHint theme={props.theme} keys="F6" label="Sessions" width={props.width} quiet button onPress={() => props.model.onOpenSwitcher?.()}/>
421
426
  </Show>
422
427
  <Show when={props.model.onOpenAttention}>
423
- <NavigationRow theme={props.theme} id="machine:attention" label={`Attention (${props.model.groups().reduce((sum, group) => sum + (group.state === "ready" ? (group.agents ?? []).filter((agent) => agent.attention && !agent.disabled).length : 0), 0)}) · F7`} marker="!" width={props.width} onActivate={() => props.model.onOpenAttention?.()}/>
428
+ <KeyHint theme={props.theme} keys="F7" label={`Attention (${props.model.groups().reduce((sum, group) => sum + (group.state === "ready" ? (group.agents ?? []).filter((agent) => agent.attention && !agent.disabled).length : 0), 0)})`} width={props.width} quiet button onPress={() => props.model.onOpenAttention?.()}/>
424
429
  </Show>
425
430
  <Show when={controlsHeight() > 0 && controlGroup()}>
426
431
  {(group) => (<>
@@ -429,12 +434,12 @@ export function ApplicationMachineSidebar(props) {
429
434
  ? fleetConnectionMessage(group().diagnostic)
430
435
  : connectionDetail(group())}
431
436
  </text>
432
- <NavigationRow theme={props.theme} id="machine:retry" label="Retry connection (R)" marker="↻" width={props.width} onActivate={() => props.model.onRetryMachine?.(group().id)}/>
433
- <NavigationRow theme={props.theme} id="machine:disconnect" label="Disconnect (D)" marker="×" width={props.width} onActivate={() => props.model.onDisconnectMachine?.(group().id)}/>
437
+ <KeyHint theme={props.theme} keys="R" label="Retry connection" width={props.width} quiet button onPress={() => props.model.onRetryMachine?.(group().id)}/>
438
+ <KeyHint theme={props.theme} keys="D" label="Disconnect" width={props.width} quiet button onPress={() => props.model.onDisconnectMachine?.(group().id)}/>
434
439
  </>)}
435
440
  </Show>
436
441
  <For each={props.model.onAddMachine ? [props.model.onAddMachine] : []}>
437
- {(add) => (<NavigationRow theme={props.theme} id="machine:add" label="Add machine" detail="A" marker=" " width={props.width} onActivate={add}/>)}
442
+ {(add) => (<KeyHint theme={props.theme} keys="A" label="Add machine" width={props.width} quiet button onPress={add}/>)}
438
443
  </For>
439
444
  </Surface>);
440
445
  }
@@ -21,6 +21,7 @@ import {
21
21
  } from "solid-js";
22
22
  import { clipTerminal, friendlySessionLabel } from "../terminal-text.ts";
23
23
  import type { SemanticThemeSnapshot } from "../theme.ts";
24
+ import { KeyHint } from "../ui/key-hint.tsx";
24
25
  import { NavigationRow } from "../ui/navigation-row.tsx";
25
26
  import { Surface } from "../ui/surface.tsx";
26
27
  import { useKeyboardRoute } from "../ui/keyboard-router.tsx";
@@ -458,10 +459,21 @@ export function ApplicationMachineSidebar(props: {
458
459
  flexDirection="column"
459
460
  overflow="hidden"
460
461
  >
461
- <text height={1} fg={props.theme.roles.text.secondary}>
462
- {" "}
463
- {props.model.tabs?.().length ? "Machines · F9 tabs · ?" : "Machines · ? help"}
464
- </text>
462
+ <box height={1} flexShrink={0} flexDirection="row" overflow="hidden">
463
+ <text fg={props.theme.roles.text.secondary}>{" Machines"}</text>
464
+ <box flexGrow={1} />
465
+ <Show when={props.model.tabs?.().length && props.width >= 28}>
466
+ <KeyHint theme={props.theme} keys="F9" label="Tabs" quiet />
467
+ </Show>
468
+ <KeyHint
469
+ theme={props.theme}
470
+ keys="?"
471
+ label={props.width >= 20 ? "Help" : undefined}
472
+ quiet
473
+ button
474
+ onPress={() => setShowHelp(!showHelp())}
475
+ />
476
+ </box>
465
477
  <For each={visibleTabs()}>
466
478
  {(tab) => (
467
479
  <box height={1} flexDirection="row">
@@ -653,24 +665,25 @@ export function ApplicationMachineSidebar(props: {
653
665
  </text>
654
666
  </Show>
655
667
  <Show when={props.model.onOpenSwitcher}>
656
- <NavigationRow
668
+ <KeyHint
657
669
  theme={props.theme}
658
- id="machine:switcher"
670
+ keys="F6"
659
671
  label="Sessions"
660
- detail="F6"
661
- marker=" "
662
672
  width={props.width}
663
- onActivate={() => props.model.onOpenSwitcher?.()}
673
+ quiet
674
+ button
675
+ onPress={() => props.model.onOpenSwitcher?.()}
664
676
  />
665
677
  </Show>
666
678
  <Show when={props.model.onOpenAttention}>
667
- <NavigationRow
679
+ <KeyHint
668
680
  theme={props.theme}
669
- id="machine:attention"
670
- label={`Attention (${props.model.groups().reduce((sum, group) => sum + (group.state === "ready" ? (group.agents ?? []).filter((agent) => agent.attention && !agent.disabled).length : 0), 0)}) · F7`}
671
- marker="!"
681
+ keys="F7"
682
+ label={`Attention (${props.model.groups().reduce((sum, group) => sum + (group.state === "ready" ? (group.agents ?? []).filter((agent) => agent.attention && !agent.disabled).length : 0), 0)})`}
672
683
  width={props.width}
673
- onActivate={() => props.model.onOpenAttention?.()}
684
+ quiet
685
+ button
686
+ onPress={() => props.model.onOpenAttention?.()}
674
687
  />
675
688
  </Show>
676
689
  <Show when={controlsHeight() > 0 && controlGroup()}>
@@ -681,35 +694,37 @@ export function ApplicationMachineSidebar(props: {
681
694
  ? fleetConnectionMessage(group().diagnostic!)
682
695
  : connectionDetail(group())}
683
696
  </text>
684
- <NavigationRow
697
+ <KeyHint
685
698
  theme={props.theme}
686
- id="machine:retry"
687
- label="Retry connection (R)"
688
- marker="↻"
699
+ keys="R"
700
+ label="Retry connection"
689
701
  width={props.width}
690
- onActivate={() => props.model.onRetryMachine?.(group().id)}
702
+ quiet
703
+ button
704
+ onPress={() => props.model.onRetryMachine?.(group().id)}
691
705
  />
692
- <NavigationRow
706
+ <KeyHint
693
707
  theme={props.theme}
694
- id="machine:disconnect"
695
- label="Disconnect (D)"
696
- marker="×"
708
+ keys="D"
709
+ label="Disconnect"
697
710
  width={props.width}
698
- onActivate={() => props.model.onDisconnectMachine?.(group().id)}
711
+ quiet
712
+ button
713
+ onPress={() => props.model.onDisconnectMachine?.(group().id)}
699
714
  />
700
715
  </>
701
716
  )}
702
717
  </Show>
703
718
  <For each={props.model.onAddMachine ? [props.model.onAddMachine] : []}>
704
719
  {(add) => (
705
- <NavigationRow
720
+ <KeyHint
706
721
  theme={props.theme}
707
- id="machine:add"
722
+ keys="A"
708
723
  label="Add machine"
709
- detail="A"
710
- marker=" "
711
724
  width={props.width}
712
- onActivate={add}
725
+ quiet
726
+ button
727
+ onPress={add}
713
728
  />
714
729
  )}
715
730
  </For>
@@ -395,6 +395,16 @@ export function ApplicationShellView(props: ApplicationShellViewProps): JSX.Elem
395
395
  }}
396
396
  >
397
397
  <ApplicationShell
398
+ onFooterAction={(key) => {
399
+ props.machineSidebar?.onBlur?.();
400
+ if (key === "F6") props.machineSidebar?.onOpenSwitcher?.();
401
+ else if (key === "F7") props.machineSidebar?.onOpenAttention?.();
402
+ else
403
+ props.onPaletteActivate?.(
404
+ props.sidebarVisible === false ? "show-sidebar" : "hide-sidebar",
405
+ "mouse",
406
+ );
407
+ }}
398
408
  footerContext={props.surface() === "home" ? "home" : "terminals"}
399
409
  scrollback={props.surface() === "terminals" && scrollback()}
400
410
  rightChips={
@@ -164,6 +164,7 @@ export interface ShellStatusStripProps {
164
164
  tool?: string | null;
165
165
  dockMode?: string | null;
166
166
  focus?: string | null;
167
+ onFooterAction?: (key: "F6" | "F7" | "F10") => void;
167
168
  scrollback?: boolean;
168
169
  notification: string | null;
169
170
  transient?: string | null;
@@ -219,7 +220,26 @@ export function ContextStatusBar(props: ShellStatusStripProps) {
219
220
  when={showMessage()}
220
221
  fallback={
221
222
  <For each={hints()}>
222
- {(hint) => <KeyHint theme={props.theme} keys={hint.keys} label={hint.label} quiet />}
223
+ {(hint) => {
224
+ const action = () =>
225
+ hint.keys === "F6" || hint.keys === "F7" || hint.keys === "F10"
226
+ ? hint.keys
227
+ : null;
228
+ return (
229
+ <KeyHint
230
+ theme={props.theme}
231
+ keys={hint.keys}
232
+ label={hint.label}
233
+ quiet
234
+ button={action() !== null}
235
+ onPress={
236
+ action() && props.onFooterAction
237
+ ? () => props.onFooterAction?.(action()!)
238
+ : undefined
239
+ }
240
+ />
241
+ );
242
+ }}
223
243
  </For>
224
244
  }
225
245
  >
@@ -11,6 +11,7 @@ import type { SemanticThemeSnapshot } from "../theme.ts";
11
11
  import type { ApplicationShellProjection } from "./application-shell.ts";
12
12
 
13
13
  export interface ApplicationShellProps {
14
+ onFooterAction?: (key: "F6" | "F7" | "F10") => void;
14
15
  scrollback?: boolean;
15
16
  footerContext?: "home" | "terminals";
16
17
  theme: SemanticThemeSnapshot;
@@ -145,6 +146,7 @@ export function ApplicationShell(props: ApplicationShellProps) {
145
146
  props.showToolStatus === false ? null : props.projection.semantic.bottomDock.mode
146
147
  }
147
148
  focus={props.focusLabel ?? applicationShellFocusLabel(props.projection)}
149
+ onFooterAction={props.onFooterAction}
148
150
  scrollback={props.scrollback}
149
151
  notification={props.projection.semantic.statusStrip.message}
150
152
  transient={props.note}