@aws-amplify/ui-react-storage 3.9.1 → 3.9.2

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 (124) hide show
  1. package/dist/browser.js +3 -1
  2. package/dist/{createAmplifyAuthAdapter-Cf4yJo1e.js → createAmplifyAuthAdapter-BJjOYxQA.js} +533 -377
  3. package/dist/esm/browser.mjs +6 -0
  4. package/dist/esm/components/StorageBrowser/StorageBrowserAmplify.mjs +1 -0
  5. package/dist/esm/components/StorageBrowser/StorageBrowserDefault.mjs +3 -2
  6. package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +10 -12
  7. package/dist/esm/components/StorageBrowser/actions/handlers/constants.mjs +4 -1
  8. package/dist/esm/components/StorageBrowser/actions/handlers/copy.mjs +4 -1
  9. package/dist/esm/components/StorageBrowser/actions/handlers/createFolder.mjs +4 -3
  10. package/dist/esm/components/StorageBrowser/actions/handlers/defaults.mjs +17 -0
  11. package/dist/esm/components/StorageBrowser/actions/handlers/delete.mjs +4 -1
  12. package/dist/esm/components/StorageBrowser/actions/handlers/download.mjs +4 -1
  13. package/dist/esm/components/StorageBrowser/actions/handlers/upload.mjs +6 -11
  14. package/dist/esm/components/StorageBrowser/actions/handlers/utils.mjs +4 -3
  15. package/dist/esm/components/StorageBrowser/adapters/createManagedAuthAdapter/createManagedAuthAdapter.mjs +2 -1
  16. package/dist/esm/components/StorageBrowser/componentsDefault.mjs +4 -4
  17. package/dist/esm/components/StorageBrowser/createStorageBrowser.mjs +7 -1
  18. package/dist/esm/components/StorageBrowser/displayText/libraries/en/shared.mjs +0 -1
  19. package/dist/esm/components/StorageBrowser/displayText/libraries/en/uploadView.mjs +3 -2
  20. package/dist/esm/components/StorageBrowser/displayText/utils.mjs +7 -0
  21. package/dist/esm/components/StorageBrowser/providers/store/locationItems/context.mjs +1 -0
  22. package/dist/esm/components/StorageBrowser/tasks/useProcessTasks.mjs +20 -22
  23. package/dist/esm/components/StorageBrowser/useAction/useAction.mjs +14 -7
  24. package/dist/esm/components/StorageBrowser/useAction/useHandler.mjs +26 -32
  25. package/dist/esm/components/StorageBrowser/useAction/useList.mjs +0 -1
  26. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +6 -9
  27. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useCopyView.mjs +1 -0
  28. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/useFolders.mjs +11 -13
  29. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/useCreateFolderView.mjs +1 -0
  30. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteViewProvider.mjs +6 -9
  31. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/useDeleteView.mjs +1 -0
  32. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +14 -12
  33. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +2 -1
  34. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.mjs +1 -0
  35. package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +7 -11
  36. package/dist/esm/components/StorageBrowser/views/LocationsView/useLocationsView.mjs +5 -5
  37. package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +3 -2
  38. package/dist/esm/components/StorageBrowser/views/context/getViews.mjs +4 -1
  39. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +3 -2
  40. package/dist/esm/components/StorageBrowser/views/hooks/usePaginate.mjs +19 -21
  41. package/dist/esm/components/StorageBrowser/views/hooks/useResolveTableData/useResolveTableData.mjs +15 -0
  42. package/dist/esm/components/StorageBrowser/views/useView.mjs +6 -7
  43. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/constants.mjs +18 -0
  44. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/copyResolvers.mjs +82 -0
  45. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.mjs +82 -0
  46. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/uploadResolvers.mjs +112 -0
  47. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/utils.mjs +49 -0
  48. package/dist/esm/version.mjs +1 -1
  49. package/dist/index.js +1 -1
  50. package/dist/types/components/StorageBrowser/ComponentsProvider.d.ts +4 -1
  51. package/dist/types/components/StorageBrowser/actions/configs/types.d.ts +41 -2
  52. package/dist/types/components/StorageBrowser/actions/handlers/constants.d.ts +1 -0
  53. package/dist/types/components/StorageBrowser/actions/handlers/copy.d.ts +4 -7
  54. package/dist/types/components/StorageBrowser/actions/handlers/createFolder.d.ts +1 -3
  55. package/dist/types/components/StorageBrowser/actions/handlers/defaults.d.ts +15 -0
  56. package/dist/types/components/StorageBrowser/actions/handlers/delete.d.ts +2 -2
  57. package/dist/types/components/StorageBrowser/actions/handlers/index.d.ts +1 -0
  58. package/dist/types/components/StorageBrowser/actions/handlers/listLocations.d.ts +4 -12
  59. package/dist/types/components/StorageBrowser/actions/handlers/types.d.ts +26 -17
  60. package/dist/types/components/StorageBrowser/actions/handlers/upload.d.ts +1 -4
  61. package/dist/types/components/StorageBrowser/actions/handlers/utils.d.ts +2 -2
  62. package/dist/types/components/StorageBrowser/actions/index.d.ts +1 -1
  63. package/dist/types/components/StorageBrowser/componentsDefault.d.ts +2 -2
  64. package/dist/types/components/StorageBrowser/createStorageBrowser.d.ts +6 -0
  65. package/dist/types/components/StorageBrowser/displayText/index.d.ts +1 -0
  66. package/dist/types/components/StorageBrowser/displayText/types.d.ts +16 -5
  67. package/dist/types/components/StorageBrowser/displayText/utils.d.ts +3 -0
  68. package/dist/types/components/StorageBrowser/index.d.ts +4 -3
  69. package/dist/types/components/StorageBrowser/providers/configuration/createConfigurationProvider.d.ts +1 -1
  70. package/dist/types/components/StorageBrowser/providers/configuration/types.d.ts +3 -3
  71. package/dist/types/components/StorageBrowser/providers/index.d.ts +1 -1
  72. package/dist/types/components/StorageBrowser/providers/store/actionType/types.d.ts +4 -0
  73. package/dist/types/components/StorageBrowser/providers/store/files/types.d.ts +1 -4
  74. package/dist/types/components/StorageBrowser/providers/store/index.d.ts +1 -1
  75. package/dist/types/components/StorageBrowser/providers/store/location/context.d.ts +6 -0
  76. package/dist/types/components/StorageBrowser/storage-internal.d.ts +1 -1
  77. package/dist/types/components/StorageBrowser/tasks/index.d.ts +1 -1
  78. package/dist/types/components/StorageBrowser/tasks/types.d.ts +41 -23
  79. package/dist/types/components/StorageBrowser/tasks/useProcessTasks.d.ts +3 -3
  80. package/dist/types/components/StorageBrowser/types.d.ts +191 -15
  81. package/dist/types/components/StorageBrowser/useAction/types.d.ts +60 -32
  82. package/dist/types/components/StorageBrowser/useAction/useHandler.d.ts +4 -3
  83. package/dist/types/components/StorageBrowser/useAction/useList.d.ts +10 -7
  84. package/dist/types/components/StorageBrowser/views/LocationActionView/CopyView/types.d.ts +5 -0
  85. package/dist/types/components/StorageBrowser/views/LocationActionView/UploadView/types.d.ts +2 -2
  86. package/dist/types/components/StorageBrowser/views/LocationActionView/types.d.ts +4 -4
  87. package/dist/types/components/StorageBrowser/views/LocationDetailView/index.d.ts +1 -1
  88. package/dist/types/components/StorageBrowser/views/LocationsView/index.d.ts +1 -1
  89. package/dist/types/components/StorageBrowser/views/context/getViews.d.ts +2 -2
  90. package/dist/types/components/StorageBrowser/views/context/views.d.ts +2 -2
  91. package/dist/types/components/StorageBrowser/views/hooks/usePaginate.d.ts +8 -8
  92. package/dist/types/components/StorageBrowser/views/hooks/useResolveTableData/index.d.ts +2 -0
  93. package/dist/types/components/StorageBrowser/views/hooks/useResolveTableData/types.d.ts +26 -0
  94. package/dist/types/components/StorageBrowser/views/hooks/useResolveTableData/useResolveTableData.d.ts +6 -0
  95. package/dist/types/components/StorageBrowser/views/types.d.ts +1 -1
  96. package/dist/types/components/StorageBrowser/views/useView.d.ts +16 -13
  97. package/dist/types/components/StorageBrowser/views/utils/index.d.ts +1 -0
  98. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/__testUtils__/tasks.d.ts +23 -0
  99. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/constants.d.ts +16 -0
  100. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/copyResolvers.d.ts +3 -0
  101. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/deleteResolvers.d.ts +3 -0
  102. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/index.d.ts +3 -0
  103. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/types.d.ts +36 -0
  104. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/uploadResolvers.d.ts +3 -0
  105. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/utils.d.ts +12 -0
  106. package/dist/types/version.d.ts +1 -1
  107. package/package.json +5 -5
  108. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/utils.mjs +0 -3
  109. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/utils.mjs +0 -3
  110. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/utils.mjs +0 -5
  111. package/dist/esm/components/StorageBrowser/views/LocationActionView/getActionIcon.mjs +0 -25
  112. package/dist/esm/components/StorageBrowser/views/LocationActionView/getActionViewTableData.mjs +0 -141
  113. package/dist/esm/components/StorageBrowser/views/LocationActionView/getDefaultActionViewHeaders.mjs +0 -24
  114. package/dist/esm/components/StorageBrowser/views/LocationActionView/getFileTypeDisplayValue.mjs +0 -5
  115. package/dist/esm/components/StorageBrowser/views/LocationActionView/getPercentValue.mjs +0 -3
  116. package/dist/types/components/StorageBrowser/displayText/en.d.ts +0 -9
  117. package/dist/types/components/StorageBrowser/views/LocationActionView/CopyView/utils.d.ts +0 -3
  118. package/dist/types/components/StorageBrowser/views/LocationActionView/DeleteView/utils.d.ts +0 -3
  119. package/dist/types/components/StorageBrowser/views/LocationActionView/UploadView/utils.d.ts +0 -3
  120. package/dist/types/components/StorageBrowser/views/LocationActionView/getActionIcon.d.ts +0 -3
  121. package/dist/types/components/StorageBrowser/views/LocationActionView/getActionViewTableData.d.ts +0 -14
  122. package/dist/types/components/StorageBrowser/views/LocationActionView/getDefaultActionViewHeaders.d.ts +0 -5
  123. package/dist/types/components/StorageBrowser/views/LocationActionView/getFileTypeDisplayValue.d.ts +0 -1
  124. package/dist/types/components/StorageBrowser/views/LocationActionView/getPercentValue.d.ts +0 -1
@@ -32,7 +32,12 @@ function _interopNamespace(e) {
32
32
 
33
33
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
34
 
35
- const VERSION = '3.9.1';
35
+ const VERSION = '3.9.2';
36
+
37
+ const DEFAULT_CHECKSUM_ALGORITHM = 'crc-32';
38
+ // 5MiB for multipart upload
39
+ // https://github.com/aws-amplify/amplify-js/blob/1a5366d113c9af4ce994168653df3aadb142c581/packages/storage/src/providers/s3/utils/constants.ts#L16
40
+ const MULTIPART_UPLOAD_THRESHOLD_BYTES = 5 * 1024 * 1024;
36
41
 
37
42
  const constructBucket = ({ bucket: bucketName, region, }) => ({ bucketName, region });
38
43
  const parseAccessGrantLocation = (location) => {
@@ -118,9 +123,8 @@ const createFileDataItem = (data) => ({
118
123
  ...data,
119
124
  fileKey: getFileKey(data.key),
120
125
  });
121
- const isFileItem = (value) => !!value.file;
122
- const isFileDataItem = (item) => !!item.fileKey;
123
126
  const getProgress = ({ totalBytes, transferredBytes, }) => totalBytes ? transferredBytes / totalBytes : undefined;
127
+ const isMultipartUpload = (file) => file.size > MULTIPART_UPLOAD_THRESHOLD_BYTES;
124
128
 
125
129
  const copyHandler = (input) => {
126
130
  const { config, data } = input;
@@ -155,12 +159,13 @@ const copyHandler = (input) => {
155
159
  status: 'COMPLETE',
156
160
  value: { key: path },
157
161
  }))
158
- .catch(({ message }) => ({ message, status: 'FAILED' })),
162
+ .catch((error) => {
163
+ const { message } = error;
164
+ return { error, message, status: 'FAILED' };
165
+ }),
159
166
  };
160
167
  };
161
168
 
162
- const DEFAULT_CHECKSUM_ALGORITHM = 'crc-32';
163
-
164
169
  const createFolderHandler = (input) => {
165
170
  const { config, data, options } = input;
166
171
  const { accountId, credentials, customEndpoint } = config;
@@ -189,11 +194,12 @@ const createFolderHandler = (input) => {
189
194
  status: 'COMPLETE',
190
195
  value: { key: path },
191
196
  }))
192
- .catch(({ message, name }) => {
197
+ .catch((error) => {
198
+ const { message, name } = error;
193
199
  if (name === 'PreconditionFailed') {
194
- return { message, status: 'OVERWRITE_PREVENTED' };
200
+ return { error, message, status: 'OVERWRITE_PREVENTED' };
195
201
  }
196
- return { message, status: 'FAILED' };
202
+ return { error, message, status: 'FAILED' };
197
203
  }),
198
204
  };
199
205
  };
@@ -214,7 +220,10 @@ const deleteHandler = ({ config, data, }) => {
214
220
  status: 'COMPLETE',
215
221
  value: { key: path },
216
222
  }))
217
- .catch(({ message }) => ({ message, status: 'FAILED' }));
223
+ .catch((error) => {
224
+ const { message } = error;
225
+ return { error, message, status: 'FAILED' };
226
+ });
218
227
  return { result };
219
228
  };
220
229
 
@@ -244,11 +253,14 @@ const downloadHandler = ({ config, data: { key }, }) => {
244
253
  downloadFromUrl(key, url.toString());
245
254
  return { status: 'COMPLETE', value: { url } };
246
255
  })
247
- .catch(({ message }) => ({ message, status: 'FAILED' }));
256
+ .catch((error) => {
257
+ const { message } = error;
258
+ return { error, message, status: 'FAILED' };
259
+ });
248
260
  return { result };
249
261
  };
250
262
 
251
- const DEFAULT_PAGE_SIZE$3 = 1000;
263
+ const DEFAULT_PAGE_SIZE$4 = 1000;
252
264
  const parseItems = (items, excludedPath) => items
253
265
  // remove root `key` from results
254
266
  .filter(({ path }) => path !== excludedPath)
@@ -281,7 +293,7 @@ const parseResult = ({ excludedSubpaths, items }, prefix) => filterDotItems([...
281
293
  const listLocationItemsHandler = async (input) => {
282
294
  const { config, prefix, options } = input;
283
295
  const { bucket: _bucket, credentials, customEndpoint, region, accountId, } = config;
284
- const { exclude, delimiter, nextToken, pageSize: _pageSize = DEFAULT_PAGE_SIZE$3, ..._options } = options ?? {};
296
+ const { exclude, delimiter, nextToken, pageSize: _pageSize = DEFAULT_PAGE_SIZE$4, ..._options } = options ?? {};
285
297
  const bucket = { bucketName: _bucket, region };
286
298
  const subpathStrategy = {
287
299
  delimiter,
@@ -318,39 +330,6 @@ const listLocationItemsHandler = async (input) => {
318
330
  return { items: result, nextToken: nextNextToken };
319
331
  };
320
332
 
321
- function assertLocationPermissions(value, message) {
322
- if (!Array.isArray(value) ||
323
- value.some((inputPermissionEntry) => typeof inputPermissionEntry !== 'string' ||
324
- !['list', 'get', 'write', 'delete'].includes(inputPermissionEntry))) {
325
- throw new Error(message);
326
- }
327
- }
328
- function assertLocationData(value, message = 'Invalid value provided as `location`.') {
329
- const locationStringDataKeys = ['bucket', 'id', 'prefix', 'type'];
330
- if (!ui.isObject(value) ||
331
- locationStringDataKeys.some((key) => !ui.isString(value[key]))) {
332
- throw new Error(message);
333
- }
334
- assertLocationPermissions(value?.permissions, message);
335
- }
336
- function assertPrefix(value, message) {
337
- if (!ui.isString(value)) {
338
- throw new Error(message ?? 'Invalid value provided as `prefix`.');
339
- }
340
- }
341
-
342
- function assertRegisterAuthListener(value) {
343
- if (!ui.isFunction(value)) {
344
- throw new Error('StorageBrowser: `registerAuthListener` must be a function.');
345
- }
346
- }
347
-
348
- const UPLOAD_FILE_SIZE_LIMIT = 160 * 1000 * 1000 * 1000;
349
- const isFileTooBig = (file) => file.size > UPLOAD_FILE_SIZE_LIMIT;
350
-
351
- // 5MB for multipart upload
352
- // https://github.com/aws-amplify/amplify-js/blob/1a5366d113c9af4ce994168653df3aadb142c581/packages/storage/src/providers/s3/utils/constants.ts#L16
353
- const MULTIPART_UPLOAD_THRESHOLD_BYTES = 5 * 1024 * 1024;
354
333
  const UNDEFINED_CALLBACKS = {
355
334
  cancel: undefined,
356
335
  pause: undefined,
@@ -378,7 +357,7 @@ const uploadHandler = ({ config, data, options }) => {
378
357
  };
379
358
  const { cancel, pause, resume, result } = internals.uploadData(input);
380
359
  return {
381
- ...(file.size > MULTIPART_UPLOAD_THRESHOLD_BYTES
360
+ ...(isMultipartUpload(file)
382
361
  ? { cancel, pause, resume }
383
362
  : UNDEFINED_CALLBACKS),
384
363
  result: result
@@ -389,16 +368,53 @@ const uploadHandler = ({ config, data, options }) => {
389
368
  .catch((error) => {
390
369
  const { message } = error;
391
370
  if (error.name === 'PreconditionFailed') {
392
- return { message, status: 'OVERWRITE_PREVENTED' };
371
+ return { error, message, status: 'OVERWRITE_PREVENTED' };
393
372
  }
394
- return {
395
- message,
396
- status: storage.isCancelError(error) ? 'CANCELED' : 'FAILED',
397
- };
373
+ const status = storage.isCancelError(error) ? 'CANCELED' : 'FAILED';
374
+ return { error, message, status };
398
375
  }),
399
376
  };
400
377
  };
401
378
 
379
+ const defaultHandlers = {
380
+ copy: copyHandler,
381
+ createFolder: createFolderHandler,
382
+ delete: deleteHandler,
383
+ download: downloadHandler,
384
+ listLocationItems: listLocationItemsHandler,
385
+ upload: uploadHandler,
386
+ };
387
+
388
+ function assertLocationPermissions(value, message) {
389
+ if (!Array.isArray(value) ||
390
+ value.some((inputPermissionEntry) => typeof inputPermissionEntry !== 'string' ||
391
+ !['list', 'get', 'write', 'delete'].includes(inputPermissionEntry))) {
392
+ throw new Error(message);
393
+ }
394
+ }
395
+ function assertLocationData(value, message = 'Invalid value provided as `location`.') {
396
+ const locationStringDataKeys = ['bucket', 'id', 'prefix', 'type'];
397
+ if (!ui.isObject(value) ||
398
+ locationStringDataKeys.some((key) => !ui.isString(value[key]))) {
399
+ throw new Error(message);
400
+ }
401
+ assertLocationPermissions(value?.permissions, message);
402
+ }
403
+ function assertPrefix(value, message) {
404
+ if (!ui.isString(value)) {
405
+ throw new Error(message ?? 'Invalid value provided as `prefix`.');
406
+ }
407
+ }
408
+
409
+ function assertRegisterAuthListener(value) {
410
+ if (!ui.isFunction(value)) {
411
+ throw new Error('StorageBrowser: `registerAuthListener` must be a function.');
412
+ }
413
+ }
414
+
415
+ const UPLOAD_FILE_SIZE_LIMIT = 160 * 1000 * 1000 * 1000;
416
+ const isFileTooBig = (file) => file.size > UPLOAD_FILE_SIZE_LIMIT;
417
+
402
418
  const defaultValue$9 = {
403
419
  actionConfigs: undefined,
404
420
  };
@@ -412,7 +428,7 @@ const copyActionConfig = {
412
428
  icon: 'copy-file',
413
429
  label: 'Copy',
414
430
  },
415
- handler: copyHandler,
431
+ handler: defaultHandlers.copy,
416
432
  };
417
433
  const deleteActionConfig = {
418
434
  viewName: 'DeleteView',
@@ -422,7 +438,7 @@ const deleteActionConfig = {
422
438
  icon: 'delete-file',
423
439
  label: 'Delete',
424
440
  },
425
- handler: deleteHandler,
441
+ handler: defaultHandlers.delete,
426
442
  };
427
443
  const createFolderActionConfig = {
428
444
  viewName: 'CreateFolderView',
@@ -431,7 +447,7 @@ const createFolderActionConfig = {
431
447
  icon: 'create-folder',
432
448
  label: 'Create folder',
433
449
  },
434
- handler: createFolderHandler,
450
+ handler: defaultHandlers.createFolder,
435
451
  };
436
452
  const uploadActionConfig = {
437
453
  viewName: 'UploadView',
@@ -440,12 +456,14 @@ const uploadActionConfig = {
440
456
  icon: 'upload-file',
441
457
  label: 'Upload',
442
458
  },
443
- handler: uploadHandler,
459
+ handler: defaultHandlers.upload,
444
460
  };
461
+ // Action view configs only, does not include `listLocationItems`
445
462
  const defaultActionViewConfigs = {
446
463
  copy: copyActionConfig,
447
464
  createFolder: createFolderActionConfig,
448
- download: downloadHandler,
465
+ // provide `download` handler only; `download` does not have a dedicated view/config
466
+ download: defaultHandlers.download,
449
467
  delete: deleteActionConfig,
450
468
  upload: uploadActionConfig,
451
469
  };
@@ -453,7 +471,7 @@ const DEFAULT_ACTION_VIEW_TYPES = Object.keys(defaultActionViewConfigs);
453
471
  const isDefaultActionViewType = (value) => DEFAULT_ACTION_VIEW_TYPES.some((type) => type === value);
454
472
  const defaultActionConfigs = {
455
473
  ...defaultActionViewConfigs,
456
- listLocationItems: listLocationItemsHandler,
474
+ listLocationItems: defaultHandlers.listLocationItems,
457
475
  };
458
476
 
459
477
  const isActionConfig = (value) => ui.isObject(value);
@@ -1084,7 +1102,7 @@ const OverwriteToggle = ({ isDisabled, isOverwritingEnabled, label = '', onToggl
1084
1102
  onToggle?.();
1085
1103
  } }));
1086
1104
  };
1087
- const SearchSubfoldersToggle = ({ isSearchingSubfolders, label = '', onToggle, }) => {
1105
+ const SearchSubfoldersToggle = ({ isSearchingSubfolders, label = '', onToggle }) => {
1088
1106
  return (React__namespace.createElement(uiReact.CheckboxField, { name: label, label: label, labelPosition: "end", checked: isSearchingSubfolders, onChange: () => {
1089
1107
  onToggle?.();
1090
1108
  } }));
@@ -1114,7 +1132,7 @@ const Navigation = ({ items }) => {
1114
1132
  item.isCurrent ? null : React__namespace.createElement(uiReact.Breadcrumbs.Separator, null)));
1115
1133
  })));
1116
1134
  };
1117
- const LoadingIndicator = ({ isLoading }) => {
1135
+ const LoadingIndicator = ({ isLoading, }) => {
1118
1136
  if (isLoading) {
1119
1137
  return (React__namespace.createElement(uiReact.Loader, { className: "amplify-storage-browser__loader", variation: "linear", size: "small" }));
1120
1138
  }
@@ -1129,7 +1147,7 @@ const FolderNameField = ({ onChange, label, placeholder, validationMessage, onVa
1129
1147
  onChange?.(value);
1130
1148
  } }));
1131
1149
  };
1132
- const DataRefresh = ({ onRefresh }) => {
1150
+ const DataRefresh = ({ onRefresh, }) => {
1133
1151
  return (React__namespace.createElement(uiReact.Button, { onClick: () => {
1134
1152
  onRefresh?.();
1135
1153
  }, "aria-label": "Refresh data" },
@@ -1147,7 +1165,7 @@ const ActionsList = ({ items, onActionSelect, isDisabled, }) => {
1147
1165
  label));
1148
1166
  })));
1149
1167
  };
1150
- const StatusDisplay = ({ statuses, total }) => {
1168
+ const StatusDisplay = ({ statuses, total, }) => {
1151
1169
  if (!statuses?.length) {
1152
1170
  return null;
1153
1171
  }
@@ -1203,7 +1221,6 @@ const DEFAULT_ACTION_VIEW_DISPLAY_TEXT = {
1203
1221
  tableColumnNameHeader: 'Name',
1204
1222
  tableColumnTypeHeader: 'Type',
1205
1223
  tableColumnSizeHeader: 'Size',
1206
- tableColumnProgressHeader: 'Progress',
1207
1224
  };
1208
1225
  const DEFAULT_LIST_VIEW_DISPLAY_TEXT = {
1209
1226
  loadingIndicatorLabel: 'Loading',
@@ -1433,7 +1450,6 @@ const DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT = {
1433
1450
 
1434
1451
  const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT = {
1435
1452
  ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
1436
- title: 'Upload',
1437
1453
  actionStartLabel: 'Upload',
1438
1454
  addFilesLabel: 'Add files',
1439
1455
  addFolderLabel: 'Add folder',
@@ -1509,8 +1525,10 @@ const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT = {
1509
1525
  }
1510
1526
  return undefined;
1511
1527
  },
1512
- statusDisplayOverwritePreventedLabel: 'Overwrite prevented',
1513
1528
  overwriteToggleLabel: 'Overwrite existing files',
1529
+ statusDisplayOverwritePreventedLabel: 'Overwrite prevented',
1530
+ tableColumnProgressHeader: 'Progress',
1531
+ title: 'Upload',
1514
1532
  };
1515
1533
 
1516
1534
  const DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT = {
@@ -1561,6 +1579,9 @@ function DisplayTextProvider({ children, displayText: _override, }) {
1561
1579
  return (React__namespace["default"].createElement(DisplayTextContext.Provider, { value: resolvedDisplayText }, children));
1562
1580
  }
1563
1581
 
1582
+ const isCopyViewDisplayTextKey = (value) => !!DEFAULT_COPY_VIEW_DISPLAY_TEXT[value];
1583
+ const isDeleteViewDisplayTextKey = (value) => !!DEFAULT_DELETE_VIEW_DISPLAY_TEXT[value];
1584
+
1564
1585
  const Fallback = () => (React__namespace["default"].createElement("div", { className: STORAGE_BROWSER_BLOCK_TO_BE_UPDATED },
1565
1586
  React__namespace["default"].createElement("div", { className: `${STORAGE_BROWSER_BLOCK_TO_BE_UPDATED}__error-boundary` }, "Something went wrong.")));
1566
1587
  class ErrorBoundary extends React__namespace["default"].Component {
@@ -2464,197 +2485,342 @@ const TitleControl = () => {
2464
2485
  return React__namespace["default"].createElement(Resolved, { ...props });
2465
2486
  };
2466
2487
 
2467
- const getActionIcon = (status) => {
2468
- switch (status) {
2469
- case 'PENDING': {
2470
- return 'action-progress';
2471
- }
2472
- case 'COMPLETE': {
2473
- return 'action-success';
2474
- }
2475
- case 'FAILED': {
2476
- return 'action-error';
2477
- }
2478
- case 'OVERWRITE_PREVENTED': {
2479
- return 'action-info';
2480
- }
2481
- case 'CANCELED': {
2482
- return 'action-canceled';
2483
- }
2484
- case 'QUEUED':
2485
- default: {
2486
- return 'action-queued';
2487
- }
2488
- }
2489
- };
2490
-
2491
- const getFileTypeDisplayValue = (fileName) => fileName.lastIndexOf('.') !== -1
2492
- ? fileName.slice(fileName.lastIndexOf('.') + 1)
2493
- : '';
2488
+ function useResolveDataTable(keys, { getCell, getHeader, getRowKey }, { items, props }) {
2489
+ return React__namespace["default"].useMemo(() => {
2490
+ const getRow = (item) => ({
2491
+ key: getRowKey({ item, props }),
2492
+ content: keys.map((key) => getCell({ key, item, props })),
2493
+ });
2494
+ const headers = keys.map((key) => getHeader({ key, props }));
2495
+ const rows = (items ?? []).map(getRow);
2496
+ return { headers, rows };
2497
+ }, [getCell, getHeader, getRowKey, keys, items, props]);
2498
+ }
2494
2499
 
2495
- const getPercentValue = (value) => Math.round(value * 100);
2500
+ const STATUS_LABELS = {
2501
+ PENDING: 'statusDisplayInProgressLabel',
2502
+ CANCELED: 'statusDisplayCanceledLabel',
2503
+ COMPLETE: 'statusDisplayCompletedLabel',
2504
+ FAILED: 'statusDisplayFailedLabel',
2505
+ QUEUED: 'statusDisplayQueuedLabel',
2506
+ OVERWRITE_PREVENTED: 'statusDisplayOverwritePreventedLabel',
2507
+ };
2508
+ const STATUS_ICONS = {
2509
+ PENDING: 'action-progress',
2510
+ COMPLETE: 'action-success',
2511
+ FAILED: 'action-error',
2512
+ OVERWRITE_PREVENTED: 'action-info',
2513
+ CANCELED: 'action-canceled',
2514
+ QUEUED: 'action-queued',
2515
+ };
2516
+
2517
+ const getFileType = (value, fallback = '') => value.lastIndexOf('.') !== -1
2518
+ ? value.slice(value.lastIndexOf('.') + 1)
2519
+ : fallback;
2520
+ const getCellName = (value) =>
2521
+ // `value.split` always returns an array with at least one entry
2522
+ // ensruing `.pop()` will always return a string
2523
+ value.split('/').pop();
2524
+ const getUploadCellFolder = ({ data: { file: { webkitRelativePath }, }, }, fallback = '-') => webkitRelativePath
2525
+ ? webkitRelativePath.slice(0, webkitRelativePath.lastIndexOf('/') + 1)
2526
+ : fallback;
2527
+ const getCopyCellFolder = ({ data: { fileKey, sourceKey }, }) => sourceKey.slice(0, -fileKey.length);
2528
+ const getDeleteCellFolder = ({ data: { fileKey, key }, }) => key.slice(0, -fileKey.length);
2529
+ const getUploadCellProgress = ({ progress, status, }) => {
2530
+ // prefer `progress` if available, 1 if status is complete, default 0
2531
+ const value = progress ?? (status === 'COMPLETE' ? 1 : 0);
2532
+ const displayValue = `${Math.round(value * 100)}%`;
2533
+ return { displayValue, value };
2534
+ };
2535
+ const getFileSize = (value, fallback = '-') => (!value ? fallback : ui.humanFileSize(value, true));
2536
+ const getCopyOrDeleteCancelCellContent = (data) => {
2537
+ const { item, props } = data;
2538
+ const { cancel, status } = item;
2539
+ const { isProcessing, onTaskRemove } = props;
2540
+ const isQueued = status === 'QUEUED';
2541
+ // a task is removable prior to processing start. Including `isQueued` ensures
2542
+ // that `isRemovable` is `false` on all tasks processing complete
2543
+ const isRemovable = isQueued && !isProcessing;
2544
+ // a task is cancelable while processing is true, and the task has a cancel handler
2545
+ const isCancelable = isProcessing && !!cancel;
2546
+ const ariaLabel = `${isRemovable ? 'Remove' : 'Cancel'} item: ${getCellName(item.data.fileKey)}`;
2547
+ const isDisabled = !isRemovable && !isCancelable;
2548
+ // resolve to `undefined` if not cancelable or removable
2549
+ const onClick = !isCancelable && !isRemovable
2550
+ ? undefined
2551
+ : () => {
2552
+ if (isRemovable) {
2553
+ onTaskRemove?.(item);
2554
+ // do not run cancel handler on remove
2555
+ return;
2556
+ }
2557
+ if (isCancelable)
2558
+ cancel();
2559
+ };
2560
+ return { ariaLabel, isDisabled, onClick, icon: 'cancel' };
2561
+ };
2496
2562
 
2497
- const getDefaultActionViewHeaders = ({ displayText: { tableColumnNameHeader, tableColumnTypeHeader, tableColumnSizeHeader, tableColumnStatusHeader, tableColumnCancelHeader, tableColumnFolderHeader, }, }) => {
2498
- return [
2499
- {
2500
- key: 'name',
2501
- type: 'sort',
2502
- content: { label: tableColumnNameHeader },
2503
- },
2504
- {
2505
- key: 'folder',
2506
- type: 'sort',
2507
- content: { label: tableColumnFolderHeader },
2508
- },
2509
- { key: 'type', type: 'sort', content: { label: tableColumnTypeHeader } },
2510
- { key: 'size', type: 'sort', content: { label: tableColumnSizeHeader } },
2511
- {
2512
- key: 'status',
2513
- type: 'sort',
2514
- content: { label: tableColumnStatusHeader },
2515
- },
2516
- { key: 'cancel', type: 'text', content: { text: tableColumnCancelHeader } },
2517
- ];
2563
+ const COPY_TABLE_KEYS = [
2564
+ 'name',
2565
+ 'folder',
2566
+ 'type',
2567
+ 'size',
2568
+ 'status',
2569
+ 'cancel',
2570
+ ];
2571
+ const getCopyCellKey = ({ key, item, }) => `${key}-${item.data.id}`;
2572
+ const name$2 = (data) => {
2573
+ const key = getCopyCellKey(data);
2574
+ const { item } = data;
2575
+ const text = item.data.fileKey;
2576
+ const icon = STATUS_ICONS[item.status];
2577
+ return { key, type: 'text', content: { icon, text } };
2578
+ };
2579
+ const folder$2 = (data) => {
2580
+ const key = getCopyCellKey(data);
2581
+ const text = getCopyCellFolder(data.item);
2582
+ return { key, type: 'text', content: { text } };
2583
+ };
2584
+ const type$2 = (data) => {
2585
+ const key = getCopyCellKey(data);
2586
+ const { fileKey } = data.item.data;
2587
+ const text = getFileType(fileKey);
2588
+ return { key, type: 'text', content: { text } };
2589
+ };
2590
+ const size$2 = (data) => {
2591
+ const key = getCopyCellKey(data);
2592
+ const { size: value } = data.item.data;
2593
+ const displayValue = getFileSize(value);
2594
+ return { key, type: 'number', content: { value, displayValue } };
2595
+ };
2596
+ const status$2 = (data) => {
2597
+ const key = getCopyCellKey(data);
2598
+ const { item: { status }, props: { displayText }, } = data;
2599
+ const statusLabelKey = STATUS_LABELS[status];
2600
+ const text = isCopyViewDisplayTextKey(statusLabelKey)
2601
+ ? displayText[statusLabelKey]
2602
+ : '';
2603
+ return { key, type: 'text', content: { text } };
2604
+ };
2605
+ const cancel$2 = (data) => {
2606
+ const key = getCopyCellKey(data);
2607
+ const content = getCopyOrDeleteCancelCellContent(data);
2608
+ return { key, type: 'button', content };
2609
+ };
2610
+ const COPY_CELL_RESOLVERS = {
2611
+ name: name$2,
2612
+ folder: folder$2,
2613
+ type: type$2,
2614
+ size: size$2,
2615
+ status: status$2,
2616
+ cancel: cancel$2,
2617
+ /**
2618
+ * @deprecated
2619
+ *
2620
+ * non-upload view tables do not include "progress" headers but include here to
2621
+ * keep TS happy as "progress" headers were included in display text interfaces
2622
+ * and cannot be removed from the tables without a breaking change
2623
+ */
2624
+ progress: ui.noop,
2625
+ };
2626
+ const COPY_TABLE_RESOLVERS = {
2627
+ getCell: (data) => COPY_CELL_RESOLVERS[data.key](data),
2628
+ getHeader: ({ key, props: { displayText } }) => {
2629
+ const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
2630
+ if (key === 'cancel') {
2631
+ return { key, type: 'text', content: { text } };
2632
+ }
2633
+ return { key, type: 'sort', content: { label: text } };
2634
+ },
2635
+ getRowKey: ({ item }) => item.data.id,
2518
2636
  };
2519
2637
 
2520
- const getTaskStatusDisplayLabel = ({ status, displayText: { statusDisplayInProgressLabel, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, statusDisplayOverwritePreventedLabel, }, }) => {
2521
- switch (status) {
2522
- case 'PENDING':
2523
- return statusDisplayInProgressLabel;
2524
- case 'CANCELED':
2525
- return statusDisplayCanceledLabel;
2526
- case 'COMPLETE':
2527
- return statusDisplayCompletedLabel;
2528
- case 'FAILED':
2529
- return statusDisplayFailedLabel;
2530
- case 'QUEUED':
2531
- return statusDisplayQueuedLabel;
2532
- case 'OVERWRITE_PREVENTED':
2533
- return statusDisplayOverwritePreventedLabel;
2534
- default:
2535
- return statusDisplayQueuedLabel;
2638
+ const UPLOAD_TABLE_KEYS = [
2639
+ 'name',
2640
+ 'folder',
2641
+ 'type',
2642
+ 'size',
2643
+ 'status',
2644
+ 'progress',
2645
+ 'cancel',
2646
+ ];
2647
+ const getUploadCellKey = ({ key, item, }) => `${key}-${item.data.id}`;
2648
+ const name$1 = (data) => {
2649
+ const key = getUploadCellKey(data);
2650
+ const { item } = data;
2651
+ const icon = STATUS_ICONS[item.status];
2652
+ const text = getCellName(item.data.key);
2653
+ return { key, type: 'text', content: { icon, text } };
2654
+ };
2655
+ const folder$1 = (data) => {
2656
+ const key = getUploadCellKey(data);
2657
+ const text = getUploadCellFolder(data.item);
2658
+ return { key, type: 'text', content: { text } };
2659
+ };
2660
+ const type$1 = (data) => {
2661
+ const key = getUploadCellKey(data);
2662
+ const { item } = data;
2663
+ const text = getFileType(getCellName(item.data.key));
2664
+ return { key, type: 'text', content: { text } };
2665
+ };
2666
+ const size$1 = (data) => {
2667
+ const key = getUploadCellKey(data);
2668
+ const { size: value } = data.item.data.file;
2669
+ const displayValue = getFileSize(value);
2670
+ return { key, type: 'number', content: { value, displayValue } };
2671
+ };
2672
+ const status$1 = (data) => {
2673
+ const key = getUploadCellKey(data);
2674
+ const { item: { status }, props: { displayText }, } = data;
2675
+ const text = displayText[STATUS_LABELS[status]];
2676
+ return { key, type: 'text', content: { text } };
2677
+ };
2678
+ const progress = (data) => {
2679
+ const key = getUploadCellKey(data);
2680
+ const content = getUploadCellProgress(data.item);
2681
+ return { key, type: 'number', content };
2682
+ };
2683
+ const cancel$1 = (data) => {
2684
+ const key = getUploadCellKey(data);
2685
+ const { item, props } = data;
2686
+ const { cancel, data: taskData, status, progress } = item;
2687
+ const { isMultipartUpload, isProcessing, onTaskRemove } = props;
2688
+ const isQueued = status === 'QUEUED';
2689
+ const isPending = status === 'PENDING';
2690
+ // cancelability is dependent on differing conditions for multipart and single part uploads
2691
+ let isCancelable;
2692
+ if (isMultipartUpload(taskData.file)) {
2693
+ // signals MPU complete has been reached
2694
+ const hasUploadedAllBytes = progress === 1;
2695
+ // MPU allows cancel when tasks processing has begun and task is queued or
2696
+ // pending but not yet reached MPU complete
2697
+ isCancelable =
2698
+ isProcessing && (isQueued || isPending) && !hasUploadedAllBytes;
2536
2699
  }
2537
- };
2538
- const getProgressHeader = (label) => ({
2539
- key: 'progress',
2540
- type: 'sort',
2541
- content: { label },
2542
- });
2543
- const getActionViewTableData = ({ tasks, displayText, getFolderText, isProcessing, shouldDisplayProgress = false, onTaskRemove, }) => {
2544
- const headers = [
2545
- ...getDefaultActionViewHeaders({
2546
- displayText,
2547
- }),
2548
- ];
2549
- if (shouldDisplayProgress) {
2550
- headers.splice(-1, 0, getProgressHeader(displayText.tableColumnProgressHeader));
2700
+ else {
2701
+ // single part upload allows cancel when processing has begun and task is queued
2702
+ isCancelable = isProcessing && isQueued;
2551
2703
  }
2552
- const rows = tasks.map((task) => {
2553
- const { cancel, data, progress, status } = task;
2554
- const { id } = data;
2555
- const displayKey = isFileDataItem(data)
2556
- ? data.fileKey
2557
- : data.key.split('/').pop() ?? '';
2558
- return {
2559
- key: id,
2560
- content: headers.map(({ key: columnKey }) => {
2561
- const key = `${columnKey}-${id}`;
2562
- switch (columnKey) {
2563
- case 'name': {
2564
- return {
2565
- key,
2566
- type: 'text',
2567
- content: {
2568
- icon: getActionIcon(status),
2569
- text: displayKey,
2570
- },
2571
- };
2572
- }
2573
- case 'folder': {
2574
- const text = getFolderText?.(task) ?? '/';
2575
- return { key, type: 'text', content: { text } };
2576
- }
2577
- case 'type': {
2578
- return {
2579
- key,
2580
- type: 'text',
2581
- content: { text: getFileTypeDisplayValue(displayKey) },
2582
- };
2583
- }
2584
- case 'size': {
2585
- const value = isFileItem(data)
2586
- ? data.file.size
2587
- : isFileDataItem(data)
2588
- ? data.size
2589
- : undefined;
2590
- return {
2591
- key,
2592
- type: 'number',
2593
- content: {
2594
- value,
2595
- displayValue: value ? ui.humanFileSize(value, true) : '-',
2596
- },
2597
- };
2598
- }
2599
- case 'status': {
2600
- return {
2601
- key,
2602
- type: 'text',
2603
- content: {
2604
- text: getTaskStatusDisplayLabel({ status, displayText }),
2605
- },
2606
- };
2607
- }
2608
- case 'progress': {
2609
- return {
2610
- key,
2611
- type: 'number',
2612
- content: {
2613
- value: progress,
2614
- displayValue: `${getPercentValue(
2615
- // Default progress to 100% if progress value is unavailable but status is recognized as complete
2616
- progress ?? (status === 'COMPLETE' ? 1 : 0))}%`,
2617
- },
2618
- };
2619
- }
2620
- case 'cancel': {
2621
- const isPending = status === 'PENDING';
2622
- const isQueued = status === 'QUEUED';
2623
- const isDisabled = (!isPending && !isQueued) || !cancel || progress === 1;
2624
- const ariaLabel = `${isProcessing ? 'Cancel' : 'Remove'} item: ${displayKey}`;
2625
- return {
2626
- key,
2627
- type: 'button',
2628
- content: {
2629
- isDisabled,
2630
- onClick: () => {
2631
- if (!isProcessing) {
2632
- onTaskRemove?.(task);
2633
- }
2634
- cancel?.();
2635
- },
2636
- ariaLabel,
2637
- icon: 'cancel',
2638
- },
2639
- };
2640
- }
2641
- default:
2642
- return { key, type: 'text', content: {} };
2643
- }
2644
- }),
2704
+ // all uploads are removable prior to processing start. Including `isQueued`
2705
+ // ensures that `isRemovable` is `false` on all tasks processing complete
2706
+ const isRemovable = !isProcessing && isQueued;
2707
+ const isDisabled = !isRemovable && !isCancelable;
2708
+ const ariaLabel = `${isRemovable ? 'Remove' : 'Cancel'} item: ${getCellName(item.data.key)}`;
2709
+ // resolve to `undefined` if not cancelable or removable
2710
+ const onClick = !isCancelable && !isRemovable
2711
+ ? undefined
2712
+ : () => {
2713
+ if (isRemovable) {
2714
+ onTaskRemove?.(item);
2715
+ // do not run cancel handler on remove
2716
+ return;
2717
+ }
2718
+ if (!!cancel && isCancelable)
2719
+ cancel();
2645
2720
  };
2646
- });
2647
- return { headers, rows };
2721
+ const content = { ariaLabel, isDisabled, onClick, icon: 'cancel' };
2722
+ return { key, type: 'button', content };
2723
+ };
2724
+ const UPLOAD_CELL_RESOLVERS = {
2725
+ cancel: cancel$1,
2726
+ folder: folder$1,
2727
+ name: name$1,
2728
+ progress,
2729
+ size: size$1,
2730
+ status: status$1,
2731
+ type: type$1,
2732
+ };
2733
+ const UPLOAD_TABLE_RESOLVERS = {
2734
+ getCell: (data) => UPLOAD_CELL_RESOLVERS[data.key](data),
2735
+ getHeader: ({ key, props: { displayText } }) => {
2736
+ const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
2737
+ if (key === 'cancel') {
2738
+ return { key, type: 'text', content: { text } };
2739
+ }
2740
+ return { key, type: 'sort', content: { label: text } };
2741
+ },
2742
+ getRowKey: ({ item }) => item.data.id,
2648
2743
  };
2649
2744
 
2650
- const getFolderText$2 = ({ data: { file: { webkitRelativePath }, }, }) => webkitRelativePath
2651
- ? webkitRelativePath.slice(0, webkitRelativePath.lastIndexOf('/') + 1)
2652
- : '-';
2745
+ const DELETE_TABLE_KEYS = [
2746
+ 'name',
2747
+ 'folder',
2748
+ 'type',
2749
+ 'size',
2750
+ 'status',
2751
+ 'cancel',
2752
+ ];
2753
+ const getDeleteCellKey = ({ key, item, }) => `${key}-${item.data.id}`;
2754
+ const name = (data) => {
2755
+ const key = getDeleteCellKey(data);
2756
+ const { item } = data;
2757
+ const text = item.data.fileKey;
2758
+ const icon = STATUS_ICONS[item.status];
2759
+ return { key, type: 'text', content: { icon, text } };
2760
+ };
2761
+ const folder = (data) => {
2762
+ const key = getDeleteCellKey(data);
2763
+ const text = getDeleteCellFolder(data.item);
2764
+ return { key, type: 'text', content: { text } };
2765
+ };
2766
+ const type = (data) => {
2767
+ const key = getDeleteCellKey(data);
2768
+ const { fileKey } = data.item.data;
2769
+ const text = getFileType(fileKey);
2770
+ return { key, type: 'text', content: { text } };
2771
+ };
2772
+ const size = (data) => {
2773
+ const key = getDeleteCellKey(data);
2774
+ const { size: value } = data.item.data;
2775
+ const displayValue = getFileSize(value);
2776
+ return { key, type: 'number', content: { value, displayValue } };
2777
+ };
2778
+ const status = (data) => {
2779
+ const key = getDeleteCellKey(data);
2780
+ const { item: { status }, props: { displayText }, } = data;
2781
+ const statusLabelKey = STATUS_LABELS[status];
2782
+ const text = isDeleteViewDisplayTextKey(statusLabelKey)
2783
+ ? displayText[statusLabelKey]
2784
+ : '';
2785
+ return { key, type: 'text', content: { text } };
2786
+ };
2787
+ const cancel = (data) => {
2788
+ const key = getDeleteCellKey(data);
2789
+ const content = getCopyOrDeleteCancelCellContent(data);
2790
+ return { key, type: 'button', content };
2791
+ };
2792
+ const DELETE_CELL_RESOLVERS = {
2793
+ name,
2794
+ folder,
2795
+ type,
2796
+ size,
2797
+ status,
2798
+ cancel,
2799
+ /**
2800
+ * @deprecated
2801
+ *
2802
+ * non-upload view tables do not include "progress" headers but include here to
2803
+ * keep TS happy as "progress" headers were included in display text interfaces
2804
+ * and cannot be removed from the tables without a breaking change
2805
+ */
2806
+ progress: ui.noop,
2807
+ };
2808
+ const DELETE_TABLE_RESOLVERS = {
2809
+ getCell: (data) => DELETE_CELL_RESOLVERS[data.key](data),
2810
+ getHeader: ({ key, props: { displayText } }) => {
2811
+ const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
2812
+ if (key === 'cancel') {
2813
+ return { key, type: 'text', content: { text } };
2814
+ }
2815
+ return { key, type: 'sort', content: { label: text } };
2816
+ },
2817
+ getRowKey: ({ item }) => item.data.id,
2818
+ };
2653
2819
 
2654
2820
  function UploadViewProvider({ children, ...props }) {
2655
2821
  const { UploadView: displayText } = useDisplayText();
2656
2822
  const { actionCancelLabel, actionDestinationLabel, actionExitLabel, actionStartLabel, addFilesLabel, addFolderLabel, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, overwriteToggleLabel, title, getActionCompleteMessage, getFilesValidationMessage, } = displayText;
2657
- const { isOverwritingEnabled, isProcessing, isProcessingComplete, location, tasks, statusCounts, invalidFiles, onActionStart, onActionCancel, onDropFiles, onActionExit, onTaskRemove, onSelectFiles, onToggleOverwrite, } = props;
2823
+ const { isOverwritingEnabled, isProcessing, isProcessingComplete, location, tasks: items, statusCounts, invalidFiles, onActionStart, onActionCancel, onDropFiles, onActionExit, onTaskRemove, onSelectFiles, onToggleOverwrite, } = props;
2658
2824
  const isActionStartDisabled = isProcessing || isProcessingComplete || statusCounts.TOTAL === 0;
2659
2825
  const isActionCancelDisabled = !isProcessing || isProcessingComplete;
2660
2826
  const isAddFilesDisabled = isProcessing || isProcessingComplete;
@@ -2668,6 +2834,10 @@ function UploadViewProvider({ children, ...props }) {
2668
2834
  const filesValidationMessage = invalidFiles && !isProcessing
2669
2835
  ? getFilesValidationMessage({ invalidFiles })
2670
2836
  : undefined;
2837
+ const tableData = useResolveDataTable(UPLOAD_TABLE_KEYS, UPLOAD_TABLE_RESOLVERS, {
2838
+ items,
2839
+ props: { displayText, isProcessing, isMultipartUpload, onTaskRemove },
2840
+ });
2671
2841
  return (React__namespace["default"].createElement(ControlsContextProvider, { data: {
2672
2842
  actionCancelLabel,
2673
2843
  actionDestinationLabel,
@@ -2691,14 +2861,7 @@ function UploadViewProvider({ children, ...props }) {
2691
2861
  statusDisplayCompletedLabel,
2692
2862
  statusDisplayFailedLabel,
2693
2863
  statusDisplayQueuedLabel,
2694
- tableData: getActionViewTableData({
2695
- getFolderText: getFolderText$2,
2696
- tasks,
2697
- shouldDisplayProgress: true,
2698
- displayText,
2699
- isProcessing,
2700
- onTaskRemove,
2701
- }),
2864
+ tableData,
2702
2865
  title,
2703
2866
  }, onActionCancel: onActionCancel, onActionExit: onActionExit, onActionStart: onActionStart, onAddFiles: () => {
2704
2867
  onSelectFiles('FILE');
@@ -2834,6 +2997,9 @@ const createEnhancedListHandler = (action) => {
2834
2997
  };
2835
2998
  };
2836
2999
 
3000
+ const DEFAULT_ACTION_CONCURRENCY = 4;
3001
+ const USE_LIST_ERROR_MESSAGE = '`useList` must be called from within `StorageBrowser.Provider`';
3002
+
2837
3003
  const INITIAL_STATUS_COUNTS = {
2838
3004
  CANCELED: 0,
2839
3005
  COMPLETE: 0,
@@ -2864,8 +3030,8 @@ const QUEUED_TASK_BASE = {
2864
3030
  status: 'QUEUED',
2865
3031
  };
2866
3032
  const isTaskHandlerInput = (input) => !!input.data;
2867
- const useProcessTasks = (handler, items, options) => {
2868
- const { concurrency, ...callbacks } = options ?? {};
3033
+ function useProcessTasks(handler, options) {
3034
+ const { concurrency, items, ...callbacks } = options ?? {};
2869
3035
  const callbacksRef = React__namespace["default"].useRef(callbacks);
2870
3036
  if (callbacks) {
2871
3037
  callbacksRef.current = callbacks;
@@ -2891,6 +3057,7 @@ const useProcessTasks = (handler, items, options) => {
2891
3057
  tasksRef.current.set(id, { ...task, ...next });
2892
3058
  }
2893
3059
  flush();
3060
+ return !next ? undefined : tasksRef.current.get(id);
2894
3061
  }, [flush]);
2895
3062
  const createTask = React__namespace["default"].useCallback((data) => {
2896
3063
  const getTask = () => tasksRef.current.get(data.id);
@@ -2899,9 +3066,12 @@ const useProcessTasks = (handler, items, options) => {
2899
3066
  const task = getTask();
2900
3067
  if (!task || task?.status !== 'QUEUED')
2901
3068
  return;
2902
- if (task && ui.isFunction(onTaskCancel))
2903
- onTaskCancel(task);
2904
- updateTask(data.id, { cancel: undefined, status: 'CANCELED' });
3069
+ const canceledTask = updateTask(data.id, {
3070
+ cancel: undefined,
3071
+ status: 'CANCELED',
3072
+ });
3073
+ if (canceledTask && ui.isFunction(onTaskCancel))
3074
+ onTaskCancel(canceledTask);
2905
3075
  }
2906
3076
  const task = { ...QUEUED_TASK_BASE, cancel, data };
2907
3077
  tasksRef.current.set(data.id, task);
@@ -2946,16 +3116,15 @@ const useProcessTasks = (handler, items, options) => {
2946
3116
  const { onTaskCancel, onTaskComplete, onTaskError, onTaskProgress, onTaskSuccess, } = callbacksRef.current;
2947
3117
  const getTask = () => tasksRef.current.get(data.id);
2948
3118
  const { options } = _input;
2949
- const { onProgress: _onProgress, onSuccess, onError } = options ?? {};
3119
+ const { onProgress: _onProgress } = options ?? {};
2950
3120
  const onProgress = ({ id }, progress) => {
2951
- const task = getTask();
3121
+ const task = updateTask(id, { progress });
2952
3122
  if (task && ui.isFunction(onTaskProgress)) {
2953
3123
  onTaskProgress(task, progress);
2954
3124
  }
2955
3125
  if (task && ui.isFunction(_onProgress)) {
2956
3126
  _onProgress(data, progress);
2957
3127
  }
2958
- updateTask(id, { progress });
2959
3128
  };
2960
3129
  const input = { ..._input, data, options: { ...options, onProgress } };
2961
3130
  const { cancel: _cancel, result } = handler(input);
@@ -2969,21 +3138,16 @@ const useProcessTasks = (handler, items, options) => {
2969
3138
  };
2970
3139
  result
2971
3140
  .then((output) => {
2972
- const task = getTask();
2973
- if (task && ui.isFunction(onTaskSuccess)) {
2974
- onTaskSuccess(task, output?.value);
2975
- }
2976
- if (task && ui.isFunction(onSuccess))
2977
- onSuccess(data, output?.value);
2978
- updateTask(data.id, output);
3141
+ const task = updateTask(data.id, output);
3142
+ const { value } = output;
3143
+ if (task && ui.isFunction(onTaskSuccess))
3144
+ onTaskSuccess(task, value);
2979
3145
  })
2980
- .catch((e) => {
2981
- const task = getTask();
3146
+ .catch((error) => {
3147
+ const { message } = error;
3148
+ const task = updateTask(data.id, { message, status: 'FAILED' });
2982
3149
  if (task && ui.isFunction(onTaskError))
2983
- onTaskError(task, e);
2984
- if (task && ui.isFunction(onError))
2985
- onError(data, e?.message);
2986
- updateTask(data.id, { message: e.message, status: 'FAILED' });
3150
+ onTaskError(task, error);
2987
3151
  })
2988
3152
  .finally(() => {
2989
3153
  const task = getTask();
@@ -3021,52 +3185,54 @@ const useProcessTasks = (handler, items, options) => {
3021
3185
  { isProcessing, isProcessingComplete, reset, statusCounts, tasks },
3022
3186
  handleProcessTasks,
3023
3187
  ];
3024
- };
3025
-
3026
- const DEFAULT_ACTION_CONCURRENCY = 4;
3027
- const USE_LIST_ERROR_MESSAGE = '`useList` must be called from within `StorageBrowser.Provider`';
3188
+ }
3028
3189
 
3029
- const isTasksOptions = (value) => ui.isObject(value);
3030
- const useHandler = (action, options) => {
3031
- const hasOptions = isTasksOptions(options);
3032
- const { items, onTaskSuccess } = options ?? {};
3033
- const getConfig = useGetActionInput();
3034
- const { location: { current }, } = useStore()[0];
3035
- const [state, processTask] = useProcessTasks(action, items, {
3036
- onTaskSuccess,
3037
- ...(items ? { concurrency: DEFAULT_ACTION_CONCURRENCY } : undefined),
3190
+ const isOptionsWithItems = (options) => !!options?.items;
3191
+ const isHandleTaskInput = (value) => !!value?.data;
3192
+ function useHandler(handler, options) {
3193
+ const [state, handleProcessing] = useProcessTasks(handler, {
3194
+ ...options,
3195
+ concurrency: DEFAULT_ACTION_CONCURRENCY,
3038
3196
  });
3039
- const { reset, isProcessing, tasks } = state;
3040
- const handler = React__namespace["default"].useCallback((input) => {
3041
- const { location } = input ?? {};
3042
- const config = getConfig(location ?? current);
3043
- if (!hasOptions) {
3044
- // clean up previous state
3197
+ const getConfig = useGetActionInput();
3198
+ const { reset, isProcessing, tasks, ...rest } = state;
3199
+ const handleDispatch = React__namespace["default"].useCallback((input) => {
3200
+ const config = getConfig(input?.location);
3201
+ const hasData = isHandleTaskInput(input);
3202
+ // clean up previous state for atomic handler
3203
+ if (hasData)
3045
3204
  reset();
3046
- processTask({ ...input, config });
3047
- return;
3048
- }
3049
- processTask({ config });
3050
- }, [current, getConfig, hasOptions, processTask, reset]);
3051
- return [
3052
- hasOptions ? state : { isProcessing, task: tasks?.[0] },
3053
- handler,
3054
- ];
3055
- };
3205
+ handleProcessing({
3206
+ config,
3207
+ ...(hasData ? { data: input.data } : undefined),
3208
+ });
3209
+ }, [getConfig, handleProcessing, reset]);
3210
+ if (isOptionsWithItems(options)) {
3211
+ return [{ ...rest, isProcessing, reset, tasks }, handleDispatch];
3212
+ }
3213
+ return [{ isProcessing, task: tasks?.[0] }, handleDispatch];
3214
+ }
3056
3215
 
3057
3216
  const ERROR_MESSAGE = '`useAction` must be called from within `StorageBrowser.Provider`';
3058
- const useAction = (key, options) => {
3059
- if (key === 'listLocations' ||
3060
- key === 'listLocationItems') {
3217
+ function assertActionHandlerKey(key) {
3218
+ if (key === 'listLocations' || key === 'listLocationItems') {
3061
3219
  throw new Error(`Value of \`${key}\` cannot be provided to \`useAction\``);
3062
3220
  }
3063
- const { handlers } = useActionHandlers({ errorMessage: ERROR_MESSAGE });
3064
- const handler = handlers?.[key];
3065
- if (!handler) {
3221
+ }
3222
+ function assertActionHandler(handler, key) {
3223
+ if (typeof handler !== 'function') {
3066
3224
  throw new Error(`No handler found for value of \`${key}\` provided to \`useAction\``);
3067
3225
  }
3226
+ }
3227
+ const useAction = ((key, options) => {
3228
+ assertActionHandlerKey(key);
3229
+ const { handlers } = useActionHandlers({ errorMessage: ERROR_MESSAGE });
3230
+ const handler = handlers?.[key];
3231
+ assertActionHandler(handler, key);
3068
3232
  return useHandler(handler, options);
3069
- };
3233
+ // casting to allow usage of `UseAction` interface which ensures that
3234
+ // the `options` param receives the correct typing
3235
+ });
3070
3236
 
3071
3237
  const useListLocations = () => {
3072
3238
  const { handlers } = useActionHandlers({
@@ -3112,7 +3278,6 @@ const LIST_ACTION_HOOKS = {
3112
3278
  locations: useListLocations,
3113
3279
  };
3114
3280
  const isListActionViewType = (value) => Object.keys(LIST_ACTION_HOOKS).includes(value);
3115
- // @ts-expect-error
3116
3281
  const useList = (type) => {
3117
3282
  if (!isListActionViewType(type)) {
3118
3283
  throw new Error(`Value of \`${type}\` cannot be used to index \`useList\``);
@@ -3476,19 +3641,14 @@ const FoldersTableControl = () => {
3476
3641
  };
3477
3642
  FoldersTableControl.displayName = 'FoldersTable';
3478
3643
 
3479
- const getFolderText$1 = ({ data: { fileKey, sourceKey }, }) => sourceKey.slice(0, -fileKey.length);
3480
-
3481
3644
  function CopyViewProvider({ children, ...props }) {
3482
3645
  const { CopyView: displayText } = useDisplayText();
3483
3646
  const { actionCancelLabel, actionDestinationLabel, actionExitLabel, actionStartLabel, getActionCompleteMessage, overwriteWarningMessage, searchPlaceholder, searchSubmitLabel, searchClearLabel, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, title, } = displayText;
3484
- const { destination, folders, isProcessing, isProcessingComplete, statusCounts, tasks, onActionCancel, onActionExit, onActionStart, onSelectDestination, onTaskRemove, } = props;
3647
+ const { destination, folders, isProcessing, isProcessingComplete, statusCounts, tasks: items, onActionCancel, onActionExit, onActionStart, onSelectDestination, onTaskRemove, } = props;
3485
3648
  const { hasNextPage, highestPageVisited, hasError: hasFoldersError, message: foldersErrorMessage, query, hasExhaustedSearch, isLoading, page, pageItems, onPaginate, onQuery, onSearchClear, onSearch, onSelectFolder, } = folders;
3486
- const tableData = getActionViewTableData({
3487
- getFolderText: getFolderText$1,
3488
- tasks,
3489
- isProcessing,
3490
- displayText,
3491
- onTaskRemove,
3649
+ const tableData = useResolveDataTable(COPY_TABLE_KEYS, COPY_TABLE_RESOLVERS, {
3650
+ items,
3651
+ props: { displayText, isProcessing, onTaskRemove },
3492
3652
  });
3493
3653
  const isActionStartDisabled = isProcessing || isProcessingComplete || !destination?.current;
3494
3654
  const isActionCancelDisabled = !isProcessing || isProcessingComplete;
@@ -3527,40 +3687,38 @@ function CopyViewProvider({ children, ...props }) {
3527
3687
  React__namespace["default"].createElement(FoldersMessageProvider, { folders: folders.pageItems, hasError: hasFoldersError, message: foldersErrorMessage, query: query, hasExhaustedSearch: hasExhaustedSearch }, children)))));
3528
3688
  }
3529
3689
 
3530
- const usePaginate = ({ hasNextToken, items, paginateCallback, pageSize, }) => {
3531
- const [currentPage, setCurrentPage] = React__namespace["default"].useState(1);
3690
+ const DEFAULT_PAGE_SIZE$3 = 100;
3691
+ const usePaginate = ({ items, onPaginate, page = 1, pageSize = DEFAULT_PAGE_SIZE$3, }) => {
3692
+ const [currentPage, setCurrentPage] = React__namespace["default"].useState(page);
3693
+ const visitedRef = React__namespace["default"].useRef(page);
3532
3694
  const handleReset = React__namespace["default"].useRef(() => {
3533
- setCurrentPage(1);
3695
+ setCurrentPage(page);
3696
+ // set `visitedRef` to initially provided `page`
3697
+ visitedRef.current = page;
3534
3698
  }).current;
3535
3699
  return React__namespace["default"].useMemo(() => {
3536
- const resultCount = Array.isArray(items) ? items.length : 0;
3537
- const highestPageVisited = Math.ceil(resultCount / pageSize);
3700
+ const hasItems = Array.isArray(items);
3701
+ const highestPageVisited = visitedRef.current;
3538
3702
  const isFirstPage = currentPage === 1;
3539
3703
  const start = isFirstPage ? 0 : (currentPage - 1) * pageSize;
3540
3704
  const end = isFirstPage ? pageSize : currentPage * pageSize;
3541
- const pageItems = Array.isArray(items) ? items.slice(start, end) : [];
3705
+ const pageItems = hasItems ? items.slice(start, end) : [];
3542
3706
  return {
3543
3707
  currentPage,
3544
- onPaginate: (page) => {
3545
- const shouldPaginate = page >= 1 && (page <= highestPageVisited || hasNextToken);
3546
- if (shouldPaginate) {
3547
- if (ui.isFunction(paginateCallback))
3548
- paginateCallback();
3549
- setCurrentPage(page);
3550
- }
3708
+ handlePaginate: (page) => {
3709
+ if (page < 1)
3710
+ return;
3711
+ if (ui.isFunction(onPaginate))
3712
+ onPaginate(page);
3713
+ if (page > currentPage)
3714
+ visitedRef.current = page;
3715
+ setCurrentPage(page);
3551
3716
  },
3552
3717
  handleReset,
3553
3718
  highestPageVisited,
3554
3719
  pageItems,
3555
3720
  };
3556
- }, [
3557
- currentPage,
3558
- handleReset,
3559
- hasNextToken,
3560
- items,
3561
- paginateCallback,
3562
- pageSize,
3563
- ]);
3721
+ }, [currentPage, handleReset, items, onPaginate, pageSize]);
3564
3722
  };
3565
3723
 
3566
3724
  function useSearch(props) {
@@ -3605,20 +3763,19 @@ const useFolders = ({ destination, setDestination, }) => {
3605
3763
  options: { ...DEFAULT_REFRESH_OPTIONS },
3606
3764
  });
3607
3765
  }, [handleList, key]);
3608
- const hasNextToken = !!nextToken;
3609
- const paginateCallback = () => {
3610
- if (!nextToken)
3766
+ const hasNextPage = !!nextToken;
3767
+ const onPaginate = () => {
3768
+ if (!hasNextPage)
3611
3769
  return;
3612
3770
  handleList({
3613
3771
  prefix: key,
3614
3772
  options: { ...DEFAULT_LIST_OPTIONS$2, nextToken },
3615
3773
  });
3616
3774
  };
3617
- const { currentPage: page, onPaginate, highestPageVisited, pageItems, handleReset, } = usePaginate({
3775
+ const { currentPage: page, handlePaginate, highestPageVisited, pageItems, handleReset, } = usePaginate({
3618
3776
  items,
3619
- paginateCallback,
3777
+ onPaginate,
3620
3778
  pageSize: DEFAULT_PAGE_SIZE$2,
3621
- hasNextToken,
3622
3779
  });
3623
3780
  const onSearch = (query) => {
3624
3781
  handleReset();
@@ -3644,7 +3801,7 @@ const useFolders = ({ destination, setDestination, }) => {
3644
3801
  };
3645
3802
  return {
3646
3803
  hasError,
3647
- hasNextPage: hasNextToken,
3804
+ hasNextPage,
3648
3805
  highestPageVisited,
3649
3806
  isLoading,
3650
3807
  message,
@@ -3653,7 +3810,7 @@ const useFolders = ({ destination, setDestination, }) => {
3653
3810
  pageItems,
3654
3811
  query,
3655
3812
  hasExhaustedSearch,
3656
- onPaginate,
3813
+ onPaginate: handlePaginate,
3657
3814
  onQuery,
3658
3815
  onSearch: onSearchSubmit,
3659
3816
  onSearchClear: () => {
@@ -3786,21 +3943,16 @@ CopyView.Statuses = StatusDisplayControl;
3786
3943
  CopyView.TasksTable = DataTableControl;
3787
3944
  CopyView.Title = TitleControl;
3788
3945
 
3789
- const getFolderText = ({ data: { fileKey, key }, }) => key.slice(0, -fileKey.length);
3790
-
3791
3946
  function DeleteViewProvider({ children, ...props }) {
3792
3947
  const { DeleteView: displayText } = useDisplayText();
3793
3948
  const { actionCancelLabel, actionExitLabel, actionStartLabel, title, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, getActionCompleteMessage, } = displayText;
3794
- const { isProcessing, isProcessingComplete, statusCounts, tasks, onActionCancel, onActionStart, onActionExit, onTaskRemove, } = props;
3949
+ const { isProcessing, isProcessingComplete, statusCounts, tasks: items, onActionCancel, onActionStart, onActionExit, onTaskRemove, } = props;
3795
3950
  const message = isProcessingComplete
3796
3951
  ? getActionCompleteMessage({ counts: statusCounts })
3797
3952
  : undefined;
3798
- const tableData = getActionViewTableData({
3799
- tasks,
3800
- isProcessing,
3801
- displayText,
3802
- getFolderText,
3803
- onTaskRemove,
3953
+ const tableData = useResolveDataTable(DELETE_TABLE_KEYS, DELETE_TABLE_RESOLVERS, {
3954
+ items,
3955
+ props: { displayText, isProcessing, onTaskRemove },
3804
3956
  });
3805
3957
  return (React__namespace["default"].createElement(ControlsContextProvider, { data: {
3806
3958
  actionCancelLabel,
@@ -4025,8 +4177,7 @@ const useLocationDetailView = (options) => {
4025
4177
  // set up pagination
4026
4178
  const { items, nextToken, search } = data;
4027
4179
  const { hasExhaustedSearch = false } = search ?? {};
4028
- const hasNextToken = !!nextToken;
4029
- const paginateCallback = () => {
4180
+ const onPaginate = () => {
4030
4181
  if (hasInvalidPrefix || !nextToken)
4031
4182
  return;
4032
4183
  dispatchStoreAction({ type: 'RESET_LOCATION_ITEMS' });
@@ -4035,11 +4186,10 @@ const useLocationDetailView = (options) => {
4035
4186
  options: { ...listOptions, nextToken },
4036
4187
  });
4037
4188
  };
4038
- const { currentPage, onPaginate, handleReset, highestPageVisited, pageItems, } = usePaginate({
4189
+ const { currentPage, handlePaginate, handleReset, highestPageVisited, pageItems, } = usePaginate({
4039
4190
  items,
4040
- paginateCallback,
4191
+ onPaginate,
4041
4192
  pageSize: listOptions.pageSize,
4042
- hasNextToken,
4043
4193
  });
4044
4194
  const onSearch = (query, includeSubfolders) => {
4045
4195
  if (hasInvalidPrefix)
@@ -4107,13 +4257,13 @@ const useLocationDetailView = (options) => {
4107
4257
  fileDataItems,
4108
4258
  hasError,
4109
4259
  hasDownloadError: task?.status === 'FAILED',
4110
- hasNextPage: hasNextToken,
4260
+ hasNextPage: !!nextToken,
4111
4261
  highestPageVisited,
4112
4262
  message,
4113
4263
  downloadErrorMessage: getDownloadErrorMessageFromFailedDownloadTask(task),
4114
4264
  isLoading,
4115
4265
  isSearchSubfoldersEnabled,
4116
- onPaginate,
4266
+ onPaginate: handlePaginate,
4117
4267
  searchQuery,
4118
4268
  hasExhaustedSearch,
4119
4269
  onRefresh,
@@ -4169,10 +4319,7 @@ const useLocationDetailView = (options) => {
4169
4319
  resetSearch();
4170
4320
  if (hasInvalidPrefix)
4171
4321
  return;
4172
- handleList({
4173
- prefix: key,
4174
- options: { ...listOptions, refresh: true },
4175
- });
4322
+ handleList({ prefix: key, options: { ...listOptions, refresh: true } });
4176
4323
  handleReset();
4177
4324
  },
4178
4325
  onSearchQueryChange,
@@ -4679,16 +4826,15 @@ const useLocationsView = (options) => {
4679
4826
  handleList({ options: { ...listOptions, refresh: true } });
4680
4827
  }, [handleList, listOptions]);
4681
4828
  // set up pagination
4682
- const paginateCallback = () => {
4829
+ const onPaginate = () => {
4683
4830
  if (!nextToken)
4684
4831
  return;
4685
4832
  handleList({ options: { ...listOptions, nextToken } });
4686
4833
  };
4687
- const { currentPage, onPaginate, handleReset, highestPageVisited, pageItems, } = usePaginate({
4834
+ const { currentPage, handlePaginate, handleReset, highestPageVisited, pageItems, } = usePaginate({
4688
4835
  items,
4689
- paginateCallback,
4836
+ onPaginate,
4690
4837
  pageSize: listOptions.pageSize,
4691
- hasNextToken,
4692
4838
  });
4693
4839
  const onSearch = (query) => {
4694
4840
  handleReset();
@@ -4735,7 +4881,7 @@ const useLocationsView = (options) => {
4735
4881
  handleReset();
4736
4882
  handleList({ options: { ...listOptions, refresh: true } });
4737
4883
  },
4738
- onPaginate,
4884
+ onPaginate: handlePaginate,
4739
4885
  onSearch: onSearchSubmit,
4740
4886
  onSearchQueryChange,
4741
4887
  onSearchClear: () => {
@@ -4799,7 +4945,10 @@ const getViews = (views, customConfigs) => {
4799
4945
  // ignore custom actions that are only handlers
4800
4946
  return !ui.isObject(config) || ui.isFunction(config)
4801
4947
  ? acc
4802
- : { ...acc, [key]: views?.[config.viewName] };
4948
+ : {
4949
+ ...acc,
4950
+ [key]: views?.[config.viewName],
4951
+ };
4803
4952
  }, {});
4804
4953
  return {
4805
4954
  action: { ...resolvedDefaultActionViews, ...customActionViews },
@@ -4824,7 +4973,7 @@ function useViews() {
4824
4973
  };
4825
4974
  }
4826
4975
 
4827
- const DEFAULT_VIEW_HOOKS = {
4976
+ const USE_VIEW_HOOKS = {
4828
4977
  Copy: useCopyView,
4829
4978
  CreateFolder: useCreateFolderView,
4830
4979
  Delete: useDeleteView,
@@ -4832,13 +4981,12 @@ const DEFAULT_VIEW_HOOKS = {
4832
4981
  Locations: useLocationsView,
4833
4982
  Upload: useUploadView,
4834
4983
  };
4835
- const isUseViewType = (value) => !!DEFAULT_VIEW_HOOKS?.[value];
4836
- // @ts-expect-error
4984
+ const isUseViewType = (value) => !!USE_VIEW_HOOKS?.[value];
4837
4985
  const useView = (type) => {
4838
4986
  if (!isUseViewType(type)) {
4839
4987
  throw new Error(`Value of \`${type}\` cannot be used to index \`useView\``);
4840
4988
  }
4841
- return DEFAULT_VIEW_HOOKS[type]();
4989
+ return USE_VIEW_HOOKS[type]();
4842
4990
  };
4843
4991
 
4844
4992
  /**
@@ -4861,6 +5009,12 @@ function StorageBrowserDefault() {
4861
5009
  return React__namespace["default"].createElement(LocationsView, null);
4862
5010
  }
4863
5011
 
5012
+ /**
5013
+ * Creates a `StorageBrowser` component and utility hooks from provided configuration `input`.
5014
+ *
5015
+ * @param input - `StorageBrowser` auth, actions and ui configuration values
5016
+ * @returns `StorageBrowser` component, `useAction` and `useView` hooks
5017
+ */
4864
5018
  function createStorageBrowser(input) {
4865
5019
  assertRegisterAuthListener(input.config.registerAuthListener);
4866
5020
  const { accountId, customEndpoint, registerAuthListener, getLocationCredentials, region, } = input.config;
@@ -5062,5 +5216,7 @@ exports.VERSION = VERSION;
5062
5216
  exports.componentsDefault = componentsDefault;
5063
5217
  exports.createAmplifyAuthAdapter = createAmplifyAuthAdapter;
5064
5218
  exports.createStorageBrowser = createStorageBrowser;
5219
+ exports.defaultActionConfigs = defaultActionConfigs;
5220
+ exports.defaultHandlers = defaultHandlers;
5065
5221
  exports.getFilteredLocations = getFilteredLocations;
5066
5222
  exports.toAccessGrantPermission = toAccessGrantPermission;