@imparth/react-file-viewer
Version:
Extendable file viewer for web that preview images, pdf and text files via file object or web url
116 lines (115 loc) • 4.7 kB
JavaScript
import React, { useState, useEffect } from "react";
const invalidFileExtensions = [
"exe",
"scr",
"msi",
"bat",
"sh",
"cmd",
"com",
"dll",
"pif",
"vb",
"vbe",
"vbs",
"ws",
"wsc",
"wsf",
"wsh",
];
const defaultStyles = {
container: {
flexDirection: "column",
backgroundColor: "#fff",
borderRadius: "10px",
boxShadow: "0 1px 2px 0 rgb(0 0 0 / 10%)",
padding: "auto",
},
svg: {
position: "relative",
userSelect: "none",
display: "inline-block",
height: "42px",
fill: "grey",
},
noPreviewText: {
color: "rgb(128, 144, 162)",
fontSize: "12px",
textAlign: "center",
},
};
function getFileUrl({ type, url, file, onError, }) {
let resolvedUrl = url || "";
if (type === "file" && file) {
try {
const fileExtension = file.name.split(".").pop()?.toLowerCase();
if (file.type === "" ||
invalidFileExtensions.includes(fileExtension || "") ||
(file.type.includes("application") && file.type !== "application/pdf")) {
const msg = `${file.name} is not a valid file.`;
if (onError) {
onError(msg);
}
else {
alert(msg);
}
}
else {
resolvedUrl = URL.createObjectURL(file);
}
}
catch (err) {
if (onError) {
onError(err);
}
else {
alert(err);
}
}
}
return {
url: resolvedUrl,
preview: resolvedUrl !== "" ? "imgPreview" : "noURL",
};
}
const FilePreview = ({ type = "url", file = null, url = "", width = "424px", height = "424px", invalidExtensions = invalidFileExtensions, styles = defaultStyles, onError, }) => {
const [state, setState] = useState(() => {
const { url: initialUrl, preview } = getFileUrl({ type, url, file, onError });
return {
preview,
type,
file,
url: initialUrl,
};
});
const objPreviewStyle = {
width: "100%",
height,
};
useEffect(() => {
const { url: newUrl, preview } = getFileUrl({ type, url, file, onError });
setState({
preview,
type,
file,
url: newUrl,
});
}, [type, file, url, onError]);
const { preview, url: resolvedUrl } = state;
return (React.createElement("div", { style: {
...styles.container,
width,
} }, preview === "imgPreview" ? (React.createElement("img", { src: resolvedUrl, onError: () => setState((prev) => ({ ...prev, preview: "docPreview" })), style: objPreviewStyle, alt: "Preview" })) : preview === "docPreview" ? (React.createElement("object", { style: {
width: "100%",
objectFit: "cover",
objectPosition: "center",
aspectRatio: "4/3",
}, data: resolvedUrl })) : (React.createElement("div", { style: { ...styles.container, padding: "5em" } },
React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 7 } },
React.createElement("svg", { color: "grey", viewBox: "0 0 24 24", style: styles.svg },
React.createElement("g", null,
React.createElement("path", { d: "M2.25 24A2.252 2.252 0 0 1 0 21.75V2.25A2.252 2.252 0 0 1 2.25 0h19.5A2.252 2.252 0 0 1 24 2.25v19.5A2.252 2.252 0 0 1 21.75 24H2.25zm0-22.5a.75.75 0 0 0-.75.75v19.5c0 .414.336.75.75.75h19.5a.75.75 0 0 0 .75-.75V2.25a.75.75 0 0 0-.75-.75H2.25z" }),
React.createElement("path", { d: "M16.5 11.25c-2.068 0-3.75-1.682-3.75-3.75s1.682-3.75 3.75-3.75 3.75 1.682 3.75 3.75-1.682 3.75-3.75 3.75zm0-6c-1.241 0-2.25 1.009-2.25 2.25s1.009 2.25 2.25 2.25 2.25-1.009 2.25-2.25-1.009-2.25-2.25-2.25zM15.655 19.858a.746.746 0 0 1-.699-.478 7.507 7.507 0 0 0-1.132-1.96l-.021-.026a7.364 7.364 0 0 0-3.819-2.495 7.485 7.485 0 0 0-1.979-.268 7.442 7.442 0 0 0-3.674.98.754.754 0 0 1-1.023-.281.751.751 0 0 1 .28-1.023 8.936 8.936 0 0 1 4.415-1.177 8.97 8.97 0 0 1 2.376.322 8.892 8.892 0 0 1 4.1 2.441 5.243 5.243 0 0 1 2.902-.879c1.219 0 2.402.427 3.331 1.204a.743.743 0 0 1 .266.509.743.743 0 0 1-.172.548.747.747 0 0 1-1.056.094 3.699 3.699 0 0 0-2.369-.855c-.692 0-1.375.195-1.957.555a8.833 8.833 0 0 1 .928 1.769.747.747 0 0 1-.697 1.02z" }))),
React.createElement("span", { style: styles.noPreviewText }, "No Preview Available"))))));
};
export default FilePreview;