@tangle-network/ui 11.9.0 → 11.11.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 (155) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +14 -0
  3. package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
  4. package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
  5. package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
  6. package/dist/artifact-pane-DMXT9a8U.js +70 -0
  7. package/dist/auth-DixfCMCk.js +154 -0
  8. package/dist/auth.d.ts +2 -74
  9. package/dist/auth.js +2 -15
  10. package/dist/branding-26d5ARIr.d.ts +14 -0
  11. package/dist/button-uhNnwdsD.js +78 -0
  12. package/dist/button-yoIv77e2.d.ts +16 -0
  13. package/dist/chat-CPLL0Fd9.js +667 -0
  14. package/dist/chat.d.ts +2 -201
  15. package/dist/chat.js +2 -30
  16. package/dist/code-block-B9miUPht.d.ts +23 -0
  17. package/dist/code-block-CngSn37j.js +165 -0
  18. package/dist/diff-preview-cySuqowW.js +533 -0
  19. package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
  20. package/dist/document-editor-pane-Cz6oEF1o.js +1287 -0
  21. package/dist/dropdown-menu-BpcLa5vF.js +101 -0
  22. package/dist/editor.d.ts +76 -78
  23. package/dist/editor.js +2 -33
  24. package/dist/file-format-BgXbr-Ib.js +160 -0
  25. package/dist/files-CYlOo0mE.js +743 -0
  26. package/dist/files.d.ts +2 -243
  27. package/dist/files.js +3 -40
  28. package/dist/focus-Cw02pNSr.js +56 -0
  29. package/dist/format-DfcLWqMa.js +54 -0
  30. package/dist/hooks.d.ts +30 -37
  31. package/dist/hooks.js +111 -45
  32. package/dist/index-2UntyjBb.d.ts +52 -0
  33. package/dist/index-COgqsFAQ.d.ts +42 -0
  34. package/dist/index-CPDET_s1.d.ts +549 -0
  35. package/dist/index-CUhfHT_V.d.ts +204 -0
  36. package/dist/index-Cg6gYAqh.d.ts +73 -0
  37. package/dist/index-Cq-EJzqW.d.ts +16 -0
  38. package/dist/index-DhYmSaLF.d.ts +245 -0
  39. package/dist/index-DjKxO357.d.ts +128 -0
  40. package/dist/index-b56ew9aF.d.ts +107 -0
  41. package/dist/index.d.ts +26 -43
  42. package/dist/index.js +35 -460
  43. package/dist/markdown-BprL96Gl.js +45 -0
  44. package/dist/markdown.d.ts +3 -18
  45. package/dist/markdown.js +3 -14
  46. package/dist/message-vhUI0c5G.d.ts +16 -0
  47. package/dist/nav.d.ts +6 -8
  48. package/dist/nav.js +29 -11
  49. package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
  50. package/dist/openui-artifact-renderer-DT4xbvWt.js +266 -0
  51. package/dist/openui.d.ts +2 -115
  52. package/dist/openui.js +2 -12
  53. package/dist/parts-5mhy9yJ3.d.ts +37 -0
  54. package/dist/primitives-DE-blUz-.js +1239 -0
  55. package/dist/primitives.d.ts +5 -523
  56. package/dist/primitives.js +9 -211
  57. package/dist/redaction-CGGB2ENG.js +74 -0
  58. package/dist/redaction.d.ts +2 -42
  59. package/dist/redaction.js +2 -7
  60. package/dist/run-OyWmIDqu.d.ts +41 -0
  61. package/dist/run-ZsIKPA6J.js +17 -0
  62. package/dist/run-group-D1InSdQu.js +410 -0
  63. package/dist/run.d.ts +3 -126
  64. package/dist/run.js +5 -39
  65. package/dist/sdk-hooks.d.ts +2 -285
  66. package/dist/sdk-hooks.js +3 -35
  67. package/dist/stores.d.ts +13 -14
  68. package/dist/stores.js +34 -76
  69. package/dist/table-DHyqDPbU.js +146 -0
  70. package/dist/tabs-ujuqAdtb.js +40 -0
  71. package/dist/text-shimmer-BUUo6I-g.js +64 -0
  72. package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
  73. package/dist/tool-call-feed-C1W1N54c.js +109 -0
  74. package/dist/tool-call-step-Bi3_YJRV.js +434 -0
  75. package/dist/tool-display-BAuAVa43.js +158 -0
  76. package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
  77. package/dist/tool-previews.d.ts +2 -48
  78. package/dist/tool-previews.js +2 -22
  79. package/dist/types.d.ts +6 -19
  80. package/dist/types.js +0 -1
  81. package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
  82. package/dist/use-sse-stream-BjVBDbxK.js +884 -0
  83. package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
  84. package/dist/utils-Bl_CZ0Qp.js +37 -0
  85. package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
  86. package/dist/utils.d.ts +2 -51
  87. package/dist/utils.js +6 -32
  88. package/package.json +39 -41
  89. package/src/auth/auth.tsx +5 -1
  90. package/src/chat/agent-timeline.tsx +6 -1
  91. package/src/chat/chat-container.tsx +2 -1
  92. package/src/editor/document-editor-pane.test.tsx +3 -1
  93. package/src/editor/document-editor-pane.tsx +5 -1
  94. package/src/editor/markdown-document-editor.test.tsx +9 -4
  95. package/src/files/file-artifact-pane.tsx +3 -2
  96. package/src/files/file-preview.tsx +3 -1
  97. package/src/files/file-tabs.tsx +9 -2
  98. package/src/lib/focus.ts +63 -0
  99. package/src/markdown/code-block.tsx +5 -1
  100. package/src/primitives/badge.tsx +2 -1
  101. package/src/primitives/button.tsx +2 -1
  102. package/src/primitives/card.tsx +1 -2
  103. package/src/primitives/dialog.tsx +7 -1
  104. package/src/primitives/input.tsx +15 -14
  105. package/src/primitives/segmented-control.tsx +5 -3
  106. package/src/primitives/select.tsx +3 -1
  107. package/src/primitives/switch.tsx +3 -1
  108. package/src/primitives/tabs.tsx +6 -4
  109. package/src/primitives/terminal-display.tsx +6 -8
  110. package/src/primitives/toast.tsx +5 -1
  111. package/src/tool-previews/command-preview.tsx +5 -1
  112. package/src/tool-previews/web-search-preview.tsx +2 -1
  113. package/src/utils/index.ts +7 -0
  114. package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
  115. package/dist/button-CMQuQEW_.d.ts +0 -17
  116. package/dist/chunk-34A66VBG.js +0 -214
  117. package/dist/chunk-3OI2QKFD.js +0 -0
  118. package/dist/chunk-3TI5DEHV.js +0 -299
  119. package/dist/chunk-4CLN43XT.js +0 -45
  120. package/dist/chunk-565EATZZ.js +0 -156
  121. package/dist/chunk-5Z5ZYMOJ.js +0 -0
  122. package/dist/chunk-6BGQA4BQ.js +0 -0
  123. package/dist/chunk-7YOCS6IF.js +0 -728
  124. package/dist/chunk-EOAX2ENE.js +0 -60
  125. package/dist/chunk-GYPQXTJU.js +0 -230
  126. package/dist/chunk-HFL6R6IF.js +0 -37
  127. package/dist/chunk-HGML45QH.js +0 -104
  128. package/dist/chunk-KNYSKNZX.js +0 -550
  129. package/dist/chunk-L57WRIND.js +0 -59
  130. package/dist/chunk-LDLOJKPC.js +0 -1585
  131. package/dist/chunk-LTEKI7YJ.js +0 -59
  132. package/dist/chunk-MKTSMWVD.js +0 -109
  133. package/dist/chunk-ND3ZFXQK.js +0 -179
  134. package/dist/chunk-NKDZ7GZE.js +0 -192
  135. package/dist/chunk-NWECTSOH.js +0 -589
  136. package/dist/chunk-OEX7NZE3.js +0 -321
  137. package/dist/chunk-Q56BYXQF.js +0 -61
  138. package/dist/chunk-REJESC5U.js +0 -117
  139. package/dist/chunk-RQGKSCEZ.js +0 -0
  140. package/dist/chunk-TN4FUEWY.js +0 -437
  141. package/dist/chunk-VPWY4I5O.js +0 -1048
  142. package/dist/chunk-WUQDUBJG.js +0 -168
  143. package/dist/chunk-XGKULLYE.js +0 -40
  144. package/dist/chunk-XU3HB5QL.js +0 -127
  145. package/dist/chunk-XYAIX4SU.js +0 -133
  146. package/dist/chunk-YJ6RE5WV.js +0 -875
  147. package/dist/chunk-YTO5V6QS.js +0 -19
  148. package/dist/chunk-ZKCEAIIZ.js +0 -1395
  149. package/dist/code-block-0kSpWMnf.d.ts +0 -25
  150. package/dist/document-editor-pane-EX25CEYW.js +0 -12
  151. package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
  152. package/dist/message-BHWbxBtT.d.ts +0 -15
  153. package/dist/parts-dj7AcUg0.d.ts +0 -36
  154. package/dist/run-PfLmDAox.d.ts +0 -41
  155. package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
@@ -0,0 +1,282 @@
1
+ import { t as SessionMessage } from "./message-vhUI0c5G.js";
2
+ import { n as SessionPart } from "./parts-5mhy9yJ3.js";
3
+ import { a as Run, n as GroupedMessage } from "./run-OyWmIDqu.js";
4
+ import { t as FeedSegment } from "./tool-call-feed-BeB1_4pX.js";
5
+ import { c as ActiveSessionTransportMode, i as ActiveSessionConnectionState, u as RegisterActiveSessionOptions } from "./active-sessions-store-nl70ZnMC.js";
6
+ import { RefObject } from "react";
7
+ //#region src/hooks/use-auto-scroll.d.ts
8
+ /**
9
+ * Scroll-to-bottom behaviour: sticks to the bottom while streaming,
10
+ * pauses when user scrolls up, resumes when user scrolls back down.
11
+ */
12
+ declare function useAutoScroll(containerRef: RefObject<HTMLElement | null>, deps?: unknown[]): {
13
+ isAtBottom: boolean;
14
+ scrollToBottom: () => void;
15
+ };
16
+ //#endregion
17
+ //#region src/hooks/use-dropdown-menu.d.ts
18
+ interface UseDropdownMenuOptions {
19
+ closeOnEsc?: boolean;
20
+ }
21
+ declare function useDropdownMenu(options?: UseDropdownMenuOptions): {
22
+ open: boolean;
23
+ setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
24
+ ref: import("react").RefObject<HTMLDivElement | null>;
25
+ toggle: () => void;
26
+ close: () => void;
27
+ };
28
+ //#endregion
29
+ //#region src/hooks/use-run-collapse-state.d.ts
30
+ /**
31
+ * Manages per-run collapse state with auto-collapse after run completion.
32
+ *
33
+ * - Runs stay expanded by default
34
+ * - Collapse is manual only
35
+ */
36
+ declare function useRunCollapseState(runs: Run[]): {
37
+ isCollapsed: (runId: string) => boolean;
38
+ toggleCollapse: (runId: string) => void;
39
+ };
40
+ //#endregion
41
+ //#region src/hooks/use-run-groups.d.ts
42
+ interface UseRunGroupsOptions {
43
+ messages: SessionMessage[];
44
+ partMap: Record<string, SessionPart[]>;
45
+ isStreaming: boolean;
46
+ }
47
+ declare function useRunGroups({ messages, partMap, isStreaming }: UseRunGroupsOptions): GroupedMessage[];
48
+ //#endregion
49
+ //#region src/hooks/use-tool-call-stream.d.ts
50
+ interface UseToolCallStreamReturn {
51
+ /** Current feed segments (text + tool calls interleaved) */
52
+ segments: FeedSegment[];
53
+ /** Push a raw SSE event into the stream */
54
+ pushEvent: (event: {
55
+ type: string;
56
+ data: Record<string, unknown>;
57
+ }) => void;
58
+ /** Push a text delta (from message.part.updated) */
59
+ pushText: (delta: string) => void;
60
+ /** Mark a tool call as complete */
61
+ completeToolCall: (id: string, result: {
62
+ output?: string;
63
+ error?: string;
64
+ duration?: number;
65
+ }) => void;
66
+ /** Reset the stream */
67
+ reset: () => void;
68
+ }
69
+ declare function useToolCallStream(): UseToolCallStreamReturn;
70
+ //#endregion
71
+ //#region src/hooks/use-sdk-session.d.ts
72
+ interface SdkSessionAttachment {
73
+ name: string;
74
+ size?: number;
75
+ }
76
+ interface SdkSessionSeed {
77
+ id: string;
78
+ role: SessionMessage["role"];
79
+ createdAt?: number | string | Date;
80
+ content?: string;
81
+ attachments?: SdkSessionAttachment[];
82
+ parts?: SessionPart[];
83
+ }
84
+ interface SdkSessionEvent {
85
+ type: string;
86
+ data?: Record<string, unknown>;
87
+ }
88
+ interface BeginAssistantMessageOptions {
89
+ id?: string;
90
+ role?: Extract<SessionMessage["role"], "assistant" | "system">;
91
+ createdAt?: number | string | Date;
92
+ }
93
+ interface AppendUserMessageOptions {
94
+ id?: string;
95
+ role?: Extract<SessionMessage["role"], "user" | "system">;
96
+ content: string;
97
+ createdAt?: number | string | Date;
98
+ attachments?: SdkSessionAttachment[];
99
+ }
100
+ interface CompleteAssistantMessageOptions {
101
+ messageId?: string;
102
+ finalText?: string;
103
+ }
104
+ interface ApplySdkEventOptions {
105
+ messageId?: string;
106
+ }
107
+ interface UseSdkSessionOptions {
108
+ initialMessages?: SdkSessionSeed[];
109
+ }
110
+ interface UseSdkSessionReturn {
111
+ messages: SessionMessage[];
112
+ partMap: Record<string, SessionPart[]>;
113
+ isStreaming: boolean;
114
+ activeAssistantMessageId: string | null;
115
+ replaceHistory: (messages: SdkSessionSeed[]) => void;
116
+ appendUserMessage: (message: AppendUserMessageOptions) => string;
117
+ beginAssistantMessage: (options?: BeginAssistantMessageOptions) => string;
118
+ applySdkEvent: (event: SdkSessionEvent, options?: ApplySdkEventOptions) => void;
119
+ completeAssistantMessage: (options?: CompleteAssistantMessageOptions) => void;
120
+ failAssistantMessage: (error: string, options?: {
121
+ messageId?: string;
122
+ }) => void;
123
+ setStreaming: (value: boolean) => void;
124
+ reset: () => void;
125
+ }
126
+ declare function useSdkSession({ initialMessages }?: UseSdkSessionOptions): UseSdkSessionReturn;
127
+ //#endregion
128
+ //#region src/hooks/use-realtime-session.d.ts
129
+ interface RealtimeSessionOptions extends RegisterActiveSessionOptions {
130
+ connectUrl?: string | null;
131
+ enabled?: boolean;
132
+ foreground?: boolean;
133
+ keepRegistered?: boolean;
134
+ reconnect?: boolean;
135
+ reconnectIntervalMs?: number;
136
+ maxReconnectAttempts?: number;
137
+ transportMode?: ActiveSessionTransportMode;
138
+ onEvent?: (event: SdkSessionEvent) => void;
139
+ onOpen?: () => void;
140
+ onClose?: () => void;
141
+ onError?: (error: Error) => void;
142
+ }
143
+ interface RealtimeSessionState {
144
+ connectionState: ActiveSessionConnectionState;
145
+ lastError: string | null;
146
+ reconnectAttempts: number;
147
+ isConnected: boolean;
148
+ }
149
+ interface RealtimeSessionTarget extends RealtimeSessionOptions {
150
+ key?: string;
151
+ }
152
+ interface RealtimeSessionRegistryProps {
153
+ sessions: RealtimeSessionTarget[];
154
+ }
155
+ declare function useRealtimeSession({ sessionId, projectId, projectLabel, title, href, metadata, connectUrl, enabled, foreground, keepRegistered, reconnect, reconnectIntervalMs, maxReconnectAttempts, transportMode, onEvent, onOpen, onClose, onError }: RealtimeSessionOptions): RealtimeSessionState;
156
+ declare function RealtimeSessionRegistry({ sessions }: RealtimeSessionRegistryProps): import("react").FunctionComponentElement<RealtimeSessionTarget>[];
157
+ //#endregion
158
+ //#region src/hooks/use-sse-stream.d.ts
159
+ /**
160
+ * SSE Event data structure
161
+ */
162
+ interface SSEEvent<T = unknown> {
163
+ id?: string;
164
+ event: string;
165
+ data: T;
166
+ timestamp: number;
167
+ }
168
+ /**
169
+ * Connection state for SSE streams
170
+ */
171
+ type ConnectionState = "connecting" | "connected" | "reconnecting" | "disconnected" | "error";
172
+ /**
173
+ * SSE stream options
174
+ */
175
+ interface UseSSEStreamOptions<T = unknown> {
176
+ /** URL to connect to */
177
+ url: string;
178
+ /** Authorization header value */
179
+ authToken?: string;
180
+ /** Enable automatic reconnection (default: true) */
181
+ autoReconnect?: boolean;
182
+ /** Max reconnection attempts (default: 5) */
183
+ maxRetries?: number;
184
+ /** Base delay between reconnects in ms (default: 1000) */
185
+ reconnectDelay?: number;
186
+ /** Event types to listen for (default: all) */
187
+ eventTypes?: string[];
188
+ /** Callback for each event */
189
+ onEvent?: (event: SSEEvent<T>) => void;
190
+ /** Callback on connection state change */
191
+ onStateChange?: (state: ConnectionState) => void;
192
+ /** Callback on error */
193
+ onError?: (error: Error) => void;
194
+ /** Custom headers */
195
+ headers?: Record<string, string>;
196
+ /** Whether to start connected (default: true) */
197
+ enabled?: boolean;
198
+ }
199
+ /**
200
+ * SSE stream result
201
+ */
202
+ interface UseSSEStreamResult<T = unknown> {
203
+ /** Current connection state */
204
+ state: ConnectionState;
205
+ /** All received events */
206
+ events: SSEEvent<T>[];
207
+ /** Most recent event */
208
+ lastEvent: SSEEvent<T> | null;
209
+ /** Error if any */
210
+ error: Error | null;
211
+ /** Manually connect */
212
+ connect: () => void;
213
+ /** Manually disconnect */
214
+ disconnect: () => void;
215
+ /** Clear events buffer */
216
+ clearEvents: () => void;
217
+ /** Retry count */
218
+ retryCount: number;
219
+ /** Time since last event (ms) */
220
+ timeSinceLastEvent: number;
221
+ }
222
+ /**
223
+ * React hook for consuming SSE streams with automatic reconnection,
224
+ * event buffering, and state management.
225
+ *
226
+ * @example
227
+ * ```tsx
228
+ * const { events, state, lastEvent } = useSSEStream({
229
+ * url: '/api/v1/tasks/123/stream',
230
+ * authToken: 'Bearer xxx',
231
+ * onEvent: (e) => console.log('Event:', e),
232
+ * });
233
+ *
234
+ * return (
235
+ * <div>
236
+ * <p>Status: {state}</p>
237
+ * {events.map((e, i) => (
238
+ * <div key={i}>{e.event}: {JSON.stringify(e.data)}</div>
239
+ * ))}
240
+ * </div>
241
+ * );
242
+ * ```
243
+ */
244
+ declare function useSSEStream<T = unknown>(options: UseSSEStreamOptions<T>): UseSSEStreamResult<T>;
245
+ /**
246
+ * Typed event types for common streaming scenarios
247
+ */
248
+ interface TaskStreamEvent {
249
+ task_id: string;
250
+ status?: string;
251
+ progress?: number;
252
+ message?: string;
253
+ result?: unknown;
254
+ error?: string;
255
+ }
256
+ interface AgentStreamEvent {
257
+ type: "message.updated" | "tool_call" | "tool_result" | "llm_response" | "error" | "session.idle" | "execution.started" | "execution.result";
258
+ data: unknown;
259
+ timestamp?: number;
260
+ }
261
+ interface TerminalStreamEvent {
262
+ type: "output" | "input" | "error" | "exit";
263
+ data: string;
264
+ timestamp: number;
265
+ }
266
+ interface AutomationStreamEvent {
267
+ automation_id: string;
268
+ event_id?: string;
269
+ status?: string;
270
+ variant_id?: string;
271
+ output?: string;
272
+ action_result?: unknown;
273
+ error?: string;
274
+ }
275
+ interface BotStreamEvent {
276
+ bot_id: string;
277
+ type: "balance" | "trade" | "decision" | "log" | "error";
278
+ data: unknown;
279
+ timestamp: number;
280
+ }
281
+ //#endregion
282
+ export { useRunGroups as A, SdkSessionSeed as C, UseToolCallStreamReturn as D, useSdkSession as E, useDropdownMenu as M, useAutoScroll as N, useToolCallStream as O, SdkSessionEvent as S, UseSdkSessionReturn as T, AppendUserMessageOptions as _, SSEEvent as a, CompleteAssistantMessageOptions as b, UseSSEStreamOptions as c, RealtimeSessionOptions as d, RealtimeSessionRegistry as f, useRealtimeSession as g, RealtimeSessionTarget as h, ConnectionState as i, useRunCollapseState as j, UseRunGroupsOptions as k, UseSSEStreamResult as l, RealtimeSessionState as m, AutomationStreamEvent as n, TaskStreamEvent as o, RealtimeSessionRegistryProps as p, BotStreamEvent as r, TerminalStreamEvent as s, AgentStreamEvent as t, useSSEStream as u, ApplySdkEventOptions as v, UseSdkSessionOptions as w, SdkSessionAttachment as x, BeginAssistantMessageOptions as y };
@@ -0,0 +1,37 @@
1
+ //#region src/utils/copy-text.ts
2
+ /**
3
+ * Copy text to clipboard with a non-secure-context fallback.
4
+ * Returns true if a copy strategy likely succeeded.
5
+ */
6
+ async function copyText(text) {
7
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) try {
8
+ await navigator.clipboard.writeText(text);
9
+ return true;
10
+ } catch {}
11
+ if (typeof document === "undefined") return false;
12
+ try {
13
+ const textarea = document.createElement("textarea");
14
+ textarea.value = text;
15
+ textarea.style.position = "fixed";
16
+ textarea.style.opacity = "0";
17
+ document.body.appendChild(textarea);
18
+ textarea.select();
19
+ const copied = document.execCommand("copy");
20
+ document.body.removeChild(textarea);
21
+ return copied;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ //#endregion
27
+ //#region src/utils/time-ago.ts
28
+ function timeAgo(ts) {
29
+ const secs = Math.floor((Date.now() - ts) / 1e3);
30
+ if (secs < 5) return "just now";
31
+ if (secs < 60) return `${secs}s ago`;
32
+ const mins = Math.floor(secs / 60);
33
+ if (mins < 60) return `${mins}m ago`;
34
+ return `${Math.floor(mins / 60)}h ago`;
35
+ }
36
+ //#endregion
37
+ export { copyText as n, timeAgo as t };
@@ -1,10 +1,8 @@
1
- // src/lib/utils.ts
2
1
  import { clsx } from "clsx";
3
2
  import { twMerge } from "tailwind-merge";
3
+ //#region src/lib/utils.ts
4
4
  function cn(...inputs) {
5
- return twMerge(clsx(inputs));
5
+ return twMerge(clsx(inputs));
6
6
  }
7
-
8
- export {
9
- cn
10
- };
7
+ //#endregion
8
+ export { cn as t };
package/dist/utils.d.ts CHANGED
@@ -1,51 +1,2 @@
1
- import { a as ToolPart } from './parts-dj7AcUg0.js';
2
- import { T as ToolDisplayMetadata } from './tool-display-z4JcDmMQ.js';
3
- import { T as ToolCategory } from './run-PfLmDAox.js';
4
- import { ClassValue } from 'clsx';
5
- import 'react';
6
- import './message-BHWbxBtT.js';
7
-
8
- /**
9
- * Copy text to clipboard with a non-secure-context fallback.
10
- * Returns true if a copy strategy likely succeeded.
11
- */
12
- declare function copyText(text: string): Promise<boolean>;
13
-
14
- /** Format a duration in milliseconds to a human-readable string. */
15
- declare function formatDuration(ms: number): string;
16
- /** Truncate text to `max` characters, appending "..." if truncated. */
17
- declare function truncateText(text: string, max: number): string;
18
- /**
19
- * Format an uptime duration in milliseconds with progressive
20
- * granularity, so short-lived sandboxes don't render as "0d 0h".
21
- * - < 60s → "Ns"
22
- * - < 60m → "Nm Ss"
23
- * - < 24h → "Nh Mm"
24
- * - otherwise → "Nd Hh"
25
- */
26
- declare function formatUptime(ms: number): string;
27
- /**
28
- * Format a byte count using binary units (KiB/MiB/GiB, surfaced as
29
- * "KB/MB/GB" for readability). KB and MB use one decimal below 10 and
30
- * round above; GB keeps two decimals below 10 so half-GB changes stay
31
- * visible on memory dashboards, and drops to one decimal above.
32
- */
33
- declare function formatBytes(bytes: number): string;
34
-
35
- declare function timeAgo(ts: number): string;
36
-
37
- declare const TOOL_CATEGORY_ICONS: Record<ToolCategory, string>;
38
- declare function getToolCategory(toolName: string): ToolCategory;
39
- /**
40
- * Title is the bare verb ("Read", "Edit", "Shell"); the path, command, pattern
41
- * or query lives in `description` only, so a row prints its subject once.
42
- * `targetPath` / `commandSnippet` carry the untruncated value for consumers
43
- * that need it (diff headers, expanded detail).
44
- */
45
- declare function getToolDisplayMetadata(part: ToolPart): ToolDisplayMetadata;
46
- /** Extract error text from a tool part, if any. */
47
- declare function getToolErrorText(part: ToolPart, fallback?: string): string | undefined;
48
-
49
- declare function cn(...inputs: ClassValue[]): string;
50
-
51
- export { TOOL_CATEGORY_ICONS, cn, copyText, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText };
1
+ import { a as focusRingInset, c as getToolCategory, d as timeAgo, f as formatBytes, g as copyText, h as truncateText, i as focusRing, l as getToolDisplayMetadata, m as formatUptime, n as focusFieldInvalid, o as cn, p as formatDuration, r as focusFieldWithin, s as TOOL_CATEGORY_ICONS, t as focusField, u as getToolErrorText } from "./index-b56ew9aF.js";
2
+ export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText };
package/dist/utils.js CHANGED
@@ -1,32 +1,6 @@
1
- import {
2
- copyText,
3
- timeAgo
4
- } from "./chunk-XGKULLYE.js";
5
- import {
6
- TOOL_CATEGORY_ICONS,
7
- getToolCategory,
8
- getToolDisplayMetadata,
9
- getToolErrorText
10
- } from "./chunk-ND3ZFXQK.js";
11
- import {
12
- formatBytes,
13
- formatDuration,
14
- formatUptime,
15
- truncateText
16
- } from "./chunk-4CLN43XT.js";
17
- import {
18
- cn
19
- } from "./chunk-RQHJBTEU.js";
20
- export {
21
- TOOL_CATEGORY_ICONS,
22
- cn,
23
- copyText,
24
- formatBytes,
25
- formatDuration,
26
- formatUptime,
27
- getToolCategory,
28
- getToolDisplayMetadata,
29
- getToolErrorText,
30
- timeAgo,
31
- truncateText
32
- };
1
+ import { a as focusRingInset, i as focusRing, n as focusFieldInvalid, r as focusFieldWithin, t as focusField } from "./focus-Cw02pNSr.js";
2
+ import { t as cn } from "./utils-C_uf36nf.js";
3
+ import { i as getToolErrorText, n as getToolCategory, r as getToolDisplayMetadata, t as TOOL_CATEGORY_ICONS } from "./tool-display-BAuAVa43.js";
4
+ import { i as truncateText, n as formatDuration, r as formatUptime, t as formatBytes } from "./format-DfcLWqMa.js";
5
+ import { n as copyText, t as timeAgo } from "./utils-Bl_CZ0Qp.js";
6
+ export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.9.0",
3
+ "version": "11.11.0",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -109,34 +109,32 @@
109
109
  }
110
110
  },
111
111
  "dependencies": {
112
- "@pierre/trees": "1.0.0-beta.3",
113
- "@radix-ui/react-avatar": "^1.1.0",
114
- "@radix-ui/react-collapsible": "^1.1.0",
115
- "@radix-ui/react-dialog": "^1.1.0",
116
- "@radix-ui/react-dropdown-menu": "^2.1.0",
117
- "@radix-ui/react-label": "^2.1.0",
118
- "@radix-ui/react-progress": "^1.1.0",
119
- "@radix-ui/react-select": "^2.1.0",
120
- "@radix-ui/react-slot": "^1.1.0",
121
- "@radix-ui/react-switch": "^1.1.0",
122
- "@radix-ui/react-tabs": "^1.1.0",
123
- "@radix-ui/react-toast": "^1.2.0",
124
- "class-variance-authority": "^0.7.0",
112
+ "@pierre/trees": "1.0.0-beta.6",
113
+ "@radix-ui/react-avatar": "^1.2.6",
114
+ "@radix-ui/react-collapsible": "^1.1.20",
115
+ "@radix-ui/react-dialog": "^1.1.23",
116
+ "@radix-ui/react-dropdown-menu": "^2.1.24",
117
+ "@radix-ui/react-label": "^2.1.15",
118
+ "@radix-ui/react-progress": "^1.1.16",
119
+ "@radix-ui/react-select": "^2.3.7",
120
+ "@radix-ui/react-slot": "^1.3.3",
121
+ "@radix-ui/react-switch": "^1.3.7",
122
+ "@radix-ui/react-tabs": "^1.1.21",
123
+ "class-variance-authority": "^0.7.1",
125
124
  "clsx": "^2.1.1",
126
- "lucide-react": "^0.469.0",
127
- "marked": "^17.0.5",
125
+ "lucide-react": "^1.48.0",
126
+ "marked": "^18.0.14",
128
127
  "react-markdown": "^10.1.0",
129
- "react-pdf": "^9.2.1",
130
128
  "react-syntax-highlighter": "^16.1.1",
131
129
  "rehype-sanitize": "^6.0.0",
132
130
  "remark-gfm": "^4.0.1",
133
- "tailwind-merge": "^3.0.2",
134
- "turndown": "^7.2.2"
131
+ "tailwind-merge": "^3.7.0",
132
+ "turndown": "^7.2.4"
135
133
  },
136
134
  "peerDependencies": {
137
- "@tangle-network/brand": "^1.5.0",
138
135
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
139
- "@nanostores/react": ">=0.8.4 <2.0.0",
136
+ "@nanostores/react": ">=0.8.4 <3.0.0",
137
+ "@tangle-network/brand": "^1.8.1",
140
138
  "@tiptap/core": ">=3.20.4 <4.0.0",
141
139
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
142
140
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
@@ -181,25 +179,25 @@
181
179
  }
182
180
  },
183
181
  "devDependencies": {
184
- "@hocuspocus/provider": "^4.4.0",
185
- "@nanostores/react": "^1.1.0",
186
- "@tiptap/core": "^3.28.0",
187
- "@tiptap/extension-collaboration": "^3.28.0",
188
- "@tiptap/extension-collaboration-caret": "^3.28.0",
189
- "@tiptap/react": "^3.28.0",
190
- "@tiptap/starter-kit": "^3.28.0",
191
- "@tiptap/y-tiptap": "^3.0.7",
192
- "@types/react": "^19.0.0",
182
+ "@hocuspocus/provider": "^4.7.0",
183
+ "@nanostores/react": "^2.0.1",
184
+ "@storybook/react": "^10.6.0",
185
+ "@tiptap/core": "^3.31.3",
186
+ "@tiptap/extension-collaboration": "^3.31.3",
187
+ "@tiptap/extension-collaboration-caret": "^3.31.3",
188
+ "@tiptap/react": "^3.31.3",
189
+ "@tiptap/starter-kit": "^3.31.3",
190
+ "@tiptap/y-tiptap": "^3.0.9",
191
+ "@types/react": "^19.3.0",
193
192
  "@types/react-syntax-highlighter": "^15.5.13",
194
- "@types/turndown": "^5.0.5",
195
- "nanostores": "^1.4.1",
196
- "react": "^19.2.8",
197
- "react-dom": "^19.2.8",
198
- "@storybook/react": "^10.5.5",
199
- "tsup": "^8.3.5",
200
- "typescript": "^5.6.0",
201
- "yjs": "^13.6.31",
202
- "react-router": "^8.3.0"
193
+ "@types/turndown": "^5.0.6",
194
+ "nanostores": "^1.5.4",
195
+ "react": "^19.3.0",
196
+ "react-dom": "^19.3.0",
197
+ "react-router": "^8.4.0",
198
+ "tsdown": "^0.23.0",
199
+ "typescript": "^7.0.2",
200
+ "yjs": "^13.6.33"
203
201
  },
204
202
  "keywords": [
205
203
  "tangle",
@@ -209,7 +207,7 @@
209
207
  "design-system"
210
208
  ],
211
209
  "scripts": {
212
- "build": "tsup && node ../../scripts/validate-dist.mjs",
213
- "dev": "tsup --watch"
210
+ "build": "tsdown && node ../../scripts/validate-dist.mjs",
211
+ "dev": "tsdown --watch"
214
212
  }
215
213
  }
package/src/auth/auth.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import type * as React from "react";
4
+ import { focusRing } from "../lib/focus";
4
5
  import { cn } from "../lib/utils";
5
6
  import { Avatar, AvatarFallback, AvatarImage } from "../primitives/avatar";
6
7
  import { Button, type ButtonProps } from "../primitives/button";
@@ -120,7 +121,10 @@ export function UserMenu({
120
121
  <DropdownMenuTrigger asChild>
121
122
  <button
122
123
  type="button"
123
- 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"
124
+ className={cn(
125
+ "flex items-center gap-2 rounded-lg p-1.5 transition-colors hover:bg-accent",
126
+ focusRing,
127
+ )}
124
128
  >
125
129
  <Avatar className="h-8 w-8">
126
130
  <AvatarImage src={undefined} alt={user.name ?? user.email} />
@@ -6,6 +6,7 @@ import {
6
6
  FileText,
7
7
  Info,
8
8
  } from "lucide-react";
9
+ import { focusRing } from "../lib/focus";
9
10
  import { cn } from "../lib/utils";
10
11
  import { type MessageRole } from "./chat-message";
11
12
  import { UserMessage } from "./user-message";
@@ -235,7 +236,11 @@ function ArtifactCard({ item }: { item: AgentTimelineArtifactItem }) {
235
236
  item.onClick?.();
236
237
  }
237
238
  }}
238
- className="block w-full text-left transition-transform hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
239
+ // Rounded like the card inside it, so the focus ring follows its corners.
240
+ className={cn(
241
+ "block w-full rounded-[var(--radius-lg)] text-left transition-transform hover:-translate-y-0.5",
242
+ focusRing,
243
+ )}
239
244
  >
240
245
  {content}
241
246
  </div>
@@ -5,6 +5,7 @@ import {
5
5
  useRef,
6
6
  } from "react";
7
7
  import { ArrowDown } from "lucide-react";
8
+ import { focusRing } from "../lib/focus";
8
9
  import { cn } from "../lib/utils";
9
10
  import type { SessionMessage } from "../types/message";
10
11
  import type { SessionPart, TextPart, ToolPart } from "../types/parts";
@@ -459,7 +460,7 @@ export const ChatContainer = memo(
459
460
  "flex items-center gap-1.5 px-3 py-1.5 rounded-full",
460
461
  "border border-border bg-card shadow-[0_6px_16px_rgba(15,23,42,0.08)]",
461
462
  "text-xs text-foreground transition-colors hover:bg-accent",
462
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
463
+ focusRing,
463
464
  )}
464
465
  >
465
466
  <ArrowDown className="w-3 h-3" />
@@ -32,6 +32,8 @@ async function paneWithoutPeers(message: string) {
32
32
  return { DocumentEditorPane, loaders };
33
33
  }
34
34
 
35
+ // The pane is imported on a fresh module graph, which re-transforms its whole
36
+ // dependency tree: seconds on a busy runner, past the 5s default.
35
37
  describe("DocumentEditorPane without the editor peers", () => {
36
38
  it("renders the preview, because only the edit tab needs the peers", async () => {
37
39
  const { DocumentEditorPane, loaders } = await paneWithoutPeers(
@@ -54,5 +56,5 @@ describe("DocumentEditorPane without the editor peers", () => {
54
56
  expect(loaders.loadDocumentEditorPeers).not.toHaveBeenCalled();
55
57
  expect(loaders.loadCollaborationPeers).not.toHaveBeenCalled();
56
58
  expect(loaders.loadEditorProviderPeers).not.toHaveBeenCalled();
57
- });
59
+ }, 30_000);
58
60
  });
@@ -4,6 +4,7 @@ import { type ReactNode, useEffect, useMemo, useState } from "react";
4
4
  import { PencilLine, Save, Users, Wifi, WifiOff } from "lucide-react";
5
5
  import { Markdown } from "../markdown/markdown";
6
6
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../primitives/tabs";
7
+ import { focusRing } from "../lib/focus";
7
8
  import { cn } from "../lib/utils";
8
9
  import { ArtifactPane, type ArtifactPaneProps } from "../primitives/artifact-pane";
9
10
  import {
@@ -276,7 +277,10 @@ export function DocumentEditorPane({
276
277
  type="button"
277
278
  onClick={() => void onSave(draft)}
278
279
  disabled={saving || !isDirty}
279
- className="inline-flex items-center gap-2 rounded-[var(--radius-full)] border border-border bg-card px-3 py-1.5 text-xs font-semibold text-foreground transition-colors hover:border-primary/40 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
280
+ className={cn(
281
+ "inline-flex items-center gap-2 rounded-[var(--radius-full)] border border-border bg-card px-3 py-1.5 text-xs font-semibold text-foreground transition-colors hover:border-[var(--border-strong)] hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
282
+ focusRing,
283
+ )}
280
284
  >
281
285
  <Save className="h-3.5 w-3.5" />
282
286
  {saving ? "Saving..." : saveLabel}