@aws-amplify/ui-react-storage 3.15.0 → 3.17.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 (101) hide show
  1. package/dist/browser.js +1 -1
  2. package/dist/{createStorageBrowser-CG-6mXiT.js → createStorageBrowser-De4hcP-u.js} +710 -158
  3. package/dist/esm/browser.mjs +1 -0
  4. package/dist/esm/components/StorageBrowser/ErrorBoundary/ErrorBoundary.mjs +1 -4
  5. package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +13 -3
  6. package/dist/esm/components/StorageBrowser/actions/handlers/delete.mjs +39 -8
  7. package/dist/esm/components/StorageBrowser/components/ComponentsProvider.mjs +1 -4
  8. package/dist/esm/components/StorageBrowser/components/base/preview/DownloadButton.mjs +1 -4
  9. package/dist/esm/components/StorageBrowser/components/composables/ActionConfirmationModal.mjs +34 -0
  10. package/dist/esm/components/StorageBrowser/components/composables/defaults.mjs +2 -0
  11. package/dist/esm/components/StorageBrowser/components/elements/definitions.mjs +2 -2
  12. package/dist/esm/components/StorageBrowser/configuration/paginationContext.mjs +15 -0
  13. package/dist/esm/components/StorageBrowser/controls/ActionConfirmationModalControl.mjs +12 -0
  14. package/dist/esm/components/StorageBrowser/controls/DataTableControl.mjs +1 -4
  15. package/dist/esm/components/StorageBrowser/controls/hooks/useActionConfirmationModal.mjs +17 -0
  16. package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +9 -4
  17. package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +11 -9
  18. package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +10 -5
  19. package/dist/esm/components/StorageBrowser/displayText/libraries/en/deleteView.mjs +117 -5
  20. package/dist/esm/components/StorageBrowser/displayText/libraries/en/locationDetailView.mjs +1 -0
  21. package/dist/esm/components/StorageBrowser/displayText/libraries/en/shared.mjs +1 -0
  22. package/dist/esm/components/StorageBrowser/locationItems/context.mjs +17 -14
  23. package/dist/esm/components/StorageBrowser/locationItems/utils.mjs +38 -0
  24. package/dist/esm/components/StorageBrowser/store/validateStoreProps.mjs +1 -1
  25. package/dist/esm/components/StorageBrowser/tasks/useProcessTasks.mjs +7 -4
  26. package/dist/esm/components/StorageBrowser/useAction/useHandler.mjs +1 -0
  27. package/dist/esm/components/StorageBrowser/useAction/useListFolderItems.mjs +1 -0
  28. package/dist/esm/components/StorageBrowser/useAction/useListLocationItems.mjs +1 -0
  29. package/dist/esm/components/StorageBrowser/useAction/utils.mjs +0 -5
  30. package/dist/esm/components/StorageBrowser/utils/validatePageSize.mjs +12 -0
  31. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyView.mjs +1 -4
  32. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +5 -4
  33. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/FoldersMessageControl.mjs +1 -4
  34. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useCopyView.mjs +1 -4
  35. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useFolders.mjs +1 -4
  36. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/CreateFolderView.mjs +1 -4
  37. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/useCreateFolderView.mjs +1 -4
  38. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteView.mjs +6 -6
  39. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteViewProvider.mjs +7 -6
  40. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/useDeleteView.mjs +70 -7
  41. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/utils.mjs +87 -0
  42. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +1 -4
  43. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.mjs +9 -0
  44. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs +1 -4
  45. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +3 -6
  46. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +3 -0
  47. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +11 -12
  48. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailView.mjs +1 -4
  49. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailViewProvider.mjs +2 -1
  50. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFolderRowContent.mjs +38 -27
  51. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.mjs +8 -1
  52. package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +24 -20
  53. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsView.mjs +1 -4
  54. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsViewProvider.mjs +1 -4
  55. package/dist/esm/components/StorageBrowser/views/LocationsView/useLocationsView.mjs +13 -10
  56. package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +12 -8
  57. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +9 -4
  58. package/dist/esm/components/StorageBrowser/views/hooks/usePaginate.mjs +18 -7
  59. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/constants.mjs +10 -1
  60. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.mjs +123 -13
  61. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/utils.mjs +3 -3
  62. package/dist/esm/version.mjs +1 -1
  63. package/dist/index.js +1 -1
  64. package/dist/styles.css +83 -1
  65. package/dist/types/components/StorageBrowser/StorageBrowserAmplify.d.ts +3 -1
  66. package/dist/types/components/StorageBrowser/actions/handlers/delete.d.ts +5 -3
  67. package/dist/types/components/StorageBrowser/actions/handlers/types.d.ts +15 -1
  68. package/dist/types/components/StorageBrowser/components/composables/ActionConfirmationModal.d.ts +12 -0
  69. package/dist/types/components/StorageBrowser/components/composables/types.d.ts +2 -0
  70. package/dist/types/components/StorageBrowser/configuration/index.d.ts +2 -0
  71. package/dist/types/components/StorageBrowser/configuration/paginationContext.d.ts +12 -0
  72. package/dist/types/components/StorageBrowser/controls/ActionConfirmationModalControl.d.ts +2 -0
  73. package/dist/types/components/StorageBrowser/controls/hooks/useActionConfirmationModal.d.ts +2 -0
  74. package/dist/types/components/StorageBrowser/controls/index.d.ts +1 -0
  75. package/dist/types/components/StorageBrowser/controls/types.d.ts +4 -0
  76. package/dist/types/components/StorageBrowser/createStorageBrowser/types.d.ts +7 -1
  77. package/dist/types/components/StorageBrowser/displayText/types.d.ts +7 -0
  78. package/dist/types/components/StorageBrowser/locationItems/context.d.ts +12 -3
  79. package/dist/types/components/StorageBrowser/locationItems/index.d.ts +1 -0
  80. package/dist/types/components/StorageBrowser/locationItems/utils.d.ts +27 -0
  81. package/dist/types/components/StorageBrowser/store/types.d.ts +7 -0
  82. package/dist/types/components/StorageBrowser/tasks/types.d.ts +7 -2
  83. package/dist/types/components/StorageBrowser/utils/index.d.ts +1 -0
  84. package/dist/types/components/StorageBrowser/utils/validatePageSize.d.ts +1 -0
  85. package/dist/types/components/StorageBrowser/views/LocationActionView/DeleteView/types.d.ts +5 -0
  86. package/dist/types/components/StorageBrowser/views/LocationActionView/DeleteView/utils.d.ts +26 -0
  87. package/dist/types/components/StorageBrowser/views/LocationActionView/UploadView/types.d.ts +7 -0
  88. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFolderRowContent.d.ts +4 -1
  89. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.d.ts +3 -2
  90. package/dist/types/components/StorageBrowser/views/LocationDetailView/types.d.ts +10 -3
  91. package/dist/types/components/StorageBrowser/views/LocationsView/types.d.ts +2 -2
  92. package/dist/types/components/StorageBrowser/views/hooks/usePaginate.d.ts +1 -1
  93. package/dist/types/components/StorageBrowser/views/types.d.ts +6 -0
  94. package/dist/types/components/StorageBrowser/views/utils/index.d.ts +1 -1
  95. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/constants.d.ts +1 -0
  96. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.d.ts +5 -2
  97. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/index.d.ts +1 -1
  98. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/types.d.ts +4 -0
  99. package/dist/types/index.d.ts +1 -1
  100. package/dist/types/version.d.ts +1 -1
  101. package/package.json +7 -7
@@ -18,6 +18,7 @@ import './components/StorageBrowser/useAction/context.mjs';
18
18
  import '@aws-amplify/ui-react-core/elements';
19
19
  import './components/StorageBrowser/credentials/context.mjs';
20
20
  import './components/StorageBrowser/configuration/context.mjs';
21
+ import './components/StorageBrowser/configuration/paginationContext.mjs';
21
22
  import './components/StorageBrowser/displayText/context.mjs';
22
23
  export { DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT as DefaultStorageBrowserDisplayText } from './components/StorageBrowser/displayText/libraries/en/default.mjs';
23
24
  import './components/StorageBrowser/filePreview/context.mjs';
@@ -11,10 +11,7 @@ import '@aws-amplify/ui-react-core/elements';
11
11
  import '../credentials/context.mjs';
12
12
  import '@aws-amplify/storage/internals';
13
13
  import '../configuration/context.mjs';
14
- import 'aws-amplify';
15
- import 'jszip';
16
- import 'aws-amplify/storage';
17
- import '../actions/configs/context.mjs';
14
+ import '../configuration/paginationContext.mjs';
18
15
  import '../actions/configs/defaults.mjs';
19
16
  import '../displayText/context.mjs';
20
17
  import '../filePreview/context.mjs';
@@ -1,3 +1,4 @@
1
+ import { hasSelectedFolders } from '../../locationItems/utils.mjs';
1
2
  import '@aws-amplify/storage/internals';
2
3
  import 'aws-amplify';
3
4
  import '@aws-amplify/ui';
@@ -8,7 +9,10 @@ import 'aws-amplify/storage';
8
9
  const copyActionConfig = {
9
10
  viewName: 'CopyView',
10
11
  actionListItem: {
11
- disable: (selected) => !selected || selected.length === 0,
12
+ disable: (selected) => {
13
+ const hasNoSelection = !selected || selected.length === 0;
14
+ return hasNoSelection || hasSelectedFolders(selected);
15
+ },
12
16
  hide: (permissions) => !permissions.includes('write'),
13
17
  icon: 'copy-file',
14
18
  label: 'Copy',
@@ -18,7 +22,10 @@ const copyActionConfig = {
18
22
  const deleteActionConfig = {
19
23
  viewName: 'DeleteView',
20
24
  actionListItem: {
21
- disable: (selected) => !selected || selected.length === 0,
25
+ disable: (selected) => {
26
+ const hasNoSelection = !selected || selected.length === 0;
27
+ return hasNoSelection;
28
+ },
22
29
  hide: (permissions) => !permissions.includes('delete'),
23
30
  icon: 'delete-file',
24
31
  label: 'Delete',
@@ -46,7 +53,10 @@ const uploadActionConfig = {
46
53
  const downloadActionConfig = {
47
54
  viewName: 'DownloadView',
48
55
  actionListItem: {
49
- disable: (selected) => !selected || selected.length === 0,
56
+ disable: (selected) => {
57
+ const hasNoSelection = !selected || selected.length === 0;
58
+ return hasNoSelection || hasSelectedFolders(selected);
59
+ },
50
60
  hide: (permissions) => !permissions.includes('get'),
51
61
  icon: 'download',
52
62
  label: 'Download',
@@ -1,27 +1,58 @@
1
1
  import { remove } from '@aws-amplify/storage/internals';
2
2
  import { constructBucket } from './utils.mjs';
3
3
 
4
- const deleteHandler = ({ config, data, }) => {
4
+ const deleteHandler = ({ config, data, options, }) => {
5
5
  const { key } = data;
6
6
  const { accountId, credentials, customEndpoint } = config;
7
- const result = remove({
7
+ const { onProgress } = options ?? {};
8
+ let cumulativeSuccessCount = 0;
9
+ let cumulativeFailureCount = 0;
10
+ let operationCancel = () => {
11
+ // noop
12
+ };
13
+ const cancel = () => {
14
+ operationCancel?.();
15
+ };
16
+ const operation = remove({
8
17
  path: key,
9
18
  options: {
10
19
  bucket: constructBucket(config),
11
20
  locationCredentialsProvider: credentials,
12
21
  expectedBucketOwner: accountId,
13
22
  customEndpoint,
23
+ onProgress: (progress) => {
24
+ if (!progress) {
25
+ return;
26
+ }
27
+ const batchSuccessCount = progress?.deleted?.length ?? 0;
28
+ const batchFailureCount = progress?.failed?.length ?? 0;
29
+ cumulativeSuccessCount += batchSuccessCount;
30
+ cumulativeFailureCount += batchFailureCount;
31
+ onProgress?.(data, {
32
+ successCount: cumulativeSuccessCount,
33
+ failureCount: cumulativeFailureCount,
34
+ });
35
+ },
14
36
  },
37
+ });
38
+ operationCancel = operation?.cancel ? operation?.cancel : () => { };
39
+ const operationPromise = operation?.result ?? operation;
40
+ const result = operationPromise
41
+ ?.then?.(({ path }) => {
42
+ return {
43
+ status: 'COMPLETE',
44
+ value: {
45
+ key: path,
46
+ successCount: cumulativeSuccessCount,
47
+ failureCount: cumulativeFailureCount,
48
+ },
49
+ };
15
50
  })
16
- .then(({ path }) => ({
17
- status: 'COMPLETE',
18
- value: { key: path },
19
- }))
20
- .catch((error) => {
51
+ ?.catch?.((error) => {
21
52
  const { message } = error;
22
53
  return { error, message, status: 'FAILED' };
23
54
  });
24
- return { result };
55
+ return { result, cancel };
25
56
  };
26
57
 
27
58
  export { deleteHandler };
@@ -11,10 +11,7 @@ import '../useAction/context.mjs';
11
11
  import '../credentials/context.mjs';
12
12
  import '@aws-amplify/storage/internals';
13
13
  import '../configuration/context.mjs';
14
- import 'aws-amplify';
15
- import 'jszip';
16
- import 'aws-amplify/storage';
17
- import '../actions/configs/context.mjs';
14
+ import '../configuration/paginationContext.mjs';
18
15
  import '../actions/configs/defaults.mjs';
19
16
  import '../displayText/context.mjs';
20
17
  import '../filePreview/context.mjs';
@@ -11,11 +11,8 @@ import '@aws-amplify/ui-react-core/elements';
11
11
  import '../../../credentials/context.mjs';
12
12
  import '@aws-amplify/storage/internals';
13
13
  import '../../../configuration/context.mjs';
14
+ import '../../../configuration/paginationContext.mjs';
14
15
  import '@aws-amplify/ui';
15
- import 'aws-amplify';
16
- import 'jszip';
17
- import 'aws-amplify/storage';
18
- import '../../../actions/configs/context.mjs';
19
16
  import '../../../actions/configs/defaults.mjs';
20
17
  import { useDisplayText } from '../../../displayText/context.mjs';
21
18
 
@@ -0,0 +1,34 @@
1
+ import React__default from 'react';
2
+ import '@aws-amplify/ui-react';
3
+ import { ViewElement, HeadingElement, TextElement, ButtonElement } from '../elements/definitions.mjs';
4
+ import '../elements/IconElement.mjs';
5
+
6
+ const ActionConfirmationModal = ({ isOpen = false, title, message, content, onConfirm, onCancel, confirmLabel, cancelLabel, }) => {
7
+ const modalRef = React__default.useRef(null);
8
+ React__default.useEffect(() => {
9
+ if (isOpen && modalRef.current) {
10
+ modalRef.current.focus();
11
+ }
12
+ }, [isOpen]);
13
+ const handleKeyDown = (event) => {
14
+ if (event.key === 'Escape') {
15
+ onCancel?.();
16
+ }
17
+ };
18
+ if (!isOpen)
19
+ return null;
20
+ return (React__default.createElement("div", { ref: modalRef, className: "amplify-modal__overlay", role: "dialog", "aria-modal": "true", tabIndex: -1, onKeyDown: handleKeyDown, onClick: (e) => {
21
+ if (e.target === e.currentTarget) {
22
+ onCancel?.();
23
+ }
24
+ } },
25
+ React__default.createElement(ViewElement, { className: "amplify-modal__content", role: "document" },
26
+ React__default.createElement(HeadingElement, { className: "amplify-modal__title" }, title),
27
+ message && (React__default.createElement(TextElement, { className: "amplify-modal__body" }, message)),
28
+ content && (React__default.createElement(ViewElement, { className: "amplify-modal__body" }, content)),
29
+ React__default.createElement(ViewElement, { className: "amplify-modal__footer" },
30
+ React__default.createElement(ButtonElement, { className: "amplify-modal__cancel", onClick: onCancel, variant: "cancel" }, cancelLabel),
31
+ React__default.createElement(ButtonElement, { className: "amplify-modal__confirm", onClick: onConfirm, variant: "primary" }, confirmLabel)))));
32
+ };
33
+
34
+ export { ActionConfirmationModal };
@@ -1,4 +1,5 @@
1
1
  import { ActionCancel } from './ActionCancel.mjs';
2
+ import { ActionConfirmationModal } from './ActionConfirmationModal.mjs';
2
3
  import { ActionDestination } from './ActionDestination.mjs';
3
4
  import { ActionExit } from './ActionExit.mjs';
4
5
  import { ActionStart } from './ActionStart.mjs';
@@ -22,6 +23,7 @@ import { Title } from './Title.mjs';
22
23
 
23
24
  const DEFAULT_COMPOSABLES = {
24
25
  ActionCancel,
26
+ ActionConfirmationModal,
25
27
  ActionDestination,
26
28
  ActionExit,
27
29
  ActionStart,
@@ -29,7 +29,7 @@ const OrderedListElement = defineBaseElement({
29
29
  type: 'ol',
30
30
  displayName: 'OrderedList',
31
31
  });
32
- defineBaseElement({
32
+ const UnorderedListElement = defineBaseElement({
33
33
  type: 'ul',
34
34
  displayName: 'UnorderedList',
35
35
  });
@@ -83,4 +83,4 @@ const SpanElement = defineBaseElement({
83
83
  displayName: 'Span',
84
84
  });
85
85
 
86
- export { ButtonElement, DescriptionDetailsElement, DescriptionListElement, DescriptionTermElement, HeadingElement, InputElement, LabelElement, ListItemElement, NavElement, OrderedListElement, SpanElement, TableBodyElement, TableDataCellElement, TableElement, TableHeadElement, TableHeaderElement, TableRowElement, TextElement, ViewElement };
86
+ export { ButtonElement, DescriptionDetailsElement, DescriptionListElement, DescriptionTermElement, HeadingElement, InputElement, LabelElement, ListItemElement, NavElement, OrderedListElement, SpanElement, TableBodyElement, TableDataCellElement, TableElement, TableHeadElement, TableHeaderElement, TableRowElement, TextElement, UnorderedListElement, ViewElement };
@@ -0,0 +1,15 @@
1
+ import React__default from 'react';
2
+ import { createContextUtilities } from '@aws-amplify/ui-react-core';
3
+ import { validatePageSize } from '../utils/validatePageSize.mjs';
4
+
5
+ const ERROR_MESSAGE = '`usePaginationConfig` must be called from within a `PaginationConfigProvider`.';
6
+ const { usePaginationConfig, PaginationConfigContext } = createContextUtilities({
7
+ contextName: 'PaginationConfig',
8
+ errorMessage: ERROR_MESSAGE,
9
+ });
10
+ function PaginationConfigProvider({ children, pageSize, }) {
11
+ const value = React__default.useMemo(() => ({ pageSize: validatePageSize(pageSize) }), [pageSize]);
12
+ return (React__default.createElement(PaginationConfigContext.Provider, { value: value }, children));
13
+ }
14
+
15
+ export { PaginationConfigContext, PaginationConfigProvider, usePaginationConfig };
@@ -0,0 +1,12 @@
1
+ import React__default from 'react';
2
+ import { ActionConfirmationModal } from '../components/composables/ActionConfirmationModal.mjs';
3
+ import { useResolvedComposable } from './hooks/useResolvedComposable.mjs';
4
+ import { useActionConfirmationModal } from './hooks/useActionConfirmationModal.mjs';
5
+
6
+ const ActionConfirmationModalControl = () => {
7
+ const props = useActionConfirmationModal();
8
+ const Resolved = useResolvedComposable(ActionConfirmationModal, 'ActionConfirmationModal');
9
+ return React__default.createElement(Resolved, { ...props });
10
+ };
11
+
12
+ export { ActionConfirmationModalControl };
@@ -11,10 +11,7 @@ import '@aws-amplify/ui-react-core/elements';
11
11
  import '../credentials/context.mjs';
12
12
  import '@aws-amplify/storage/internals';
13
13
  import '../configuration/context.mjs';
14
- import 'aws-amplify';
15
- import 'jszip';
16
- import 'aws-amplify/storage';
17
- import '../actions/configs/context.mjs';
14
+ import '../configuration/paginationContext.mjs';
18
15
  import '../actions/configs/defaults.mjs';
19
16
  import '../displayText/context.mjs';
20
17
  import '../filePreview/context.mjs';
@@ -0,0 +1,17 @@
1
+ import { useControlsContext } from '../context.mjs';
2
+
3
+ const useActionConfirmationModal = () => {
4
+ const { data: { confirmationModal = {} }, onConfirmationModalConfirm = () => { }, onConfirmationModalCancel = () => { }, } = useControlsContext();
5
+ return {
6
+ isOpen: false,
7
+ title: 'Confirm Action',
8
+ message: '',
9
+ confirmLabel: 'Confirm',
10
+ cancelLabel: 'Cancel',
11
+ ...confirmationModal,
12
+ onConfirm: onConfirmationModalConfirm,
13
+ onCancel: onConfirmationModalCancel,
14
+ };
15
+ };
16
+
17
+ export { useActionConfirmationModal };
@@ -9,19 +9,24 @@ import '@aws-amplify/ui-react-core/elements';
9
9
  import '../credentials/context.mjs';
10
10
  import '@aws-amplify/storage/internals';
11
11
  import '../configuration/context.mjs';
12
+ import '../configuration/paginationContext.mjs';
12
13
  import '@aws-amplify/ui-react-core';
13
- import 'aws-amplify';
14
- import 'jszip';
15
- import 'aws-amplify/storage';
16
- import '../actions/configs/context.mjs';
17
14
  import '../actions/configs/defaults.mjs';
18
15
  import '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
19
16
  import '../views/LocationActionView/DeleteView/DeleteView.mjs';
17
+ import '../displayText/context.mjs';
18
+ import '@aws-amplify/ui-react';
19
+ import '../components/elements/definitions.mjs';
20
+ import '../components/elements/IconElement.mjs';
21
+ import 'aws-amplify';
22
+ import 'jszip';
23
+ import 'aws-amplify/storage';
20
24
  import '../views/LocationActionView/DownloadView/DownloadView.mjs';
21
25
  import '../views/context/actionViews.mjs';
22
26
  import '../views/LocationActionView/UploadView/UploadView.mjs';
23
27
  import '../fileItems/context.mjs';
24
28
  import '../views/LocationDetailView/LocationDetailView.mjs';
29
+ import '../actions/configs/context.mjs';
25
30
  import '../filePreview/context.mjs';
26
31
  import '../views/LocationsView/LocationsView.mjs';
27
32
 
@@ -16,6 +16,7 @@ import { ComponentsProvider } from '../components/ComponentsProvider.mjs';
16
16
  import { componentsDefault } from '../components/defaults.mjs';
17
17
  import { createConfigurationProvider } from '../configuration/createConfigurationProvider.mjs';
18
18
  import '../configuration/context.mjs';
19
+ import { PaginationConfigProvider } from '../configuration/paginationContext.mjs';
19
20
  import { DisplayTextProvider } from '../displayText/context.mjs';
20
21
  import { FileItemsProvider } from '../fileItems/context.mjs';
21
22
  import { defaultValidateFile } from '../fileItems/utils.mjs';
@@ -69,17 +70,18 @@ function createProvider({ actions, components, config, options, filePreview = {}
69
70
  * Provides state, configuration and action values that are shared between
70
71
  * the primary View components
71
72
  */
72
- function Provider({ children, displayText, views, ...props }) {
73
+ function Provider({ children, displayText, views, pageSize, ...props }) {
73
74
  return (React__default.createElement(StoreProvider, { ...props },
74
75
  React__default.createElement(ConfigurationProvider, null,
75
- React__default.createElement(ActionConfigsProvider, { actionConfigs: actionConfigs },
76
- React__default.createElement(ActionHandlersProvider, { handlers: handlers },
77
- React__default.createElement(DisplayTextProvider, { displayText: displayText },
78
- React__default.createElement(ViewsProvider, { actions: resolvedActions, views: views },
79
- React__default.createElement(ComponentsProvider, { composables: composables },
80
- React__default.createElement(LocationItemsProvider, null,
81
- React__default.createElement(FileItemsProvider, { validateFile: validateFile },
82
- React__default.createElement(FilePreviewProvider, { filePreview: filePreview }, children)))))))))));
76
+ React__default.createElement(PaginationConfigProvider, { pageSize: pageSize },
77
+ React__default.createElement(ActionConfigsProvider, { actionConfigs: actionConfigs },
78
+ React__default.createElement(ActionHandlersProvider, { handlers: handlers },
79
+ React__default.createElement(DisplayTextProvider, { displayText: displayText },
80
+ React__default.createElement(ViewsProvider, { actions: resolvedActions, views: views },
81
+ React__default.createElement(ComponentsProvider, { composables: composables },
82
+ React__default.createElement(LocationItemsProvider, null,
83
+ React__default.createElement(FileItemsProvider, { validateFile: validateFile },
84
+ React__default.createElement(FilePreviewProvider, { filePreview: filePreview }, children))))))))))));
83
85
  }
84
86
  return Provider;
85
87
  }
@@ -9,12 +9,9 @@ import '@aws-amplify/ui-react-core/elements';
9
9
  import '../credentials/context.mjs';
10
10
  import '@aws-amplify/storage/internals';
11
11
  import '../configuration/context.mjs';
12
- import 'aws-amplify';
13
- import 'jszip';
14
- import 'aws-amplify/storage';
15
- import { assertRegisterAuthListener } from '../validators/assertRegisterAuthListener.mjs';
16
- import '../actions/configs/context.mjs';
12
+ import '../configuration/paginationContext.mjs';
17
13
  import '../actions/configs/defaults.mjs';
14
+ import { assertRegisterAuthListener } from '../validators/assertRegisterAuthListener.mjs';
18
15
  import '../views/context/actionViews.mjs';
19
16
  import '../views/context/primaryViews.mjs';
20
17
  import { CopyView } from '../views/LocationActionView/CopyView/CopyView.mjs';
@@ -22,11 +19,19 @@ import '../locationItems/context.mjs';
22
19
  import '../store/context.mjs';
23
20
  import { CreateFolderView } from '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
24
21
  import { DeleteView } from '../views/LocationActionView/DeleteView/DeleteView.mjs';
22
+ import '../displayText/context.mjs';
23
+ import '@aws-amplify/ui-react';
24
+ import '../components/elements/definitions.mjs';
25
+ import '../components/elements/IconElement.mjs';
26
+ import 'aws-amplify';
27
+ import 'jszip';
28
+ import 'aws-amplify/storage';
25
29
  import { DownloadView } from '../views/LocationActionView/DownloadView/DownloadView.mjs';
26
30
  import { LocationActionView } from '../views/LocationActionView/LocationActionView.mjs';
27
31
  import { UploadView } from '../views/LocationActionView/UploadView/UploadView.mjs';
28
32
  import '../fileItems/context.mjs';
29
33
  import { LocationDetailView } from '../views/LocationDetailView/LocationDetailView.mjs';
34
+ import '../actions/configs/context.mjs';
30
35
  import '../filePreview/context.mjs';
31
36
  import { LocationsView } from '../views/LocationsView/LocationsView.mjs';
32
37
  import { useView } from '../views/useView.mjs';
@@ -1,20 +1,132 @@
1
1
  import { DEFAULT_ACTION_VIEW_DISPLAY_TEXT } from './shared.mjs';
2
2
 
3
+ const pluralize = (count, word) => count === 1 ? word : `${word}s`;
4
+ const formatCount = (count, word) => `${count === 1 ? '' : 'All '}${count} ${pluralize(count, word)}`;
3
5
  const DEFAULT_DELETE_VIEW_DISPLAY_TEXT = {
4
6
  ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
5
7
  title: 'Delete',
6
8
  actionStartLabel: 'Delete',
9
+ confirmationModalTitle: 'Confirm Deletion',
10
+ confirmationModalConfirmLabel: 'Delete',
11
+ confirmationModalCancelLabel: 'Cancel',
12
+ confirmationModalMessage: 'The items that will be deleted contain {count} folder{plural}',
13
+ confirmationModalFolderListTitle: 'Folder list:',
7
14
  getActionCompleteMessage: (data) => {
8
- const { counts } = data ?? {};
9
- const { COMPLETE, FAILED, TOTAL } = counts ?? {};
15
+ const { counts, tasks } = data ?? {};
16
+ const { COMPLETE = 0, FAILED = 0, TOTAL = 0 } = counts ?? {};
17
+ if (!TOTAL || TOTAL === 0) {
18
+ return { content: 'No items to delete.', type: 'info' };
19
+ }
20
+ if (tasks && tasks.length > 0) {
21
+ const folderTasks = tasks.filter((task) => task.data.type === 'FOLDER');
22
+ const fileTasks = tasks.filter((task) => task.data.type === 'FILE');
23
+ const completeFolders = folderTasks.filter((task) => task.status === 'COMPLETE').length;
24
+ const failedFolders = folderTasks.filter((task) => task.status === 'FAILED').length;
25
+ const completeFiles = fileTasks.filter((task) => task.status === 'COMPLETE').length;
26
+ const failedFiles = fileTasks.filter((task) => task.status === 'FAILED').length;
27
+ const hasFolders = folderTasks.length > 0;
28
+ const hasFiles = fileTasks.length > 0;
29
+ const isMixed = hasFolders && hasFiles;
30
+ // All successful
31
+ if (COMPLETE === TOTAL) {
32
+ if (isMixed) {
33
+ return {
34
+ content: `${formatCount(completeFolders, 'folder')} and ${completeFiles} ${pluralize(completeFiles, 'file')} deleted successfully.`,
35
+ type: 'success',
36
+ };
37
+ }
38
+ else if (hasFolders) {
39
+ return {
40
+ content: `${formatCount(completeFolders, 'folder')} deleted successfully.`,
41
+ type: 'success',
42
+ };
43
+ }
44
+ else {
45
+ return {
46
+ content: `${formatCount(completeFiles, 'file')} deleted successfully.`,
47
+ type: 'success',
48
+ };
49
+ }
50
+ }
51
+ // Complete failure
52
+ if (FAILED === TOTAL) {
53
+ if (isMixed) {
54
+ return {
55
+ content: `Failed to delete ${failedFolders} ${pluralize(failedFolders, 'folder')} and ${failedFiles} ${pluralize(failedFiles, 'file')}. Some contents may have been deleted.`,
56
+ type: 'error',
57
+ };
58
+ }
59
+ else if (hasFolders) {
60
+ return {
61
+ content: `Failed to delete ${failedFolders} ${pluralize(failedFolders, 'folder')}. Some items may have been deleted.`,
62
+ type: 'error',
63
+ };
64
+ }
65
+ else {
66
+ return {
67
+ content: `Failed to delete ${failedFiles} ${pluralize(failedFiles, 'file')}.`,
68
+ type: 'error',
69
+ };
70
+ }
71
+ }
72
+ // Partial failure
73
+ if (isMixed) {
74
+ const messages = [];
75
+ if (completeFiles > 0) {
76
+ messages.push(`${completeFiles} ${pluralize(completeFiles, 'file')} deleted`);
77
+ }
78
+ if (completeFolders > 0) {
79
+ messages.push(`${completeFolders} ${pluralize(completeFolders, 'folder')} deleted`);
80
+ }
81
+ if (failedFiles > 0) {
82
+ messages.push(`${failedFiles} ${pluralize(failedFiles, 'file')} failed`);
83
+ }
84
+ if (failedFolders > 0) {
85
+ messages.push(`${failedFolders} ${pluralize(failedFolders, 'folder')} failed`);
86
+ }
87
+ return {
88
+ content: messages.join(', ') + '. Some items may have been deleted.',
89
+ type: 'error',
90
+ };
91
+ }
92
+ else if (hasFolders) {
93
+ // Folders only partial failure
94
+ if (completeFolders > 0) {
95
+ return {
96
+ content: `${completeFolders} ${pluralize(completeFolders, 'folder')} deleted, ${failedFolders} ${pluralize(failedFolders, 'folder')} failed. Some items may have been deleted.`,
97
+ type: 'error',
98
+ };
99
+ }
100
+ else {
101
+ return {
102
+ content: `Failed to delete ${failedFolders} ${pluralize(failedFolders, 'folder')}. Some items may have been deleted.`,
103
+ type: 'error',
104
+ };
105
+ }
106
+ }
107
+ else {
108
+ // Files only partial failure
109
+ return {
110
+ content: `${completeFiles} ${pluralize(completeFiles, 'file')} deleted, ${failedFiles} ${pluralize(failedFiles, 'file')} failed.`,
111
+ type: 'error',
112
+ };
113
+ }
114
+ }
115
+ // Fallback to generic messaging if tasks not available
10
116
  if (COMPLETE === TOTAL) {
11
- return { content: 'All files deleted.', type: 'success' };
117
+ return {
118
+ content: `${formatCount(TOTAL, 'item')} deleted successfully.`,
119
+ type: 'success',
120
+ };
12
121
  }
13
122
  if (FAILED === TOTAL) {
14
- return { content: 'All files failed to delete.', type: 'error' };
123
+ return {
124
+ content: `Failed to delete ${formatCount(TOTAL, 'item')}.`,
125
+ type: 'error',
126
+ };
15
127
  }
16
128
  return {
17
- content: `${COMPLETE} files deleted, ${FAILED} files failed to delete.`,
129
+ content: `${COMPLETE} ${pluralize(COMPLETE, 'item')} deleted, ${FAILED} ${pluralize(FAILED, 'item')} failed to delete.`,
18
130
  type: 'error',
19
131
  };
20
132
  },
@@ -69,6 +69,7 @@ const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT = {
69
69
  tableColumnSizeHeader: 'Size',
70
70
  tableColumnTypeHeader: 'Type',
71
71
  selectFileLabel: 'Select file',
72
+ selectFolderLabel: 'Select folder',
72
73
  selectAllFilesLabel: 'Select all files',
73
74
  getActionListItemLabel: (key = '') => {
74
75
  switch (key) {
@@ -17,6 +17,7 @@ const DEFAULT_ACTION_VIEW_DISPLAY_TEXT = {
17
17
  tableColumnNameHeader: 'Name',
18
18
  tableColumnTypeHeader: 'Type',
19
19
  tableColumnSizeHeader: 'Size',
20
+ tableColumnProgressHeader: 'Progress',
20
21
  };
21
22
  const DEFAULT_LIST_VIEW_DISPLAY_TEXT = {
22
23
  loadingIndicatorLabel: 'Loading',
@@ -9,6 +9,7 @@ import '../actions/configs/context.mjs';
9
9
  import '../actions/configs/defaults.mjs';
10
10
 
11
11
  const DEFAULT_STATE = {
12
+ dataItems: undefined,
12
13
  fileDataItems: undefined,
13
14
  };
14
15
  const locationItemsReducer = (prevState, event) => {
@@ -17,27 +18,29 @@ const locationItemsReducer = (prevState, event) => {
17
18
  const { items } = event;
18
19
  if (!items?.length)
19
20
  return prevState;
20
- if (!prevState.fileDataItems?.length) {
21
- return { fileDataItems: items.map(createFileDataItem) };
22
- }
23
- const nextFileDataItems = items?.reduce((fileDataItems, data) => prevState.fileDataItems?.some(({ id }) => id === data.id)
24
- ? fileDataItems
25
- : fileDataItems.concat(createFileDataItem(data)), []);
26
- if (!nextFileDataItems?.length)
27
- return prevState;
21
+ const nextDataItems = !prevState.dataItems?.length
22
+ ? items
23
+ : prevState.dataItems.concat(items.filter((data) => !prevState.dataItems?.some(({ id }) => id === data.id)));
24
+ const fileItems = items.filter((item) => item.type === 'FILE');
25
+ const nextFileDataItems = !prevState.fileDataItems?.length
26
+ ? fileItems.map(createFileDataItem)
27
+ : prevState.fileDataItems.concat(fileItems
28
+ .filter((data) => !prevState.fileDataItems?.some(({ id }) => id === data.id))
29
+ .map(createFileDataItem));
28
30
  return {
29
- fileDataItems: prevState.fileDataItems.concat(nextFileDataItems),
31
+ dataItems: nextDataItems,
32
+ fileDataItems: nextFileDataItems,
30
33
  };
31
34
  }
32
35
  case 'REMOVE_LOCATION_ITEM': {
33
36
  const { id } = event;
34
- if (!prevState.fileDataItems)
35
- return prevState;
36
- const fileDataItems = prevState.fileDataItems.filter((item) => item.id !== id);
37
- if (fileDataItems.length === prevState.fileDataItems.length) {
37
+ const dataItems = prevState.dataItems?.filter((item) => item.id !== id);
38
+ const fileDataItems = prevState.fileDataItems?.filter((item) => item.id !== id);
39
+ if (dataItems?.length === prevState.dataItems?.length &&
40
+ fileDataItems?.length === prevState.fileDataItems?.length) {
38
41
  return prevState;
39
42
  }
40
- return { fileDataItems };
43
+ return { dataItems, fileDataItems };
41
44
  }
42
45
  case 'RESET_LOCATION_ITEMS': {
43
46
  return DEFAULT_STATE;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Selection utility functions for LocationItems
3
+ */
4
+ /**
5
+ * Get selected files from dataItems
6
+ */
7
+ const getSelectedFiles = (dataItems) => {
8
+ return dataItems?.filter((item) => item.type === 'FILE') ?? [];
9
+ };
10
+ /**
11
+ * Get selected folders from dataItems
12
+ */
13
+ const getSelectedFolders = (dataItems) => {
14
+ return dataItems?.filter((item) => item.type === 'FOLDER') ?? [];
15
+ };
16
+ /**
17
+ * Check if selection contains folders
18
+ */
19
+ const hasSelectedFolders = (dataItems) => {
20
+ return dataItems?.some((item) => item.type === 'FOLDER') ?? false;
21
+ };
22
+ /**
23
+ * Get selection summary
24
+ */
25
+ const getSelectionSummary = (dataItems) => {
26
+ const files = getSelectedFiles(dataItems);
27
+ const folders = getSelectedFolders(dataItems);
28
+ return {
29
+ total: dataItems?.length ?? 0,
30
+ files: files.length,
31
+ folders: folders.length,
32
+ hasFiles: files.length > 0,
33
+ hasFolders: folders.length > 0,
34
+ isMixed: files.length > 0 && folders.length > 0,
35
+ };
36
+ };
37
+
38
+ export { getSelectedFiles, getSelectedFolders, getSelectionSummary, hasSelectedFolders };
@@ -12,7 +12,7 @@ const DEPRECATED_PROP_KEYS = ['actionType', 'location', 'path'];
12
12
  const template = (key, index, values) => `\`${key}\`${index < values.length - 1 ? ', ' : ''}`;
13
13
  const getMissingLocationKeys = (location) => location === null
14
14
  ? []
15
- : REQUIRED_LOCATION_KEYS.filter((key) => !location[key]);
15
+ : REQUIRED_LOCATION_KEYS.filter((key) => location[key] === undefined || location[key] === null);
16
16
  let didWarnConflictingBehavior = false;
17
17
  let didWarnDeprecatedAndConflictingProps = false;
18
18
  let didWarnDeprecatedProps = false;