@monolith-forensics/monolith-ui 1.2.50 → 1.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
1
  export type File = {
2
2
  name: string;
3
- ext: string;
4
- size: number;
3
+ ext?: string;
4
+ size?: number;
5
5
  type?: string;
6
- url: string;
6
+ url?: string;
7
7
  };
8
8
  export declare const FileViewer: React.FC<{
9
9
  file: File;
10
10
  open: boolean;
11
+ isPending?: boolean;
11
12
  onClose: () => void;
12
13
  }>;
@@ -5,6 +5,7 @@ import { FloatingPortal } from "@floating-ui/react";
5
5
  import { DownloadIcon, XIcon, ZoomInIcon, ZoomOutIcon } from "lucide-react";
6
6
  import Button from "../Button";
7
7
  import { useState } from "react";
8
+ import Loader from "../Loader";
8
9
  var ViewerTypes;
9
10
  (function (ViewerTypes) {
10
11
  ViewerTypes["Office"] = "office";
@@ -151,7 +152,7 @@ const resolveViewerType = (file) => {
151
152
  }
152
153
  return ViewerTypes.Code;
153
154
  };
154
- export const FileViewer = ({ file, open, onClose }) => {
155
+ export const FileViewer = ({ file, open, isPending, onClose }) => {
155
156
  const [zoomFactor, setZoomFactor] = useState(1);
156
157
  if (!open)
157
158
  return null;
@@ -163,5 +164,12 @@ export const FileViewer = ({ file, open, onClose }) => {
163
164
  return (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsxs(StyledContainer, { className: "mfui-FileViewer", children: [_jsxs(StyledMenu, { className: "FileViewer-menu", children: [_jsx(Button, { variant: "text", onClick: () => {
164
165
  onClose === null || onClose === void 0 ? void 0 : onClose();
165
166
  setZoomFactor(1);
166
- }, children: _jsx(XIcon, { size: 18 }) }), _jsx("div", { children: file.name }), _jsxs(StyledActionsMenu, { children: [ZoomableViewerTypes.includes(viewerType) && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "text", children: _jsx(ZoomInIcon, { size: 18, onClick: () => setZoomFactor((prev) => prev * 1.1) }) }), _jsx(Button, { variant: "text", children: _jsx(ZoomOutIcon, { size: 18, onClick: () => setZoomFactor((prev) => prev * 0.9) }) })] })), _jsx("a", { href: file.url, download: file.name, children: _jsx(Button, { variant: "text", children: _jsx(DownloadIcon, { size: 18 }) }) })] })] }), _jsxs(StyledInnerContainer, { onClick: handleBackgroundClick, "data-type": viewerType, children: [viewerType === ViewerTypes.PDF && (_jsx(PdfViewer, { file: file, zoomFactor: zoomFactor })), viewerType === ViewerTypes.Image && (_jsx(ImageViewer, { file: file, zoomFactor: zoomFactor })), viewerType === ViewerTypes.Video && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor })), viewerType === ViewerTypes.Audio && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor })), viewerType === ViewerTypes.Office && _jsx(OfficeViewer, { file: file }), viewerType === ViewerTypes.Text && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor })), viewerType === ViewerTypes.Code && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor }))] })] }) }));
167
+ }, children: _jsx(XIcon, { size: 18 }) }), _jsx("div", { children: file.name }), file.url ? (_jsxs(StyledActionsMenu, { children: [ZoomableViewerTypes.includes(viewerType) && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "text", children: _jsx(ZoomInIcon, { size: 18, onClick: () => setZoomFactor((prev) => prev * 1.1) }) }), _jsx(Button, { variant: "text", children: _jsx(ZoomOutIcon, { size: 18, onClick: () => setZoomFactor((prev) => prev * 0.9) }) })] })), _jsx("a", { href: file.url, download: file.name, children: _jsx(Button, { variant: "text", children: _jsx(DownloadIcon, { size: 18 }) }) })] })) : (_jsx("div", {}) // used as placeholder for spacing and alignment
168
+ )] }), file.url ? (_jsxs(StyledInnerContainer, { onClick: handleBackgroundClick, "data-type": viewerType, children: [viewerType === ViewerTypes.PDF && (_jsx(PdfViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Image && (_jsx(ImageViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Video && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Audio && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Office && (_jsx(OfficeViewer, { file: file, isPending: isPending })), viewerType === ViewerTypes.Text && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Code && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending }))] })) : (_jsx(StyledInnerContainer, { children: _jsxs("div", { style: {
169
+ margin: "auto",
170
+ display: "flex",
171
+ gap: "10px",
172
+ flexDirection: "column",
173
+ alignItems: "center",
174
+ }, children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading File..." })] }) }))] }) }));
167
175
  };
@@ -2,4 +2,5 @@ import { File } from "../FileViewer";
2
2
  export declare const CodeViewer: React.FC<{
3
3
  file: File;
4
4
  zoomFactor?: number;
5
+ isPending?: boolean;
5
6
  }>;
@@ -27,6 +27,8 @@ const resolveLanguage = (file) => __awaiter(void 0, void 0, void 0, function* ()
27
27
  return null;
28
28
  });
29
29
  const getFileData = (file) => __awaiter(void 0, void 0, void 0, function* () {
30
+ if (!file.url)
31
+ return "";
30
32
  const response = yield fetch(file.url);
31
33
  const text = yield response.text();
32
34
  return text;
@@ -62,7 +64,7 @@ const StyledLoader = styled.div `
62
64
  align-items: center;
63
65
  gap: 10px;
64
66
  `;
65
- export const CodeViewer = ({ file, zoomFactor }) => {
67
+ export const CodeViewer = ({ file, zoomFactor, isPending }) => {
66
68
  const [CodeMirror, setCodeMirror] = useState(null);
67
69
  const [language, setLanguage] = useState(null);
68
70
  const [theme, setTheme] = useState(null);
@@ -93,6 +95,9 @@ export const CodeViewer = ({ file, zoomFactor }) => {
93
95
  if (CodeMirror) {
94
96
  extensions.push(CodeMirror.EditorView.lineWrapping);
95
97
  }
98
+ if (isPending) {
99
+ return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] }));
100
+ }
96
101
  return (_jsxs(StyledContainer, { zoomFactor: zoomFactor, children: [loading && (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading File..." })] })), !loading && (_jsx(CodeMirror.default, { value: query.data || "", theme: theme, extensions: extensions, readOnly: true, editable: false, onClick: (event) => {
97
102
  event.stopPropagation();
98
103
  } }))] }));
@@ -2,4 +2,5 @@ import { File } from "../FileViewer";
2
2
  export declare const ImageViewer: React.FC<{
3
3
  file: File;
4
4
  zoomFactor?: number;
5
+ isPending?: boolean;
5
6
  }>;
@@ -24,7 +24,7 @@ const StyledLoader = styled.div `
24
24
  align-items: center;
25
25
  gap: 10px;
26
26
  `;
27
- export const ImageViewer = ({ file, zoomFactor = 1, }) => {
27
+ export const ImageViewer = ({ file, zoomFactor = 1, isPending }) => {
28
28
  const [imageLoaded, setImageLoaded] = useState(false);
29
29
  const [originalDimensions, setOriginalDimensions] = useState({
30
30
  naturalWidth: 0,
@@ -36,6 +36,8 @@ export const ImageViewer = ({ file, zoomFactor = 1, }) => {
36
36
  setOriginalDimensions((prev) => (Object.assign(Object.assign({}, prev), { width: e.target.clientWidth, height: e.target.offsetHeight })));
37
37
  };
38
38
  const loadImage = () => {
39
+ if (!file.url)
40
+ return;
39
41
  const img = document.createElement("img");
40
42
  img.src = file.url;
41
43
  img.onload = () => {
@@ -46,6 +48,9 @@ export const ImageViewer = ({ file, zoomFactor = 1, }) => {
46
48
  useEffect(() => {
47
49
  loadImage();
48
50
  }, [file.url]);
51
+ if (isPending) {
52
+ return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] }));
53
+ }
49
54
  return (_jsxs(ImageViewerContainer, { className: "mfui-ImageViewer", children: [!imageLoaded && (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] })), imageLoaded && (_jsx(Image, { src: file.url, alt: file.name ? file.name : "Image", zoomFactor: zoomFactor, onLoad: handleImageLoad, height: zoomFactor === 1 ? "100%" : originalDimensions.height * zoomFactor, onClick: (e) => {
50
55
  e.stopPropagation();
51
56
  } }))] }));
@@ -1,4 +1,5 @@
1
1
  import { File } from "../FileViewer";
2
2
  export declare const OfficeViewer: React.FC<{
3
3
  file: File;
4
+ isPending?: boolean;
4
5
  }>;
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styled from "styled-components";
3
3
  import Loader from "../../Loader";
4
4
  const StyledContainer = styled.div `
@@ -32,6 +32,13 @@ const StyledIframe = styled.iframe `
32
32
  height: 100%;
33
33
  border: none;
34
34
  `;
35
+ const StyledLoader = styled.div `
36
+ display: flex;
37
+ flex-direction: column;
38
+ justify-content: center;
39
+ align-items: center;
40
+ gap: 10px;
41
+ `;
35
42
  const resolveOfficeType = (file) => {
36
43
  let ext = file.ext;
37
44
  if (!ext) {
@@ -54,7 +61,10 @@ const resolveOfficeType = (file) => {
54
61
  return null;
55
62
  }
56
63
  };
57
- export const OfficeViewer = ({ file }) => {
64
+ export const OfficeViewer = ({ file, isPending }) => {
58
65
  const type = resolveOfficeType(file);
66
+ if (isPending) {
67
+ return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] }));
68
+ }
59
69
  return (_jsx(StyledContainer, { children: _jsx(StyledInnerContainer, { "data-type": type, children: !(file === null || file === void 0 ? void 0 : file.url) ? (_jsx(Loader, {})) : (_jsx(StyledIframe, { id: "office-iframe", title: "office-iframe", src: `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(file.url)}` })) }) }));
60
70
  };
@@ -3,5 +3,6 @@ import "react-pdf/dist/esm/Page/TextLayer.css";
3
3
  import { File } from "../FileViewer";
4
4
  export declare const PdfViewer: React.FC<{
5
5
  file: File;
6
+ isPending?: boolean;
6
7
  zoomFactor?: number;
7
8
  }>;
@@ -39,7 +39,7 @@ const StyledLoader = styled.div `
39
39
  left: 50%;
40
40
  transform: translate(-50%, -50%);
41
41
  `;
42
- export const PdfViewer = ({ file, zoomFactor = 1, }) => {
42
+ export const PdfViewer = ({ file, zoomFactor = 1, isPending }) => {
43
43
  const [loading, setLoading] = useState(true);
44
44
  const [numPages, setNumPages] = useState();
45
45
  const [pageNumber, setPageNumber] = useState(1);
@@ -51,6 +51,9 @@ export const PdfViewer = ({ file, zoomFactor = 1, }) => {
51
51
  }
52
52
  // viewport width
53
53
  const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) / 1.15;
54
+ if (isPending) {
55
+ return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading PDF..." })] }));
56
+ }
54
57
  return (_jsx(StyledContainer, { className: "PdfViewer", children: _jsx(StyledDocument, { file: file.url, onLoadSuccess: onDocumentLoadSuccess, loading: _jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading PDF..." })] }), onClick: (e) => {
55
58
  e.stopPropagation();
56
59
  }, children: Array.from(new Array(numPages), (el, index) => (_jsx(StyledPage, { pageNumber: index + 1, scale: zoomFactor, width: vw }, `page_${index + 1}`))) }) }));
@@ -12,6 +12,8 @@ import styled from "styled-components";
12
12
  import { useState } from "react";
13
13
  import Loader from "../../Loader";
14
14
  const getFileData = (file) => __awaiter(void 0, void 0, void 0, function* () {
15
+ if (!file.url)
16
+ return "";
15
17
  const response = yield fetch(file.url);
16
18
  const text = yield response.text();
17
19
  return text;
@@ -2,4 +2,5 @@ import { File } from "../FileViewer";
2
2
  export declare const VideoViewer: React.FC<{
3
3
  file: File;
4
4
  zoomFactor?: number;
5
+ isPending?: boolean;
5
6
  }>;
@@ -1,5 +1,6 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styled from "styled-components";
3
+ import Loader from "../../Loader";
3
4
  const StyledContainer = styled.div `
4
5
  display: flex;
5
6
  justify-content: center;
@@ -12,7 +13,17 @@ const StyledVideo = styled.video `
12
13
  max-height: 100%;
13
14
  object-fit: contain;
14
15
  `;
15
- export const VideoViewer = ({ file }) => {
16
+ const StyledLoader = styled.div `
17
+ display: flex;
18
+ flex-direction: column;
19
+ justify-content: center;
20
+ align-items: center;
21
+ gap: 10px;
22
+ `;
23
+ export const VideoViewer = ({ file, isPending }) => {
24
+ if (isPending) {
25
+ return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] }));
26
+ }
16
27
  return (_jsx(StyledContainer, { className: "mfui-VideoViewer", children: _jsx(StyledVideo, { src: file.url, controls: true, autoPlay: true, onClick: (e) => {
17
28
  e.stopPropagation();
18
29
  } }) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.2.50",
3
+ "version": "1.2.53",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",