@tangle-network/sandbox-ui 0.13.0 → 0.15.1

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 (106) hide show
  1. package/dist/auth.d.ts +1 -74
  2. package/dist/auth.js +1 -4
  3. package/dist/chat.d.ts +1 -136
  4. package/dist/chat.js +2 -15
  5. package/dist/chunk-2BUPSB7O.js +0 -0
  6. package/dist/chunk-3J6FG3FJ.js +18 -0
  7. package/dist/chunk-76IQLPW2.js +206 -0
  8. package/dist/chunk-7ZA5SEK3.js +239 -0
  9. package/dist/{chunk-ESVYBDGA.js → chunk-AG7QDC2Q.js} +182 -2
  10. package/dist/chunk-AHBZCBDO.js +2960 -0
  11. package/dist/chunk-AZ3AWMTM.js +8 -0
  12. package/dist/chunk-CMY7W45U.js +380 -0
  13. package/dist/{chunk-QMU2PWOU.js → chunk-DNZ4DTNA.js} +71 -17
  14. package/dist/chunk-EI44GEQ5.js +6 -0
  15. package/dist/{chunk-5OQ27N57.js → chunk-GPT7VKK6.js} +34 -38
  16. package/dist/chunk-JBGKGLD7.js +16 -0
  17. package/dist/chunk-NJNME4J4.js +14 -0
  18. package/dist/chunk-QPAJR74X.js +20 -0
  19. package/dist/chunk-TK46XFLM.js +28 -0
  20. package/dist/chunk-WID73FPH.js +89 -0
  21. package/dist/chunk-YVXK4XRO.js +30 -0
  22. package/dist/dashboard.d.ts +538 -4
  23. package/dist/dashboard.js +15 -886
  24. package/dist/editor.d.ts +1 -120
  25. package/dist/editor.js +1 -5
  26. package/dist/files.d.ts +1 -129
  27. package/dist/files.js +2 -7
  28. package/dist/globals.css +5 -1265
  29. package/dist/hooks.d.ts +114 -11
  30. package/dist/hooks.js +17 -88
  31. package/dist/index.d.ts +24 -99
  32. package/dist/index.js +247 -252
  33. package/dist/markdown.d.ts +1 -29
  34. package/dist/markdown.js +2 -2
  35. package/dist/openui.d.ts +8 -115
  36. package/dist/openui.js +1 -6
  37. package/dist/pages.d.ts +1 -2
  38. package/dist/pages.js +68 -66
  39. package/dist/primitives.d.ts +14 -49
  40. package/dist/primitives.js +69 -77
  41. package/dist/run.d.ts +1 -14
  42. package/dist/run.js +2 -22
  43. package/dist/sdk-hooks.d.ts +3 -283
  44. package/dist/sdk-hooks.js +10 -14
  45. package/dist/stores.d.ts +2 -14
  46. package/dist/stores.js +11 -39
  47. package/dist/styles.css +5 -1265
  48. package/dist/{usage-chart-CPTcNlGs.d.ts → template-card-UhV3pmRC.d.ts} +16 -1
  49. package/dist/terminal.js +39 -2
  50. package/dist/types.d.ts +11 -8
  51. package/dist/types.js +1 -0
  52. package/dist/utils.d.ts +1 -44
  53. package/dist/utils.js +6 -12
  54. package/dist/workspace.d.ts +5 -10
  55. package/dist/workspace.js +3 -19
  56. package/package.json +23 -54
  57. package/dist/active-sessions-store-CeOmXgv5.d.ts +0 -85
  58. package/dist/artifact-pane-Bh45Ssco.d.ts +0 -24
  59. package/dist/branding-DCi5VEik.d.ts +0 -13
  60. package/dist/button-CMQuQEW_.d.ts +0 -17
  61. package/dist/chat-container-f4yEs6KN.d.ts +0 -106
  62. package/dist/chunk-34A66VBG.js +0 -214
  63. package/dist/chunk-34I7UFSX.js +0 -92
  64. package/dist/chunk-36QY2W5G.js +0 -802
  65. package/dist/chunk-4CLN43XT.js +0 -45
  66. package/dist/chunk-54SQQMMM.js +0 -156
  67. package/dist/chunk-66EZOYZR.js +0 -102
  68. package/dist/chunk-BX6AQMUS.js +0 -183
  69. package/dist/chunk-DI3NZ5ZX.js +0 -192
  70. package/dist/chunk-DPGIXDAI.js +0 -220
  71. package/dist/chunk-DXMIEK4K.js +0 -1426
  72. package/dist/chunk-GSZA3TSY.js +0 -79
  73. package/dist/chunk-HB5Y37YU.js +0 -54
  74. package/dist/chunk-LQNEZDRM.js +0 -109
  75. package/dist/chunk-MA7YKRUP.js +0 -131
  76. package/dist/chunk-MKTSMWVD.js +0 -109
  77. package/dist/chunk-MQXABZTB.js +0 -1348
  78. package/dist/chunk-MT5FJ3ZT.js +0 -186
  79. package/dist/chunk-NKUPJC34.js +0 -2070
  80. package/dist/chunk-OEX7NZE3.js +0 -321
  81. package/dist/chunk-OKLQVY3Y.js +0 -139
  82. package/dist/chunk-Q56BYXQF.js +0 -61
  83. package/dist/chunk-QD4QE5P5.js +0 -40
  84. package/dist/chunk-QDH5GEGY.js +0 -630
  85. package/dist/chunk-QID2OOMG.js +0 -133
  86. package/dist/chunk-RQHJBTEU.js +0 -10
  87. package/dist/chunk-T7HMZEVO.js +0 -216
  88. package/dist/chunk-U6QTHMY6.js +0 -1290
  89. package/dist/chunk-US6JKJKH.js +0 -124
  90. package/dist/chunk-VX3XOUEB.js +0 -63
  91. package/dist/chunk-XLG757B6.js +0 -933
  92. package/dist/chunk-ZMNSRDMH.js +0 -127
  93. package/dist/chunk-ZNCEM5CD.js +0 -316
  94. package/dist/document-editor-pane-A70-EhdQ.d.ts +0 -124
  95. package/dist/document-editor-pane-TLPVRBBU.js +0 -11
  96. package/dist/expanded-tool-detail-Dh99mcbY.d.ts +0 -63
  97. package/dist/file-tabs-BLfxfmAH.d.ts +0 -51
  98. package/dist/parts-CyGkM6Fp.d.ts +0 -50
  99. package/dist/run-CtFZ6s-D.d.ts +0 -41
  100. package/dist/sidebar-drop-zone-tDBsuOH5.d.ts +0 -301
  101. package/dist/sidecar-CFU2W9j1.d.ts +0 -8
  102. package/dist/template-card-BAtvcAkU.d.ts +0 -18
  103. package/dist/tool-call-feed-Bs3MyQMT.d.ts +0 -68
  104. package/dist/tool-display-Ct9nFAzJ.d.ts +0 -32
  105. package/dist/use-sandbox-metrics-B64diPqN.d.ts +0 -141
  106. package/dist/variant-list-BrHYcBCk.d.ts +0 -540
@@ -1,45 +0,0 @@
1
- // src/utils/format.ts
2
- function formatDuration(ms) {
3
- if (ms < 1e3) return "<1s";
4
- const seconds = Math.floor(ms / 1e3);
5
- if (seconds < 60) return `${seconds}s`;
6
- const minutes = Math.floor(seconds / 60);
7
- const remaining = seconds % 60;
8
- return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
9
- }
10
- function truncateText(text, max) {
11
- const cleaned = text.replace(/\s+/g, " ").trim();
12
- if (cleaned.length <= max) return cleaned;
13
- return cleaned.slice(0, max).trim() + "...";
14
- }
15
- function formatUptime(ms) {
16
- if (!Number.isFinite(ms) || ms < 0) return "\u2014";
17
- const totalSeconds = Math.floor(ms / 1e3);
18
- if (totalSeconds < 60) return `${totalSeconds}s`;
19
- const minutes = Math.floor(totalSeconds / 60);
20
- const seconds = totalSeconds % 60;
21
- if (minutes < 60) return `${minutes}m ${seconds}s`;
22
- const hours = Math.floor(minutes / 60);
23
- const remMinutes = minutes % 60;
24
- if (hours < 24) return `${hours}h ${remMinutes}m`;
25
- const days = Math.floor(hours / 24);
26
- const remHours = hours % 24;
27
- return `${days}d ${remHours}h`;
28
- }
29
- function formatBytes(bytes) {
30
- if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
31
- if (bytes < 1024) return `${Math.round(bytes)} B`;
32
- const kb = bytes / 1024;
33
- if (kb < 1024) return `${kb < 10 ? kb.toFixed(1) : Math.round(kb)} KB`;
34
- const mb = kb / 1024;
35
- if (mb < 1024) return `${mb < 10 ? mb.toFixed(1) : Math.round(mb)} MB`;
36
- const gb = mb / 1024;
37
- return `${gb < 10 ? gb.toFixed(2) : gb.toFixed(1)} GB`;
38
- }
39
-
40
- export {
41
- formatDuration,
42
- truncateText,
43
- formatUptime,
44
- formatBytes
45
- };
@@ -1,156 +0,0 @@
1
- import {
2
- getToolCategory
3
- } from "./chunk-BX6AQMUS.js";
4
-
5
- // src/hooks/use-run-groups.ts
6
- import { useMemo } from "react";
7
- function computeRunStats(messages, partMap) {
8
- const stats = {
9
- toolCount: 0,
10
- messageCount: messages.length,
11
- thinkingDurationMs: 0,
12
- textPartCount: 0,
13
- toolCategories: /* @__PURE__ */ new Set()
14
- };
15
- for (const msg of messages) {
16
- const parts = partMap[msg.id] ?? [];
17
- for (const part of parts) {
18
- switch (part.type) {
19
- case "tool":
20
- stats.toolCount++;
21
- stats.toolCategories.add(getToolCategory(part.tool));
22
- break;
23
- case "text":
24
- if (!part.synthetic) stats.textPartCount++;
25
- break;
26
- case "reasoning": {
27
- const start = part.time?.start;
28
- const end = part.time?.end;
29
- if (start && end) stats.thinkingDurationMs += end - start;
30
- break;
31
- }
32
- }
33
- }
34
- }
35
- return stats;
36
- }
37
- function getLastTextContent(messages, partMap) {
38
- for (let i = messages.length - 1; i >= 0; i--) {
39
- const parts = partMap[messages[i].id] ?? [];
40
- for (let j = parts.length - 1; j >= 0; j--) {
41
- const part = parts[j];
42
- if (part.type === "text" && !part.synthetic && part.text.trim()) {
43
- return part.text.trim();
44
- }
45
- }
46
- }
47
- return null;
48
- }
49
- function useRunGroups({
50
- messages,
51
- partMap,
52
- isStreaming
53
- }) {
54
- return useMemo(() => {
55
- const groups = [];
56
- let currentRunMessages = [];
57
- function flushRun(streaming) {
58
- if (currentRunMessages.length === 0) return;
59
- const msgs = [...currentRunMessages];
60
- const stats = computeRunStats(msgs, partMap);
61
- const summaryText = getLastTextContent(msgs, partMap);
62
- const isComplete = !streaming;
63
- groups.push({
64
- type: "run",
65
- run: {
66
- id: msgs[0].id,
67
- messages: msgs,
68
- isComplete,
69
- isStreaming: streaming,
70
- stats,
71
- summaryText,
72
- finalTextPart: null
73
- }
74
- });
75
- currentRunMessages = [];
76
- }
77
- for (let i = 0; i < messages.length; i++) {
78
- const msg = messages[i];
79
- if (msg.role === "user") {
80
- flushRun(false);
81
- groups.push({ type: "user", message: msg });
82
- } else {
83
- currentRunMessages.push(msg);
84
- }
85
- }
86
- if (currentRunMessages.length > 0) {
87
- flushRun(isStreaming);
88
- }
89
- return groups;
90
- }, [messages, partMap, isStreaming]);
91
- }
92
-
93
- // src/hooks/use-run-collapse-state.ts
94
- import { useCallback, useState } from "react";
95
- function useRunCollapseState(runs) {
96
- const [collapsedMap, setCollapsedMap] = useState({});
97
- const isCollapsed = useCallback(
98
- (runId) => {
99
- return collapsedMap[runId] ?? false;
100
- },
101
- [collapsedMap]
102
- );
103
- const toggleCollapse = useCallback((runId) => {
104
- setCollapsedMap((prev) => ({ ...prev, [runId]: !prev[runId] }));
105
- }, []);
106
- return { isCollapsed, toggleCollapse };
107
- }
108
-
109
- // src/hooks/use-auto-scroll.ts
110
- import {
111
- useCallback as useCallback2,
112
- useEffect,
113
- useRef,
114
- useState as useState2
115
- } from "react";
116
- var BOTTOM_THRESHOLD = 40;
117
- function useAutoScroll(containerRef, deps = []) {
118
- const [isAtBottom, setIsAtBottom] = useState2(true);
119
- const userScrolledUp = useRef(false);
120
- const checkBottom = useCallback2(() => {
121
- const el = containerRef.current;
122
- if (!el) return true;
123
- return el.scrollHeight - el.scrollTop - el.clientHeight < BOTTOM_THRESHOLD;
124
- }, [containerRef]);
125
- useEffect(() => {
126
- const el = containerRef.current;
127
- if (!el) return;
128
- const onScroll = () => {
129
- const atBottom = checkBottom();
130
- setIsAtBottom(atBottom);
131
- userScrolledUp.current = !atBottom;
132
- };
133
- el.addEventListener("scroll", onScroll, { passive: true });
134
- return () => el.removeEventListener("scroll", onScroll);
135
- }, [containerRef, checkBottom]);
136
- useEffect(() => {
137
- if (userScrolledUp.current) return;
138
- const el = containerRef.current;
139
- if (!el) return;
140
- el.scrollTop = el.scrollHeight;
141
- }, deps);
142
- const scrollToBottom = useCallback2(() => {
143
- const el = containerRef.current;
144
- if (!el) return;
145
- userScrolledUp.current = false;
146
- el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
147
- setIsAtBottom(true);
148
- }, [containerRef]);
149
- return { isAtBottom, scrollToBottom };
150
- }
151
-
152
- export {
153
- useRunGroups,
154
- useRunCollapseState,
155
- useAutoScroll
156
- };
@@ -1,102 +0,0 @@
1
- import {
2
- cn
3
- } from "./chunk-RQHJBTEU.js";
4
-
5
- // src/primitives/progress.tsx
6
- import * as ProgressPrimitive from "@radix-ui/react-progress";
7
- import * as React from "react";
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
- var Progress = React.forwardRef(
10
- ({ className, value, variant = "default", showValue = false, ...props }, ref) => {
11
- const indicatorVariants = {
12
- default: "bg-primary",
13
- sandbox: "bg-[image:var(--accent-gradient-strong)]"
14
- };
15
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
16
- /* @__PURE__ */ jsx(
17
- ProgressPrimitive.Root,
18
- {
19
- ref,
20
- className: cn(
21
- "relative h-2 w-full overflow-hidden rounded-full bg-muted",
22
- className
23
- ),
24
- ...props,
25
- children: /* @__PURE__ */ jsx(
26
- ProgressPrimitive.Indicator,
27
- {
28
- className: cn(
29
- "h-full w-full flex-1 transition-all duration-300 ease-out",
30
- indicatorVariants[variant]
31
- ),
32
- style: { transform: `translateX(-${100 - (value || 0)}%)` }
33
- }
34
- )
35
- }
36
- ),
37
- showValue && /* @__PURE__ */ jsxs("span", { className: "absolute -top-6 right-0 text-muted-foreground text-xs", children: [
38
- value,
39
- "%"
40
- ] })
41
- ] });
42
- }
43
- );
44
- Progress.displayName = ProgressPrimitive.Root.displayName;
45
-
46
- // src/primitives/skeleton.tsx
47
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
48
- function Skeleton({
49
- className,
50
- ...props
51
- }) {
52
- return /* @__PURE__ */ jsx2(
53
- "div",
54
- {
55
- className: cn("animate-pulse rounded-lg bg-muted/50", className),
56
- ...props
57
- }
58
- );
59
- }
60
- function SkeletonCard({ className }) {
61
- return /* @__PURE__ */ jsxs2(
62
- "div",
63
- {
64
- className: cn(
65
- "space-y-4 rounded-xl border border-border bg-card p-6",
66
- className
67
- ),
68
- children: [
69
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-3/4" }),
70
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/2" }),
71
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2 pt-4", children: [
72
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-full" }),
73
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-5/6" }),
74
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-4/6" })
75
- ] })
76
- ]
77
- }
78
- );
79
- }
80
- function SkeletonTable({ rows = 5 }) {
81
- return /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
82
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-4 border-border border-b pb-2", children: [
83
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
84
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
85
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
86
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" })
87
- ] }),
88
- Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-4", children: [
89
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
90
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
91
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" }),
92
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-4 w-1/4" })
93
- ] }, i))
94
- ] });
95
- }
96
-
97
- export {
98
- Progress,
99
- Skeleton,
100
- SkeletonCard,
101
- SkeletonTable
102
- };
@@ -1,183 +0,0 @@
1
- // src/utils/tool-display.ts
2
- var TOOL_NAME_PREFIX = "tool:";
3
- function normalizeToolName(tool) {
4
- const n = tool?.toLowerCase() ?? "";
5
- return n.startsWith(TOOL_NAME_PREFIX) ? n.slice(TOOL_NAME_PREFIX.length) : n;
6
- }
7
- function extractString(obj, key) {
8
- if (typeof obj === "object" && obj !== null && key in obj) {
9
- const val = obj[key];
10
- if (typeof val === "string") return val;
11
- }
12
- return void 0;
13
- }
14
- function extractCommand(input) {
15
- if (typeof input === "string") return input;
16
- return extractString(input, "command") ?? extractString(input, "cmd");
17
- }
18
- function extractFilePath(input) {
19
- return extractString(input, "file_path") ?? extractString(input, "path") ?? extractString(input, "filePath") ?? extractString(input, "file");
20
- }
21
- function cleanPath(path) {
22
- const parts = path.split("/");
23
- return parts.length > 3 ? ".../" + parts.slice(-2).join("/") : path;
24
- }
25
- var TOOL_CATEGORY_ICONS = {
26
- command: "terminal",
27
- write: "file-plus",
28
- read: "file-text",
29
- search: "search",
30
- edit: "file-edit",
31
- task: "cpu",
32
- web: "globe",
33
- todo: "check-square",
34
- other: "box"
35
- };
36
- function getToolCategory(toolName) {
37
- const name = normalizeToolName(toolName);
38
- switch (name) {
39
- case "bash":
40
- case "shell":
41
- case "command":
42
- case "execute":
43
- return "command";
44
- case "write":
45
- case "write_file":
46
- case "create_file":
47
- return "write";
48
- case "read":
49
- case "read_file":
50
- case "cat":
51
- return "read";
52
- case "grep":
53
- case "search":
54
- case "rg":
55
- return "search";
56
- case "edit":
57
- case "patch":
58
- case "sed":
59
- return "edit";
60
- case "glob":
61
- case "find":
62
- case "ls":
63
- return "search";
64
- case "web_search":
65
- case "web_fetch":
66
- case "fetch":
67
- return "web";
68
- case "task":
69
- case "agent":
70
- case "spawn":
71
- return "task";
72
- case "todo":
73
- case "todo_write":
74
- return "todo";
75
- default:
76
- return "other";
77
- }
78
- }
79
- function getToolDisplayMetadata(part) {
80
- const name = normalizeToolName(part.tool);
81
- const input = part.state.status !== "pending" ? part.state.input : void 0;
82
- const filePath = extractFilePath(input);
83
- const command = extractCommand(input);
84
- switch (name) {
85
- case "bash":
86
- case "shell":
87
- case "command":
88
- case "execute":
89
- return {
90
- title: "Run command",
91
- description: command ? truncateCommand(command) : void 0,
92
- displayVariant: "command",
93
- commandSnippet: command
94
- };
95
- case "write":
96
- case "write_file":
97
- case "create_file":
98
- return {
99
- title: filePath ? `Write ${cleanPath(filePath)}` : "Write file",
100
- description: filePath,
101
- displayVariant: "write-file",
102
- targetPath: filePath
103
- };
104
- case "edit":
105
- case "patch":
106
- return {
107
- title: filePath ? `Edit ${cleanPath(filePath)}` : "Edit file",
108
- description: filePath,
109
- hasDiffOutput: true,
110
- diffFilePath: filePath,
111
- displayVariant: "diff",
112
- targetPath: filePath
113
- };
114
- case "read":
115
- case "read_file":
116
- case "cat":
117
- return {
118
- title: filePath ? `Read ${cleanPath(filePath)}` : "Read file",
119
- description: filePath,
120
- displayVariant: "read-file",
121
- targetPath: filePath
122
- };
123
- case "grep":
124
- case "search":
125
- case "rg": {
126
- const pattern = extractString(input, "pattern");
127
- return {
128
- title: pattern ? `Search: ${pattern}` : "Search",
129
- description: pattern,
130
- displayVariant: "grep"
131
- };
132
- }
133
- case "glob":
134
- case "find":
135
- case "ls": {
136
- const pattern = extractString(input, "pattern");
137
- return {
138
- title: pattern ? `Find: ${pattern}` : "Find files",
139
- description: pattern,
140
- displayVariant: "glob"
141
- };
142
- }
143
- case "web_search":
144
- case "web_fetch":
145
- case "fetch": {
146
- const query = extractString(input, "query") ?? extractString(input, "url");
147
- return {
148
- title: query ? `Web: ${truncateCommand(query)}` : "Web search",
149
- description: query,
150
- displayVariant: "web-search"
151
- };
152
- }
153
- case "task":
154
- case "agent":
155
- case "spawn": {
156
- const desc = extractString(input, "description") ?? extractString(input, "prompt");
157
- return {
158
- title: desc ? `Task: ${truncateCommand(desc)}` : "Agent task",
159
- description: desc
160
- };
161
- }
162
- default:
163
- return {
164
- title: part.tool || "Tool",
165
- description: command ?? filePath ?? extractString(input, "pattern") ?? extractString(input, "query")
166
- };
167
- }
168
- }
169
- function truncateCommand(cmd) {
170
- const first = cmd.split("\n")[0];
171
- return first.length > 60 ? first.slice(0, 57) + "..." : first;
172
- }
173
- function getToolErrorText(part, fallback) {
174
- if (part.state.status !== "error") return void 0;
175
- return part.state.error || fallback;
176
- }
177
-
178
- export {
179
- TOOL_CATEGORY_ICONS,
180
- getToolCategory,
181
- getToolDisplayMetadata,
182
- getToolErrorText
183
- };
@@ -1,192 +0,0 @@
1
- import {
2
- Avatar,
3
- AvatarFallback,
4
- AvatarImage,
5
- DropdownMenu,
6
- DropdownMenuContent,
7
- DropdownMenuItem,
8
- DropdownMenuLabel,
9
- DropdownMenuSeparator,
10
- DropdownMenuTrigger
11
- } from "./chunk-34A66VBG.js";
12
- import {
13
- Button
14
- } from "./chunk-MKTSMWVD.js";
15
- import {
16
- cn
17
- } from "./chunk-RQHJBTEU.js";
18
-
19
- // src/auth/auth.tsx
20
- import { jsx, jsxs } from "react/jsx-runtime";
21
- function GitHubIcon({ className }) {
22
- return /* @__PURE__ */ jsx(
23
- "svg",
24
- {
25
- className,
26
- viewBox: "0 0 24 24",
27
- fill: "currentColor",
28
- "aria-hidden": "true",
29
- children: /* @__PURE__ */ jsx(
30
- "path",
31
- {
32
- fillRule: "evenodd",
33
- clipRule: "evenodd",
34
- d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
35
- }
36
- )
37
- }
38
- );
39
- }
40
- function GitHubLoginButton({
41
- authUrl = "/auth/github",
42
- variant = "default",
43
- className,
44
- children,
45
- ...props
46
- }) {
47
- return /* @__PURE__ */ jsxs(
48
- Button,
49
- {
50
- variant,
51
- className: cn("gap-2", className),
52
- onClick: () => {
53
- window.location.href = authUrl;
54
- },
55
- ...props,
56
- children: [
57
- /* @__PURE__ */ jsx(GitHubIcon, { className: "h-5 w-5" }),
58
- children ?? "Sign in with GitHub"
59
- ]
60
- }
61
- );
62
- }
63
- function UserMenu({
64
- user,
65
- logoutUrl = "/auth/logout",
66
- links = [],
67
- variant = "sandbox",
68
- onLogout
69
- }) {
70
- const initials = user.name ? user.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : user.email.slice(0, 2).toUpperCase();
71
- const avatarGradient = {
72
- sandbox: "bg-[image:var(--accent-gradient-strong)]"
73
- }[variant];
74
- const handleLogout = () => {
75
- if (onLogout) {
76
- onLogout();
77
- }
78
- window.location.href = logoutUrl;
79
- };
80
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
81
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
82
- "button",
83
- {
84
- type: "button",
85
- className: "flex items-center gap-2 rounded-lg p-1.5 transition-colors hover:bg-accent focus:outline-none focus:ring-2 focus:ring-ring",
86
- children: [
87
- /* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8", children: [
88
- /* @__PURE__ */ jsx(AvatarImage, { src: void 0, alt: user.name ?? user.email }),
89
- /* @__PURE__ */ jsx(
90
- AvatarFallback,
91
- {
92
- className: cn(
93
- "text-white text-xs",
94
- avatarGradient
95
- ),
96
- children: initials
97
- }
98
- )
99
- ] }),
100
- /* @__PURE__ */ jsxs("div", { className: "hidden text-left md:block", children: [
101
- /* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: user.name ?? user.email }),
102
- user.tier && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-xs capitalize", children: [
103
- user.tier,
104
- " Plan"
105
- ] })
106
- ] })
107
- ]
108
- }
109
- ) }),
110
- /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
111
- /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-1", children: [
112
- /* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: user.name ?? "Account" }),
113
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: user.email })
114
- ] }) }),
115
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
116
- links.map((link) => /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs("a", { href: link.href, className: "flex items-center gap-2", children: [
117
- link.icon,
118
- link.label
119
- ] }) }, link.href)),
120
- links.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
121
- /* @__PURE__ */ jsx(
122
- DropdownMenuItem,
123
- {
124
- onClick: handleLogout,
125
- className: "text-[var(--surface-danger-text)] focus:text-[var(--surface-danger-text)]",
126
- children: "Sign out"
127
- }
128
- )
129
- ] })
130
- ] });
131
- }
132
- function AuthHeader({
133
- user,
134
- loading = false,
135
- variant = "sandbox",
136
- apiBaseUrl = "",
137
- menuLinks,
138
- className
139
- }) {
140
- if (loading) {
141
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
142
- /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-pulse rounded-full bg-muted" }),
143
- /* @__PURE__ */ jsx("div", { className: "hidden md:block", children: /* @__PURE__ */ jsx("div", { className: "h-4 w-20 animate-pulse rounded bg-muted" }) })
144
- ] });
145
- }
146
- if (!user) {
147
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), children: /* @__PURE__ */ jsx(
148
- GitHubLoginButton,
149
- {
150
- authUrl: `${apiBaseUrl}/auth/github`,
151
- variant,
152
- size: "sm"
153
- }
154
- ) });
155
- }
156
- return /* @__PURE__ */ jsx(
157
- UserMenu,
158
- {
159
- user,
160
- variant,
161
- logoutUrl: `${apiBaseUrl}/auth/logout`,
162
- links: menuLinks
163
- }
164
- );
165
- }
166
-
167
- // src/auth/login-layout.tsx
168
- import { Terminal } from "lucide-react";
169
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
170
- function LoginLayout({
171
- title = "Welcome Back",
172
- subtitle = "Sign in to your workspace.",
173
- brandIcon,
174
- children,
175
- className
176
- }) {
177
- return /* @__PURE__ */ jsx2("div", { className: cn("relative flex min-h-screen items-center justify-center bg-background overflow-hidden antialiased font-sans flex-col", className), children: /* @__PURE__ */ jsxs2("div", { className: "z-10 w-full max-w-md px-6 animate-in flex flex-col items-center", children: [
178
- /* @__PURE__ */ jsxs2("div", { className: "mb-10 text-center flex flex-col items-center", children: [
179
- /* @__PURE__ */ jsx2("div", { className: "inline-flex h-14 w-14 mb-4 items-center justify-center rounded-lg bg-muted border border-border", children: brandIcon || /* @__PURE__ */ jsx2(Terminal, { className: "h-7 w-7 text-foreground" }) }),
180
- /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight text-foreground font-display", children: title }),
181
- /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: subtitle })
182
- ] }),
183
- /* @__PURE__ */ jsx2("div", { className: "w-full bg-card p-8 border border-border rounded-lg", children })
184
- ] }) });
185
- }
186
-
187
- export {
188
- GitHubLoginButton,
189
- UserMenu,
190
- AuthHeader,
191
- LoginLayout
192
- };