@llamaindex/ui
Version:
A comprehensive UI component library built with React, TypeScript, and Tailwind CSS for LlamaIndex applications
214 lines (211 loc) • 6.74 kB
JavaScript
import { BoundingBoxOverlay } from './chunk-XIANQWOZ.mjs';
import { Card } from './chunk-2QBCG3BE.mjs';
import { memo, lazy, Suspense, useState, useEffect, useRef } from 'react';
import { jsx, jsxs } from 'react/jsx-runtime';
import { getFileApiV1FilesIdGet, readFileContentApiV1FilesIdContentGet } from 'llama-cloud-services/api';
import { Clock, XCircle } from 'lucide-react';
function ImagePreview({
src,
boundingBoxes = [],
onBoundingBoxClick,
onImageLoad
}) {
const imgRef = useRef(null);
const [imageDimensions, setImageDimensions] = useState({
width: 0,
height: 0
});
const handleImageLoad = () => {
if (imgRef.current) {
const { naturalWidth, naturalHeight } = imgRef.current;
setImageDimensions({ width: naturalWidth, height: naturalHeight });
onImageLoad == null ? void 0 : onImageLoad({ width: naturalWidth, height: naturalHeight });
}
};
return /* @__PURE__ */ jsxs(
"div",
{
style: {
position: "relative",
display: "inline-block",
border: "1px solid #eee"
},
children: [
/* @__PURE__ */ jsx(
"img",
{
ref: imgRef,
src,
alt: "Preview",
onLoad: handleImageLoad,
style: {
maxWidth: "100%",
height: "auto"
}
}
),
/* @__PURE__ */ jsx(
BoundingBoxOverlay,
{
boundingBoxes,
zoom: 1,
containerWidth: imageDimensions.width,
containerHeight: imageDimensions.height,
onBoundingBoxClick
}
)
]
}
);
}
function useFileData(fileId, mockData) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchFileData = async () => {
var _a, _b, _c;
if (!fileId) {
setLoading(false);
return;
}
if (mockData) {
setData(mockData);
setLoading(false);
return;
}
setLoading(true);
setError(null);
try {
const getFilePromise = getFileApiV1FilesIdGet({
headers: {
"Content-Type": "application/json"
},
path: {
id: fileId
}
});
const getFileContentPromise = readFileContentApiV1FilesIdContentGet({
headers: {
"Content-Type": "application/json"
},
path: {
id: fileId
}
});
const fileResponse = await getFilePromise;
const contentResponse = await getFileContentPromise;
const fileType = (_a = fileResponse.data) == null ? void 0 : _a.file_type;
const url = (_b = contentResponse.data) == null ? void 0 : _b.url;
setData({
url,
name: (_c = fileResponse.data) == null ? void 0 : _c.name,
type: fileType || void 0
});
} catch (err) {
console.error("Error fetching file data:", err);
setError(
err instanceof Error ? err.message : "Failed to load file data"
);
} finally {
setLoading(false);
}
};
fetchFileData();
}, [fileId, mockData]);
return { data, loading, error };
}
var PdfPreview = memo(
({
url,
highlight,
fileName,
toolbarClassName,
onRemove
}) => {
if (typeof window === "undefined") {
return null;
}
const PdfPreviewLazy = lazy(
() => import('./pdf-preview-impl-2GSZCJCJ.mjs').then((module) => ({
default: module.PdfPreviewImpl
}))
);
return /* @__PURE__ */ jsx(
Suspense,
{
fallback: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center p-8", children: [
/* @__PURE__ */ jsx(Clock, { className: "h-6 w-6 animate-pulse text-gray-400" }),
/* @__PURE__ */ jsx("span", { className: "ml-2 text-gray-600", children: "Loading PDF viewer..." })
] }),
children: /* @__PURE__ */ jsx(
PdfPreviewLazy,
{
url,
highlight,
fileName,
toolbarClassName,
onRemove
}
)
}
);
}
);
function getFileType(fileType) {
if (!fileType) return "unsupported";
const type = fileType.toLowerCase();
if (type.includes("image/") || type.includes("png") || type.includes("jpg") || type.includes("jpeg") || type.includes("gif") || type.includes("webp")) {
return "image";
}
if (type.includes("pdf")) {
return "pdf";
}
return "unsupported";
}
function FilePreview({
onBoundingBoxClick,
highlight,
fileId,
mockData
}) {
const { data, loading, error } = useFileData(fileId || "", mockData);
const fileName = (data == null ? void 0 : data.name) || "";
const fileType = getFileType(data == null ? void 0 : data.type) || "unsupported";
if (loading) {
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx("div", { className: "flex h-32 items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
/* @__PURE__ */ jsx(Clock, { className: "h-8 w-8 animate-spin mx-auto mb-2" }),
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Loading file..." })
] }) }) });
}
if (error) {
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx("div", { className: "flex h-32 items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
/* @__PURE__ */ jsx(XCircle, { className: "h-8 w-8 text-red-500 mx-auto mb-2" }),
/* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
"Error loading file: ",
error
] })
] }) }) });
}
if (fileType === "unsupported") {
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
"Unsupported file type: ",
fileName
] }) }) });
}
if (fileType === "image") {
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ jsx(
ImagePreview,
{
src: (data == null ? void 0 : data.url) || "",
boundingBoxes: [],
onBoundingBoxClick: (box) => onBoundingBoxClick == null ? void 0 : onBoundingBoxClick(box, 1)
}
) });
}
if (fileType === "pdf") {
return /* @__PURE__ */ jsx(PdfPreview, { url: (data == null ? void 0 : data.url) || "", highlight });
}
return null;
}
export { FilePreview, PdfPreview, useFileData };