@hansenexus/hud 0.1.0 → 0.2.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.
- package/README.md +42 -23
- package/dist/index.d.ts +39 -0
- package/dist/index.js +399 -0
- package/package.json +45 -136
- package/chunk-0cj8dkk7.js +0 -127
- package/chunk-1atxwdhw.js +0 -48
- package/chunk-24vrg16w.js +0 -39
- package/chunk-3j9sm249.js +0 -26
- package/chunk-50pq4sg6.js +0 -41
- package/chunk-5gtx3pza.js +0 -9
- package/chunk-6gw4x08j.js +0 -264
- package/chunk-6jt8yg4m.js +0 -117
- package/chunk-71se605m.js +0 -85
- package/chunk-82nm9wcg.js +0 -316
- package/chunk-8tam7r3h.js +0 -68
- package/chunk-babjpqkb.js +0 -52
- package/chunk-c5y856ad.js +0 -98
- package/chunk-ghxh8926.js +0 -172
- package/chunk-hc2g0n35.js +0 -24
- package/chunk-k0vr8dsy.js +0 -179
- package/chunk-k50yfp5d.js +0 -166
- package/chunk-kyeb6qeq.js +0 -95
- package/chunk-msqkkqw7.js +0 -140
- package/chunk-nm82wr8r.js +0 -58
- package/chunk-r06bpmy6.js +0 -79
- package/chunk-t9eh4t0b.js +0 -89
- package/chunk-tf774c4w.js +0 -115
- package/chunk-v086j53b.js +0 -19
- package/chunk-wspz08q7.js +0 -67
- package/chunk-xezxydm3.js +0 -47
- package/chunk-xjn0896g.js +0 -574
- package/chunk-xztw0xyt.js +0 -113
- package/chunk-zzrpd92r.js +0 -172
- package/core/access.d.mts +0 -53
- package/core/access.js +0 -27
- package/core/api-types.d.mts +0 -146
- package/core/api-types.js +0 -9
- package/core/capabilities.d.mts +0 -27
- package/core/capabilities.js +0 -14
- package/core/capture-buffer.d.mts +0 -37
- package/core/capture-buffer.js +0 -9
- package/core/force-state.d.mts +0 -68
- package/core/force-state.js +0 -21
- package/core/mock-cookie.d.mts +0 -30
- package/core/mock-cookie.js +0 -15
- package/core/types.d.mts +0 -59
- package/core/types.js +0 -9
- package/hud-provider.d.mts +0 -38
- package/hud-provider.js +0 -15
- package/hud.d.mts +0 -15
- package/hud.js +0 -18
- package/index.d.mts +0 -94
- package/index.js +0 -170
- package/lazy-panel.d.mts +0 -28
- package/lazy-panel.js +0 -11
- package/panels/cicd-panel.d.mts +0 -9
- package/panels/cicd-panel.js +0 -13
- package/panels/debug-info-panel.d.mts +0 -21
- package/panels/debug-info-panel.js +0 -9
- package/panels/dispatch-panel.d.mts +0 -10
- package/panels/dispatch-panel.js +0 -14
- package/panels/env-info-panel.d.mts +0 -9
- package/panels/env-info-panel.js +0 -12
- package/panels/feature-flags-panel.d.mts +0 -26
- package/panels/feature-flags-panel.js +0 -9
- package/panels/force-state-panel.d.mts +0 -11
- package/panels/force-state-panel.js +0 -113
- package/panels/info-row.d.mts +0 -21
- package/panels/info-row.js +0 -14
- package/panels/mock-seed-panel.d.mts +0 -15
- package/panels/mock-seed-panel.js +0 -14
- package/panels/network-console-panel.d.mts +0 -6
- package/panels/network-console-panel.js +0 -9
- package/panels/role-switcher-panel.d.mts +0 -28
- package/panels/role-switcher-panel.js +0 -9
- package/panels/sessions-panel.d.mts +0 -6
- package/panels/sessions-panel.js +0 -13
- package/panels/tokens-panel.d.mts +0 -38
- package/panels/tokens-panel.js +0 -9
- package/panels/unlock-panel.d.mts +0 -33
- package/panels/unlock-panel.js +0 -14
- package/panels/variants-panel.d.mts +0 -51
- package/panels/variants-panel.js +0 -12
- package/panels/vitals-panel.d.mts +0 -11
- package/panels/vitals-panel.js +0 -15
- package/server/guard.d.mts +0 -42
- package/server/guard.js +0 -12
- package/server/unlock.d.mts +0 -28
- package/server/unlock.js +0 -108
- package/state-boundary.d.mts +0 -25
- package/state-boundary.js +0 -54
package/chunk-xjn0896g.js
DELETED
|
@@ -1,574 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HudUnlockPanel,
|
|
3
|
-
useHudUnlock
|
|
4
|
-
} from "./chunk-msqkkqw7.js";
|
|
5
|
-
import {
|
|
6
|
-
DevDrawer,
|
|
7
|
-
DevDrawerProvider,
|
|
8
|
-
cancelGrab,
|
|
9
|
-
completeGrab,
|
|
10
|
-
getGrabberState,
|
|
11
|
-
subscribeGrabber,
|
|
12
|
-
useDevDrawer
|
|
13
|
-
} from "./chunk-82nm9wcg.js";
|
|
14
|
-
import {
|
|
15
|
-
getVitalsSnapshot
|
|
16
|
-
} from "./chunk-ghxh8926.js";
|
|
17
|
-
import {
|
|
18
|
-
captureBuffer
|
|
19
|
-
} from "./chunk-24vrg16w.js";
|
|
20
|
-
import {
|
|
21
|
-
hudRequiresUnlock,
|
|
22
|
-
resolveHudAccess
|
|
23
|
-
} from "./chunk-r06bpmy6.js";
|
|
24
|
-
import {
|
|
25
|
-
HudProvider,
|
|
26
|
-
useHud
|
|
27
|
-
} from "./chunk-wspz08q7.js";
|
|
28
|
-
import {
|
|
29
|
-
isHudVisible,
|
|
30
|
-
resolveHudEnv
|
|
31
|
-
} from "./chunk-babjpqkb.js";
|
|
32
|
-
import {
|
|
33
|
-
HUD_BUNDLE_MARKER
|
|
34
|
-
} from "./chunk-v086j53b.js";
|
|
35
|
-
|
|
36
|
-
// ../review-kit/rail/rail-store.ts
|
|
37
|
-
var tools = [];
|
|
38
|
-
var insetPx = 0;
|
|
39
|
-
var listeners = new Set;
|
|
40
|
-
function emit() {
|
|
41
|
-
tools = [...tools];
|
|
42
|
-
for (const listener of listeners)
|
|
43
|
-
listener();
|
|
44
|
-
}
|
|
45
|
-
function subscribeRail(listener) {
|
|
46
|
-
listeners.add(listener);
|
|
47
|
-
return () => listeners.delete(listener);
|
|
48
|
-
}
|
|
49
|
-
function getRailTools() {
|
|
50
|
-
return tools;
|
|
51
|
-
}
|
|
52
|
-
function registerRailTool(tool) {
|
|
53
|
-
const index = tools.findIndex((t) => t.id === tool.id);
|
|
54
|
-
if (index === -1)
|
|
55
|
-
tools.push(tool);
|
|
56
|
-
else
|
|
57
|
-
tools[index] = tool;
|
|
58
|
-
tools.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
59
|
-
emit();
|
|
60
|
-
}
|
|
61
|
-
function unregisterRailTool(id) {
|
|
62
|
-
tools = tools.filter((t) => t.id !== id);
|
|
63
|
-
emit();
|
|
64
|
-
}
|
|
65
|
-
function getRailInset() {
|
|
66
|
-
return insetPx;
|
|
67
|
-
}
|
|
68
|
-
var host = null;
|
|
69
|
-
function claimRailHost(token) {
|
|
70
|
-
if (host === null)
|
|
71
|
-
host = token;
|
|
72
|
-
return host === token;
|
|
73
|
-
}
|
|
74
|
-
function releaseRailHost(token) {
|
|
75
|
-
if (host === token)
|
|
76
|
-
host = null;
|
|
77
|
-
}
|
|
78
|
-
// ../review-kit/rail/tool-rail.tsx
|
|
79
|
-
import { useEffect as useEffect2, useId, useRef, useSyncExternalStore } from "react";
|
|
80
|
-
import { createPortal as createPortal2 } from "react-dom";
|
|
81
|
-
|
|
82
|
-
// ../review-kit/picker/element-picker.tsx
|
|
83
|
-
import { useEffect, useState } from "react";
|
|
84
|
-
import { createPortal } from "react-dom";
|
|
85
|
-
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
86
|
-
"use client";
|
|
87
|
-
var OVERLAY_MARKER = "data-hn-overlay";
|
|
88
|
-
var OVERLAY_Z_INDEX = 2147483000;
|
|
89
|
-
function ElementPicker({
|
|
90
|
-
active,
|
|
91
|
-
chromeSelector,
|
|
92
|
-
onPick,
|
|
93
|
-
onCancel,
|
|
94
|
-
hint = "Element wählen · Esc bricht ab",
|
|
95
|
-
accent = "#fbbf24",
|
|
96
|
-
accentText = "#3a2a00"
|
|
97
|
-
}) {
|
|
98
|
-
const [highlight, setHighlight] = useState(null);
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (!active) {
|
|
101
|
-
setHighlight(null);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const exclude = chromeSelector ? `[${OVERLAY_MARKER}],${chromeSelector}` : `[${OVERLAY_MARKER}]`;
|
|
105
|
-
document.body.style.cursor = "crosshair";
|
|
106
|
-
function targetFrom(event) {
|
|
107
|
-
const el = event.target;
|
|
108
|
-
if (!(el instanceof Element))
|
|
109
|
-
return null;
|
|
110
|
-
if (el.closest(exclude))
|
|
111
|
-
return null;
|
|
112
|
-
return el;
|
|
113
|
-
}
|
|
114
|
-
function onMove(event) {
|
|
115
|
-
const el = targetFrom(event);
|
|
116
|
-
if (!el) {
|
|
117
|
-
setHighlight(null);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const r = el.getBoundingClientRect();
|
|
121
|
-
setHighlight({
|
|
122
|
-
left: r.left,
|
|
123
|
-
top: r.top,
|
|
124
|
-
width: r.width,
|
|
125
|
-
height: r.height,
|
|
126
|
-
label: el.tagName.toLowerCase()
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function onClick(event) {
|
|
130
|
-
const el = targetFrom(event);
|
|
131
|
-
if (!el)
|
|
132
|
-
return;
|
|
133
|
-
event.preventDefault();
|
|
134
|
-
event.stopPropagation();
|
|
135
|
-
onPick(el, { clientX: event.clientX, clientY: event.clientY });
|
|
136
|
-
}
|
|
137
|
-
function onKey(event) {
|
|
138
|
-
if (event.key === "Escape")
|
|
139
|
-
onCancel();
|
|
140
|
-
}
|
|
141
|
-
document.addEventListener("mousemove", onMove, true);
|
|
142
|
-
document.addEventListener("click", onClick, true);
|
|
143
|
-
document.addEventListener("keydown", onKey, true);
|
|
144
|
-
return () => {
|
|
145
|
-
document.body.style.cursor = "";
|
|
146
|
-
document.removeEventListener("mousemove", onMove, true);
|
|
147
|
-
document.removeEventListener("click", onClick, true);
|
|
148
|
-
document.removeEventListener("keydown", onKey, true);
|
|
149
|
-
};
|
|
150
|
-
}, [active, chromeSelector, onPick, onCancel]);
|
|
151
|
-
if (!active || typeof document === "undefined")
|
|
152
|
-
return null;
|
|
153
|
-
const marker = { [OVERLAY_MARKER]: "" };
|
|
154
|
-
return createPortal(/* @__PURE__ */ jsxs("div", {
|
|
155
|
-
...marker,
|
|
156
|
-
style: { position: "fixed", inset: 0, zIndex: OVERLAY_Z_INDEX, pointerEvents: "none" },
|
|
157
|
-
children: [
|
|
158
|
-
/* @__PURE__ */ jsx("div", {
|
|
159
|
-
style: {
|
|
160
|
-
position: "fixed",
|
|
161
|
-
top: 0,
|
|
162
|
-
left: "50%",
|
|
163
|
-
transform: "translateX(-50%)",
|
|
164
|
-
background: accent,
|
|
165
|
-
color: accentText,
|
|
166
|
-
font: "700 11px ui-monospace, monospace",
|
|
167
|
-
padding: "3px 12px",
|
|
168
|
-
borderRadius: "0 0 6px 6px"
|
|
169
|
-
},
|
|
170
|
-
children: hint
|
|
171
|
-
}),
|
|
172
|
-
highlight && /* @__PURE__ */ jsxs(Fragment, {
|
|
173
|
-
children: [
|
|
174
|
-
/* @__PURE__ */ jsx("div", {
|
|
175
|
-
style: {
|
|
176
|
-
position: "fixed",
|
|
177
|
-
left: highlight.left - 2,
|
|
178
|
-
top: highlight.top - 2,
|
|
179
|
-
width: highlight.width + 4,
|
|
180
|
-
height: highlight.height + 4,
|
|
181
|
-
border: `1.5px solid ${accent}`,
|
|
182
|
-
background: "rgba(251,191,36,.08)",
|
|
183
|
-
borderRadius: 3
|
|
184
|
-
}
|
|
185
|
-
}),
|
|
186
|
-
/* @__PURE__ */ jsx("div", {
|
|
187
|
-
style: {
|
|
188
|
-
position: "fixed",
|
|
189
|
-
left: highlight.left - 2,
|
|
190
|
-
top: Math.max(highlight.top - 20, 0),
|
|
191
|
-
background: accent,
|
|
192
|
-
color: accentText,
|
|
193
|
-
font: "700 10px ui-monospace, monospace",
|
|
194
|
-
padding: "1px 6px",
|
|
195
|
-
borderRadius: 3
|
|
196
|
-
},
|
|
197
|
-
children: highlight.label
|
|
198
|
-
})
|
|
199
|
-
]
|
|
200
|
-
})
|
|
201
|
-
]
|
|
202
|
-
}), document.body);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// ../review-kit/rail/tool-rail.tsx
|
|
206
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
207
|
-
"use client";
|
|
208
|
-
function ToolRail() {
|
|
209
|
-
const token = useRef(Symbol("rail-host"));
|
|
210
|
-
const id = useId();
|
|
211
|
-
const tools2 = useSyncExternalStore(subscribeRail, getRailTools, getRailTools);
|
|
212
|
-
const inset = useSyncExternalStore(subscribeRail, getRailInset, getRailInset);
|
|
213
|
-
const isHost = claimRailHost(token.current);
|
|
214
|
-
useEffect2(() => {
|
|
215
|
-
const claimed = token.current;
|
|
216
|
-
return () => releaseRailHost(claimed);
|
|
217
|
-
}, []);
|
|
218
|
-
if (!isHost || tools2.length === 0 || typeof document === "undefined")
|
|
219
|
-
return null;
|
|
220
|
-
const marker = { [OVERLAY_MARKER]: "" };
|
|
221
|
-
return createPortal2(/* @__PURE__ */ jsx2("div", {
|
|
222
|
-
...marker,
|
|
223
|
-
style: {
|
|
224
|
-
position: "fixed",
|
|
225
|
-
right: inset,
|
|
226
|
-
top: "50%",
|
|
227
|
-
transform: "translateY(-50%)",
|
|
228
|
-
zIndex: OVERLAY_Z_INDEX + 100,
|
|
229
|
-
display: "flex",
|
|
230
|
-
flexDirection: "column",
|
|
231
|
-
gap: 4,
|
|
232
|
-
transition: "right 180ms ease",
|
|
233
|
-
pointerEvents: "auto"
|
|
234
|
-
},
|
|
235
|
-
children: tools2.map((tool) => /* @__PURE__ */ jsx2(RailTab, {
|
|
236
|
-
tool
|
|
237
|
-
}, `${id}-${tool.id}`))
|
|
238
|
-
}), document.body);
|
|
239
|
-
}
|
|
240
|
-
function RailTab({ tool }) {
|
|
241
|
-
const accent = tool.accent ?? "#111827";
|
|
242
|
-
return /* @__PURE__ */ jsxs2("button", {
|
|
243
|
-
onClick: tool.onClick,
|
|
244
|
-
style: {
|
|
245
|
-
display: "flex",
|
|
246
|
-
alignItems: "center",
|
|
247
|
-
justifyContent: "center",
|
|
248
|
-
gap: 6,
|
|
249
|
-
padding: "14px 9px",
|
|
250
|
-
borderRadius: "8px 0 0 8px",
|
|
251
|
-
border: "none",
|
|
252
|
-
borderRight: tool.active ? "3px solid #fff" : "none",
|
|
253
|
-
background: accent,
|
|
254
|
-
color: "#fff",
|
|
255
|
-
font: "600 12px ui-sans-serif, system-ui, sans-serif",
|
|
256
|
-
letterSpacing: ".02em",
|
|
257
|
-
cursor: "pointer",
|
|
258
|
-
writingMode: "vertical-rl",
|
|
259
|
-
boxShadow: "0 2px 10px rgba(0,0,0,.3)",
|
|
260
|
-
opacity: tool.active ? 1 : 0.92
|
|
261
|
-
},
|
|
262
|
-
title: tool.label,
|
|
263
|
-
type: "button",
|
|
264
|
-
children: [
|
|
265
|
-
tool.label,
|
|
266
|
-
tool.badge !== undefined && tool.badge !== "" && /* @__PURE__ */ jsx2("span", {
|
|
267
|
-
style: {
|
|
268
|
-
display: "inline-flex",
|
|
269
|
-
alignItems: "center",
|
|
270
|
-
justifyContent: "center",
|
|
271
|
-
minWidth: 16,
|
|
272
|
-
height: 16,
|
|
273
|
-
padding: "0 4px",
|
|
274
|
-
borderRadius: 8,
|
|
275
|
-
background: "rgba(255,255,255,.22)",
|
|
276
|
-
font: "700 10px ui-monospace, monospace",
|
|
277
|
-
writingMode: "horizontal-tb"
|
|
278
|
-
},
|
|
279
|
-
children: tool.badge
|
|
280
|
-
})
|
|
281
|
-
]
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
// hud.tsx
|
|
285
|
-
import { Lock } from "lucide-react";
|
|
286
|
-
import { useEffect as useEffect3, useMemo } from "react";
|
|
287
|
-
|
|
288
|
-
// capture.ts
|
|
289
|
-
var installed = false;
|
|
290
|
-
var restorers = [];
|
|
291
|
-
var MAX_TEXT = 300;
|
|
292
|
-
function toText(args) {
|
|
293
|
-
return args.map((arg) => {
|
|
294
|
-
if (typeof arg === "string")
|
|
295
|
-
return arg;
|
|
296
|
-
if (arg instanceof Error)
|
|
297
|
-
return `${arg.name}: ${arg.message}`;
|
|
298
|
-
try {
|
|
299
|
-
return JSON.stringify(arg);
|
|
300
|
-
} catch {
|
|
301
|
-
return String(arg);
|
|
302
|
-
}
|
|
303
|
-
}).join(" ").slice(0, MAX_TEXT);
|
|
304
|
-
}
|
|
305
|
-
function isHudInternal(url, input, init) {
|
|
306
|
-
if (url.includes("/api/hud/") || url.includes("/api/otel/vitals"))
|
|
307
|
-
return true;
|
|
308
|
-
try {
|
|
309
|
-
if (new Headers(init?.headers).has("x-hud-internal"))
|
|
310
|
-
return true;
|
|
311
|
-
if (input instanceof Request && input.headers.has("x-hud-internal"))
|
|
312
|
-
return true;
|
|
313
|
-
} catch {}
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
function patchConsole() {
|
|
317
|
-
const kinds = ["log", "warn", "error"];
|
|
318
|
-
for (const kind of kinds) {
|
|
319
|
-
const original = console[kind].bind(console);
|
|
320
|
-
console[kind] = (...args) => {
|
|
321
|
-
captureBuffer.push({ kind, text: toText(args) });
|
|
322
|
-
original(...args);
|
|
323
|
-
};
|
|
324
|
-
restorers.push(() => {
|
|
325
|
-
console[kind] = original;
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
function patchFetch() {
|
|
330
|
-
const originalFetch = window.fetch;
|
|
331
|
-
const callOriginal = originalFetch.bind(window);
|
|
332
|
-
const patched = async (input, init) => {
|
|
333
|
-
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
334
|
-
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
335
|
-
if (isHudInternal(url, input, init))
|
|
336
|
-
return callOriginal(input, init);
|
|
337
|
-
const started = performance.now();
|
|
338
|
-
try {
|
|
339
|
-
const response = await callOriginal(input, init);
|
|
340
|
-
captureBuffer.push({
|
|
341
|
-
kind: "fetch",
|
|
342
|
-
text: `${method.toUpperCase()} ${url}`.slice(0, MAX_TEXT),
|
|
343
|
-
status: response.status,
|
|
344
|
-
durationMs: Math.round(performance.now() - started)
|
|
345
|
-
});
|
|
346
|
-
return response;
|
|
347
|
-
} catch (error) {
|
|
348
|
-
captureBuffer.push({
|
|
349
|
-
kind: "fetch",
|
|
350
|
-
text: `${method.toUpperCase()} ${url} — ${toText([error])}`.slice(0, MAX_TEXT),
|
|
351
|
-
status: 0,
|
|
352
|
-
durationMs: Math.round(performance.now() - started)
|
|
353
|
-
});
|
|
354
|
-
throw error;
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
window.fetch = Object.assign(patched, originalFetch);
|
|
358
|
-
restorers.push(() => {
|
|
359
|
-
window.fetch = originalFetch;
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
function observeLongTasks() {
|
|
363
|
-
if (typeof PerformanceObserver === "undefined")
|
|
364
|
-
return;
|
|
365
|
-
try {
|
|
366
|
-
const observer = new PerformanceObserver((list) => {
|
|
367
|
-
for (const entry of list.getEntries()) {
|
|
368
|
-
captureBuffer.push({
|
|
369
|
-
kind: "longtask",
|
|
370
|
-
text: `long task ${Math.round(entry.duration)} ms`,
|
|
371
|
-
durationMs: Math.round(entry.duration)
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
observer.observe({ type: "longtask", buffered: true });
|
|
376
|
-
restorers.push(() => observer.disconnect());
|
|
377
|
-
} catch {}
|
|
378
|
-
}
|
|
379
|
-
function installCapture() {
|
|
380
|
-
if (installed || typeof window === "undefined")
|
|
381
|
-
return;
|
|
382
|
-
installed = true;
|
|
383
|
-
patchConsole();
|
|
384
|
-
patchFetch();
|
|
385
|
-
observeLongTasks();
|
|
386
|
-
}
|
|
387
|
-
function uninstallCapture() {
|
|
388
|
-
if (!installed)
|
|
389
|
-
return;
|
|
390
|
-
while (restorers.length > 0)
|
|
391
|
-
restorers.pop()?.();
|
|
392
|
-
installed = false;
|
|
393
|
-
}
|
|
394
|
-
// grabber/element-grabber.tsx
|
|
395
|
-
import { useCallback, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
396
|
-
|
|
397
|
-
// ../review-kit/anchor/selector.ts
|
|
398
|
-
function buildAnchorSelector(el, root) {
|
|
399
|
-
const segments = [];
|
|
400
|
-
let node = el;
|
|
401
|
-
while (node && node !== root) {
|
|
402
|
-
const tag = node.tagName.toLowerCase();
|
|
403
|
-
const parent = node.parentElement;
|
|
404
|
-
if (!parent)
|
|
405
|
-
break;
|
|
406
|
-
const siblings = [...parent.children].filter((c) => c.tagName === node?.tagName);
|
|
407
|
-
const index = siblings.indexOf(node) + 1;
|
|
408
|
-
segments.unshift(siblings.length > 1 ? `${tag}:nth-of-type(${index})` : tag);
|
|
409
|
-
node = parent;
|
|
410
|
-
}
|
|
411
|
-
return segments.join(" > ");
|
|
412
|
-
}
|
|
413
|
-
function anchorLabelFor(el) {
|
|
414
|
-
const text = (el.textContent ?? "").trim().replace(/\s+/g, " ");
|
|
415
|
-
const tag = el.tagName.toLowerCase();
|
|
416
|
-
return text ? `${tag} “${text.slice(0, 32)}${text.length > 32 ? "…" : ""}”` : tag;
|
|
417
|
-
}
|
|
418
|
-
// grabber/payload.ts
|
|
419
|
-
function buildAnchor(el) {
|
|
420
|
-
const r = el.getBoundingClientRect();
|
|
421
|
-
const pct = (part, whole) => whole > 0 ? Number((part / whole * 100).toFixed(1)) : 0;
|
|
422
|
-
return {
|
|
423
|
-
selector: buildAnchorSelector(el, document.body),
|
|
424
|
-
label: anchorLabelFor(el),
|
|
425
|
-
x: pct(r.left, window.innerWidth),
|
|
426
|
-
y: pct(r.top, window.innerHeight),
|
|
427
|
-
width: pct(r.width, window.innerWidth),
|
|
428
|
-
height: pct(r.height, window.innerHeight)
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
function matchComponentHints(hints, route, label, max = 5) {
|
|
432
|
-
if (!hints?.length)
|
|
433
|
-
return [];
|
|
434
|
-
const tokens = `${route} ${label}`.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 2);
|
|
435
|
-
if (tokens.length === 0)
|
|
436
|
-
return hints.slice(0, max);
|
|
437
|
-
return hints.map((hint) => {
|
|
438
|
-
const haystack = `${hint.name} ${hint.path}`.toLowerCase();
|
|
439
|
-
const score = tokens.reduce((n, token) => haystack.includes(token) ? n + 1 : n, 0);
|
|
440
|
-
return { hint, score };
|
|
441
|
-
}).filter((h) => h.score > 0).sort((a, b) => b.score - a.score).slice(0, max).map((h) => h.hint);
|
|
442
|
-
}
|
|
443
|
-
function buildDispatchPayload(input) {
|
|
444
|
-
const route = window.location.pathname;
|
|
445
|
-
const recentErrors = captureBuffer.getSnapshot().filter((entry) => entry.kind === "error" || entry.kind === "warn").slice(-5).map((entry) => `[${entry.kind}] ${entry.text.slice(0, 200)}`);
|
|
446
|
-
return {
|
|
447
|
-
app: input.config.appSlug,
|
|
448
|
-
env: input.env,
|
|
449
|
-
route,
|
|
450
|
-
anchor: input.anchor,
|
|
451
|
-
componentHints: matchComponentHints(input.config.componentHints, route, input.anchor.label),
|
|
452
|
-
recentErrors,
|
|
453
|
-
vitals: input.vitals,
|
|
454
|
-
grabbedAt: new Date().toISOString()
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// grabber/element-grabber.tsx
|
|
459
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
460
|
-
"use client";
|
|
461
|
-
function GrabberController() {
|
|
462
|
-
const { config, env } = useHud();
|
|
463
|
-
const { openDrawer, setActiveTab } = useDevDrawer();
|
|
464
|
-
const grabber = useSyncExternalStore2(subscribeGrabber, getGrabberState, getGrabberState);
|
|
465
|
-
const onPick = useCallback((el, _point) => {
|
|
466
|
-
completeGrab(buildDispatchPayload({ config, env, anchor: buildAnchor(el), vitals: getVitalsSnapshot() }));
|
|
467
|
-
setActiveTab("dispatch");
|
|
468
|
-
openDrawer();
|
|
469
|
-
}, [config, env, openDrawer, setActiveTab]);
|
|
470
|
-
return /* @__PURE__ */ jsx3(ElementPicker, {
|
|
471
|
-
active: grabber.mode === "grabbing",
|
|
472
|
-
chromeSelector: HUD_CHROME_SELECTOR,
|
|
473
|
-
onPick,
|
|
474
|
-
onCancel: cancelGrab,
|
|
475
|
-
hint: "grab active — click an element · Esc cancels"
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
var HUD_CHROME_SELECTOR = "[data-hud-chrome]";
|
|
479
|
-
|
|
480
|
-
// hud.tsx
|
|
481
|
-
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
482
|
-
"use client";
|
|
483
|
-
var ENV_BADGE = {
|
|
484
|
-
development: "DEV",
|
|
485
|
-
preview: "PREVIEW",
|
|
486
|
-
staging: "STAGING",
|
|
487
|
-
production: "PROD · READ-ONLY",
|
|
488
|
-
disabled: "OFF"
|
|
489
|
-
};
|
|
490
|
-
function Hud({ config, panels }) {
|
|
491
|
-
const env = resolveHudEnv();
|
|
492
|
-
if (!isHudVisible(env))
|
|
493
|
-
return null;
|
|
494
|
-
return /* @__PURE__ */ jsx4(DevDrawerProvider, {
|
|
495
|
-
config: {
|
|
496
|
-
storageKey: config.storageKey ?? `${config.appSlug}-hud`,
|
|
497
|
-
shortcutKey: config.shortcutKey === undefined ? "h" : config.shortcutKey,
|
|
498
|
-
defaultHeight: 38,
|
|
499
|
-
minHeight: 25,
|
|
500
|
-
maxHeight: 75
|
|
501
|
-
},
|
|
502
|
-
children: /* @__PURE__ */ jsx4(HudProvider, {
|
|
503
|
-
config,
|
|
504
|
-
env,
|
|
505
|
-
panels,
|
|
506
|
-
children: /* @__PURE__ */ jsx4(HudChrome, {})
|
|
507
|
-
})
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
function HudChrome() {
|
|
511
|
-
const { config, env, name, panels } = useHud();
|
|
512
|
-
const { isOpen, toggleDrawer } = useDevDrawer();
|
|
513
|
-
const access = resolveHudAccess(env);
|
|
514
|
-
const apiBase = config.apiBase ?? "/api/hud";
|
|
515
|
-
const { state: unlockState, error: unlockError, unlock } = useHudUnlock(apiBase, access);
|
|
516
|
-
const locked = hudRequiresUnlock(access) && unlockState !== "unlocked";
|
|
517
|
-
useEffect3(() => {
|
|
518
|
-
installCapture();
|
|
519
|
-
}, []);
|
|
520
|
-
const tabs = useMemo(() => {
|
|
521
|
-
if (locked) {
|
|
522
|
-
return [
|
|
523
|
-
{
|
|
524
|
-
id: "unlock",
|
|
525
|
-
label: "Locked",
|
|
526
|
-
icon: Lock,
|
|
527
|
-
content: /* @__PURE__ */ jsx4(HudUnlockPanel, {
|
|
528
|
-
env,
|
|
529
|
-
state: unlockState,
|
|
530
|
-
error: unlockError,
|
|
531
|
-
onUnlock: unlock
|
|
532
|
-
})
|
|
533
|
-
}
|
|
534
|
-
];
|
|
535
|
-
}
|
|
536
|
-
return panels.map((panel) => ({
|
|
537
|
-
id: panel.id,
|
|
538
|
-
label: panel.label,
|
|
539
|
-
icon: panel.icon,
|
|
540
|
-
content: panel.content
|
|
541
|
-
}));
|
|
542
|
-
}, [locked, env, unlockState, unlockError, unlock, panels]);
|
|
543
|
-
useEffect3(() => {
|
|
544
|
-
if (config.showFab === false)
|
|
545
|
-
return;
|
|
546
|
-
registerRailTool({
|
|
547
|
-
id: "hud",
|
|
548
|
-
label: "hud",
|
|
549
|
-
accent: "#0369a1",
|
|
550
|
-
order: 20,
|
|
551
|
-
active: isOpen,
|
|
552
|
-
onClick: toggleDrawer
|
|
553
|
-
});
|
|
554
|
-
return () => unregisterRailTool("hud");
|
|
555
|
-
}, [config.showFab, isOpen, toggleDrawer]);
|
|
556
|
-
if (tabs.length === 0)
|
|
557
|
-
return null;
|
|
558
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
559
|
-
"data-hud-chrome": true,
|
|
560
|
-
"data-hud-marker": HUD_BUNDLE_MARKER,
|
|
561
|
-
style: { display: "contents" },
|
|
562
|
-
children: [
|
|
563
|
-
/* @__PURE__ */ jsx4(ToolRail, {}),
|
|
564
|
-
/* @__PURE__ */ jsx4(DevDrawer, {
|
|
565
|
-
tabs,
|
|
566
|
-
title: name,
|
|
567
|
-
badgeLabel: ENV_BADGE[env]
|
|
568
|
-
}),
|
|
569
|
-
!locked && /* @__PURE__ */ jsx4(GrabberController, {})
|
|
570
|
-
]
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
export { installCapture, uninstallCapture, buildAnchorSelector, buildAnchor, matchComponentHints, buildDispatchPayload, Hud };
|
package/chunk-xztw0xyt.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
// ../ui/lib/utils.ts
|
|
2
|
-
import { clsx } from "clsx";
|
|
3
|
-
import { twMerge } from "tailwind-merge";
|
|
4
|
-
function cn(...inputs) {
|
|
5
|
-
return twMerge(clsx(inputs));
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// ../ui/components/badge.tsx
|
|
9
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
10
|
-
import { cva } from "class-variance-authority";
|
|
11
|
-
import { jsx } from "react/jsx-runtime";
|
|
12
|
-
var badgeVariants = cva("inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
|
|
13
|
-
variants: {
|
|
14
|
-
variant: {
|
|
15
|
-
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
16
|
-
secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
17
|
-
destructive: "bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
18
|
-
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
19
|
-
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
20
|
-
link: "text-primary underline-offset-4 [a&]:hover:underline",
|
|
21
|
-
success: "bg-emerald-500/15 text-emerald-700 border-emerald-500/20 dark:text-emerald-300 dark:bg-emerald-400/15 dark:border-emerald-400/25 [a&]:hover:bg-emerald-500/25",
|
|
22
|
-
warning: "bg-amber-500/15 text-amber-700 border-amber-500/20 dark:text-amber-300 dark:bg-amber-400/15 dark:border-amber-400/25 [a&]:hover:bg-amber-500/25",
|
|
23
|
-
info: "bg-blue-500/15 text-blue-700 border-blue-500/20 dark:text-blue-300 dark:bg-blue-400/15 dark:border-blue-400/25 [a&]:hover:bg-blue-500/25",
|
|
24
|
-
muted: "bg-muted text-muted-foreground border-transparent [a&]:hover:bg-muted/80"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
defaultVariants: {
|
|
28
|
-
variant: "default"
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
function Badge({
|
|
32
|
-
className,
|
|
33
|
-
variant = "default",
|
|
34
|
-
asChild = false,
|
|
35
|
-
...props
|
|
36
|
-
}) {
|
|
37
|
-
const Comp = asChild ? Slot : "span";
|
|
38
|
-
return /* @__PURE__ */ jsx(Comp, {
|
|
39
|
-
"data-slot": "badge",
|
|
40
|
-
"data-variant": variant,
|
|
41
|
-
className: cn(badgeVariants({ variant }), className),
|
|
42
|
-
...props
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ../ui/components/button.tsx
|
|
47
|
-
import { Slot as Slot2 } from "@radix-ui/react-slot";
|
|
48
|
-
import { cva as cva2 } from "class-variance-authority";
|
|
49
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
50
|
-
var buttonVariants = cva2("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
|
|
51
|
-
variants: {
|
|
52
|
-
variant: {
|
|
53
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
54
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
55
|
-
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
56
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
57
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
58
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
59
|
-
},
|
|
60
|
-
size: {
|
|
61
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
62
|
-
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
63
|
-
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
64
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
65
|
-
icon: "size-9",
|
|
66
|
-
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
67
|
-
"icon-sm": "size-8",
|
|
68
|
-
"icon-lg": "size-10"
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
defaultVariants: {
|
|
72
|
-
variant: "default",
|
|
73
|
-
size: "default"
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
function Button({
|
|
77
|
-
className,
|
|
78
|
-
variant = "default",
|
|
79
|
-
size = "default",
|
|
80
|
-
asChild = false,
|
|
81
|
-
...props
|
|
82
|
-
}) {
|
|
83
|
-
const Comp = asChild ? Slot2 : "button";
|
|
84
|
-
return /* @__PURE__ */ jsx2(Comp, {
|
|
85
|
-
"data-slot": "button",
|
|
86
|
-
"data-variant": variant,
|
|
87
|
-
"data-size": size,
|
|
88
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
89
|
-
...props
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ../ui/components/switch.tsx
|
|
94
|
-
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
95
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
96
|
-
"use client";
|
|
97
|
-
function Switch({
|
|
98
|
-
className,
|
|
99
|
-
size = "default",
|
|
100
|
-
...props
|
|
101
|
-
}) {
|
|
102
|
-
return /* @__PURE__ */ jsx3(SwitchPrimitive.Root, {
|
|
103
|
-
"data-slot": "switch",
|
|
104
|
-
"data-size": size,
|
|
105
|
-
className: cn("peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6", className),
|
|
106
|
-
...props,
|
|
107
|
-
children: /* @__PURE__ */ jsx3(SwitchPrimitive.Thumb, {
|
|
108
|
-
"data-slot": "switch-thumb",
|
|
109
|
-
className: cn("bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0")
|
|
110
|
-
})
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
export { cn, Badge, Button, Switch };
|