@tangle-network/ui 11.24.0 → 11.26.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 (56) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +22 -0
  3. package/dist/chat/agent-timeline.d.ts +13 -1
  4. package/dist/chat/agent-timeline.js +25 -4
  5. package/dist/chat/chat-message.d.ts +13 -1
  6. package/dist/chat/chat-message.js +9 -5
  7. package/dist/chat/message-author.d.ts +24 -0
  8. package/dist/chat/message-author.js +53 -0
  9. package/dist/chat/user-message.d.ts +12 -2
  10. package/dist/chat/user-message.js +52 -16
  11. package/dist/chat.d.ts +3 -1
  12. package/dist/chat.js +2 -1
  13. package/dist/editor/editor-peers.js +1 -21
  14. package/dist/files/file-card.d.ts +30 -0
  15. package/dist/files/file-card.js +162 -0
  16. package/dist/files/file-list.d.ts +25 -0
  17. package/dist/files/file-list.js +88 -0
  18. package/dist/files/file-preview.js +16 -62
  19. package/dist/files/pdf-loader.d.ts +22 -0
  20. package/dist/files/pdf-loader.js +82 -0
  21. package/dist/files/pdf-viewer.d.ts +32 -0
  22. package/dist/files/pdf-viewer.js +567 -0
  23. package/dist/files.d.ts +5 -1
  24. package/dist/files.js +5 -1
  25. package/dist/index.d.ts +9 -4
  26. package/dist/index.js +6 -1
  27. package/dist/lib/optional-peer.js +29 -0
  28. package/dist/primitives.d.ts +2 -2
  29. package/dist/types/message.d.ts +19 -0
  30. package/dist/types.d.ts +2 -2
  31. package/package.json +7 -2
  32. package/src/chat/agent-timeline.tsx +33 -3
  33. package/src/chat/chat-message.tsx +37 -10
  34. package/src/chat/index.ts +2 -0
  35. package/src/chat/message-author.stories.tsx +170 -0
  36. package/src/chat/message-author.test.tsx +189 -0
  37. package/src/chat/message-author.tsx +52 -0
  38. package/src/chat/user-message.tsx +63 -8
  39. package/src/editor/editor-peers.ts +3 -25
  40. package/src/files/file-artifact-pane.test.tsx +12 -2
  41. package/src/files/file-card.test.tsx +62 -0
  42. package/src/files/file-card.tsx +210 -0
  43. package/src/files/file-list.stories.tsx +121 -0
  44. package/src/files/file-list.test.tsx +81 -0
  45. package/src/files/file-list.tsx +167 -0
  46. package/src/files/file-preview.tsx +25 -94
  47. package/src/files/index.ts +9 -0
  48. package/src/files/pdf-loader.test.ts +130 -0
  49. package/src/files/pdf-loader.ts +169 -0
  50. package/src/files/pdf-viewer.stories.tsx +81 -0
  51. package/src/files/pdf-viewer.test.tsx +245 -0
  52. package/src/files/pdf-viewer.tsx +677 -0
  53. package/src/files/pdfjs-worker.d.ts +3 -0
  54. package/src/lib/optional-peer.ts +30 -0
  55. package/src/markdown/code-block.test.tsx +2 -1
  56. package/src/types/message.ts +20 -0
@@ -0,0 +1,567 @@
1
+ import { focusRingInset } from "../lib/focus.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { fieldPresentation } from "../lib/control-presentation.js";
4
+ import { Button } from "../primitives/button.js";
5
+ import { Alert, AlertDescription } from "../primitives/alert.js";
6
+ import { FileCard } from "./file-card.js";
7
+ import { isMissingPdfjsError, loadPdfjs, pdfAssetParams } from "./pdf-loader.js";
8
+ import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ import { ChevronLeft, ChevronRight, Download, Info, LoaderCircle, ZoomIn, ZoomOut } from "lucide-react";
11
+ //#region src/files/pdf-viewer.tsx
12
+ /**
13
+ * PdfViewer — renders a PDF's pages to canvas with pdf.js, so a document reads
14
+ * the same in every browser, phones included. A continuous column of pages
15
+ * with page navigation, zoom and fit-to-width, and Download.
16
+ *
17
+ * Only pages within a screen of the visible area hold a canvas; the rest keep
18
+ * their size and release theirs, so a long document stays inside the canvas
19
+ * memory a phone allows.
20
+ *
21
+ * When pdf.js is not installed or cannot open the file, the viewer says so
22
+ * and falls back to the browser's own viewer through `<object>`, and from
23
+ * there to a FileCard where the browser has none (Android Chrome).
24
+ */
25
+ /** pdf.js measures in points; CSS pixels are 96 to the inch. */
26
+ const PDF_TO_CSS = 96 / 72;
27
+ const ZOOM_STEPS = [
28
+ .25,
29
+ .5,
30
+ .75,
31
+ 1,
32
+ 1.25,
33
+ 1.5,
34
+ 2,
35
+ 3,
36
+ 4
37
+ ];
38
+ const MIN_ZOOM = ZOOM_STEPS[0];
39
+ const MAX_ZOOM = ZOOM_STEPS[ZOOM_STEPS.length - 1];
40
+ /** Matches the column's `p-3`. */
41
+ const COLUMN_PADDING = 12;
42
+ /**
43
+ * iOS Safari refuses to draw a canvas above 4096 × 4096 pixels. Past that, a
44
+ * page renders below the device pixel ratio, softer but whole.
45
+ */
46
+ const MAX_CANVAS_PIXELS = 16777216;
47
+ function clamp(value, min, max) {
48
+ return Math.min(max, Math.max(min, value));
49
+ }
50
+ /**
51
+ * pdf.js streams an http(s) URL itself, with range requests, so the first
52
+ * page shows before a long file finishes downloading. It reads other URLs
53
+ * through XMLHttpRequest, which not every browser allows for a data URL, so
54
+ * those are read here and handed over as bytes.
55
+ */
56
+ async function documentSource(src, signal) {
57
+ if (/^https?:/i.test(new URL(src, document.baseURI).protocol)) return { url: src };
58
+ const response = await fetch(src, { signal });
59
+ if (!response.ok) throw new Error(`Reading the PDF failed with status ${response.status}.`);
60
+ return { data: new Uint8Array(await response.arrayBuffer()) };
61
+ }
62
+ /** What the reader is told when the viewer falls back, and whether retrying can help. */
63
+ function fallbackFor(error) {
64
+ if (isMissingPdfjsError(error)) return {
65
+ notice: "This is the browser's PDF viewer, because this app does not include the page viewer.",
66
+ retry: false
67
+ };
68
+ const name = error instanceof Error ? error.name : "";
69
+ if (name === "PasswordException") return {
70
+ notice: "This PDF is password-protected, so it opens in the browser's PDF viewer.",
71
+ retry: false
72
+ };
73
+ if (name === "InvalidPDFException") return {
74
+ notice: "This file could not be read as a PDF.",
75
+ retry: false
76
+ };
77
+ const status = error?.status;
78
+ if (name === "ResponseException" && typeof status === "number" && status > 0) return {
79
+ notice: `The PDF could not be downloaded (HTTP ${status}).`,
80
+ retry: true
81
+ };
82
+ return {
83
+ notice: "The page viewer could not open this PDF, so this is the browser's PDF viewer.",
84
+ retry: true
85
+ };
86
+ }
87
+ function PdfViewer({ src, filename = "Document", size, onDownload, className }) {
88
+ const [attempt, setAttempt] = useState(0);
89
+ const [state, setState] = useState({ status: "loading" });
90
+ useEffect(() => {
91
+ let active = true;
92
+ let destroy;
93
+ const abort = new AbortController();
94
+ setState({ status: "loading" });
95
+ const fail = (error) => {
96
+ if (!active) return;
97
+ console.error(`PdfViewer: falling back to the browser's PDF viewer for ${filename}.`, error);
98
+ setState({
99
+ status: "fallback",
100
+ ...fallbackFor(error)
101
+ });
102
+ };
103
+ (async () => {
104
+ const pdfjs = await loadPdfjs();
105
+ const source = await documentSource(src, abort.signal);
106
+ if (!active) return;
107
+ const task = pdfjs.getDocument({
108
+ ...source,
109
+ ...pdfAssetParams()
110
+ });
111
+ destroy = () => task.destroy();
112
+ task.onProgress = ({ loaded, total }) => {
113
+ if (active && total > 0) setState({
114
+ status: "loading",
115
+ percent: Math.min(100, Math.round(loaded / total * 100))
116
+ });
117
+ };
118
+ const doc = await task.promise;
119
+ if (active) setState({
120
+ status: "ready",
121
+ doc
122
+ });
123
+ })().catch(fail);
124
+ return () => {
125
+ active = false;
126
+ abort.abort();
127
+ destroy?.();
128
+ };
129
+ }, [src, attempt]);
130
+ return /* @__PURE__ */ jsx("div", {
131
+ "data-state": state.status,
132
+ className: cn("flex max-h-[100dvh] min-h-0 flex-col overflow-hidden rounded-[var(--radius-md)] border border-border bg-card", className),
133
+ children: state.status === "ready" ? /* @__PURE__ */ jsx(PdfDocument, {
134
+ doc: state.doc,
135
+ filename,
136
+ onDownload
137
+ }) : state.status === "loading" ? /* @__PURE__ */ jsxs("div", {
138
+ role: "status",
139
+ className: "flex min-h-[12rem] flex-1 flex-col items-center justify-center gap-3 p-6 text-sm text-muted-foreground",
140
+ children: [/* @__PURE__ */ jsx(LoaderCircle, {
141
+ "aria-hidden": "true",
142
+ className: "size-5 animate-spin motion-reduce:animate-none"
143
+ }), /* @__PURE__ */ jsxs("span", { children: [
144
+ "Loading ",
145
+ filename,
146
+ state.percent === void 0 ? "…" : ` · ${state.percent}%`
147
+ ] })]
148
+ }) : /* @__PURE__ */ jsxs("div", {
149
+ className: "flex min-h-0 flex-1 flex-col gap-3 overflow-auto p-3",
150
+ children: [/* @__PURE__ */ jsxs(Alert, {
151
+ tone: "info",
152
+ icon: /* @__PURE__ */ jsx(Info, {}),
153
+ children: [/* @__PURE__ */ jsx(AlertDescription, { children: state.notice }), state.retry && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, {
154
+ type: "button",
155
+ variant: "outline",
156
+ size: "sm",
157
+ onClick: () => setAttempt((n) => n + 1),
158
+ children: "Try again"
159
+ }) })]
160
+ }), /* @__PURE__ */ jsx("object", {
161
+ data: src,
162
+ type: "application/pdf",
163
+ title: filename,
164
+ className: "min-h-[20rem] w-full flex-1 rounded-[var(--radius-md)]",
165
+ children: /* @__PURE__ */ jsx(FileCard, {
166
+ filename,
167
+ mimeType: "application/pdf",
168
+ size,
169
+ description: "This browser does not show PDFs inline.",
170
+ onDownload,
171
+ className: "h-full"
172
+ })
173
+ })]
174
+ })
175
+ });
176
+ }
177
+ function PdfDocument({ doc, filename, onDownload }) {
178
+ const pageCount = doc.numPages;
179
+ const [scroller, setScroller] = useState(null);
180
+ const pageElements = useRef([]);
181
+ const [firstPage, setFirstPage] = useState(null);
182
+ const [availableWidth, setAvailableWidth] = useState(0);
183
+ const [zoomSetting, setZoomSetting] = useState({ mode: "fit" });
184
+ const [currentPage, setCurrentPage] = useState(1);
185
+ const anchor = useRef(null);
186
+ const registerPage = useCallback((pageNumber, element) => {
187
+ pageElements.current[pageNumber - 1] = element;
188
+ }, []);
189
+ useEffect(() => {
190
+ let active = true;
191
+ doc.getPage(1).then((page) => {
192
+ if (!active) return;
193
+ const { width, height } = page.getViewport({ scale: PDF_TO_CSS });
194
+ setFirstPage({
195
+ width,
196
+ height
197
+ });
198
+ }, () => {
199
+ if (active) setFirstPage({
200
+ width: 612 * PDF_TO_CSS,
201
+ height: 792 * PDF_TO_CSS
202
+ });
203
+ });
204
+ return () => {
205
+ active = false;
206
+ };
207
+ }, [doc]);
208
+ useLayoutEffect(() => {
209
+ if (!scroller) return;
210
+ setAvailableWidth(scroller.clientWidth);
211
+ if (typeof ResizeObserver === "undefined") return;
212
+ const observer = new ResizeObserver(() => setAvailableWidth(scroller.clientWidth));
213
+ observer.observe(scroller);
214
+ return () => observer.disconnect();
215
+ }, [scroller]);
216
+ const fitZoom = firstPage && availableWidth > 24 ? clamp((availableWidth - 24) / firstPage.width, MIN_ZOOM, MAX_ZOOM) : 1;
217
+ const zoom = zoomSetting.mode === "fit" ? fitZoom : zoomSetting.value;
218
+ const readPosition = useCallback(() => {
219
+ if (!scroller) return;
220
+ const top = scroller.scrollTop;
221
+ const bottom = top + scroller.clientHeight;
222
+ let best = 0;
223
+ let bestVisible = -1;
224
+ pageElements.current.forEach((element, index) => {
225
+ if (!element) return;
226
+ const visible = Math.min(bottom, element.offsetTop + element.offsetHeight) - Math.max(top, element.offsetTop);
227
+ if (visible > bestVisible) {
228
+ best = index;
229
+ bestVisible = visible;
230
+ }
231
+ });
232
+ if (top + scroller.clientHeight >= scroller.scrollHeight - 1 && top > 0) best = pageCount - 1;
233
+ const element = pageElements.current[best];
234
+ anchor.current = {
235
+ index: best,
236
+ fraction: element?.offsetHeight ? (top - element.offsetTop) / element.offsetHeight : 0
237
+ };
238
+ setCurrentPage(best + 1);
239
+ }, [scroller, pageCount]);
240
+ useLayoutEffect(() => {
241
+ const element = anchor.current && pageElements.current[anchor.current.index];
242
+ if (!scroller || !anchor.current || !element) return;
243
+ scroller.scrollTop = element.offsetTop + anchor.current.fraction * element.offsetHeight;
244
+ scroller.scrollLeft = (scroller.scrollWidth - scroller.clientWidth) / 2;
245
+ }, [scroller, zoom]);
246
+ const frame = useRef(0);
247
+ useEffect(() => () => cancelAnimationFrame(frame.current), []);
248
+ const onScroll = () => {
249
+ if (frame.current) return;
250
+ frame.current = requestAnimationFrame(() => {
251
+ frame.current = 0;
252
+ readPosition();
253
+ });
254
+ };
255
+ const goToPage = (pageNumber) => {
256
+ const target = clamp(pageNumber, 1, pageCount);
257
+ const element = pageElements.current[target - 1];
258
+ if (scroller && element) {
259
+ scroller.scrollTop = element.offsetTop - COLUMN_PADDING;
260
+ anchor.current = {
261
+ index: target - 1,
262
+ fraction: element.offsetHeight ? -12 / element.offsetHeight : 0
263
+ };
264
+ }
265
+ setCurrentPage(target);
266
+ };
267
+ const zoomBy = (direction) => {
268
+ readPosition();
269
+ const next = direction > 0 ? ZOOM_STEPS.find((step) => step > zoom + .001) ?? MAX_ZOOM : [...ZOOM_STEPS].reverse().find((step) => step < zoom - .001) ?? MIN_ZOOM;
270
+ setZoomSetting({
271
+ mode: "manual",
272
+ value: next
273
+ });
274
+ };
275
+ const percent = Math.round(zoom * 100);
276
+ const fitting = zoomSetting.mode === "fit";
277
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
278
+ role: "group",
279
+ "aria-label": `${filename} controls`,
280
+ className: "flex shrink-0 items-center gap-0.5 overflow-x-auto border-b border-border px-1 py-1 [&>*]:shrink-0",
281
+ children: [
282
+ /* @__PURE__ */ jsx(Button, {
283
+ type: "button",
284
+ variant: "ghost",
285
+ size: "icon",
286
+ "aria-label": "Previous page",
287
+ title: "Previous page",
288
+ disabled: currentPage <= 1,
289
+ onClick: () => goToPage(currentPage - 1),
290
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
291
+ }),
292
+ /* @__PURE__ */ jsx(PageField, {
293
+ current: currentPage,
294
+ total: pageCount,
295
+ onCommit: goToPage
296
+ }),
297
+ /* @__PURE__ */ jsx(Button, {
298
+ type: "button",
299
+ variant: "ghost",
300
+ size: "icon",
301
+ "aria-label": "Next page",
302
+ title: "Next page",
303
+ disabled: currentPage >= pageCount,
304
+ onClick: () => goToPage(currentPage + 1),
305
+ children: /* @__PURE__ */ jsx(ChevronRight, {})
306
+ }),
307
+ /* @__PURE__ */ jsxs("div", {
308
+ className: "ml-auto flex items-center gap-0.5",
309
+ children: [
310
+ /* @__PURE__ */ jsx(Button, {
311
+ type: "button",
312
+ variant: "ghost",
313
+ size: "icon",
314
+ "aria-label": "Zoom out",
315
+ title: "Zoom out",
316
+ disabled: zoom <= MIN_ZOOM + .001,
317
+ onClick: () => zoomBy(-1),
318
+ children: /* @__PURE__ */ jsx(ZoomOut, {})
319
+ }),
320
+ /* @__PURE__ */ jsxs(Button, {
321
+ type: "button",
322
+ variant: "ghost",
323
+ size: "sm",
324
+ "aria-label": `${percent}%, fit to width`,
325
+ title: "Fit to width",
326
+ "aria-pressed": fitting,
327
+ className: cn("min-w-12 px-1.5 tabular-nums", fitting && "bg-primary/10 text-[var(--accent-text)] hover:text-[var(--accent-text)]"),
328
+ onClick: () => {
329
+ readPosition();
330
+ setZoomSetting({ mode: "fit" });
331
+ },
332
+ children: [percent, "%"]
333
+ }),
334
+ /* @__PURE__ */ jsxs("span", {
335
+ className: "sr-only",
336
+ "aria-live": "polite",
337
+ children: [
338
+ "Zoom ",
339
+ percent,
340
+ "%"
341
+ ]
342
+ }),
343
+ /* @__PURE__ */ jsx(Button, {
344
+ type: "button",
345
+ variant: "ghost",
346
+ size: "icon",
347
+ "aria-label": "Zoom in",
348
+ title: "Zoom in",
349
+ disabled: zoom >= MAX_ZOOM - .001,
350
+ onClick: () => zoomBy(1),
351
+ children: /* @__PURE__ */ jsx(ZoomIn, {})
352
+ }),
353
+ onDownload && /* @__PURE__ */ jsx(Button, {
354
+ type: "button",
355
+ variant: "ghost",
356
+ size: "icon",
357
+ "aria-label": `Download ${filename}`,
358
+ title: "Download",
359
+ onClick: onDownload,
360
+ children: /* @__PURE__ */ jsx(Download, {})
361
+ })
362
+ ]
363
+ })
364
+ ]
365
+ }), /* @__PURE__ */ jsx("div", {
366
+ ref: setScroller,
367
+ tabIndex: 0,
368
+ role: "region",
369
+ "aria-label": filename,
370
+ onScroll,
371
+ className: cn("relative min-h-0 flex-1 overflow-auto overscroll-contain bg-muted [scrollbar-gutter:stable]", focusRingInset),
372
+ children: firstPage ? /* @__PURE__ */ jsx("div", {
373
+ className: "flex w-max min-w-full flex-col items-center gap-3 p-3",
374
+ children: Array.from({ length: pageCount }, (_, index) => /* @__PURE__ */ jsx(PdfPage, {
375
+ doc,
376
+ pageNumber: index + 1,
377
+ pageCount,
378
+ zoom,
379
+ placeholder: firstPage,
380
+ root: scroller,
381
+ register: registerPage
382
+ }, index))
383
+ }) : /* @__PURE__ */ jsxs("div", {
384
+ role: "status",
385
+ className: "flex h-full min-h-[12rem] items-center justify-center text-sm text-muted-foreground",
386
+ children: [/* @__PURE__ */ jsx(LoaderCircle, {
387
+ "aria-hidden": "true",
388
+ className: "size-5 animate-spin motion-reduce:animate-none"
389
+ }), /* @__PURE__ */ jsxs("span", {
390
+ className: "sr-only",
391
+ children: [
392
+ "Loading ",
393
+ filename,
394
+ "…"
395
+ ]
396
+ })]
397
+ })
398
+ })] });
399
+ }
400
+ /**
401
+ * The current page number, editable. A typed number applies on Enter or when
402
+ * the field loses focus; Escape restores the current page.
403
+ */
404
+ function PageField({ current, total, onCommit }) {
405
+ const [draft, setDraft] = useState(null);
406
+ const commit = () => {
407
+ if (draft === null) return;
408
+ const page = Number.parseInt(draft, 10);
409
+ setDraft(null);
410
+ if (Number.isFinite(page)) onCommit(page);
411
+ };
412
+ return /* @__PURE__ */ jsxs("span", {
413
+ className: "flex items-center gap-1.5 text-sm text-muted-foreground",
414
+ children: [/* @__PURE__ */ jsx("input", {
415
+ type: "text",
416
+ inputMode: "numeric",
417
+ "aria-label": `Page, 1 to ${total}`,
418
+ value: draft ?? String(current),
419
+ onFocus: (event) => event.currentTarget.select(),
420
+ onChange: (event) => setDraft(event.currentTarget.value.replace(/\D/g, "")),
421
+ onBlur: commit,
422
+ onKeyDown: (event) => {
423
+ if (event.key === "Enter") commit();
424
+ if (event.key === "Escape") setDraft(null);
425
+ },
426
+ className: cn(fieldPresentation, "h-8 w-11 rounded-md border px-1 text-center text-base tabular-nums sm:text-sm")
427
+ }), /* @__PURE__ */ jsxs("span", {
428
+ "aria-hidden": "true",
429
+ className: "whitespace-nowrap tabular-nums",
430
+ children: ["/ ", total]
431
+ })]
432
+ });
433
+ }
434
+ function releaseCanvases(host) {
435
+ for (const canvas of host.querySelectorAll("canvas")) {
436
+ canvas.width = 0;
437
+ canvas.height = 0;
438
+ }
439
+ host.replaceChildren();
440
+ }
441
+ const PdfPage = memo(function PdfPage({ doc, pageNumber, pageCount, zoom, placeholder, root, register }) {
442
+ const [page, setPage] = useState(null);
443
+ const [near, setNear] = useState(false);
444
+ const [failed, setFailed] = useState(false);
445
+ const boxRef = useRef(null);
446
+ const hostRef = useRef(null);
447
+ const scale = zoom * PDF_TO_CSS;
448
+ useEffect(() => {
449
+ let active = true;
450
+ doc.getPage(pageNumber).then((loaded) => active && setPage(loaded), () => active && setFailed(true));
451
+ return () => {
452
+ active = false;
453
+ };
454
+ }, [doc, pageNumber]);
455
+ useEffect(() => {
456
+ const box = boxRef.current;
457
+ if (!box) return;
458
+ if (typeof IntersectionObserver === "undefined") {
459
+ setNear(true);
460
+ return;
461
+ }
462
+ const observer = new IntersectionObserver(([entry]) => setNear(entry?.isIntersecting ?? false), {
463
+ root,
464
+ rootMargin: "100% 0px"
465
+ });
466
+ observer.observe(box);
467
+ return () => observer.disconnect();
468
+ }, [root]);
469
+ useEffect(() => {
470
+ const host = hostRef.current;
471
+ if (!host || !page) return;
472
+ if (!near) {
473
+ releaseCanvases(host);
474
+ page.cleanup();
475
+ return;
476
+ }
477
+ const viewport = page.getViewport({ scale });
478
+ const ratio = Math.min(window.devicePixelRatio || 1, Math.sqrt(MAX_CANVAS_PIXELS / (viewport.width * viewport.height)));
479
+ const canvas = document.createElement("canvas");
480
+ canvas.width = Math.max(1, Math.floor(viewport.width * ratio));
481
+ canvas.height = Math.max(1, Math.floor(viewport.height * ratio));
482
+ canvas.style.cssText = "display:block;width:100%;height:100%";
483
+ canvas.setAttribute("aria-hidden", "true");
484
+ const task = page.render({
485
+ canvas,
486
+ viewport,
487
+ transform: ratio === 1 ? void 0 : [
488
+ ratio,
489
+ 0,
490
+ 0,
491
+ ratio,
492
+ 0,
493
+ 0
494
+ ]
495
+ });
496
+ let finished = false;
497
+ task.promise.then(() => {
498
+ finished = true;
499
+ releaseCanvases(host);
500
+ host.append(canvas);
501
+ setFailed(false);
502
+ }, (error) => {
503
+ finished = true;
504
+ canvas.width = 0;
505
+ canvas.height = 0;
506
+ if (error?.name !== "RenderingCancelledException") setFailed(true);
507
+ });
508
+ return () => {
509
+ if (!finished) task.cancel();
510
+ };
511
+ }, [
512
+ page,
513
+ near,
514
+ scale
515
+ ]);
516
+ useEffect(() => {
517
+ const host = hostRef.current;
518
+ return () => {
519
+ if (host) releaseCanvases(host);
520
+ };
521
+ }, []);
522
+ const box = useMemo(() => {
523
+ if (page) {
524
+ const { width, height } = page.getViewport({ scale });
525
+ return {
526
+ width,
527
+ height
528
+ };
529
+ }
530
+ return {
531
+ width: placeholder.width * zoom,
532
+ height: placeholder.height * zoom
533
+ };
534
+ }, [
535
+ page,
536
+ scale,
537
+ zoom,
538
+ placeholder
539
+ ]);
540
+ return /* @__PURE__ */ jsxs("div", {
541
+ ref: (element) => {
542
+ boxRef.current = element;
543
+ register(pageNumber, element);
544
+ },
545
+ role: "img",
546
+ "aria-label": `Page ${pageNumber} of ${pageCount}`,
547
+ "data-page-number": pageNumber,
548
+ style: {
549
+ width: Math.round(box.width),
550
+ height: Math.round(box.height)
551
+ },
552
+ className: "relative shrink-0 overflow-hidden bg-card shadow-sm ring-1 ring-border",
553
+ children: [/* @__PURE__ */ jsx("div", {
554
+ ref: hostRef,
555
+ className: "absolute inset-0"
556
+ }), failed && /* @__PURE__ */ jsxs("p", {
557
+ className: "absolute inset-0 flex items-center justify-center p-4 text-center text-sm text-muted-foreground",
558
+ children: [
559
+ "Page ",
560
+ pageNumber,
561
+ " could not be displayed."
562
+ ]
563
+ })]
564
+ });
565
+ });
566
+ //#endregion
567
+ export { PdfViewer };
package/dist/files.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import { FileNode, FileTree, FileTreeProps, FileTreeVisibilityOptions, filterFileTree } from "./files/file-tree.js";
2
2
  import { RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars } from "./files/rich-file-tree.js";
3
3
  import { CSV_PREVIEW_ROW_LIMIT, FilePreview, FilePreviewProps, parseCsv } from "./files/file-preview.js";
4
+ import { PdfViewer, PdfViewerProps } from "./files/pdf-viewer.js";
5
+ import { PdfViewerConfig, configurePdfViewer } from "./files/pdf-loader.js";
6
+ import { FileCard, FileCardProps, FileDetails, FileUploader } from "./files/file-card.js";
7
+ import { FileList, FileListItem, FileListProps } from "./files/file-list.js";
4
8
  import { FileTabData, FileTabs, FileTabsProps } from "./files/file-tabs.js";
5
9
  import { FileArtifactPane, FileArtifactPaneProps } from "./files/file-artifact-pane.js";
6
10
  import { FileFormat, FilePreviewKind, detectFileFormat, fileExtension, getCodeLanguage, getFormatLabel, getSyntaxLanguage, resolveFilePreviewKind } from "./files/file-format.js";
7
- export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, type FileArtifactPaneProps, type FileFormat, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind };
11
+ export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, type FileArtifactPaneProps, FileCard, type FileCardProps, type FileDetails, type FileFormat, FileList, type FileListItem, type FileListProps, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, type FileUploader, PdfViewer, type PdfViewerConfig, type PdfViewerProps, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, configurePdfViewer, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind };
package/dist/files.js CHANGED
@@ -1,7 +1,11 @@
1
1
  import { detectFileFormat, fileExtension, getCodeLanguage, getFormatLabel, getSyntaxLanguage, resolveFilePreviewKind } from "./files/file-format.js";
2
2
  import { FileTree, filterFileTree } from "./files/file-tree.js";
3
3
  import { RichFileTree } from "./files/rich-file-tree.js";
4
+ import { FileCard } from "./files/file-card.js";
5
+ import { configurePdfViewer } from "./files/pdf-loader.js";
6
+ import { PdfViewer } from "./files/pdf-viewer.js";
4
7
  import { CSV_PREVIEW_ROW_LIMIT, FilePreview, parseCsv } from "./files/file-preview.js";
8
+ import { FileList } from "./files/file-list.js";
5
9
  import { FileTabs } from "./files/file-tabs.js";
6
10
  import { FileArtifactPane } from "./files/file-artifact-pane.js";
7
- export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FilePreview, FileTabs, FileTree, RichFileTree, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind };
11
+ export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FileCard, FileList, FilePreview, FileTabs, FileTree, PdfViewer, RichFileTree, configurePdfViewer, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Button, ButtonProps, buttonVariants } from "./primitives/button.js";
2
2
  import { AuthHeader, AuthHeaderProps, GitHubLoginButton, GitHubLoginButtonProps, SessionUser, UserMenu, UserMenuProps } from "./auth/auth.js";
3
3
  import { LoginLayout, LoginLayoutProps } from "./auth/login-layout.js";
4
4
  import "./auth.js";
5
- import { SessionMessage } from "./types/message.js";
5
+ import { ChatAuthor, SessionMessage } from "./types/message.js";
6
6
  import { ReasoningPart, SessionPart, TextPart, ToolPart, ToolState, ToolStatus, ToolTime } from "./types/parts.js";
7
7
  import { AgentBranding } from "./types/branding.js";
8
8
  import { CustomToolRenderer, DisplayVariant, ToolDisplayMetadata } from "./types/tool-display.js";
@@ -13,6 +13,7 @@ import { ChatContainer, ChatContainerProps } from "./chat/chat-container.js";
13
13
  import { MessageList, MessageListProps } from "./chat/message-list.js";
14
14
  import { UserMessage, UserMessageProps } from "./chat/user-message.js";
15
15
  import { ChatMessage, ChatMessageProps, MessageRole } from "./chat/chat-message.js";
16
+ import { MessageAuthor, MessageAuthorProps, isViewerMessage } from "./chat/message-author.js";
16
17
  import { ThinkingIndicator, ThinkingIndicatorProps } from "./chat/thinking-indicator.js";
17
18
  import { ToolCallStatus, ToolCallType } from "./run/tool-call-step.js";
18
19
  import { FeedSegment, ToolCallData, ToolCallFeed, ToolCallFeedProps, parseToolEvent } from "./run/tool-call-feed.js";
@@ -22,6 +23,12 @@ import { ArtifactPane, ArtifactPaneProps } from "./primitives/artifact-pane.js";
22
23
  import { FileNode, FileTree, FileTreeProps, FileTreeVisibilityOptions, filterFileTree } from "./files/file-tree.js";
23
24
  import { RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars } from "./files/rich-file-tree.js";
24
25
  import { CSV_PREVIEW_ROW_LIMIT, FilePreview, FilePreviewProps, parseCsv } from "./files/file-preview.js";
26
+ import { PdfViewer, PdfViewerProps } from "./files/pdf-viewer.js";
27
+ import { PdfViewerConfig, configurePdfViewer } from "./files/pdf-loader.js";
28
+ import { CATEGORY_TONES, CategoryTone, TONE_CLASSES, Tone, ToneClasses, toneFor } from "./primitives/tone.js";
29
+ import { IconTile, IconTileProps, initialsOf } from "./primitives/icon-tile.js";
30
+ import { FileCard, FileCardProps, FileDetails, FileUploader } from "./files/file-card.js";
31
+ import { FileList, FileListItem, FileListProps } from "./files/file-list.js";
25
32
  import { FileTabData, FileTabs, FileTabsProps } from "./files/file-tabs.js";
26
33
  import { FileArtifactPane, FileArtifactPaneProps } from "./files/file-artifact-pane.js";
27
34
  import { FileFormat, FilePreviewKind, detectFileFormat, fileExtension, getCodeLanguage, getFormatLabel, getSyntaxLanguage, resolveFilePreviewKind } from "./files/file-format.js";
@@ -78,10 +85,8 @@ import { PageHeader, PageHeaderProps } from "./primitives/page-header.js";
78
85
  import { StatusPill, StatusPillProps, StatusTone } from "./primitives/status-pill.js";
79
86
  import { Alert, AlertDescription, AlertProps, AlertTitle, AlertTone } from "./primitives/alert.js";
80
87
  import { Pagination, PaginationProps } from "./primitives/pagination.js";
81
- import { CATEGORY_TONES, CategoryTone, TONE_CLASSES, Tone, ToneClasses, toneFor } from "./primitives/tone.js";
82
88
  import { Tag, TagProps } from "./primitives/tag.js";
83
89
  import { Chip, ChipProps } from "./primitives/chip.js";
84
- import { IconTile, IconTileProps, initialsOf } from "./primitives/icon-tile.js";
85
90
  import { Metric, MetricProps, MetricStrip, MetricStripProps } from "./primitives/metric-strip.js";
86
91
  import { FilterField, FilterFieldProps, Toolbar, ToolbarProps } from "./primitives/toolbar.js";
87
92
  import { Logo, LogoProps, TangleKnot } from "./primitives.js";
@@ -114,4 +119,4 @@ import { QuestionPreview, QuestionPreviewProps } from "./tool-previews/question-
114
119
  import { DiffPreview, DiffPreviewProps } from "./tool-previews/diff-preview.js";
115
120
  import { RedactedDocSegment, RedactedDocument, RedactedDocumentData, RedactedDocumentProps, RevealResult } from "./redaction/redacted-document.js";
116
121
  import "./redaction.js";
117
- export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTone, AppendUserMessageOptions, ApplySdkEventOptions, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, Checkbox, Chip, type ChipProps, CodeBlock, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CustomToolRenderer, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, type FileFormat, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, Heading, type HeadingProps, type HeadingVariant, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Pagination, type PaginationProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, type QuestionPreviewProps, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
122
+ export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTone, AppendUserMessageOptions, ApplySdkEventOptions, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CATEGORY_TONES, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, ChatAuthor, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, Checkbox, Chip, type ChipProps, CodeBlock, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CustomToolRenderer, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, FileCard, type FileCardProps, type FileDetails, type FileFormat, FileList, type FileListItem, type FileListProps, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, type FileUploader, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, Heading, type HeadingProps, type HeadingVariant, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownProps, MessageAuthor, type MessageAuthorProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Pagination, type PaginationProps, PdfViewer, type PdfViewerConfig, type PdfViewerProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QuestionPreview, type QuestionPreviewProps, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, configurePdfViewer, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, initialsOf, isStreamingAtom, isViewerMessage, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, toneFor, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };