@h-rig/cli 0.0.6-alpha.86 → 0.0.6-alpha.87

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 (61) hide show
  1. package/dist/bin/rig.js +79 -18
  2. package/dist/src/app-opentui/bootstrap.js +79 -18
  3. package/dist/src/app-opentui/command-palette.js +1 -0
  4. package/dist/src/app-opentui/drone.js +1 -0
  5. package/dist/src/app-opentui/index.js +61 -7
  6. package/dist/src/app-opentui/list-search.d.ts +5 -1
  7. package/dist/src/app-opentui/list-search.js +2 -2
  8. package/dist/src/app-opentui/react/App.js +67 -8
  9. package/dist/src/app-opentui/react/Backdrop.js +1 -0
  10. package/dist/src/app-opentui/react/ChromeHost.js +7 -0
  11. package/dist/src/app-opentui/react/SceneFrameView.js +55 -5
  12. package/dist/src/app-opentui/react/launch.js +67 -8
  13. package/dist/src/app-opentui/react/syntax.js +1 -0
  14. package/dist/src/app-opentui/registry.js +3 -5
  15. package/dist/src/app-opentui/render/graphics.js +1 -0
  16. package/dist/src/app-opentui/render/hover.d.ts +11 -0
  17. package/dist/src/app-opentui/render/hover.js +34 -0
  18. package/dist/src/app-opentui/render/native-host.js +1 -0
  19. package/dist/src/app-opentui/render/panels.js +50 -3
  20. package/dist/src/app-opentui/render/preloader.js +1 -0
  21. package/dist/src/app-opentui/render/scene.js +1 -0
  22. package/dist/src/app-opentui/render/text.d.ts +13 -0
  23. package/dist/src/app-opentui/render/text.js +54 -5
  24. package/dist/src/app-opentui/render/type-bar.js +1 -0
  25. package/dist/src/app-opentui/runtime.js +61 -7
  26. package/dist/src/app-opentui/scenes/command.js +1 -0
  27. package/dist/src/app-opentui/scenes/doctor.js +1 -0
  28. package/dist/src/app-opentui/scenes/error.js +1 -0
  29. package/dist/src/app-opentui/scenes/family-domains/agent.js +1 -0
  30. package/dist/src/app-opentui/scenes/family-domains/browser.js +1 -0
  31. package/dist/src/app-opentui/scenes/family-domains/dist.js +1 -0
  32. package/dist/src/app-opentui/scenes/family-domains/git.js +1 -0
  33. package/dist/src/app-opentui/scenes/family-domains/github.js +1 -0
  34. package/dist/src/app-opentui/scenes/family-domains/harness.js +1 -0
  35. package/dist/src/app-opentui/scenes/family-domains/index.js +1 -0
  36. package/dist/src/app-opentui/scenes/family-domains/kit.js +1 -0
  37. package/dist/src/app-opentui/scenes/family-domains/profile.js +1 -0
  38. package/dist/src/app-opentui/scenes/family-domains/queue.js +1 -0
  39. package/dist/src/app-opentui/scenes/family-domains/remote.js +1 -0
  40. package/dist/src/app-opentui/scenes/family-domains/review.js +1 -0
  41. package/dist/src/app-opentui/scenes/family-domains/setup.js +1 -0
  42. package/dist/src/app-opentui/scenes/family-domains/stats.js +1 -0
  43. package/dist/src/app-opentui/scenes/family.js +1 -0
  44. package/dist/src/app-opentui/scenes/fleet.js +3 -5
  45. package/dist/src/app-opentui/scenes/handoff.js +1 -0
  46. package/dist/src/app-opentui/scenes/help.js +1 -0
  47. package/dist/src/app-opentui/scenes/inbox.js +1 -0
  48. package/dist/src/app-opentui/scenes/init.js +1 -0
  49. package/dist/src/app-opentui/scenes/inspect.js +1 -0
  50. package/dist/src/app-opentui/scenes/main.js +1 -0
  51. package/dist/src/app-opentui/scenes/pi.js +1 -0
  52. package/dist/src/app-opentui/scenes/plugin.js +1 -0
  53. package/dist/src/app-opentui/scenes/repo.js +1 -0
  54. package/dist/src/app-opentui/scenes/run-detail.js +1 -0
  55. package/dist/src/app-opentui/scenes/server.js +1 -0
  56. package/dist/src/app-opentui/scenes/tasks.js +3 -5
  57. package/dist/src/app-opentui/scenes/workspace.js +1 -0
  58. package/dist/src/app-opentui/selectable.js +1 -0
  59. package/dist/src/app-opentui/theme.d.ts +1 -0
  60. package/dist/src/app-opentui/theme.js +1 -0
  61. package/package.json +8 -8
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/cli/src/app-opentui/react/App.tsx
3
- import { useMemo, useRef as useRef4 } from "react";
3
+ import { useMemo, useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
4
4
  import { useKeyboard, useRenderer as useRenderer4, useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
5
5
 
6
6
  // packages/cli/src/app-opentui/layout.ts
@@ -59,6 +59,7 @@ var RIG_UI = {
59
59
  bg2: "#0b0c0e",
60
60
  panel: "#101115",
61
61
  panel2: "#14161b",
62
+ hover: "#181b24",
62
63
  glass: "#1e2230",
63
64
  border: "#2a2e3a",
64
65
  ink: "#f4f5f8",
@@ -3104,15 +3105,69 @@ function drawAmbientField(layer, layout, _tick, scene = "fleet", load = 0, activ
3104
3105
 
3105
3106
  // packages/cli/src/app-opentui/render/text.ts
3106
3107
  import { RGBA as RGBA4, TextAttributes as TextAttributes4, TextRenderable } from "@opentui/core";
3108
+
3109
+ // packages/cli/src/app-opentui/render/hover.ts
3110
+ var hoveredId;
3111
+ var listeners = new Set;
3112
+ function getHoveredSelectableId() {
3113
+ return hoveredId;
3114
+ }
3115
+ function isHovered(id) {
3116
+ return id !== undefined && id === hoveredId;
3117
+ }
3118
+ function setHoveredSelectableId(id) {
3119
+ if (hoveredId === id)
3120
+ return;
3121
+ hoveredId = id;
3122
+ for (const listener of listeners)
3123
+ listener();
3124
+ }
3125
+ function clearHoveredSelectableId(id) {
3126
+ if (id !== undefined && hoveredId === id)
3127
+ setHoveredSelectableId(undefined);
3128
+ }
3129
+ function subscribeHover(listener) {
3130
+ listeners.add(listener);
3131
+ return () => {
3132
+ listeners.delete(listener);
3133
+ };
3134
+ }
3135
+
3136
+ // packages/cli/src/app-opentui/render/text.ts
3107
3137
  var TRANSPARENT2 = RGBA4.fromInts(0, 0, 0, 0);
3138
+ var HOVER_BG = RGBA4.fromHex(RIG_UI.hover);
3139
+ function lineIsClickable(line2) {
3140
+ return line2?.selectable !== undefined || line2?.selectableIndex !== undefined;
3141
+ }
3142
+ function lineSelectableId(line2) {
3143
+ return line2?.selectable?.id ?? line2?.selectableId;
3144
+ }
3145
+ function lineBackground(line2) {
3146
+ if (line2?.bg)
3147
+ return RGBA4.fromHex(line2.bg);
3148
+ const id = lineSelectableId(line2);
3149
+ if (id !== undefined && isHovered(id))
3150
+ return HOVER_BG;
3151
+ return TRANSPARENT2;
3152
+ }
3108
3153
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
3109
3154
  return (event) => {
3110
3155
  const currentLine = currentLineRef();
3111
- if (currentLine?.selectableIndex === undefined)
3156
+ if (!lineIsClickable(currentLine))
3112
3157
  return;
3113
3158
  onLineMouseDown?.(currentLine, event);
3114
3159
  };
3115
3160
  }
3161
+ function hoverHandlers(currentLineRef) {
3162
+ return {
3163
+ onMouseOver: () => {
3164
+ const id = lineSelectableId(currentLineRef());
3165
+ if (id !== undefined)
3166
+ setHoveredSelectableId(id);
3167
+ },
3168
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
3169
+ };
3170
+ }
3116
3171
  function createFlowTextLine(renderer, id, onLineMouseDown) {
3117
3172
  let currentLine;
3118
3173
  const renderable = new TextRenderable(renderer, {
@@ -3123,7 +3178,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
3123
3178
  flexShrink: 0,
3124
3179
  fg: RIG_UI.ink2,
3125
3180
  selectable: true,
3126
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
3181
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
3182
+ ...hoverHandlers(() => currentLine)
3127
3183
  });
3128
3184
  renderable.setRigSceneLine = (line2) => {
3129
3185
  currentLine = line2;
@@ -3137,7 +3193,7 @@ function applyFlowTextLine(renderable, line2, width) {
3137
3193
  renderable.width = Math.max(1, width);
3138
3194
  renderable.content = line2?.styledText ?? line2?.text ?? "";
3139
3195
  renderable.fg = line2?.fg ?? RIG_UI.ink2;
3140
- renderable.bg = line2?.bg ?? TRANSPARENT2;
3196
+ renderable.bg = lineBackground(line2);
3141
3197
  renderable.attributes = line2?.bold ? TextAttributes4.BOLD : line2?.dim ? TextAttributes4.DIM : 0;
3142
3198
  }
3143
3199
 
@@ -3810,13 +3866,16 @@ function lineContent(line2) {
3810
3866
  }
3811
3867
  function LineView(props) {
3812
3868
  const { line: line2, onLineClick } = props;
3869
+ const id = lineSelectableId(line2);
3813
3870
  return /* @__PURE__ */ jsxDEV("text", {
3814
3871
  style: { position: "absolute", left: props.left, top: props.top, width: props.width, zIndex: 5 },
3815
3872
  fg: line2.fg ?? RIG_UI.ink2,
3816
- bg: line2.bg ?? TRANSPARENT2,
3873
+ bg: lineBackground(line2),
3817
3874
  attributes: lineAttributes(line2),
3818
3875
  content: lineContent(line2),
3819
- onMouseDown: onLineClick ? () => onLineClick(line2) : undefined
3876
+ onMouseDown: onLineClick ? () => onLineClick(line2) : undefined,
3877
+ onMouseOver: id !== undefined ? () => setHoveredSelectableId(id) : undefined,
3878
+ onMouseOut: id !== undefined ? () => clearHoveredSelectableId(id) : undefined
3820
3879
  }, undefined, false, undefined, this);
3821
3880
  }
3822
3881
  function PanelHost(props) {
@@ -4052,6 +4111,7 @@ function App(props) {
4052
4111
  const runAppAction = useRunAppAction();
4053
4112
  const store = useStore();
4054
4113
  const renderer = useRenderer4();
4114
+ useSyncExternalStore2(subscribeHover, getHoveredSelectableId, getHoveredSelectableId);
4055
4115
  const dims = useTerminalDimensions2();
4056
4116
  const layout = computeStageLayout(dims.width, dims.height);
4057
4117
  const registry = useMemo(() => ({ ...BUILTIN, ...props.sceneRenderers ?? {} }), [props.sceneRenderers]);
@@ -4086,8 +4146,7 @@ function App(props) {
4086
4146
  } else {
4087
4147
  return;
4088
4148
  }
4089
- if (line2.activateOnClick)
4090
- runAppAction("Activate selection", () => activateSelection(runtime, items));
4149
+ runAppAction("Activate selection", () => activateSelection(runtime, items));
4091
4150
  };
4092
4151
  return /* @__PURE__ */ jsxDEV3("box", {
4093
4152
  style: { position: "absolute", left: 0, top: 0, width: "100%", height: "100%" },
@@ -39,6 +39,7 @@ var RIG_UI = {
39
39
  bg2: "#0b0c0e",
40
40
  panel: "#101115",
41
41
  panel2: "#14161b",
42
+ hover: "#181b24",
42
43
  glass: "#1e2230",
43
44
  border: "#2a2e3a",
44
45
  ink: "#f4f5f8",
@@ -43,6 +43,7 @@ var RIG_UI = {
43
43
  bg2: "#0b0c0e",
44
44
  panel: "#101115",
45
45
  panel2: "#14161b",
46
+ hover: "#181b24",
46
47
  glass: "#1e2230",
47
48
  border: "#2a2e3a",
48
49
  ink: "#f4f5f8",
@@ -1747,7 +1748,13 @@ var ACTIVE_STATUSES = new Set([
1747
1748
 
1748
1749
  // packages/cli/src/app-opentui/render/text.ts
1749
1750
  import { RGBA as RGBA5, TextAttributes as TextAttributes4, TextRenderable as TextRenderable2 } from "@opentui/core";
1751
+
1752
+ // packages/cli/src/app-opentui/render/hover.ts
1753
+ var listeners = new Set;
1754
+
1755
+ // packages/cli/src/app-opentui/render/text.ts
1750
1756
  var TRANSPARENT2 = RGBA5.fromInts(0, 0, 0, 0);
1757
+ var HOVER_BG = RGBA5.fromHex(RIG_UI.hover);
1751
1758
 
1752
1759
  // packages/cli/src/app-opentui/render/panels.ts
1753
1760
  import { RGBA as RGBA6, ScrollBoxRenderable } from "@opentui/core";
@@ -17,6 +17,7 @@ var RIG_UI = {
17
17
  bg2: "#0b0c0e",
18
18
  panel: "#101115",
19
19
  panel2: "#14161b",
20
+ hover: "#181b24",
20
21
  glass: "#1e2230",
21
22
  border: "#2a2e3a",
22
23
  ink: "#f4f5f8",
@@ -95,15 +96,60 @@ function fitSceneLines(lines, layout) {
95
96
 
96
97
  // packages/cli/src/app-opentui/render/text.ts
97
98
  import { RGBA as RGBA2, TextAttributes as TextAttributes3, TextRenderable } from "@opentui/core";
99
+
100
+ // packages/cli/src/app-opentui/render/hover.ts
101
+ var hoveredId;
102
+ var listeners = new Set;
103
+ function isHovered(id) {
104
+ return id !== undefined && id === hoveredId;
105
+ }
106
+ function setHoveredSelectableId(id) {
107
+ if (hoveredId === id)
108
+ return;
109
+ hoveredId = id;
110
+ for (const listener of listeners)
111
+ listener();
112
+ }
113
+ function clearHoveredSelectableId(id) {
114
+ if (id !== undefined && hoveredId === id)
115
+ setHoveredSelectableId(undefined);
116
+ }
117
+
118
+ // packages/cli/src/app-opentui/render/text.ts
98
119
  var TRANSPARENT = RGBA2.fromInts(0, 0, 0, 0);
120
+ var HOVER_BG = RGBA2.fromHex(RIG_UI.hover);
121
+ function lineIsClickable(line) {
122
+ return line?.selectable !== undefined || line?.selectableIndex !== undefined;
123
+ }
124
+ function lineSelectableId(line) {
125
+ return line?.selectable?.id ?? line?.selectableId;
126
+ }
127
+ function lineBackground(line) {
128
+ if (line?.bg)
129
+ return RGBA2.fromHex(line.bg);
130
+ const id = lineSelectableId(line);
131
+ if (id !== undefined && isHovered(id))
132
+ return HOVER_BG;
133
+ return TRANSPARENT;
134
+ }
99
135
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
100
136
  return (event) => {
101
137
  const currentLine = currentLineRef();
102
- if (currentLine?.selectableIndex === undefined)
138
+ if (!lineIsClickable(currentLine))
103
139
  return;
104
140
  onLineMouseDown?.(currentLine, event);
105
141
  };
106
142
  }
143
+ function hoverHandlers(currentLineRef) {
144
+ return {
145
+ onMouseOver: () => {
146
+ const id = lineSelectableId(currentLineRef());
147
+ if (id !== undefined)
148
+ setHoveredSelectableId(id);
149
+ },
150
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
151
+ };
152
+ }
107
153
  function createFlowTextLine(renderer, id, onLineMouseDown) {
108
154
  let currentLine;
109
155
  const renderable = new TextRenderable(renderer, {
@@ -114,7 +160,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
114
160
  flexShrink: 0,
115
161
  fg: RIG_UI.ink2,
116
162
  selectable: true,
117
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
163
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
164
+ ...hoverHandlers(() => currentLine)
118
165
  });
119
166
  renderable.setRigSceneLine = (line) => {
120
167
  currentLine = line;
@@ -128,7 +175,7 @@ function applyFlowTextLine(renderable, line, width) {
128
175
  renderable.width = Math.max(1, width);
129
176
  renderable.content = line?.styledText ?? line?.text ?? "";
130
177
  renderable.fg = line?.fg ?? RIG_UI.ink2;
131
- renderable.bg = line?.bg ?? TRANSPARENT;
178
+ renderable.bg = lineBackground(line);
132
179
  renderable.attributes = line?.bold ? TextAttributes3.BOLD : line?.dim ? TextAttributes3.DIM : 0;
133
180
  }
134
181
 
@@ -435,13 +482,16 @@ function lineContent(line) {
435
482
  }
436
483
  function LineView(props) {
437
484
  const { line, onLineClick } = props;
485
+ const id = lineSelectableId(line);
438
486
  return /* @__PURE__ */ jsxDEV("text", {
439
487
  style: { position: "absolute", left: props.left, top: props.top, width: props.width, zIndex: 5 },
440
488
  fg: line.fg ?? RIG_UI.ink2,
441
- bg: line.bg ?? TRANSPARENT,
489
+ bg: lineBackground(line),
442
490
  attributes: lineAttributes(line),
443
491
  content: lineContent(line),
444
- onMouseDown: onLineClick ? () => onLineClick(line) : undefined
492
+ onMouseDown: onLineClick ? () => onLineClick(line) : undefined,
493
+ onMouseOver: id !== undefined ? () => setHoveredSelectableId(id) : undefined,
494
+ onMouseOut: id !== undefined ? () => clearHoveredSelectableId(id) : undefined
445
495
  }, undefined, false, undefined, this);
446
496
  }
447
497
  function PanelHost(props) {
@@ -2290,6 +2290,7 @@ var RIG_UI = {
2290
2290
  bg2: "#0b0c0e",
2291
2291
  panel: "#101115",
2292
2292
  panel2: "#14161b",
2293
+ hover: "#181b24",
2293
2294
  glass: "#1e2230",
2294
2295
  border: "#2a2e3a",
2295
2296
  ink: "#f4f5f8",
@@ -3201,15 +3202,69 @@ function sparklineString(values, width) {
3201
3202
 
3202
3203
  // packages/cli/src/app-opentui/render/text.ts
3203
3204
  import { RGBA as RGBA4, TextAttributes as TextAttributes4, TextRenderable } from "@opentui/core";
3205
+
3206
+ // packages/cli/src/app-opentui/render/hover.ts
3207
+ var hoveredId;
3208
+ var listeners = new Set;
3209
+ function getHoveredSelectableId() {
3210
+ return hoveredId;
3211
+ }
3212
+ function isHovered(id) {
3213
+ return id !== undefined && id === hoveredId;
3214
+ }
3215
+ function setHoveredSelectableId(id) {
3216
+ if (hoveredId === id)
3217
+ return;
3218
+ hoveredId = id;
3219
+ for (const listener of listeners)
3220
+ listener();
3221
+ }
3222
+ function clearHoveredSelectableId(id) {
3223
+ if (id !== undefined && hoveredId === id)
3224
+ setHoveredSelectableId(undefined);
3225
+ }
3226
+ function subscribeHover(listener) {
3227
+ listeners.add(listener);
3228
+ return () => {
3229
+ listeners.delete(listener);
3230
+ };
3231
+ }
3232
+
3233
+ // packages/cli/src/app-opentui/render/text.ts
3204
3234
  var TRANSPARENT2 = RGBA4.fromInts(0, 0, 0, 0);
3235
+ var HOVER_BG = RGBA4.fromHex(RIG_UI.hover);
3236
+ function lineIsClickable(line2) {
3237
+ return line2?.selectable !== undefined || line2?.selectableIndex !== undefined;
3238
+ }
3239
+ function lineSelectableId(line2) {
3240
+ return line2?.selectable?.id ?? line2?.selectableId;
3241
+ }
3242
+ function lineBackground(line2) {
3243
+ if (line2?.bg)
3244
+ return RGBA4.fromHex(line2.bg);
3245
+ const id = lineSelectableId(line2);
3246
+ if (id !== undefined && isHovered(id))
3247
+ return HOVER_BG;
3248
+ return TRANSPARENT2;
3249
+ }
3205
3250
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
3206
3251
  return (event) => {
3207
3252
  const currentLine = currentLineRef();
3208
- if (currentLine?.selectableIndex === undefined)
3253
+ if (!lineIsClickable(currentLine))
3209
3254
  return;
3210
3255
  onLineMouseDown?.(currentLine, event);
3211
3256
  };
3212
3257
  }
3258
+ function hoverHandlers(currentLineRef) {
3259
+ return {
3260
+ onMouseOver: () => {
3261
+ const id = lineSelectableId(currentLineRef());
3262
+ if (id !== undefined)
3263
+ setHoveredSelectableId(id);
3264
+ },
3265
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
3266
+ };
3267
+ }
3213
3268
  function createFlowTextLine(renderer, id, onLineMouseDown) {
3214
3269
  let currentLine;
3215
3270
  const renderable = new TextRenderable(renderer, {
@@ -3220,7 +3275,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
3220
3275
  flexShrink: 0,
3221
3276
  fg: RIG_UI.ink2,
3222
3277
  selectable: true,
3223
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
3278
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
3279
+ ...hoverHandlers(() => currentLine)
3224
3280
  });
3225
3281
  renderable.setRigSceneLine = (line2) => {
3226
3282
  currentLine = line2;
@@ -3234,7 +3290,7 @@ function applyFlowTextLine(renderable, line2, width) {
3234
3290
  renderable.width = Math.max(1, width);
3235
3291
  renderable.content = line2?.styledText ?? line2?.text ?? "";
3236
3292
  renderable.fg = line2?.fg ?? RIG_UI.ink2;
3237
- renderable.bg = line2?.bg ?? TRANSPARENT2;
3293
+ renderable.bg = lineBackground(line2);
3238
3294
  renderable.attributes = line2?.bold ? TextAttributes4.BOLD : line2?.dim ? TextAttributes4.DIM : 0;
3239
3295
  }
3240
3296
 
@@ -4178,7 +4234,7 @@ async function activateSelection(runtime, renderedItems) {
4178
4234
  }
4179
4235
 
4180
4236
  // packages/cli/src/app-opentui/react/App.tsx
4181
- import { useMemo, useRef as useRef4 } from "react";
4237
+ import { useMemo, useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
4182
4238
  import { useKeyboard, useRenderer as useRenderer4, useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
4183
4239
 
4184
4240
  // packages/cli/src/app-opentui/react/Backdrop.tsx
@@ -4263,13 +4319,16 @@ function lineContent(line2) {
4263
4319
  }
4264
4320
  function LineView(props) {
4265
4321
  const { line: line2, onLineClick } = props;
4322
+ const id = lineSelectableId(line2);
4266
4323
  return /* @__PURE__ */ jsxDEV("text", {
4267
4324
  style: { position: "absolute", left: props.left, top: props.top, width: props.width, zIndex: 5 },
4268
4325
  fg: line2.fg ?? RIG_UI.ink2,
4269
- bg: line2.bg ?? TRANSPARENT2,
4326
+ bg: lineBackground(line2),
4270
4327
  attributes: lineAttributes(line2),
4271
4328
  content: lineContent(line2),
4272
- onMouseDown: onLineClick ? () => onLineClick(line2) : undefined
4329
+ onMouseDown: onLineClick ? () => onLineClick(line2) : undefined,
4330
+ onMouseOver: id !== undefined ? () => setHoveredSelectableId(id) : undefined,
4331
+ onMouseOut: id !== undefined ? () => clearHoveredSelectableId(id) : undefined
4273
4332
  }, undefined, false, undefined, this);
4274
4333
  }
4275
4334
  function PanelHost(props) {
@@ -4511,6 +4570,7 @@ function App(props) {
4511
4570
  const runAppAction = useRunAppAction();
4512
4571
  const store = useStore();
4513
4572
  const renderer = useRenderer4();
4573
+ useSyncExternalStore2(subscribeHover, getHoveredSelectableId, getHoveredSelectableId);
4514
4574
  const dims = useTerminalDimensions2();
4515
4575
  const layout = computeStageLayout(dims.width, dims.height);
4516
4576
  const registry = useMemo(() => ({ ...BUILTIN, ...props.sceneRenderers ?? {} }), [props.sceneRenderers]);
@@ -4545,8 +4605,7 @@ function App(props) {
4545
4605
  } else {
4546
4606
  return;
4547
4607
  }
4548
- if (line2.activateOnClick)
4549
- runAppAction("Activate selection", () => activateSelection(runtime, items));
4608
+ runAppAction("Activate selection", () => activateSelection(runtime, items));
4550
4609
  };
4551
4610
  return /* @__PURE__ */ jsxDEV3("box", {
4552
4611
  style: { position: "absolute", left: 0, top: 0, width: "100%", height: "100%" },
@@ -15,6 +15,7 @@ var RIG_UI = {
15
15
  bg2: "#0b0c0e",
16
16
  panel: "#101115",
17
17
  panel2: "#14161b",
18
+ hover: "#181b24",
18
19
  glass: "#1e2230",
19
20
  border: "#2a2e3a",
20
21
  ink: "#f4f5f8",
@@ -17045,6 +17045,7 @@ var RIG_UI = {
17045
17045
  bg2: "#0b0c0e",
17046
17046
  panel: "#101115",
17047
17047
  panel2: "#14161b",
17048
+ hover: "#181b24",
17048
17049
  glass: "#1e2230",
17049
17050
  border: "#2a2e3a",
17050
17051
  ink: "#f4f5f8",
@@ -19347,11 +19348,8 @@ function renderFamilyScene(state, layout) {
19347
19348
  }
19348
19349
 
19349
19350
  // packages/cli/src/app-opentui/list-search.ts
19350
- function isListSearchScene(scene) {
19351
- return scene === "fleet" || scene === "tasks";
19352
- }
19353
- function listSearchQuery(state) {
19354
- return isListSearchScene(state.scene) ? state.typeBar.value.trim() : "";
19351
+ function listSearchQuery(_state) {
19352
+ return "";
19355
19353
  }
19356
19354
  function valueText(value) {
19357
19355
  if (value === undefined || value === null)
@@ -15,6 +15,7 @@ var RIG_UI = {
15
15
  bg2: "#0b0c0e",
16
16
  panel: "#101115",
17
17
  panel2: "#14161b",
18
+ hover: "#181b24",
18
19
  glass: "#1e2230",
19
20
  border: "#2a2e3a",
20
21
  ink: "#f4f5f8",
@@ -0,0 +1,11 @@
1
+ export declare function getHoveredSelectableId(): string | undefined;
2
+ export declare function isHovered(id: string | undefined): boolean;
3
+ /** Set the hovered row (or clear with `undefined`). No-ops when unchanged so we
4
+ * don't churn renders on every mouse-move event within the same row. */
5
+ export declare function setHoveredSelectableId(id: string | undefined): void;
6
+ /** Clear the hover only if `id` is the currently-hovered row — guards against a
7
+ * stale mouseout (from a row we already left) wiping a newer hover. */
8
+ export declare function clearHoveredSelectableId(id: string | undefined): void;
9
+ /** Subscribe to hover changes. Legacy shell passes its render scheduler; the
10
+ * react shell bridges this into a re-render. Returns an unsubscribe fn. */
11
+ export declare function subscribeHover(listener: () => void): () => void;
@@ -0,0 +1,34 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/render/hover.ts
3
+ var hoveredId;
4
+ var listeners = new Set;
5
+ function getHoveredSelectableId() {
6
+ return hoveredId;
7
+ }
8
+ function isHovered(id) {
9
+ return id !== undefined && id === hoveredId;
10
+ }
11
+ function setHoveredSelectableId(id) {
12
+ if (hoveredId === id)
13
+ return;
14
+ hoveredId = id;
15
+ for (const listener of listeners)
16
+ listener();
17
+ }
18
+ function clearHoveredSelectableId(id) {
19
+ if (id !== undefined && hoveredId === id)
20
+ setHoveredSelectableId(undefined);
21
+ }
22
+ function subscribeHover(listener) {
23
+ listeners.add(listener);
24
+ return () => {
25
+ listeners.delete(listener);
26
+ };
27
+ }
28
+ export {
29
+ subscribeHover,
30
+ setHoveredSelectableId,
31
+ isHovered,
32
+ getHoveredSelectableId,
33
+ clearHoveredSelectableId
34
+ };
@@ -24,6 +24,7 @@ var RIG_UI = {
24
24
  bg2: "#0b0c0e",
25
25
  panel: "#101115",
26
26
  panel2: "#14161b",
27
+ hover: "#181b24",
27
28
  glass: "#1e2230",
28
29
  border: "#2a2e3a",
29
30
  ink: "#f4f5f8",
@@ -15,6 +15,7 @@ var RIG_UI = {
15
15
  bg2: "#0b0c0e",
16
16
  panel: "#101115",
17
17
  panel2: "#14161b",
18
+ hover: "#181b24",
18
19
  glass: "#1e2230",
19
20
  border: "#2a2e3a",
20
21
  ink: "#f4f5f8",
@@ -74,15 +75,60 @@ function panelContentRect(layout, panel) {
74
75
 
75
76
  // packages/cli/src/app-opentui/render/text.ts
76
77
  import { RGBA, TextAttributes as TextAttributes2, TextRenderable } from "@opentui/core";
78
+
79
+ // packages/cli/src/app-opentui/render/hover.ts
80
+ var hoveredId;
81
+ var listeners = new Set;
82
+ function isHovered(id) {
83
+ return id !== undefined && id === hoveredId;
84
+ }
85
+ function setHoveredSelectableId(id) {
86
+ if (hoveredId === id)
87
+ return;
88
+ hoveredId = id;
89
+ for (const listener of listeners)
90
+ listener();
91
+ }
92
+ function clearHoveredSelectableId(id) {
93
+ if (id !== undefined && hoveredId === id)
94
+ setHoveredSelectableId(undefined);
95
+ }
96
+
97
+ // packages/cli/src/app-opentui/render/text.ts
77
98
  var TRANSPARENT = RGBA.fromInts(0, 0, 0, 0);
99
+ var HOVER_BG = RGBA.fromHex(RIG_UI.hover);
100
+ function lineIsClickable(line) {
101
+ return line?.selectable !== undefined || line?.selectableIndex !== undefined;
102
+ }
103
+ function lineSelectableId(line) {
104
+ return line?.selectable?.id ?? line?.selectableId;
105
+ }
106
+ function lineBackground(line) {
107
+ if (line?.bg)
108
+ return RGBA.fromHex(line.bg);
109
+ const id = lineSelectableId(line);
110
+ if (id !== undefined && isHovered(id))
111
+ return HOVER_BG;
112
+ return TRANSPARENT;
113
+ }
78
114
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
79
115
  return (event) => {
80
116
  const currentLine = currentLineRef();
81
- if (currentLine?.selectableIndex === undefined)
117
+ if (!lineIsClickable(currentLine))
82
118
  return;
83
119
  onLineMouseDown?.(currentLine, event);
84
120
  };
85
121
  }
122
+ function hoverHandlers(currentLineRef) {
123
+ return {
124
+ onMouseOver: () => {
125
+ const id = lineSelectableId(currentLineRef());
126
+ if (id !== undefined)
127
+ setHoveredSelectableId(id);
128
+ },
129
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
130
+ };
131
+ }
86
132
  function createFlowTextLine(renderer, id, onLineMouseDown) {
87
133
  let currentLine;
88
134
  const renderable = new TextRenderable(renderer, {
@@ -93,7 +139,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
93
139
  flexShrink: 0,
94
140
  fg: RIG_UI.ink2,
95
141
  selectable: true,
96
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
142
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
143
+ ...hoverHandlers(() => currentLine)
97
144
  });
98
145
  renderable.setRigSceneLine = (line) => {
99
146
  currentLine = line;
@@ -107,7 +154,7 @@ function applyFlowTextLine(renderable, line, width) {
107
154
  renderable.width = Math.max(1, width);
108
155
  renderable.content = line?.styledText ?? line?.text ?? "";
109
156
  renderable.fg = line?.fg ?? RIG_UI.ink2;
110
- renderable.bg = line?.bg ?? TRANSPARENT;
157
+ renderable.bg = lineBackground(line);
111
158
  renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
112
159
  }
113
160
 
@@ -12,6 +12,7 @@ var RIG_UI = {
12
12
  bg2: "#0b0c0e",
13
13
  panel: "#101115",
14
14
  panel2: "#14161b",
15
+ hover: "#181b24",
15
16
  glass: "#1e2230",
16
17
  border: "#2a2e3a",
17
18
  ink: "#f4f5f8",
@@ -37,6 +37,7 @@ var RIG_UI = {
37
37
  bg2: "#0b0c0e",
38
38
  panel: "#101115",
39
39
  panel2: "#14161b",
40
+ hover: "#181b24",
40
41
  glass: "#1e2230",
41
42
  border: "#2a2e3a",
42
43
  ink: "#f4f5f8",
@@ -6,6 +6,19 @@ import type { AppSceneLine } from "../types";
6
6
  * this is the one selection-highlight mechanism, plumbed end-to-end here so
7
7
  * scenes only set `bg` on the AppSceneLine and never touch RGBA. */
8
8
  export declare const TRANSPARENT: RGBA;
9
+ /** A line is clickable when it carries a selectable. The imperative shell stamps
10
+ * `selectableId`/`selectableIndex` via remapSelectableLine; the @opentui/react
11
+ * shell does not, so it only carries `selectable`. Check all three so clicks +
12
+ * hover work identically in both shells. */
13
+ export declare function lineIsClickable(line: AppSceneLine | undefined): boolean;
14
+ /** The stable id used to key hover (and click resolution): the selectable's id,
15
+ * falling back to the imperative-stamped selectableId. Identical in both shells
16
+ * (remapSelectableLine sets selectableId = selectable.id). */
17
+ export declare function lineSelectableId(line: AppSceneLine | undefined): string | undefined;
18
+ /** The bg a line paints: an explicit `bg` (a selected row) always wins;
19
+ * otherwise a clickable row that is currently mouse-hovered gets the hover bar;
20
+ * otherwise transparent so the panel ground shows through. */
21
+ export declare function lineBackground(line: AppSceneLine | undefined): RGBA;
9
22
  export type TextLineRenderable = TextRenderable & {
10
23
  setRigSceneLine?(line: AppSceneLine | undefined): void;
11
24
  };