@mainframework/dropzone 1.0.18 → 1.0.19
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/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/components/FileSelector/FileSelector.js +53 -0
- package/dist/shared/components/FileSelector/FileSelector.js.map +1 -0
- package/dist/shared/components/FileSelector/index.js +2 -0
- package/dist/shared/components/FileSelector/index.js.map +1 -0
- package/dist/shared/hooks/useCustomCallback.js +16 -0
- package/dist/shared/hooks/useCustomCallback.js.map +1 -0
- package/dist/shared/hooks/useFileSelector.js +220 -0
- package/dist/shared/hooks/useFileSelector.js.map +1 -0
- package/dist/shared/types/types.js +2 -0
- package/dist/shared/types/types.js.map +1 -0
- package/dist/shared/utils/dragAndDrop.js +9 -0
- package/dist/shared/utils/dragAndDrop.js.map +1 -0
- package/dist/shared/utils/mergeStyles.js +5 -0
- package/dist/shared/utils/mergeStyles.js.map +1 -0
- package/dist/shared/utils/processUploadedFiles.js +156 -0
- package/dist/shared/utils/processUploadedFiles.js.map +1 -0
- package/package.json +1 -1
- /package/dist/{esm/index.d.ts → index.d.ts} +0 -0
- /package/dist/{esm/shared → shared}/components/FileSelector/FileSelector.d.ts +0 -0
- /package/dist/{esm/shared → shared}/components/FileSelector/index.d.ts +0 -0
- /package/dist/{esm/shared → shared}/hooks/useCustomCallback.d.ts +0 -0
- /package/dist/{esm/shared → shared}/hooks/useFileSelector.d.ts +0 -0
- /package/dist/{esm/shared → shared}/types/types.d.ts +0 -0
- /package/dist/{esm/shared → shared}/utils/dragAndDrop.d.ts +0 -0
- /package/dist/{esm/shared → shared}/utils/mergeStyles.d.ts +0 -0
- /package/dist/{esm/shared → shared}/utils/processUploadedFiles.d.ts +0 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useRef, useCallback, useId } from "react";
|
|
4
|
+
import { mergeStyles } from "../../utils/mergeStyles";
|
|
5
|
+
import "./tailwind.css";
|
|
6
|
+
if (typeof window !== "undefined") {
|
|
7
|
+
import("./tailwind.css");
|
|
8
|
+
}
|
|
9
|
+
import { withDragDefaults } from "../../utils/dragAndDrop";
|
|
10
|
+
const defaultAcceptTypes = ".png, .jpg, .jpeg, .pdf, .svg, image/svg+xml, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
11
|
+
const defaultInputClassName = "hiddenInput";
|
|
12
|
+
const defaultClickableAreaClassName = "dropzone border-dashed border-2 border-gray-500 p-4 rounded-md text-center cursor-pointer bg-inherit hover:border-gray-400 text-inherit font-bold py-2 px-4";
|
|
13
|
+
const defaultDropZoneWrapperClassName = "flex flex-col min-h-[120px] border border-gray-300 rounded-md shadow-md";
|
|
14
|
+
const defaultMessageParagraphClassName = "text-center text-gray-600";
|
|
15
|
+
const defaultMessageParagraph = "Drag 'n' drop some files here, or click to select files";
|
|
16
|
+
const defaultAriaLabel = "File upload drop zone";
|
|
17
|
+
const defaultAriaDescribedBy = undefined;
|
|
18
|
+
const defaultAriaLabelButton = "Choose files to upload";
|
|
19
|
+
const FileSelectorComponent = ({ inputId, acceptTypes = defaultAcceptTypes, messageParagraph = defaultMessageParagraph, inputClassName, clickableAreaClassName, dropZoneWrapperClassName, messageParagraphClassName, ariaLabel = defaultAriaLabel, ariaDescribedBy = defaultAriaDescribedBy, ariaLabelButton = defaultAriaLabelButton, ariaLabelledBy, // New prop for button
|
|
20
|
+
onChange, onDragOver, onDrop, onDragEnter, onDragLeave, }) => {
|
|
21
|
+
const fileInputRef = useRef(null);
|
|
22
|
+
const messageId = useId();
|
|
23
|
+
//Note, eslint doesn't like that I'm wrapping the anonymous function in withDragDefaults. Ignore for now
|
|
24
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
|
+
const internalOnClick = useCallback(withDragDefaults(() => {
|
|
26
|
+
fileInputRef.current?.click();
|
|
27
|
+
}), []);
|
|
28
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
+
const internalOnDrop = useCallback(withDragDefaults((e) => {
|
|
30
|
+
onDrop(e);
|
|
31
|
+
}), [onDrop]);
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
+
const internalOnDragOver = useCallback(withDragDefaults((e) => {
|
|
34
|
+
onDragOver(e);
|
|
35
|
+
}), [onDragOver]);
|
|
36
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
|
+
const internalOnDragEnter = useCallback(withDragDefaults((e) => {
|
|
38
|
+
onDragEnter(e);
|
|
39
|
+
}), [onDragEnter]);
|
|
40
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
+
const internalOnDragLeave = useCallback(withDragDefaults((e) => {
|
|
42
|
+
onDragLeave(e);
|
|
43
|
+
}), [onDragLeave]);
|
|
44
|
+
const inputClasses = mergeStyles(defaultInputClassName, inputClassName);
|
|
45
|
+
const resolvedClickableAreaClassName = mergeStyles(clickableAreaClassName ?? defaultClickableAreaClassName, "w-full h-full flex-1 min-h-0");
|
|
46
|
+
const resolvedDropZoneWrapperClassName = mergeStyles(dropZoneWrapperClassName ?? defaultDropZoneWrapperClassName);
|
|
47
|
+
const resolvedMessageParagraphClassName = mergeStyles(messageParagraphClassName ?? defaultMessageParagraphClassName);
|
|
48
|
+
const resolvedInputId = inputId ?? messageId;
|
|
49
|
+
return (_jsxs("div", { role: "group", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, className: resolvedDropZoneWrapperClassName, draggable: false, children: [_jsx("button", { type: "button", className: resolvedClickableAreaClassName, onClick: internalOnClick, onDragOver: internalOnDragOver, onDrop: internalOnDrop, onDragEnter: internalOnDragEnter, onDragLeave: internalOnDragLeave, draggable: false, "aria-label": ariaLabelButton, "aria-labelledby": ariaLabelledBy ?? messageId, "aria-controls": resolvedInputId, "aria-haspopup": "dialog", children: _jsx("p", { id: messageId, className: resolvedMessageParagraphClassName, children: messageParagraph }) }), _jsx("input", { ref: fileInputRef, id: resolvedInputId, type: "file", className: inputClasses, onChange: onChange, accept: acceptTypes, multiple: true, "aria-hidden": "true", tabIndex: -1 })] }));
|
|
50
|
+
};
|
|
51
|
+
export const FileSelector = memo(FileSelectorComponent);
|
|
52
|
+
FileSelector.displayName = "FileSelector";
|
|
53
|
+
//# sourceMappingURL=FileSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSelector.js","sourceRoot":"","sources":["../../../../src/shared/components/FileSelector/FileSelector.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/shared/components/FileSelector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { isEqual } from "@mainframework/is-deep-equal";
|
|
4
|
+
export const useCustomCallback = (callback, dependencies) => {
|
|
5
|
+
const refCallback = useRef(callback);
|
|
6
|
+
const refDependencies = useRef(dependencies);
|
|
7
|
+
// Update refs synchronously during render
|
|
8
|
+
if (!dependencies.every((dep, index) => isEqual(dep, refDependencies.current[index]))) {
|
|
9
|
+
refDependencies.current = dependencies;
|
|
10
|
+
refCallback.current = callback;
|
|
11
|
+
}
|
|
12
|
+
// Stable callback, always calls latest callback
|
|
13
|
+
const stableCallback = useRef((...args) => refCallback.current(...args)).current;
|
|
14
|
+
return stableCallback;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=useCustomCallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCustomCallback.js","sourceRoot":"","sources":["../../../src/shared/hooks/useCustomCallback.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAEvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAoC,QAAW,EAAE,YAAuB,EAAK,EAAE;IAC9G,MAAM,WAAW,GAAG,MAAM,CAAI,QAAQ,CAAC,CAAC;IACxC,MAAM,eAAe,GAAG,MAAM,CAAY,YAAY,CAAC,CAAC;IAExD,0CAA0C;IAC1C,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;QACvC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC;IAED,gDAAgD;IAChD,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,GAAG,IAAmB,EAAiB,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IAE/G,OAAO,cAAmB,CAAC;AAC7B,CAAC,CAAC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useRef, useState, useMemo } from "react";
|
|
4
|
+
import { defaultTypeExtensions, maximumUploadCount as maxUploadCount, maximumFileSize as maxFileSize, printableMaximumFileSize, checkFilesMaximumSize, isValidFileType, SvgXmlnsAttributeCheck, checkFile, clearBlobFromMemory, } from "../utils/processUploadedFiles";
|
|
5
|
+
import { useCustomCallback } from "./useCustomCallback";
|
|
6
|
+
import { FileSelector } from "../components/FileSelector";
|
|
7
|
+
export const useFileSelector = ({ maximumUploadCount = maxUploadCount, maximumFileSize = maxFileSize, acceptedTypes = defaultTypeExtensions, } = {}) => {
|
|
8
|
+
//State
|
|
9
|
+
//Trigger a re-render
|
|
10
|
+
const [, setUpdateTrigger] = useState(0);
|
|
11
|
+
const [validFiles, SetValidFiles] = useState([]);
|
|
12
|
+
const [invalidFiles, SetInvalidFiles] = useState([]);
|
|
13
|
+
//Refs
|
|
14
|
+
const maxUploadErrorRef = useRef({
|
|
15
|
+
status: false,
|
|
16
|
+
message: "",
|
|
17
|
+
});
|
|
18
|
+
const maxFileSizeErrorRef = useRef({
|
|
19
|
+
status: false,
|
|
20
|
+
message: "",
|
|
21
|
+
});
|
|
22
|
+
const setMaximumUploadsExceeded = useCallback((status = false, fileCount, maximumUploads) => {
|
|
23
|
+
maxUploadErrorRef.current.status = status;
|
|
24
|
+
maxUploadErrorRef.current.message = status
|
|
25
|
+
? `You have attempted to upload ${fileCount} files. The maximum allowable uploads for this feature is ${maximumUploads}`
|
|
26
|
+
: "";
|
|
27
|
+
setUpdateTrigger((state) => (state += 1));
|
|
28
|
+
}, []);
|
|
29
|
+
const setMaximumFileSizeExceeded = useCallback((status = false) => {
|
|
30
|
+
maxFileSizeErrorRef.current.status = status;
|
|
31
|
+
maxFileSizeErrorRef.current.message = status
|
|
32
|
+
? `You have attempted upload a file(s) that exceeds the maximum size of ${printableMaximumFileSize}`
|
|
33
|
+
: "";
|
|
34
|
+
setUpdateTrigger((state) => (state += 1));
|
|
35
|
+
}, []);
|
|
36
|
+
const clearBlobs = useCustomCallback(() => {
|
|
37
|
+
//Remove any blobs created in memory
|
|
38
|
+
let i = 0;
|
|
39
|
+
while (i < validFiles.length) {
|
|
40
|
+
const file = validFiles[i].file;
|
|
41
|
+
if (file instanceof File) {
|
|
42
|
+
clearBlobFromMemory(file);
|
|
43
|
+
}
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
}, [validFiles]);
|
|
47
|
+
const clearCache = useCustomCallback(() => {
|
|
48
|
+
//Clear any blobs held in memory
|
|
49
|
+
clearBlobs();
|
|
50
|
+
SetInvalidFiles([]);
|
|
51
|
+
SetValidFiles([]);
|
|
52
|
+
}, [clearBlobs]);
|
|
53
|
+
const onCancel = useCustomCallback(() => {
|
|
54
|
+
clearCache();
|
|
55
|
+
}, [clearCache]);
|
|
56
|
+
const getValidFileStreams = useCallback(() => (validFiles.length ? validFiles.map(({ file }) => file) : []), [validFiles]);
|
|
57
|
+
//Main Engine to deal with files
|
|
58
|
+
const processFiles = useCustomCallback((files) => {
|
|
59
|
+
const maxFileSizeCheck = checkFilesMaximumSize(files, maximumFileSize) && !maxFileSizeErrorRef.current.status;
|
|
60
|
+
const maxUploadCountCheck = typeof maximumUploadCount !== "undefined"
|
|
61
|
+
? !maxUploadErrorRef.current.status && files.length > maximumUploadCount
|
|
62
|
+
: false;
|
|
63
|
+
if (maxFileSizeCheck || maxUploadCountCheck) {
|
|
64
|
+
if (maxFileSizeCheck)
|
|
65
|
+
setMaximumFileSizeExceeded(true);
|
|
66
|
+
if (maxUploadCountCheck)
|
|
67
|
+
setMaximumUploadsExceeded(true, files.length, maximumUploadCount);
|
|
68
|
+
onCancel();
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const valid = [];
|
|
72
|
+
const invalid = [];
|
|
73
|
+
let i = 0;
|
|
74
|
+
while (i < files.length) {
|
|
75
|
+
const file = files[i];
|
|
76
|
+
if (isValidFileType(file, acceptedTypes)) {
|
|
77
|
+
valid.push(SvgXmlnsAttributeCheck(file, acceptedTypes));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
invalid.push(file);
|
|
81
|
+
}
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
if (valid.length > 0) {
|
|
85
|
+
Promise.all(valid)
|
|
86
|
+
.then((results) => {
|
|
87
|
+
const filteredResults = [];
|
|
88
|
+
let j = 0;
|
|
89
|
+
while (j < results.length) {
|
|
90
|
+
const result = results[j];
|
|
91
|
+
if (result !== null) {
|
|
92
|
+
filteredResults.push(result);
|
|
93
|
+
}
|
|
94
|
+
j++;
|
|
95
|
+
}
|
|
96
|
+
SetValidFiles(filteredResults);
|
|
97
|
+
})
|
|
98
|
+
.catch((error) => {
|
|
99
|
+
console.error("File processing error:", error);
|
|
100
|
+
// Optionally expose error state to engineers
|
|
101
|
+
SetInvalidFiles(invalid.concat(files)); // Treat all as invalid on error
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (invalid.length > 0) {
|
|
105
|
+
SetInvalidFiles(invalid);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}, [
|
|
109
|
+
acceptedTypes,
|
|
110
|
+
maximumFileSize,
|
|
111
|
+
maximumUploadCount,
|
|
112
|
+
setMaximumFileSizeExceeded,
|
|
113
|
+
setMaximumUploadsExceeded,
|
|
114
|
+
onCancel,
|
|
115
|
+
]);
|
|
116
|
+
const onRemoveFile = useCustomCallback((index) => {
|
|
117
|
+
const updatedValidFiles = [];
|
|
118
|
+
let i = 0;
|
|
119
|
+
while (i < validFiles.length) {
|
|
120
|
+
if (i === index) {
|
|
121
|
+
const file = validFiles[i].file;
|
|
122
|
+
if (file instanceof File) {
|
|
123
|
+
clearBlobFromMemory(file);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
updatedValidFiles.push(validFiles[i]);
|
|
128
|
+
}
|
|
129
|
+
i++;
|
|
130
|
+
}
|
|
131
|
+
SetValidFiles(updatedValidFiles);
|
|
132
|
+
}, [validFiles]);
|
|
133
|
+
const onIdChange = useCallback((index, id, files) => {
|
|
134
|
+
const updatedValidFiles = files.map((fileData, i) => {
|
|
135
|
+
if (i === index) {
|
|
136
|
+
const renamedFile = checkFile(id, fileData.file);
|
|
137
|
+
return { ...fileData, file: renamedFile, id };
|
|
138
|
+
}
|
|
139
|
+
return fileData;
|
|
140
|
+
});
|
|
141
|
+
SetValidFiles(updatedValidFiles);
|
|
142
|
+
}, []);
|
|
143
|
+
const onInputChange = useCustomCallback((event) => {
|
|
144
|
+
const files = Array.from(event.target.files || []);
|
|
145
|
+
processFiles(files);
|
|
146
|
+
}, [processFiles]);
|
|
147
|
+
//Drag and Drop
|
|
148
|
+
const onDrop = useCustomCallback((e) => {
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
processFiles(Array.from(e.dataTransfer.files));
|
|
151
|
+
}, [processFiles]);
|
|
152
|
+
const onDragOver = useCallback((e) => {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
e.dataTransfer.dropEffect = "copy";
|
|
155
|
+
}, []);
|
|
156
|
+
const onDragEnter = useCallback((e) => {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
const { classList } = e.currentTarget;
|
|
159
|
+
classList.add("border-yellow-400");
|
|
160
|
+
classList.remove("border-silver-600");
|
|
161
|
+
}, []);
|
|
162
|
+
const onDragLeave = useCallback((e) => {
|
|
163
|
+
e.preventDefault();
|
|
164
|
+
const currentTarget = e.currentTarget;
|
|
165
|
+
const timeoutId = setTimeout(() => {
|
|
166
|
+
if (currentTarget && !currentTarget.contains(e.relatedTarget)) {
|
|
167
|
+
const { classList } = currentTarget;
|
|
168
|
+
classList.remove("border-yellow-400");
|
|
169
|
+
classList.add("border-silver-600");
|
|
170
|
+
}
|
|
171
|
+
clearTimeout(timeoutId);
|
|
172
|
+
}, 200);
|
|
173
|
+
}, []);
|
|
174
|
+
// const FileSelectorRef = useRef(() => (
|
|
175
|
+
// <FileSelector
|
|
176
|
+
// acceptTypes={acceptTypes}
|
|
177
|
+
// onChange={onInputChange}
|
|
178
|
+
// onDragOver={onDragOver}
|
|
179
|
+
// onDrop={onDrop}
|
|
180
|
+
// onDragEnter={onDragEnter}
|
|
181
|
+
// onDragLeave={onDragLeave}
|
|
182
|
+
// />
|
|
183
|
+
// ));
|
|
184
|
+
// In useFileSelector.ts, create a wrapper component
|
|
185
|
+
const createFileSelectorComponent = (handlers) => {
|
|
186
|
+
// Return a component that accepts only the visual/accessibility props
|
|
187
|
+
const Component = (props) => (_jsx(FileSelector, { ...props, onChange: handlers.onInputChange, onDragOver: handlers.onDragOver, onDrop: handlers.onDrop, onDragEnter: handlers.onDragEnter, onDragLeave: handlers.onDragLeave }));
|
|
188
|
+
Component.displayName = "FileSelectorWrapper"; // <-- fix the ESLint warning
|
|
189
|
+
return Component;
|
|
190
|
+
};
|
|
191
|
+
// Then in the hook's return:
|
|
192
|
+
const BoundFileSelector = useMemo(() => createFileSelectorComponent({
|
|
193
|
+
onInputChange,
|
|
194
|
+
onDragOver,
|
|
195
|
+
onDrop,
|
|
196
|
+
onDragEnter,
|
|
197
|
+
onDragLeave,
|
|
198
|
+
}), [onInputChange, onDragOver, onDrop, onDragEnter, onDragLeave]);
|
|
199
|
+
return {
|
|
200
|
+
//Properties
|
|
201
|
+
validFiles,
|
|
202
|
+
invalidFiles,
|
|
203
|
+
//Methods
|
|
204
|
+
clearCache,
|
|
205
|
+
getValidFileStreams,
|
|
206
|
+
onCancel,
|
|
207
|
+
onIdChange,
|
|
208
|
+
onRemoveFile,
|
|
209
|
+
clearBlobs,
|
|
210
|
+
clearBlob: clearBlobFromMemory,
|
|
211
|
+
//Errors
|
|
212
|
+
maxUploadError: maxUploadErrorRef.current,
|
|
213
|
+
maxFileSizeError: maxFileSizeErrorRef.current,
|
|
214
|
+
setMaximumFileSizeExceeded,
|
|
215
|
+
setMaximumUploadsExceeded,
|
|
216
|
+
//Component - Export the FileSelector
|
|
217
|
+
FileSelector: BoundFileSelector,
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
//# sourceMappingURL=useFileSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFileSelector.js","sourceRoot":"","sources":["../../../src/shared/hooks/useFileSelector.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/shared/types/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dragAndDrop.js","sourceRoot":"","sources":["../../../src/shared/utils/dragAndDrop.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAA2B,OAAuB,EAAE,EAAE;IACpF,OAAO,CAAC,CAAI,EAAE,EAAE;QACd,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,CAAC,CAAC,CAAC;IACb,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeStyles.js","sourceRoot":"","sources":["../../../src/shared/utils/mergeStyles.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAG,MAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//Use this to quickly get the file extensions
|
|
3
|
+
//Devs can pass their own custom type mappings to override these defaults
|
|
4
|
+
export const defaultTypeExtensions = {
|
|
5
|
+
"image/png": ".png",
|
|
6
|
+
"image/jpeg": ".jpeg",
|
|
7
|
+
"image/jpg": ".jpg",
|
|
8
|
+
"image/svg+xml": ".svg",
|
|
9
|
+
"application/pdf": ".pdf",
|
|
10
|
+
"application/msword": ".doc",
|
|
11
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
12
|
+
};
|
|
13
|
+
//This is the attribute that should be present in all svg files
|
|
14
|
+
const xmlns = "<svg xmlns='http://www.w3.org/2000/svg'";
|
|
15
|
+
export const maximumUploadCount = 30;
|
|
16
|
+
export const maximumFileSize = 5e6; //5 mb's
|
|
17
|
+
export const printableMaximumFileSize = "5 Megabytes";
|
|
18
|
+
// HELPER: Extract file ID (filename without extension)
|
|
19
|
+
/*
|
|
20
|
+
* Extracts filename without extension, handling multiple dots correctly.
|
|
21
|
+
* "my.photo.final.png" -> "my.photo.final"
|
|
22
|
+
* "README.md" -> "README"
|
|
23
|
+
* "no-extension" -> "no-extension"
|
|
24
|
+
*/
|
|
25
|
+
const getFileId = (fileName) => {
|
|
26
|
+
const lastDotIndex = fileName.lastIndexOf(".");
|
|
27
|
+
return lastDotIndex > 0 ? fileName.slice(0, lastDotIndex) : fileName;
|
|
28
|
+
};
|
|
29
|
+
// BLOB URL REGISTRY - WeakMap for automatic GC cleanup
|
|
30
|
+
/*
|
|
31
|
+
* WeakMap prevents memory leaks by allowing GC to reclaim File objects.
|
|
32
|
+
* No manual cleanup needed when Files are no longer referenced.
|
|
33
|
+
*/
|
|
34
|
+
const blobUrlRegistry = new WeakMap();
|
|
35
|
+
export const createUrlString = (file) => {
|
|
36
|
+
const existing = blobUrlRegistry.get(file);
|
|
37
|
+
if (existing)
|
|
38
|
+
return existing;
|
|
39
|
+
const url = URL.createObjectURL(file);
|
|
40
|
+
blobUrlRegistry.set(file, url);
|
|
41
|
+
return url;
|
|
42
|
+
};
|
|
43
|
+
export const clearBlobFromMemory = (file) => {
|
|
44
|
+
const url = blobUrlRegistry.get(file);
|
|
45
|
+
if (!url)
|
|
46
|
+
return;
|
|
47
|
+
URL.revokeObjectURL(url);
|
|
48
|
+
blobUrlRegistry.delete(file);
|
|
49
|
+
};
|
|
50
|
+
/*
|
|
51
|
+
* Creates a blob URL with automatic cleanup after specified duration.
|
|
52
|
+
* Returns object with url and cancel function for lifecycle control.
|
|
53
|
+
*
|
|
54
|
+
* @param file - The file to create a URL for
|
|
55
|
+
* @param autoCleanupMs - Milliseconds before auto-cleanup (default: 5 minutes)
|
|
56
|
+
* @returns Object with url and cancel function
|
|
57
|
+
*/
|
|
58
|
+
export const createUrlStringWithAutoCleanup = (file, autoCleanupMs = 300_000) => {
|
|
59
|
+
const url = createUrlString(file);
|
|
60
|
+
const timer = setTimeout(() => {
|
|
61
|
+
clearBlobFromMemory(file);
|
|
62
|
+
}, autoCleanupMs);
|
|
63
|
+
return {
|
|
64
|
+
url,
|
|
65
|
+
cancel: () => {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
clearBlobFromMemory(file);
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
// VALIDATION FUNCTIONS
|
|
72
|
+
/*
|
|
73
|
+
* Checks if file type is in accepted types map.
|
|
74
|
+
* Uses 'in' operator for better performance than Boolean() conversion.
|
|
75
|
+
*/
|
|
76
|
+
export const isValidFileType = (file, acceptedTypes = defaultTypeExtensions) => file.type in acceptedTypes;
|
|
77
|
+
export const hasSurpassedMaxSize = (file, maxSize = maximumFileSize) => file.size > maxSize;
|
|
78
|
+
/*
|
|
79
|
+
* Returns true if ANY file exceeds the maximum size limit.
|
|
80
|
+
* Optimized with for-loop to avoid callback allocations in hot path.
|
|
81
|
+
*/
|
|
82
|
+
export const checkFilesMaximumSize = (files, max = maximumFileSize) => {
|
|
83
|
+
let i = 0;
|
|
84
|
+
while (i < files.length) {
|
|
85
|
+
if (files[i].size > max)
|
|
86
|
+
return true;
|
|
87
|
+
i++;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
};
|
|
91
|
+
// DOCUMENT CREATION
|
|
92
|
+
/*
|
|
93
|
+
* Creates document data object with file metadata.
|
|
94
|
+
* Returns null if file type is not in allowableTypes to prevent invalid state.
|
|
95
|
+
*/
|
|
96
|
+
const createDocumentData = (file, allowableTypes = defaultTypeExtensions) => {
|
|
97
|
+
const type = allowableTypes[file.type];
|
|
98
|
+
if (!type)
|
|
99
|
+
return null;
|
|
100
|
+
return {
|
|
101
|
+
id: getFileId(file.name),
|
|
102
|
+
type,
|
|
103
|
+
file,
|
|
104
|
+
url: createUrlString(file),
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
/*
|
|
108
|
+
* Optimized SVG xmlns check - only reads first 2KB initially.
|
|
109
|
+
* Avoids toLowerCase() allocation and uses safer regex for replacement.
|
|
110
|
+
*/
|
|
111
|
+
export const SvgXmlnsAttributeCheck = async (file, allowableTypes = defaultTypeExtensions) => {
|
|
112
|
+
if (file.type !== "image/svg+xml") {
|
|
113
|
+
return createDocumentData(file, allowableTypes);
|
|
114
|
+
}
|
|
115
|
+
// OPTIMIZATION: Only read first 2KB to check for xmlns
|
|
116
|
+
const chunk = file.slice(0, 2048);
|
|
117
|
+
const text = await chunk.text();
|
|
118
|
+
// No toLowerCase() needed - xmlns attribute is case-sensitive in XML
|
|
119
|
+
if (text.includes("xmlns=")) {
|
|
120
|
+
return createDocumentData(file, allowableTypes);
|
|
121
|
+
}
|
|
122
|
+
// Missing the xmlns attribute, add it
|
|
123
|
+
// Need full file content for modification
|
|
124
|
+
const fullText = await file.text();
|
|
125
|
+
// SAFER: Use regex with word boundary instead of simple string replace
|
|
126
|
+
// Handles <svg> without space and various attribute orders
|
|
127
|
+
const svgWithXmlns = fullText.replace(/<svg\b/, xmlns);
|
|
128
|
+
return createDocumentData(new File([svgWithXmlns], file.name, {
|
|
129
|
+
type: file.type,
|
|
130
|
+
}), allowableTypes);
|
|
131
|
+
};
|
|
132
|
+
// FILE RENAMING
|
|
133
|
+
/*
|
|
134
|
+
* Renames a file or blob. Optimized to avoid unnecessary File creation
|
|
135
|
+
* if name already matches.
|
|
136
|
+
*/
|
|
137
|
+
export const renameFile = (file, name) => file instanceof File && file.name === name ? file : new File([file], name, { type: file.type });
|
|
138
|
+
/*
|
|
139
|
+
* Checks if file needs renaming based on ID comparison.
|
|
140
|
+
* - Handles Blobs (no name) by converting to File
|
|
141
|
+
* - Avoids repeated string operations
|
|
142
|
+
* - Case-sensitive comparison
|
|
143
|
+
*/
|
|
144
|
+
export const checkFile = (id, file) => {
|
|
145
|
+
// No ID provided, return as-is
|
|
146
|
+
if (!id)
|
|
147
|
+
return file;
|
|
148
|
+
// Handle Blob (not a File subclass)
|
|
149
|
+
if (!(file instanceof File)) {
|
|
150
|
+
return renameFile(file, id);
|
|
151
|
+
}
|
|
152
|
+
// It's a File - check if renaming is needed
|
|
153
|
+
const currentId = getFileId(file.name);
|
|
154
|
+
return id === currentId ? file : renameFile(file, id);
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=processUploadedFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processUploadedFiles.js","sourceRoot":"","sources":["../../../src/shared/utils/processUploadedFiles.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|