UNPKG

@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
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 };