@tangle-network/ui 11.10.0 → 11.11.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.
- package/CHANGELOG.md +14 -0
- package/README.md +4 -1
- package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
- package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
- package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
- package/dist/artifact-pane-DMXT9a8U.js +70 -0
- package/dist/auth-DOETfnd9.js +154 -0
- package/dist/auth.d.ts +2 -74
- package/dist/auth.js +2 -16
- package/dist/branding-26d5ARIr.d.ts +14 -0
- package/dist/button-C87nEe2R.js +78 -0
- package/dist/button-yoIv77e2.d.ts +16 -0
- package/dist/chat-D4jAfEmj.js +667 -0
- package/dist/chat.d.ts +2 -201
- package/dist/chat.js +2 -31
- package/dist/code-block-B36KVUSN.js +165 -0
- package/dist/code-block-B9miUPht.d.ts +23 -0
- package/dist/diff-preview-BcK3nRXb.js +533 -0
- package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
- package/dist/document-editor-pane-BxlPjaTP.js +1287 -0
- package/dist/dropdown-menu-BpcLa5vF.js +101 -0
- package/dist/editor.d.ts +76 -78
- package/dist/editor.js +2 -34
- package/dist/file-format-BgXbr-Ib.js +160 -0
- package/dist/files-Bug33qCl.js +743 -0
- package/dist/files.d.ts +2 -243
- package/dist/files.js +3 -41
- package/dist/focus-BcE_SHqz.js +57 -0
- package/dist/format-DfcLWqMa.js +54 -0
- package/dist/hooks.d.ts +30 -37
- package/dist/hooks.js +111 -46
- package/dist/index-2UntyjBb.d.ts +52 -0
- package/dist/index-BgUHilZm.d.ts +108 -0
- package/dist/index-COgqsFAQ.d.ts +42 -0
- package/dist/index-CPDET_s1.d.ts +549 -0
- package/dist/index-CUhfHT_V.d.ts +204 -0
- package/dist/index-Cg6gYAqh.d.ts +73 -0
- package/dist/index-Cq-EJzqW.d.ts +16 -0
- package/dist/index-DhYmSaLF.d.ts +245 -0
- package/dist/index-DjKxO357.d.ts +128 -0
- package/dist/index.d.ts +26 -43
- package/dist/index.js +35 -472
- package/dist/markdown-BGqicV82.js +45 -0
- package/dist/markdown.d.ts +3 -18
- package/dist/markdown.js +3 -15
- package/dist/message-vhUI0c5G.d.ts +16 -0
- package/dist/nav.d.ts +6 -8
- package/dist/nav.js +29 -11
- package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
- package/dist/openui-artifact-renderer-DrU1AdVk.js +266 -0
- package/dist/openui.d.ts +2 -115
- package/dist/openui.js +2 -13
- package/dist/parts-5mhy9yJ3.d.ts +37 -0
- package/dist/primitives-Cb8GGVKr.js +1239 -0
- package/dist/primitives.d.ts +5 -525
- package/dist/primitives.js +9 -212
- package/dist/redaction-CGGB2ENG.js +74 -0
- package/dist/redaction.d.ts +2 -42
- package/dist/redaction.js +2 -7
- package/dist/run-OyWmIDqu.d.ts +41 -0
- package/dist/run-ZsIKPA6J.js +17 -0
- package/dist/run-group-BACLbCFl.js +410 -0
- package/dist/run.d.ts +3 -126
- package/dist/run.js +5 -40
- package/dist/sdk-hooks.d.ts +2 -285
- package/dist/sdk-hooks.js +3 -36
- package/dist/stores.d.ts +13 -14
- package/dist/stores.js +34 -76
- package/dist/table-Bss73DhB.js +146 -0
- package/dist/tabs-BVHR6NkO.js +40 -0
- package/dist/text-shimmer-BUUo6I-g.js +64 -0
- package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
- package/dist/tool-call-feed-Djt2q11V.js +109 -0
- package/dist/tool-call-step-DNebqhmX.js +434 -0
- package/dist/tool-display-BAuAVa43.js +158 -0
- package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
- package/dist/tool-previews.d.ts +2 -48
- package/dist/tool-previews.js +2 -23
- package/dist/types.d.ts +6 -19
- package/dist/types.js +0 -1
- package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
- package/dist/use-sse-stream-BVgO1QBN.js +884 -0
- package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
- package/dist/utils-Bl_CZ0Qp.js +37 -0
- package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
- package/dist/utils.d.ts +2 -104
- package/dist/utils.js +6 -44
- package/package.json +39 -41
- package/src/lib/focus.ts +2 -1
- package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
- package/dist/button-CMQuQEW_.d.ts +0 -17
- package/dist/chunk-34A66VBG.js +0 -214
- package/dist/chunk-3OI2QKFD.js +0 -0
- package/dist/chunk-3XXBZL53.js +0 -174
- package/dist/chunk-42PAH5D2.js +0 -112
- package/dist/chunk-4CLN43XT.js +0 -45
- package/dist/chunk-55WHV7SS.js +0 -1604
- package/dist/chunk-565EATZZ.js +0 -156
- package/dist/chunk-5Z5ZYMOJ.js +0 -0
- package/dist/chunk-6BGQA4BQ.js +0 -0
- package/dist/chunk-BEBXZPHW.js +0 -299
- package/dist/chunk-C5WF4WMV.js +0 -734
- package/dist/chunk-HFL6R6IF.js +0 -37
- package/dist/chunk-HGML45QH.js +0 -104
- package/dist/chunk-HMAPIH7L.js +0 -595
- package/dist/chunk-K5XFRUS4.js +0 -1401
- package/dist/chunk-KFQGHD73.js +0 -198
- package/dist/chunk-L57WRIND.js +0 -59
- package/dist/chunk-LTEKI7YJ.js +0 -59
- package/dist/chunk-M3QZK62R.js +0 -233
- package/dist/chunk-ND3ZFXQK.js +0 -179
- package/dist/chunk-OEX7NZE3.js +0 -321
- package/dist/chunk-OL5GYLHV.js +0 -60
- package/dist/chunk-QGFYBNSO.js +0 -133
- package/dist/chunk-R7B3UWPF.js +0 -550
- package/dist/chunk-R7SUY4E3.js +0 -65
- package/dist/chunk-REJESC5U.js +0 -117
- package/dist/chunk-RQGKSCEZ.js +0 -0
- package/dist/chunk-SNLR2AEA.js +0 -40
- package/dist/chunk-WKWBTL2V.js +0 -15
- package/dist/chunk-X7CU776B.js +0 -1048
- package/dist/chunk-XU3HB5QL.js +0 -127
- package/dist/chunk-YTO5V6QS.js +0 -19
- package/dist/chunk-YU4E5J2N.js +0 -437
- package/dist/chunk-YZ6AK25N.js +0 -886
- package/dist/code-block-0kSpWMnf.d.ts +0 -25
- package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
- package/dist/document-editor-pane-QHDOBA43.js +0 -13
- package/dist/message-BHWbxBtT.d.ts +0 -15
- package/dist/parts-dj7AcUg0.d.ts +0 -36
- package/dist/run-PfLmDAox.d.ts +0 -41
- package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @tangle-network/ui
|
|
2
2
|
|
|
3
|
+
## 11.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1f0b651: Keep the native field fallback outline off borderless editors inside composite fields. The shared focusFieldWithin helper retains the rounded outer border and halo; standalone fields keep their own focus treatment.
|
|
8
|
+
|
|
9
|
+
## 11.11.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- dc84d1c: Update every dependency to its latest release and build with tsdown on TypeScript 7.
|
|
14
|
+
`@tangle-network/ui` now accepts `@nanostores/react` 2 as a peer, moves to lucide-react 1 and marked 18, and drops the unused `react-pdf` and `@radix-ui/react-toast` dependencies.
|
|
15
|
+
Export paths are unchanged; internal chunk file names differ.
|
|
16
|
+
|
|
3
17
|
## 11.10.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -114,4 +114,7 @@ A TypeScript consumer resolves these entries through the emitted declarations, a
|
|
|
114
114
|
|
|
115
115
|
Because the peers now resolve at first render rather than at build time, a missing one surfaces as a thrown error while React renders. Wrap the editors in an error boundary, so the install list reaches a surface you control instead of unmounting the tree.
|
|
116
116
|
|
|
117
|
-
`nanostores` and `@nanostores/react` back `./stores`, and `react-router` backs `./nav`.
|
|
117
|
+
`nanostores` and `@nanostores/react` back `./stores`, and `react-router` backs `./nav`.
|
|
118
|
+
Those entries create values at module scope, so consumers must install their peers before importing them.
|
|
119
|
+
The package root also re-exports `./stores`, so a root import requires both nanostores peers.
|
|
120
|
+
Consumers that use only other subpath entries do not need these three peers.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useStore } from "@nanostores/react";
|
|
3
|
+
import { atom } from "nanostores";
|
|
4
|
+
//#region src/stores/active-sessions-store.ts
|
|
5
|
+
const INITIAL_STATE = {
|
|
6
|
+
sessions: {},
|
|
7
|
+
lastUpdatedAt: 0
|
|
8
|
+
};
|
|
9
|
+
const STATUS_PRIORITY = {
|
|
10
|
+
running: 0,
|
|
11
|
+
error: 1,
|
|
12
|
+
"attention-needed": 2,
|
|
13
|
+
idle: 3
|
|
14
|
+
};
|
|
15
|
+
const DEFAULT_RECORD = {
|
|
16
|
+
status: "idle",
|
|
17
|
+
isRunning: false,
|
|
18
|
+
isForeground: false,
|
|
19
|
+
needsAttention: false,
|
|
20
|
+
connectionState: "disconnected",
|
|
21
|
+
reconnectState: "idle",
|
|
22
|
+
transportMode: null,
|
|
23
|
+
lastError: null,
|
|
24
|
+
lastEventAt: null
|
|
25
|
+
};
|
|
26
|
+
const activeSessionsAtom = atom(INITIAL_STATE);
|
|
27
|
+
let foregroundSessionId = null;
|
|
28
|
+
function createRecord(options, now) {
|
|
29
|
+
return {
|
|
30
|
+
sessionId: options.sessionId,
|
|
31
|
+
projectId: options.projectId ?? null,
|
|
32
|
+
projectLabel: options.projectLabel,
|
|
33
|
+
title: options.title,
|
|
34
|
+
href: options.href,
|
|
35
|
+
registeredAt: now,
|
|
36
|
+
lastActivityAt: now,
|
|
37
|
+
metadata: options.metadata,
|
|
38
|
+
...DEFAULT_RECORD,
|
|
39
|
+
isForeground: options.sessionId === foregroundSessionId
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function resolveStatus(session) {
|
|
43
|
+
if (session.isRunning) return "running";
|
|
44
|
+
if (session.lastError || session.reconnectState === "failed") return "error";
|
|
45
|
+
if (session.needsAttention) return "attention-needed";
|
|
46
|
+
return "idle";
|
|
47
|
+
}
|
|
48
|
+
function normalizeSession(session) {
|
|
49
|
+
return {
|
|
50
|
+
...session,
|
|
51
|
+
status: resolveStatus(session)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function updateSession(sessionId, updater) {
|
|
55
|
+
const current = activeSessionsAtom.get();
|
|
56
|
+
const existing = current.sessions[sessionId];
|
|
57
|
+
if (!existing) return;
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
activeSessionsAtom.set({
|
|
60
|
+
sessions: {
|
|
61
|
+
...current.sessions,
|
|
62
|
+
[sessionId]: normalizeSession(updater(existing, now))
|
|
63
|
+
},
|
|
64
|
+
lastUpdatedAt: now
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function registerActiveSession(options) {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const current = activeSessionsAtom.get();
|
|
70
|
+
const existing = current.sessions[options.sessionId];
|
|
71
|
+
activeSessionsAtom.set({
|
|
72
|
+
sessions: {
|
|
73
|
+
...current.sessions,
|
|
74
|
+
[options.sessionId]: normalizeSession(existing ? {
|
|
75
|
+
...existing,
|
|
76
|
+
projectId: existing.projectId ?? options.projectId ?? null,
|
|
77
|
+
projectLabel: options.projectLabel ?? existing.projectLabel,
|
|
78
|
+
title: options.title ?? existing.title,
|
|
79
|
+
href: options.href ?? existing.href,
|
|
80
|
+
metadata: options.metadata ?? existing.metadata,
|
|
81
|
+
lastActivityAt: now,
|
|
82
|
+
isForeground: options.sessionId === foregroundSessionId || existing.isForeground
|
|
83
|
+
} : createRecord(options, now))
|
|
84
|
+
},
|
|
85
|
+
lastUpdatedAt: now
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function unregisterActiveSession(sessionId) {
|
|
89
|
+
const current = activeSessionsAtom.get();
|
|
90
|
+
if (!current.sessions[sessionId]) return;
|
|
91
|
+
const { [sessionId]: _removed, ...remaining } = current.sessions;
|
|
92
|
+
if (foregroundSessionId === sessionId) foregroundSessionId = null;
|
|
93
|
+
activeSessionsAtom.set({
|
|
94
|
+
sessions: remaining,
|
|
95
|
+
lastUpdatedAt: Date.now()
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function setForegroundActiveSession(sessionId) {
|
|
99
|
+
foregroundSessionId = sessionId;
|
|
100
|
+
const current = activeSessionsAtom.get();
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
let changed = false;
|
|
103
|
+
const sessions = Object.fromEntries(Object.entries(current.sessions).map(([id, session]) => {
|
|
104
|
+
const isForeground = id === sessionId;
|
|
105
|
+
if (session.isForeground !== isForeground) changed = true;
|
|
106
|
+
return [id, {
|
|
107
|
+
...session,
|
|
108
|
+
isForeground,
|
|
109
|
+
lastActivityAt: isForeground ? now : session.lastActivityAt
|
|
110
|
+
}];
|
|
111
|
+
}));
|
|
112
|
+
if (!changed) return;
|
|
113
|
+
activeSessionsAtom.set({
|
|
114
|
+
sessions,
|
|
115
|
+
lastUpdatedAt: now
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function updateActiveSessionMeta(sessionId, meta) {
|
|
119
|
+
updateSession(sessionId, (session, now) => ({
|
|
120
|
+
...session,
|
|
121
|
+
...meta,
|
|
122
|
+
lastActivityAt: now
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
function setActiveSessionConnection(sessionId, options) {
|
|
126
|
+
updateSession(sessionId, (session, now) => ({
|
|
127
|
+
...session,
|
|
128
|
+
connectionState: options.connectionState,
|
|
129
|
+
reconnectState: options.reconnectState ?? session.reconnectState,
|
|
130
|
+
transportMode: options.transportMode ?? session.transportMode,
|
|
131
|
+
lastError: options.lastError === void 0 ? session.lastError : options.lastError,
|
|
132
|
+
lastEventAt: options.lastEventAt ?? session.lastEventAt,
|
|
133
|
+
lastActivityAt: now
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
function setActiveSessionRunning(sessionId, isRunning, options) {
|
|
137
|
+
updateSession(sessionId, (session, now) => ({
|
|
138
|
+
...session,
|
|
139
|
+
isRunning,
|
|
140
|
+
needsAttention: isRunning ? false : session.needsAttention,
|
|
141
|
+
lastError: isRunning ? null : session.lastError,
|
|
142
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt,
|
|
143
|
+
lastActivityAt: now
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
function setActiveSessionAttention(sessionId, needsAttention, options) {
|
|
147
|
+
updateSession(sessionId, (session, now) => ({
|
|
148
|
+
...session,
|
|
149
|
+
needsAttention,
|
|
150
|
+
isRunning: needsAttention ? false : session.isRunning,
|
|
151
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt,
|
|
152
|
+
lastActivityAt: now
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
function setActiveSessionError(sessionId, error) {
|
|
156
|
+
updateSession(sessionId, (session, now) => ({
|
|
157
|
+
...session,
|
|
158
|
+
isRunning: false,
|
|
159
|
+
needsAttention: false,
|
|
160
|
+
lastError: error,
|
|
161
|
+
reconnectState: error ? "failed" : "idle",
|
|
162
|
+
connectionState: error ? "error" : session.connectionState,
|
|
163
|
+
lastEventAt: now,
|
|
164
|
+
lastActivityAt: now
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
function bumpActiveSessionActivity(sessionId, options) {
|
|
168
|
+
updateSession(sessionId, (session, now) => ({
|
|
169
|
+
...session,
|
|
170
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt ?? now,
|
|
171
|
+
lastActivityAt: now
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
function resetActiveSessions() {
|
|
175
|
+
foregroundSessionId = null;
|
|
176
|
+
activeSessionsAtom.set(INITIAL_STATE);
|
|
177
|
+
}
|
|
178
|
+
function getAllActiveSessions(state) {
|
|
179
|
+
return Object.values(state.sessions);
|
|
180
|
+
}
|
|
181
|
+
function getActiveSession(state, sessionId) {
|
|
182
|
+
return state.sessions[sessionId] ?? null;
|
|
183
|
+
}
|
|
184
|
+
function getSessionsForProject(state, projectId) {
|
|
185
|
+
return Object.values(state.sessions).filter((session) => session.projectId === projectId);
|
|
186
|
+
}
|
|
187
|
+
function getSessionsForNavbar(state, projectId) {
|
|
188
|
+
return [...projectId == null ? Object.values(state.sessions) : getSessionsForProject(state, projectId)].sort((left, right) => {
|
|
189
|
+
if (left.isForeground !== right.isForeground) return Number(right.isForeground) - Number(left.isForeground);
|
|
190
|
+
const statusDiff = STATUS_PRIORITY[left.status] - STATUS_PRIORITY[right.status];
|
|
191
|
+
if (statusDiff !== 0) return statusDiff;
|
|
192
|
+
return right.lastActivityAt - left.lastActivityAt;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function getSessionsByActivity(state) {
|
|
196
|
+
return [...Object.values(state.sessions)].sort((left, right) => right.lastActivityAt - left.lastActivityAt);
|
|
197
|
+
}
|
|
198
|
+
function getTotalRunningSessionCount(state) {
|
|
199
|
+
return Object.values(state.sessions).filter((session) => session.isRunning).length;
|
|
200
|
+
}
|
|
201
|
+
function hasBackgroundRunningSessions(state) {
|
|
202
|
+
return Object.values(state.sessions).some((session) => session.isRunning && !session.isForeground);
|
|
203
|
+
}
|
|
204
|
+
function getAllProjectActivity(state) {
|
|
205
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const session of Object.values(state.sessions)) {
|
|
207
|
+
if (session.projectId == null) continue;
|
|
208
|
+
const existing = grouped.get(session.projectId);
|
|
209
|
+
if (existing) {
|
|
210
|
+
existing.activeSessionCount += 1;
|
|
211
|
+
existing.lastActivityAt = Math.max(existing.lastActivityAt, session.lastActivityAt);
|
|
212
|
+
if (session.isRunning) existing.runningSessionIds.push(session.sessionId);
|
|
213
|
+
if (!existing.projectLabel && session.projectLabel) existing.projectLabel = session.projectLabel;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
grouped.set(session.projectId, {
|
|
217
|
+
projectId: session.projectId,
|
|
218
|
+
projectLabel: session.projectLabel,
|
|
219
|
+
activeSessionCount: 1,
|
|
220
|
+
runningSessionIds: session.isRunning ? [session.sessionId] : [],
|
|
221
|
+
lastActivityAt: session.lastActivityAt
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return [...grouped.values()].sort((left, right) => right.lastActivityAt - left.lastActivityAt);
|
|
225
|
+
}
|
|
226
|
+
function useActiveSessionsState() {
|
|
227
|
+
return useStore(activeSessionsAtom);
|
|
228
|
+
}
|
|
229
|
+
function useActiveSessions() {
|
|
230
|
+
const state = useStore(activeSessionsAtom);
|
|
231
|
+
return useMemo(() => getAllActiveSessions(state), [state]);
|
|
232
|
+
}
|
|
233
|
+
function useActiveSession(sessionId) {
|
|
234
|
+
const state = useStore(activeSessionsAtom);
|
|
235
|
+
return useMemo(() => sessionId ? getActiveSession(state, sessionId) : null, [sessionId, state]);
|
|
236
|
+
}
|
|
237
|
+
function useProjectSessions(projectId) {
|
|
238
|
+
const state = useStore(activeSessionsAtom);
|
|
239
|
+
return useMemo(() => projectId == null ? [] : getSessionsForProject(state, projectId), [projectId, state]);
|
|
240
|
+
}
|
|
241
|
+
function useNavbarSessions(projectId) {
|
|
242
|
+
const state = useStore(activeSessionsAtom);
|
|
243
|
+
return useMemo(() => getSessionsForNavbar(state, projectId), [projectId, state]);
|
|
244
|
+
}
|
|
245
|
+
function useSessionsByActivity() {
|
|
246
|
+
const state = useStore(activeSessionsAtom);
|
|
247
|
+
return useMemo(() => getSessionsByActivity(state), [state]);
|
|
248
|
+
}
|
|
249
|
+
function useProjectActivity() {
|
|
250
|
+
const state = useStore(activeSessionsAtom);
|
|
251
|
+
return useMemo(() => getAllProjectActivity(state), [state]);
|
|
252
|
+
}
|
|
253
|
+
function useTotalRunningSessions() {
|
|
254
|
+
const state = useStore(activeSessionsAtom);
|
|
255
|
+
return useMemo(() => getTotalRunningSessionCount(state), [state]);
|
|
256
|
+
}
|
|
257
|
+
function useHasBackgroundRunningSessions() {
|
|
258
|
+
const state = useStore(activeSessionsAtom);
|
|
259
|
+
return useMemo(() => hasBackgroundRunningSessions(state), [state]);
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
export { useHasBackgroundRunningSessions as C, useSessionsByActivity as D, useProjectSessions as E, useTotalRunningSessions as O, useActiveSessionsState as S, useProjectActivity as T, setForegroundActiveSession as _, getAllProjectActivity as a, useActiveSession as b, getSessionsForProject as c, registerActiveSession as d, resetActiveSessions as f, setActiveSessionRunning as g, setActiveSessionError as h, getAllActiveSessions as i, getTotalRunningSessionCount as l, setActiveSessionConnection as m, bumpActiveSessionActivity as n, getSessionsByActivity as o, setActiveSessionAttention as p, getActiveSession as r, getSessionsForNavbar as s, activeSessionsAtom as t, hasBackgroundRunningSessions as u, unregisterActiveSession as v, useNavbarSessions as w, useActiveSessions as x, updateActiveSessionMeta as y };
|
|
@@ -1,59 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/stores/active-sessions-store.d.ts
|
|
3
2
|
type SessionProjectKey = string | number;
|
|
4
3
|
type ActiveSessionStatus = "idle" | "running" | "attention-needed" | "error";
|
|
5
4
|
type ActiveSessionReconnectState = "idle" | "reconnecting" | "failed";
|
|
6
5
|
type ActiveSessionConnectionState = "disconnected" | "connecting" | "connected" | "reconnecting" | "error";
|
|
7
6
|
type ActiveSessionTransportMode = "websocket" | "sse" | "polling" | "custom";
|
|
8
7
|
interface ActiveSessionRecord {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
sessionId: string;
|
|
9
|
+
projectId: SessionProjectKey | null;
|
|
10
|
+
projectLabel?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
href?: string;
|
|
13
|
+
registeredAt: number;
|
|
14
|
+
lastActivityAt: number;
|
|
15
|
+
lastEventAt: number | null;
|
|
16
|
+
status: ActiveSessionStatus;
|
|
17
|
+
isRunning: boolean;
|
|
18
|
+
isForeground: boolean;
|
|
19
|
+
needsAttention: boolean;
|
|
20
|
+
connectionState: ActiveSessionConnectionState;
|
|
21
|
+
reconnectState: ActiveSessionReconnectState;
|
|
22
|
+
transportMode: ActiveSessionTransportMode | null;
|
|
23
|
+
lastError: string | null;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
26
25
|
}
|
|
27
26
|
interface ActiveSessionsState {
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
sessions: Record<string, ActiveSessionRecord>;
|
|
28
|
+
lastUpdatedAt: number;
|
|
30
29
|
}
|
|
31
30
|
interface RegisterActiveSessionOptions {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
sessionId: string;
|
|
32
|
+
projectId?: SessionProjectKey | null;
|
|
33
|
+
projectLabel?: string;
|
|
34
|
+
title?: string;
|
|
35
|
+
href?: string;
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
38
37
|
}
|
|
39
38
|
interface ActiveSessionConnectionOptions {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
connectionState: ActiveSessionConnectionState;
|
|
40
|
+
reconnectState?: ActiveSessionReconnectState;
|
|
41
|
+
transportMode?: ActiveSessionTransportMode | null;
|
|
42
|
+
lastError?: string | null;
|
|
43
|
+
lastEventAt?: number | null;
|
|
45
44
|
}
|
|
46
45
|
interface ActiveSessionActivityOptions {
|
|
47
|
-
|
|
46
|
+
lastEventAt?: number | null;
|
|
48
47
|
}
|
|
49
48
|
interface ActiveProjectActivity {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
projectId: SessionProjectKey;
|
|
50
|
+
projectLabel?: string;
|
|
51
|
+
activeSessionCount: number;
|
|
52
|
+
runningSessionIds: string[];
|
|
53
|
+
lastActivityAt: number;
|
|
55
54
|
}
|
|
56
|
-
declare const activeSessionsAtom: nanostores.PreinitializedWritableAtom<ActiveSessionsState> & object;
|
|
55
|
+
declare const activeSessionsAtom: import("nanostores").PreinitializedWritableAtom<ActiveSessionsState> & object;
|
|
57
56
|
declare function registerActiveSession(options: RegisterActiveSessionOptions): void;
|
|
58
57
|
declare function unregisterActiveSession(sessionId: string): void;
|
|
59
58
|
declare function setForegroundActiveSession(sessionId: string | null): void;
|
|
@@ -81,5 +80,5 @@ declare function useSessionsByActivity(): ActiveSessionRecord[];
|
|
|
81
80
|
declare function useProjectActivity(): ActiveProjectActivity[];
|
|
82
81
|
declare function useTotalRunningSessions(): number;
|
|
83
82
|
declare function useHasBackgroundRunningSessions(): boolean;
|
|
84
|
-
|
|
85
|
-
export {
|
|
83
|
+
//#endregion
|
|
84
|
+
export { updateActiveSessionMeta as A, resetActiveSessions as C, setActiveSessionRunning as D, setActiveSessionError as E, useNavbarSessions as F, useProjectActivity as I, useProjectSessions as L, useActiveSessions as M, useActiveSessionsState as N, setForegroundActiveSession as O, useHasBackgroundRunningSessions as P, useSessionsByActivity as R, registerActiveSession as S, setActiveSessionConnection as T, getSessionsByActivity as _, ActiveSessionReconnectState as a, getTotalRunningSessionCount as b, ActiveSessionTransportMode as c, SessionProjectKey as d, activeSessionsAtom as f, getAllProjectActivity as g, getAllActiveSessions as h, ActiveSessionConnectionState as i, useActiveSession as j, unregisterActiveSession as k, ActiveSessionsState as l, getActiveSession as m, ActiveSessionActivityOptions as n, ActiveSessionRecord as o, bumpActiveSessionActivity as p, ActiveSessionConnectionOptions as r, ActiveSessionStatus as s, ActiveProjectActivity as t, RegisterActiveSessionOptions as u, getSessionsForNavbar as v, setActiveSessionAttention as w, hasBackgroundRunningSessions as x, getSessionsForProject as y, useTotalRunningSessions as z };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/primitives/artifact-pane.d.ts
|
|
3
|
+
interface ArtifactPaneProps {
|
|
4
|
+
eyebrow?: ReactNode;
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
subtitle?: ReactNode;
|
|
7
|
+
meta?: ReactNode;
|
|
8
|
+
headerActions?: ReactNode;
|
|
9
|
+
tabs?: ReactNode;
|
|
10
|
+
toolbar?: ReactNode;
|
|
11
|
+
footer?: ReactNode;
|
|
12
|
+
emptyState?: ReactNode;
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
contentClassName?: string;
|
|
16
|
+
/** Extra classes for the header band (e.g. to align its surface with the host chrome). */
|
|
17
|
+
headerClassName?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Suppress the eyebrow/title/subtitle/meta block. Use when the host already
|
|
20
|
+
* shows the artifact's identity elsewhere (e.g. a surrounding path row), so the
|
|
21
|
+
* pane keeps only its tabs, toolbar, and header actions. The whole header row
|
|
22
|
+
* collapses when nothing else would render in it.
|
|
23
|
+
*/
|
|
24
|
+
hideTitleBlock?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* ArtifactPane — shared frame for files, previews, documents, inspectors, and
|
|
28
|
+
* other artifact-like surfaces inside sandbox applications.
|
|
29
|
+
*/
|
|
30
|
+
declare function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, headerClassName, hideTitleBlock }: ArtifactPaneProps): import("react").JSX.Element;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ArtifactPaneProps as n, ArtifactPane as t };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { t as cn } from "./utils-C_uf36nf.js";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/primitives/artifact-pane.tsx
|
|
4
|
+
/**
|
|
5
|
+
* ArtifactPane — shared frame for files, previews, documents, inspectors, and
|
|
6
|
+
* other artifact-like surfaces inside sandbox applications.
|
|
7
|
+
*/
|
|
8
|
+
function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, headerClassName, hideTitleBlock = false }) {
|
|
9
|
+
const hasContent = children !== void 0 && children !== null;
|
|
10
|
+
const showTitleRow = !hideTitleBlock || Boolean(headerActions);
|
|
11
|
+
const hasHeader = showTitleRow || Boolean(tabs) || Boolean(toolbar);
|
|
12
|
+
const toolbarNeedsDivider = showTitleRow || Boolean(tabs);
|
|
13
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
14
|
+
className: cn("flex h-full min-h-0 flex-col overflow-hidden bg-background text-foreground", className),
|
|
15
|
+
children: [
|
|
16
|
+
hasHeader && /* @__PURE__ */ jsxs("header", {
|
|
17
|
+
className: cn("border-b border-border bg-muted/10", headerClassName),
|
|
18
|
+
children: [
|
|
19
|
+
showTitleRow && /* @__PURE__ */ jsxs("div", {
|
|
20
|
+
className: "flex items-start justify-between gap-3 px-3 py-2",
|
|
21
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
22
|
+
className: "min-w-0 flex-1",
|
|
23
|
+
children: !hideTitleBlock && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24
|
+
eyebrow && /* @__PURE__ */ jsx("div", {
|
|
25
|
+
className: "mb-1 inline-flex max-w-full items-center px-1 py-0.5 text-[10px] font-bold uppercase tracking-wider text-muted-foreground",
|
|
26
|
+
children: eyebrow
|
|
27
|
+
}),
|
|
28
|
+
/* @__PURE__ */ jsx("div", {
|
|
29
|
+
className: "min-w-0 text-[13px] font-medium text-foreground",
|
|
30
|
+
children: title
|
|
31
|
+
}),
|
|
32
|
+
(subtitle || meta) && /* @__PURE__ */ jsxs("div", {
|
|
33
|
+
className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-relaxed text-muted-foreground",
|
|
34
|
+
children: [subtitle && /* @__PURE__ */ jsx("span", {
|
|
35
|
+
className: "truncate",
|
|
36
|
+
children: subtitle
|
|
37
|
+
}), meta && /* @__PURE__ */ jsx("span", {
|
|
38
|
+
className: "flex items-center gap-2",
|
|
39
|
+
children: meta
|
|
40
|
+
})]
|
|
41
|
+
})
|
|
42
|
+
] })
|
|
43
|
+
}), headerActions && /* @__PURE__ */ jsx("div", {
|
|
44
|
+
className: "flex shrink-0 items-center gap-1.5",
|
|
45
|
+
children: headerActions
|
|
46
|
+
})]
|
|
47
|
+
}),
|
|
48
|
+
tabs,
|
|
49
|
+
toolbar && /* @__PURE__ */ jsx("div", {
|
|
50
|
+
className: cn("px-3 py-2", toolbarNeedsDivider && "border-t border-border"),
|
|
51
|
+
children: toolbar
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
}),
|
|
55
|
+
/* @__PURE__ */ jsx("div", {
|
|
56
|
+
className: cn("min-h-0 flex-1 overflow-auto", contentClassName),
|
|
57
|
+
children: hasContent ? children : emptyState ? /* @__PURE__ */ jsx("div", {
|
|
58
|
+
className: "flex h-full items-center justify-center p-6",
|
|
59
|
+
children: emptyState
|
|
60
|
+
}) : null
|
|
61
|
+
}),
|
|
62
|
+
footer && /* @__PURE__ */ jsx("footer", {
|
|
63
|
+
className: "shrink-0 border-t border-border bg-card px-3 py-2",
|
|
64
|
+
children: footer
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { ArtifactPane as t };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { i as focusRing } from "./focus-BcE_SHqz.js";
|
|
2
|
+
import { t as cn } from "./utils-C_uf36nf.js";
|
|
3
|
+
import { t as Button } from "./button-C87nEe2R.js";
|
|
4
|
+
import { _ as AvatarFallback, a as DropdownMenuItem, g as Avatar, h as DropdownMenuTrigger, o as DropdownMenuLabel, r as DropdownMenuContent, t as DropdownMenu, u as DropdownMenuSeparator, v as AvatarImage } from "./dropdown-menu-BpcLa5vF.js";
|
|
5
|
+
import "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Terminal } from "lucide-react";
|
|
8
|
+
//#region src/auth/auth.tsx
|
|
9
|
+
function GitHubIcon({ className }) {
|
|
10
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
11
|
+
className,
|
|
12
|
+
viewBox: "0 0 24 24",
|
|
13
|
+
fill: "currentColor",
|
|
14
|
+
"aria-hidden": "true",
|
|
15
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
16
|
+
fillRule: "evenodd",
|
|
17
|
+
clipRule: "evenodd",
|
|
18
|
+
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"
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function GitHubLoginButton({ authUrl = "/auth/github", variant = "default", className, children, ...props }) {
|
|
23
|
+
return /* @__PURE__ */ jsxs(Button, {
|
|
24
|
+
variant,
|
|
25
|
+
className: cn("gap-2", className),
|
|
26
|
+
onClick: () => {
|
|
27
|
+
window.location.href = authUrl;
|
|
28
|
+
},
|
|
29
|
+
...props,
|
|
30
|
+
children: [/* @__PURE__ */ jsx(GitHubIcon, { className: "h-5 w-5" }), children ?? "Sign in with GitHub"]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function UserMenu({ user, logoutUrl = "/auth/logout", links = [], variant = "sandbox", onLogout }) {
|
|
34
|
+
const initials = user.name ? user.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : user.email.slice(0, 2).toUpperCase();
|
|
35
|
+
const avatarGradient = { sandbox: "bg-[image:var(--accent-gradient-strong)]" }[variant];
|
|
36
|
+
const handleLogout = () => {
|
|
37
|
+
if (onLogout) onLogout();
|
|
38
|
+
window.location.href = logoutUrl;
|
|
39
|
+
};
|
|
40
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
41
|
+
asChild: true,
|
|
42
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
43
|
+
type: "button",
|
|
44
|
+
className: cn("flex items-center gap-2 rounded-lg p-1.5 transition-colors hover:bg-accent", focusRing),
|
|
45
|
+
children: [/* @__PURE__ */ jsxs(Avatar, {
|
|
46
|
+
className: "h-8 w-8",
|
|
47
|
+
children: [/* @__PURE__ */ jsx(AvatarImage, {
|
|
48
|
+
src: void 0,
|
|
49
|
+
alt: user.name ?? user.email
|
|
50
|
+
}), /* @__PURE__ */ jsx(AvatarFallback, {
|
|
51
|
+
className: cn("text-white text-xs", avatarGradient),
|
|
52
|
+
children: initials
|
|
53
|
+
})]
|
|
54
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
55
|
+
className: "hidden text-left md:block",
|
|
56
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
57
|
+
className: "font-medium text-sm",
|
|
58
|
+
children: user.name ?? user.email
|
|
59
|
+
}), user.tier && /* @__PURE__ */ jsxs("p", {
|
|
60
|
+
className: "text-muted-foreground text-xs capitalize",
|
|
61
|
+
children: [user.tier, " Plan"]
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
})
|
|
65
|
+
}), /* @__PURE__ */ jsxs(DropdownMenuContent, {
|
|
66
|
+
align: "end",
|
|
67
|
+
className: "w-56",
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, {
|
|
70
|
+
className: "font-normal",
|
|
71
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
72
|
+
className: "flex flex-col space-y-1",
|
|
73
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
74
|
+
className: "font-medium text-sm",
|
|
75
|
+
children: user.name ?? "Account"
|
|
76
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
77
|
+
className: "text-muted-foreground text-xs",
|
|
78
|
+
children: user.email
|
|
79
|
+
})]
|
|
80
|
+
})
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
83
|
+
links.map((link) => /* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
84
|
+
asChild: true,
|
|
85
|
+
children: /* @__PURE__ */ jsxs("a", {
|
|
86
|
+
href: link.href,
|
|
87
|
+
className: "flex items-center gap-2",
|
|
88
|
+
children: [link.icon, link.label]
|
|
89
|
+
})
|
|
90
|
+
}, link.href)),
|
|
91
|
+
links.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
92
|
+
/* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
93
|
+
onClick: handleLogout,
|
|
94
|
+
className: "text-[var(--surface-danger-text)] focus:text-[var(--surface-danger-text)]",
|
|
95
|
+
children: "Sign out"
|
|
96
|
+
})
|
|
97
|
+
]
|
|
98
|
+
})] });
|
|
99
|
+
}
|
|
100
|
+
function AuthHeader({ user, loading = false, variant = "sandbox", apiBaseUrl = "", menuLinks, className }) {
|
|
101
|
+
if (loading) return /* @__PURE__ */ jsxs("div", {
|
|
102
|
+
className: cn("flex items-center gap-2", className),
|
|
103
|
+
children: [/* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-pulse rounded-full bg-muted" }), /* @__PURE__ */ jsx("div", {
|
|
104
|
+
className: "hidden md:block",
|
|
105
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-4 w-20 animate-pulse rounded bg-muted" })
|
|
106
|
+
})]
|
|
107
|
+
});
|
|
108
|
+
if (!user) return /* @__PURE__ */ jsx("div", {
|
|
109
|
+
className: cn("flex items-center gap-2", className),
|
|
110
|
+
children: /* @__PURE__ */ jsx(GitHubLoginButton, {
|
|
111
|
+
authUrl: `${apiBaseUrl}/auth/github`,
|
|
112
|
+
variant,
|
|
113
|
+
size: "sm"
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
return /* @__PURE__ */ jsx(UserMenu, {
|
|
117
|
+
user,
|
|
118
|
+
variant,
|
|
119
|
+
logoutUrl: `${apiBaseUrl}/auth/logout`,
|
|
120
|
+
links: menuLinks
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/auth/login-layout.tsx
|
|
125
|
+
function LoginLayout({ title = "Welcome Back", subtitle = "Sign in to your workspace.", brandIcon, children, className }) {
|
|
126
|
+
return /* @__PURE__ */ jsx("div", {
|
|
127
|
+
className: cn("relative flex min-h-screen items-center justify-center bg-background overflow-hidden antialiased font-sans flex-col", className),
|
|
128
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
129
|
+
className: "z-10 w-full max-w-md px-6 animate-in flex flex-col items-center",
|
|
130
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
131
|
+
className: "mb-10 text-center flex flex-col items-center",
|
|
132
|
+
children: [
|
|
133
|
+
/* @__PURE__ */ jsx("div", {
|
|
134
|
+
className: "inline-flex h-14 w-14 mb-4 items-center justify-center rounded-lg bg-muted border border-border",
|
|
135
|
+
children: brandIcon || /* @__PURE__ */ jsx(Terminal, { className: "h-7 w-7 text-foreground" })
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ jsx("h1", {
|
|
138
|
+
className: "text-2xl font-bold tracking-tight text-foreground font-display",
|
|
139
|
+
children: title
|
|
140
|
+
}),
|
|
141
|
+
/* @__PURE__ */ jsx("p", {
|
|
142
|
+
className: "mt-2 text-sm text-muted-foreground",
|
|
143
|
+
children: subtitle
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
147
|
+
className: "w-full bg-card p-8 border border-border rounded-lg",
|
|
148
|
+
children
|
|
149
|
+
})]
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { UserMenu as i, AuthHeader as n, GitHubLoginButton as r, LoginLayout as t };
|