@tangle-network/sandbox-ui 0.2.2 → 0.3.3

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 (67) hide show
  1. package/README.md +201 -10
  2. package/dist/auth.js +2 -2
  3. package/dist/chat-container-C8eHLw8z.d.ts +67 -0
  4. package/dist/chat.d.ts +70 -78
  5. package/dist/chat.js +8 -8
  6. package/dist/chunk-4F2GJRGU.js +756 -0
  7. package/dist/{chunk-HYEAX3DC.js → chunk-5LV6DZZF.js} +445 -114
  8. package/dist/chunk-67C53XVV.js +1106 -0
  9. package/dist/{chunk-QSQBDR3N.js → chunk-BX6AQMUS.js} +5 -2
  10. package/dist/chunk-CCKNIAS7.js +124 -0
  11. package/dist/chunk-CJ2RYVZH.js +128 -0
  12. package/dist/{chunk-KMXV7DDX.js → chunk-CNWVHQFY.js} +1 -1
  13. package/dist/{chunk-OU4TRNQZ.js → chunk-COCSO7FG.js} +3 -3
  14. package/dist/chunk-FJSVPBKY.js +85 -0
  15. package/dist/chunk-FRGMMANX.js +102 -0
  16. package/dist/{chunk-E6FS7R4X.js → chunk-HWLX5NME.js} +1 -1
  17. package/dist/chunk-JF6E2DS5.js +610 -0
  18. package/dist/chunk-MUOL44AE.js +121 -0
  19. package/dist/chunk-MXCSSOGH.js +105 -0
  20. package/dist/{chunk-J4OADEUK.js → chunk-OM6ON27W.js} +24 -9
  21. package/dist/{chunk-NI2EI43H.js → chunk-PDV7W4NY.js} +9 -124
  22. package/dist/chunk-TQN3VR4F.js +92 -0
  23. package/dist/{chunk-SOT2V7TX.js → chunk-TXI4MZAZ.js} +62 -144
  24. package/dist/chunk-WUR652Y3.js +1140 -0
  25. package/dist/chunk-YDBXQQLC.js +336 -0
  26. package/dist/{chunk-4EIWPJMJ.js → chunk-ZP6GSX4D.js} +36 -27
  27. package/dist/dashboard.d.ts +5 -2
  28. package/dist/dashboard.js +5 -4
  29. package/dist/{expanded-tool-detail-OkXGqTHe.d.ts → expanded-tool-detail-BDi_h_dZ.d.ts} +11 -4
  30. package/dist/file-tabs-CmaoDVBI.d.ts +72 -0
  31. package/dist/files.d.ts +25 -44
  32. package/dist/files.js +8 -3
  33. package/{src/styles → dist}/globals.css +16 -67
  34. package/dist/hooks.d.ts +5 -4
  35. package/dist/hooks.js +14 -9
  36. package/dist/index.d.ts +38 -9
  37. package/dist/index.js +100 -126
  38. package/dist/markdown.d.ts +1 -24
  39. package/dist/markdown.js +1 -7
  40. package/dist/openui.d.ts +115 -0
  41. package/dist/openui.js +11 -0
  42. package/dist/pages.d.ts +3 -2
  43. package/dist/pages.js +19 -16
  44. package/dist/primitives.js +25 -19
  45. package/dist/run.d.ts +2 -2
  46. package/dist/run.js +8 -7
  47. package/dist/{use-sidecar-auth-Bb0-w3lX.d.ts → sdk-hooks.d.ts} +61 -72
  48. package/dist/sdk-hooks.js +29 -0
  49. package/dist/styles.css +179 -0
  50. package/dist/tokens.css +165 -0
  51. package/dist/{tool-display-BvsVW_Ur.d.ts → tool-display-Ct9nFAzJ.d.ts} +1 -1
  52. package/dist/types.d.ts +1 -1
  53. package/dist/{usage-chart-DINgSVL5.d.ts → usage-chart-CY9xo3KX.d.ts} +8 -3
  54. package/dist/use-pty-session-DeZSxOCN.d.ts +69 -0
  55. package/dist/utils.d.ts +1 -1
  56. package/dist/utils.js +1 -1
  57. package/dist/workspace.d.ts +171 -33
  58. package/dist/workspace.js +25 -1
  59. package/package.json +10 -3
  60. package/dist/chunk-2UHPE5T7.js +0 -201
  61. package/dist/chunk-6MQIDUPA.js +0 -502
  62. package/dist/chunk-KYY2X6LY.js +0 -318
  63. package/dist/chunk-L6ZDH5F4.js +0 -334
  64. package/dist/chunk-M34OA6PQ.js +0 -233
  65. package/dist/chunk-M6VLC32S.js +0 -219
  66. package/dist/chunk-U62G5TS7.js +0 -472
  67. package/src/styles/tokens.css +0 -73
@@ -1,472 +0,0 @@
1
- import {
2
- useAutoScroll,
3
- useRunCollapseState,
4
- useRunGroups
5
- } from "./chunk-KMXV7DDX.js";
6
- import {
7
- RunGroup
8
- } from "./chunk-6MQIDUPA.js";
9
- import {
10
- Markdown
11
- } from "./chunk-LTFK464G.js";
12
- import {
13
- SimpleMarkdown
14
- } from "./chunk-M34OA6PQ.js";
15
- import {
16
- cn
17
- } from "./chunk-RQHJBTEU.js";
18
-
19
- // src/chat/chat-message.tsx
20
- import { User, Bot } from "lucide-react";
21
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
- function ChatMessage({
23
- role,
24
- content,
25
- toolCalls,
26
- isStreaming,
27
- timestamp,
28
- className
29
- }) {
30
- const isUser = role === "user";
31
- return /* @__PURE__ */ jsxs("div", { className: cn("flex gap-3 px-4 py-3", className), children: [
32
- /* @__PURE__ */ jsx(
33
- "div",
34
- {
35
- className: cn(
36
- "w-7 h-7 rounded-lg shrink-0 flex items-center justify-center mt-0.5",
37
- isUser ? "bg-[var(--brand-cool)]/15 text-[var(--brand-cool)]" : "bg-[var(--brand-glow)]/15 text-[var(--brand-glow)]"
38
- ),
39
- children: isUser ? /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Bot, { className: "h-4 w-4" })
40
- }
41
- ),
42
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-1", children: [
43
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
44
- /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-[var(--text-secondary)]", children: isUser ? "You" : "Agent" }),
45
- timestamp && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--text-muted)]", children: formatTime(timestamp) })
46
- ] }),
47
- isUser ? /* @__PURE__ */ jsx("div", { className: "text-[var(--text-primary)] text-sm whitespace-pre-wrap leading-relaxed", children: content }) : /* @__PURE__ */ jsxs(Fragment, { children: [
48
- content && /* @__PURE__ */ jsx(SimpleMarkdown, { content }),
49
- isStreaming && /* @__PURE__ */ jsx("span", { className: "inline-block w-2 h-4 bg-[var(--brand-cool)] animate-pulse rounded-sm ml-0.5 align-text-bottom" })
50
- ] }),
51
- toolCalls
52
- ] })
53
- ] });
54
- }
55
- function formatTime(date) {
56
- return date.toLocaleTimeString(void 0, {
57
- hour: "numeric",
58
- minute: "2-digit"
59
- });
60
- }
61
-
62
- // src/chat/chat-message-list.tsx
63
- import { useRef, useEffect, useState } from "react";
64
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
65
- function ChatMessageList({
66
- messages,
67
- renderAfter,
68
- emptyState,
69
- isThinking,
70
- className
71
- }) {
72
- const containerRef = useRef(null);
73
- const endRef = useRef(null);
74
- const [isNearBottom, setIsNearBottom] = useState(true);
75
- const handleScroll = () => {
76
- const el = containerRef.current;
77
- if (!el) return;
78
- const threshold = 100;
79
- const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
80
- setIsNearBottom(nearBottom);
81
- };
82
- useEffect(() => {
83
- if (isNearBottom) {
84
- endRef.current?.scrollIntoView({ behavior: "smooth" });
85
- }
86
- }, [messages, isThinking, isNearBottom]);
87
- if (messages.length === 0 && emptyState) {
88
- return /* @__PURE__ */ jsx2("div", { className: cn("flex-1 flex items-center justify-center p-8", className), children: emptyState });
89
- }
90
- return /* @__PURE__ */ jsx2(
91
- "div",
92
- {
93
- ref: containerRef,
94
- onScroll: handleScroll,
95
- className: cn("flex-1 overflow-y-auto", className),
96
- children: /* @__PURE__ */ jsxs2("div", { className: "max-w-3xl mx-auto py-4", children: [
97
- messages.map((msg, i) => /* @__PURE__ */ jsxs2("div", { children: [
98
- /* @__PURE__ */ jsx2(
99
- ChatMessage,
100
- {
101
- role: msg.role,
102
- content: msg.content,
103
- toolCalls: msg.toolCalls,
104
- isStreaming: msg.isStreaming,
105
- timestamp: msg.timestamp
106
- }
107
- ),
108
- renderAfter?.(msg, i)
109
- ] }, msg.id)),
110
- isThinking && /* @__PURE__ */ jsx2(ThinkingIndicator, {}),
111
- /* @__PURE__ */ jsx2("div", { ref: endRef })
112
- ] })
113
- }
114
- );
115
- }
116
- function ThinkingIndicator({ className }) {
117
- const [elapsed, setElapsed] = useState(0);
118
- useEffect(() => {
119
- const interval = setInterval(() => setElapsed((e) => e + 1), 1e3);
120
- return () => clearInterval(interval);
121
- }, []);
122
- return /* @__PURE__ */ jsxs2("div", { className: cn("flex gap-3 px-4 py-3", className), children: [
123
- /* @__PURE__ */ jsx2("div", { className: "w-7 h-7 rounded-lg shrink-0 flex items-center justify-center mt-0.5 bg-[var(--brand-glow)]/15 text-[var(--brand-glow)]", children: /* @__PURE__ */ jsxs2("div", { className: "flex gap-0.5", children: [
124
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce", style: { animationDelay: "0ms" } }),
125
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce", style: { animationDelay: "150ms" } }),
126
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-current animate-bounce", style: { animationDelay: "300ms" } })
127
- ] }) }),
128
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
129
- /* @__PURE__ */ jsx2("span", { className: "text-sm text-[var(--text-muted)]", children: elapsed < 10 ? "Thinking..." : elapsed < 60 ? "Thinking deeply..." : "Still working..." }),
130
- elapsed > 5 && /* @__PURE__ */ jsxs2("span", { className: "text-xs text-[var(--text-muted)] tabular-nums", children: [
131
- elapsed,
132
- "s"
133
- ] })
134
- ] })
135
- ] });
136
- }
137
-
138
- // src/chat/chat-input.tsx
139
- import { useState as useState2, useRef as useRef2, useCallback } from "react";
140
- import { Send, Square, Paperclip, X } from "lucide-react";
141
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
142
- function ChatInput({
143
- onSend,
144
- onCancel,
145
- isStreaming,
146
- disabled,
147
- placeholder = "Ask about your taxes, build a model, or give instructions...",
148
- modelLabel,
149
- onModelClick,
150
- pendingFiles = [],
151
- onRemoveFile,
152
- onAttach,
153
- className
154
- }) {
155
- const [value, setValue] = useState2("");
156
- const textareaRef = useRef2(null);
157
- const fileInputRef = useRef2(null);
158
- const handleSend = useCallback(() => {
159
- const trimmed = value.trim();
160
- if (!trimmed || isStreaming || disabled) return;
161
- onSend(trimmed);
162
- setValue("");
163
- if (textareaRef.current) {
164
- textareaRef.current.style.height = "auto";
165
- }
166
- }, [value, isStreaming, disabled, onSend]);
167
- const handleKeyDown = (e) => {
168
- if (e.key === "Enter" && !e.shiftKey) {
169
- e.preventDefault();
170
- handleSend();
171
- }
172
- };
173
- const handleChange = (e) => {
174
- setValue(e.target.value);
175
- const el = e.target;
176
- el.style.height = "auto";
177
- el.style.height = `${Math.min(el.scrollHeight, 160)}px`;
178
- };
179
- const handleAttachClick = () => {
180
- fileInputRef.current?.click();
181
- };
182
- const handleFileChange = (e) => {
183
- if (e.target.files?.length) {
184
- onAttach?.(e.target.files);
185
- e.target.value = "";
186
- }
187
- };
188
- return /* @__PURE__ */ jsxs3("div", { className: cn("px-4 py-3", className), children: [
189
- pendingFiles.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-1.5 mb-2", children: pendingFiles.map((f) => /* @__PURE__ */ jsxs3(
190
- "span",
191
- {
192
- className: cn(
193
- "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-[var(--radius-full)] text-xs",
194
- "bg-[var(--bg-input)] border border-[var(--border-subtle)]",
195
- f.status === "error" && "border-[var(--code-error)]/30 text-[var(--code-error)]",
196
- f.status !== "error" && "text-[var(--text-secondary)]"
197
- ),
198
- children: [
199
- /* @__PURE__ */ jsx3("span", { className: "truncate max-w-[150px]", children: f.name }),
200
- f.status === "uploading" && /* @__PURE__ */ jsx3("span", { className: "w-3 h-3 border-2 border-[var(--brand-cool)] border-t-transparent rounded-full animate-spin" }),
201
- onRemoveFile && /* @__PURE__ */ jsx3(
202
- "button",
203
- {
204
- onClick: () => onRemoveFile(f.id),
205
- className: "hover:text-[var(--text-primary)] transition-colors",
206
- children: /* @__PURE__ */ jsx3(X, { className: "h-3 w-3" })
207
- }
208
- )
209
- ]
210
- },
211
- f.id
212
- )) }),
213
- /* @__PURE__ */ jsxs3("div", { className: "flex items-end gap-2 bg-[var(--bg-card)] border border-[var(--border-default)] rounded-[var(--radius-lg)] px-3 py-2 focus-within:border-[var(--border-accent)] transition-colors", children: [
214
- onAttach && /* @__PURE__ */ jsxs3(Fragment2, { children: [
215
- /* @__PURE__ */ jsx3(
216
- "button",
217
- {
218
- onClick: handleAttachClick,
219
- disabled: isStreaming,
220
- className: "p-1.5 rounded-[var(--radius-sm)] hover:bg-[var(--bg-hover)] text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors disabled:opacity-50 shrink-0 mb-0.5",
221
- children: /* @__PURE__ */ jsx3(Paperclip, { className: "h-4 w-4" })
222
- }
223
- ),
224
- /* @__PURE__ */ jsx3(
225
- "input",
226
- {
227
- ref: fileInputRef,
228
- type: "file",
229
- multiple: true,
230
- className: "hidden",
231
- onChange: handleFileChange,
232
- accept: ".pdf,.csv,.xlsx,.xls,.jpg,.jpeg,.png,.gif,.txt,.json,.yaml,.yml"
233
- }
234
- )
235
- ] }),
236
- /* @__PURE__ */ jsx3(
237
- "textarea",
238
- {
239
- ref: textareaRef,
240
- value,
241
- onChange: handleChange,
242
- onKeyDown: handleKeyDown,
243
- placeholder,
244
- disabled: isStreaming || disabled,
245
- rows: 1,
246
- className: "flex-1 bg-transparent text-[var(--text-primary)] text-sm placeholder:text-[var(--text-muted)] resize-none outline-none min-h-[24px] max-h-[160px] leading-relaxed disabled:opacity-50"
247
- }
248
- ),
249
- isStreaming ? /* @__PURE__ */ jsx3(
250
- "button",
251
- {
252
- onClick: onCancel,
253
- className: "p-1.5 rounded-[var(--radius-sm)] bg-[var(--code-error)]/15 hover:bg-[var(--code-error)]/25 text-[var(--code-error)] transition-colors shrink-0 mb-0.5",
254
- children: /* @__PURE__ */ jsx3(Square, { className: "h-4 w-4" })
255
- }
256
- ) : /* @__PURE__ */ jsx3(
257
- "button",
258
- {
259
- onClick: handleSend,
260
- disabled: !value.trim() || disabled,
261
- className: "p-1.5 rounded-[var(--radius-sm)] bg-[var(--brand-cool)]/15 hover:bg-[var(--brand-cool)]/25 text-[var(--brand-cool)] transition-colors disabled:opacity-30 shrink-0 mb-0.5",
262
- children: /* @__PURE__ */ jsx3(Send, { className: "h-4 w-4" })
263
- }
264
- )
265
- ] }),
266
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mt-1.5 px-1", children: [
267
- /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-2", children: modelLabel && /* @__PURE__ */ jsxs3(
268
- "button",
269
- {
270
- onClick: onModelClick,
271
- className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-[var(--radius-full)] border border-[var(--border-subtle)] text-xs text-[var(--text-muted)] hover:border-[var(--border-accent)] hover:text-[var(--text-secondary)] transition-colors",
272
- children: [
273
- /* @__PURE__ */ jsx3("span", { className: "w-1.5 h-1.5 rounded-full bg-[var(--code-success)]" }),
274
- modelLabel
275
- ]
276
- }
277
- ) }),
278
- /* @__PURE__ */ jsxs3("span", { className: "text-xs text-[var(--text-muted)]", children: [
279
- /* @__PURE__ */ jsx3("kbd", { className: "px-1 py-0.5 bg-[var(--bg-input)] rounded border border-[var(--border-subtle)] text-[10px]", children: "Cmd" }),
280
- /* @__PURE__ */ jsx3("kbd", { className: "px-1 py-0.5 bg-[var(--bg-input)] rounded border border-[var(--border-subtle)] text-[10px] ml-0.5", children: "L" }),
281
- /* @__PURE__ */ jsx3("span", { className: "ml-1", children: "to focus" })
282
- ] })
283
- ] })
284
- ] });
285
- }
286
-
287
- // src/chat/user-message.tsx
288
- import { memo } from "react";
289
- import { jsx as jsx4 } from "react/jsx-runtime";
290
- var UserMessage = memo(({ message, parts }) => {
291
- const textContent = parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
292
- if (!textContent.trim()) return null;
293
- return /* @__PURE__ */ jsx4("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx4("div", { className: "max-w-[85%] rounded-2xl rounded-br-md px-4 py-2.5 bg-blue-600/10 dark:bg-blue-600/20 border border-blue-500/15 dark:border-blue-500/20", children: /* @__PURE__ */ jsx4("div", { className: "text-sm text-neutral-900 dark:text-neutral-100", children: /* @__PURE__ */ jsx4(Markdown, { children: textContent }) }) }) });
294
- });
295
- UserMessage.displayName = "UserMessage";
296
-
297
- // src/chat/message-list.tsx
298
- import { memo as memo2 } from "react";
299
- import { jsx as jsx5 } from "react/jsx-runtime";
300
- var MessageList = memo2(
301
- ({
302
- groups,
303
- partMap,
304
- isCollapsed,
305
- onToggleCollapse,
306
- branding,
307
- renderToolDetail
308
- }) => {
309
- return /* @__PURE__ */ jsx5("div", { className: "space-y-3", children: groups.map((group) => {
310
- if (group.type === "user") {
311
- return /* @__PURE__ */ jsx5(
312
- UserMessage,
313
- {
314
- message: group.message,
315
- parts: partMap[group.message.id] ?? []
316
- },
317
- group.message.id
318
- );
319
- }
320
- return /* @__PURE__ */ jsx5(
321
- RunGroup,
322
- {
323
- run: group.run,
324
- partMap,
325
- collapsed: isCollapsed(group.run.id),
326
- onToggle: () => onToggleCollapse(group.run.id),
327
- branding,
328
- renderToolDetail
329
- },
330
- group.run.id
331
- );
332
- }) });
333
- }
334
- );
335
- MessageList.displayName = "MessageList";
336
-
337
- // src/chat/chat-container.tsx
338
- import {
339
- memo as memo3,
340
- useCallback as useCallback2,
341
- useRef as useRef3,
342
- useState as useState3
343
- } from "react";
344
- import { ArrowDown, SendHorizonal } from "lucide-react";
345
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
346
- var ChatContainer = memo3(
347
- ({
348
- messages,
349
- partMap,
350
- isStreaming,
351
- onSend,
352
- branding,
353
- placeholder = "Type a message...",
354
- className,
355
- hideInput = false,
356
- renderToolDetail
357
- }) => {
358
- const [inputValue, setInputValue] = useState3("");
359
- const scrollRef = useRef3(null);
360
- const inputRef = useRef3(null);
361
- const groups = useRunGroups({ messages, partMap, isStreaming });
362
- const runs = groups.filter((g) => g.type === "run").map((g) => g.run);
363
- const { isCollapsed, toggleCollapse } = useRunCollapseState(runs);
364
- const { isAtBottom, scrollToBottom } = useAutoScroll(scrollRef, [
365
- messages,
366
- partMap,
367
- isStreaming
368
- ]);
369
- const handleSubmit = useCallback2(
370
- (e) => {
371
- e?.preventDefault();
372
- const text = inputValue.trim();
373
- if (!text || !onSend) return;
374
- onSend(text);
375
- setInputValue("");
376
- inputRef.current?.focus();
377
- },
378
- [inputValue, onSend]
379
- );
380
- const handleKeyDown = useCallback2(
381
- (e) => {
382
- if (e.key === "Enter" && !e.shiftKey) {
383
- e.preventDefault();
384
- handleSubmit();
385
- }
386
- },
387
- [handleSubmit]
388
- );
389
- return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col h-full", className), children: [
390
- /* @__PURE__ */ jsx6("div", { ref: scrollRef, className: "flex-1 overflow-y-auto px-4 py-4", children: messages.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center h-full text-sm text-neutral-400 dark:text-neutral-500", children: "No messages yet" }) : /* @__PURE__ */ jsx6(
391
- MessageList,
392
- {
393
- groups,
394
- partMap,
395
- isCollapsed,
396
- onToggleCollapse: toggleCollapse,
397
- branding,
398
- renderToolDetail
399
- }
400
- ) }),
401
- !isAtBottom && /* @__PURE__ */ jsx6("div", { className: "flex justify-center -mt-10 relative z-10", children: /* @__PURE__ */ jsxs4(
402
- "button",
403
- {
404
- onClick: scrollToBottom,
405
- className: cn(
406
- "flex items-center gap-1.5 px-3 py-1.5 rounded-full",
407
- "bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 shadow-lg",
408
- "text-xs text-neutral-600 dark:text-neutral-300 hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors"
409
- ),
410
- children: [
411
- /* @__PURE__ */ jsx6(ArrowDown, { className: "w-3 h-3" }),
412
- "Scroll to bottom"
413
- ]
414
- }
415
- ) }),
416
- !hideInput && onSend && /* @__PURE__ */ jsx6(
417
- "form",
418
- {
419
- onSubmit: handleSubmit,
420
- className: "shrink-0 border-t border-neutral-200/50 dark:border-neutral-700/50 p-3",
421
- children: /* @__PURE__ */ jsxs4("div", { className: "flex items-end gap-2", children: [
422
- /* @__PURE__ */ jsx6(
423
- "textarea",
424
- {
425
- ref: inputRef,
426
- value: inputValue,
427
- onChange: (e) => setInputValue(e.target.value),
428
- onKeyDown: handleKeyDown,
429
- placeholder,
430
- rows: 1,
431
- disabled: isStreaming,
432
- className: cn(
433
- "flex-1 resize-none rounded-lg px-3 py-2",
434
- "bg-neutral-50/60 dark:bg-neutral-800/60 border border-neutral-200/50 dark:border-neutral-700/50",
435
- "text-sm text-neutral-900 dark:text-neutral-100 placeholder:text-neutral-400 dark:placeholder:text-neutral-500",
436
- "focus:outline-none focus:border-blue-500/50",
437
- "disabled:opacity-50 disabled:cursor-not-allowed",
438
- "max-h-32"
439
- ),
440
- style: { minHeight: "2.5rem" }
441
- }
442
- ),
443
- /* @__PURE__ */ jsx6(
444
- "button",
445
- {
446
- type: "submit",
447
- disabled: isStreaming || !inputValue.trim(),
448
- className: cn(
449
- "flex items-center justify-center w-9 h-9 rounded-lg",
450
- "bg-blue-600 hover:bg-blue-500 transition-colors",
451
- "disabled:opacity-30 disabled:cursor-not-allowed"
452
- ),
453
- children: /* @__PURE__ */ jsx6(SendHorizonal, { className: "w-4 h-4 text-white" })
454
- }
455
- )
456
- ] })
457
- }
458
- )
459
- ] });
460
- }
461
- );
462
- ChatContainer.displayName = "ChatContainer";
463
-
464
- export {
465
- ChatMessage,
466
- ChatMessageList,
467
- ThinkingIndicator,
468
- ChatInput,
469
- UserMessage,
470
- MessageList,
471
- ChatContainer
472
- };
@@ -1,73 +0,0 @@
1
- /* Tangle Design System Tokens */
2
-
3
- :root {
4
- /* Brand gradient */
5
- --tangle-gradient: linear-gradient(135deg, #8E59FF, #6888F9);
6
- --tangle-gradient-text: linear-gradient(45deg, #5f5bee, #465cd2);
7
-
8
- /* Backgrounds */
9
- --bg-root: #000000;
10
- --bg-dark: #1f1d2b;
11
- --bg-card: #161425;
12
- --bg-elevated: #1e1c30;
13
- --bg-section: #171528;
14
- --bg-input: #141428;
15
- --bg-hover: #1a1a30;
16
-
17
- /* Text */
18
- --text-primary: #ffffff;
19
- --text-secondary: #aab0bc;
20
- --text-muted: #6b7094;
21
-
22
- /* Brand */
23
- --brand-primary: #605dba;
24
- --brand-strong: #6941c6;
25
- --brand-cool: #6172f3;
26
- --brand-glow: #9e77ed;
27
- --brand-purple: #7f56d9;
28
- --brand-vibrant: #4a3aff;
29
-
30
- /* Borders */
31
- --border-subtle: rgba(255, 255, 255, 0.06);
32
- --border-default: rgba(255, 255, 255, 0.08);
33
- --border-hover: rgba(255, 255, 255, 0.1);
34
- --border-accent: rgba(142, 89, 255, 0.2);
35
- --border-accent-hover: rgba(142, 89, 255, 0.4);
36
-
37
- /* Buttons */
38
- --btn-primary-bg: #1e116e;
39
- --btn-primary-hover: #281ca5;
40
- --btn-cta-bg: #ffffff;
41
- --btn-cta-text: #1d1d1d;
42
-
43
- /* Code syntax */
44
- --code-keyword: #c084fc;
45
- --code-string: #a78bfa;
46
- --code-function: #60a5fa;
47
- --code-number: #fcd34d;
48
- --code-success: #4ade80;
49
- --code-comment: rgba(255, 255, 255, 0.25);
50
- --code-error: #f87171;
51
-
52
- /* Shadows */
53
- --shadow-card: 0 4px 24px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(142, 89, 255, 0.1);
54
- --shadow-dropdown: 0 20px 60px rgba(0, 0, 0, 0.5);
55
- --shadow-glow: 0 0 40px rgba(130, 99, 255, 0.15);
56
-
57
- /* Radii */
58
- --radius-sm: 8px;
59
- --radius-md: 12px;
60
- --radius-lg: 1.25rem;
61
- --radius-xl: 1.5rem;
62
- --radius-pill: 48px;
63
- --radius-full: 62.5rem;
64
-
65
- /* Transitions */
66
- --transition-fast: 0.15s ease;
67
- --transition-default: 0.2s ease;
68
- --transition-medium: 0.3s ease;
69
-
70
- /* Fonts */
71
- --font-sans: 'Satoshi', ui-sans-serif, system-ui, sans-serif;
72
- --font-mono: 'JetBrains Mono', ui-monospace, monospace;
73
- }