@aws-amplify/ui-react-storage 3.10.3 → 3.12.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.
Files changed (88) hide show
  1. package/dist/browser.js +1 -1
  2. package/dist/{createStorageBrowser-B75dAYRb.js → createStorageBrowser-D5xaObbd.js} +439 -251
  3. package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +12 -3
  4. package/dist/esm/components/StorageBrowser/actions/handlers/listLocationItems.mjs +1 -1
  5. package/dist/esm/components/StorageBrowser/actions/handlers/listLocations.mjs +1 -1
  6. package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +2 -1
  7. package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +6 -3
  8. package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +3 -1
  9. package/dist/esm/components/StorageBrowser/displayText/context.mjs +5 -1
  10. package/dist/esm/components/StorageBrowser/displayText/libraries/en/default.mjs +2 -0
  11. package/dist/esm/components/StorageBrowser/displayText/libraries/en/downloadView.mjs +23 -0
  12. package/dist/esm/components/StorageBrowser/displayText/libraries/en/locationDetailView.mjs +2 -0
  13. package/dist/esm/components/StorageBrowser/displayText/libraries/en/uploadView.mjs +3 -6
  14. package/dist/esm/components/StorageBrowser/displayText/utils.mjs +3 -1
  15. package/dist/esm/components/StorageBrowser/fileItems/constants.mjs +11 -0
  16. package/dist/esm/components/StorageBrowser/fileItems/context.mjs +42 -0
  17. package/dist/esm/components/StorageBrowser/fileItems/fileItemsReducer.mjs +33 -0
  18. package/dist/esm/components/StorageBrowser/fileItems/utils.mjs +55 -0
  19. package/dist/esm/components/StorageBrowser/useAction/utils.mjs +2 -2
  20. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +3 -2
  21. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/CreateFolderViewProvider.mjs +0 -1
  22. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteViewProvider.mjs +4 -3
  23. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +47 -0
  24. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.mjs +38 -0
  25. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs +66 -0
  26. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +3 -0
  27. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +7 -2
  28. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +23 -35
  29. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailViewProvider.mjs +0 -1
  30. package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +3 -3
  31. package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +3 -1
  32. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +2 -1
  33. package/dist/esm/components/StorageBrowser/views/hooks/usePaginate.mjs +1 -1
  34. package/dist/esm/components/StorageBrowser/views/useView.mjs +3 -0
  35. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/constants.mjs +9 -1
  36. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/copyResolvers.mjs +4 -42
  37. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.mjs +4 -42
  38. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/downloadResolvers.mjs +36 -0
  39. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/utils.mjs +45 -5
  40. package/dist/esm/version.mjs +1 -1
  41. package/dist/index.js +1 -1
  42. package/dist/styles.css +17 -2
  43. package/dist/types/components/StorageBrowser/actions/configs/defaults.d.ts +4 -3
  44. package/dist/types/components/StorageBrowser/actions/configs/types.d.ts +3 -1
  45. package/dist/types/components/StorageBrowser/actions/handlers/download.d.ts +2 -2
  46. package/dist/types/components/StorageBrowser/actions/index.d.ts +1 -1
  47. package/dist/types/components/StorageBrowser/createStorageBrowser/createProvider.d.ts +1 -1
  48. package/dist/types/components/StorageBrowser/createStorageBrowser/types.d.ts +23 -4
  49. package/dist/types/components/StorageBrowser/displayText/index.d.ts +2 -2
  50. package/dist/types/components/StorageBrowser/displayText/libraries/en/downloadView.d.ts +2 -0
  51. package/dist/types/components/StorageBrowser/displayText/types.d.ts +8 -2
  52. package/dist/types/components/StorageBrowser/displayText/utils.d.ts +2 -1
  53. package/dist/types/components/StorageBrowser/fileItems/constants.d.ts +4 -0
  54. package/dist/types/components/StorageBrowser/fileItems/context.d.ts +6 -0
  55. package/dist/types/components/StorageBrowser/fileItems/fileItemsReducer.d.ts +6 -0
  56. package/dist/types/components/StorageBrowser/fileItems/index.d.ts +3 -0
  57. package/dist/types/components/StorageBrowser/fileItems/types.d.ts +44 -0
  58. package/dist/types/components/StorageBrowser/fileItems/utils.d.ts +5 -0
  59. package/dist/types/components/StorageBrowser/validators/index.d.ts +1 -2
  60. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.d.ts +2 -0
  61. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.d.ts +3 -0
  62. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/index.d.ts +3 -0
  63. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/types.d.ts +22 -0
  64. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.d.ts +2 -0
  65. package/dist/types/components/StorageBrowser/views/LocationActionView/UploadView/types.d.ts +6 -1
  66. package/dist/types/components/StorageBrowser/views/LocationActionView/index.d.ts +2 -0
  67. package/dist/types/components/StorageBrowser/views/index.d.ts +2 -2
  68. package/dist/types/components/StorageBrowser/views/types.d.ts +5 -3
  69. package/dist/types/components/StorageBrowser/views/useView.d.ts +2 -1
  70. package/dist/types/components/StorageBrowser/views/utils/index.d.ts +1 -1
  71. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/__testUtils__/tasks.d.ts +6 -11
  72. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/constants.d.ts +1 -0
  73. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/copyResolvers.d.ts +2 -3
  74. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.d.ts +2 -3
  75. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/downloadResolvers.d.ts +2 -0
  76. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/index.d.ts +4 -2
  77. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/types.d.ts +15 -11
  78. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/utils.d.ts +15 -7
  79. package/dist/types/version.d.ts +1 -1
  80. package/package.json +3 -3
  81. package/dist/esm/components/StorageBrowser/files/context.mjs +0 -31
  82. package/dist/esm/components/StorageBrowser/files/utils.mjs +0 -52
  83. package/dist/esm/components/StorageBrowser/validators/isFileTooBig.mjs +0 -4
  84. package/dist/types/components/StorageBrowser/files/context.d.ts +0 -6
  85. package/dist/types/components/StorageBrowser/files/index.d.ts +0 -2
  86. package/dist/types/components/StorageBrowser/files/types.d.ts +0 -28
  87. package/dist/types/components/StorageBrowser/files/utils.d.ts +0 -7
  88. package/dist/types/components/StorageBrowser/validators/isFileTooBig.d.ts +0 -2
@@ -41,12 +41,21 @@ const uploadActionConfig = {
41
41
  },
42
42
  handler: defaultHandlers.upload,
43
43
  };
44
+ const downloadActionConfig = {
45
+ viewName: 'DownloadView',
46
+ actionListItem: {
47
+ disable: (selected) => !selected || selected.length === 0,
48
+ hide: (permissions) => !permissions.includes('get'),
49
+ icon: 'download',
50
+ label: 'Download',
51
+ },
52
+ handler: defaultHandlers.download,
53
+ };
44
54
  // Action view configs only, does not include `listLocationItems`
45
55
  const defaultActionViewConfigs = {
46
56
  copy: copyActionConfig,
47
57
  createFolder: createFolderActionConfig,
48
- // provide `download` handler only; `download` does not have a dedicated view/config
49
- download: defaultHandlers.download,
58
+ download: downloadActionConfig,
50
59
  delete: deleteActionConfig,
51
60
  upload: uploadActionConfig,
52
61
  };
@@ -57,4 +66,4 @@ const defaultActionConfigs = {
57
66
  listLocationItems: defaultHandlers.listLocationItems,
58
67
  };
59
68
 
60
- export { DEFAULT_ACTION_VIEW_TYPES, copyActionConfig, createFolderActionConfig, defaultActionConfigs, defaultActionViewConfigs, deleteActionConfig, isDefaultActionViewType, uploadActionConfig };
69
+ export { DEFAULT_ACTION_VIEW_TYPES, copyActionConfig, createFolderActionConfig, defaultActionConfigs, defaultActionViewConfigs, deleteActionConfig, downloadActionConfig, isDefaultActionViewType, uploadActionConfig };
@@ -66,7 +66,7 @@ const listLocationItemsHandler = async (input) => {
66
66
  nextNextToken = output.nextToken;
67
67
  const items = parseResult(output, prefix);
68
68
  result.push(...(exclude ? items.filter((item) => item.type !== exclude) : items));
69
- } while (nextNextToken && result.length < pageSize);
69
+ } while (nextNextToken && result.length < _pageSize);
70
70
  return { items: result, nextToken: nextNextToken };
71
71
  };
72
72
 
@@ -1,6 +1,6 @@
1
1
  import { listCallerAccessGrants } from '@aws-amplify/storage/internals';
2
- import '@aws-amplify/ui';
3
2
  import { assertAccountId } from '../../validators/assertAccountId.mjs';
3
+ import '@aws-amplify/ui';
4
4
  import { getFilteredLocations } from './utils.mjs';
5
5
 
6
6
  const DEFAULT_PAGE_SIZE = 1000;
@@ -15,9 +15,10 @@ import '../actions/configs/context.mjs';
15
15
  import '../actions/configs/defaults.mjs';
16
16
  import '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
17
17
  import '../views/LocationActionView/DeleteView/DeleteView.mjs';
18
+ import '../views/LocationActionView/DownloadView/DownloadView.mjs';
18
19
  import '../views/context/actionViews.mjs';
19
20
  import '../views/LocationActionView/UploadView/UploadView.mjs';
20
- import '../files/context.mjs';
21
+ import '../fileItems/context.mjs';
21
22
  import '../views/LocationDetailView/LocationDetailView.mjs';
22
23
  import '../views/LocationsView/LocationsView.mjs';
23
24
 
@@ -15,7 +15,8 @@ import { componentsDefault } from '../components/defaults.mjs';
15
15
  import { createConfigurationProvider } from '../configuration/createConfigurationProvider.mjs';
16
16
  import '../configuration/context.mjs';
17
17
  import { DisplayTextProvider } from '../displayText/context.mjs';
18
- import { FilesProvider } from '../files/context.mjs';
18
+ import { FileItemsProvider } from '../fileItems/context.mjs';
19
+ import { defaultValidateFile } from '../fileItems/utils.mjs';
19
20
  import { LocationItemsProvider } from '../locationItems/context.mjs';
20
21
  import { StoreProvider } from '../store/context.mjs';
21
22
  import { ActionHandlersProvider } from '../useAction/context.mjs';
@@ -25,12 +26,13 @@ import { ViewsProvider } from '../views/context/views.mjs';
25
26
  import '../views/LocationActionView/CopyView/CopyView.mjs';
26
27
  import '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
27
28
  import '../views/LocationActionView/DeleteView/DeleteView.mjs';
29
+ import '../views/LocationActionView/DownloadView/DownloadView.mjs';
28
30
  import '../views/context/actionViews.mjs';
29
31
  import '../views/LocationActionView/UploadView/UploadView.mjs';
30
32
  import '../views/LocationDetailView/LocationDetailView.mjs';
31
33
  import '../views/LocationsView/LocationsView.mjs';
32
34
 
33
- function createProvider({ actions, components, config, }) {
35
+ function createProvider({ actions, components, config, options, }) {
34
36
  const { accountId, customEndpoint, registerAuthListener, getLocationCredentials, region, listLocations, } = config;
35
37
  const resolvedActions = {
36
38
  default: {
@@ -59,6 +61,7 @@ function createProvider({ actions, components, config, }) {
59
61
  // override components
60
62
  ...components,
61
63
  };
64
+ const { validateFile = defaultValidateFile } = options ?? {};
62
65
  /**
63
66
  * Provides state, configuration and action values that are shared between
64
67
  * the primary View components
@@ -72,7 +75,7 @@ function createProvider({ actions, components, config, }) {
72
75
  React__default.createElement(ViewsProvider, { actions: resolvedActions, views: views },
73
76
  React__default.createElement(ComponentsProvider, { composables: composables },
74
77
  React__default.createElement(LocationItemsProvider, null,
75
- React__default.createElement(FilesProvider, null, children))))))))));
78
+ React__default.createElement(FileItemsProvider, { validateFile: validateFile }, children))))))))));
76
79
  }
77
80
  return Provider;
78
81
  }
@@ -20,9 +20,10 @@ import '../locationItems/context.mjs';
20
20
  import '../store/context.mjs';
21
21
  import { CreateFolderView } from '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
22
22
  import { DeleteView } from '../views/LocationActionView/DeleteView/DeleteView.mjs';
23
+ import { DownloadView } from '../views/LocationActionView/DownloadView/DownloadView.mjs';
23
24
  import { LocationActionView } from '../views/LocationActionView/LocationActionView.mjs';
24
25
  import { UploadView } from '../views/LocationActionView/UploadView/UploadView.mjs';
25
- import '../files/context.mjs';
26
+ import '../fileItems/context.mjs';
26
27
  import { LocationDetailView } from '../views/LocationDetailView/LocationDetailView.mjs';
27
28
  import { LocationsView } from '../views/LocationsView/LocationsView.mjs';
28
29
  import { useView } from '../views/useView.mjs';
@@ -61,6 +62,7 @@ function createStorageBrowser(input) {
61
62
  StorageBrowser.CopyView = CopyView;
62
63
  StorageBrowser.CreateFolderView = CreateFolderView;
63
64
  StorageBrowser.DeleteView = DeleteView;
65
+ StorageBrowser.DownloadView = DownloadView;
64
66
  StorageBrowser.UploadView = UploadView;
65
67
  StorageBrowser.Provider = Provider;
66
68
  StorageBrowser.displayName = 'StorageBrowser';
@@ -10,7 +10,7 @@ function resolveDisplayText(displayText) {
10
10
  if (!displayText)
11
11
  return DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT;
12
12
  // override
13
- const { CopyView, CreateFolderView, DeleteView, LocationDetailView, LocationsView, UploadView, } = displayText;
13
+ const { CopyView, CreateFolderView, DeleteView, DownloadView, LocationDetailView, LocationsView, UploadView, } = displayText;
14
14
  return {
15
15
  CopyView: { ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.CopyView, ...CopyView },
16
16
  CreateFolderView: {
@@ -21,6 +21,10 @@ function resolveDisplayText(displayText) {
21
21
  ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.DeleteView,
22
22
  ...DeleteView,
23
23
  },
24
+ DownloadView: {
25
+ ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.DownloadView,
26
+ ...DownloadView,
27
+ },
24
28
  LocationDetailView: {
25
29
  ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView,
26
30
  ...LocationDetailView,
@@ -4,11 +4,13 @@ import { DEFAULT_DELETE_VIEW_DISPLAY_TEXT } from './deleteView.mjs';
4
4
  import { DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT } from './locationDetailView.mjs';
5
5
  import { DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT } from './locationsView.mjs';
6
6
  import { DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT } from './uploadView.mjs';
7
+ import { DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT } from './downloadView.mjs';
7
8
 
8
9
  const DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT = {
9
10
  CopyView: DEFAULT_COPY_VIEW_DISPLAY_TEXT,
10
11
  CreateFolderView: DEFAULT_CREATE_FOLDER_VIEW_DISPLAY_TEXT,
11
12
  DeleteView: DEFAULT_DELETE_VIEW_DISPLAY_TEXT,
13
+ DownloadView: DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT,
12
14
  LocationDetailView: DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT,
13
15
  LocationsView: DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT,
14
16
  UploadView: DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT,
@@ -0,0 +1,23 @@
1
+ import { DEFAULT_ACTION_VIEW_DISPLAY_TEXT } from './shared.mjs';
2
+
3
+ const DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT = {
4
+ ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
5
+ title: 'Download',
6
+ actionStartLabel: 'Download',
7
+ getActionCompleteMessage: (data) => {
8
+ const { counts } = data ?? {};
9
+ const { COMPLETE, FAILED, TOTAL } = counts ?? {};
10
+ if (COMPLETE === TOTAL) {
11
+ return { content: 'All files downloaded.', type: 'success' };
12
+ }
13
+ if (FAILED === TOTAL) {
14
+ return { content: 'All files failed to download.', type: 'error' };
15
+ }
16
+ return {
17
+ content: `${COMPLETE} files downloaded, ${FAILED} files failed to download.`,
18
+ type: 'error',
19
+ };
20
+ },
21
+ };
22
+
23
+ export { DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT };
@@ -53,6 +53,8 @@ const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT = {
53
53
  return 'Create folder';
54
54
  case 'Upload':
55
55
  return 'Upload';
56
+ case 'Download':
57
+ return 'Download';
56
58
  default:
57
59
  return key;
58
60
  }
@@ -1,6 +1,4 @@
1
1
  import { DEFAULT_ACTION_VIEW_DISPLAY_TEXT } from './shared.mjs';
2
- import '@aws-amplify/ui';
3
- import { isFileTooBig } from '../../../validators/isFileTooBig.mjs';
4
2
 
5
3
  const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT = {
6
4
  ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
@@ -67,13 +65,12 @@ const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT = {
67
65
  if (!data?.invalidFiles) {
68
66
  return undefined;
69
67
  }
70
- const tooBigFileNames = data.invalidFiles
71
- .filter(({ file }) => isFileTooBig(file))
68
+ const invalidFileNames = data.invalidFiles
72
69
  .map(({ file }) => file.name)
73
70
  .join(', ');
74
- if (tooBigFileNames) {
71
+ if (invalidFileNames) {
75
72
  return {
76
- content: `Files larger than 160GB cannot be added to the upload queue: ${tooBigFileNames}`,
73
+ content: `Files larger than 160GB cannot be added to the upload queue: ${invalidFileNames}`,
77
74
  type: 'warning',
78
75
  };
79
76
  }
@@ -1,7 +1,9 @@
1
1
  import { DEFAULT_COPY_VIEW_DISPLAY_TEXT } from './libraries/en/copyView.mjs';
2
2
  import { DEFAULT_DELETE_VIEW_DISPLAY_TEXT } from './libraries/en/deleteView.mjs';
3
+ import { DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT } from './libraries/en/downloadView.mjs';
3
4
 
4
5
  const isCopyViewDisplayTextKey = (value) => !!DEFAULT_COPY_VIEW_DISPLAY_TEXT[value];
5
6
  const isDeleteViewDisplayTextKey = (value) => !!DEFAULT_DELETE_VIEW_DISPLAY_TEXT[value];
7
+ const isDownloadViewDisplayTextKey = (value) => !!DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT[value];
6
8
 
7
- export { isCopyViewDisplayTextKey, isDeleteViewDisplayTextKey };
9
+ export { isCopyViewDisplayTextKey, isDeleteViewDisplayTextKey, isDownloadViewDisplayTextKey };
@@ -0,0 +1,11 @@
1
+ const DEFAULT_STATE = {
2
+ validItems: undefined,
3
+ invalidItems: undefined,
4
+ };
5
+ const DEFAULT_RESOLVED_FILES = {
6
+ validFiles: undefined,
7
+ invalidFiles: undefined,
8
+ };
9
+ const UPLOAD_FILE_SIZE_LIMIT = 160 * 1000 * 1000 * 1000;
10
+
11
+ export { DEFAULT_RESOLVED_FILES, DEFAULT_STATE, UPLOAD_FILE_SIZE_LIMIT };
@@ -0,0 +1,42 @@
1
+ import React__default from 'react';
2
+ import { noop } from '@aws-amplify/ui';
3
+ import { createContextUtilities } from '@aws-amplify/ui-react-core';
4
+ import { useFileSelect } from '@aws-amplify/ui-react/internal';
5
+ import { DEFAULT_STATE } from './constants.mjs';
6
+ import { fileItemsReducer } from './fileItemsReducer.mjs';
7
+ import { resolveFiles, parseFileSelectParams } from './utils.mjs';
8
+
9
+ const defaultValue = [DEFAULT_STATE, noop];
10
+ const { FileItemsContext, useFileItems } = createContextUtilities({
11
+ contextName: 'FileItems',
12
+ defaultValue,
13
+ });
14
+ function FileItemsProvider({ children, validateFile, }) {
15
+ const [state, dispatch] = React__default.useReducer(fileItemsReducer, DEFAULT_STATE);
16
+ const [fileInput, handleFileSelect] = useFileSelect((nextFiles) => {
17
+ dispatch({
18
+ type: 'ADD_FILE_ITEMS',
19
+ ...resolveFiles(nextFiles, validateFile),
20
+ });
21
+ });
22
+ const handleFilesAction = React__default.useCallback((action) => {
23
+ if (action.type === 'SELECT_FILES') {
24
+ handleFileSelect(...parseFileSelectParams(action.selectionType));
25
+ }
26
+ else if (action.type === 'ADD_FILES') {
27
+ dispatch({
28
+ type: 'ADD_FILE_ITEMS',
29
+ ...resolveFiles(action.files, validateFile),
30
+ });
31
+ }
32
+ else {
33
+ dispatch(action);
34
+ }
35
+ }, [handleFileSelect, validateFile]);
36
+ const value = React__default.useMemo(() => [state, handleFilesAction], [state, handleFilesAction]);
37
+ return (React__default.createElement(FileItemsContext.Provider, { value: value },
38
+ fileInput,
39
+ children));
40
+ }
41
+
42
+ export { FileItemsContext, FileItemsProvider, useFileItems };
@@ -0,0 +1,33 @@
1
+ import { DEFAULT_STATE } from './constants.mjs';
2
+ import { processFileItems } from './utils.mjs';
3
+
4
+ const fileItemsReducer = (state, action) => {
5
+ switch (action.type) {
6
+ case 'ADD_FILE_ITEMS': {
7
+ if (!action.validFiles?.length && !action.invalidFiles?.length) {
8
+ return state;
9
+ }
10
+ const validItems = processFileItems(state.validItems, action.validFiles);
11
+ // `invalidItems` should only track invalid items from latest action taken
12
+ const invalidItems = processFileItems(undefined, action.invalidFiles);
13
+ return { validItems, invalidItems };
14
+ }
15
+ case 'REMOVE_FILE_ITEM': {
16
+ const { validItems: prevItems } = state;
17
+ if (!prevItems?.length)
18
+ return state;
19
+ const nextItems = prevItems.filter(({ id }) => id !== action.id);
20
+ if (nextItems.length === prevItems.length)
21
+ return state;
22
+ // `validItems` is strictly undefined if it has 0 file items
23
+ // otherwise, `validItems` is guaranteed to have at least 1+ file items
24
+ const validItems = nextItems.length ? nextItems : undefined;
25
+ return { ...state, validItems };
26
+ }
27
+ case 'RESET_FILE_ITEMS': {
28
+ return DEFAULT_STATE;
29
+ }
30
+ }
31
+ };
32
+
33
+ export { fileItemsReducer };
@@ -0,0 +1,55 @@
1
+ import { isUndefined, isString, isEmpty } from '@aws-amplify/ui';
2
+ import { UPLOAD_FILE_SIZE_LIMIT, DEFAULT_RESOLVED_FILES } from './constants.mjs';
3
+
4
+ const compareFileItems = (prev, next) => prev.key.localeCompare(next.key);
5
+ const constructFiles = (files, file) => isUndefined(files) ? [file] : files.concat(file);
6
+ const defaultValidateFile = (file) => file.size <= UPLOAD_FILE_SIZE_LIMIT;
7
+ const resolveFiles = (files, validateFile) => {
8
+ if (!files?.length)
9
+ return DEFAULT_RESOLVED_FILES;
10
+ if (!validateFile)
11
+ return { validFiles: files, invalidFiles: undefined };
12
+ return files.reduce((acc, file) => {
13
+ if (validateFile(file)) {
14
+ acc.validFiles = constructFiles(acc.validFiles, file);
15
+ }
16
+ else {
17
+ acc.invalidFiles = constructFiles(acc.invalidFiles, file);
18
+ }
19
+ return acc;
20
+ },
21
+ // create new copy of default to be modified
22
+ { ...DEFAULT_RESOLVED_FILES });
23
+ };
24
+ const processFileItems = (prevItems, files) => {
25
+ if (!files?.length)
26
+ return prevItems;
27
+ // construct `nextItems` and filter out existing `file` entries
28
+ const nextItems = files.reduce((items, file) => {
29
+ const { name, webkitRelativePath } = file;
30
+ return prevItems?.some(({ file: existing }) => existing.name === name &&
31
+ existing.webkitRelativePath === webkitRelativePath)
32
+ ? items
33
+ : items.concat({
34
+ key: isEmpty(webkitRelativePath) ? name : webkitRelativePath,
35
+ id: crypto.randomUUID(),
36
+ file,
37
+ });
38
+ }, []);
39
+ if (!nextItems.length)
40
+ return prevItems;
41
+ if (!prevItems?.length) {
42
+ return nextItems.sort(compareFileItems);
43
+ }
44
+ return prevItems?.concat(nextItems).sort(compareFileItems);
45
+ };
46
+ const parseFileSelectParams = (value) => {
47
+ if (isUndefined(value))
48
+ return ['FILE', undefined];
49
+ if (isString(value))
50
+ return [value, undefined];
51
+ const [selectType, ...rest] = value;
52
+ return [selectType, !rest?.length ? undefined : { accept: rest.join() }];
53
+ };
54
+
55
+ export { defaultValidateFile, parseFileSelectParams, processFileItems, resolveFiles };
@@ -6,12 +6,12 @@ import { isDefaultActionViewType } from '../actions/configs/defaults.mjs';
6
6
 
7
7
  const resolveHandler = (value) => (isFunction(value) ? value : value.handler);
8
8
  const getActionHandlers = (configs) => {
9
- const { copy: copyConfig, createFolder: createFolderConfig, delete: deleteConfig, download, upload: uploadConfig, listLocationItems, listLocations, } = configs.default;
9
+ const { copy: copyConfig, createFolder: createFolderConfig, delete: deleteConfig, download: downloadConfig, upload: uploadConfig, listLocationItems, listLocations, } = configs.default;
10
10
  const defaultHandlers = {
11
11
  copy: copyConfig.handler,
12
12
  createFolder: createFolderConfig.handler,
13
13
  delete: deleteConfig.handler,
14
- download,
14
+ download: 'handler' in downloadConfig ? downloadConfig.handler : downloadConfig,
15
15
  listLocationItems,
16
16
  listLocations,
17
17
  upload: uploadConfig.handler,
@@ -9,7 +9,8 @@ import '@aws-amplify/ui-react-core';
9
9
  import '@aws-amplify/ui-react-core/elements';
10
10
  import { useDisplayText } from '../../../displayText/context.mjs';
11
11
  import useResolveTableData from '../../hooks/useResolveTableData/useResolveTableData.mjs';
12
- import { COPY_TABLE_RESOLVERS, COPY_TABLE_KEYS } from '../../utils/tableResolvers/copyResolvers.mjs';
12
+ import { COPY_TABLE_RESOLVERS } from '../../utils/tableResolvers/copyResolvers.mjs';
13
+ import { FILE_DATA_ITEM_TABLE_KEYS } from '../../utils/tableResolvers/constants.mjs';
13
14
  import { FoldersMessageProvider } from './FoldersMessageControl.mjs';
14
15
  import { FoldersPaginationProvider } from './FoldersPaginationControl.mjs';
15
16
  import { FoldersTableProvider } from './FoldersTableControl.mjs';
@@ -19,7 +20,7 @@ function CopyViewProvider({ children, ...props }) {
19
20
  const { actionCancelLabel, actionDestinationLabel, actionExitLabel, actionStartLabel, getActionCompleteMessage, overwriteWarningMessage, searchPlaceholder, searchSubmitLabel, searchClearLabel, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, title, } = displayText;
20
21
  const { destination, folders, isProcessing, isProcessingComplete, statusCounts, tasks: items, onActionCancel, onActionExit, onActionStart, onSelectDestination, onTaskRemove, } = props;
21
22
  const { hasNextPage, highestPageVisited, hasError: hasFoldersError, message: foldersErrorMessage, query, hasExhaustedSearch, isLoading, page, pageItems, onPaginate, onQuery, onSearchClear, onSearch, onSelectFolder, } = folders;
22
- const tableData = useResolveTableData(COPY_TABLE_KEYS, COPY_TABLE_RESOLVERS, {
23
+ const tableData = useResolveTableData(FILE_DATA_ITEM_TABLE_KEYS, COPY_TABLE_RESOLVERS, {
23
24
  items,
24
25
  props: { displayText, isProcessing, onTaskRemove },
25
26
  });
@@ -1,7 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { ControlsContextProvider } from '../../../controls/context.mjs';
3
3
  import { useDisplayText } from '../../../displayText/context.mjs';
4
- import '@aws-amplify/ui';
5
4
  import { isValidFolderName } from './utils.mjs';
6
5
 
7
6
  function CreateFolderViewProvider({ children, ...props }) {
@@ -1,9 +1,10 @@
1
1
  import React__default from 'react';
2
2
  import { ControlsContextProvider } from '../../../controls/context.mjs';
3
3
  import { useDisplayText } from '../../../displayText/context.mjs';
4
- import '@aws-amplify/ui';
5
4
  import useResolveTableData from '../../hooks/useResolveTableData/useResolveTableData.mjs';
6
- import { DELETE_TABLE_RESOLVERS, DELETE_TABLE_KEYS } from '../../utils/tableResolvers/deleteResolvers.mjs';
5
+ import '@aws-amplify/ui';
6
+ import { FILE_DATA_ITEM_TABLE_KEYS } from '../../utils/tableResolvers/constants.mjs';
7
+ import { DELETE_TABLE_RESOLVERS } from '../../utils/tableResolvers/deleteResolvers.mjs';
7
8
 
8
9
  function DeleteViewProvider({ children, ...props }) {
9
10
  const { DeleteView: displayText } = useDisplayText();
@@ -12,7 +13,7 @@ function DeleteViewProvider({ children, ...props }) {
12
13
  const message = isProcessingComplete
13
14
  ? getActionCompleteMessage({ counts: statusCounts })
14
15
  : undefined;
15
- const tableData = useResolveTableData(DELETE_TABLE_KEYS, DELETE_TABLE_RESOLVERS, {
16
+ const tableData = useResolveTableData(FILE_DATA_ITEM_TABLE_KEYS, DELETE_TABLE_RESOLVERS, {
16
17
  items,
17
18
  props: { displayText, isProcessing, onTaskRemove },
18
19
  });
@@ -0,0 +1,47 @@
1
+ import React__default from 'react';
2
+ import '@aws-amplify/ui-react';
3
+ import { ViewElement } from '../../../components/elements/definitions.mjs';
4
+ import '../../../components/elements/IconElement.mjs';
5
+ import { ActionCancelControl } from '../../../controls/ActionCancelControl.mjs';
6
+ import { ActionExitControl } from '../../../controls/ActionExitControl.mjs';
7
+ import { ActionStartControl } from '../../../controls/ActionStartControl.mjs';
8
+ import { DataTableControl } from '../../../controls/DataTableControl.mjs';
9
+ import { MessageControl } from '../../../controls/MessageControl.mjs';
10
+ import { StatusDisplayControl } from '../../../controls/StatusDisplayControl.mjs';
11
+ import { TitleControl } from '../../../controls/TitleControl.mjs';
12
+ import { classNames } from '@aws-amplify/ui';
13
+ import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
14
+ import '../../../components/composables/context.mjs';
15
+ import '@aws-amplify/ui-react-core';
16
+ import '@aws-amplify/ui-react-core/elements';
17
+ import { DownloadViewProvider } from './DownloadViewProvider.mjs';
18
+ import { useDownloadView } from './useDownloadView.mjs';
19
+
20
+ const DownloadView = ({ className, ...props }) => {
21
+ const state = useDownloadView(props);
22
+ return (React__default.createElement(ViewElement, { className: classNames(STORAGE_BROWSER_BLOCK, className) },
23
+ React__default.createElement(DownloadViewProvider, { ...state },
24
+ React__default.createElement(ActionExitControl, null),
25
+ React__default.createElement(TitleControl, null),
26
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__data-table` },
27
+ React__default.createElement(DataTableControl, null)),
28
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__summary` },
29
+ React__default.createElement(StatusDisplayControl, null)),
30
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__footer` },
31
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__message` },
32
+ React__default.createElement(MessageControl, null)),
33
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__buttons` },
34
+ React__default.createElement(ActionCancelControl, null),
35
+ React__default.createElement(ActionStartControl, null))))));
36
+ };
37
+ DownloadView.displayName = 'DownloadView';
38
+ DownloadView.Provider = DownloadViewProvider;
39
+ DownloadView.Cancel = ActionCancelControl;
40
+ DownloadView.Exit = ActionExitControl;
41
+ DownloadView.Message = MessageControl;
42
+ DownloadView.Start = ActionStartControl;
43
+ DownloadView.Statuses = StatusDisplayControl;
44
+ DownloadView.TasksTable = DataTableControl;
45
+ DownloadView.Title = TitleControl;
46
+
47
+ export { DownloadView };
@@ -0,0 +1,38 @@
1
+ import React__default from 'react';
2
+ import { ControlsContextProvider } from '../../../controls/context.mjs';
3
+ import { useDisplayText } from '../../../displayText/context.mjs';
4
+ import useResolveTableData from '../../hooks/useResolveTableData/useResolveTableData.mjs';
5
+ import '@aws-amplify/ui';
6
+ import { FILE_DATA_ITEM_TABLE_KEYS } from '../../utils/tableResolvers/constants.mjs';
7
+ import { DOWNLOAD_TABLE_RESOLVERS } from '../../utils/tableResolvers/downloadResolvers.mjs';
8
+
9
+ function DownloadViewProvider({ children, ...props }) {
10
+ const { DownloadView: displayText } = useDisplayText();
11
+ const { actionCancelLabel, actionExitLabel, actionStartLabel, title, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, getActionCompleteMessage, } = displayText;
12
+ const { isProcessing, isProcessingComplete, statusCounts, tasks: items, onActionCancel, onActionStart, onActionExit, onTaskRemove, } = props;
13
+ const message = isProcessingComplete
14
+ ? getActionCompleteMessage({ counts: statusCounts })
15
+ : undefined;
16
+ const tableData = useResolveTableData(FILE_DATA_ITEM_TABLE_KEYS, DOWNLOAD_TABLE_RESOLVERS, {
17
+ items,
18
+ props: { displayText, isProcessing, onTaskRemove },
19
+ });
20
+ return (React__default.createElement(ControlsContextProvider, { data: {
21
+ actionCancelLabel,
22
+ actionExitLabel,
23
+ actionStartLabel,
24
+ isActionCancelDisabled: !isProcessing || isProcessingComplete,
25
+ isActionExitDisabled: isProcessing,
26
+ isActionStartDisabled: isProcessing || isProcessingComplete,
27
+ statusDisplayCanceledLabel,
28
+ statusDisplayCompletedLabel,
29
+ statusDisplayFailedLabel,
30
+ statusDisplayQueuedLabel,
31
+ statusCounts,
32
+ tableData,
33
+ title,
34
+ message,
35
+ }, onActionStart: onActionStart, onActionExit: onActionExit, onActionCancel: onActionCancel }, children));
36
+ }
37
+
38
+ export { DownloadViewProvider };
@@ -0,0 +1,66 @@
1
+ import React__default from 'react';
2
+ import { isFunction } from '@aws-amplify/ui';
3
+ import { useLocationItems } from '../../../locationItems/context.mjs';
4
+ import { useStore } from '../../../store/context.mjs';
5
+ import '../../../useAction/context.mjs';
6
+ import { useAction } from '../../../useAction/useAction.mjs';
7
+ import '@aws-amplify/ui-react-core';
8
+ import '@aws-amplify/ui-react-core/elements';
9
+ import '../../../credentials/context.mjs';
10
+ import '@aws-amplify/storage/internals';
11
+ import '../../../configuration/context.mjs';
12
+ import 'aws-amplify/storage';
13
+ import '../../../actions/configs/context.mjs';
14
+ import '../../../actions/configs/defaults.mjs';
15
+
16
+ // assign to constant to ensure referential equality
17
+ const EMPTY_ITEMS = [];
18
+ const useDownloadView = (options) => {
19
+ const { onExit: _onExit } = options ?? {};
20
+ const [{ location }, storeDispatch] = useStore();
21
+ const [locationItems, locationItemsDispatch] = useLocationItems();
22
+ const { current } = location;
23
+ const { fileDataItems: items = EMPTY_ITEMS } = locationItems;
24
+ const [processState, handleProcess] = useAction('download', {
25
+ items,
26
+ });
27
+ const { isProcessing, isProcessingComplete, statusCounts, tasks } = processState;
28
+ const onActionStart = () => {
29
+ if (!current)
30
+ return;
31
+ handleProcess();
32
+ };
33
+ const onActionCancel = () => {
34
+ tasks.forEach((task) => {
35
+ // Calling cancel on task works only on queued tasks.
36
+ // In case of download, all download presigned url open at once
37
+ // When certain threshold is reached for queuing inside StorageBrowser, cancel might be possible.
38
+ if (isFunction(task.cancel))
39
+ task.cancel();
40
+ });
41
+ };
42
+ const onActionExit = () => {
43
+ // clear files state
44
+ locationItemsDispatch({ type: 'RESET_LOCATION_ITEMS' });
45
+ // clear selected action
46
+ storeDispatch({ type: 'RESET_ACTION_TYPE' });
47
+ if (isFunction(_onExit))
48
+ _onExit(current);
49
+ };
50
+ const onTaskRemove = React__default.useCallback(({ data }) => {
51
+ locationItemsDispatch({ type: 'REMOVE_LOCATION_ITEM', id: data.id });
52
+ }, [locationItemsDispatch]);
53
+ return {
54
+ isProcessing,
55
+ isProcessingComplete,
56
+ location,
57
+ statusCounts,
58
+ tasks,
59
+ onActionCancel,
60
+ onActionExit,
61
+ onActionStart,
62
+ onTaskRemove,
63
+ };
64
+ };
65
+
66
+ export { useDownloadView };
@@ -18,6 +18,7 @@ import { DataTableControl } from '../../../controls/DataTableControl.mjs';
18
18
  import { DropZoneControl } from '../../../controls/DropZoneControl.mjs';
19
19
  import { MessageControl } from '../../../controls/MessageControl.mjs';
20
20
  import { OverwriteToggleControl } from '../../../controls/OverwriteToggleControl.mjs';
21
+ import { PaginationControl } from '../../../controls/PaginationControl.mjs';
21
22
  import { StatusDisplayControl } from '../../../controls/StatusDisplayControl.mjs';
22
23
  import { TitleControl } from '../../../controls/TitleControl.mjs';
23
24
  import { UploadViewProvider } from './UploadViewProvider.mjs';
@@ -32,6 +33,7 @@ const UploadView = ({ className, ...props }) => {
32
33
  React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__controls` },
33
34
  React__default.createElement(OverwriteToggleControl, null),
34
35
  React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__buttons` },
36
+ React__default.createElement(PaginationControl, null),
35
37
  React__default.createElement(AddFolderControl, null),
36
38
  React__default.createElement(AddFilesControl, null))),
37
39
  React__default.createElement(DropZoneControl, null,
@@ -51,6 +53,7 @@ UploadView.displayName = 'UploadView';
51
53
  UploadView.Provider = UploadViewProvider;
52
54
  UploadView.AddFiles = AddFilesControl;
53
55
  UploadView.AddFolder = AddFolderControl;
56
+ UploadView.Pagination = PaginationControl;
54
57
  UploadView.Cancel = ActionCancelControl;
55
58
  UploadView.Destination = ActionDestinationControl;
56
59
  UploadView.DropZone = DropZoneControl;