@aws-amplify/ui-react-storage 3.2.0 → 3.3.0
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/esm/components/FileUploader/FileUploader.mjs +185 -0
- package/dist/esm/components/FileUploader/hooks/useFileUploader/actions.mjs +39 -0
- package/dist/esm/components/FileUploader/hooks/useFileUploader/reducer.mjs +93 -0
- package/dist/esm/components/FileUploader/hooks/useFileUploader/types.mjs +13 -0
- package/dist/esm/components/FileUploader/hooks/useFileUploader/useFileUploader.mjs +62 -0
- package/dist/esm/components/FileUploader/hooks/useUploadFiles/useUploadFiles.mjs +79 -0
- package/dist/esm/components/FileUploader/types.mjs +11 -0
- package/dist/esm/components/FileUploader/ui/Container/Container.mjs +8 -0
- package/dist/esm/components/FileUploader/ui/DropZone/DropZone.mjs +16 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileControl.mjs +23 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileDetails.mjs +12 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileList.mjs +44 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileRemoveButton.mjs +12 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileStatusMessage.mjs +28 -0
- package/dist/esm/components/FileUploader/ui/FileList/FileThumbnail.mjs +12 -0
- package/dist/esm/components/FileUploader/ui/FileListFooter/FileListFooter.mjs +13 -0
- package/dist/esm/components/FileUploader/ui/FileListHeader/FileListHeader.mjs +14 -0
- package/dist/esm/components/FileUploader/ui/FilePicker/FilePicker.mjs +9 -0
- package/dist/esm/components/FileUploader/utils/checkMaxFileSize.mjs +12 -0
- package/dist/esm/components/FileUploader/utils/displayText.mjs +39 -0
- package/dist/esm/components/FileUploader/utils/filterAllowedFiles.mjs +27 -0
- package/dist/esm/components/FileUploader/utils/getInput.mjs +39 -0
- package/dist/esm/components/FileUploader/utils/resolveFile.mjs +20 -0
- package/dist/esm/components/FileUploader/utils/uploadFile.mjs +26 -0
- package/dist/esm/components/StorageManager/StorageManager.mjs +4 -0
- package/dist/esm/components/StorageManager/ui/FileList/FileDetails.mjs +1 -4
- package/dist/esm/components/StorageManager/utils/checkMaxFileSize.mjs +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/version.mjs +1 -1
- package/dist/index.js +723 -37
- package/dist/styles.css +23 -42
- package/dist/types/components/FileUploader/FileUploader.d.ts +15 -0
- package/dist/types/components/FileUploader/hooks/index.d.ts +2 -0
- package/dist/types/components/FileUploader/hooks/useFileUploader/actions.d.ts +22 -0
- package/dist/types/components/FileUploader/hooks/useFileUploader/index.d.ts +1 -0
- package/dist/types/components/FileUploader/hooks/useFileUploader/reducer.d.ts +2 -0
- package/dist/types/components/FileUploader/hooks/useFileUploader/types.d.ts +50 -0
- package/dist/types/components/FileUploader/hooks/useFileUploader/useFileUploader.d.ts +35 -0
- package/dist/types/components/FileUploader/hooks/useUploadFiles/index.d.ts +1 -0
- package/dist/types/components/FileUploader/hooks/useUploadFiles/useUploadFiles.d.ts +12 -0
- package/dist/types/components/FileUploader/index.d.ts +3 -0
- package/dist/types/components/FileUploader/types.d.ts +129 -0
- package/dist/types/components/FileUploader/ui/Container/Container.d.ts +6 -0
- package/dist/types/components/FileUploader/ui/Container/index.d.ts +1 -0
- package/dist/types/components/FileUploader/ui/DropZone/DropZone.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/DropZone/index.d.ts +2 -0
- package/dist/types/components/FileUploader/ui/DropZone/types.d.ts +13 -0
- package/dist/types/components/FileUploader/ui/FileList/FileControl.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/FileDetails.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/FileList.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/FileRemoveButton.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/FileStatusMessage.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/FileThumbnail.d.ts +3 -0
- package/dist/types/components/FileUploader/ui/FileList/index.d.ts +2 -0
- package/dist/types/components/FileUploader/ui/FileList/types.d.ts +51 -0
- package/dist/types/components/FileUploader/ui/FileListFooter/FileListFooter.d.ts +9 -0
- package/dist/types/components/FileUploader/ui/FileListFooter/index.d.ts +1 -0
- package/dist/types/components/FileUploader/ui/FileListHeader/FileListHeader.d.ts +10 -0
- package/dist/types/components/FileUploader/ui/FileListHeader/index.d.ts +1 -0
- package/dist/types/components/FileUploader/ui/FilePicker/FilePicker.d.ts +4 -0
- package/dist/types/components/FileUploader/ui/FilePicker/index.d.ts +1 -0
- package/dist/types/components/FileUploader/ui/index.d.ts +6 -0
- package/dist/types/components/FileUploader/utils/checkMaxFileSize.d.ts +5 -0
- package/dist/types/components/FileUploader/utils/displayText.d.ts +22 -0
- package/dist/types/components/FileUploader/utils/filterAllowedFiles.d.ts +1 -0
- package/dist/types/components/FileUploader/utils/getInput.d.ts +17 -0
- package/dist/types/components/FileUploader/utils/index.d.ts +5 -0
- package/dist/types/components/FileUploader/utils/resolveFile.d.ts +9 -0
- package/dist/types/components/FileUploader/utils/uploadFile.d.ts +32 -0
- package/dist/types/components/StorageManager/utils/index.d.ts +0 -1
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -4
- package/dist/esm/components/StorageManager/utils/humanFileSize.mjs +0 -29
- package/dist/types/components/StorageManager/utils/humanFileSize.d.ts +0 -11
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var ui = require('@aws-amplify/ui');
|
|
7
7
|
var uiReact = require('@aws-amplify/ui-react');
|
|
8
|
-
var internal = require('@aws-amplify/ui-react/internal');
|
|
9
8
|
var uiReactCore = require('@aws-amplify/ui-react-core');
|
|
9
|
+
var internal = require('@aws-amplify/ui-react/internal');
|
|
10
10
|
var auth = require('aws-amplify/auth');
|
|
11
11
|
var storage = require('aws-amplify/storage');
|
|
12
12
|
|
|
@@ -24,16 +24,725 @@ function _interopNamespace(e) {
|
|
|
24
24
|
get: function () { return e[k]; }
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
n["default"] = e;
|
|
30
|
+
return Object.freeze(n);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
34
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
35
|
+
|
|
36
|
+
var FileStatus$1;
|
|
37
|
+
(function (FileStatus) {
|
|
38
|
+
FileStatus["ADDED"] = "added";
|
|
39
|
+
FileStatus["QUEUED"] = "queued";
|
|
40
|
+
FileStatus["UPLOADING"] = "uploading";
|
|
41
|
+
FileStatus["PAUSED"] = "paused";
|
|
42
|
+
FileStatus["ERROR"] = "error";
|
|
43
|
+
FileStatus["UPLOADED"] = "uploaded";
|
|
44
|
+
})(FileStatus$1 || (FileStatus$1 = {}));
|
|
45
|
+
|
|
46
|
+
var FileUploaderActionTypes;
|
|
47
|
+
(function (FileUploaderActionTypes) {
|
|
48
|
+
FileUploaderActionTypes["ADD_FILES"] = "ADD_FILES";
|
|
49
|
+
FileUploaderActionTypes["CLEAR_FILES"] = "CLEAR_FILES";
|
|
50
|
+
FileUploaderActionTypes["QUEUE_FILES"] = "QUEUE_FILES";
|
|
51
|
+
FileUploaderActionTypes["SET_STATUS"] = "SET_STATUS";
|
|
52
|
+
FileUploaderActionTypes["SET_PROCESSED_FILE_KEY"] = "SET_PROCESSED_FILE_KEY";
|
|
53
|
+
FileUploaderActionTypes["SET_STATUS_UPLOADING"] = "SET_STATUS_UPLOADING";
|
|
54
|
+
FileUploaderActionTypes["SET_UPLOAD_PROGRESS"] = "SET_UPLOAD_PROGRESS";
|
|
55
|
+
FileUploaderActionTypes["REMOVE_UPLOAD"] = "REMOVE_UPLOAD";
|
|
56
|
+
})(FileUploaderActionTypes || (FileUploaderActionTypes = {}));
|
|
57
|
+
|
|
58
|
+
const updateFiles$1 = (files, nextFileData) => files.reduce((files, currentFile) => {
|
|
59
|
+
if (currentFile.id === nextFileData.id) {
|
|
60
|
+
return [...files, { ...currentFile, ...nextFileData }];
|
|
61
|
+
}
|
|
62
|
+
return [...files, currentFile];
|
|
63
|
+
}, []);
|
|
64
|
+
function fileUploaderStateReducer(state, action) {
|
|
65
|
+
switch (action.type) {
|
|
66
|
+
case FileUploaderActionTypes.ADD_FILES: {
|
|
67
|
+
const { files, status } = action;
|
|
68
|
+
const newUploads = files.map((file) => {
|
|
69
|
+
const errorText = action.getFileErrorMessage(file);
|
|
70
|
+
return {
|
|
71
|
+
// make sure id is unique,
|
|
72
|
+
// we only use it internally and don't send it to Storage
|
|
73
|
+
id: `${Date.now()}-${file.name}`,
|
|
74
|
+
file,
|
|
75
|
+
error: errorText,
|
|
76
|
+
key: file.name,
|
|
77
|
+
status: errorText ? FileStatus$1.ERROR : status,
|
|
78
|
+
isImage: file.type.startsWith('image/'),
|
|
79
|
+
progress: -1,
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
const newFiles = [...state.files, ...newUploads];
|
|
83
|
+
return { ...state, files: newFiles };
|
|
84
|
+
}
|
|
85
|
+
case FileUploaderActionTypes.CLEAR_FILES: {
|
|
86
|
+
return { ...state, files: [] };
|
|
87
|
+
}
|
|
88
|
+
case FileUploaderActionTypes.QUEUE_FILES: {
|
|
89
|
+
const { files } = state;
|
|
90
|
+
const newFiles = files.reduce((files, currentFile) => {
|
|
91
|
+
return [
|
|
92
|
+
...files,
|
|
93
|
+
{
|
|
94
|
+
...currentFile,
|
|
95
|
+
...(currentFile.status === FileStatus$1.ADDED
|
|
96
|
+
? { status: FileStatus$1.QUEUED }
|
|
97
|
+
: {}),
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}, []);
|
|
101
|
+
return {
|
|
102
|
+
...state,
|
|
103
|
+
files: newFiles,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
case FileUploaderActionTypes.SET_STATUS_UPLOADING: {
|
|
107
|
+
const { id, uploadTask } = action;
|
|
108
|
+
const status = FileStatus$1.UPLOADING;
|
|
109
|
+
const progress = 0;
|
|
110
|
+
const nextFileData = { status, progress, id, uploadTask };
|
|
111
|
+
const files = updateFiles$1(state.files, nextFileData);
|
|
112
|
+
return { ...state, files };
|
|
113
|
+
}
|
|
114
|
+
case FileUploaderActionTypes.SET_PROCESSED_FILE_KEY: {
|
|
115
|
+
const { processedKey, id } = action;
|
|
116
|
+
const files = updateFiles$1(state.files, { processedKey, id });
|
|
117
|
+
return { files };
|
|
118
|
+
}
|
|
119
|
+
case FileUploaderActionTypes.SET_UPLOAD_PROGRESS: {
|
|
120
|
+
const { id, progress } = action;
|
|
121
|
+
const files = updateFiles$1(state.files, { id, progress });
|
|
122
|
+
return { ...state, files };
|
|
123
|
+
}
|
|
124
|
+
case FileUploaderActionTypes.SET_STATUS: {
|
|
125
|
+
const { id, status } = action;
|
|
126
|
+
const files = updateFiles$1(state.files, { id, status });
|
|
127
|
+
return { ...state, files };
|
|
128
|
+
}
|
|
129
|
+
case FileUploaderActionTypes.REMOVE_UPLOAD: {
|
|
130
|
+
const { id } = action;
|
|
131
|
+
const { files } = state;
|
|
132
|
+
const newFiles = files.reduce((files, currentFile) => {
|
|
133
|
+
if (currentFile.id === id) {
|
|
134
|
+
// remove by not returning currentFile
|
|
135
|
+
return [...files];
|
|
136
|
+
}
|
|
137
|
+
return [...files, currentFile];
|
|
138
|
+
}, []);
|
|
139
|
+
return {
|
|
140
|
+
...state,
|
|
141
|
+
files: newFiles,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const addFilesAction$1 = ({ files, status, getFileErrorMessage, }) => ({
|
|
148
|
+
type: FileUploaderActionTypes.ADD_FILES,
|
|
149
|
+
files,
|
|
150
|
+
status,
|
|
151
|
+
getFileErrorMessage,
|
|
152
|
+
});
|
|
153
|
+
const clearFilesAction$1 = () => ({
|
|
154
|
+
type: FileUploaderActionTypes.CLEAR_FILES,
|
|
155
|
+
});
|
|
156
|
+
const queueFilesAction$1 = () => ({
|
|
157
|
+
type: FileUploaderActionTypes.QUEUE_FILES,
|
|
158
|
+
});
|
|
159
|
+
const setProcessedKeyAction$1 = (input) => ({
|
|
160
|
+
...input,
|
|
161
|
+
type: FileUploaderActionTypes.SET_PROCESSED_FILE_KEY,
|
|
162
|
+
});
|
|
163
|
+
const setUploadingFileAction$1 = ({ id, uploadTask, }) => ({
|
|
164
|
+
type: FileUploaderActionTypes.SET_STATUS_UPLOADING,
|
|
165
|
+
id,
|
|
166
|
+
uploadTask,
|
|
167
|
+
});
|
|
168
|
+
const setUploadProgressAction$1 = ({ id, progress, }) => ({
|
|
169
|
+
type: FileUploaderActionTypes.SET_UPLOAD_PROGRESS,
|
|
170
|
+
id,
|
|
171
|
+
progress,
|
|
172
|
+
});
|
|
173
|
+
const setUploadStatusAction$1 = ({ id, status, }) => ({
|
|
174
|
+
type: FileUploaderActionTypes.SET_STATUS,
|
|
175
|
+
id,
|
|
176
|
+
status,
|
|
177
|
+
});
|
|
178
|
+
const removeUploadAction$1 = ({ id }) => ({
|
|
179
|
+
type: FileUploaderActionTypes.REMOVE_UPLOAD,
|
|
180
|
+
id,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const isDefaultFile$1 = (file) => !!(ui.isObject(file) && file.key);
|
|
184
|
+
const createFileFromDefault$1 = (file) => isDefaultFile$1(file)
|
|
185
|
+
? { ...file, id: file.key, status: FileStatus$1.UPLOADED }
|
|
186
|
+
: undefined;
|
|
187
|
+
function useFileUploader(defaultFiles = []) {
|
|
188
|
+
const [{ files }, dispatch] = React__default["default"].useReducer(fileUploaderStateReducer, {
|
|
189
|
+
files: (Array.isArray(defaultFiles)
|
|
190
|
+
? defaultFiles.map(createFileFromDefault$1).filter((file) => !!file)
|
|
191
|
+
: []),
|
|
192
|
+
});
|
|
193
|
+
const addFiles = ({ files, status, getFileErrorMessage, }) => {
|
|
194
|
+
dispatch(addFilesAction$1({ files, status, getFileErrorMessage }));
|
|
195
|
+
};
|
|
196
|
+
const clearFiles = () => {
|
|
197
|
+
dispatch(clearFilesAction$1());
|
|
198
|
+
};
|
|
199
|
+
const queueFiles = () => {
|
|
200
|
+
dispatch(queueFilesAction$1());
|
|
201
|
+
};
|
|
202
|
+
const setUploadingFile = ({ uploadTask, id, }) => {
|
|
203
|
+
dispatch(setUploadingFileAction$1({ id, uploadTask }));
|
|
204
|
+
};
|
|
205
|
+
const setProcessedKey = (input) => {
|
|
206
|
+
dispatch(setProcessedKeyAction$1(input));
|
|
207
|
+
};
|
|
208
|
+
const setUploadProgress = ({ progress, id, }) => {
|
|
209
|
+
dispatch(setUploadProgressAction$1({ id, progress }));
|
|
210
|
+
};
|
|
211
|
+
const setUploadSuccess = ({ id }) => {
|
|
212
|
+
dispatch(setUploadStatusAction$1({ id, status: FileStatus$1.UPLOADED }));
|
|
213
|
+
};
|
|
214
|
+
const setUploadPaused = ({ id }) => {
|
|
215
|
+
dispatch(setUploadStatusAction$1({ id, status: FileStatus$1.PAUSED }));
|
|
216
|
+
};
|
|
217
|
+
const setUploadResumed = ({ id }) => {
|
|
218
|
+
dispatch(setUploadStatusAction$1({ id, status: FileStatus$1.UPLOADING }));
|
|
219
|
+
};
|
|
220
|
+
const removeUpload = ({ id }) => {
|
|
221
|
+
dispatch(removeUploadAction$1({ id }));
|
|
222
|
+
};
|
|
223
|
+
return {
|
|
224
|
+
removeUpload,
|
|
225
|
+
setProcessedKey,
|
|
226
|
+
setUploadPaused,
|
|
227
|
+
setUploadProgress,
|
|
228
|
+
setUploadResumed,
|
|
229
|
+
setUploadSuccess,
|
|
230
|
+
setUploadingFile,
|
|
231
|
+
queueFiles,
|
|
232
|
+
addFiles,
|
|
233
|
+
clearFiles,
|
|
234
|
+
files,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const checkMaxFileSize$1 = ({ file, getFileSizeErrorText, maxFileSize, }) => {
|
|
239
|
+
if (maxFileSize === undefined)
|
|
240
|
+
return '';
|
|
241
|
+
if (file.size > maxFileSize) {
|
|
242
|
+
return getFileSizeErrorText(ui.humanFileSize(maxFileSize, true));
|
|
243
|
+
}
|
|
244
|
+
return '';
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const defaultFileUploaderDisplayText = {
|
|
248
|
+
getFilesUploadedText(count) {
|
|
249
|
+
return `${count} ${count === 1 ? 'file uploaded' : 'files uploaded'}`;
|
|
250
|
+
},
|
|
251
|
+
getFileSizeErrorText(sizeText) {
|
|
252
|
+
return `File size must be below ${sizeText}`;
|
|
253
|
+
},
|
|
254
|
+
getRemainingFilesText(count) {
|
|
255
|
+
return `${count} ${count === 1 ? 'file' : 'files'} uploading`;
|
|
256
|
+
},
|
|
257
|
+
getSelectedFilesText(count) {
|
|
258
|
+
return `${count} ${count === 1 ? 'file' : 'files'} selected`;
|
|
259
|
+
},
|
|
260
|
+
getUploadingText(percentage) {
|
|
261
|
+
return `Uploading${percentage > 0 ? `: ${percentage}%` : ''}`;
|
|
262
|
+
},
|
|
263
|
+
getUploadButtonText(count) {
|
|
264
|
+
return `Upload ${count} ${count === 1 ? 'file' : 'files'}`;
|
|
265
|
+
},
|
|
266
|
+
getMaxFilesErrorText(count) {
|
|
267
|
+
return `Cannot choose more than ${count} ${count === 1 ? 'file' : 'files'}. Remove files before updating`;
|
|
268
|
+
},
|
|
269
|
+
getErrorText(message) {
|
|
270
|
+
return message;
|
|
271
|
+
},
|
|
272
|
+
doneButtonText: 'Done',
|
|
273
|
+
clearAllButtonText: 'Clear all',
|
|
274
|
+
extensionNotAllowedText: 'Extension not allowed',
|
|
275
|
+
browseFilesText: 'Browse files',
|
|
276
|
+
dropFilesText: 'Drop files here or',
|
|
277
|
+
pauseButtonText: 'Pause',
|
|
278
|
+
resumeButtonText: 'Resume',
|
|
279
|
+
uploadSuccessfulText: 'Uploaded',
|
|
280
|
+
getPausedText(percentage) {
|
|
281
|
+
return `Paused: ${percentage}%`;
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const filterAllowedFiles$1 = (files, acceptedFileTypes) => {
|
|
286
|
+
// Allow any files if acceptedFileTypes is undefined, empty array, or contains '*'
|
|
287
|
+
if (!acceptedFileTypes ||
|
|
288
|
+
acceptedFileTypes.length === 0 ||
|
|
289
|
+
acceptedFileTypes.includes('*')) {
|
|
290
|
+
return files;
|
|
291
|
+
}
|
|
292
|
+
// Remove any files that are not in the accepted file list
|
|
293
|
+
return files.filter((file) => {
|
|
294
|
+
const fileName = file.name || '';
|
|
295
|
+
const mimeType = (file.type || '').toLowerCase();
|
|
296
|
+
const baseMimeType = mimeType.replace(/\/.*$/, '');
|
|
297
|
+
return acceptedFileTypes.some((type) => {
|
|
298
|
+
const validType = type.trim().toLowerCase();
|
|
299
|
+
if (validType.charAt(0) === '.') {
|
|
300
|
+
return fileName.toLowerCase().endsWith(validType);
|
|
301
|
+
}
|
|
302
|
+
else if (validType.endsWith('/*')) {
|
|
303
|
+
// This is something like a image/* mime type
|
|
304
|
+
return baseMimeType === validType.replace(/\/.*$/, '');
|
|
305
|
+
}
|
|
306
|
+
return mimeType === validType;
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Utility function that takes the processFile prop, along with a file a key
|
|
313
|
+
* and returns a Promise that resolves to { file, key, ..rest }
|
|
314
|
+
* regardless if processFile is defined and if it is sync or async
|
|
315
|
+
*/
|
|
316
|
+
const resolveFile$1 = ({ processFile, ...input }) => {
|
|
317
|
+
return new Promise((resolve, reject) => {
|
|
318
|
+
const result = ui.isFunction(processFile) ? processFile(input) : input;
|
|
319
|
+
if (result instanceof Promise) {
|
|
320
|
+
result.then(resolve).catch(reject);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
resolve(result);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const getInput$1 = ({ accessLevel, file, key, onProcessFileSuccess, onProgress, path, processFile, useAccelerateEndpoint, }) => {
|
|
329
|
+
return async () => {
|
|
330
|
+
const hasCallbackPath = ui.isTypedFunction(path);
|
|
331
|
+
const hasStringPath = ui.isString(path);
|
|
332
|
+
const hasKeyInput = !!accessLevel && !hasCallbackPath;
|
|
333
|
+
const { file: data, key: processedKey, ...rest } = await resolveFile$1({ file, key, processFile });
|
|
334
|
+
const contentType = file.type || 'binary/octet-stream';
|
|
335
|
+
// IMPORTANT: always pass `...rest` here for backwards compatibility
|
|
336
|
+
const options = { contentType, onProgress, useAccelerateEndpoint, ...rest };
|
|
337
|
+
let inputResult;
|
|
338
|
+
if (hasKeyInput) {
|
|
339
|
+
// legacy handling of `path` is to prefix to `fileKey`
|
|
340
|
+
const resolvedKey = hasStringPath
|
|
341
|
+
? `${path}${processedKey}`
|
|
342
|
+
: processedKey;
|
|
343
|
+
inputResult = {
|
|
344
|
+
data,
|
|
345
|
+
key: resolvedKey,
|
|
346
|
+
options: { ...options, accessLevel },
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
const { identityId } = await auth.fetchAuthSession();
|
|
351
|
+
const resolvedPath = `${hasCallbackPath ? path({ identityId }) : path}${processedKey}`;
|
|
352
|
+
inputResult = { data: file, path: resolvedPath, options };
|
|
353
|
+
}
|
|
354
|
+
if (processFile) {
|
|
355
|
+
// provide post-processing value of target `key`
|
|
356
|
+
onProcessFileSuccess({ processedKey });
|
|
357
|
+
}
|
|
358
|
+
return inputResult;
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
async function uploadFile$1({ input, onError, onStart, onComplete, }) {
|
|
363
|
+
const resolvedInput = await input();
|
|
364
|
+
const uploadTask = storage.uploadData(resolvedInput);
|
|
365
|
+
const key = resolvedInput?.key ??
|
|
366
|
+
resolvedInput?.path;
|
|
367
|
+
if (ui.isFunction(onStart)) {
|
|
368
|
+
onStart({ key, uploadTask });
|
|
369
|
+
}
|
|
370
|
+
uploadTask.result
|
|
371
|
+
.then((result) => {
|
|
372
|
+
if (ui.isFunction(onComplete) && uploadTask.state === 'SUCCESS') {
|
|
373
|
+
onComplete(result);
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
.catch((error) => {
|
|
377
|
+
if (ui.isFunction(onError)) {
|
|
378
|
+
onError({ key, error });
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
return uploadTask;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function useUploadFiles$1({ accessLevel, files, isResumable, maxFileCount, onProcessFileSuccess, onUploadError, onUploadStart, onUploadSuccess, path, processFile, setUploadingFile, setUploadProgress, setUploadSuccess, useAccelerateEndpoint, }) {
|
|
385
|
+
React__namespace.useEffect(() => {
|
|
386
|
+
const filesReadyToUpload = files.filter((file) => file.status === FileStatus$1.QUEUED);
|
|
387
|
+
if (filesReadyToUpload.length > maxFileCount) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
for (const { file, key, id } of filesReadyToUpload) {
|
|
391
|
+
const onProgress = (event) => {
|
|
392
|
+
/**
|
|
393
|
+
* When a file is zero bytes, the progress.total will equal zero.
|
|
394
|
+
* Therefore, this will prevent a divide by zero error.
|
|
395
|
+
*/
|
|
396
|
+
const progress = event.totalBytes === undefined || event.totalBytes === 0
|
|
397
|
+
? 100
|
|
398
|
+
: Math.floor((event.transferredBytes / event.totalBytes) * 100);
|
|
399
|
+
setUploadProgress({ id, progress });
|
|
400
|
+
};
|
|
401
|
+
if (file) {
|
|
402
|
+
const handleProcessFileSuccess = (input) => onProcessFileSuccess({ id, ...input });
|
|
403
|
+
const input = getInput$1({
|
|
404
|
+
accessLevel,
|
|
405
|
+
file,
|
|
406
|
+
key,
|
|
407
|
+
onProcessFileSuccess: handleProcessFileSuccess,
|
|
408
|
+
onProgress,
|
|
409
|
+
path,
|
|
410
|
+
processFile,
|
|
411
|
+
useAccelerateEndpoint,
|
|
412
|
+
});
|
|
413
|
+
uploadFile$1({
|
|
414
|
+
input,
|
|
415
|
+
onComplete: (event) => {
|
|
416
|
+
if (ui.isFunction(onUploadSuccess)) {
|
|
417
|
+
onUploadSuccess({
|
|
418
|
+
key: event.key ??
|
|
419
|
+
event.path,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
setUploadSuccess({ id });
|
|
423
|
+
},
|
|
424
|
+
onError: ({ key, error }) => {
|
|
425
|
+
if (ui.isFunction(onUploadError)) {
|
|
426
|
+
onUploadError(error.message, { key });
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
onStart: ({ key, uploadTask }) => {
|
|
430
|
+
if (ui.isFunction(onUploadStart)) {
|
|
431
|
+
onUploadStart({ key });
|
|
432
|
+
}
|
|
433
|
+
setUploadingFile({ id, uploadTask });
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}, [
|
|
439
|
+
files,
|
|
440
|
+
accessLevel,
|
|
441
|
+
isResumable,
|
|
442
|
+
setUploadProgress,
|
|
443
|
+
setUploadingFile,
|
|
444
|
+
onUploadError,
|
|
445
|
+
onProcessFileSuccess,
|
|
446
|
+
onUploadSuccess,
|
|
447
|
+
onUploadStart,
|
|
448
|
+
maxFileCount,
|
|
449
|
+
setUploadSuccess,
|
|
450
|
+
processFile,
|
|
451
|
+
path,
|
|
452
|
+
useAccelerateEndpoint,
|
|
453
|
+
]);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function Container$1({ children, className, }) {
|
|
457
|
+
return React__default["default"].createElement(uiReact.View, { className: className }, children);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function DropZone$1({ children, displayText, inDropZone, onDragEnter, onDragLeave, onDragOver, onDragStart, onDrop, testId, }) {
|
|
461
|
+
const { dropFilesText } = displayText;
|
|
462
|
+
const icons = internal.useIcons('storageManager');
|
|
463
|
+
return (React__default["default"].createElement(uiReact.View, { className: ui.classNames(inDropZone &&
|
|
464
|
+
ui.classNameModifier(ui.ComponentClassName.FileUploaderDropZone, 'active'), ui.ComponentClassName.FileUploaderDropZone), "data-testid": testId, onDragStart: onDragStart, onDragEnter: onDragEnter, onDragLeave: onDragLeave, onDrop: onDrop, onDragOver: onDragOver },
|
|
465
|
+
React__default["default"].createElement(uiReact.View, { as: "span", "aria-hidden": true, className: ui.ComponentClassName.FileUploaderDropZoneIcon }, icons?.upload ?? React__default["default"].createElement(internal.IconUpload, null)),
|
|
466
|
+
React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.FileUploaderDropZoneText }, dropFilesText),
|
|
467
|
+
children));
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const FileStatusMessage$1 = ({ errorMessage, getPausedText, getUploadingText, percentage, status, uploadSuccessfulText, }) => {
|
|
471
|
+
const icons = internal.useIcons('storageManager');
|
|
472
|
+
switch (status) {
|
|
473
|
+
case FileStatus$1.UPLOADING: {
|
|
474
|
+
return (React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.FileUploaderFileStatus }, getUploadingText(percentage)));
|
|
475
|
+
}
|
|
476
|
+
case FileStatus$1.PAUSED:
|
|
477
|
+
return (React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.FileUploaderFileStatus }, getPausedText(percentage)));
|
|
478
|
+
case FileStatus$1.UPLOADED:
|
|
479
|
+
return (React__default["default"].createElement(uiReact.Text, { className: ui.classNames(ui.ComponentClassName.FileUploaderFileStatus, ui.classNameModifier(ui.ComponentClassName.FileUploaderFileStatus, 'success')) },
|
|
480
|
+
React__default["default"].createElement(uiReact.View, { as: "span", fontSize: "xl" }, icons?.success ?? React__default["default"].createElement(internal.IconCheck, null)),
|
|
481
|
+
uploadSuccessfulText));
|
|
482
|
+
case FileStatus$1.ERROR:
|
|
483
|
+
return (React__default["default"].createElement(uiReact.Text, { className: ui.classNames(ui.ComponentClassName.FileUploaderFileStatus, ui.classNameModifier(ui.ComponentClassName.FileUploaderFileStatus, 'error')) },
|
|
484
|
+
React__default["default"].createElement(uiReact.View, { as: "span", fontSize: "xl" }, icons?.error ?? React__default["default"].createElement(internal.IconError, null)),
|
|
485
|
+
errorMessage));
|
|
486
|
+
default:
|
|
487
|
+
return null;
|
|
28
488
|
}
|
|
29
|
-
|
|
30
|
-
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const FileRemoveButton$1 = ({ altText, onClick, }) => {
|
|
492
|
+
const icons = internal.useIcons('storageManager');
|
|
493
|
+
return (React__default["default"].createElement(uiReact.Button, { size: "small", onClick: onClick, testId: "storage-manager-remove-button" },
|
|
494
|
+
React__default["default"].createElement(uiReact.VisuallyHidden, null, altText),
|
|
495
|
+
React__default["default"].createElement(uiReact.View, { as: "span", "aria-hidden": true, fontSize: "medium" }, icons?.remove ?? React__default["default"].createElement(internal.IconClose, null))));
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const UploadDetails$1 = ({ displayName, fileSize, }) => {
|
|
499
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
500
|
+
React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderFileMain },
|
|
501
|
+
React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.FileUploaderFileName }, displayName)),
|
|
502
|
+
React__default["default"].createElement(uiReact.Text, { as: "span", className: ui.ComponentClassName.FileUploaderFileSize }, fileSize ? ui.humanFileSize(fileSize, true) : '')));
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
const FileThumbnail$1 = ({ fileName, isImage, url, }) => {
|
|
506
|
+
const icons = internal.useIcons('storageManager');
|
|
507
|
+
const thumbnail = isImage ? (React__default["default"].createElement(uiReact.Image, { alt: fileName, src: url })) : (icons?.file ?? React__default["default"].createElement(internal.IconFile, null));
|
|
508
|
+
return (React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderFileImage }, thumbnail));
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
function FileControl$1({ onPause, onResume, displayName, errorMessage, isImage, isResumable, loaderIsDeterminate, onRemove, progress, showThumbnails = true, size, status, displayText, thumbnailUrl, }) {
|
|
512
|
+
const { getPausedText, getUploadingText, uploadSuccessfulText, pauseButtonText, resumeButtonText, } = displayText;
|
|
513
|
+
return (React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderFile },
|
|
514
|
+
React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderFileWrapper },
|
|
515
|
+
showThumbnails ? (React__default["default"].createElement(FileThumbnail$1, { isImage: isImage, fileName: displayName, url: thumbnailUrl })) : null,
|
|
516
|
+
React__default["default"].createElement(UploadDetails$1, { displayName: displayName, fileSize: size }),
|
|
517
|
+
status === FileStatus$1.UPLOADING ? (React__default["default"].createElement(uiReact.Loader, { className: ui.ComponentClassName.FileUploaderLoader, variation: "linear", percentage: progress, isDeterminate: loaderIsDeterminate, isPercentageTextHidden: true })) : null,
|
|
518
|
+
isResumable &&
|
|
519
|
+
(status === FileStatus$1.UPLOADING || status === FileStatus$1.PAUSED) ? (status === FileStatus$1.PAUSED ? (React__default["default"].createElement(uiReact.Button, { onClick: onResume, size: "small", variation: "link" }, resumeButtonText)) : (React__default["default"].createElement(uiReact.Button, { onClick: onPause, size: "small", variation: "link" }, pauseButtonText))) : null,
|
|
520
|
+
React__default["default"].createElement(FileRemoveButton$1, { altText: `Remove file ${displayName}`, onClick: onRemove })),
|
|
521
|
+
React__default["default"].createElement(FileStatusMessage$1, { uploadSuccessfulText: uploadSuccessfulText, getUploadingText: getUploadingText, getPausedText: getPausedText, status: status, errorMessage: errorMessage, percentage: progress })));
|
|
31
522
|
}
|
|
32
523
|
|
|
33
|
-
|
|
34
|
-
|
|
524
|
+
function FileList$1({ displayText, files, hasMaxFilesError, isResumable, onCancelUpload, onDeleteUpload, onResume, onPause, showThumbnails, maxFileCount, }) {
|
|
525
|
+
if (files.length < 1) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
const { getMaxFilesErrorText } = displayText;
|
|
529
|
+
const headingMaxFiles = getMaxFilesErrorText(maxFileCount);
|
|
530
|
+
return (React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderFileList },
|
|
531
|
+
files.map((storageFile) => {
|
|
532
|
+
const { file, status, progress, error, key, isImage, id, uploadTask } = storageFile;
|
|
533
|
+
const thumbnailUrl = file && isImage ? URL.createObjectURL(file) : '';
|
|
534
|
+
const loaderIsDeterminate = isResumable ? progress > 0 : true;
|
|
535
|
+
const isUploading = status === FileStatus$1.UPLOADING;
|
|
536
|
+
const onRemove = () => {
|
|
537
|
+
if (isResumable &&
|
|
538
|
+
(status === FileStatus$1.UPLOADING || status === FileStatus$1.PAUSED) &&
|
|
539
|
+
uploadTask) {
|
|
540
|
+
onCancelUpload({ id, uploadTask });
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
onDeleteUpload({ id });
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
const handlePauseUpload = () => {
|
|
547
|
+
if (uploadTask) {
|
|
548
|
+
onPause({ id, uploadTask });
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const handleResumeUpload = () => {
|
|
552
|
+
if (uploadTask) {
|
|
553
|
+
onResume({ id, uploadTask });
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
return (React__default["default"].createElement(FileControl$1, { displayName: key, errorMessage: error, displayText: displayText, isImage: isImage, isUploading: isUploading, isResumable: isResumable, key: id, loaderIsDeterminate: loaderIsDeterminate, onRemove: onRemove, onPause: handlePauseUpload, onResume: handleResumeUpload, progress: progress, showThumbnails: showThumbnails, size: file?.size, status: status, thumbnailUrl: thumbnailUrl }));
|
|
557
|
+
}),
|
|
558
|
+
hasMaxFilesError && (React__default["default"].createElement(uiReact.Alert, { variation: "error", heading: headingMaxFiles }))));
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function FileListHeader$1({ allUploadsSuccessful, displayText, fileCount, remainingFilesCount, selectedFilesCount = 0, }) {
|
|
562
|
+
const { getFilesUploadedText, getRemainingFilesText, getSelectedFilesText } = displayText;
|
|
563
|
+
return (React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.FileUploaderPreviewerText }, selectedFilesCount
|
|
564
|
+
? getSelectedFilesText(selectedFilesCount)
|
|
565
|
+
: allUploadsSuccessful
|
|
566
|
+
? getFilesUploadedText(fileCount)
|
|
567
|
+
: getRemainingFilesText(remainingFilesCount)));
|
|
568
|
+
}
|
|
35
569
|
|
|
36
|
-
|
|
570
|
+
function FileListFooter$1({ displayText, remainingFilesCount, onClearAll, onUploadAll, }) {
|
|
571
|
+
const { clearAllButtonText, getUploadButtonText } = displayText;
|
|
572
|
+
return (React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderPreviewerFooter },
|
|
573
|
+
React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.FileUploaderPreviewerActions },
|
|
574
|
+
React__default["default"].createElement(uiReact.Button, { size: "small", variation: "link", onClick: onClearAll }, clearAllButtonText),
|
|
575
|
+
React__default["default"].createElement(uiReact.Button, { size: "small", variation: "primary", onClick: onUploadAll }, getUploadButtonText(remainingFilesCount)))));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function FilePicker$1({ children, className = ui.ComponentClassName.FileUploaderFilePicker, size = 'small', ...props }) {
|
|
579
|
+
return (React__default["default"].createElement(uiReact.Button, { ...props, className: className, size: size }, children));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const VERSION = '3.3.0';
|
|
583
|
+
|
|
584
|
+
const logger$1 = ui.getLogger('Storage');
|
|
585
|
+
const MISSING_REQUIRED_PROPS_MESSAGE$1 = '`FileUploader` requires a `maxFileCount` prop to be provided.';
|
|
586
|
+
const ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE$1 = '`FileUploader` does not allow usage of a `path` callback prop with an `accessLevel` prop.';
|
|
587
|
+
const ACCESS_LEVEL_DEPRECATION_MESSAGE$1 = '`accessLevel` has been deprecated and will be removed in a future major version. See migration notes at https://ui.docs.amplify.aws/react/connected-components/storage/FileUploader';
|
|
588
|
+
const FileUploaderBase = React__namespace.forwardRef(function FileUploader({ acceptedFileTypes = [], accessLevel, autoUpload = true, components, defaultFiles, displayText: overrideDisplayText, isResumable = false, maxFileCount, maxFileSize, onFileRemove, onUploadError, onUploadStart, onUploadSuccess, path, processFile, showThumbnails = true, useAccelerateEndpoint, }, ref) {
|
|
589
|
+
if (!maxFileCount) {
|
|
590
|
+
// eslint-disable-next-line no-console
|
|
591
|
+
console.warn(MISSING_REQUIRED_PROPS_MESSAGE$1);
|
|
592
|
+
}
|
|
593
|
+
if (accessLevel && typeof path === 'function') {
|
|
594
|
+
throw new Error(ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE$1);
|
|
595
|
+
}
|
|
596
|
+
uiReactCore.useDeprecationWarning({
|
|
597
|
+
message: ACCESS_LEVEL_DEPRECATION_MESSAGE$1,
|
|
598
|
+
shouldWarn: !!accessLevel,
|
|
599
|
+
});
|
|
600
|
+
const Components = {
|
|
601
|
+
Container: Container$1,
|
|
602
|
+
DropZone: DropZone$1,
|
|
603
|
+
FileList: FileList$1,
|
|
604
|
+
FilePicker: FilePicker$1,
|
|
605
|
+
FileListHeader: FileListHeader$1,
|
|
606
|
+
FileListFooter: FileListFooter$1,
|
|
607
|
+
...components,
|
|
608
|
+
};
|
|
609
|
+
const allowMultipleFiles = maxFileCount === undefined ||
|
|
610
|
+
(typeof maxFileCount === 'number' && maxFileCount > 1);
|
|
611
|
+
const displayText = {
|
|
612
|
+
...defaultFileUploaderDisplayText,
|
|
613
|
+
...overrideDisplayText,
|
|
614
|
+
};
|
|
615
|
+
const { getFileSizeErrorText } = displayText;
|
|
616
|
+
const getMaxFileSizeErrorMessage = (file) => {
|
|
617
|
+
return checkMaxFileSize$1({
|
|
618
|
+
file,
|
|
619
|
+
maxFileSize,
|
|
620
|
+
getFileSizeErrorText,
|
|
621
|
+
});
|
|
622
|
+
};
|
|
623
|
+
const { addFiles, clearFiles, files, removeUpload, queueFiles, setProcessedKey, setUploadingFile, setUploadPaused, setUploadProgress, setUploadSuccess, setUploadResumed, } = useFileUploader(defaultFiles);
|
|
624
|
+
React__namespace.useImperativeHandle(ref, () => ({ clearFiles }));
|
|
625
|
+
const { dragState, ...dropZoneProps } = internal.useDropZone({
|
|
626
|
+
acceptedFileTypes,
|
|
627
|
+
onDropComplete: ({ acceptedFiles, rejectedFiles }) => {
|
|
628
|
+
if (rejectedFiles && rejectedFiles.length > 0) {
|
|
629
|
+
logger$1.warn('Rejected files: ', rejectedFiles);
|
|
630
|
+
}
|
|
631
|
+
// We need to filter out files by extension here,
|
|
632
|
+
// we don't get filenames on the drag event, only on drop
|
|
633
|
+
const _acceptedFiles = filterAllowedFiles$1(acceptedFiles, acceptedFileTypes);
|
|
634
|
+
addFiles({
|
|
635
|
+
files: _acceptedFiles,
|
|
636
|
+
status: autoUpload ? FileStatus$1.QUEUED : FileStatus$1.ADDED,
|
|
637
|
+
getFileErrorMessage: getMaxFileSizeErrorMessage,
|
|
638
|
+
});
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
useUploadFiles$1({
|
|
642
|
+
accessLevel,
|
|
643
|
+
files,
|
|
644
|
+
isResumable,
|
|
645
|
+
maxFileCount,
|
|
646
|
+
onUploadError,
|
|
647
|
+
onUploadSuccess,
|
|
648
|
+
onUploadStart,
|
|
649
|
+
onProcessFileSuccess: setProcessedKey,
|
|
650
|
+
setUploadingFile,
|
|
651
|
+
setUploadProgress,
|
|
652
|
+
setUploadSuccess,
|
|
653
|
+
processFile,
|
|
654
|
+
path,
|
|
655
|
+
useAccelerateEndpoint,
|
|
656
|
+
});
|
|
657
|
+
const onFilePickerChange = (event) => {
|
|
658
|
+
const { files } = event.target;
|
|
659
|
+
if (!files || files.length === 0) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
addFiles({
|
|
663
|
+
files: Array.from(files),
|
|
664
|
+
status: autoUpload ? FileStatus$1.QUEUED : FileStatus$1.ADDED,
|
|
665
|
+
getFileErrorMessage: getMaxFileSizeErrorMessage,
|
|
666
|
+
});
|
|
667
|
+
};
|
|
668
|
+
const onClearAll = () => {
|
|
669
|
+
clearFiles();
|
|
670
|
+
};
|
|
671
|
+
const onUploadAll = () => {
|
|
672
|
+
queueFiles();
|
|
673
|
+
};
|
|
674
|
+
const onPauseUpload = ({ id, uploadTask }) => {
|
|
675
|
+
uploadTask.pause();
|
|
676
|
+
setUploadPaused({ id });
|
|
677
|
+
};
|
|
678
|
+
const onResumeUpload = ({ id, uploadTask }) => {
|
|
679
|
+
uploadTask.resume();
|
|
680
|
+
setUploadResumed({ id });
|
|
681
|
+
};
|
|
682
|
+
const onCancelUpload = ({ id, uploadTask }) => {
|
|
683
|
+
// At this time we don't know if the delete
|
|
684
|
+
// permissions are enabled (required to cancel upload),
|
|
685
|
+
// so we do a pause instead and remove from files
|
|
686
|
+
uploadTask.pause();
|
|
687
|
+
removeUpload({ id });
|
|
688
|
+
};
|
|
689
|
+
const onDeleteUpload = ({ id }) => {
|
|
690
|
+
// At this time we don't know if the delete
|
|
691
|
+
// permissions are enabled, so we do a soft delete
|
|
692
|
+
// from file list, but don't remove from storage
|
|
693
|
+
removeUpload({ id });
|
|
694
|
+
if (typeof onFileRemove === 'function') {
|
|
695
|
+
const file = files.find((file) => file.id === id);
|
|
696
|
+
if (file) {
|
|
697
|
+
// return `processedKey` if available and `processFile` is provided
|
|
698
|
+
const key = (processFile && file?.processedKey) ?? file.key;
|
|
699
|
+
onFileRemove({ key });
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
// checks if all downloads completed to 100%
|
|
704
|
+
const allUploadsSuccessful = files.length === 0
|
|
705
|
+
? false
|
|
706
|
+
: files.every((file) => file?.status === FileStatus$1.UPLOADED);
|
|
707
|
+
// Displays if over max files
|
|
708
|
+
const hasMaxFilesError = files.filter((file) => file.progress < 100).length > maxFileCount;
|
|
709
|
+
const uploadedFilesLength = files.filter((file) => file?.status === FileStatus$1.UPLOADED).length;
|
|
710
|
+
const remainingFilesCount = files.length - uploadedFilesLength;
|
|
711
|
+
// number of files selected for upload when autoUpload is turned off
|
|
712
|
+
const selectedFilesCount = autoUpload ? 0 : remainingFilesCount;
|
|
713
|
+
const hasFiles = files.length > 0;
|
|
714
|
+
const hasUploadActions = !autoUpload && remainingFilesCount > 0;
|
|
715
|
+
const hiddenInput = React__namespace.useRef(null);
|
|
716
|
+
function handleClick() {
|
|
717
|
+
if (hiddenInput.current) {
|
|
718
|
+
hiddenInput.current.click();
|
|
719
|
+
hiddenInput.current.value = '';
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
uiReactCore.useSetUserAgent({
|
|
723
|
+
componentName: 'FileUploader',
|
|
724
|
+
packageName: 'react-storage',
|
|
725
|
+
version: VERSION,
|
|
726
|
+
});
|
|
727
|
+
return (React__namespace.createElement(Components.Container, { className: `${ui.ComponentClassName.FileUploader} ${hasFiles ? ui.ComponentClassName.FileUploaderPreviewer : ''}` },
|
|
728
|
+
React__namespace.createElement(Components.DropZone, { inDropZone: dragState !== 'inactive', ...dropZoneProps, displayText: displayText },
|
|
729
|
+
React__namespace.createElement(React__namespace.Fragment, null,
|
|
730
|
+
React__namespace.createElement(Components.FilePicker, { onClick: handleClick }, displayText.browseFilesText),
|
|
731
|
+
React__namespace.createElement(uiReact.VisuallyHidden, null,
|
|
732
|
+
React__namespace.createElement("input", { type: "file", tabIndex: -1, ref: hiddenInput, onChange: onFilePickerChange, multiple: allowMultipleFiles, accept: acceptedFileTypes.join(',') })))),
|
|
733
|
+
hasFiles ? (React__namespace.createElement(Components.FileListHeader, { allUploadsSuccessful: allUploadsSuccessful, displayText: displayText, fileCount: files.length, remainingFilesCount: remainingFilesCount, selectedFilesCount: selectedFilesCount })) : null,
|
|
734
|
+
React__namespace.createElement(Components.FileList, { displayText: displayText, files: files, isResumable: isResumable, onCancelUpload: onCancelUpload, onDeleteUpload: onDeleteUpload, onResume: onResumeUpload, onPause: onPauseUpload, showThumbnails: showThumbnails, hasMaxFilesError: hasMaxFilesError, maxFileCount: maxFileCount }),
|
|
735
|
+
hasUploadActions ? (React__namespace.createElement(Components.FileListFooter, { displayText: displayText, remainingFilesCount: remainingFilesCount, onClearAll: onClearAll, onUploadAll: onUploadAll })) : null));
|
|
736
|
+
});
|
|
737
|
+
// pass an empty object as first param to avoid destructive action on `FileUploaderBase`
|
|
738
|
+
const FileUploader = Object.assign({}, FileUploaderBase, {
|
|
739
|
+
Container: Container$1,
|
|
740
|
+
DropZone: DropZone$1,
|
|
741
|
+
FileList: FileList$1,
|
|
742
|
+
FileListHeader: FileListHeader$1,
|
|
743
|
+
FileListFooter: FileListFooter$1,
|
|
744
|
+
FilePicker: FilePicker$1,
|
|
745
|
+
});
|
|
37
746
|
|
|
38
747
|
const MISSING_REQUIRED_PROP_MESSAGE = '`StorageImage` requires either an `imgKey` or `path` prop.';
|
|
39
748
|
const HAS_DEPRECATED_PROPS_MESSAGE = '`imgKey`, `accessLevel`, and `identityId` will be replaced with `path` in a future major version. See https://ui.docs.amplify.aws/react/connected-components/storage/storageimage#props';
|
|
@@ -286,39 +995,11 @@ function useStorageManager(defaultFiles = []) {
|
|
|
286
995
|
};
|
|
287
996
|
}
|
|
288
997
|
|
|
289
|
-
/**
|
|
290
|
-
* Format bytes as human-readable text.
|
|
291
|
-
*
|
|
292
|
-
* @param bytes Number of bytes.
|
|
293
|
-
* @param si True to use metric (SI) units, aka powers of 1000. False to use
|
|
294
|
-
* binary (IEC), aka powers of 1024.
|
|
295
|
-
* @param dp Number of decimal places to display.
|
|
296
|
-
*
|
|
297
|
-
* @return Formatted string.
|
|
298
|
-
*/
|
|
299
|
-
function humanFileSize(bytes, si = false, dp = 1) {
|
|
300
|
-
const thresh = si ? 1000 : 1024;
|
|
301
|
-
if (Math.abs(bytes) < thresh) {
|
|
302
|
-
return `${bytes} B`;
|
|
303
|
-
}
|
|
304
|
-
const units = si
|
|
305
|
-
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
306
|
-
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
307
|
-
let unit = -1;
|
|
308
|
-
const range = 10 ** dp;
|
|
309
|
-
do {
|
|
310
|
-
bytes /= thresh;
|
|
311
|
-
++unit;
|
|
312
|
-
} while (Math.round(Math.abs(bytes) * range) / range >= thresh &&
|
|
313
|
-
unit < units.length - 1);
|
|
314
|
-
return bytes.toFixed(dp) + ' ' + units[unit];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
998
|
const checkMaxFileSize = ({ file, getFileSizeErrorText, maxFileSize, }) => {
|
|
318
999
|
if (maxFileSize === undefined)
|
|
319
1000
|
return '';
|
|
320
1001
|
if (file.size > maxFileSize) {
|
|
321
|
-
return getFileSizeErrorText(humanFileSize(maxFileSize, true));
|
|
1002
|
+
return getFileSizeErrorText(ui.humanFileSize(maxFileSize, true));
|
|
322
1003
|
}
|
|
323
1004
|
return '';
|
|
324
1005
|
};
|
|
@@ -578,7 +1259,7 @@ const UploadDetails = ({ displayName, fileSize, }) => {
|
|
|
578
1259
|
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
579
1260
|
React__default["default"].createElement(uiReact.View, { className: ui.ComponentClassName.StorageManagerFileMain },
|
|
580
1261
|
React__default["default"].createElement(uiReact.Text, { className: ui.ComponentClassName.StorageManagerFileName }, displayName)),
|
|
581
|
-
React__default["default"].createElement(uiReact.Text, { as: "span", className: ui.ComponentClassName.StorageManagerFileSize }, fileSize ? humanFileSize(fileSize, true) : '')));
|
|
1262
|
+
React__default["default"].createElement(uiReact.Text, { as: "span", className: ui.ComponentClassName.StorageManagerFileSize }, fileSize ? ui.humanFileSize(fileSize, true) : '')));
|
|
582
1263
|
};
|
|
583
1264
|
|
|
584
1265
|
const FileThumbnail = ({ fileName, isImage, url, }) => {
|
|
@@ -663,6 +1344,10 @@ const MISSING_REQUIRED_PROPS_MESSAGE = '`StorageManager` requires a `maxFileCoun
|
|
|
663
1344
|
const ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE = '`StorageManager` does not allow usage of a `path` callback prop with an `accessLevel` prop.';
|
|
664
1345
|
const ACCESS_LEVEL_DEPRECATION_MESSAGE = '`accessLevel` has been deprecated and will be removed in a future major version. See migration notes at https://ui.docs.amplify.aws/react/connected-components/storage/storagemanager';
|
|
665
1346
|
const StorageManagerBase = React__namespace.forwardRef(function StorageManager({ acceptedFileTypes = [], accessLevel, autoUpload = true, components, defaultFiles, displayText: overrideDisplayText, isResumable = false, maxFileCount, maxFileSize, onFileRemove, onUploadError, onUploadStart, onUploadSuccess, path, processFile, showThumbnails = true, useAccelerateEndpoint, }, ref) {
|
|
1347
|
+
uiReactCore.useDeprecationWarning({
|
|
1348
|
+
message: 'The `StorageManager` component has been renamed as the `FileUploader` component.',
|
|
1349
|
+
shouldWarn: false,
|
|
1350
|
+
});
|
|
666
1351
|
if (!maxFileCount) {
|
|
667
1352
|
// eslint-disable-next-line no-console
|
|
668
1353
|
console.warn(MISSING_REQUIRED_PROPS_MESSAGE);
|
|
@@ -821,5 +1506,6 @@ const StorageManager = Object.assign({}, StorageManagerBase, {
|
|
|
821
1506
|
FilePicker,
|
|
822
1507
|
});
|
|
823
1508
|
|
|
1509
|
+
exports.FileUploader = FileUploader;
|
|
824
1510
|
exports.StorageImage = StorageImage;
|
|
825
1511
|
exports.StorageManager = StorageManager;
|