@tangle-network/ui 11.25.0 → 11.27.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.
- package/CHANGELOG.md +12 -0
- package/README.md +22 -0
- package/dist/editor/editor-peers.js +1 -21
- package/dist/files/file-card.d.ts +30 -0
- package/dist/files/file-card.js +162 -0
- package/dist/files/file-list.d.ts +25 -0
- package/dist/files/file-list.js +88 -0
- package/dist/files/file-preview.js +16 -62
- package/dist/files/pdf-loader.d.ts +22 -0
- package/dist/files/pdf-loader.js +82 -0
- package/dist/files/pdf-viewer.d.ts +32 -0
- package/dist/files/pdf-viewer.js +567 -0
- package/dist/files.d.ts +5 -1
- package/dist/files.js +5 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.js +5 -1
- package/dist/lib/optional-peer.js +29 -0
- package/dist/markdown/markdown.d.ts +3 -2
- package/dist/markdown/markdown.js +70 -4
- package/dist/primitives.d.ts +2 -2
- package/package.json +7 -2
- package/src/editor/editor-peers.ts +3 -25
- package/src/files/file-artifact-pane.test.tsx +12 -2
- package/src/files/file-card.test.tsx +62 -0
- package/src/files/file-card.tsx +210 -0
- package/src/files/file-list.stories.tsx +121 -0
- package/src/files/file-list.test.tsx +81 -0
- package/src/files/file-list.tsx +167 -0
- package/src/files/file-preview.tsx +25 -94
- package/src/files/index.ts +9 -0
- package/src/files/pdf-loader.test.ts +130 -0
- package/src/files/pdf-loader.ts +169 -0
- package/src/files/pdf-viewer.stories.tsx +81 -0
- package/src/files/pdf-viewer.test.tsx +245 -0
- package/src/files/pdf-viewer.tsx +677 -0
- package/src/files/pdfjs-worker.d.ts +3 -0
- package/src/lib/optional-peer.ts +30 -0
- package/src/markdown/markdown.test.tsx +32 -3
- package/src/markdown/markdown.tsx +85 -4
|
@@ -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
|
@@ -23,6 +23,12 @@ import { ArtifactPane, ArtifactPaneProps } from "./primitives/artifact-pane.js";
|
|
|
23
23
|
import { FileNode, FileTree, FileTreeProps, FileTreeVisibilityOptions, filterFileTree } from "./files/file-tree.js";
|
|
24
24
|
import { RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars } from "./files/rich-file-tree.js";
|
|
25
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";
|
|
26
32
|
import { FileTabData, FileTabs, FileTabsProps } from "./files/file-tabs.js";
|
|
27
33
|
import { FileArtifactPane, FileArtifactPaneProps } from "./files/file-artifact-pane.js";
|
|
28
34
|
import { FileFormat, FilePreviewKind, detectFileFormat, fileExtension, getCodeLanguage, getFormatLabel, getSyntaxLanguage, resolveFilePreviewKind } from "./files/file-format.js";
|
|
@@ -79,10 +85,8 @@ import { PageHeader, PageHeaderProps } from "./primitives/page-header.js";
|
|
|
79
85
|
import { StatusPill, StatusPillProps, StatusTone } from "./primitives/status-pill.js";
|
|
80
86
|
import { Alert, AlertDescription, AlertProps, AlertTitle, AlertTone } from "./primitives/alert.js";
|
|
81
87
|
import { Pagination, PaginationProps } from "./primitives/pagination.js";
|
|
82
|
-
import { CATEGORY_TONES, CategoryTone, TONE_CLASSES, Tone, ToneClasses, toneFor } from "./primitives/tone.js";
|
|
83
88
|
import { Tag, TagProps } from "./primitives/tag.js";
|
|
84
89
|
import { Chip, ChipProps } from "./primitives/chip.js";
|
|
85
|
-
import { IconTile, IconTileProps, initialsOf } from "./primitives/icon-tile.js";
|
|
86
90
|
import { Metric, MetricProps, MetricStrip, MetricStripProps } from "./primitives/metric-strip.js";
|
|
87
91
|
import { FilterField, FilterFieldProps, Toolbar, ToolbarProps } from "./primitives/toolbar.js";
|
|
88
92
|
import { Logo, LogoProps, TangleKnot } from "./primitives.js";
|
|
@@ -115,4 +119,4 @@ import { QuestionPreview, QuestionPreviewProps } from "./tool-previews/question-
|
|
|
115
119
|
import { DiffPreview, DiffPreviewProps } from "./tool-previews/diff-preview.js";
|
|
116
120
|
import { RedactedDocSegment, RedactedDocument, RedactedDocumentData, RedactedDocumentProps, RevealResult } from "./redaction/redacted-document.js";
|
|
117
121
|
import "./redaction.js";
|
|
118
|
-
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, 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, 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, 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, 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 };
|
|
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 };
|