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