@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.
Files changed (91) hide show
  1. package/README.md +42 -23
  2. package/dist/index.d.ts +39 -0
  3. package/dist/index.js +399 -0
  4. package/package.json +45 -136
  5. package/chunk-0cj8dkk7.js +0 -127
  6. package/chunk-1atxwdhw.js +0 -48
  7. package/chunk-24vrg16w.js +0 -39
  8. package/chunk-3j9sm249.js +0 -26
  9. package/chunk-50pq4sg6.js +0 -41
  10. package/chunk-5gtx3pza.js +0 -9
  11. package/chunk-6gw4x08j.js +0 -264
  12. package/chunk-6jt8yg4m.js +0 -117
  13. package/chunk-71se605m.js +0 -85
  14. package/chunk-82nm9wcg.js +0 -316
  15. package/chunk-8tam7r3h.js +0 -68
  16. package/chunk-babjpqkb.js +0 -52
  17. package/chunk-c5y856ad.js +0 -98
  18. package/chunk-ghxh8926.js +0 -172
  19. package/chunk-hc2g0n35.js +0 -24
  20. package/chunk-k0vr8dsy.js +0 -179
  21. package/chunk-k50yfp5d.js +0 -166
  22. package/chunk-kyeb6qeq.js +0 -95
  23. package/chunk-msqkkqw7.js +0 -140
  24. package/chunk-nm82wr8r.js +0 -58
  25. package/chunk-r06bpmy6.js +0 -79
  26. package/chunk-t9eh4t0b.js +0 -89
  27. package/chunk-tf774c4w.js +0 -115
  28. package/chunk-v086j53b.js +0 -19
  29. package/chunk-wspz08q7.js +0 -67
  30. package/chunk-xezxydm3.js +0 -47
  31. package/chunk-xjn0896g.js +0 -574
  32. package/chunk-xztw0xyt.js +0 -113
  33. package/chunk-zzrpd92r.js +0 -172
  34. package/core/access.d.mts +0 -53
  35. package/core/access.js +0 -27
  36. package/core/api-types.d.mts +0 -146
  37. package/core/api-types.js +0 -9
  38. package/core/capabilities.d.mts +0 -27
  39. package/core/capabilities.js +0 -14
  40. package/core/capture-buffer.d.mts +0 -37
  41. package/core/capture-buffer.js +0 -9
  42. package/core/force-state.d.mts +0 -68
  43. package/core/force-state.js +0 -21
  44. package/core/mock-cookie.d.mts +0 -30
  45. package/core/mock-cookie.js +0 -15
  46. package/core/types.d.mts +0 -59
  47. package/core/types.js +0 -9
  48. package/hud-provider.d.mts +0 -38
  49. package/hud-provider.js +0 -15
  50. package/hud.d.mts +0 -15
  51. package/hud.js +0 -18
  52. package/index.d.mts +0 -94
  53. package/index.js +0 -170
  54. package/lazy-panel.d.mts +0 -28
  55. package/lazy-panel.js +0 -11
  56. package/panels/cicd-panel.d.mts +0 -9
  57. package/panels/cicd-panel.js +0 -13
  58. package/panels/debug-info-panel.d.mts +0 -21
  59. package/panels/debug-info-panel.js +0 -9
  60. package/panels/dispatch-panel.d.mts +0 -10
  61. package/panels/dispatch-panel.js +0 -14
  62. package/panels/env-info-panel.d.mts +0 -9
  63. package/panels/env-info-panel.js +0 -12
  64. package/panels/feature-flags-panel.d.mts +0 -26
  65. package/panels/feature-flags-panel.js +0 -9
  66. package/panels/force-state-panel.d.mts +0 -11
  67. package/panels/force-state-panel.js +0 -113
  68. package/panels/info-row.d.mts +0 -21
  69. package/panels/info-row.js +0 -14
  70. package/panels/mock-seed-panel.d.mts +0 -15
  71. package/panels/mock-seed-panel.js +0 -14
  72. package/panels/network-console-panel.d.mts +0 -6
  73. package/panels/network-console-panel.js +0 -9
  74. package/panels/role-switcher-panel.d.mts +0 -28
  75. package/panels/role-switcher-panel.js +0 -9
  76. package/panels/sessions-panel.d.mts +0 -6
  77. package/panels/sessions-panel.js +0 -13
  78. package/panels/tokens-panel.d.mts +0 -38
  79. package/panels/tokens-panel.js +0 -9
  80. package/panels/unlock-panel.d.mts +0 -33
  81. package/panels/unlock-panel.js +0 -14
  82. package/panels/variants-panel.d.mts +0 -51
  83. package/panels/variants-panel.js +0 -12
  84. package/panels/vitals-panel.d.mts +0 -11
  85. package/panels/vitals-panel.js +0 -15
  86. package/server/guard.d.mts +0 -42
  87. package/server/guard.js +0 -12
  88. package/server/unlock.d.mts +0 -28
  89. package/server/unlock.js +0 -108
  90. package/state-boundary.d.mts +0 -25
  91. package/state-boundary.js +0 -54
package/chunk-ghxh8926.js DELETED
@@ -1,172 +0,0 @@
1
- import {
2
- usePoll
3
- } from "./chunk-xezxydm3.js";
4
- import {
5
- useHud
6
- } from "./chunk-wspz08q7.js";
7
- import {
8
- LoadingSpinner,
9
- PanelSection
10
- } from "./chunk-kyeb6qeq.js";
11
- import {
12
- Badge
13
- } from "./chunk-xztw0xyt.js";
14
- import {
15
- __require
16
- } from "./chunk-5gtx3pza.js";
17
-
18
- // panels/vitals-panel.tsx
19
- import { Activity, ServerCrash } from "lucide-react";
20
- import { useEffect, useSyncExternalStore } from "react";
21
- import { jsx, jsxs } from "react/jsx-runtime";
22
- "use client";
23
- var VITAL_ORDER = ["LCP", "INP", "CLS", "TTFB", "FCP"];
24
- var vitals = new Map;
25
- var vitalsSnapshot = new Map;
26
- var vitalListeners = new Set;
27
- var vitalsStarted = false;
28
- function recordVital(name, value, rating) {
29
- vitals.set(name, { value, rating });
30
- vitalsSnapshot = new Map(vitals);
31
- for (const listener of vitalListeners)
32
- listener();
33
- }
34
- function startVitals() {
35
- if (vitalsStarted || typeof window === "undefined")
36
- return;
37
- vitalsStarted = true;
38
- import("web-vitals").then(({ onCLS, onFCP, onLCP, onTTFB, onINP }) => {
39
- const report = (metric) => recordVital(metric.name, metric.value, metric.rating);
40
- onCLS(report, { reportAllChanges: true });
41
- onINP(report, { reportAllChanges: true });
42
- onLCP(report);
43
- onFCP(report);
44
- onTTFB(report);
45
- });
46
- }
47
- function subscribeVitals(listener) {
48
- vitalListeners.add(listener);
49
- return () => vitalListeners.delete(listener);
50
- }
51
- function getVitalsSnapshot() {
52
- const out = {};
53
- for (const [name, sample] of vitals)
54
- out[name] = Number(sample.value.toFixed(2));
55
- return out;
56
- }
57
- function formatVital(name, value) {
58
- if (name === "CLS")
59
- return value.toFixed(3);
60
- if (value >= 1000)
61
- return `${(value / 1000).toFixed(2)} s`;
62
- return `${Math.round(value)} ms`;
63
- }
64
- var RATING_CLASS = {
65
- good: "text-emerald-500",
66
- "needs-improvement": "text-amber-500",
67
- poor: "text-red-500"
68
- };
69
- function VitalsPanel() {
70
- const { config } = useHud();
71
- const samples = useSyncExternalStore(subscribeVitals, () => vitalsSnapshot, () => vitalsSnapshot);
72
- useEffect(() => {
73
- startVitals();
74
- }, []);
75
- const apiBase = config.apiBase ?? "/api/hud";
76
- const signoz = usePoll(`${apiBase}/signoz?service=${encodeURIComponent(config.appSlug)}`, 60000);
77
- return /* @__PURE__ */ jsxs("div", {
78
- className: "space-y-4",
79
- children: [
80
- /* @__PURE__ */ jsxs(PanelSection, {
81
- icon: Activity,
82
- title: "Web Vitals · this page load",
83
- children: [
84
- /* @__PURE__ */ jsx("div", {
85
- className: "flex flex-wrap gap-2 px-2",
86
- children: VITAL_ORDER.map((name) => {
87
- const sample = samples.get(name);
88
- return /* @__PURE__ */ jsxs("div", {
89
- className: "min-w-[92px] rounded-md border bg-muted/20 px-3 py-2",
90
- children: [
91
- /* @__PURE__ */ jsx("div", {
92
- className: "text-[10px] uppercase tracking-wider text-muted-foreground",
93
- children: name
94
- }),
95
- /* @__PURE__ */ jsx("div", {
96
- className: `font-mono text-sm font-semibold ${sample ? RATING_CLASS[sample.rating] : "text-muted-foreground/50"}`,
97
- children: sample ? formatVital(name, sample.value) : "—"
98
- })
99
- ]
100
- }, name);
101
- })
102
- }),
103
- /* @__PURE__ */ jsx("p", {
104
- className: "px-2 text-[10px] text-muted-foreground/60",
105
- children: "CLS/INP update live; LCP/FCP/TTFB are per page load. History lands in SigNoz via /api/otel/vitals."
106
- })
107
- ]
108
- }),
109
- /* @__PURE__ */ jsxs(PanelSection, {
110
- icon: ServerCrash,
111
- title: `Server · ${config.appSlug} (1h)`,
112
- children: [
113
- signoz.loading && /* @__PURE__ */ jsx(LoadingSpinner, {}),
114
- signoz.error && /* @__PURE__ */ jsxs("p", {
115
- className: "px-2 text-[10px] text-amber-500",
116
- children: [
117
- "hub unreachable — ",
118
- signoz.error
119
- ]
120
- }),
121
- signoz.data && /* @__PURE__ */ jsxs("div", {
122
- className: "space-y-1 px-2",
123
- children: [
124
- /* @__PURE__ */ jsxs("div", {
125
- className: "flex items-center gap-2",
126
- children: [
127
- /* @__PURE__ */ jsx(ServerStat, {
128
- label: "error rate",
129
- value: signoz.data.errorRate,
130
- unit: "/s"
131
- }),
132
- /* @__PURE__ */ jsx(ServerStat, {
133
- label: "p95",
134
- value: signoz.data.p95Latency,
135
- unit: " ms"
136
- }),
137
- /* @__PURE__ */ jsx(ServerStat, {
138
- label: "req rate",
139
- value: signoz.data.requestCount,
140
- unit: "/s"
141
- })
142
- ]
143
- }),
144
- signoz.data.source === "mock" && /* @__PURE__ */ jsx(Badge, {
145
- variant: "outline",
146
- className: "h-4 px-1.5 text-[9px] text-muted-foreground",
147
- children: "mock data — SIGNOZ_QUERY_URL unset"
148
- })
149
- ]
150
- })
151
- ]
152
- })
153
- ]
154
- });
155
- }
156
- function ServerStat({ label, value, unit }) {
157
- return /* @__PURE__ */ jsxs("div", {
158
- className: "min-w-[92px] rounded-md border bg-muted/20 px-3 py-2",
159
- children: [
160
- /* @__PURE__ */ jsx("div", {
161
- className: "text-[10px] uppercase tracking-wider text-muted-foreground",
162
- children: label
163
- }),
164
- /* @__PURE__ */ jsx("div", {
165
- className: "font-mono text-sm font-semibold",
166
- children: value === null ? "—" : `${value.toFixed(value < 10 ? 2 : 0)}${unit}`
167
- })
168
- ]
169
- });
170
- }
171
-
172
- export { getVitalsSnapshot, VitalsPanel };
package/chunk-hc2g0n35.js DELETED
@@ -1,24 +0,0 @@
1
- // core/mock-cookie.ts
2
- var HUD_MOCK_COOKIE = "hud-mock";
3
- function isHudMockEnabled(cookieValue, env) {
4
- const hudAllowed = env.nodeEnv === "development" || env.hudEnabled === "true";
5
- return hudAllowed && cookieValue === "1";
6
- }
7
- function hudMockCookieString(enabled) {
8
- if (!enabled)
9
- return `${HUD_MOCK_COOKIE}=; path=/; max-age=0; samesite=lax`;
10
- return `${HUD_MOCK_COOKIE}=1; path=/; max-age=${60 * 60 * 24 * 30}; samesite=lax`;
11
- }
12
- function readHudMockCookie() {
13
- if (typeof document === "undefined")
14
- return;
15
- const match = document.cookie.split("; ").find((part) => part.startsWith(`${HUD_MOCK_COOKIE}=`));
16
- return match?.slice(HUD_MOCK_COOKIE.length + 1);
17
- }
18
- function setHudMockCookie(enabled) {
19
- if (typeof document === "undefined")
20
- return;
21
- document.cookie = hudMockCookieString(enabled);
22
- }
23
-
24
- export { HUD_MOCK_COOKIE, isHudMockEnabled, hudMockCookieString, readHudMockCookie, setHudMockCookie };
package/chunk-k0vr8dsy.js DELETED
@@ -1,179 +0,0 @@
1
- import {
2
- bridgeFetch,
3
- getBridgeInfo
4
- } from "./chunk-50pq4sg6.js";
5
- import {
6
- useHud
7
- } from "./chunk-wspz08q7.js";
8
- import {
9
- LoadingSpinner,
10
- PanelSection
11
- } from "./chunk-kyeb6qeq.js";
12
- import {
13
- Badge,
14
- Button,
15
- Switch
16
- } from "./chunk-xztw0xyt.js";
17
- import {
18
- readHudMockCookie,
19
- setHudMockCookie
20
- } from "./chunk-hc2g0n35.js";
21
-
22
- // panels/mock-seed-panel.tsx
23
- import { Database, FlaskConical, RefreshCw } from "lucide-react";
24
- import { useEffect, useState } from "react";
25
- import { jsx, jsxs } from "react/jsx-runtime";
26
- "use client";
27
- function MockSeedPanel({ seeds = [] }) {
28
- const { config, can } = useHud();
29
- const [mockCookie, setMockCookie] = useState(undefined);
30
- const [bridge, setBridge] = useState(undefined);
31
- const [runs, setRuns] = useState([]);
32
- const apiBase = config.apiBase ?? "/api/hud";
33
- const canSeed = can("inject.seed") && seeds.length > 0;
34
- useEffect(() => {
35
- setMockCookie(readHudMockCookie());
36
- }, []);
37
- useEffect(() => {
38
- if (!canSeed)
39
- return;
40
- let cancelled = false;
41
- getBridgeInfo(apiBase).then((info) => {
42
- if (!cancelled)
43
- setBridge(info);
44
- });
45
- return () => {
46
- cancelled = true;
47
- };
48
- }, [apiBase, canSeed]);
49
- const mockOn = mockCookie === "1";
50
- function toggleMock(next) {
51
- setHudMockCookie(next);
52
- setMockCookie(next ? "1" : undefined);
53
- window.location.reload();
54
- }
55
- async function runSeed(seed) {
56
- if (!bridge)
57
- return;
58
- const runId = `${seed.id}-${Date.now()}`;
59
- setRuns((prev) => [{ id: runId, label: seed.label, status: "running" }, ...prev]);
60
- try {
61
- const res = await bridgeFetch(bridge, "/seed", {
62
- method: "POST",
63
- body: JSON.stringify({
64
- app: config.appSlug,
65
- fn: seed.fn,
66
- args: seed.args,
67
- local: seed.local
68
- })
69
- });
70
- const body = await res.json();
71
- setRuns((prev) => prev.map((run) => run.id === runId ? { ...run, status: body.ok ? "done" : "failed", detail: body.output ?? body.error } : run));
72
- } catch (error) {
73
- setRuns((prev) => prev.map((run) => run.id === runId ? {
74
- ...run,
75
- status: "failed",
76
- detail: error instanceof Error ? error.message : "seed failed"
77
- } : run));
78
- }
79
- }
80
- return /* @__PURE__ */ jsxs("div", {
81
- className: "space-y-4",
82
- children: [
83
- can("mock.toggle") && /* @__PURE__ */ jsx(PanelSection, {
84
- icon: FlaskConical,
85
- title: "Mock Convex",
86
- children: /* @__PURE__ */ jsxs("div", {
87
- className: "flex items-center justify-between px-2",
88
- children: [
89
- /* @__PURE__ */ jsxs("div", {
90
- children: [
91
- /* @__PURE__ */ jsx("div", {
92
- className: "text-xs font-medium",
93
- children: "Mock backend"
94
- }),
95
- /* @__PURE__ */ jsx("p", {
96
- className: "text-[10px] text-muted-foreground/60",
97
- children: "Swaps the Convex client for a dummy — reload applies (server re-reads the cookie)."
98
- })
99
- ]
100
- }),
101
- /* @__PURE__ */ jsxs("div", {
102
- className: "flex items-center gap-2",
103
- children: [
104
- mockOn && /* @__PURE__ */ jsx(Badge, {
105
- variant: "outline",
106
- className: "h-4 px-1.5 text-[9px] text-amber-500",
107
- children: "mock"
108
- }),
109
- /* @__PURE__ */ jsx(Switch, {
110
- checked: mockOn,
111
- onCheckedChange: toggleMock
112
- })
113
- ]
114
- })
115
- ]
116
- })
117
- }),
118
- canSeed && /* @__PURE__ */ jsxs(PanelSection, {
119
- icon: Database,
120
- title: "Seed data",
121
- children: [
122
- bridge === undefined && /* @__PURE__ */ jsx(LoadingSpinner, {}),
123
- bridge === null && /* @__PURE__ */ jsx("p", {
124
- className: "px-2 text-[10px] text-amber-500",
125
- children: "bridge not reachable — run `bun hud:bridge` in the repo to seed from here."
126
- }),
127
- bridge != null && /* @__PURE__ */ jsx("div", {
128
- className: "space-y-1 px-2",
129
- children: seeds.map((seed) => /* @__PURE__ */ jsxs("div", {
130
- className: "flex items-center gap-2",
131
- children: [
132
- /* @__PURE__ */ jsxs(Button, {
133
- size: "sm",
134
- variant: "outline",
135
- className: "h-6 text-[11px]",
136
- onClick: () => runSeed(seed),
137
- children: [
138
- /* @__PURE__ */ jsx(RefreshCw, {
139
- className: "mr-1.5 h-3 w-3"
140
- }),
141
- seed.label
142
- ]
143
- }),
144
- seed.description && /* @__PURE__ */ jsx("span", {
145
- className: "min-w-0 flex-1 truncate text-[10px] text-muted-foreground/60",
146
- children: seed.description
147
- })
148
- ]
149
- }, seed.id))
150
- })
151
- ]
152
- }),
153
- runs.length > 0 && /* @__PURE__ */ jsx(PanelSection, {
154
- title: "Seed runs",
155
- children: runs.map((run) => /* @__PURE__ */ jsxs("div", {
156
- className: "flex items-center gap-2 px-2 py-1 font-mono text-[10.5px]",
157
- children: [
158
- /* @__PURE__ */ jsx(Badge, {
159
- variant: "outline",
160
- className: `h-4 px-1.5 text-[9px] ${run.status === "done" ? "text-emerald-500" : run.status === "failed" ? "text-red-500" : "text-amber-500"}`,
161
- children: run.status
162
- }),
163
- /* @__PURE__ */ jsx("span", {
164
- className: "min-w-0 flex-1 truncate",
165
- children: run.label
166
- }),
167
- run.detail && /* @__PURE__ */ jsx("span", {
168
- className: "max-w-[220px] truncate text-muted-foreground/60",
169
- title: run.detail,
170
- children: run.detail
171
- })
172
- ]
173
- }, run.id))
174
- })
175
- ]
176
- });
177
- }
178
-
179
- export { MockSeedPanel };
package/chunk-k50yfp5d.js DELETED
@@ -1,166 +0,0 @@
1
- import {
2
- useHud
3
- } from "./chunk-wspz08q7.js";
4
- import {
5
- PanelSection
6
- } from "./chunk-kyeb6qeq.js";
7
- import {
8
- Badge,
9
- Button
10
- } from "./chunk-xztw0xyt.js";
11
-
12
- // panels/variants-panel.tsx
13
- import { ArrowUpRight, Beaker, Wand2 } from "lucide-react";
14
- import { useState } from "react";
15
- import { jsx, jsxs } from "react/jsx-runtime";
16
- "use client";
17
- var STATUS_CLASS = {
18
- active: "text-emerald-500",
19
- decided: "text-muted-foreground"
20
- };
21
- function VariantsPanel({ adapter }) {
22
- const { can } = useHud();
23
- const { categories, reviewHref, categoryHref, openPreview, generate } = adapter;
24
- const [path, setPath] = useState("");
25
- const [brief, setBrief] = useState("");
26
- const [result, setResult] = useState(null);
27
- const [sending, setSending] = useState(false);
28
- const grouped = new Map;
29
- for (const category of categories) {
30
- const key = category.domain ?? "shared";
31
- grouped.set(key, [...grouped.get(key) ?? [], category]);
32
- }
33
- async function submitGenerate() {
34
- if (!generate || !path.trim())
35
- return;
36
- setSending(true);
37
- setResult(null);
38
- try {
39
- setResult(await generate({ path: path.trim(), brief: brief.trim(), count: 3 }));
40
- } catch (error) {
41
- setResult({ ok: false, error: error instanceof Error ? error.message : "generate failed" });
42
- } finally {
43
- setSending(false);
44
- }
45
- }
46
- return /* @__PURE__ */ jsxs("div", {
47
- className: "space-y-4",
48
- children: [
49
- /* @__PURE__ */ jsxs(PanelSection, {
50
- icon: Beaker,
51
- title: `Categories (${categories.length})`,
52
- children: [
53
- categories.length === 0 && /* @__PURE__ */ jsx("p", {
54
- className: "px-2 text-[10px] text-muted-foreground/60",
55
- children: "No preview categories registered for this app."
56
- }),
57
- /* @__PURE__ */ jsx("div", {
58
- className: "space-y-2 px-2",
59
- children: Array.from(grouped.entries()).map(([domain, list]) => /* @__PURE__ */ jsxs("div", {
60
- children: [
61
- /* @__PURE__ */ jsx("div", {
62
- className: "text-[9px] uppercase tracking-wider text-muted-foreground/50",
63
- children: domain
64
- }),
65
- list.map((category) => /* @__PURE__ */ jsxs("div", {
66
- className: "flex items-center gap-2 py-1 text-[11px]",
67
- children: [
68
- /* @__PURE__ */ jsx(Badge, {
69
- variant: "outline",
70
- className: `h-4 px-1.5 text-[9px] ${STATUS_CLASS[category.status] ?? "text-amber-500"}`,
71
- children: category.status
72
- }),
73
- /* @__PURE__ */ jsx("span", {
74
- className: "min-w-0 flex-1 truncate",
75
- children: category.name
76
- }),
77
- /* @__PURE__ */ jsxs("span", {
78
- className: "text-muted-foreground/60",
79
- children: [
80
- category.alternativeCount,
81
- " alt",
82
- category.alternativeCount === 1 ? "" : "s"
83
- ]
84
- }),
85
- openPreview ? /* @__PURE__ */ jsx(Button, {
86
- variant: "ghost",
87
- size: "sm",
88
- className: "h-5 px-1.5 text-[10px]",
89
- onClick: () => openPreview(category.id),
90
- children: "open"
91
- }) : categoryHref ? /* @__PURE__ */ jsxs("a", {
92
- href: categoryHref(category.id),
93
- className: "inline-flex items-center gap-0.5 text-[10px] text-primary hover:underline",
94
- children: [
95
- "open",
96
- /* @__PURE__ */ jsx(ArrowUpRight, {
97
- className: "h-2.5 w-2.5"
98
- })
99
- ]
100
- }) : null
101
- ]
102
- }, category.id))
103
- ]
104
- }, domain))
105
- }),
106
- /* @__PURE__ */ jsx("div", {
107
- className: "px-2 pt-1",
108
- children: /* @__PURE__ */ jsxs("a", {
109
- href: reviewHref,
110
- className: "inline-flex items-center gap-1 text-[10px] text-primary hover:underline",
111
- children: [
112
- "Full review dashboard (vote, showcase, decisions)",
113
- /* @__PURE__ */ jsx(ArrowUpRight, {
114
- className: "h-3 w-3"
115
- })
116
- ]
117
- })
118
- })
119
- ]
120
- }),
121
- generate && can("variants.generate") && /* @__PURE__ */ jsx(PanelSection, {
122
- icon: Wand2,
123
- title: "Generate variants",
124
- children: /* @__PURE__ */ jsxs("div", {
125
- className: "space-y-2 px-2",
126
- children: [
127
- /* @__PURE__ */ jsx("input", {
128
- value: path,
129
- onChange: (e) => setPath(e.target.value),
130
- placeholder: "apps/console/src/components/… (repo-relative)",
131
- className: "w-full rounded-md border bg-muted/20 p-2 font-mono text-[11px] outline-none focus:ring-1 focus:ring-ring"
132
- }),
133
- /* @__PURE__ */ jsx("textarea", {
134
- value: brief,
135
- onChange: (e) => setBrief(e.target.value),
136
- placeholder: "Brief, e.g.: three denser table treatments, keep the glass language",
137
- className: "min-h-[44px] w-full rounded-md border bg-muted/20 p-2 font-mono text-[11px] outline-none focus:ring-1 focus:ring-ring"
138
- }),
139
- /* @__PURE__ */ jsxs("div", {
140
- className: "flex items-center gap-2",
141
- children: [
142
- /* @__PURE__ */ jsx(Button, {
143
- size: "sm",
144
- className: "h-6 text-[11px]",
145
- disabled: sending || !path.trim(),
146
- onClick: submitGenerate,
147
- children: "Queue 3 variants"
148
- }),
149
- /* @__PURE__ */ jsx("span", {
150
- className: "text-[10px] text-muted-foreground/60",
151
- children: "Writes a .claude/queue marker — the next session runs /generate-variants."
152
- })
153
- ]
154
- }),
155
- result && /* @__PURE__ */ jsx("p", {
156
- className: `font-mono text-[10px] ${result.ok ? "text-emerald-500" : "text-red-500"}`,
157
- children: result.ok ? `queued → ${result.markerPath}` : result.error
158
- })
159
- ]
160
- })
161
- })
162
- ]
163
- });
164
- }
165
-
166
- export { VariantsPanel };
package/chunk-kyeb6qeq.js DELETED
@@ -1,95 +0,0 @@
1
- import {
2
- Button
3
- } from "./chunk-xztw0xyt.js";
4
-
5
- // panels/info-row.tsx
6
- import { Copy } from "lucide-react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- "use client";
9
- function PanelSection({
10
- icon: Icon,
11
- title,
12
- children
13
- }) {
14
- return /* @__PURE__ */ jsxs("div", {
15
- children: [
16
- /* @__PURE__ */ jsxs("h4", {
17
- className: "mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground",
18
- children: [
19
- Icon && /* @__PURE__ */ jsx(Icon, {
20
- className: "h-3 w-3"
21
- }),
22
- title
23
- ]
24
- }),
25
- /* @__PURE__ */ jsx("div", {
26
- className: "space-y-1.5",
27
- children
28
- })
29
- ]
30
- });
31
- }
32
- function InfoRow({
33
- label,
34
- value,
35
- copyable = false
36
- }) {
37
- function handleCopy() {
38
- navigator.clipboard.writeText(value);
39
- }
40
- return /* @__PURE__ */ jsxs("div", {
41
- className: "flex items-center justify-between px-2 py-1 hover:bg-muted/50",
42
- children: [
43
- /* @__PURE__ */ jsx("span", {
44
- className: "text-[10px] text-muted-foreground",
45
- children: label
46
- }),
47
- /* @__PURE__ */ jsxs("div", {
48
- className: "flex items-center gap-1",
49
- children: [
50
- /* @__PURE__ */ jsx("span", {
51
- className: "max-w-[220px] truncate font-mono text-[10px]",
52
- children: value
53
- }),
54
- copyable && /* @__PURE__ */ jsx(Button, {
55
- variant: "ghost",
56
- size: "icon",
57
- className: "h-4 w-4 shrink-0",
58
- onClick: handleCopy,
59
- children: /* @__PURE__ */ jsx(Copy, {
60
- className: "h-2.5 w-2.5"
61
- })
62
- })
63
- ]
64
- })
65
- ]
66
- });
67
- }
68
- function ShortcutRow({ keys, label }) {
69
- return /* @__PURE__ */ jsxs("div", {
70
- className: "flex items-center justify-between px-2 py-1",
71
- children: [
72
- /* @__PURE__ */ jsx("span", {
73
- className: "text-[10px] text-muted-foreground",
74
- children: label
75
- }),
76
- /* @__PURE__ */ jsx("div", {
77
- className: "flex gap-0.5",
78
- children: keys.map((key) => /* @__PURE__ */ jsx("kbd", {
79
- className: "flex h-5 min-w-[20px] items-center justify-center rounded border bg-muted/50 px-1 font-mono text-[10px]",
80
- children: key
81
- }, key))
82
- })
83
- ]
84
- });
85
- }
86
- function LoadingSpinner() {
87
- return /* @__PURE__ */ jsx("div", {
88
- className: "flex items-center justify-center py-8",
89
- children: /* @__PURE__ */ jsx("div", {
90
- className: "h-5 w-5 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent"
91
- })
92
- });
93
- }
94
-
95
- export { PanelSection, InfoRow, ShortcutRow, LoadingSpinner };