@aws-amplify/ui-react-storage 3.14.0 → 3.16.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 +8 -2
  2. package/dist/{createStorageBrowser-CotOvK0A.js → createStorageBrowser-B-J76Lyp.js} +1012 -249
  3. package/dist/esm/browser.mjs +1 -0
  4. package/dist/esm/components/StorageBrowser/ErrorBoundary/ErrorBoundary.mjs +0 -3
  5. package/dist/esm/components/StorageBrowser/StorageBrowserAmplify.mjs +1 -0
  6. package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +14 -3
  7. package/dist/esm/components/StorageBrowser/actions/handlers/defaults.mjs +1 -1
  8. package/dist/esm/components/StorageBrowser/actions/handlers/delete.mjs +39 -8
  9. package/dist/esm/components/StorageBrowser/actions/handlers/listLocations.mjs +7 -2
  10. package/dist/esm/components/StorageBrowser/actions/handlers/utils.mjs +65 -1
  11. package/dist/esm/components/StorageBrowser/actions/handlers/zipdownload.mjs +195 -0
  12. package/dist/esm/components/StorageBrowser/adapters/createAmplifyAuthAdapter/createAmplifyListLocationsHandler.mjs +3 -1
  13. package/dist/esm/components/StorageBrowser/adapters/createManagedAuthAdapter/createManagedAuthAdapter.mjs +1 -0
  14. package/dist/esm/components/StorageBrowser/components/ComponentsProvider.mjs +0 -3
  15. package/dist/esm/components/StorageBrowser/components/base/preview/DownloadButton.mjs +0 -3
  16. package/dist/esm/components/StorageBrowser/components/composables/ActionConfirmationModal.mjs +34 -0
  17. package/dist/esm/components/StorageBrowser/components/composables/defaults.mjs +2 -0
  18. package/dist/esm/components/StorageBrowser/components/elements/definitions.mjs +2 -2
  19. package/dist/esm/components/StorageBrowser/controls/ActionConfirmationModalControl.mjs +12 -0
  20. package/dist/esm/components/StorageBrowser/controls/DataTableControl.mjs +0 -3
  21. package/dist/esm/components/StorageBrowser/controls/hooks/useActionConfirmationModal.mjs +17 -0
  22. package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +8 -3
  23. package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +1 -0
  24. package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +9 -4
  25. package/dist/esm/components/StorageBrowser/displayText/libraries/en/deleteView.mjs +117 -5
  26. package/dist/esm/components/StorageBrowser/displayText/libraries/en/downloadView.mjs +2 -0
  27. package/dist/esm/components/StorageBrowser/displayText/libraries/en/locationDetailView.mjs +1 -0
  28. package/dist/esm/components/StorageBrowser/displayText/libraries/en/shared.mjs +3 -0
  29. package/dist/esm/components/StorageBrowser/locationItems/context.mjs +18 -14
  30. package/dist/esm/components/StorageBrowser/locationItems/utils.mjs +38 -0
  31. package/dist/esm/components/StorageBrowser/store/validateStoreProps.mjs +1 -1
  32. package/dist/esm/components/StorageBrowser/tasks/constants.mjs +2 -0
  33. package/dist/esm/components/StorageBrowser/tasks/useProcessTasks.mjs +14 -5
  34. package/dist/esm/components/StorageBrowser/tasks/utils.mjs +4 -1
  35. package/dist/esm/components/StorageBrowser/useAction/useHandler.mjs +1 -1
  36. package/dist/esm/components/StorageBrowser/useAction/utils.mjs +0 -4
  37. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyView.mjs +0 -3
  38. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +4 -3
  39. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/FoldersMessageControl.mjs +0 -3
  40. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useCopyView.mjs +0 -3
  41. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useFolders.mjs +0 -3
  42. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/CreateFolderView.mjs +0 -3
  43. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/useCreateFolderView.mjs +0 -3
  44. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteView.mjs +5 -5
  45. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteViewProvider.mjs +7 -6
  46. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/useDeleteView.mjs +69 -6
  47. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/utils.mjs +87 -0
  48. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +0 -3
  49. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.mjs +9 -0
  50. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs +0 -3
  51. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +1 -4
  52. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +4 -0
  53. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +0 -3
  54. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailView.mjs +0 -3
  55. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailViewProvider.mjs +2 -1
  56. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFolderRowContent.mjs +38 -27
  57. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.mjs +9 -1
  58. package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +11 -9
  59. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsView.mjs +0 -3
  60. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsViewProvider.mjs +0 -3
  61. package/dist/esm/components/StorageBrowser/views/LocationsView/useLocationsView.mjs +1 -0
  62. package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +7 -3
  63. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +8 -3
  64. package/dist/esm/components/StorageBrowser/views/hooks/useFilePreview/useFilePreview.mjs +1 -0
  65. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/constants.mjs +14 -1
  66. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.mjs +123 -13
  67. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/utils.mjs +4 -4
  68. package/dist/esm/version.mjs +1 -1
  69. package/dist/index.js +2 -1
  70. package/dist/styles.css +100 -1
  71. package/dist/types/components/StorageBrowser/actions/handlers/delete.d.ts +5 -3
  72. package/dist/types/components/StorageBrowser/actions/handlers/index.d.ts +1 -0
  73. package/dist/types/components/StorageBrowser/actions/handlers/types.d.ts +18 -2
  74. package/dist/types/components/StorageBrowser/actions/handlers/utils.d.ts +11 -0
  75. package/dist/types/components/StorageBrowser/actions/handlers/zipdownload.d.ts +3 -0
  76. package/dist/types/components/StorageBrowser/components/composables/ActionConfirmationModal.d.ts +12 -0
  77. package/dist/types/components/StorageBrowser/components/composables/types.d.ts +2 -0
  78. package/dist/types/components/StorageBrowser/controls/ActionConfirmationModalControl.d.ts +2 -0
  79. package/dist/types/components/StorageBrowser/controls/hooks/useActionConfirmationModal.d.ts +2 -0
  80. package/dist/types/components/StorageBrowser/controls/index.d.ts +1 -0
  81. package/dist/types/components/StorageBrowser/controls/types.d.ts +4 -0
  82. package/dist/types/components/StorageBrowser/displayText/types.d.ts +9 -0
  83. package/dist/types/components/StorageBrowser/locationItems/context.d.ts +12 -3
  84. package/dist/types/components/StorageBrowser/locationItems/index.d.ts +1 -0
  85. package/dist/types/components/StorageBrowser/locationItems/utils.d.ts +27 -0
  86. package/dist/types/components/StorageBrowser/tasks/types.d.ts +10 -5
  87. package/dist/types/components/StorageBrowser/tasks/useProcessTasks.d.ts +1 -1
  88. package/dist/types/components/StorageBrowser/useAction/useHandler.d.ts +1 -1
  89. package/dist/types/components/StorageBrowser/views/LocationActionView/DeleteView/types.d.ts +5 -0
  90. package/dist/types/components/StorageBrowser/views/LocationActionView/DeleteView/utils.d.ts +26 -0
  91. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFolderRowContent.d.ts +4 -1
  92. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.d.ts +3 -2
  93. package/dist/types/components/StorageBrowser/views/LocationDetailView/types.d.ts +8 -1
  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 +5 -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/version.d.ts +1 -1
  100. package/package.json +12 -9
  101. package/dist/esm/components/StorageBrowser/actions/handlers/download.mjs +0 -38
@@ -1,11 +1,95 @@
1
- import { noop, capitalize } from '@aws-amplify/ui';
1
+ import { capitalize } from '@aws-amplify/ui';
2
2
  import '../../../displayText/context.mjs';
3
3
  import { isDeleteViewDisplayTextKey } from '../../../displayText/utils.mjs';
4
- import { STATUS_LABELS } from './constants.mjs';
5
- import { cancel, size, type, folder, name, getFileDataCellKey } from './utils.mjs';
4
+ import { STATUS_ICONS, STATUS_LABELS } from './constants.mjs';
5
+ import { getFileSize, getFileType, getCellName } from './utils.mjs';
6
+ import '@aws-amplify/storage/internals';
7
+ import { getFileKey } from '../../../actions/handlers/utils.mjs';
8
+ import 'jszip';
9
+ import 'aws-amplify/storage';
10
+ import '../../../actions/configs/context.mjs';
11
+ import '../../../actions/configs/defaults.mjs';
12
+ import { getFolderName } from '../../LocationActionView/DeleteView/utils.mjs';
6
13
 
14
+ const getDeleteCellKey = (data) => `${data.key}-${data.item.data.id}`;
15
+ const getCellDataFolder = (data) => {
16
+ const { type, key } = data;
17
+ const fileKey = getFileKey(key);
18
+ const targetKey = data.key;
19
+ if (type === 'FOLDER') {
20
+ const pathWithoutTrailingSlash = targetKey.replace(/\/$/, '');
21
+ const lastSlashIndex = pathWithoutTrailingSlash.lastIndexOf('/');
22
+ return lastSlashIndex >= 0
23
+ ? pathWithoutTrailingSlash.slice(0, lastSlashIndex + 1)
24
+ : '';
25
+ }
26
+ return targetKey.slice(0, -fileKey?.length);
27
+ };
28
+ const name = (data) => {
29
+ const key = getDeleteCellKey(data);
30
+ const { item } = data;
31
+ let text;
32
+ if (item.data.type === 'FOLDER') {
33
+ text = `${getFolderName(item.data.key)}/`;
34
+ }
35
+ else {
36
+ text = item.data.fileKey ?? getCellName(item.data.key);
37
+ }
38
+ const icon = STATUS_ICONS[item.status];
39
+ return { key, type: 'text', content: { icon, text } };
40
+ };
41
+ const folder = (data) => {
42
+ const key = getDeleteCellKey(data);
43
+ const text = getCellDataFolder(data.item.data);
44
+ return { key, type: 'text', content: { text } };
45
+ };
46
+ const type = (data) => {
47
+ const key = getDeleteCellKey(data);
48
+ if (data.item.data.type === 'FOLDER') {
49
+ return { key, type: 'text', content: { text: 'Folder' } };
50
+ }
51
+ const text = getFileType(data.item.data.key);
52
+ return { key, type: 'text', content: { text } };
53
+ };
54
+ const size = (data) => {
55
+ const key = getDeleteCellKey(data);
56
+ const itemData = data.item.data;
57
+ if (data.item.data.type === 'FOLDER') {
58
+ return { key, type: 'text', content: { text: '-' } };
59
+ }
60
+ const value = 'size' in itemData ? itemData.size : 0;
61
+ const displayValue = getFileSize(value);
62
+ return { key, type: 'number', content: { value, displayValue } };
63
+ };
64
+ const getCancelCellContent = (data) => {
65
+ const { item, props } = data;
66
+ const { cancel, status } = item;
67
+ const { isProcessing, onTaskRemove } = props;
68
+ const isQueued = status === 'QUEUED';
69
+ const isRemovable = isQueued && !isProcessing;
70
+ const isCancelable = isProcessing && !!cancel;
71
+ const itemAriaValue = getCellName(item.data.fileKey ?? item.data.key);
72
+ const ariaLabel = `${isRemovable ? 'Remove' : 'Cancel'} item: ${itemAriaValue}`;
73
+ const isDisabled = !isRemovable && !isCancelable;
74
+ const onClick = !isCancelable && !isRemovable
75
+ ? undefined
76
+ : () => {
77
+ if (isRemovable) {
78
+ onTaskRemove?.(item);
79
+ return;
80
+ }
81
+ if (isCancelable)
82
+ cancel();
83
+ };
84
+ return { ariaLabel, isDisabled, onClick, icon: 'cancel' };
85
+ };
86
+ const cancel = (data) => {
87
+ const key = getDeleteCellKey(data);
88
+ const content = getCancelCellContent(data);
89
+ return { key, type: 'button', content };
90
+ };
7
91
  const status = (data) => {
8
- const key = getFileDataCellKey(data);
92
+ const key = getDeleteCellKey(data);
9
93
  const { item: { status }, props: { displayText }, } = data;
10
94
  const statusLabelKey = STATUS_LABELS[status];
11
95
  const text = isDeleteViewDisplayTextKey(statusLabelKey)
@@ -13,21 +97,47 @@ const status = (data) => {
13
97
  : '';
14
98
  return { key, type: 'text', content: { text } };
15
99
  };
100
+ const progress = (data) => {
101
+ const key = getDeleteCellKey(data);
102
+ const { item } = data;
103
+ const itemIsFile = item.data.type === 'FILE';
104
+ if (itemIsFile) {
105
+ const text = item.status === 'COMPLETE' ? 'Deleted' : '-';
106
+ return { key, type: 'text', content: { text } };
107
+ }
108
+ if ((item.status === 'PENDING' ||
109
+ item.status === 'FAILED' ||
110
+ item.status === 'CANCELED') &&
111
+ item.data.totalCount !== undefined) {
112
+ const countDisplay = item.data.totalCount ?? '?';
113
+ const text = `${item.successCount ?? 0}/${countDisplay} files`;
114
+ return { key, type: 'text', content: { text } };
115
+ }
116
+ else if (item.status === 'COMPLETE') {
117
+ if (item.data.totalCount === null) {
118
+ const text = `${item.successCount ?? 0} files deleted`;
119
+ return { key, type: 'text', content: { text } };
120
+ }
121
+ const text = `${item.data.totalCount} files deleted`;
122
+ return { key, type: 'text', content: { text } };
123
+ }
124
+ else {
125
+ const text = item.data.totalCount === null
126
+ ? 'Count failed'
127
+ : item.data.totalCount !== undefined
128
+ ? `${item.data.totalCount} files`
129
+ : 'Calculating...';
130
+ return { key, type: 'text', content: { text } };
131
+ }
132
+ };
16
133
  const DELETE_CELL_RESOLVERS = {
17
134
  name,
18
135
  folder,
19
136
  type,
20
137
  size,
21
138
  status,
139
+ progress,
22
140
  cancel,
23
- /**
24
- * @deprecated
25
- *
26
- * non-upload view tables do not include "progress" headers but include here to
27
- * keep TS happy as "progress" headers were included in display text interfaces
28
- * and cannot be removed from the tables without a breaking change
29
- */
30
- progress: noop,
31
141
  };
32
142
  const DELETE_TABLE_RESOLVERS = {
33
143
  getCell: (data) => DELETE_CELL_RESOLVERS[data.key](data),
@@ -41,4 +151,4 @@ const DELETE_TABLE_RESOLVERS = {
41
151
  getRowKey: ({ item }) => item.data.id,
42
152
  };
43
153
 
44
- export { DELETE_TABLE_RESOLVERS };
154
+ export { DELETE_TABLE_RESOLVERS, getCancelCellContent };
@@ -1,8 +1,8 @@
1
1
  import { humanFileSize } from '@aws-amplify/ui';
2
2
  import { STATUS_ICONS } from './constants.mjs';
3
3
 
4
- const getFileType = (value, fallback = '') => value.lastIndexOf('.') !== -1
5
- ? value.slice(value.lastIndexOf('.') + 1)
4
+ const getFileType = (value, fallback = '') => value?.lastIndexOf?.('.') !== -1
5
+ ? value?.slice(value?.lastIndexOf?.('.') + 1)
6
6
  : fallback;
7
7
  const getCellName = (value) =>
8
8
  // `value.split` always returns an array with at least one entry
@@ -17,7 +17,7 @@ const getFileDataCellFolder = (task) => {
17
17
  ? task.data.sourceKey
18
18
  : task.data.key;
19
19
  const { fileKey } = task.data;
20
- return targetKey.slice(0, -fileKey.length);
20
+ return targetKey.slice(0, -fileKey?.length);
21
21
  };
22
22
  const getUploadCellProgress = ({ progress, status, }) => {
23
23
  // prefer `progress` if available, 1 if status is complete, default 0
@@ -27,7 +27,7 @@ const getUploadCellProgress = ({ progress, status, }) => {
27
27
  };
28
28
  const getDownloadCellProgress = ({ progress, status, }) => {
29
29
  // prefer `progress` if available, 1 if status is complete, default 0
30
- const value = progress ?? (status === 'COMPLETE' ? 1 : 0);
30
+ const value = progress ?? (status === 'LOADED' || status === 'COMPLETE' ? 1 : 0);
31
31
  const displayValue = `${Math.round(value * 100)}%`;
32
32
  return { displayValue, value };
33
33
  };
@@ -1,3 +1,3 @@
1
- const VERSION = '3.14.0';
1
+ const VERSION = '3.16.0';
2
2
 
3
3
  export { VERSION };
package/dist/index.js CHANGED
@@ -9,9 +9,10 @@ var uiReactCore = require('@aws-amplify/ui-react-core');
9
9
  var auth = require('aws-amplify/auth');
10
10
  var storage = require('aws-amplify/storage');
11
11
  var internal = require('@aws-amplify/ui-react/internal');
12
- var createStorageBrowser = require('./createStorageBrowser-CotOvK0A.js');
12
+ var createStorageBrowser = require('./createStorageBrowser-B-J76Lyp.js');
13
13
  require('@aws-amplify/storage/internals');
14
14
  require('aws-amplify');
15
+ require('jszip');
15
16
  require('aws-amplify/utils');
16
17
  require('@aws-amplify/ui-react-core/elements');
17
18
 
package/dist/styles.css CHANGED
@@ -3565,6 +3565,23 @@ strong.amplify-text {
3565
3565
  gap: var(--amplify-space-medium);
3566
3566
  }
3567
3567
 
3568
+ [data-amplify-authenticator-passkeyprompt] .amplify-authenticator__passkey-success-icon {
3569
+ font-size: var(--amplify-font-sizes-xxxl);
3570
+ color: var(--amplify-colors-green-60, #34a853);
3571
+ }
3572
+ [data-amplify-authenticator-passkeyprompt] .amplify-authenticator__passkey-credential-item {
3573
+ padding: var(--amplify-space-medium);
3574
+ background-color: var(--amplify-colors-background-secondary);
3575
+ border-radius: var(--amplify-radii-small);
3576
+ }
3577
+ [data-amplify-authenticator-passkeyprompt] .amplify-authenticator__passkey-error {
3578
+ color: var(--amplify-colors-font-error);
3579
+ margin-top: var(--amplify-space-small);
3580
+ }
3581
+ [data-amplify-authenticator-passkeyprompt] .amplify-authenticator__passkey-icon {
3582
+ font-size: var(--amplify-components-authenticator-passkey-icon-size, 12rem);
3583
+ }
3584
+
3568
3585
  .amplify-avatar {
3569
3586
  --avatar-color: var(--amplify-components-avatar-color);
3570
3587
  --avatar-background-color: var(--amplify-components-avatar-background-color);
@@ -4799,6 +4816,88 @@ html[dir=rtl] .amplify-field-group__inner-start {
4799
4816
  gap: var(--amplify-components-message-dismiss-gap);
4800
4817
  }
4801
4818
 
4819
+ /* Modal component with highest specificity to override global resets */
4820
+ .amplify-modal__overlay.amplify-modal__overlay {
4821
+ position: fixed;
4822
+ top: 0;
4823
+ left: 0;
4824
+ right: 0;
4825
+ bottom: 0;
4826
+ background-color: rgba(0, 0, 0, 0.5);
4827
+ z-index: 1000;
4828
+ display: flex;
4829
+ align-items: center;
4830
+ justify-content: center;
4831
+ box-sizing: border-box;
4832
+ }
4833
+
4834
+ .amplify-modal__content.amplify-modal__content {
4835
+ background-color: var(--amplify-colors-background-primary);
4836
+ padding: var(--amplify-space-large);
4837
+ border-radius: var(--amplify-radii-medium);
4838
+ box-shadow: var(--amplify-shadows-large);
4839
+ max-width: 500px;
4840
+ width: 90%;
4841
+ box-sizing: border-box;
4842
+ }
4843
+
4844
+ .amplify-modal__header.amplify-modal__header {
4845
+ margin-bottom: var(--amplify-space-medium);
4846
+ display: flex;
4847
+ justify-content: space-between;
4848
+ align-items: center;
4849
+ }
4850
+
4851
+ .amplify-modal__title.amplify-modal__title {
4852
+ font-weight: var(--amplify-font-weights-bold);
4853
+ font-size: var(--amplify-font-sizes-large);
4854
+ margin: 0;
4855
+ }
4856
+
4857
+ .amplify-modal__close-button.amplify-modal__close-button {
4858
+ background: none;
4859
+ border: none;
4860
+ font-size: var(--amplify-font-sizes-large);
4861
+ cursor: pointer;
4862
+ padding: var(--amplify-space-xs);
4863
+ color: var(--amplify-colors-font-secondary);
4864
+ }
4865
+
4866
+ .amplify-modal__close-button.amplify-modal__close-button:hover {
4867
+ color: var(--amplify-colors-font-primary);
4868
+ }
4869
+
4870
+ .amplify-modal__body.amplify-modal__body {
4871
+ margin-bottom: var(--amplify-space-medium);
4872
+ color: var(--amplify-colors-font-primary);
4873
+ }
4874
+
4875
+ .amplify-modal__footer.amplify-modal__footer {
4876
+ display: flex;
4877
+ gap: var(--amplify-space-xs);
4878
+ justify-content: flex-end;
4879
+ }
4880
+
4881
+ .amplify-modal__list-title.amplify-modal__list-title {
4882
+ margin-bottom: var(--amplify-space-xs);
4883
+ font-weight: var(--amplify-font-weights-bold);
4884
+ box-sizing: border-box;
4885
+ }
4886
+
4887
+ .amplify-modal__list.amplify-modal__list {
4888
+ margin: var(--amplify-space-xs) 0;
4889
+ padding-left: var(--amplify-space-medium);
4890
+ max-height: 250px;
4891
+ overflow-y: auto;
4892
+ box-sizing: border-box;
4893
+ list-style: disc;
4894
+ }
4895
+
4896
+ .amplify-modal__list-item.amplify-modal__list-item {
4897
+ margin-bottom: var(--amplify-space-xxs);
4898
+ box-sizing: border-box;
4899
+ }
4900
+
4802
4901
  .amplify-pagination {
4803
4902
  list-style-type: none;
4804
4903
  }
@@ -7007,7 +7106,6 @@ html[dir=rtl] .amplify-field-group__inner-start {
7007
7106
  animation-timing-function: linear;
7008
7107
  animation-name: spin;
7009
7108
  }
7010
-
7011
7109
  @keyframes spin {
7012
7110
  0% {
7013
7111
  transform: rotate(0deg);
@@ -7019,6 +7117,7 @@ html[dir=rtl] .amplify-field-group__inner-start {
7019
7117
  transform: rotate(360deg);
7020
7118
  }
7021
7119
  }
7120
+
7022
7121
  .amplify-ai-conversation {
7023
7122
  display: flex;
7024
7123
  flex-direction: column;
@@ -1,8 +1,10 @@
1
- import type { OptionalFileData, TaskHandler, TaskHandlerOptions, TaskHandlerInput, TaskHandlerOutput, TaskData } from './types';
1
+ import type { TaskHandler, TaskHandlerOptions, TaskHandlerInput, TaskHandlerOutput, TaskData, OptionalFileData } from './types';
2
2
  export interface DeleteHandlerOptions extends TaskHandlerOptions {
3
3
  }
4
- export interface DeleteHandlerData extends OptionalFileData, TaskData {
5
- fileKey: string;
4
+ export interface DeleteHandlerData extends Omit<OptionalFileData, 'type'>, TaskData {
5
+ fileKey?: string;
6
+ type?: 'FILE' | 'FOLDER';
7
+ totalCount?: number | null;
6
8
  }
7
9
  export interface DeleteHandlerInput extends TaskHandlerInput<DeleteHandlerData, DeleteHandlerOptions> {
8
10
  }
@@ -3,6 +3,7 @@ export * from './createFolder';
3
3
  export * from './defaults';
4
4
  export * from './delete';
5
5
  export * from './download';
6
+ export * from './zipdownload';
6
7
  export * from './listLocationItems';
7
8
  export * from './listLocations';
8
9
  export * from './upload';
@@ -1,5 +1,6 @@
1
1
  import type { AllFileTypes } from '../../createStorageBrowser/types';
2
2
  import type { LocationCredentialsProvider } from '../../storage-internal';
3
+ import type { TaskStatus } from '../../tasks';
3
4
  /**
4
5
  * `location` grant scope
5
6
  */
@@ -78,14 +79,19 @@ export interface TaskHandlerOptions {
78
79
  onProgress?: (data: {
79
80
  key: string;
80
81
  id: string;
81
- }, progress: number | undefined) => void;
82
+ }, progressDetails: number | undefined | {
83
+ progress?: number;
84
+ successCount?: number;
85
+ failureCount?: number;
86
+ }, state?: TaskStatus) => void;
82
87
  }
83
88
  export interface TaskHandlerInput<TData extends TaskData = TaskData, TOptions extends TaskHandlerOptions = TaskHandlerOptions> {
84
89
  config: ActionInputConfig;
85
90
  data: TData;
91
+ all: TData[];
86
92
  options?: TOptions;
87
93
  }
88
- export type TaskResultStatus = 'CANCELED' | 'COMPLETE' | 'FAILED' | 'OVERWRITE_PREVENTED';
94
+ export type TaskResultStatus = 'CANCELED' | 'COMPLETE' | 'FAILED' | 'LOADED' | 'OVERWRITE_PREVENTED';
89
95
  export interface TaskResult<TStatus, TValue> {
90
96
  /**
91
97
  * result error (if any)
@@ -103,6 +109,16 @@ export interface TaskResult<TStatus, TValue> {
103
109
  * task result value (if any)
104
110
  */
105
111
  value?: TValue;
112
+ /**
113
+ * Number of items successfully processed during the operation
114
+ * @example 150 // out of 200 total items
115
+ */
116
+ successCount?: number;
117
+ /**
118
+ * Number of items that failed during the operation
119
+ * @example 5 // out of 200 total items
120
+ */
121
+ failureCount?: number;
106
122
  }
107
123
  export interface TaskHandlerOutput<K = any> {
108
124
  cancel?: () => void;
@@ -8,6 +8,17 @@ export declare const constructBucket: ({ bucket: bucketName, region: globalRegio
8
8
  };
9
9
  export declare const parseAccessGrantLocation: (location: AccessGrantLocation) => LocationData;
10
10
  export declare const shouldExcludeLocation: ({ permissions, type }: LocationData, exclude?: ListLocationsExcludeOptions) => boolean;
11
+ /**
12
+ * Deduplicates locations with the same bucket and prefix.
13
+ * Only deduplicates when one location's permissions are a superset of another's.
14
+ * This prevents deduplication of incompatible grants like READ + WRITE.
15
+ *
16
+ * Examples:
17
+ * - READ + READWRITE → Keep READWRITE (superset)
18
+ * - READ + READ → Keep first (identical)
19
+ * - READ + WRITE → Keep both (not superset, need separate locations)
20
+ */
21
+ export declare const deduplicateLocations: (locations: LocationData[]) => LocationData[];
11
22
  export declare const getFilteredLocations: (locations: AccessGrantLocation[], exclude?: ListLocationsExcludeOptions) => LocationData[];
12
23
  export declare const getFileKey: (key: string) => string;
13
24
  export declare const createFileDataItem: (data: FileData) => FileDataItem;
@@ -0,0 +1,3 @@
1
+ import type { DownloadHandler } from './download';
2
+ declare const downloadHandler: DownloadHandler;
3
+ export { downloadHandler as zipDownloadHandler };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export interface ActionConfirmationModalProps {
3
+ isOpen: boolean;
4
+ title: string;
5
+ message: string;
6
+ content?: React.ReactNode;
7
+ onConfirm: () => void;
8
+ onCancel: () => void;
9
+ confirmLabel: string;
10
+ cancelLabel: string;
11
+ }
12
+ export declare const ActionConfirmationModal: ({ isOpen, title, message, content, onConfirm, onCancel, confirmLabel, cancelLabel, }: ActionConfirmationModalProps) => React.JSX.Element | null;
@@ -1,4 +1,5 @@
1
1
  import type { ActionCancelProps } from './ActionCancel';
2
+ import type { ActionConfirmationModalProps } from './ActionConfirmationModal';
2
3
  import type { ActionDestinationProps } from './ActionDestination';
3
4
  import type { ActionExitProps } from './ActionExit';
4
5
  import type { ActionStartProps } from './ActionStart';
@@ -21,6 +22,7 @@ import type { TitleProps } from './Title';
21
22
  import type { FilePreviewProps } from './FilePreview';
22
23
  export interface Composables {
23
24
  ActionCancel: React.ComponentType<ActionCancelProps>;
25
+ ActionConfirmationModal: React.ComponentType<ActionConfirmationModalProps>;
24
26
  ActionDestination: React.ComponentType<ActionDestinationProps>;
25
27
  ActionExit: React.ComponentType<ActionExitProps>;
26
28
  ActionStart: React.ComponentType<ActionStartProps>;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ActionConfirmationModalControl: () => React.JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { ActionConfirmationModalProps } from '../../components/composables/ActionConfirmationModal';
2
+ export declare const useActionConfirmationModal: () => ActionConfirmationModalProps;
@@ -1,4 +1,5 @@
1
1
  export { ActionCancelControl } from './ActionCancelControl';
2
+ export { ActionConfirmationModalControl } from './ActionConfirmationModalControl';
2
3
  export { ActionDestinationControl } from './ActionDestinationControl';
3
4
  export { ActionExitControl } from './ActionExitControl';
4
5
  export { ActionsListControl } from './ActionsListControl';
@@ -1,5 +1,6 @@
1
1
  import type { FileData, LocationData } from '../actions';
2
2
  import type { ActionListItem, Composables, DataTableProps, DataTableSortHeader, MessageProps } from '../components';
3
+ import type { ActionConfirmationModalProps } from '../components/composables/ActionConfirmationModal';
3
4
  import type { LocationState } from '../store';
4
5
  import type { StatusCounts } from '../tasks';
5
6
  import type { FilePreviewState } from '../views/hooks/useFilePreview';
@@ -53,6 +54,7 @@ export interface ControlsContext {
53
54
  location?: LocationState;
54
55
  overwriteToggleLabel?: string;
55
56
  message?: MessageProps;
57
+ confirmationModal?: Omit<ActionConfirmationModalProps, 'onConfirm' | 'onCancel'>;
56
58
  paginationData?: PaginationData;
57
59
  searchPlaceholder?: string;
58
60
  searchQuery?: string;
@@ -91,5 +93,7 @@ export interface ControlsContext {
91
93
  onToggleOverwrite?: () => void;
92
94
  onToggleSearchSubfolders?: () => void;
93
95
  onValidateFolderName?: (value: string) => void;
96
+ onConfirmationModalConfirm?: () => void;
97
+ onConfirmationModalCancel?: () => void;
94
98
  }
95
99
  export {};
@@ -73,6 +73,7 @@ export interface DefaultLocationDetailViewDisplayText extends DefaultListViewDis
73
73
  } | undefined;
74
74
  searchSubfoldersToggleLabel: string;
75
75
  selectFileLabel: string;
76
+ selectFolderLabel: string;
76
77
  selectAllFilesLabel: string;
77
78
  tableColumnLastModifiedHeader: string;
78
79
  tableColumnNameHeader: string;
@@ -102,8 +103,10 @@ export interface DefaultActionViewDisplayText<T extends TaskData = TaskData> {
102
103
  } | undefined;
103
104
  statusDisplayCanceledLabel: string;
104
105
  statusDisplayCompletedLabel: string;
106
+ statusDisplayLoadedLabel: string;
105
107
  statusDisplayFailedLabel: string;
106
108
  statusDisplayInProgressLabel: string;
109
+ statusDisplayFinishingLabel: string;
107
110
  statusDisplayQueuedLabel: string;
108
111
  statusDisplayTotalLabel: string;
109
112
  title: string;
@@ -113,6 +116,7 @@ export interface DefaultActionViewDisplayText<T extends TaskData = TaskData> {
113
116
  tableColumnNameHeader: string;
114
117
  tableColumnTypeHeader: string;
115
118
  tableColumnSizeHeader: string;
119
+ tableColumnProgressHeader?: string;
116
120
  }
117
121
  export interface DefaultCreateFolderViewDisplayText extends Omit<DefaultActionViewDisplayText<CreateFolderHandlerData>, `${'tableColumn' | 'statusDisplay'}${string}`> {
118
122
  folderNameLabel: string;
@@ -142,6 +146,11 @@ export interface DefaultDeleteViewDisplayText extends DefaultActionViewDisplayTe
142
146
  * @deprecated `DeleteView` does not render a "progress" header
143
147
  */
144
148
  tableColumnProgressHeader?: string;
149
+ confirmationModalTitle: string;
150
+ confirmationModalConfirmLabel: string;
151
+ confirmationModalCancelLabel: string;
152
+ confirmationModalMessage: string;
153
+ confirmationModalFolderListTitle: string;
145
154
  }
146
155
  export interface DefaultDownloadViewDisplayText extends DefaultActionViewDisplayText<DownloadHandlerData> {
147
156
  tableColumnProgressHeader: string;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import type { FileData, FileDataItem } from '../actions';
2
+ import type { FileDataItem, LocationItemData } from '../actions';
3
3
  export declare const DEFAULT_STATE: LocationItemsState;
4
4
  export type LocationItemsAction = {
5
5
  type: 'SET_LOCATION_ITEMS';
6
- items?: FileData[];
6
+ items?: LocationItemData[];
7
7
  } | {
8
8
  type: 'REMOVE_LOCATION_ITEM';
9
9
  id: string;
@@ -11,7 +11,16 @@ export type LocationItemsAction = {
11
11
  type: 'RESET_LOCATION_ITEMS';
12
12
  };
13
13
  export interface LocationItemsState {
14
- fileDataItems: FileDataItem[] | undefined;
14
+ /**
15
+ * Selected items (files and folders)
16
+ * Replaces fileDataItems to support mixed selections
17
+ */
18
+ dataItems?: LocationItemData[];
19
+ /**
20
+ * @deprecated Use dataItems instead
21
+ * Will be removed in v4.0.0
22
+ */
23
+ fileDataItems?: FileDataItem[];
15
24
  }
16
25
  export type HandleLocationItemsAction = (event: LocationItemsAction) => void;
17
26
  export type LocationItemStateContext = [
@@ -1,2 +1,3 @@
1
1
  export type { LocationItemsAction, LocationItemsProviderProps, LocationItemsState, } from './context';
2
2
  export { LocationItemsProvider, useLocationItems } from './context';
3
+ export { getSelectedFiles, getSelectedFolders, hasSelectedFolders, getSelectionSummary, } from './utils';
@@ -0,0 +1,27 @@
1
+ import type { LocationItemData } from '../actions';
2
+ /**
3
+ * Selection utility functions for LocationItems
4
+ */
5
+ /**
6
+ * Get selected files from dataItems
7
+ */
8
+ export declare const getSelectedFiles: (dataItems?: LocationItemData[]) => LocationItemData[];
9
+ /**
10
+ * Get selected folders from dataItems
11
+ */
12
+ export declare const getSelectedFolders: (dataItems?: LocationItemData[]) => LocationItemData[];
13
+ /**
14
+ * Check if selection contains folders
15
+ */
16
+ export declare const hasSelectedFolders: (dataItems?: LocationItemData[]) => boolean;
17
+ /**
18
+ * Get selection summary
19
+ */
20
+ export declare const getSelectionSummary: (dataItems?: LocationItemData[]) => {
21
+ total: number;
22
+ files: number;
23
+ folders: number;
24
+ hasFiles: boolean;
25
+ hasFolders: boolean;
26
+ isMixed: boolean;
27
+ };
@@ -1,9 +1,9 @@
1
- import type { TaskHandlerInput, TaskData, TaskResult, TaskResultStatus, TaskHandlerOptions } from '../actions';
1
+ import type { TaskData, TaskHandlerInput, TaskHandlerOptions, TaskResult, TaskResultStatus } from '../actions';
2
2
  /**
3
3
  * extends {@link TaskResultStatus} to include `QUEUED` and `PENDING` statuses
4
4
  * used in task processing
5
5
  */
6
- export type TaskStatus = TaskResultStatus | 'QUEUED' | 'PENDING';
6
+ export type TaskStatus = TaskResultStatus | 'QUEUED' | 'PENDING' | 'FINISHING';
7
7
  /**
8
8
  * aggregate task status counts
9
9
  */
@@ -13,7 +13,11 @@ export interface ProcessTasksOptions<TTask extends Task, TItems = []> {
13
13
  onTaskCancel?: (task: TTask) => void;
14
14
  onTaskComplete?: (task: TTask) => void;
15
15
  onTaskError?: (task: TTask, error: unknown) => void;
16
- onTaskProgress?: (task: TTask, progress: number | undefined) => void;
16
+ onTaskProgress?: (task: TTask, progressDetails: number | {
17
+ progress?: number;
18
+ successCount?: number;
19
+ failureCount?: number;
20
+ }) => void;
17
21
  onTaskSuccess?: (task: TTask, value: TTask['value'] | undefined) => void;
18
22
  onTaskRemove?: (task: TTask) => void;
19
23
  }
@@ -27,7 +31,8 @@ export interface Task<TData = unknown, TValue = any> extends TaskResult<TaskStat
27
31
  */
28
32
  data: TData & TaskData;
29
33
  /**
30
- * task progress
34
+ * task progress (0-1 representing completion percentage)
35
+ * @example 0.75 // 75% complete
31
36
  */
32
37
  progress?: number;
33
38
  /**
@@ -50,7 +55,7 @@ export type UseProcessTasksState<TTask, TInput> = [
50
55
  interface HandleTasksOptions extends TaskHandlerOptions {
51
56
  concurrency?: number;
52
57
  }
53
- export interface HandleBatchTasksInput<TData extends TaskData> extends Omit<TaskHandlerInput<TData, HandleTasksOptions>, 'data'> {
58
+ export interface HandleBatchTasksInput<TData extends TaskData> extends Omit<TaskHandlerInput<TData, HandleTasksOptions>, 'data' | 'all'> {
54
59
  }
55
60
  export interface HandleSingleTaskInput<TData extends TaskData> extends TaskHandlerInput<TData> {
56
61
  }
@@ -1,3 +1,3 @@
1
1
  import type { ActionHandler } from '../actions';
2
- import type { InferHandleTasksInput, Task, ProcessTasksOptions, UseProcessTasksState } from './types';
2
+ import type { InferHandleTasksInput, ProcessTasksOptions, Task, UseProcessTasksState } from './types';
3
3
  export declare function useProcessTasks<TData, TValue, TTask extends Task<TData, TValue>, TInput extends InferHandleTasksInput<TItems, TTask['data']>, TItems extends TTask['data'][] | undefined = undefined>(handler: ActionHandler<TData, TValue>, options?: ProcessTasksOptions<TTask, TItems>): UseProcessTasksState<TTask, TInput>;
@@ -1,4 +1,4 @@
1
1
  import type { ActionHandler } from '../actions';
2
- import type { InferTask, HandleTaskState, HandleTasksState, UseHandlerOptions, UseHandlerOptionsWithItems } from './types';
2
+ import type { HandleTasksState, HandleTaskState, InferTask, UseHandlerOptions, UseHandlerOptionsWithItems } from './types';
3
3
  export declare function useHandler<THandler extends ActionHandler, TTask extends InferTask<THandler>>(handler: THandler, options: UseHandlerOptionsWithItems<TTask>): HandleTasksState<TTask>;
4
4
  export declare function useHandler<THandler extends ActionHandler, TTask extends InferTask<THandler>>(handler: THandler, options?: UseHandlerOptions<TTask>): HandleTaskState<TTask>;