@nolwenture/formik-jsonschema-form 1.0.0-beta.55 → 1.0.0-beta.57
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/cjs/Form/fields/FilesUploadField/FilesUploadField.js +30 -11
- package/dist/cjs/Form/fields/FilesUploadField/FilesUploadFieldInput.js +2 -2
- package/dist/esm/Form/fields/FilesUploadField/FilesUploadField.js +30 -11
- package/dist/esm/Form/fields/FilesUploadField/FilesUploadFieldInput.js +2 -2
- package/dist/types/Form/fields/FilesUploadField/FilesUploadFieldInput.d.ts +5 -4
- package/dist/types/common/FilesUploadContext.d.ts +8 -3
- package/package.json +1 -1
|
@@ -17,27 +17,45 @@ const FilesUploadField = (props) => {
|
|
|
17
17
|
const value = (0, formik_1.getIn)(values, name);
|
|
18
18
|
const { uploadFiles, removeFile } = (0, react_1.useContext)(FilesUploadContext_1.FilesUploadContext);
|
|
19
19
|
const [uploadedFiles, setUploadedFiles] = (0, react_1.useState)([]);
|
|
20
|
-
(0, react_1.useEffect)(() => {
|
|
21
|
-
(async () => setUploadedFiles(value))();
|
|
22
|
-
}, [value]);
|
|
23
20
|
const [uploadProgress, setUploadProgress] = (0, react_1.useState)({});
|
|
21
|
+
(0, react_1.useEffect)(() => {
|
|
22
|
+
setUploadedFiles(() => value.map(f => ({
|
|
23
|
+
name: f.name,
|
|
24
|
+
id: f.id,
|
|
25
|
+
progressId: f.id,
|
|
26
|
+
mimeType: f.mimeType,
|
|
27
|
+
size: f.size
|
|
28
|
+
})));
|
|
29
|
+
value.forEach(f => setUploadProgress((prev) => ({ ...prev, [f.id]: 100 })));
|
|
30
|
+
}, []);
|
|
24
31
|
const handleFileUpload = async (files, setFieldValue) => {
|
|
25
|
-
const
|
|
32
|
+
const filesWithIds = [];
|
|
33
|
+
const newFiles = [];
|
|
26
34
|
for (const file of files) {
|
|
27
|
-
|
|
35
|
+
const progressId = file.name + file.size + file.lastModified + Math.random();
|
|
36
|
+
filesWithIds.push({ data: file, progressId });
|
|
37
|
+
newFiles.push({ name: file.name, size: file.size, progressId, mimeType: file.type, id: null });
|
|
28
38
|
}
|
|
39
|
+
setUploadedFiles((f) => f.concat(newFiles));
|
|
29
40
|
try {
|
|
30
41
|
const result = await uploadFiles({
|
|
31
|
-
|
|
32
|
-
onUploadProgress: (progressEvent,
|
|
42
|
+
files: filesWithIds,
|
|
43
|
+
onUploadProgress: (progressEvent, progressId) => {
|
|
33
44
|
const totalLength = progressEvent.total;
|
|
34
45
|
if (totalLength !== null && totalLength !== undefined) {
|
|
35
46
|
const progress = Math.round((progressEvent.loaded * 100) / totalLength);
|
|
36
|
-
setUploadProgress((prev) => ({ ...prev, [
|
|
47
|
+
setUploadProgress((prev) => ({ ...prev, [progressId]: progress }));
|
|
37
48
|
}
|
|
38
49
|
},
|
|
39
50
|
});
|
|
40
|
-
|
|
51
|
+
// remove progressId values for adding to form data
|
|
52
|
+
const newFormValues = result.map(({ progressId, ...rest }) => rest);
|
|
53
|
+
// update ids for uploaded files
|
|
54
|
+
setUploadedFiles(prev => prev.map(item => {
|
|
55
|
+
const match = result.find(f => f.progressId === item.progressId);
|
|
56
|
+
return match ? { ...item, id: match.id } : item;
|
|
57
|
+
}));
|
|
58
|
+
const newValue = (Array.isArray(value) ? value : []).concat(newFormValues);
|
|
41
59
|
setFieldValue(name, newValue);
|
|
42
60
|
}
|
|
43
61
|
catch (error) {
|
|
@@ -48,10 +66,11 @@ const FilesUploadField = (props) => {
|
|
|
48
66
|
if (file.id) {
|
|
49
67
|
await removeFile(file);
|
|
50
68
|
setUploadProgress((prev) => {
|
|
51
|
-
const { [file.
|
|
69
|
+
const { [file.progressId]: _, ...rest } = prev;
|
|
52
70
|
return rest;
|
|
53
71
|
});
|
|
54
|
-
|
|
72
|
+
setUploadedFiles((prev) => prev.filter(f => f.id !== file.id));
|
|
73
|
+
setFieldValue(name, (value || []).filter((f) => f.id !== file.id));
|
|
55
74
|
}
|
|
56
75
|
};
|
|
57
76
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
@@ -63,10 +63,10 @@ const FilesUploadFieldInput = ({ acceptedFiletypes, className, deleteFileAriaLab
|
|
|
63
63
|
e.dataTransfer.clearData();
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
|
-
const defaultRenderFile = (file, progress, onDelete) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: progress === 100 ? ((0, jsx_runtime_1.jsxs)(UploadedFileItemContainer, { children: [(0, jsx_runtime_1.jsxs)(UploadedFileInfoContainer, { children: [!hideFileTypeIcon && ((0, jsx_runtime_1.jsx)(FileTypeIcon, { children: getFileIcon(file.mimeType) })), (0, jsx_runtime_1.jsxs)(UploadedFileName, { children: [file.name, !hideFileSize && ((0, jsx_runtime_1.jsx)(FileSize, { children: ` | ${(file.size / (1024 * 1024)).toFixed(3)} MB` }))] })] }), !hideRemoveButton && ((0, jsx_runtime_1.jsx)(RemoveButton, { "aria-label": deleteFileAriaLabel ?? "Delete file", type: "button", onClick: () => onDelete(), ...removeButton?.props, children: removeButton?.content ?? (0, jsx_runtime_1.jsx)(RemoveButtonIcon, {}) }))] })) : ((0, jsx_runtime_1.jsxs)(FileItemContainer, { children: [(0, jsx_runtime_1.jsx)(UploadingFileName, { children: file.name }), (0, jsx_runtime_1.jsx)(ProgressBarContainer, { children: (0, jsx_runtime_1.jsx)(ProgressBar, { "$progress": progress }) })] })) }));
|
|
66
|
+
const defaultRenderFile = (file, progress, onDelete) => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: progress === 100 ? ((0, jsx_runtime_1.jsxs)(UploadedFileItemContainer, { children: [(0, jsx_runtime_1.jsxs)(UploadedFileInfoContainer, { children: [!hideFileTypeIcon && ((0, jsx_runtime_1.jsx)(FileTypeIcon, { children: getFileIcon(file.mimeType ?? "") })), (0, jsx_runtime_1.jsxs)(UploadedFileName, { children: [file.name, !hideFileSize && ((0, jsx_runtime_1.jsx)(FileSize, { children: ` | ${file.size ? (file.size / (1024 * 1024)).toFixed(3) : "?"} MB` }))] })] }), !hideRemoveButton && file.id && ((0, jsx_runtime_1.jsx)(RemoveButton, { "aria-label": deleteFileAriaLabel ?? "Delete file", type: "button", onClick: () => onDelete(), ...removeButton?.props, children: removeButton?.content ?? (0, jsx_runtime_1.jsx)(RemoveButtonIcon, {}) }))] })) : ((0, jsx_runtime_1.jsxs)(FileItemContainer, { children: [(0, jsx_runtime_1.jsx)(UploadingFileName, { children: file.name }), (0, jsx_runtime_1.jsx)(ProgressBarContainer, { children: (0, jsx_runtime_1.jsx)(ProgressBar, { "$progress": progress }) })] })) }));
|
|
67
67
|
const uploadedFile = renderFile ?? defaultRenderFile;
|
|
68
68
|
const fileTypes = acceptedFiletypes ? { accept: acceptedFiletypes } : {};
|
|
69
|
-
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(FileUploadFieldContainer, { className: className, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [isDragging && ((0, jsx_runtime_1.jsx)(DragOverlay, { children: infoText })), Array.isArray(uploadedFiles) && uploadedFiles.map(file => ((0, jsx_runtime_1.jsx)(UploadedFileWrapper, { children: uploadedFile(file, uploadProgress[file.
|
|
69
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(FileUploadFieldContainer, { className: className, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [isDragging && ((0, jsx_runtime_1.jsx)(DragOverlay, { children: infoText })), Array.isArray(uploadedFiles) && uploadedFiles.map(file => ((0, jsx_runtime_1.jsx)(UploadedFileWrapper, { children: uploadedFile(file, uploadProgress[file.progressId], () => handleRemoveFile(file, setFieldValue)) }, file.progressId))), !uploadedFiles || uploadedFiles.length === 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!hideUploadIcon && (0, jsx_runtime_1.jsx)(UploadIcon, {}), infoText && (0, jsx_runtime_1.jsx)(InfoText, { children: infoText }), (0, jsx_runtime_1.jsx)(Divider, { children: (0, jsx_runtime_1.jsx)(DividerText, { children: orText ?? "or" }) }), (0, jsx_runtime_1.jsx)(FileUploadButton, { "aria-label": uploadButtonText ?? "Browse files", type: "button", onClick: () => document.getElementById(name)?.click(), children: uploadButtonText ?? "Browse files" }), fileInfoText && (0, jsx_runtime_1.jsx)(FileInfoText, { children: fileInfoText })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [infoText && ((0, jsx_runtime_1.jsxs)(InfoText, { children: [`${infoText} ${orText ?? 'or'} `, (0, jsx_runtime_1.jsx)(FileUploadText, { "aria-label": uploadButtonText ?? 'Browse files', onClick: () => document.getElementById(name)?.click(), children: uploadButtonText ?? 'Browse files' })] })), fileInfoText && (0, jsx_runtime_1.jsx)(FileInfoTextMinimized, { children: fileInfoText })] })), (0, jsx_runtime_1.jsx)(HiddenFileInput, { multiple: true, ...fileTypes, id: name, name: name, type: "file", onChange: (event) => {
|
|
70
70
|
const files = event.target.files;
|
|
71
71
|
if (files) {
|
|
72
72
|
handleFileUpload(files, setFieldValue);
|
|
@@ -14,27 +14,45 @@ export const FilesUploadField = (props) => {
|
|
|
14
14
|
const value = getIn(values, name);
|
|
15
15
|
const { uploadFiles, removeFile } = useContext(FilesUploadContext);
|
|
16
16
|
const [uploadedFiles, setUploadedFiles] = useState([]);
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
(async () => setUploadedFiles(value))();
|
|
19
|
-
}, [value]);
|
|
20
17
|
const [uploadProgress, setUploadProgress] = useState({});
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
setUploadedFiles(() => value.map(f => ({
|
|
20
|
+
name: f.name,
|
|
21
|
+
id: f.id,
|
|
22
|
+
progressId: f.id,
|
|
23
|
+
mimeType: f.mimeType,
|
|
24
|
+
size: f.size
|
|
25
|
+
})));
|
|
26
|
+
value.forEach(f => setUploadProgress((prev) => ({ ...prev, [f.id]: 100 })));
|
|
27
|
+
}, []);
|
|
21
28
|
const handleFileUpload = async (files, setFieldValue) => {
|
|
22
|
-
const
|
|
29
|
+
const filesWithIds = [];
|
|
30
|
+
const newFiles = [];
|
|
23
31
|
for (const file of files) {
|
|
24
|
-
|
|
32
|
+
const progressId = file.name + file.size + file.lastModified + Math.random();
|
|
33
|
+
filesWithIds.push({ data: file, progressId });
|
|
34
|
+
newFiles.push({ name: file.name, size: file.size, progressId, mimeType: file.type, id: null });
|
|
25
35
|
}
|
|
36
|
+
setUploadedFiles((f) => f.concat(newFiles));
|
|
26
37
|
try {
|
|
27
38
|
const result = await uploadFiles({
|
|
28
|
-
|
|
29
|
-
onUploadProgress: (progressEvent,
|
|
39
|
+
files: filesWithIds,
|
|
40
|
+
onUploadProgress: (progressEvent, progressId) => {
|
|
30
41
|
const totalLength = progressEvent.total;
|
|
31
42
|
if (totalLength !== null && totalLength !== undefined) {
|
|
32
43
|
const progress = Math.round((progressEvent.loaded * 100) / totalLength);
|
|
33
|
-
setUploadProgress((prev) => ({ ...prev, [
|
|
44
|
+
setUploadProgress((prev) => ({ ...prev, [progressId]: progress }));
|
|
34
45
|
}
|
|
35
46
|
},
|
|
36
47
|
});
|
|
37
|
-
|
|
48
|
+
// remove progressId values for adding to form data
|
|
49
|
+
const newFormValues = result.map(({ progressId, ...rest }) => rest);
|
|
50
|
+
// update ids for uploaded files
|
|
51
|
+
setUploadedFiles(prev => prev.map(item => {
|
|
52
|
+
const match = result.find(f => f.progressId === item.progressId);
|
|
53
|
+
return match ? { ...item, id: match.id } : item;
|
|
54
|
+
}));
|
|
55
|
+
const newValue = (Array.isArray(value) ? value : []).concat(newFormValues);
|
|
38
56
|
setFieldValue(name, newValue);
|
|
39
57
|
}
|
|
40
58
|
catch (error) {
|
|
@@ -45,10 +63,11 @@ export const FilesUploadField = (props) => {
|
|
|
45
63
|
if (file.id) {
|
|
46
64
|
await removeFile(file);
|
|
47
65
|
setUploadProgress((prev) => {
|
|
48
|
-
const { [file.
|
|
66
|
+
const { [file.progressId]: _, ...rest } = prev;
|
|
49
67
|
return rest;
|
|
50
68
|
});
|
|
51
|
-
|
|
69
|
+
setUploadedFiles((prev) => prev.filter(f => f.id !== file.id));
|
|
70
|
+
setFieldValue(name, (value || []).filter((f) => f.id !== file.id));
|
|
52
71
|
}
|
|
53
72
|
};
|
|
54
73
|
const SelectedFieldTemplate = (props.uiSchema?.["ui:template"] &&
|
|
@@ -60,10 +60,10 @@ export const FilesUploadFieldInput = ({ acceptedFiletypes, className, deleteFile
|
|
|
60
60
|
e.dataTransfer.clearData();
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
-
const defaultRenderFile = (file, progress, onDelete) => (_jsx(_Fragment, { children: progress === 100 ? (_jsxs(UploadedFileItemContainer, { children: [_jsxs(UploadedFileInfoContainer, { children: [!hideFileTypeIcon && (_jsx(FileTypeIcon, { children: getFileIcon(file.mimeType) })), _jsxs(UploadedFileName, { children: [file.name, !hideFileSize && (_jsx(FileSize, { children: ` | ${(file.size / (1024 * 1024)).toFixed(3)} MB` }))] })] }), !hideRemoveButton && (_jsx(RemoveButton, { "aria-label": deleteFileAriaLabel ?? "Delete file", type: "button", onClick: () => onDelete(), ...removeButton?.props, children: removeButton?.content ?? _jsx(RemoveButtonIcon, {}) }))] })) : (_jsxs(FileItemContainer, { children: [_jsx(UploadingFileName, { children: file.name }), _jsx(ProgressBarContainer, { children: _jsx(ProgressBar, { "$progress": progress }) })] })) }));
|
|
63
|
+
const defaultRenderFile = (file, progress, onDelete) => (_jsx(_Fragment, { children: progress === 100 ? (_jsxs(UploadedFileItemContainer, { children: [_jsxs(UploadedFileInfoContainer, { children: [!hideFileTypeIcon && (_jsx(FileTypeIcon, { children: getFileIcon(file.mimeType ?? "") })), _jsxs(UploadedFileName, { children: [file.name, !hideFileSize && (_jsx(FileSize, { children: ` | ${file.size ? (file.size / (1024 * 1024)).toFixed(3) : "?"} MB` }))] })] }), !hideRemoveButton && file.id && (_jsx(RemoveButton, { "aria-label": deleteFileAriaLabel ?? "Delete file", type: "button", onClick: () => onDelete(), ...removeButton?.props, children: removeButton?.content ?? _jsx(RemoveButtonIcon, {}) }))] })) : (_jsxs(FileItemContainer, { children: [_jsx(UploadingFileName, { children: file.name }), _jsx(ProgressBarContainer, { children: _jsx(ProgressBar, { "$progress": progress }) })] })) }));
|
|
64
64
|
const uploadedFile = renderFile ?? defaultRenderFile;
|
|
65
65
|
const fileTypes = acceptedFiletypes ? { accept: acceptedFiletypes } : {};
|
|
66
|
-
return (_jsx(_Fragment, { children: _jsxs(FileUploadFieldContainer, { className: className, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [isDragging && (_jsx(DragOverlay, { children: infoText })), Array.isArray(uploadedFiles) && uploadedFiles.map(file => (_jsx(UploadedFileWrapper, { children: uploadedFile(file, uploadProgress[file.
|
|
66
|
+
return (_jsx(_Fragment, { children: _jsxs(FileUploadFieldContainer, { className: className, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [isDragging && (_jsx(DragOverlay, { children: infoText })), Array.isArray(uploadedFiles) && uploadedFiles.map(file => (_jsx(UploadedFileWrapper, { children: uploadedFile(file, uploadProgress[file.progressId], () => handleRemoveFile(file, setFieldValue)) }, file.progressId))), !uploadedFiles || uploadedFiles.length === 0 ? (_jsxs(_Fragment, { children: [!hideUploadIcon && _jsx(UploadIcon, {}), infoText && _jsx(InfoText, { children: infoText }), _jsx(Divider, { children: _jsx(DividerText, { children: orText ?? "or" }) }), _jsx(FileUploadButton, { "aria-label": uploadButtonText ?? "Browse files", type: "button", onClick: () => document.getElementById(name)?.click(), children: uploadButtonText ?? "Browse files" }), fileInfoText && _jsx(FileInfoText, { children: fileInfoText })] })) : (_jsxs(_Fragment, { children: [infoText && (_jsxs(InfoText, { children: [`${infoText} ${orText ?? 'or'} `, _jsx(FileUploadText, { "aria-label": uploadButtonText ?? 'Browse files', onClick: () => document.getElementById(name)?.click(), children: uploadButtonText ?? 'Browse files' })] })), fileInfoText && _jsx(FileInfoTextMinimized, { children: fileInfoText })] })), _jsx(HiddenFileInput, { multiple: true, ...fileTypes, id: name, name: name, type: "file", onChange: (event) => {
|
|
67
67
|
const files = event.target.files;
|
|
68
68
|
if (files) {
|
|
69
69
|
handleFileUpload(files, setFieldValue);
|
|
@@ -2,13 +2,14 @@ import React from "react";
|
|
|
2
2
|
import { FormikErrors } from "formik";
|
|
3
3
|
type UploadedFile = {
|
|
4
4
|
name: string;
|
|
5
|
-
id: string;
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
id: null | string;
|
|
6
|
+
progressId: string;
|
|
7
|
+
mimeType?: string;
|
|
8
|
+
size?: number;
|
|
8
9
|
};
|
|
9
10
|
export type FilesUploadFieldInputProps = {
|
|
10
11
|
name: string;
|
|
11
|
-
uploadedFiles:
|
|
12
|
+
uploadedFiles: UploadedFile[];
|
|
12
13
|
handleFileUpload: (files: FileList, setFieldValue: (field: string, value: any, shouldValidate?: boolean) => Promise<void | FormikErrors<any>>) => Promise<void>;
|
|
13
14
|
handleRemoveFile: (file: UploadedFile, setFieldValue: any) => void;
|
|
14
15
|
value: any;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { AxiosProgressEvent } from "axios";
|
|
2
2
|
export type FilesUploadContextType<T> = {
|
|
3
3
|
uploadFiles: (x: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
files: {
|
|
5
|
+
data: File;
|
|
6
|
+
progressId: string;
|
|
7
|
+
}[];
|
|
8
|
+
onUploadProgress?: (progressEvent: AxiosProgressEvent, progressId: string) => void;
|
|
9
|
+
}) => Promise<T & {
|
|
10
|
+
progressId: string;
|
|
11
|
+
}[]>;
|
|
7
12
|
removeFile: (file: T) => Promise<{
|
|
8
13
|
success: boolean;
|
|
9
14
|
message?: string;
|
package/package.json
CHANGED