@monolith-forensics/monolith-ui 1.2.19 → 1.2.21
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.
- package/dist/FileViewer/FileViewer.d.ts +12 -0
- package/dist/FileViewer/FileViewer.js +156 -0
- package/dist/FileViewer/index.d.ts +1 -0
- package/dist/FileViewer/index.js +1 -0
- package/dist/FileViewer/viewers/CodeViewer.d.ts +5 -0
- package/dist/FileViewer/viewers/CodeViewer.js +99 -0
- package/dist/FileViewer/viewers/ImageViewer.d.ts +5 -0
- package/dist/FileViewer/viewers/ImageViewer.js +53 -0
- package/dist/FileViewer/viewers/OfficeViewer.d.ts +4 -0
- package/dist/FileViewer/viewers/OfficeViewer.js +60 -0
- package/dist/FileViewer/viewers/PdfViewer.d.ts +7 -0
- package/dist/FileViewer/viewers/PdfViewer.js +58 -0
- package/dist/FileViewer/viewers/PlainTextViewer.d.ts +4 -0
- package/dist/FileViewer/viewers/PlainTextViewer.js +60 -0
- package/dist/FileViewer/viewers/VideoViewer.d.ts +5 -0
- package/dist/FileViewer/viewers/VideoViewer.js +19 -0
- package/dist/FileViewer/viewers/index.d.ts +6 -0
- package/dist/FileViewer/viewers/index.js +6 -0
- package/dist/RichTextEditor/RichTextEditor.d.ts +2 -3
- package/dist/RichTextEditor/RichTextEditor.js +86 -82
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +6 -3
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import { CodeViewer, ImageViewer, OfficeViewer, PdfViewer, VideoViewer, } from "./viewers";
|
|
4
|
+
import { FloatingPortal } from "@floating-ui/react";
|
|
5
|
+
import { DownloadIcon, XIcon, ZoomInIcon, ZoomOutIcon } from "lucide-react";
|
|
6
|
+
import Button from "../Button";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
var ViewerTypes;
|
|
9
|
+
(function (ViewerTypes) {
|
|
10
|
+
ViewerTypes["Office"] = "office";
|
|
11
|
+
ViewerTypes["Image"] = "image";
|
|
12
|
+
ViewerTypes["Video"] = "video";
|
|
13
|
+
ViewerTypes["Audio"] = "audio";
|
|
14
|
+
ViewerTypes["PDF"] = "pdf";
|
|
15
|
+
ViewerTypes["Text"] = "text";
|
|
16
|
+
ViewerTypes["Code"] = "code";
|
|
17
|
+
})(ViewerTypes || (ViewerTypes = {}));
|
|
18
|
+
const ZoomableViewerTypes = [
|
|
19
|
+
ViewerTypes.Image,
|
|
20
|
+
ViewerTypes.PDF,
|
|
21
|
+
ViewerTypes.Code,
|
|
22
|
+
ViewerTypes.Text,
|
|
23
|
+
];
|
|
24
|
+
const RotatableViewerTypes = [ViewerTypes.Image];
|
|
25
|
+
const OfficeExtensions = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
|
|
26
|
+
const ImageExtensions = ["jpg", "jpeg", "png", "gif"];
|
|
27
|
+
const VideoExtensions = ["mp4", "webm", "mov"];
|
|
28
|
+
const AudioExtensions = ["mp3", "wav"];
|
|
29
|
+
const PDFExtensions = ["pdf"];
|
|
30
|
+
const PlainTextExtensions = ["txt", "log", "csv"];
|
|
31
|
+
const CodeExtensions = [
|
|
32
|
+
"js",
|
|
33
|
+
"ts",
|
|
34
|
+
"jsx",
|
|
35
|
+
"tsx",
|
|
36
|
+
"json",
|
|
37
|
+
"html",
|
|
38
|
+
"css",
|
|
39
|
+
"xml",
|
|
40
|
+
"py",
|
|
41
|
+
"py3",
|
|
42
|
+
"dymo",
|
|
43
|
+
];
|
|
44
|
+
const StyledMenu = styled.div `
|
|
45
|
+
height: 50px;
|
|
46
|
+
min-height: 50px;
|
|
47
|
+
width: 100%;
|
|
48
|
+
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: space-between;
|
|
52
|
+
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
|
|
55
|
+
padding: 0 10px;
|
|
56
|
+
|
|
57
|
+
background-color: ${(props) => props.theme.palette.background.alt};
|
|
58
|
+
`;
|
|
59
|
+
const StyledActionsMenu = styled.div `
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: row;
|
|
62
|
+
gap: 10px;
|
|
63
|
+
align-items: center;
|
|
64
|
+
`;
|
|
65
|
+
const StyledContainer = styled.div `
|
|
66
|
+
position: fixed;
|
|
67
|
+
top: 0;
|
|
68
|
+
left: 0;
|
|
69
|
+
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
|
|
73
|
+
height: 100%;
|
|
74
|
+
width: 100%;
|
|
75
|
+
|
|
76
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
77
|
+
|
|
78
|
+
// blur
|
|
79
|
+
backdrop-filter: blur(3px);
|
|
80
|
+
|
|
81
|
+
// scroll bar
|
|
82
|
+
::-webkit-scrollbar {
|
|
83
|
+
width: 14px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
::-webkit-scrollbar-track {
|
|
87
|
+
background: rgba(255, 255, 255, 0.075);
|
|
88
|
+
border-radius: 10px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
::-webkit-scrollbar-thumb {
|
|
92
|
+
background: #888;
|
|
93
|
+
border-radius: 10px;
|
|
94
|
+
border: 4px solid rgba(0, 0, 0, 0);
|
|
95
|
+
background-clip: padding-box;
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
const StyledInnerContainer = styled.div `
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-direction: column;
|
|
101
|
+
flex: 1 1 auto;
|
|
102
|
+
|
|
103
|
+
height: 0px;
|
|
104
|
+
width: 100%;
|
|
105
|
+
|
|
106
|
+
overflow-y: auto;
|
|
107
|
+
|
|
108
|
+
&[data-type="office"] {
|
|
109
|
+
margin-bottom: 10px;
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
const resolveViewerType = (file) => {
|
|
113
|
+
let ext = file.ext;
|
|
114
|
+
if (!ext) {
|
|
115
|
+
ext = file.name.split(".").pop();
|
|
116
|
+
}
|
|
117
|
+
if (!ext) {
|
|
118
|
+
return ViewerTypes.Code;
|
|
119
|
+
}
|
|
120
|
+
if (OfficeExtensions.includes(ext)) {
|
|
121
|
+
return ViewerTypes.Office;
|
|
122
|
+
}
|
|
123
|
+
if (ImageExtensions.includes(ext)) {
|
|
124
|
+
return ViewerTypes.Image;
|
|
125
|
+
}
|
|
126
|
+
if (VideoExtensions.includes(ext)) {
|
|
127
|
+
return ViewerTypes.Video;
|
|
128
|
+
}
|
|
129
|
+
if (AudioExtensions.includes(ext)) {
|
|
130
|
+
return ViewerTypes.Audio;
|
|
131
|
+
}
|
|
132
|
+
if (PDFExtensions.includes(ext)) {
|
|
133
|
+
return ViewerTypes.PDF;
|
|
134
|
+
}
|
|
135
|
+
if (PlainTextExtensions.includes(ext)) {
|
|
136
|
+
return ViewerTypes.Text;
|
|
137
|
+
}
|
|
138
|
+
if (CodeExtensions.includes(ext)) {
|
|
139
|
+
return ViewerTypes.Code;
|
|
140
|
+
}
|
|
141
|
+
return ViewerTypes.Code;
|
|
142
|
+
};
|
|
143
|
+
export const FileViewer = ({ file, open, onClose }) => {
|
|
144
|
+
const [zoomFactor, setZoomFactor] = useState(1);
|
|
145
|
+
if (!open)
|
|
146
|
+
return null;
|
|
147
|
+
const viewerType = resolveViewerType(file);
|
|
148
|
+
const handleBackgroundClick = (e) => {
|
|
149
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
150
|
+
setZoomFactor(1);
|
|
151
|
+
};
|
|
152
|
+
return (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsxs(StyledContainer, { className: "mfui-FileViewer", children: [_jsxs(StyledMenu, { className: "FileViewer-menu", children: [_jsx(Button, { variant: "text", onClick: () => {
|
|
153
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
154
|
+
setZoomFactor(1);
|
|
155
|
+
}, 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 }))] })] }) }));
|
|
156
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./FileViewer";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./FileViewer";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import styled from "styled-components";
|
|
13
|
+
import Loader from "../../Loader";
|
|
14
|
+
const resolveLanguage = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const { languages } = yield import("@codemirror/language-data");
|
|
16
|
+
let ext = file.ext;
|
|
17
|
+
if (!ext) {
|
|
18
|
+
ext = file.name.split(".").pop();
|
|
19
|
+
}
|
|
20
|
+
if (!ext) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const l = languages.find((lang) => lang.extensions.includes(ext));
|
|
24
|
+
if (l) {
|
|
25
|
+
return yield l.load();
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
});
|
|
29
|
+
const getFileData = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
const response = yield fetch(file.url);
|
|
31
|
+
const text = yield response.text();
|
|
32
|
+
return text;
|
|
33
|
+
});
|
|
34
|
+
const loadCodemirror = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const language = yield resolveLanguage(file);
|
|
36
|
+
const CodeMirror = yield import("@uiw/react-codemirror");
|
|
37
|
+
const { vscodeDark } = yield import("@uiw/codemirror-theme-vscode");
|
|
38
|
+
return { language, CodeMirror, theme: vscodeDark };
|
|
39
|
+
});
|
|
40
|
+
const StyledContainer = styled.div `
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
|
|
44
|
+
flex: 1 1 auto;
|
|
45
|
+
height: 0px;
|
|
46
|
+
width: 100%;
|
|
47
|
+
|
|
48
|
+
.cm-theme {
|
|
49
|
+
font-size: ${(props) => props.zoomFactor ? `${props.zoomFactor * 12}px` : "12px"};
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.cm-editor {
|
|
54
|
+
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
55
|
+
width: 100%;
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
const StyledLoader = styled.div `
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: 10px;
|
|
64
|
+
`;
|
|
65
|
+
export const CodeViewer = ({ file, zoomFactor }) => {
|
|
66
|
+
const [CodeMirror, setCodeMirror] = useState(null);
|
|
67
|
+
const [language, setLanguage] = useState(null);
|
|
68
|
+
const [theme, setTheme] = useState(null);
|
|
69
|
+
const [query, setQuery] = useState({
|
|
70
|
+
data: null,
|
|
71
|
+
isLoading: false,
|
|
72
|
+
});
|
|
73
|
+
if (!query.data) {
|
|
74
|
+
if (!query.isLoading) {
|
|
75
|
+
setQuery({ data: null, isLoading: true });
|
|
76
|
+
getFileData(file).then((text) => {
|
|
77
|
+
setQuery({ data: text, isLoading: false });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!CodeMirror) {
|
|
82
|
+
loadCodemirror(file).then((cm) => {
|
|
83
|
+
setCodeMirror(cm.CodeMirror);
|
|
84
|
+
setLanguage(cm.language);
|
|
85
|
+
setTheme(cm.theme);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const loading = query.isLoading || !CodeMirror;
|
|
89
|
+
const extensions = [];
|
|
90
|
+
if (language) {
|
|
91
|
+
extensions.push(language);
|
|
92
|
+
}
|
|
93
|
+
if (CodeMirror) {
|
|
94
|
+
extensions.push(CodeMirror.EditorView.lineWrapping);
|
|
95
|
+
}
|
|
96
|
+
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
|
+
event.stopPropagation();
|
|
98
|
+
} }))] }));
|
|
99
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import Loader from "../../Loader";
|
|
5
|
+
const ImageViewerContainer = styled.div `
|
|
6
|
+
display: flex;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
|
|
9
|
+
flex: 1 1 auto;
|
|
10
|
+
height: 0px;
|
|
11
|
+
`;
|
|
12
|
+
// Updated Image styled-component to remove max-width and max-height
|
|
13
|
+
const Image = styled.img `
|
|
14
|
+
object-fit: contain;
|
|
15
|
+
|
|
16
|
+
// set orientation
|
|
17
|
+
image-orientation: from-image;
|
|
18
|
+
|
|
19
|
+
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
20
|
+
`;
|
|
21
|
+
const StyledLoader = styled.div `
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: 10px;
|
|
27
|
+
`;
|
|
28
|
+
export const ImageViewer = ({ file, zoomFactor = 1, }) => {
|
|
29
|
+
const [imageLoaded, setImageLoaded] = useState(false);
|
|
30
|
+
const [originalDimensions, setOriginalDimensions] = useState({
|
|
31
|
+
naturalWidth: 0,
|
|
32
|
+
naturalHeight: 0,
|
|
33
|
+
width: 0,
|
|
34
|
+
height: 0,
|
|
35
|
+
});
|
|
36
|
+
const handleImageLoad = (e) => {
|
|
37
|
+
setOriginalDimensions((prev) => (Object.assign(Object.assign({}, prev), { width: e.target.clientWidth, height: e.target.offsetHeight })));
|
|
38
|
+
};
|
|
39
|
+
const loadImage = () => {
|
|
40
|
+
const img = document.createElement("img");
|
|
41
|
+
img.src = file.url;
|
|
42
|
+
img.onload = () => {
|
|
43
|
+
setOriginalDimensions((prev) => (Object.assign(Object.assign({}, prev), { naturalWidth: img.naturalWidth, naturalHeight: img.naturalHeight })));
|
|
44
|
+
setImageLoaded(true);
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
loadImage();
|
|
49
|
+
}, [file.url]);
|
|
50
|
+
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) => {
|
|
51
|
+
e.stopPropagation();
|
|
52
|
+
} }))] }));
|
|
53
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import Loader from "../../Loader";
|
|
4
|
+
const StyledContainer = styled.div `
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
align-items: center;
|
|
9
|
+
|
|
10
|
+
flex: 1 1 auto;
|
|
11
|
+
height: 0px;
|
|
12
|
+
width: 100%;
|
|
13
|
+
`;
|
|
14
|
+
const StyledInnerContainer = styled.div `
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
flex: 1 1 auto;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: center;
|
|
20
|
+
|
|
21
|
+
width: 100%;
|
|
22
|
+
max-width: 100%;
|
|
23
|
+
|
|
24
|
+
#office-iframe {
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
border: none;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const StyledIframe = styled.iframe `
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
border: none;
|
|
34
|
+
`;
|
|
35
|
+
const resolveOfficeType = (file) => {
|
|
36
|
+
let ext = file.ext;
|
|
37
|
+
if (!ext) {
|
|
38
|
+
ext = file.name.split(".").pop();
|
|
39
|
+
}
|
|
40
|
+
if (!ext) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
switch (ext) {
|
|
44
|
+
case "doc":
|
|
45
|
+
case "docx":
|
|
46
|
+
return "word";
|
|
47
|
+
case "xls":
|
|
48
|
+
case "xlsx":
|
|
49
|
+
return "excel";
|
|
50
|
+
case "ppt":
|
|
51
|
+
case "pptx":
|
|
52
|
+
return "powerpoint";
|
|
53
|
+
default:
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
export const OfficeViewer = ({ file }) => {
|
|
58
|
+
const type = resolveOfficeType(file);
|
|
59
|
+
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
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Document, Page,
|
|
4
|
+
// pdfjs
|
|
5
|
+
} from "react-pdf";
|
|
6
|
+
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
|
|
7
|
+
import "react-pdf/dist/esm/Page/TextLayer.css";
|
|
8
|
+
import styled from "styled-components";
|
|
9
|
+
import Loader from "../../Loader";
|
|
10
|
+
// pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
|
11
|
+
// "pdfjs-dist/build/pdf.worker.min.mjs",
|
|
12
|
+
// import.meta.url
|
|
13
|
+
// ).toString();
|
|
14
|
+
const StyledContainer = styled.div `
|
|
15
|
+
display: flex;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
|
|
18
|
+
flex: 1 1 auto;
|
|
19
|
+
height: 0px;
|
|
20
|
+
|
|
21
|
+
&[data-loading="true"] > * {
|
|
22
|
+
justify-content: center;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
const StyledDocument = styled(Document) `
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
gap: 10px;
|
|
29
|
+
|
|
30
|
+
background-color: transparent;
|
|
31
|
+
|
|
32
|
+
// width: 100%;
|
|
33
|
+
`;
|
|
34
|
+
const StyledPage = styled(Page) `
|
|
35
|
+
width: fit-content;
|
|
36
|
+
background-color: transparent;
|
|
37
|
+
`;
|
|
38
|
+
const StyledLoader = styled.div `
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 10px;
|
|
44
|
+
`;
|
|
45
|
+
export const PdfViewer = ({ file, zoomFactor = 1, }) => {
|
|
46
|
+
const [loading, setLoading] = useState(true);
|
|
47
|
+
const [numPages, setNumPages] = useState();
|
|
48
|
+
const [pageNumber, setPageNumber] = useState(1);
|
|
49
|
+
function onDocumentLoadSuccess({ numPages }) {
|
|
50
|
+
setLoading(false);
|
|
51
|
+
setNumPages(numPages);
|
|
52
|
+
}
|
|
53
|
+
// viewport width
|
|
54
|
+
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) - 20;
|
|
55
|
+
return (_jsx(StyledContainer, { className: "PdfViewer", "data-loading": loading, children: _jsx(StyledDocument, { file: file.url, onLoadSuccess: onDocumentLoadSuccess, loading: _jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading PDF..." })] }), onClick: (e) => {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
}, children: Array.from(new Array(numPages), (el, index) => (_jsx(StyledPage, { pageNumber: index + 1, scale: zoomFactor, width: vw }, `page_${index + 1}`))) }) }));
|
|
58
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import styled from "styled-components";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import Loader from "../../Loader";
|
|
14
|
+
const getFileData = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const response = yield fetch(file.url);
|
|
16
|
+
const text = yield response.text();
|
|
17
|
+
return text;
|
|
18
|
+
});
|
|
19
|
+
const StyledContainer = styled.div `
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
|
|
23
|
+
flex: 1 1 auto;
|
|
24
|
+
height: 0px;
|
|
25
|
+
`;
|
|
26
|
+
const StyledTextData = styled.div `
|
|
27
|
+
width: 100%;
|
|
28
|
+
height: fit-content;
|
|
29
|
+
max-width: 8.5in;
|
|
30
|
+
padding: 25px;
|
|
31
|
+
|
|
32
|
+
background-color: ${(props) => props.theme.palette.background.alt};
|
|
33
|
+
white-space: pre-wrap !important;
|
|
34
|
+
word-wrap: break-word !important;
|
|
35
|
+
|
|
36
|
+
font-family: monospace;
|
|
37
|
+
font-size: 10px;
|
|
38
|
+
`;
|
|
39
|
+
const StyledLoader = styled.div `
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 10px;
|
|
45
|
+
`;
|
|
46
|
+
export const PlainTextViewer = ({ file }) => {
|
|
47
|
+
const [query, setQuery] = useState({
|
|
48
|
+
data: null,
|
|
49
|
+
isLoading: false,
|
|
50
|
+
});
|
|
51
|
+
if (!query.data) {
|
|
52
|
+
if (!query.isLoading) {
|
|
53
|
+
setQuery({ data: null, isLoading: true });
|
|
54
|
+
getFileData(file).then((text) => {
|
|
55
|
+
setQuery({ data: text, isLoading: false });
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return (_jsxs(StyledContainer, { className: "mfui-PlainTextViewer", children: [!query.data && (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading File..." })] })), query.data && (_jsx(StyledTextData, { className: "text-doc", children: query.data }))] }));
|
|
60
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
const StyledContainer = styled.div `
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
|
|
7
|
+
flex: 1 1 auto;
|
|
8
|
+
height: 0px;
|
|
9
|
+
`;
|
|
10
|
+
const StyledVideo = styled.video `
|
|
11
|
+
max-width: 100%;
|
|
12
|
+
max-height: 100%;
|
|
13
|
+
object-fit: contain;
|
|
14
|
+
`;
|
|
15
|
+
export const VideoViewer = ({ file }) => {
|
|
16
|
+
return (_jsx(StyledContainer, { className: "mfui-VideoViewer", children: _jsx(StyledVideo, { src: file.url, controls: true, autoPlay: true, onClick: (e) => {
|
|
17
|
+
e.stopPropagation();
|
|
18
|
+
} }) }));
|
|
19
|
+
};
|
|
@@ -9,6 +9,7 @@ interface RichTextEditorProps {
|
|
|
9
9
|
extensions?: ExtensionType[];
|
|
10
10
|
slashCommands?: any[];
|
|
11
11
|
defaultValue?: string;
|
|
12
|
+
value?: string;
|
|
12
13
|
readOnly?: boolean;
|
|
13
14
|
height?: string;
|
|
14
15
|
font?: string;
|
|
@@ -21,7 +22,5 @@ interface RichTextEditorProps {
|
|
|
21
22
|
autoFocus?: boolean;
|
|
22
23
|
style?: React.CSSProperties;
|
|
23
24
|
}
|
|
24
|
-
declare const RichTextEditor: import("
|
|
25
|
-
ref?: ((instance: unknown) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<unknown> | null | undefined;
|
|
26
|
-
}, never>> & string & Omit<import("react").ForwardRefExoticComponent<RichTextEditorProps & import("react").RefAttributes<unknown>>, keyof import("react").Component<any, {}, any>>;
|
|
25
|
+
declare const RichTextEditor: import("react").ForwardRefExoticComponent<RichTextEditorProps & import("react").RefAttributes<unknown>>;
|
|
27
26
|
export default RichTextEditor;
|
|
@@ -9,88 +9,7 @@ import { startImageUpload, } from "./Plugins/UploadImagesPlugin";
|
|
|
9
9
|
import SaveBadge from "./Components/SaveBadge";
|
|
10
10
|
import Fonts from "./Enums/Fonts";
|
|
11
11
|
import RichTextEditorContext from "./Contexts/RichTextEditorContext";
|
|
12
|
-
const
|
|
13
|
-
const [fontState, setFontState] = useState(font || Fonts.DEFAULT);
|
|
14
|
-
// check if image extension is included
|
|
15
|
-
if (extensions === null || extensions === void 0 ? void 0 : extensions.includes(Extensions.Image)) {
|
|
16
|
-
// Ensure that handleImageUpload is provided
|
|
17
|
-
if (!handleImageUpload) {
|
|
18
|
-
throw new Error("handleImageUpload is required when using the image extension.");
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const editor = useEditor({
|
|
22
|
-
content: defaultValue,
|
|
23
|
-
editable: !readOnly,
|
|
24
|
-
extensions: getTipTapExtensions({
|
|
25
|
-
extensions,
|
|
26
|
-
slashCommands,
|
|
27
|
-
bubbleMenuOptions,
|
|
28
|
-
handleImageUpload,
|
|
29
|
-
}),
|
|
30
|
-
editorProps: {
|
|
31
|
-
handlePaste: (view, event) => {
|
|
32
|
-
if (!handleImageUpload)
|
|
33
|
-
return false;
|
|
34
|
-
if (!(event === null || event === void 0 ? void 0 : event.clipboardData))
|
|
35
|
-
return false;
|
|
36
|
-
if (event.clipboardData.types.includes("text/html") ||
|
|
37
|
-
event.clipboardData.types.includes("text/plain") ||
|
|
38
|
-
event.clipboardData.types.includes("text/rtf"))
|
|
39
|
-
return false;
|
|
40
|
-
if (event.clipboardData &&
|
|
41
|
-
event.clipboardData.files &&
|
|
42
|
-
event.clipboardData.files[0]) {
|
|
43
|
-
event.preventDefault();
|
|
44
|
-
const file = event.clipboardData.files[0];
|
|
45
|
-
const pos = view.state.selection.from;
|
|
46
|
-
startImageUpload(file, view, pos, handleImageUpload);
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
},
|
|
51
|
-
handleDrop: (view, event, _slice, moved) => {
|
|
52
|
-
if (!handleImageUpload)
|
|
53
|
-
return false;
|
|
54
|
-
if (!moved &&
|
|
55
|
-
event.dataTransfer &&
|
|
56
|
-
event.dataTransfer.files &&
|
|
57
|
-
event.dataTransfer.files[0]) {
|
|
58
|
-
event.preventDefault();
|
|
59
|
-
const file = event.dataTransfer.files[0];
|
|
60
|
-
const coordinates = view.posAtCoords({
|
|
61
|
-
left: event.clientX,
|
|
62
|
-
top: event.clientY,
|
|
63
|
-
});
|
|
64
|
-
if (!coordinates)
|
|
65
|
-
return false;
|
|
66
|
-
// here we deduct 1 from the pos or else the image will create an extra node
|
|
67
|
-
startImageUpload(file, view, coordinates.pos - 1, handleImageUpload);
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
return false;
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
onUpdate: ({ editor }) => {
|
|
74
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(editor.getHTML());
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
const _ref = editorInstanceRef;
|
|
79
|
-
if (editorInstanceRef) {
|
|
80
|
-
_ref.current = editor;
|
|
81
|
-
}
|
|
82
|
-
}, [editor]);
|
|
83
|
-
// AutoFocus on the editor
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
if (autoFocus && editor) {
|
|
86
|
-
editor.view.focus();
|
|
87
|
-
}
|
|
88
|
-
}, [autoFocus, editor]);
|
|
89
|
-
return (_jsx("div", { className: className, children: _jsxs(RichTextEditorContext.Provider, { value: {
|
|
90
|
-
font: fontState,
|
|
91
|
-
setFont: setFontState,
|
|
92
|
-
}, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: toolbarOptions })), saving && _jsx(SaveBadge, {}), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": fontState || null, style: style })] }) }));
|
|
93
|
-
})) `
|
|
12
|
+
const StyledContent = styled.div `
|
|
94
13
|
position: relative;
|
|
95
14
|
display: flex;
|
|
96
15
|
flex-direction: column;
|
|
@@ -363,4 +282,89 @@ const RichTextEditor = styled(forwardRef(({ className, editorInstanceRef, defaul
|
|
|
363
282
|
margin: 0 0.125rem;
|
|
364
283
|
}
|
|
365
284
|
`;
|
|
285
|
+
const RichTextEditor = forwardRef(({ className, editorInstanceRef, defaultValue = "", value = "", readOnly = false, font, showToolbar = true, saving = false, extensions = [], slashCommands = [], bubbleMenuOptions, toolbarOptions, autoFocus, onChange, handleImageUpload, style, }, ref) => {
|
|
286
|
+
const [fontState, setFontState] = useState(font || Fonts.DEFAULT);
|
|
287
|
+
// check if image extension is included
|
|
288
|
+
if (extensions === null || extensions === void 0 ? void 0 : extensions.includes(Extensions.Image)) {
|
|
289
|
+
// Ensure that handleImageUpload is provided
|
|
290
|
+
if (!handleImageUpload) {
|
|
291
|
+
throw new Error("handleImageUpload is required when using the image extension.");
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const editor = useEditor({
|
|
295
|
+
content: defaultValue,
|
|
296
|
+
editable: !readOnly,
|
|
297
|
+
extensions: getTipTapExtensions({
|
|
298
|
+
extensions,
|
|
299
|
+
slashCommands,
|
|
300
|
+
bubbleMenuOptions,
|
|
301
|
+
handleImageUpload,
|
|
302
|
+
}),
|
|
303
|
+
editorProps: {
|
|
304
|
+
handlePaste: (view, event) => {
|
|
305
|
+
if (!handleImageUpload)
|
|
306
|
+
return false;
|
|
307
|
+
if (!(event === null || event === void 0 ? void 0 : event.clipboardData))
|
|
308
|
+
return false;
|
|
309
|
+
if (event.clipboardData.types.includes("text/html") ||
|
|
310
|
+
event.clipboardData.types.includes("text/plain") ||
|
|
311
|
+
event.clipboardData.types.includes("text/rtf"))
|
|
312
|
+
return false;
|
|
313
|
+
if (event.clipboardData &&
|
|
314
|
+
event.clipboardData.files &&
|
|
315
|
+
event.clipboardData.files[0]) {
|
|
316
|
+
event.preventDefault();
|
|
317
|
+
const file = event.clipboardData.files[0];
|
|
318
|
+
const pos = view.state.selection.from;
|
|
319
|
+
startImageUpload(file, view, pos, handleImageUpload);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return false;
|
|
323
|
+
},
|
|
324
|
+
handleDrop: (view, event, _slice, moved) => {
|
|
325
|
+
if (!handleImageUpload)
|
|
326
|
+
return false;
|
|
327
|
+
if (!moved &&
|
|
328
|
+
event.dataTransfer &&
|
|
329
|
+
event.dataTransfer.files &&
|
|
330
|
+
event.dataTransfer.files[0]) {
|
|
331
|
+
event.preventDefault();
|
|
332
|
+
const file = event.dataTransfer.files[0];
|
|
333
|
+
const coordinates = view.posAtCoords({
|
|
334
|
+
left: event.clientX,
|
|
335
|
+
top: event.clientY,
|
|
336
|
+
});
|
|
337
|
+
if (!coordinates)
|
|
338
|
+
return false;
|
|
339
|
+
// here we deduct 1 from the pos or else the image will create an extra node
|
|
340
|
+
startImageUpload(file, view, coordinates.pos - 1, handleImageUpload);
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
return false;
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
onUpdate: ({ editor }) => {
|
|
347
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(editor.getHTML());
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
useEffect(() => {
|
|
351
|
+
const _ref = editorInstanceRef;
|
|
352
|
+
if (editorInstanceRef) {
|
|
353
|
+
_ref.current = editor;
|
|
354
|
+
}
|
|
355
|
+
}, [editor]);
|
|
356
|
+
// AutoFocus on the editor
|
|
357
|
+
useEffect(() => {
|
|
358
|
+
if (autoFocus && editor) {
|
|
359
|
+
editor.view.focus();
|
|
360
|
+
}
|
|
361
|
+
}, [autoFocus, editor]);
|
|
362
|
+
useEffect(() => {
|
|
363
|
+
editor === null || editor === void 0 ? void 0 : editor.commands.setContent(defaultValue);
|
|
364
|
+
}, [defaultValue]);
|
|
365
|
+
return (_jsx(StyledContent, { className: className, children: _jsxs(RichTextEditorContext.Provider, { value: {
|
|
366
|
+
font: fontState,
|
|
367
|
+
setFont: setFontState,
|
|
368
|
+
}, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: toolbarOptions })), saving && _jsx(SaveBadge, {}), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": fontState || null, style: style })] }) }));
|
|
369
|
+
});
|
|
366
370
|
export default RichTextEditor;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.21",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"release-major": "yarn version --major --deferred && yarn build && npm publish && yarn clean"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@codemirror/language-data": "^6.5.1",
|
|
28
29
|
"@floating-ui/react": "^0.26.16",
|
|
29
30
|
"@mantine/hooks": "^7.13.0",
|
|
30
31
|
"@radix-ui/react-switch": "^1.0.7",
|
|
@@ -46,6 +47,8 @@
|
|
|
46
47
|
"@tiptap/react": "^2.5.8",
|
|
47
48
|
"@tiptap/starter-kit": "^2.5.8",
|
|
48
49
|
"@tiptap/suggestion": "^2.5.9",
|
|
50
|
+
"@uiw/codemirror-theme-vscode": "^4.23.6",
|
|
51
|
+
"@uiw/react-codemirror": "^4.23.6",
|
|
49
52
|
"deepmerge": "^4.3.1",
|
|
50
53
|
"lucide-react": "^0.378.0",
|
|
51
54
|
"moment": "^2.29.1",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"react-dom": "^18.3.1",
|
|
55
58
|
"react-dropzone": "^14.2.3",
|
|
56
59
|
"react-icons": "^5.2.1",
|
|
60
|
+
"react-pdf": "^9.1.1",
|
|
57
61
|
"react-textarea-autosize": "^8.5.3",
|
|
58
62
|
"react-virtualized-auto-sizer": "^1.0.24",
|
|
59
63
|
"react-window": "^1.8.10",
|
|
@@ -72,6 +76,5 @@
|
|
|
72
76
|
"@types/react-window": "^1.8.8",
|
|
73
77
|
"@types/spark-md5": "^3.0.4",
|
|
74
78
|
"typescript": "^5.5.4"
|
|
75
|
-
}
|
|
76
|
-
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
79
|
+
}
|
|
77
80
|
}
|