@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.
- package/dist/bin/rig.js +79 -18
- package/dist/src/app-opentui/bootstrap.js +79 -18
- package/dist/src/app-opentui/command-palette.js +1 -0
- package/dist/src/app-opentui/drone.js +1 -0
- package/dist/src/app-opentui/index.js +61 -7
- package/dist/src/app-opentui/list-search.d.ts +5 -1
- package/dist/src/app-opentui/list-search.js +2 -2
- package/dist/src/app-opentui/react/App.js +67 -8
- package/dist/src/app-opentui/react/Backdrop.js +1 -0
- package/dist/src/app-opentui/react/ChromeHost.js +7 -0
- package/dist/src/app-opentui/react/SceneFrameView.js +55 -5
- package/dist/src/app-opentui/react/launch.js +67 -8
- package/dist/src/app-opentui/react/syntax.js +1 -0
- package/dist/src/app-opentui/registry.js +3 -5
- package/dist/src/app-opentui/render/graphics.js +1 -0
- package/dist/src/app-opentui/render/hover.d.ts +11 -0
- package/dist/src/app-opentui/render/hover.js +34 -0
- package/dist/src/app-opentui/render/native-host.js +1 -0
- package/dist/src/app-opentui/render/panels.js +50 -3
- package/dist/src/app-opentui/render/preloader.js +1 -0
- package/dist/src/app-opentui/render/scene.js +1 -0
- package/dist/src/app-opentui/render/text.d.ts +13 -0
- package/dist/src/app-opentui/render/text.js +54 -5
- package/dist/src/app-opentui/render/type-bar.js +1 -0
- package/dist/src/app-opentui/runtime.js +61 -7
- package/dist/src/app-opentui/scenes/command.js +1 -0
- package/dist/src/app-opentui/scenes/doctor.js +1 -0
- package/dist/src/app-opentui/scenes/error.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/agent.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/browser.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/dist.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/git.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/github.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/harness.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/index.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/kit.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/profile.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/queue.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/remote.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/review.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/setup.js +1 -0
- package/dist/src/app-opentui/scenes/family-domains/stats.js +1 -0
- package/dist/src/app-opentui/scenes/family.js +1 -0
- package/dist/src/app-opentui/scenes/fleet.js +3 -5
- package/dist/src/app-opentui/scenes/handoff.js +1 -0
- package/dist/src/app-opentui/scenes/help.js +1 -0
- package/dist/src/app-opentui/scenes/inbox.js +1 -0
- package/dist/src/app-opentui/scenes/init.js +1 -0
- package/dist/src/app-opentui/scenes/inspect.js +1 -0
- package/dist/src/app-opentui/scenes/main.js +1 -0
- package/dist/src/app-opentui/scenes/pi.js +1 -0
- package/dist/src/app-opentui/scenes/plugin.js +1 -0
- package/dist/src/app-opentui/scenes/repo.js +1 -0
- package/dist/src/app-opentui/scenes/run-detail.js +1 -0
- package/dist/src/app-opentui/scenes/server.js +1 -0
- package/dist/src/app-opentui/scenes/tasks.js +3 -5
- package/dist/src/app-opentui/scenes/workspace.js +1 -0
- package/dist/src/app-opentui/selectable.js +1 -0
- package/dist/src/app-opentui/theme.d.ts +1 -0
- package/dist/src/app-opentui/theme.js +1 -0
- 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
|
|
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
|
|
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
|
|
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
|
-
|
|
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%" },
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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%" },
|
|
@@ -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
|
|
19351
|
-
return
|
|
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)
|
|
@@ -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
|
+
};
|
|
@@ -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
|
|
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
|
|
157
|
+
renderable.bg = lineBackground(line);
|
|
111
158
|
renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
|
|
112
159
|
}
|
|
113
160
|
|
|
@@ -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
|
};
|