@aws-amplify/ui-react-storage 0.0.0-studio-console-80bb2e2-20230921222703 → 0.0.0-theming-v2-c5d1f72-20240709163904

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.
Files changed (51) hide show
  1. package/dist/esm/components/StorageImage/StorageImage.mjs +57 -1
  2. package/dist/esm/components/StorageManager/StorageManager.mjs +181 -1
  3. package/dist/esm/components/StorageManager/hooks/useStorageManager/actions.mjs +35 -1
  4. package/dist/esm/components/StorageManager/hooks/useStorageManager/reducer.mjs +132 -1
  5. package/dist/esm/components/StorageManager/hooks/useStorageManager/types.mjs +12 -1
  6. package/dist/esm/components/StorageManager/hooks/useStorageManager/useStorageManager.mjs +58 -1
  7. package/dist/esm/components/StorageManager/hooks/useUploadFiles/useUploadFiles.mjs +74 -1
  8. package/dist/esm/components/StorageManager/types.mjs +11 -1
  9. package/dist/esm/components/StorageManager/ui/Container/Container.mjs +8 -1
  10. package/dist/esm/components/StorageManager/ui/DropZone/DropZone.mjs +16 -1
  11. package/dist/esm/components/StorageManager/ui/FileList/FileControl.mjs +23 -1
  12. package/dist/esm/components/StorageManager/ui/FileList/FileDetails.mjs +15 -1
  13. package/dist/esm/components/StorageManager/ui/FileList/FileList.mjs +44 -1
  14. package/dist/esm/components/StorageManager/ui/FileList/FileRemoveButton.mjs +12 -1
  15. package/dist/esm/components/StorageManager/ui/FileList/FileStatusMessage.mjs +28 -1
  16. package/dist/esm/components/StorageManager/ui/FileList/FileThumbnail.mjs +12 -1
  17. package/dist/esm/components/StorageManager/ui/FileListFooter/FileListFooter.mjs +13 -1
  18. package/dist/esm/components/StorageManager/ui/FileListHeader/FileListHeader.mjs +14 -1
  19. package/dist/esm/components/StorageManager/ui/FilePicker/FilePicker.mjs +9 -1
  20. package/dist/esm/components/StorageManager/utils/checkMaxFileSize.mjs +12 -1
  21. package/dist/esm/components/StorageManager/utils/displayText.mjs +39 -1
  22. package/dist/esm/components/StorageManager/utils/filterAllowedFiles.mjs +27 -1
  23. package/dist/esm/components/StorageManager/utils/getInput.mjs +25 -0
  24. package/dist/esm/components/StorageManager/utils/humanFileSize.mjs +29 -1
  25. package/dist/esm/components/StorageManager/utils/resolveFile.mjs +20 -0
  26. package/dist/esm/components/StorageManager/utils/uploadFile.mjs +26 -1
  27. package/dist/esm/index.mjs +2 -1
  28. package/dist/esm/version.mjs +3 -0
  29. package/dist/index.js +832 -1
  30. package/dist/styles.css +462 -370
  31. package/dist/types/components/StorageImage/StorageImage.d.ts +6 -2
  32. package/dist/types/components/StorageImage/types.d.ts +33 -2
  33. package/dist/types/components/StorageManager/StorageManager.d.ts +5 -2
  34. package/dist/types/components/StorageManager/hooks/useStorageManager/actions.d.ts +2 -5
  35. package/dist/types/components/StorageManager/hooks/useStorageManager/types.d.ts +1 -1
  36. package/dist/types/components/StorageManager/hooks/useStorageManager/useStorageManager.d.ts +2 -5
  37. package/dist/types/components/StorageManager/hooks/useUploadFiles/useUploadFiles.d.ts +5 -2
  38. package/dist/types/components/StorageManager/types.d.ts +17 -11
  39. package/dist/types/components/StorageManager/ui/FileList/types.d.ts +7 -17
  40. package/dist/types/components/StorageManager/ui/FileListFooter/FileListFooter.d.ts +2 -2
  41. package/dist/types/components/StorageManager/ui/FileListHeader/FileListHeader.d.ts +2 -2
  42. package/dist/types/components/StorageManager/utils/displayText.d.ts +22 -20
  43. package/dist/types/components/StorageManager/utils/getInput.d.ts +13 -0
  44. package/dist/types/components/StorageManager/utils/index.d.ts +3 -2
  45. package/dist/types/components/StorageManager/utils/resolveFile.d.ts +9 -0
  46. package/dist/types/components/StorageManager/utils/uploadFile.d.ts +30 -17
  47. package/dist/types/version.d.ts +1 -0
  48. package/package.json +9 -40
  49. package/dist/esm/components/StorageManager/hooks/useUploadFiles/resolveFile.mjs +0 -1
  50. package/dist/types/components/StorageImage/_tests_/StorageImage.test.d.ts +0 -1
  51. package/dist/types/components/StorageManager/hooks/useUploadFiles/resolveFile.d.ts +0 -10
@@ -1 +1,57 @@
1
- import*as e from"react";import r from"classnames";import{ComponentClassName as a}from"@aws-amplify/ui";import{Image as t}from"@aws-amplify/ui-react";import{useStorageURL as o}from"@aws-amplify/ui-react/internal";const m=({accessLevel:m,className:i,fallbackSrc:s,identityId:c,imgKey:l,onStorageGetError:n,...f})=>{const p=e.useMemo((()=>({level:m,identityId:c})),[m,c]),y=o({key:l,options:p,fallbackURL:s,onStorageGetError:n});return e.createElement(t,{...f,className:r(a.StorageImage,i),src:y})};export{m as StorageImage};
1
+ import * as React from 'react';
2
+ import { classNames, ComponentClassName } from '@aws-amplify/ui';
3
+ import { Image } from '@aws-amplify/ui-react';
4
+ import { useDeprecationWarning } from '@aws-amplify/ui-react/internal';
5
+ import { useSetUserAgent, useGetUrl } from '@aws-amplify/ui-react-core';
6
+ import { VERSION } from '../../version.mjs';
7
+
8
+ const MISSING_REQUIRED_PROP_MESSAGE = '`StorageImage` requires either an `imgKey` or `path` prop.';
9
+ 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';
10
+ const HAS_PATH_AND_KEY_MESSAGE = '`imgKey` is ignored when both `imgKey` and `path` props are provided.';
11
+ const HAS_PATH_AND_UNSUPPORTED_OPTIONS_MESSAGE = '`accessLevel` and `identityId` are ignored when the `path` prop is provided.';
12
+ const getDeprecationMessage = ({ hasImgkey, hasPath, hasDeprecatedOptions, }) => {
13
+ let message = '';
14
+ if (hasPath && hasImgkey) {
15
+ message = HAS_PATH_AND_KEY_MESSAGE;
16
+ }
17
+ else if (hasPath && hasDeprecatedOptions) {
18
+ message = HAS_PATH_AND_UNSUPPORTED_OPTIONS_MESSAGE;
19
+ }
20
+ else if (hasImgkey) {
21
+ message = HAS_DEPRECATED_PROPS_MESSAGE;
22
+ }
23
+ return message;
24
+ };
25
+ const StorageImage = ({ accessLevel, className, fallbackSrc, identityId, imgKey, path, onStorageGetError, onGetUrlError, validateObjectExistence = true, ...rest }) => {
26
+ const hasImgkey = !!imgKey;
27
+ const hasPath = !!path;
28
+ const hasDeprecatedOptions = !!accessLevel || !!identityId;
29
+ const message = getDeprecationMessage({
30
+ hasDeprecatedOptions,
31
+ hasImgkey,
32
+ hasPath,
33
+ });
34
+ useDeprecationWarning({ message, shouldWarn: !!message });
35
+ if (!hasImgkey && !hasPath) {
36
+ throw new Error(MISSING_REQUIRED_PROP_MESSAGE);
37
+ }
38
+ useSetUserAgent({
39
+ componentName: 'StorageImage',
40
+ packageName: 'react-storage',
41
+ version: VERSION,
42
+ });
43
+ const onError = onGetUrlError ?? onStorageGetError;
44
+ const input = React.useMemo(() => ({
45
+ ...(path ? { path } : { key: imgKey }),
46
+ onError,
47
+ options: {
48
+ accessLevel,
49
+ targetIdentityId: identityId,
50
+ validateObjectExistence,
51
+ },
52
+ }), [accessLevel, imgKey, identityId, onError, path, validateObjectExistence]);
53
+ const { url } = useGetUrl(input);
54
+ return (React.createElement(Image, { ...rest, className: classNames(ComponentClassName.StorageImage, className), src: url?.toString() ?? fallbackSrc }));
55
+ };
56
+
57
+ export { HAS_DEPRECATED_PROPS_MESSAGE, HAS_PATH_AND_KEY_MESSAGE, HAS_PATH_AND_UNSUPPORTED_OPTIONS_MESSAGE, MISSING_REQUIRED_PROP_MESSAGE, StorageImage };
@@ -1 +1,181 @@
1
- import*as e from"react";import{Logger as i}from"aws-amplify";import{ComponentClassName as t}from"@aws-amplify/ui";import{VisuallyHidden as o}from"@aws-amplify/ui-react";import{useDropZone as l}from"@aws-amplify/ui-react/internal";import{useStorageManager as r}from"./hooks/useStorageManager/useStorageManager.mjs";import{useUploadFiles as s}from"./hooks/useUploadFiles/useUploadFiles.mjs";import{FileStatus as a}from"./types.mjs";import{Container as n}from"./ui/Container/Container.mjs";import{DropZone as p}from"./ui/DropZone/DropZone.mjs";import{FileList as m}from"./ui/FileList/FileList.mjs";import{FileListHeader as c}from"./ui/FileListHeader/FileListHeader.mjs";import{FileListFooter as u}from"./ui/FileListFooter/FileListFooter.mjs";import{FilePicker as d}from"./ui/FilePicker/FilePicker.mjs";import{checkMaxFileSize as F}from"./utils/checkMaxFileSize.mjs";import{defaultStorageManagerDisplayText as f}from"./utils/displayText.mjs";import{filterAllowedFiles as g}from"./utils/filterAllowedFiles.mjs";const U=new i("Storage.StorageManager");const E=Object.assign(e.forwardRef((function({acceptedFileTypes:i=[],accessLevel:E,autoUpload:y=!0,defaultFiles:D,displayText:L,isResumable:S=!1,maxFileCount:h,maxFileSize:x,onUploadError:C,onUploadSuccess:j,onFileRemove:T,onUploadStart:k,showThumbnails:v=!0,processFile:w,components:P,provider:M,path:b},R){E&&h||U.warn("StorageManager requires accessLevel and maxFileCount props");const A={Container:n,DropZone:p,FileList:m,FilePicker:d,FileListHeader:c,FileListFooter:u,...P},H=void 0===h||"number"==typeof h&&h>1,Z={...f,...L},{getFileSizeErrorText:z}=Z,O=e=>F({file:e,maxFileSize:x,getFileSizeErrorText:z}),{addFiles:q,clearFiles:I,files:Q,removeUpload:$,queueFiles:N,setUploadingFile:B,setUploadPaused:G,setUploadProgress:J,setUploadSuccess:K,setUploadResumed:V}=r(D);e.useImperativeHandle(R,(()=>({clearFiles:I})));const{dragState:W,...X}=l({acceptedFileTypes:i,onDropComplete:({acceptedFiles:e,rejectedFiles:t})=>{t&&t.length>0&&U.warn("Rejected files: ",t);const o=g(e,i);q({files:o,status:y?a.QUEUED:a.ADDED,getFileErrorMessage:O})}});s({accessLevel:E,files:Q,isResumable:S,maxFileCount:h,onUploadError:C,onUploadSuccess:j,onUploadStart:k,setUploadingFile:B,setUploadProgress:J,setUploadSuccess:K,processFile:w,provider:M,path:b});const Y=0!==Q.length&&Q.every((e=>e?.status===a.UPLOADED)),_=Q.filter((e=>e.progress<100)).length>h,ee=Q.filter((e=>e?.status===a.UPLOADED)).length,ie=Q.length-ee,te=y?0:ie,oe=Q.length>0,le=!y&&ie>0,re=e.useRef(null);return e.createElement(A.Container,{className:`${t.StorageManager} ${oe?t.StorageManagerPreviewer:""}`},e.createElement(A.DropZone,{inDropZone:"inactive"!==W,...X,displayText:Z},e.createElement(e.Fragment,null,e.createElement(A.FilePicker,{onClick:function(){re.current&&(re.current.click(),re.current.value="")}},Z.browseFilesText),e.createElement(o,null,e.createElement("input",{type:"file",tabIndex:-1,ref:re,onChange:e=>{const{files:i}=e.target;i&&0!==i.length&&q({files:Array.from(i),status:y?a.QUEUED:a.ADDED,getFileErrorMessage:O})},multiple:H,accept:i.join(",")})))),oe?e.createElement(A.FileListHeader,{allUploadsSuccessful:Y,displayText:Z,fileCount:Q.length,remainingFilesCount:ie,selectedFilesCount:te}):null,e.createElement(A.FileList,{displayText:Z,files:Q,isResumable:S,onCancelUpload:({id:e,uploadTask:i})=>{i.pause(),$({id:e})},onDeleteUpload:({id:e})=>{if($({id:e}),"function"==typeof T){const i=Q.find((i=>i.id===e));i&&T({key:i.key})}},onResume:({id:e,uploadTask:i})=>{i.resume(),V({id:e})},onPause:({id:e,uploadTask:i})=>{i.pause(),G({id:e})},showThumbnails:v,hasMaxFilesError:_,maxFileCount:h}),le?e.createElement(A.FileListFooter,{displayText:Z,remainingFilesCount:ie,onClearAll:()=>{I()},onUploadAll:()=>{N()}}):null)})),{Container:n,DropZone:p,FileList:m,FileListHeader:c,FileListFooter:u,FilePicker:d});export{E as StorageManager};
1
+ import * as React from 'react';
2
+ import { getLogger, ComponentClassName } from '@aws-amplify/ui';
3
+ import { VisuallyHidden } from '@aws-amplify/ui-react';
4
+ import { useDeprecationWarning, useSetUserAgent } from '@aws-amplify/ui-react-core';
5
+ import { useDropZone } from '@aws-amplify/ui-react/internal';
6
+ import { useStorageManager } from './hooks/useStorageManager/useStorageManager.mjs';
7
+ import { useUploadFiles } from './hooks/useUploadFiles/useUploadFiles.mjs';
8
+ import { FileStatus } from './types.mjs';
9
+ import { Container } from './ui/Container/Container.mjs';
10
+ import { DropZone } from './ui/DropZone/DropZone.mjs';
11
+ import { FileList } from './ui/FileList/FileList.mjs';
12
+ import { FileListHeader } from './ui/FileListHeader/FileListHeader.mjs';
13
+ import { FileListFooter } from './ui/FileListFooter/FileListFooter.mjs';
14
+ import { FilePicker } from './ui/FilePicker/FilePicker.mjs';
15
+ import { checkMaxFileSize } from './utils/checkMaxFileSize.mjs';
16
+ import { defaultStorageManagerDisplayText } from './utils/displayText.mjs';
17
+ import { filterAllowedFiles } from './utils/filterAllowedFiles.mjs';
18
+ import 'aws-amplify/auth';
19
+ import 'aws-amplify/storage';
20
+ import { VERSION } from '../../version.mjs';
21
+
22
+ const logger = getLogger('Storage');
23
+ const MISSING_REQUIRED_PROPS_MESSAGE = '`StorageManager` requires a `maxFileCount` prop to be provided.';
24
+ const ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE = '`StorageManager` does not allow usage of a `path` callback prop with an `accessLevel` prop.';
25
+ 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';
26
+ const StorageManagerBase = React.forwardRef(function StorageManager({ acceptedFileTypes = [], accessLevel, autoUpload = true, components, defaultFiles, displayText: overrideDisplayText, isResumable = false, maxFileCount, maxFileSize, onFileRemove, onUploadError, onUploadStart, onUploadSuccess, path, processFile, showThumbnails = true, }, ref) {
27
+ if (!maxFileCount) {
28
+ // eslint-disable-next-line no-console
29
+ console.warn(MISSING_REQUIRED_PROPS_MESSAGE);
30
+ }
31
+ if (accessLevel && typeof path === 'function') {
32
+ throw new Error(ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE);
33
+ }
34
+ useDeprecationWarning({
35
+ message: ACCESS_LEVEL_DEPRECATION_MESSAGE,
36
+ shouldWarn: !!accessLevel,
37
+ });
38
+ const Components = {
39
+ Container,
40
+ DropZone,
41
+ FileList,
42
+ FilePicker,
43
+ FileListHeader,
44
+ FileListFooter,
45
+ ...components,
46
+ };
47
+ const allowMultipleFiles = maxFileCount === undefined ||
48
+ (typeof maxFileCount === 'number' && maxFileCount > 1);
49
+ const displayText = {
50
+ ...defaultStorageManagerDisplayText,
51
+ ...overrideDisplayText,
52
+ };
53
+ const { getFileSizeErrorText } = displayText;
54
+ const getMaxFileSizeErrorMessage = (file) => {
55
+ return checkMaxFileSize({
56
+ file,
57
+ maxFileSize,
58
+ getFileSizeErrorText,
59
+ });
60
+ };
61
+ const { addFiles, clearFiles, files, removeUpload, queueFiles, setUploadingFile, setUploadPaused, setUploadProgress, setUploadSuccess, setUploadResumed, } = useStorageManager(defaultFiles);
62
+ React.useImperativeHandle(ref, () => ({ clearFiles }));
63
+ const { dragState, ...dropZoneProps } = useDropZone({
64
+ acceptedFileTypes,
65
+ onDropComplete: ({ acceptedFiles, rejectedFiles }) => {
66
+ if (rejectedFiles && rejectedFiles.length > 0) {
67
+ logger.warn('Rejected files: ', rejectedFiles);
68
+ }
69
+ // We need to filter out files by extension here,
70
+ // we don't get filenames on the drag event, only on drop
71
+ const _acceptedFiles = filterAllowedFiles(acceptedFiles, acceptedFileTypes);
72
+ addFiles({
73
+ files: _acceptedFiles,
74
+ status: autoUpload ? FileStatus.QUEUED : FileStatus.ADDED,
75
+ getFileErrorMessage: getMaxFileSizeErrorMessage,
76
+ });
77
+ },
78
+ });
79
+ useUploadFiles({
80
+ accessLevel,
81
+ files,
82
+ isResumable,
83
+ maxFileCount,
84
+ onUploadError,
85
+ onUploadSuccess,
86
+ onUploadStart,
87
+ setUploadingFile,
88
+ setUploadProgress,
89
+ setUploadSuccess,
90
+ processFile,
91
+ path,
92
+ });
93
+ const onFilePickerChange = (event) => {
94
+ const { files } = event.target;
95
+ if (!files || files.length === 0) {
96
+ return;
97
+ }
98
+ addFiles({
99
+ files: Array.from(files),
100
+ status: autoUpload ? FileStatus.QUEUED : FileStatus.ADDED,
101
+ getFileErrorMessage: getMaxFileSizeErrorMessage,
102
+ });
103
+ };
104
+ const onClearAll = () => {
105
+ clearFiles();
106
+ };
107
+ const onUploadAll = () => {
108
+ queueFiles();
109
+ };
110
+ const onPauseUpload = ({ id, uploadTask }) => {
111
+ uploadTask.pause();
112
+ setUploadPaused({ id });
113
+ };
114
+ const onResumeUpload = ({ id, uploadTask }) => {
115
+ uploadTask.resume();
116
+ setUploadResumed({ id });
117
+ };
118
+ const onCancelUpload = ({ id, uploadTask }) => {
119
+ // At this time we don't know if the delete
120
+ // permissions are enabled (required to cancel upload),
121
+ // so we do a pause instead and remove from files
122
+ uploadTask.pause();
123
+ removeUpload({ id });
124
+ };
125
+ const onDeleteUpload = ({ id }) => {
126
+ // At this time we don't know if the delete
127
+ // permissions are enabled, so we do a soft delete
128
+ // from file list, but don't remove from storage
129
+ removeUpload({ id });
130
+ if (typeof onFileRemove === 'function') {
131
+ const file = files.find((file) => file.id === id);
132
+ if (file) {
133
+ onFileRemove({ key: file.key });
134
+ }
135
+ }
136
+ };
137
+ // checks if all downloads completed to 100%
138
+ const allUploadsSuccessful = files.length === 0
139
+ ? false
140
+ : files.every((file) => file?.status === FileStatus.UPLOADED);
141
+ // Displays if over max files
142
+ const hasMaxFilesError = files.filter((file) => file.progress < 100).length > maxFileCount;
143
+ const uploadedFilesLength = files.filter((file) => file?.status === FileStatus.UPLOADED).length;
144
+ const remainingFilesCount = files.length - uploadedFilesLength;
145
+ // number of files selected for upload when autoUpload is turned off
146
+ const selectedFilesCount = autoUpload ? 0 : remainingFilesCount;
147
+ const hasFiles = files.length > 0;
148
+ const hasUploadActions = !autoUpload && remainingFilesCount > 0;
149
+ const hiddenInput = React.useRef(null);
150
+ function handleClick() {
151
+ if (hiddenInput.current) {
152
+ hiddenInput.current.click();
153
+ hiddenInput.current.value = '';
154
+ }
155
+ }
156
+ useSetUserAgent({
157
+ componentName: 'StorageManager',
158
+ packageName: 'react-storage',
159
+ version: VERSION,
160
+ });
161
+ return (React.createElement(Components.Container, { className: `${ComponentClassName.StorageManager} ${hasFiles ? ComponentClassName.StorageManagerPreviewer : ''}` },
162
+ React.createElement(Components.DropZone, { inDropZone: dragState !== 'inactive', ...dropZoneProps, displayText: displayText },
163
+ React.createElement(React.Fragment, null,
164
+ React.createElement(Components.FilePicker, { onClick: handleClick }, displayText.browseFilesText),
165
+ React.createElement(VisuallyHidden, null,
166
+ React.createElement("input", { type: "file", tabIndex: -1, ref: hiddenInput, onChange: onFilePickerChange, multiple: allowMultipleFiles, accept: acceptedFileTypes.join(',') })))),
167
+ hasFiles ? (React.createElement(Components.FileListHeader, { allUploadsSuccessful: allUploadsSuccessful, displayText: displayText, fileCount: files.length, remainingFilesCount: remainingFilesCount, selectedFilesCount: selectedFilesCount })) : null,
168
+ React.createElement(Components.FileList, { displayText: displayText, files: files, isResumable: isResumable, onCancelUpload: onCancelUpload, onDeleteUpload: onDeleteUpload, onResume: onResumeUpload, onPause: onPauseUpload, showThumbnails: showThumbnails, hasMaxFilesError: hasMaxFilesError, maxFileCount: maxFileCount }),
169
+ hasUploadActions ? (React.createElement(Components.FileListFooter, { displayText: displayText, remainingFilesCount: remainingFilesCount, onClearAll: onClearAll, onUploadAll: onUploadAll })) : null));
170
+ });
171
+ // pass an empty object as first param to avoid destructive action on `StorageManagerBase`
172
+ const StorageManager = Object.assign({}, StorageManagerBase, {
173
+ Container,
174
+ DropZone,
175
+ FileList,
176
+ FileListHeader,
177
+ FileListFooter,
178
+ FilePicker,
179
+ });
180
+
181
+ export { ACCESS_LEVEL_DEPRECATION_MESSAGE, ACCESS_LEVEL_WITH_PATH_CALLBACK_MESSAGE, MISSING_REQUIRED_PROPS_MESSAGE, StorageManager };
@@ -1 +1,35 @@
1
- import{StorageManagerActionTypes as s}from"./types.mjs";const e=({files:e,status:t,getFileErrorMessage:p})=>({type:s.ADD_FILES,files:e,status:t,getFileErrorMessage:p}),t=()=>({type:s.CLEAR_FILES}),p=()=>({type:s.QUEUE_FILES}),E=({id:e,uploadTask:t})=>({type:s.SET_STATUS_UPLOADING,id:e,uploadTask:t}),i=({id:e,progress:t})=>({type:s.SET_UPLOAD_PROGRESS,id:e,progress:t}),r=({id:e,status:t})=>({type:s.SET_STATUS,id:e,status:t}),S=({id:e})=>({type:s.REMOVE_UPLOAD,id:e});export{e as addFilesAction,t as clearFilesAction,p as queueFilesAction,S as removeUploadAction,i as setUploadProgressAction,r as setUploadStatusAction,E as setUploadingFileAction};
1
+ import { StorageManagerActionTypes } from './types.mjs';
2
+
3
+ const addFilesAction = ({ files, status, getFileErrorMessage, }) => ({
4
+ type: StorageManagerActionTypes.ADD_FILES,
5
+ files,
6
+ status,
7
+ getFileErrorMessage,
8
+ });
9
+ const clearFilesAction = () => ({
10
+ type: StorageManagerActionTypes.CLEAR_FILES,
11
+ });
12
+ const queueFilesAction = () => ({
13
+ type: StorageManagerActionTypes.QUEUE_FILES,
14
+ });
15
+ const setUploadingFileAction = ({ id, uploadTask, }) => ({
16
+ type: StorageManagerActionTypes.SET_STATUS_UPLOADING,
17
+ id,
18
+ uploadTask,
19
+ });
20
+ const setUploadProgressAction = ({ id, progress, }) => ({
21
+ type: StorageManagerActionTypes.SET_UPLOAD_PROGRESS,
22
+ id,
23
+ progress,
24
+ });
25
+ const setUploadStatusAction = ({ id, status, }) => ({
26
+ type: StorageManagerActionTypes.SET_STATUS,
27
+ id,
28
+ status,
29
+ });
30
+ const removeUploadAction = ({ id }) => ({
31
+ type: StorageManagerActionTypes.REMOVE_UPLOAD,
32
+ id,
33
+ });
34
+
35
+ export { addFilesAction, clearFilesAction, queueFilesAction, removeUploadAction, setUploadProgressAction, setUploadStatusAction, setUploadingFileAction };
@@ -1 +1,132 @@
1
- import{FileStatus as s}from"../../types.mjs";import{StorageManagerActionTypes as e}from"./types.mjs";function r(r,t){switch(t.type){case e.ADD_FILES:{const{files:e,status:i}=t,a=e.map((e=>{const r=t.getFileErrorMessage(e);return{id:e.name,file:e,error:r,key:e.name,status:r?s.ERROR:i,isImage:e.type.startsWith("image/"),progress:-1}})),o=[...r.files,...a];return{...r,files:o}}case e.CLEAR_FILES:return{...r,files:[]};case e.QUEUE_FILES:{const{files:e}=r,t=e.reduce(((e,r)=>[...e,{...r,status:s.QUEUED}]),[]);return{...r,files:t}}case e.SET_STATUS_UPLOADING:{const{id:e,uploadTask:i}=t,{files:a}=r,o=a.reduce(((r,t)=>t.id===e?[...r,{...t,status:s.UPLOADING,progress:0,uploadTask:i||void 0}]:[...r,t]),[]);return{...r,files:o}}case e.SET_UPLOAD_PROGRESS:{const{id:s,progress:e}=t,{files:i}=r,a=i.reduce(((r,t)=>t.id===s?[...r,{...t,progress:e}]:[...r,t]),[]);return{...r,files:a}}case e.SET_STATUS:{const{id:s,status:e}=t,{files:i}=r,a=i.reduce(((r,t)=>t.id===s?[...r,{...t,status:e}]:[...r,t]),[]);return{...r,files:a}}case e.REMOVE_UPLOAD:{const{id:s}=t,{files:e}=r,i=e.reduce(((e,r)=>r.id===s?[...e]:[...e,r]),[]);return{...r,files:i}}}}export{r as storageManagerStateReducer};
1
+ import { FileStatus } from '../../types.mjs';
2
+ import { StorageManagerActionTypes } from './types.mjs';
3
+
4
+ function storageManagerStateReducer(state, action) {
5
+ switch (action.type) {
6
+ case StorageManagerActionTypes.ADD_FILES: {
7
+ const { files, status } = action;
8
+ const newUploads = files.map((file) => {
9
+ const errorText = action.getFileErrorMessage(file);
10
+ return {
11
+ // make sure id is unique,
12
+ // we only use it internally and don't send it to Storage
13
+ id: `${Date.now()}-${file.name}`,
14
+ file,
15
+ error: errorText,
16
+ key: file.name,
17
+ status: errorText ? FileStatus.ERROR : status,
18
+ isImage: file.type.startsWith('image/'),
19
+ progress: -1,
20
+ };
21
+ });
22
+ const newFiles = [...state.files, ...newUploads];
23
+ return {
24
+ ...state,
25
+ files: newFiles,
26
+ };
27
+ }
28
+ case StorageManagerActionTypes.CLEAR_FILES: {
29
+ return {
30
+ ...state,
31
+ files: [],
32
+ };
33
+ }
34
+ case StorageManagerActionTypes.QUEUE_FILES: {
35
+ const { files } = state;
36
+ const newFiles = files.reduce((files, currentFile) => {
37
+ return [
38
+ ...files,
39
+ {
40
+ ...currentFile,
41
+ ...(currentFile.status === FileStatus.ADDED
42
+ ? { status: FileStatus.QUEUED }
43
+ : {}),
44
+ },
45
+ ];
46
+ }, []);
47
+ return {
48
+ ...state,
49
+ files: newFiles,
50
+ };
51
+ }
52
+ case StorageManagerActionTypes.SET_STATUS_UPLOADING: {
53
+ const { id, uploadTask } = action;
54
+ const { files } = state;
55
+ const newFiles = files.reduce((files, currentFile) => {
56
+ if (currentFile.id === id) {
57
+ return [
58
+ ...files,
59
+ {
60
+ ...currentFile,
61
+ status: FileStatus.UPLOADING,
62
+ progress: 0,
63
+ uploadTask,
64
+ },
65
+ ];
66
+ }
67
+ return [...files, currentFile];
68
+ }, []);
69
+ return {
70
+ ...state,
71
+ files: newFiles,
72
+ };
73
+ }
74
+ case StorageManagerActionTypes.SET_UPLOAD_PROGRESS: {
75
+ const { id, progress } = action;
76
+ const { files } = state;
77
+ const newFiles = files.reduce((files, currentFile) => {
78
+ if (currentFile.id === id) {
79
+ return [
80
+ ...files,
81
+ {
82
+ ...currentFile,
83
+ progress,
84
+ },
85
+ ];
86
+ }
87
+ return [...files, currentFile];
88
+ }, []);
89
+ return {
90
+ ...state,
91
+ files: newFiles,
92
+ };
93
+ }
94
+ case StorageManagerActionTypes.SET_STATUS: {
95
+ const { id, status } = action;
96
+ const { files } = state;
97
+ const newFiles = files.reduce((files, currentFile) => {
98
+ if (currentFile.id === id) {
99
+ return [
100
+ ...files,
101
+ {
102
+ ...currentFile,
103
+ status,
104
+ },
105
+ ];
106
+ }
107
+ return [...files, currentFile];
108
+ }, []);
109
+ return {
110
+ ...state,
111
+ files: newFiles,
112
+ };
113
+ }
114
+ case StorageManagerActionTypes.REMOVE_UPLOAD: {
115
+ const { id } = action;
116
+ const { files } = state;
117
+ const newFiles = files.reduce((files, currentFile) => {
118
+ if (currentFile.id === id) {
119
+ // remove by not returning currentFile
120
+ return [...files];
121
+ }
122
+ return [...files, currentFile];
123
+ }, []);
124
+ return {
125
+ ...state,
126
+ files: newFiles,
127
+ };
128
+ }
129
+ }
130
+ }
131
+
132
+ export { storageManagerStateReducer };
@@ -1 +1,12 @@
1
- var E;!function(E){E.ADD_FILES="ADD_FILES",E.CLEAR_FILES="CLEAR_FILES",E.QUEUE_FILES="QUEUE_FILES",E.SET_STATUS="SET_STATUS",E.SET_STATUS_UPLOADING="SET_STATUS_UPLOADING",E.SET_UPLOAD_PROGRESS="SET_UPLOAD_PROGRESS",E.REMOVE_UPLOAD="REMOVE_UPLOAD"}(E||(E={}));export{E as StorageManagerActionTypes};
1
+ var StorageManagerActionTypes;
2
+ (function (StorageManagerActionTypes) {
3
+ StorageManagerActionTypes["ADD_FILES"] = "ADD_FILES";
4
+ StorageManagerActionTypes["CLEAR_FILES"] = "CLEAR_FILES";
5
+ StorageManagerActionTypes["QUEUE_FILES"] = "QUEUE_FILES";
6
+ StorageManagerActionTypes["SET_STATUS"] = "SET_STATUS";
7
+ StorageManagerActionTypes["SET_STATUS_UPLOADING"] = "SET_STATUS_UPLOADING";
8
+ StorageManagerActionTypes["SET_UPLOAD_PROGRESS"] = "SET_UPLOAD_PROGRESS";
9
+ StorageManagerActionTypes["REMOVE_UPLOAD"] = "REMOVE_UPLOAD";
10
+ })(StorageManagerActionTypes || (StorageManagerActionTypes = {}));
11
+
12
+ export { StorageManagerActionTypes };
@@ -1 +1,58 @@
1
- import s from"react";import{FileStatus as e}from"../../types.mjs";import{storageManagerStateReducer as i}from"./reducer.mjs";import{addFilesAction as r,clearFilesAction as t,queueFilesAction as o,setUploadingFileAction as a,setUploadProgressAction as d,setUploadStatusAction as l,removeUploadAction as p}from"./actions.mjs";import{isObject as u}from"@aws-amplify/ui";const m=s=>(s=>!(!u(s)||!s.key))(s)?{...s,id:s.key,status:e.UPLOADED}:void 0;function f(u=[]){const[{files:f},c]=s.useReducer(i,{files:Array.isArray(u)?u.map(m).filter((s=>!!s)):[]});return{removeUpload:({id:s})=>{c(p({id:s}))},setUploadPaused:({id:s})=>{c(l({id:s,status:e.PAUSED}))},setUploadProgress:({progress:s,id:e})=>{c(d({id:e,progress:s}))},setUploadResumed:({id:s})=>{c(l({id:s,status:e.UPLOADING}))},setUploadSuccess:({id:s})=>{c(l({id:s,status:e.UPLOADED}))},setUploadingFile:({uploadTask:s,id:e})=>{c(a({id:e,uploadTask:s}))},queueFiles:()=>{c(o())},addFiles:({files:s,status:e,getFileErrorMessage:i})=>{c(r({files:s,status:e,getFileErrorMessage:i}))},clearFiles:()=>{c(t())},files:f}}export{f as useStorageManager};
1
+ import React__default from 'react';
2
+ import { isObject } from '@aws-amplify/ui';
3
+ import { FileStatus } from '../../types.mjs';
4
+ import { storageManagerStateReducer } from './reducer.mjs';
5
+ import { addFilesAction, clearFilesAction, queueFilesAction, setUploadingFileAction, setUploadProgressAction, setUploadStatusAction, removeUploadAction } from './actions.mjs';
6
+
7
+ const isDefaultFile = (file) => !!(isObject(file) && file.key);
8
+ const createFileFromDefault = (file) => isDefaultFile(file)
9
+ ? { ...file, id: file.key, status: FileStatus.UPLOADED }
10
+ : undefined;
11
+ function useStorageManager(defaultFiles = []) {
12
+ const [{ files }, dispatch] = React__default.useReducer(storageManagerStateReducer, {
13
+ files: (Array.isArray(defaultFiles)
14
+ ? defaultFiles.map(createFileFromDefault).filter((file) => !!file)
15
+ : []),
16
+ });
17
+ const addFiles = ({ files, status, getFileErrorMessage, }) => {
18
+ dispatch(addFilesAction({ files, status, getFileErrorMessage }));
19
+ };
20
+ const clearFiles = () => {
21
+ dispatch(clearFilesAction());
22
+ };
23
+ const queueFiles = () => {
24
+ dispatch(queueFilesAction());
25
+ };
26
+ const setUploadingFile = ({ uploadTask, id, }) => {
27
+ dispatch(setUploadingFileAction({ id, uploadTask }));
28
+ };
29
+ const setUploadProgress = ({ progress, id, }) => {
30
+ dispatch(setUploadProgressAction({ id, progress }));
31
+ };
32
+ const setUploadSuccess = ({ id }) => {
33
+ dispatch(setUploadStatusAction({ id, status: FileStatus.UPLOADED }));
34
+ };
35
+ const setUploadPaused = ({ id }) => {
36
+ dispatch(setUploadStatusAction({ id, status: FileStatus.PAUSED }));
37
+ };
38
+ const setUploadResumed = ({ id }) => {
39
+ dispatch(setUploadStatusAction({ id, status: FileStatus.UPLOADING }));
40
+ };
41
+ const removeUpload = ({ id }) => {
42
+ dispatch(removeUploadAction({ id }));
43
+ };
44
+ return {
45
+ removeUpload,
46
+ setUploadPaused,
47
+ setUploadProgress,
48
+ setUploadResumed,
49
+ setUploadSuccess,
50
+ setUploadingFile,
51
+ queueFiles,
52
+ addFiles,
53
+ clearFiles,
54
+ files,
55
+ };
56
+ }
57
+
58
+ export { useStorageManager };
@@ -1 +1,74 @@
1
- import*as e from"react";import{uploadFile as o}from"../../utils/uploadFile.mjs";import{FileStatus as s}from"../../types.mjs";import{resolveFile as l}from"./resolveFile.mjs";function r({files:r,accessLevel:t,isResumable:a,setUploadProgress:i,setUploadingFile:p,setUploadSuccess:c,onUploadError:d,onUploadSuccess:f,onUploadStart:m,maxFileCount:n,processFile:u,provider:k,path:U=""}){e.useEffect((()=>{const e=r.filter((e=>e.status===s.QUEUED));if(!(e.length>n))for(const{file:s,key:r,id:n}of e){const e=e=>{f?.(e),c({id:n})},y=e=>{const o=0===e.total?100:Math.floor(e.loaded/e.total*100);i({id:n,progress:o})},v=e=>{d?.(e,{key:r})};s&&l({processFile:u,file:s,key:r}).then((({key:s,...l})=>{m?.({key:s});const r=o({...l,isResumable:a,provider:k,key:U+s,level:t,completeCallback:e,progressCallback:y,errorCallback:v});p({id:n,uploadTask:a?r:void 0})}))}}),[r,t,a,i,p,d,f,m,n,c,u,k,U])}export{r as useUploadFiles};
1
+ import * as React from 'react';
2
+ import { isFunction } from '@aws-amplify/ui';
3
+ import { getInput } from '../../utils/getInput.mjs';
4
+ import { uploadFile } from '../../utils/uploadFile.mjs';
5
+ import { FileStatus } from '../../types.mjs';
6
+
7
+ function useUploadFiles({ files, accessLevel, isResumable, setUploadProgress, setUploadingFile, setUploadSuccess, onUploadError, onUploadSuccess, onUploadStart, maxFileCount, processFile, path, }) {
8
+ React.useEffect(() => {
9
+ const filesReadyToUpload = files.filter((file) => file.status === FileStatus.QUEUED);
10
+ if (filesReadyToUpload.length > maxFileCount) {
11
+ return;
12
+ }
13
+ for (const { file, key, id } of filesReadyToUpload) {
14
+ const onProgress = (event) => {
15
+ /**
16
+ * When a file is zero bytes, the progress.total will equal zero.
17
+ * Therefore, this will prevent a divide by zero error.
18
+ */
19
+ const progress = event.totalBytes === undefined || event.totalBytes === 0
20
+ ? 100
21
+ : Math.floor((event.transferredBytes / event.totalBytes) * 100);
22
+ setUploadProgress({ id, progress });
23
+ };
24
+ if (file) {
25
+ const input = getInput({
26
+ accessLevel,
27
+ file,
28
+ key,
29
+ onProgress,
30
+ path,
31
+ processFile,
32
+ });
33
+ uploadFile({
34
+ input,
35
+ onComplete: (event) => {
36
+ if (isFunction(onUploadSuccess)) {
37
+ onUploadSuccess({
38
+ key: event.key ??
39
+ event.path,
40
+ });
41
+ }
42
+ setUploadSuccess({ id });
43
+ },
44
+ onError: ({ key, error }) => {
45
+ if (isFunction(onUploadError)) {
46
+ onUploadError(error.message, { key });
47
+ }
48
+ },
49
+ onStart: ({ key, uploadTask }) => {
50
+ if (isFunction(onUploadStart)) {
51
+ onUploadStart({ key });
52
+ }
53
+ setUploadingFile({ id, uploadTask });
54
+ },
55
+ });
56
+ }
57
+ }
58
+ }, [
59
+ files,
60
+ accessLevel,
61
+ isResumable,
62
+ setUploadProgress,
63
+ setUploadingFile,
64
+ onUploadError,
65
+ onUploadSuccess,
66
+ onUploadStart,
67
+ maxFileCount,
68
+ setUploadSuccess,
69
+ processFile,
70
+ path,
71
+ ]);
72
+ }
73
+
74
+ export { useUploadFiles };
@@ -1 +1,11 @@
1
- var d;!function(d){d.ADDED="added",d.QUEUED="queued",d.UPLOADING="uploading",d.PAUSED="paused",d.ERROR="error",d.UPLOADED="uploaded"}(d||(d={}));export{d as FileStatus};
1
+ var FileStatus;
2
+ (function (FileStatus) {
3
+ FileStatus["ADDED"] = "added";
4
+ FileStatus["QUEUED"] = "queued";
5
+ FileStatus["UPLOADING"] = "uploading";
6
+ FileStatus["PAUSED"] = "paused";
7
+ FileStatus["ERROR"] = "error";
8
+ FileStatus["UPLOADED"] = "uploaded";
9
+ })(FileStatus || (FileStatus = {}));
10
+
11
+ export { FileStatus };
@@ -1 +1,8 @@
1
- import e from"react";import{View as r}from"@aws-amplify/ui-react";function a({children:a,className:t}){return e.createElement(r,{className:t},a)}export{a as Container};
1
+ import React__default from 'react';
2
+ import { View } from '@aws-amplify/ui-react';
3
+
4
+ function Container({ children, className, }) {
5
+ return React__default.createElement(View, { className: className }, children);
6
+ }
7
+
8
+ export { Container };
@@ -1 +1,16 @@
1
- import a from"react";import e from"classnames";import{classNameModifier as r,ComponentClassName as o}from"@aws-amplify/ui";import{View as t,Text as n}from"@aws-amplify/ui-react";import{useIcons as i,IconUpload as m}from"@aws-amplify/ui-react/internal";function p({children:p,displayText:s,inDropZone:g,onDragEnter:l,onDragLeave:c,onDragOver:D,onDragStart:d,onDrop:f,testId:u}){const{dropFilesText:E}=s,S=i("storageManager");return a.createElement(t,{className:e(g&&r(o.StorageManagerDropZone,"active"),o.StorageManagerDropZone),"data-testid":u,onDragStart:d,onDragEnter:l,onDragLeave:c,onDrop:f,onDragOver:D},a.createElement(t,{as:"span","aria-hidden":!0,className:o.StorageManagerDropZoneIcon},S?.upload??a.createElement(m,null)),a.createElement(n,{className:o.StorageManagerDropZoneText},E),p)}export{p as DropZone};
1
+ import React__default from 'react';
2
+ import { classNames, classNameModifier, ComponentClassName } from '@aws-amplify/ui';
3
+ import { View, Text } from '@aws-amplify/ui-react';
4
+ import { useIcons, IconUpload } from '@aws-amplify/ui-react/internal';
5
+
6
+ function DropZone({ children, displayText, inDropZone, onDragEnter, onDragLeave, onDragOver, onDragStart, onDrop, testId, }) {
7
+ const { dropFilesText } = displayText;
8
+ const icons = useIcons('storageManager');
9
+ return (React__default.createElement(View, { className: classNames(inDropZone &&
10
+ classNameModifier(ComponentClassName.StorageManagerDropZone, 'active'), ComponentClassName.StorageManagerDropZone), "data-testid": testId, onDragStart: onDragStart, onDragEnter: onDragEnter, onDragLeave: onDragLeave, onDrop: onDrop, onDragOver: onDragOver },
11
+ React__default.createElement(View, { as: "span", "aria-hidden": true, className: ComponentClassName.StorageManagerDropZoneIcon }, icons?.upload ?? React__default.createElement(IconUpload, null)),
12
+ React__default.createElement(Text, { className: ComponentClassName.StorageManagerDropZoneText }, dropFilesText),
13
+ children));
14
+ }
15
+
16
+ export { DropZone };
@@ -1 +1,23 @@
1
- import e from"react";import{ComponentClassName as a}from"@aws-amplify/ui";import{View as t,Loader as r,Button as l}from"@aws-amplify/ui-react";import{FileStatus as s}from"../../types.mjs";import{FileStatusMessage as i}from"./FileStatusMessage.mjs";import{FileRemoveButton as m}from"./FileRemoveButton.mjs";import{UploadDetails as o}from"./FileDetails.mjs";import{FileThumbnail as n}from"./FileThumbnail.mjs";function u({onPause:u,onResume:c,displayName:p,errorMessage:g,isImage:f,isResumable:d,loaderIsDeterminate:T,onRemove:x,progress:E,showThumbnails:S=!0,size:N,status:P,displayText:D,thumbnailUrl:U}){const{getPausedText:v,getUploadingText:y,uploadSuccessfulText:F,pauseText:M,resumeText:j}=D;return e.createElement(t,{className:a.StorageManagerFile},e.createElement(t,{className:a.StorageManagerFileWrapper},S?e.createElement(n,{isImage:f,fileName:p,url:U}):null,e.createElement(o,{displayName:p,fileSize:N}),P===s.UPLOADING?e.createElement(r,{className:a.StorageManagerLoader,variation:"linear",percentage:E,isDeterminate:T,isPercentageTextHidden:!0}):null,!d||P!==s.UPLOADING&&P!==s.PAUSED?null:P===s.PAUSED?e.createElement(l,{onClick:c,size:"small",variation:"link"},j):e.createElement(l,{onClick:u,size:"small",variation:"link"},M),e.createElement(m,{altText:`Remove file ${p}`,onClick:x})),e.createElement(i,{uploadSuccessfulText:F,getUploadingText:y,getPausedText:v,status:P,errorMessage:g,percentage:E}))}export{u as FileControl};
1
+ import React__default from 'react';
2
+ import { ComponentClassName } from '@aws-amplify/ui';
3
+ import { View, Loader, Button } from '@aws-amplify/ui-react';
4
+ import { FileStatus } from '../../types.mjs';
5
+ import { FileStatusMessage } from './FileStatusMessage.mjs';
6
+ import { FileRemoveButton } from './FileRemoveButton.mjs';
7
+ import { UploadDetails } from './FileDetails.mjs';
8
+ import { FileThumbnail } from './FileThumbnail.mjs';
9
+
10
+ function FileControl({ onPause, onResume, displayName, errorMessage, isImage, isResumable, loaderIsDeterminate, onRemove, progress, showThumbnails = true, size, status, displayText, thumbnailUrl, }) {
11
+ const { getPausedText, getUploadingText, uploadSuccessfulText, pauseButtonText, resumeButtonText, } = displayText;
12
+ return (React__default.createElement(View, { className: ComponentClassName.StorageManagerFile },
13
+ React__default.createElement(View, { className: ComponentClassName.StorageManagerFileWrapper },
14
+ showThumbnails ? (React__default.createElement(FileThumbnail, { isImage: isImage, fileName: displayName, url: thumbnailUrl })) : null,
15
+ React__default.createElement(UploadDetails, { displayName: displayName, fileSize: size }),
16
+ status === FileStatus.UPLOADING ? (React__default.createElement(Loader, { className: ComponentClassName.StorageManagerLoader, variation: "linear", percentage: progress, isDeterminate: loaderIsDeterminate, isPercentageTextHidden: true })) : null,
17
+ isResumable &&
18
+ (status === FileStatus.UPLOADING || status === FileStatus.PAUSED) ? (status === FileStatus.PAUSED ? (React__default.createElement(Button, { onClick: onResume, size: "small", variation: "link" }, resumeButtonText)) : (React__default.createElement(Button, { onClick: onPause, size: "small", variation: "link" }, pauseButtonText))) : null,
19
+ React__default.createElement(FileRemoveButton, { altText: `Remove file ${displayName}`, onClick: onRemove })),
20
+ React__default.createElement(FileStatusMessage, { uploadSuccessfulText: uploadSuccessfulText, getUploadingText: getUploadingText, getPausedText: getPausedText, status: status, errorMessage: errorMessage, percentage: progress })));
21
+ }
22
+
23
+ export { FileControl };