@hansenexus/hud 0.1.1 → 0.3.0

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 (100) hide show
  1. package/README.md +106 -25
  2. package/dist/define-hud-BHQR8Lbv.d.ts +31 -0
  3. package/dist/index.d.ts +36 -0
  4. package/dist/index.js +1198 -0
  5. package/dist/next.d.ts +48 -0
  6. package/dist/next.js +77 -0
  7. package/dist/plugins/vitals.d.ts +25 -0
  8. package/dist/plugins/vitals.js +109 -0
  9. package/dist/plugins-1QmTmZyL.d.ts +76 -0
  10. package/dist/plugins-CzUiTn_r.js +68 -0
  11. package/dist/server.d.ts +39 -0
  12. package/dist/server.js +106 -0
  13. package/package.json +55 -133
  14. package/chunk-20zke7cs.js +0 -574
  15. package/chunk-24vrg16w.js +0 -39
  16. package/chunk-50pq4sg6.js +0 -41
  17. package/chunk-5gtx3pza.js +0 -9
  18. package/chunk-6cdpasm9.js +0 -79
  19. package/chunk-6jt8yg4m.js +0 -117
  20. package/chunk-6ngkpwz7.js +0 -127
  21. package/chunk-71se605m.js +0 -85
  22. package/chunk-82nm9wcg.js +0 -316
  23. package/chunk-9hw5r9y1.js +0 -67
  24. package/chunk-c5y856ad.js +0 -98
  25. package/chunk-edq4jqch.js +0 -89
  26. package/chunk-emfnvz4p.js +0 -166
  27. package/chunk-h0hmjdqa.js +0 -264
  28. package/chunk-hc2g0n35.js +0 -24
  29. package/chunk-hex3wqag.js +0 -179
  30. package/chunk-kvxve0hx.js +0 -140
  31. package/chunk-kyeb6qeq.js +0 -95
  32. package/chunk-mz55rvw3.js +0 -172
  33. package/chunk-nm82wr8r.js +0 -58
  34. package/chunk-q15xwpy8.js +0 -48
  35. package/chunk-q96mkjve.js +0 -68
  36. package/chunk-tczzx083.js +0 -26
  37. package/chunk-tf774c4w.js +0 -115
  38. package/chunk-v086j53b.js +0 -19
  39. package/chunk-vjh0d29g.js +0 -52
  40. package/chunk-xezxydm3.js +0 -47
  41. package/chunk-xztw0xyt.js +0 -113
  42. package/chunk-yn1d38pb.js +0 -172
  43. package/core/access.d.mts +0 -53
  44. package/core/access.js +0 -27
  45. package/core/api-types.d.mts +0 -146
  46. package/core/api-types.js +0 -9
  47. package/core/capabilities.d.mts +0 -27
  48. package/core/capabilities.js +0 -14
  49. package/core/capture-buffer.d.mts +0 -37
  50. package/core/capture-buffer.js +0 -9
  51. package/core/force-state.d.mts +0 -68
  52. package/core/force-state.js +0 -21
  53. package/core/mock-cookie.d.mts +0 -30
  54. package/core/mock-cookie.js +0 -15
  55. package/core/types.d.mts +0 -59
  56. package/core/types.js +0 -9
  57. package/hud-provider.d.mts +0 -38
  58. package/hud-provider.js +0 -15
  59. package/hud.d.mts +0 -15
  60. package/hud.js +0 -18
  61. package/index.d.mts +0 -94
  62. package/index.js +0 -170
  63. package/lazy-panel.d.mts +0 -28
  64. package/lazy-panel.js +0 -11
  65. package/panels/cicd-panel.d.mts +0 -9
  66. package/panels/cicd-panel.js +0 -13
  67. package/panels/debug-info-panel.d.mts +0 -21
  68. package/panels/debug-info-panel.js +0 -9
  69. package/panels/dispatch-panel.d.mts +0 -10
  70. package/panels/dispatch-panel.js +0 -14
  71. package/panels/env-info-panel.d.mts +0 -9
  72. package/panels/env-info-panel.js +0 -12
  73. package/panels/feature-flags-panel.d.mts +0 -26
  74. package/panels/feature-flags-panel.js +0 -9
  75. package/panels/force-state-panel.d.mts +0 -11
  76. package/panels/force-state-panel.js +0 -113
  77. package/panels/info-row.d.mts +0 -21
  78. package/panels/info-row.js +0 -14
  79. package/panels/mock-seed-panel.d.mts +0 -15
  80. package/panels/mock-seed-panel.js +0 -14
  81. package/panels/network-console-panel.d.mts +0 -6
  82. package/panels/network-console-panel.js +0 -9
  83. package/panels/role-switcher-panel.d.mts +0 -28
  84. package/panels/role-switcher-panel.js +0 -9
  85. package/panels/sessions-panel.d.mts +0 -6
  86. package/panels/sessions-panel.js +0 -13
  87. package/panels/tokens-panel.d.mts +0 -38
  88. package/panels/tokens-panel.js +0 -9
  89. package/panels/unlock-panel.d.mts +0 -33
  90. package/panels/unlock-panel.js +0 -14
  91. package/panels/variants-panel.d.mts +0 -51
  92. package/panels/variants-panel.js +0 -12
  93. package/panels/vitals-panel.d.mts +0 -11
  94. package/panels/vitals-panel.js +0 -15
  95. package/server/guard.d.mts +0 -42
  96. package/server/guard.js +0 -12
  97. package/server/unlock.d.mts +0 -28
  98. package/server/unlock.js +0 -108
  99. package/state-boundary.d.mts +0 -25
  100. package/state-boundary.js +0 -54
package/chunk-82nm9wcg.js DELETED
@@ -1,316 +0,0 @@
1
- import {
2
- Badge,
3
- Button,
4
- cn
5
- } from "./chunk-xztw0xyt.js";
6
-
7
- // grabber/grabber-store.ts
8
- var state = { mode: "idle", payload: null };
9
- var listeners = new Set;
10
- function setState(next) {
11
- state = next;
12
- for (const listener of listeners)
13
- listener();
14
- }
15
- function getGrabberState() {
16
- return state;
17
- }
18
- function subscribeGrabber(listener) {
19
- listeners.add(listener);
20
- return () => listeners.delete(listener);
21
- }
22
- function startGrab() {
23
- setState({ ...state, mode: "grabbing" });
24
- }
25
- function cancelGrab() {
26
- setState({ ...state, mode: "idle" });
27
- }
28
- function completeGrab(payload) {
29
- setState({ mode: "idle", payload });
30
- }
31
- function clearGrabbedPayload() {
32
- setState({ ...state, payload: null });
33
- }
34
-
35
- // ../dev-tools/drawer/dev-drawer-provider.tsx
36
- import {
37
- createContext,
38
- useCallback,
39
- useContext,
40
- useEffect,
41
- useMemo,
42
- useState
43
- } from "react";
44
- import { jsx } from "react/jsx-runtime";
45
- "use client";
46
- var DevDrawerContext = createContext(null);
47
- var DEFAULTS = {
48
- defaultHeight: 40,
49
- minHeight: 25,
50
- maxHeight: 80,
51
- shortcutKey: "d"
52
- };
53
- function loadStored(storageKey) {
54
- if (!storageKey || typeof window === "undefined")
55
- return {};
56
- try {
57
- const raw = localStorage.getItem(storageKey);
58
- if (!raw)
59
- return {};
60
- const parsed = JSON.parse(raw);
61
- return {
62
- height: typeof parsed.height === "number" ? parsed.height : undefined,
63
- activeTab: typeof parsed.activeTab === "string" ? parsed.activeTab : undefined
64
- };
65
- } catch {
66
- return {};
67
- }
68
- }
69
- function persist(storageKey, state2) {
70
- if (!storageKey || typeof window === "undefined")
71
- return;
72
- try {
73
- localStorage.setItem(storageKey, JSON.stringify(state2));
74
- } catch {}
75
- }
76
- function DevDrawerProvider({ config, children }) {
77
- const defaultHeight = config?.defaultHeight ?? DEFAULTS.defaultHeight;
78
- const minHeight = config?.minHeight ?? DEFAULTS.minHeight;
79
- const maxHeight = config?.maxHeight ?? DEFAULTS.maxHeight;
80
- const shortcutKey = config?.shortcutKey === null ? null : config?.shortcutKey ?? DEFAULTS.shortcutKey;
81
- const storageKey = config?.storageKey;
82
- const [isOpen, setIsOpen] = useState(false);
83
- const [activeTab, setActiveTabState] = useState(config?.defaultActiveTab ?? null);
84
- const [height, setHeightState] = useState(defaultHeight);
85
- useEffect(() => {
86
- const stored = loadStored(storageKey);
87
- if (stored.height != null)
88
- setHeightState(stored.height);
89
- if (stored.activeTab != null)
90
- setActiveTabState(stored.activeTab);
91
- }, [storageKey]);
92
- useEffect(() => {
93
- persist(storageKey, { height, activeTab });
94
- }, [storageKey, height, activeTab]);
95
- useEffect(() => {
96
- if (!shortcutKey)
97
- return;
98
- const handler = (event) => {
99
- if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key.toLowerCase() === shortcutKey) {
100
- event.preventDefault();
101
- setIsOpen((prev) => !prev);
102
- }
103
- };
104
- window.addEventListener("keydown", handler);
105
- return () => window.removeEventListener("keydown", handler);
106
- }, [shortcutKey]);
107
- const toggleDrawer = useCallback(() => setIsOpen((prev) => !prev), []);
108
- const openDrawer = useCallback(() => setIsOpen(true), []);
109
- const closeDrawer = useCallback(() => setIsOpen(false), []);
110
- const setActiveTab = useCallback((tab) => setActiveTabState(tab), []);
111
- const setHeight = useCallback((next) => setHeightState(Math.min(maxHeight, Math.max(minHeight, next))), [minHeight, maxHeight]);
112
- const value = useMemo(() => ({
113
- isOpen,
114
- activeTab,
115
- height,
116
- minHeight,
117
- maxHeight,
118
- toggleDrawer,
119
- openDrawer,
120
- closeDrawer,
121
- setActiveTab,
122
- setHeight
123
- }), [
124
- isOpen,
125
- activeTab,
126
- height,
127
- minHeight,
128
- maxHeight,
129
- toggleDrawer,
130
- openDrawer,
131
- closeDrawer,
132
- setActiveTab,
133
- setHeight
134
- ]);
135
- return /* @__PURE__ */ jsx(DevDrawerContext.Provider, {
136
- value,
137
- children
138
- });
139
- }
140
- function useDevDrawer() {
141
- const ctx = useContext(DevDrawerContext);
142
- if (!ctx)
143
- throw new Error("useDevDrawer must be used within a DevDrawerProvider");
144
- return ctx;
145
- }
146
-
147
- // ../dev-tools/drawer/dev-drawer.tsx
148
- import { Wrench, X } from "lucide-react";
149
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
150
- "use client";
151
- function DevDrawer({
152
- tabs,
153
- children,
154
- title = "Dev Toolbar",
155
- badgeLabel = "DEV",
156
- headerIcon: HeaderIcon = Wrench,
157
- className
158
- }) {
159
- const { isOpen, activeTab, setActiveTab, closeDrawer, height, minHeight, maxHeight, setHeight } = useDevDrawer();
160
- if (!isOpen)
161
- return null;
162
- const resolvedTabs = tabs && tabs.length > 0 ? tabs : null;
163
- const currentTab = resolvedTabs?.find((tab) => tab.id === activeTab) ?? resolvedTabs?.[0];
164
- const handleResizeStart = (event) => {
165
- event.preventDefault();
166
- const startY = event.clientY;
167
- const startHeight = height;
168
- function onMove(moveEvent) {
169
- const delta = startY - moveEvent.clientY;
170
- const deltaPercent = delta / window.innerHeight * 100;
171
- setHeight(startHeight + deltaPercent);
172
- }
173
- function onUp() {
174
- document.removeEventListener("pointermove", onMove);
175
- document.removeEventListener("pointerup", onUp);
176
- }
177
- document.addEventListener("pointermove", onMove);
178
- document.addEventListener("pointerup", onUp);
179
- };
180
- return /* @__PURE__ */ jsxs("div", {
181
- className: cn("fixed inset-x-0 bottom-0 z-50 border-t border-border/50 bg-background/95 backdrop-blur-md", className),
182
- style: { height: `${height}vh` },
183
- children: [
184
- /* @__PURE__ */ jsx2("div", {
185
- role: "slider",
186
- tabIndex: 0,
187
- "aria-label": "Resize dev drawer",
188
- "aria-orientation": "horizontal",
189
- "aria-valuemin": Math.round(minHeight),
190
- "aria-valuemax": Math.round(maxHeight),
191
- "aria-valuenow": Math.round(height),
192
- className: "absolute inset-x-0 -top-1 flex h-3 cursor-ns-resize items-center justify-center focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
193
- onPointerDown: handleResizeStart,
194
- onKeyDown: (event) => {
195
- if (event.key === "ArrowUp") {
196
- event.preventDefault();
197
- setHeight(height + 2);
198
- } else if (event.key === "ArrowDown") {
199
- event.preventDefault();
200
- setHeight(height - 2);
201
- }
202
- },
203
- children: /* @__PURE__ */ jsx2("div", {
204
- className: "h-1 w-8 bg-muted-foreground/30"
205
- })
206
- }),
207
- /* @__PURE__ */ jsxs("div", {
208
- className: "flex h-10 items-center justify-between border-b border-border/50 px-3",
209
- children: [
210
- /* @__PURE__ */ jsxs("div", {
211
- className: "flex items-center gap-2",
212
- children: [
213
- /* @__PURE__ */ jsx2(HeaderIcon, {
214
- className: "h-3.5 w-3.5 text-amber-500"
215
- }),
216
- /* @__PURE__ */ jsx2("span", {
217
- className: "text-xs font-semibold",
218
- children: title
219
- }),
220
- badgeLabel ? /* @__PURE__ */ jsx2(Badge, {
221
- variant: "outline",
222
- className: "h-4 border-amber-500/30 px-1 text-[9px] text-amber-500",
223
- children: badgeLabel
224
- }) : null
225
- ]
226
- }),
227
- /* @__PURE__ */ jsxs("div", {
228
- className: "flex items-center gap-1",
229
- children: [
230
- resolvedTabs?.map((tab) => {
231
- const Icon = tab.icon;
232
- const isActive = tab.id === (currentTab?.id ?? null);
233
- return /* @__PURE__ */ jsxs(Button, {
234
- variant: isActive ? "secondary" : "ghost",
235
- size: "sm",
236
- className: "h-6 gap-1 px-2 text-[10px]",
237
- onClick: () => setActiveTab(tab.id),
238
- children: [
239
- Icon ? /* @__PURE__ */ jsx2(Icon, {
240
- className: "h-3 w-3"
241
- }) : null,
242
- tab.label
243
- ]
244
- }, tab.id);
245
- }),
246
- resolvedTabs ? /* @__PURE__ */ jsx2("div", {
247
- className: "mx-1 h-4 w-px bg-border"
248
- }) : null,
249
- /* @__PURE__ */ jsx2(Button, {
250
- variant: "ghost",
251
- size: "icon",
252
- className: "h-6 w-6",
253
- onClick: closeDrawer,
254
- children: /* @__PURE__ */ jsx2(X, {
255
- className: "h-3 w-3"
256
- })
257
- })
258
- ]
259
- })
260
- ]
261
- }),
262
- /* @__PURE__ */ jsx2("div", {
263
- className: "h-[calc(100%-2.5rem)] overflow-y-auto px-3 py-3",
264
- children: resolvedTabs ? currentTab?.content : children
265
- })
266
- ]
267
- });
268
- }
269
- // ../ui/components/tooltip.tsx
270
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
271
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
272
- "use client";
273
-
274
- // ../dev-tools/fab/dev-floating-menu.tsx
275
- import { MoreHorizontal } from "lucide-react";
276
- import { AnimatePresence, motion } from "motion/react";
277
-
278
- // ../ui/components/kbd.tsx
279
- import { jsx as jsx4 } from "react/jsx-runtime";
280
-
281
- // ../dev-tools/fab/fab-action.tsx
282
- import Link from "next/link";
283
- import { useCallback as useCallback2, useRef } from "react";
284
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
285
- "use client";
286
- var baseClass = cn("size-9 rounded-full", "bg-background/80 backdrop-blur-sm border border-border/50", "shadow-sm hover:shadow-md transition-all duration-200");
287
- var bauhausBaseClass = cn("size-9 rounded-full border backdrop-blur-2xl transition-all duration-200", "border-[rgb(var(--bauhaus-border-strong))] bg-bauhaus-bg/60 text-bauhaus-fg/55", "shadow-[0_6px_24px_rgba(0,0,0,0.45)]", "hover:bg-bauhaus-bg/80 hover:text-[var(--fab-ink)] hover:border-[var(--fab-ink)]");
288
-
289
- // ../dev-tools/fab/use-fab-state.ts
290
- import { useCallback as useCallback3, useEffect as useEffect2, useState as useState2 } from "react";
291
- "use client";
292
-
293
- // ../dev-tools/fab/dev-floating-menu.tsx
294
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
295
- "use client";
296
- // ../dev-tools/fab/dock-context.tsx
297
- import {
298
- createContext as createContext2,
299
- useCallback as useCallback4,
300
- useContext as useContext2,
301
- useEffect as useEffect3,
302
- useMemo as useMemo2,
303
- useState as useState3
304
- } from "react";
305
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
306
- "use client";
307
- var FloatingDockContext = createContext2(null);
308
- // ../dev-tools/gate/dev-only.tsx
309
- import { jsx as jsx8, Fragment } from "react/jsx-runtime";
310
- "use client";
311
- // ../dev-tools/panels/variants-link-panel.tsx
312
- import { ArrowUpRight, Beaker } from "lucide-react";
313
- import Link2 from "next/link";
314
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
315
- "use client";
316
- export { getGrabberState, subscribeGrabber, startGrab, cancelGrab, completeGrab, clearGrabbedPayload, DevDrawerProvider, useDevDrawer, DevDrawer };
package/chunk-9hw5r9y1.js DELETED
@@ -1,67 +0,0 @@
1
- import {
2
- hasCapability
3
- } from "./chunk-vjh0d29g.js";
4
-
5
- // hud-provider.tsx
6
- import {
7
- createContext,
8
- useCallback,
9
- useContext,
10
- useEffect,
11
- useMemo,
12
- useState
13
- } from "react";
14
- import { jsx } from "react/jsx-runtime";
15
- "use client";
16
- var HudContext = createContext(null);
17
- function HudProvider({ config, env, panels: basePanels, children }) {
18
- const [sources, setSources] = useState({});
19
- const registerSource = useCallback((id, source) => {
20
- setSources((prev) => ({ ...prev, [id]: source }));
21
- }, []);
22
- const unregisterSource = useCallback((id) => {
23
- setSources((prev) => {
24
- if (!(id in prev))
25
- return prev;
26
- const next = { ...prev };
27
- delete next[id];
28
- return next;
29
- });
30
- }, []);
31
- const can = useCallback((capability) => hasCapability(env, capability), [env]);
32
- const panels = useMemo(() => {
33
- const registered = Object.values(sources).sort((a, b) => (a.order ?? 0) - (b.order ?? 0)).flatMap((source) => source.panels);
34
- return [...basePanels ?? [], ...registered].filter((panel) => can(panel.capability)).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
35
- }, [basePanels, sources, can]);
36
- const value = useMemo(() => ({
37
- config,
38
- env,
39
- name: config.name ?? "hud",
40
- can,
41
- panels,
42
- registerSource,
43
- unregisterSource
44
- }), [config, env, can, panels, registerSource, unregisterSource]);
45
- return /* @__PURE__ */ jsx(HudContext.Provider, {
46
- value,
47
- children
48
- });
49
- }
50
- function useHud() {
51
- const ctx = useContext(HudContext);
52
- if (!ctx)
53
- throw new Error("useHud must be used within a HudProvider");
54
- return ctx;
55
- }
56
- function useHudSafe() {
57
- return useContext(HudContext);
58
- }
59
- function useRegisterHudPanels(id, panels, order = 0) {
60
- const ctx = useContext(HudContext);
61
- useEffect(() => {
62
- ctx?.registerSource(id, { panels, order });
63
- }, [ctx, id, panels, order]);
64
- useEffect(() => () => ctx?.unregisterSource(id), [ctx, id]);
65
- }
66
-
67
- export { HudProvider, useHud, useHudSafe, useRegisterHudPanels };
package/chunk-c5y856ad.js DELETED
@@ -1,98 +0,0 @@
1
- // core/force-state.ts
2
- var FORCED_STATES = ["loading", "empty", "error"];
3
- var FORCE_STATE_PARAM = "__state";
4
- var FORCE_STATE_MARKER = "__HN_FORCE_STATE__";
5
- function isForcedState(value) {
6
- return FORCED_STATES.includes(value);
7
- }
8
- function parseForceStateParam(value) {
9
- if (!value)
10
- return null;
11
- const separator = value.lastIndexOf(":");
12
- if (separator === -1)
13
- return isForcedState(value) ? { state: value, target: null } : null;
14
- const target = value.slice(0, separator);
15
- const state = value.slice(separator + 1);
16
- if (!target || !isForcedState(state))
17
- return null;
18
- return { state, target };
19
- }
20
- function forceStateParamFromSearch(search) {
21
- return parseForceStateParam(new URLSearchParams(search).get(FORCE_STATE_PARAM));
22
- }
23
- function resolveForcedState(snapshot, boundary) {
24
- const override = snapshot.overrides[boundary.id];
25
- if (override)
26
- return override;
27
- const { param } = snapshot;
28
- if (!param)
29
- return null;
30
- if (param.target !== null)
31
- return param.target === boundary.id ? param.state : null;
32
- return boundary.parentId === null ? param.state : null;
33
- }
34
-
35
- class ForceStateStore {
36
- registrations = new Map;
37
- overrides = {};
38
- search = "";
39
- snapshot = { boundaries: [], overrides: {}, param: null };
40
- listeners = new Set;
41
- getSnapshot = () => this.snapshot;
42
- subscribe = (listener) => {
43
- this.listeners.add(listener);
44
- return () => {
45
- this.listeners.delete(listener);
46
- };
47
- };
48
- register(id, parentId) {
49
- const existing = this.registrations.get(id);
50
- this.registrations.set(id, { parentId, count: (existing?.count ?? 0) + 1 });
51
- this.emit();
52
- return () => {
53
- const current = this.registrations.get(id);
54
- if (!current)
55
- return;
56
- if (current.count > 1)
57
- this.registrations.set(id, { ...current, count: current.count - 1 });
58
- else
59
- this.registrations.delete(id);
60
- this.emit();
61
- };
62
- }
63
- force(id, state) {
64
- const next = { ...this.overrides };
65
- if (state)
66
- next[id] = state;
67
- else
68
- delete next[id];
69
- this.overrides = next;
70
- this.emit();
71
- }
72
- clearOverrides() {
73
- this.overrides = {};
74
- this.emit();
75
- }
76
- syncSearch(search) {
77
- if (search === this.search)
78
- return;
79
- this.search = search;
80
- this.emit();
81
- }
82
- emit() {
83
- this.snapshot = {
84
- boundaries: [...this.registrations].map(([id, { parentId }]) => ({ id, parentId })),
85
- overrides: this.overrides,
86
- param: forceStateParamFromSearch(this.search)
87
- };
88
- for (const listener of this.listeners)
89
- listener();
90
- }
91
- }
92
- function getForceStateStore() {
93
- const holder = globalThis;
94
- holder[FORCE_STATE_MARKER] ??= new ForceStateStore;
95
- return holder[FORCE_STATE_MARKER];
96
- }
97
-
98
- export { FORCED_STATES, FORCE_STATE_PARAM, FORCE_STATE_MARKER, parseForceStateParam, forceStateParamFromSearch, resolveForcedState, ForceStateStore, getForceStateStore };
package/chunk-edq4jqch.js DELETED
@@ -1,89 +0,0 @@
1
- import {
2
- bridgeFetch,
3
- getBridgeInfo
4
- } from "./chunk-50pq4sg6.js";
5
- import {
6
- useHud
7
- } from "./chunk-9hw5r9y1.js";
8
- import {
9
- LoadingSpinner,
10
- PanelSection
11
- } from "./chunk-kyeb6qeq.js";
12
- import {
13
- Badge
14
- } from "./chunk-xztw0xyt.js";
15
-
16
- // panels/sessions-panel.tsx
17
- import { CircleDot } from "lucide-react";
18
- import { useEffect, useState } from "react";
19
- import { jsx, jsxs } from "react/jsx-runtime";
20
- "use client";
21
- function SessionsPanel() {
22
- const { config } = useHud();
23
- const [state, setState] = useState({ kind: "loading" });
24
- useEffect(() => {
25
- let cancelled = false;
26
- async function load() {
27
- const info = await getBridgeInfo(config.apiBase ?? "/api/hud");
28
- if (cancelled)
29
- return;
30
- if (!info) {
31
- setState({ kind: "no-bridge" });
32
- return;
33
- }
34
- try {
35
- const res = await bridgeFetch(info, "/sessions");
36
- const sessions = await res.json();
37
- if (!cancelled)
38
- setState({ kind: "ready", sessions });
39
- } catch {
40
- if (!cancelled)
41
- setState({ kind: "no-bridge" });
42
- }
43
- }
44
- load();
45
- const timer = setInterval(() => void load(), 30000);
46
- return () => {
47
- cancelled = true;
48
- clearInterval(timer);
49
- };
50
- }, [config.apiBase]);
51
- if (state.kind === "loading")
52
- return /* @__PURE__ */ jsx(LoadingSpinner, {});
53
- if (state.kind === "no-bridge") {
54
- return /* @__PURE__ */ jsx("p", {
55
- className: "px-2 text-[10px] text-amber-500",
56
- children: "bridge not reachable — run `bun hud:bridge` in the repo to see local Claude sessions."
57
- });
58
- }
59
- return /* @__PURE__ */ jsxs(PanelSection, {
60
- icon: CircleDot,
61
- title: "Claude sessions · this machine",
62
- children: [
63
- state.sessions.length === 0 && /* @__PURE__ */ jsx("p", {
64
- className: "px-2 text-[10px] text-muted-foreground/60",
65
- children: "No active sessions."
66
- }),
67
- state.sessions.map((session) => /* @__PURE__ */ jsxs("div", {
68
- className: "flex items-center gap-2 px-2 py-1 font-mono text-[10.5px]",
69
- children: [
70
- /* @__PURE__ */ jsx(Badge, {
71
- variant: "outline",
72
- className: `h-4 px-1.5 text-[9px] ${session.idleSeconds < 120 ? "text-emerald-500" : "text-muted-foreground"}`,
73
- children: session.idleSeconds < 120 ? "active" : `idle ${Math.round(session.idleSeconds / 60)} m`
74
- }),
75
- /* @__PURE__ */ jsx("span", {
76
- className: "min-w-0 flex-1 truncate",
77
- children: session.name ?? session.sessionId.slice(0, 12)
78
- }),
79
- /* @__PURE__ */ jsx("span", {
80
- className: "max-w-[200px] truncate text-muted-foreground/60",
81
- children: session.branch || "—"
82
- })
83
- ]
84
- }, session.sessionId))
85
- ]
86
- });
87
- }
88
-
89
- export { SessionsPanel };