UNPKG

@llamaindex/ui

Version:

A comprehensive UI component library built with React, TypeScript, and Tailwind CSS for LlamaIndex applications

906 lines (900 loc) 33.9 kB
'use strict'; var chunkVN4NLXJ7_js = require('./chunk-VN4NLXJ7.js'); var chunkAETTG7GC_js = require('./chunk-AETTG7GC.js'); var chunkHKD7INX4_js = require('./chunk-HKD7INX4.js'); var chunkHNQYOC3W_js = require('./chunk-HNQYOC3W.js'); var chunkWGWQIMQI_js = require('./chunk-WGWQIMQI.js'); var chunkFIEMDG5B_js = require('./chunk-FIEMDG5B.js'); var chunkBOVUEAAQ_js = require('./chunk-BOVUEAAQ.js'); var chunkU3IWFKKJ_js = require('./chunk-U3IWFKKJ.js'); var chunkHK7TFVDA_js = require('./chunk-HK7TFVDA.js'); var chunk4E3IDRQJ_js = require('./chunk-4E3IDRQJ.js'); var react = require('react'); var lucideReact = require('lucide-react'); var Dropzone = require('react-dropzone'); var sonner = require('sonner'); var jsxRuntime = require('react/jsx-runtime'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var Dropzone__default = /*#__PURE__*/_interopDefault(Dropzone); // src/document-preview/files.ts function extractExtension(candidate) { if (!candidate) return null; const sanitized = candidate.split(/[?#]/)[0]; const segments = sanitized == null ? void 0 : sanitized.split("."); if (!segments || segments.length < 2) return null; const extension = segments.pop(); return extension ? extension.toLowerCase() : null; } function getFileTypeInfo(content) { var _a; if (content instanceof File) { const mimeType = content.type ? ((_a = content.type.split(";")[0]) == null ? void 0 : _a.trim().toLowerCase()) || null : null; const extension = content.name ? extractExtension(content.name) : null; return { mimeType, extension }; } if (typeof content === "string") { let mimeType = null; let extension = null; if (content.startsWith("data:")) { const mimeMatch = content.match(/^data:([^;]+)/); if (mimeMatch) { mimeType = mimeMatch[1].trim().toLowerCase(); } } try { const urlObj = new URL(content); extension = extractExtension(urlObj.pathname); if (!extension) { const contentDisposition = urlObj.searchParams.get( "response-content-disposition" ); if (contentDisposition) { const filenameMatch = contentDisposition.match( /filename[^;=]*=([^;]+)/ ); if (filenameMatch) { const filename = decodeURIComponent( filenameMatch[1].trim().replace(/^["']|["']$/g, "") ); extension = extractExtension(filename); } } } } catch (e) { extension = extractExtension(content); } return { mimeType, extension }; } return { mimeType: null, extension: null }; } function checkUrl(value) { if (value.startsWith("data:")) { return value; } try { new URL(value); return value; } catch (e) { if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) { return value; } return null; } } var resolveFileName = (content) => { if (content instanceof File) return content.name; if (typeof content === "string") { try { const urlObj = new URL(content); const segments = urlObj.pathname.split("/").filter(Boolean); if (segments.length === 0) return null; const last = decodeURIComponent(segments[segments.length - 1] || ""); if (!last || !last.includes(".")) return null; return last; } catch (error) { console.error(error); return null; } } return null; }; var downloadFile = (contentUrl, fileName) => { const link = document.createElement("a"); link.href = contentUrl; link.download = fileName != null ? fileName : "download"; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; function FileUpload({ className, heading = "File Upload", onContentChange, uploadDescription = "Upload file (drag or click)", uploadHelpText = "You can upload a file up to 315 MB", fileUrlPlaceholder = "Paste the file link here", footer, variant = "normal", accept, maxSize, maxFileCount = 1 }) { const [fileUrlInput, setFileUrlInput] = react.useState(""); const handleUrlSubmit = react.useCallback(() => { const trimmedUrl = fileUrlInput.trim(); if (!trimmedUrl) { return; } try { new URL(trimmedUrl); } catch (e) { sonner.toast.error("Please enter a valid URL."); return; } if (accept && typeof accept === "object") { const allowedExtensions = Object.values(accept).flat(); if (allowedExtensions.length > 0) { const urlPath = new URL(trimmedUrl).pathname.toLowerCase(); const lastDotIndex = urlPath.lastIndexOf("."); if (lastDotIndex === -1 || lastDotIndex === urlPath.length - 1) { sonner.toast.error("This file is not supported."); return; } const urlExtension = urlPath.slice(lastDotIndex).toLowerCase(); const isValidExtension = allowedExtensions.some( (ext) => ext.toLowerCase() === urlExtension ); if (!isValidExtension) { sonner.toast.error("This file is not supported."); return; } } } onContentChange(trimmedUrl); setFileUrlInput(""); }, [fileUrlInput, onContentChange, accept]); const defaultFooter = react.useMemo(() => { if (!accept || typeof accept !== "object") return null; const extensions = Object.values(accept).flat(); if (extensions.length === 0) return null; const formats = extensions.map((ext) => ext.slice(1).toUpperCase()).join(", "); return /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [ "Supported file formats: ", formats ] }); }, [accept]); const displayFooter = footer != null ? footer : defaultFooter; const onDrop = react.useCallback( (acceptedFiles, rejectedFiles) => { const tooManyFilesRejections = rejectedFiles.filter( ({ errors }) => errors.some((error) => error.code === "too-many-files") ); if (tooManyFilesRejections.length > 0) { sonner.toast.error( `Cannot upload more than ${maxFileCount} file${maxFileCount === 1 ? "" : "s"}` ); } const otherRejections = rejectedFiles.filter( ({ errors }) => !errors.some((error) => error.code === "too-many-files") ); if (otherRejections.length > 0) { otherRejections.forEach(({ file, errors }) => { const hasFileTypeError = errors.some( (error) => error.code === "file-invalid-type" ); const errorMessage = hasFileTypeError ? "File type is not supported" : errors.map((e) => e.message).join(", "); sonner.toast.error(`File ${file.name} was rejected: ${errorMessage}`); }); } if (acceptedFiles.length > 0) { onContentChange(acceptedFiles); } }, [maxFileCount, onContentChange] ); const dropzoneContent = /* @__PURE__ */ jsxRuntime.jsx( Dropzone__default.default, { onDrop, accept, maxSize, maxFiles: maxFileCount, multiple: maxFileCount > 1, children: ({ getRootProps, getInputProps, isDragActive }) => /* @__PURE__ */ jsxRuntime.jsxs( "div", chunk4E3IDRQJ_js.__spreadProps(chunk4E3IDRQJ_js.__spreadValues({}, getRootProps()), { className: chunkHK7TFVDA_js.cn( "flex min-h-[200px] cursor-pointer items-center justify-center rounded-lg border-2 border-dotted p-8 text-center transition-colors", isDragActive ? "bg-primary/5 border-primary" : "hover:border-primary/50 border-gray-300" ), children: [ /* @__PURE__ */ jsxRuntime.jsx("input", chunk4E3IDRQJ_js.__spreadValues({}, getInputProps())), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-4", children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full bg-gray-100", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "h-8 w-8" }) }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-gray-600", children: uploadDescription }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: uploadHelpText }) ] }) ] }) ) } ); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkHK7TFVDA_js.cn("w-full", className), children: [ variant === "normal" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx( "div", { className: "flex h-12 w-12 items-center justify-center rounded-full", style: { backgroundColor: "#F3F0FF", color: "#8B5CF6" }, children: /* @__PURE__ */ jsxRuntime.jsx(Logo, {}) } ) }), /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mb-8 text-sm font-semibold", children: heading }) ] }), variant === "small" ? dropzoneContent : /* @__PURE__ */ jsxRuntime.jsxs(chunkFIEMDG5B_js.Tabs, { defaultValue: "upload", children: [ /* @__PURE__ */ jsxRuntime.jsxs(chunkFIEMDG5B_js.TabsList, { className: "grid w-full grid-cols-2 rounded-none border-b border-gray-200 bg-transparent p-0", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkFIEMDG5B_js.TabsTrigger, { value: "upload", className: "rounded-none border-x-0 border-b-2 border-t-0 border-transparent bg-transparent text-xs font-semibold text-gray-500 shadow-none data-[state=active]:border-b-[#8B5CF6] data-[state=active]:text-[#8B5CF6] data-[state=active]:shadow-none", children: "Upload file" } ), /* @__PURE__ */ jsxRuntime.jsx( chunkFIEMDG5B_js.TabsTrigger, { value: "url", className: "rounded-none border-x-0 border-b-2 border-t-0 border-transparent bg-transparent text-xs font-semibold text-gray-500 shadow-none data-[state=active]:border-b-[#8B5CF6] data-[state=active]:text-[#8B5CF6] data-[state=active]:shadow-none", children: "File URL" } ) ] }), /* @__PURE__ */ jsxRuntime.jsx(chunkFIEMDG5B_js.TabsContent, { value: "upload", className: "mt-6", children: dropzoneContent }), /* @__PURE__ */ jsxRuntime.jsx(chunkFIEMDG5B_js.TabsContent, { value: "url", className: "mt-6", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-2 border-gray-200 p-8", children: /* @__PURE__ */ jsxRuntime.jsx( chunkBOVUEAAQ_js.Input, { type: "url", className: "w-full", placeholder: fileUrlPlaceholder, value: fileUrlInput, onChange: (event) => setFileUrlInput(event.target.value), onBlur: handleUrlSubmit } ) }) }) ] }), variant === "normal" && displayFooter ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 rounded-md bg-gray-100 p-4 text-center text-xs text-gray-500", children: displayFooter }) : null ] }); } function Logo() { return /* @__PURE__ */ jsxRuntime.jsxs( "svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [ /* @__PURE__ */ jsxRuntime.jsx( "path", { d: "M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" } ), /* @__PURE__ */ jsxRuntime.jsx( "path", { d: "M14 2V8H20", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" } ), /* @__PURE__ */ jsxRuntime.jsx( "path", { d: "M16 13H8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" } ), /* @__PURE__ */ jsxRuntime.jsx( "path", { d: "M16 17H8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" } ), /* @__PURE__ */ jsxRuntime.jsx( "path", { d: "M10 9H9H8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" } ) ] } ); } var FileObjectPreview = ({ fileName, contentUrl, onRemove }) => { const containerRef = react.useRef(null); const [scale, setScale] = react.useState(1); const onDownload = () => { downloadFile(contentUrl, fileName); }; const handleScaleChange = (newScale) => { setScale(newScale); }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full flex-col", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onDownload, scale, onScaleChange: handleScaleChange, onRemove } ), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx( "object", { ref: containerRef, data: contentUrl, className: "h-full w-full bg-white", style: { transform: `scale(${scale})`, transformOrigin: "top left" }, children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "p-4 text-center text-xs text-muted-foreground", children: [ "Your browser doesn't support file object preview.", " ", /* @__PURE__ */ jsxRuntime.jsx( "a", { href: contentUrl, target: "_blank", rel: "noopener noreferrer", className: "text-primary hover:underline", children: "Download File" } ) ] }) } ) }) ] }); }; var ImagePreview = ({ fileName, contentUrl, onRemove }) => { const [scale, setScale] = react.useState(1); const toggleFullscreen = () => { window.open(contentUrl, "_blank"); }; const onFullscreen = () => { toggleFullscreen(); }; const handleScaleChange = (newScale) => { setScale(newScale); }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full flex-col", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onFullscreen, scale, onScaleChange: handleScaleChange, onRemove, isOverlay: true } ), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx( "img", { src: contentUrl, alt: fileName != null ? fileName : "uploaded_file", className: "h-full w-full rounded-none object-contain p-4", style: { transform: `scale(${scale})`, transformOrigin: "top left" } } ) }) ] }); }; function TextPreview({ fileName, contentUrl, onRemove, className }) { const [fileContent, setFileContent] = react.useState(null); const [loadError, setLoadError] = react.useState(null); const [isLoading, setIsLoading] = react.useState(true); react.useEffect(() => { const fetchFileContent = async () => { try { setIsLoading(true); setLoadError(null); const response = await fetch(contentUrl); if (!response.ok) { throw new Error("Failed to fetch document content."); } const text = await response.text(); setFileContent(text); } catch (error) { console.error("[TextPreview] Error loading text content:", error); setLoadError( error instanceof Error ? error.message : "Failed to load text content" ); } finally { setIsLoading(false); } }; fetchFileContent(); }, [contentUrl]); const onDownload = () => { downloadFile(contentUrl, fileName); }; if (isLoading) { return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full flex-col", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onDownload, onRemove, isOverlay: true } ), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Loading text content..." }) }) ] }); } if (loadError) { return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full flex-col", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onDownload, onRemove } ), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 p-4", children: [ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: "Failed to load text content" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: loadError }), /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", onClick: onDownload, className: "text-sm text-primary hover:underline", children: "Download File" } ) ] }) ] }); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative flex h-full flex-col ${className != null ? className : ""}`, children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onDownload, onRemove, isOverlay: true } ), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-full w-full", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "absolute inset-0 whitespace-pre-wrap bg-gray-50/80 p-6 font-mono text-sm leading-relaxed text-gray-800", children: fileContent }) }) }) ] }); } function UnsupportedPreview({ fileName, contentUrl, onRemove }) { const handleDownload = () => { window.open(contentUrl, "_blank"); }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full flex-col", children: [ /* @__PURE__ */ jsxRuntime.jsx( chunkAETTG7GC_js.FileToolbar, { fileName, onDownload: handleDownload, onRemove } ), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full flex-1 overflow-auto bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "p-4 text-center text-xs text-muted-foreground", children: [ "This file type is not supported for preview. You can download to view it.", " ", /* @__PURE__ */ jsxRuntime.jsx( "a", { href: contentUrl, target: "_blank", rel: "noopener noreferrer", className: "text-primary hover:underline", children: "Download File" } ) ] }) }) ] }); } var SelectFileBar = ({ files, currentIndex, onSelect, onRemove, onToggleFileUpload, isFileUploadExpanded = false }) => { const makeButtonHandler = (handler) => (event) => { event.stopPropagation(); handler(); }; return /* @__PURE__ */ jsxRuntime.jsxs(chunkWGWQIMQI_js.ScrollArea, { className: "h-10 border-b", viewportClassName: "flex items-center", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 px-6", children: [ onToggleFileUpload && /* @__PURE__ */ jsxRuntime.jsx(chunkU3IWFKKJ_js.Button, { size: "xs", onClick: onToggleFileUpload, children: isFileUploadExpanded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "size-4" }), "Hide upload" ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.File, { className: "size-4" }), "Add files" ] }) }), files.map(({ fileName, index }) => { const displayName = fileName != null ? fileName : `File ${index + 1}`; const key = `${index}-${fileName != null ? fileName : `file-${index}`}`; const isCurrent = index === currentIndex; return /* @__PURE__ */ jsxRuntime.jsxs( "div", { role: "button", tabIndex: 0, className: chunkHK7TFVDA_js.cn( chunkU3IWFKKJ_js.buttonVariants({ variant: "outline", size: "xs" }), "flex shrink-0 items-center gap-2 border-border px-3 hover:bg-muted cursor-pointer", isCurrent ? "bg-accent" : "bg-white" ), onClick: () => onSelect(index), onKeyDown: (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onSelect(index); } }, children: [ /* @__PURE__ */ jsxRuntime.jsx( "span", { className: `whitespace-nowrap text-xs ${isCurrent ? "text-accent-foreground" : "text-muted-foreground"}`, children: displayName } ), /* @__PURE__ */ jsxRuntime.jsx(chunkHNQYOC3W_js.ToolTipper, { content: "Remove file", children: /* @__PURE__ */ jsxRuntime.jsx( chunkU3IWFKKJ_js.Button, { variant: "ghost", onClick: makeButtonHandler(() => onRemove(index)), className: "size-5 shrink-0 p-0", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-3" }) } ) }) ] }, key ); }) ] }), /* @__PURE__ */ jsxRuntime.jsx(chunkWGWQIMQI_js.ScrollBar, { orientation: "horizontal" }) ] }); }; function UploadSkeleton() { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full flex-col space-y-3 p-6", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntime.jsx(chunkVN4NLXJ7_js.Skeleton, { className: "h-4 w-full" }), /* @__PURE__ */ jsxRuntime.jsx(chunkVN4NLXJ7_js.Skeleton, { className: "h-4 w-5/6" }), /* @__PURE__ */ jsxRuntime.jsx(chunkVN4NLXJ7_js.Skeleton, { className: "h-4 w-4/5" }), /* @__PURE__ */ jsxRuntime.jsx(chunkVN4NLXJ7_js.Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ jsxRuntime.jsx(chunkVN4NLXJ7_js.Skeleton, { className: "h-4 w-2/3" }), i < 7 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2" }) ] }, i)) }); } var MAX_FILE_COUNT = 20; var DEFAULT_MAX_PAGES = 25; function PdfPreviewWrapper({ fileName, contentUrl, onRemove, highlights, maxPages, maxPagesWarning }) { const effectiveMaxPages = maxPages != null ? maxPages : DEFAULT_MAX_PAGES; const effectiveMaxPagesWarning = maxPagesWarning != null ? maxPagesWarning : `The document has more than ${effectiveMaxPages} pages. Limiting the preview to ${effectiveMaxPages} to increase performance.`; return /* @__PURE__ */ jsxRuntime.jsx( chunkHKD7INX4_js.PdfPreview, { url: contentUrl, onRemove, fileName, highlights, toolbarClassName: "[&>div]:border-t-0 [&>div]:border-r-0 [&>div]:border-l-0", maxPages: effectiveMaxPages, maxPagesWarning: effectiveMaxPagesWarning } ); } var DEFAULT_MIME_TYPE_MAP = { "application/pdf": PdfPreviewWrapper, "text/plain": TextPreview, "text/markdown": TextPreview, "application/json": TextPreview, "image/jpeg": ImagePreview, "image/jpg": ImagePreview, "image/png": ImagePreview, "image/gif": ImagePreview, "image/bmp": ImagePreview, "image/tiff": ImagePreview, "image/x-icon": ImagePreview, "image/vnd.microsoft.icon": ImagePreview, "image/webp": ImagePreview, "application/vnd.openxmlformats-officedocument.wordprocessingml.document": UnsupportedPreview, "application/vnd.ms-powerpoint": UnsupportedPreview, "application/vnd.openxmlformats-officedocument.presentationml.presentation": UnsupportedPreview }; var DEFAULT_EXTENSION_MAP = { pdf: PdfPreviewWrapper, txt: TextPreview, md: TextPreview, json: TextPreview, jpg: ImagePreview, jpeg: ImagePreview, png: ImagePreview, gif: ImagePreview, bmp: ImagePreview, tiff: ImagePreview, ico: ImagePreview, webp: ImagePreview, docx: UnsupportedPreview, ppt: UnsupportedPreview, pptx: UnsupportedPreview }; var toArray = (value) => { if (Array.isArray(value)) { return value; } if (value === null || value === void 0) { return []; } return [value]; }; function DocumentPreviewItem({ value, onRemove, allowRemoval = true, fileName, highlights, previews, maxPages, maxPagesWarning }) { const [blobUrl, setBlobUrl] = react.useState(null); react.useEffect(() => { if (!(value instanceof File)) { setBlobUrl(null); return; } const objectUrl = URL.createObjectURL(value); setBlobUrl(objectUrl); return () => { URL.revokeObjectURL(objectUrl); }; }, [value]); const resolvedUrl = react.useMemo(() => { if (value instanceof File) return blobUrl; if (typeof value === "string") { return checkUrl(value); } return null; }, [value, blobUrl]); if (!resolvedUrl) { return /* @__PURE__ */ jsxRuntime.jsx(UploadSkeleton, {}); } const { mimeType, extension } = getFileTypeInfo(value); const removalHandler = allowRemoval ? onRemove : void 0; const mimeTypeMap = chunk4E3IDRQJ_js.__spreadValues(chunk4E3IDRQJ_js.__spreadValues({}, DEFAULT_MIME_TYPE_MAP), previews == null ? void 0 : previews.mimeTypes); const extensionMap = chunk4E3IDRQJ_js.__spreadValues(chunk4E3IDRQJ_js.__spreadValues({}, DEFAULT_EXTENSION_MAP), previews == null ? void 0 : previews.extensions); let PreviewComponent; if (mimeType && mimeTypeMap[mimeType]) { PreviewComponent = mimeTypeMap[mimeType]; } else if (extension && extensionMap[extension]) { PreviewComponent = extensionMap[extension]; } if (!PreviewComponent) { PreviewComponent = FileObjectPreview; } const previewContent = /* @__PURE__ */ jsxRuntime.jsx( PreviewComponent, { fileName, contentUrl: resolvedUrl, onRemove: removalHandler, highlights, maxPages, maxPagesWarning } ); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative size-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col", children: previewContent }) }); } function DocumentPreview(props) { var _a, _b, _c, _d; const { isLoading = false, heading, onRemove, allowRemoval = true, allowMultiple = false, className = "h-full w-full flex-1", footer, accept, previews } = props; const [previewIndex, setPreviewIndexState] = react.useState(null); const [isFileUploadExpanded, setIsFileUploadExpanded] = react.useState(false); if (isLoading) { return /* @__PURE__ */ jsxRuntime.jsx(UploadSkeleton, {}); } const multiProps = allowMultiple ? props : null; const singleProps = allowMultiple ? null : props; const multiOnChange = multiProps == null ? void 0 : multiProps.onChange; const multiValues = (_a = multiProps == null ? void 0 : multiProps.value) != null ? _a : []; const normalizedValues = allowMultiple ? multiValues.map((item) => item.content) : toArray((_b = singleProps == null ? void 0 : singleProps.value) != null ? _b : null); const normalizedFileNames = allowMultiple ? multiValues.map((item) => { var _a2; return (_a2 = item.fileName) != null ? _a2 : resolveFileName(item.content); }) : toArray((_c = singleProps == null ? void 0 : singleProps.value) != null ? _c : null).map( (content) => { var _a2; return (_a2 = singleProps == null ? void 0 : singleProps.fileName) != null ? _a2 : resolveFileName(content); } ); const setPreviewIndex = (index) => { setPreviewIndexState(index); if (allowMultiple && (multiProps == null ? void 0 : multiProps.onPreviewChange)) { multiProps.onPreviewChange(index); } }; const handleContentChange = (newContent) => { var _a2, _b2, _c2, _d2; if (!allowMultiple) { if (Array.isArray(newContent)) { (_b2 = singleProps == null ? void 0 : singleProps.onChange) == null ? void 0 : _b2.call(singleProps, (_a2 = newContent[0]) != null ? _a2 : null); return; } (_c2 = singleProps == null ? void 0 : singleProps.onChange) == null ? void 0 : _c2.call(singleProps, newContent); return; } const newContents = Array.isArray(newContent) ? newContent : [newContent]; if (newContents.length === 0) return; const newItems = [ ...multiValues, ...newContents.map((content) => ({ content })) ]; void ((_d2 = multiProps == null ? void 0 : multiProps.onChange) == null ? void 0 : _d2.call(multiProps, newItems)); setPreviewIndex(newItems.length - 1); }; const handleRemoveAt = (index) => { var _a2, _b2, _c2; if (!allowRemoval) return; if (!allowMultiple) { const nextValues = normalizedValues.filter( (_, itemIndex) => itemIndex !== index ); (_b2 = singleProps == null ? void 0 : singleProps.onChange) == null ? void 0 : _b2.call( singleProps, nextValues.length ? (_a2 = nextValues[0]) != null ? _a2 : null : null ); (_c2 = singleProps == null ? void 0 : singleProps.onRemove) == null ? void 0 : _c2.call(singleProps); return; } const nextItems = multiValues.filter((_, itemIndex) => itemIndex !== index); onRemove == null ? void 0 : onRemove(index); void (multiOnChange == null ? void 0 : multiOnChange(nextItems)); if (previewIndex !== null) { if (previewIndex === index) { setPreviewIndex(nextItems.length > 0 ? nextItems.length - 1 : null); } else if (previewIndex > index) { setPreviewIndex(previewIndex - 1); } } }; const handleSelectAt = (index) => { if (!allowMultiple) return; setPreviewIndex(index); }; const renderFileUpload = (options) => { var _a2; const maxFileCount2 = allowMultiple ? Math.max(0, MAX_FILE_COUNT - normalizedValues.length) : 1; if (maxFileCount2 === 0) { return null; } return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-start px-20 py-8", children: /* @__PURE__ */ jsxRuntime.jsx( FileUpload, { className: "max-w-4xl", heading: heading != null ? heading : "File Upload", variant: (_a2 = options == null ? void 0 : options.variant) != null ? _a2 : "normal", onContentChange: handleContentChange, maxFileCount: maxFileCount2, maxSize: 1024 * 1024 * 315, uploadDescription: `Upload ${maxFileCount2 > 1 ? `up to ${maxFileCount2} files` : "file"} (drag or click)`, uploadHelpText: "You can upload files up to 315 MB", footer, accept } ) }); }; if (normalizedValues.length === 0) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: renderFileUpload() }); } const lastIndex = normalizedValues.length - 1; const currentPreviewIndex = previewIndex !== null ? previewIndex : lastIndex; const currentValue = normalizedValues[currentPreviewIndex]; const currentFileName = (_d = normalizedFileNames[currentPreviewIndex]) != null ? _d : void 0; const maxFileCount = allowMultiple ? Math.max(0, MAX_FILE_COUNT - normalizedValues.length) : 1; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkHK7TFVDA_js.cn("flex flex-col", className), children: [ allowMultiple && /* @__PURE__ */ jsxRuntime.jsx( SelectFileBar, { files: normalizedValues.map((_, index) => { var _a2; return { fileName: (_a2 = normalizedFileNames[index]) != null ? _a2 : null, index }; }), currentIndex: currentPreviewIndex, onSelect: handleSelectAt, onRemove: handleRemoveAt, onToggleFileUpload: maxFileCount > 0 ? () => setIsFileUploadExpanded((prev) => !prev) : void 0, isFileUploadExpanded } ), allowMultiple && isFileUploadExpanded && renderFileUpload({ variant: "small" }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col overflow-y-auto", children: currentValue && /* @__PURE__ */ jsxRuntime.jsx( DocumentPreviewItem, { value: currentValue, fileName: allowMultiple ? void 0 : currentFileName, onRemove: () => handleRemoveAt(currentPreviewIndex), allowRemoval: allowRemoval && !allowMultiple, highlights: props.highlights, previews, maxPages: props.maxPages, maxPagesWarning: props.maxPagesWarning } ) }) ] }); } exports.DocumentPreview = DocumentPreview;