@aws-amplify/ui-react-storage 3.11.0 → 3.12.1

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 (52) hide show
  1. package/dist/browser.js +1 -1
  2. package/dist/{createStorageBrowser-CVfazB4S.js → createStorageBrowser-C7xCWNpG.js} +279 -89
  3. package/dist/esm/components/StorageBrowser/actions/configs/defaults.mjs +12 -3
  4. package/dist/esm/components/StorageBrowser/actions/handlers/listLocationItems.mjs +1 -1
  5. package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +1 -0
  6. package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +1 -0
  7. package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +2 -0
  8. package/dist/esm/components/StorageBrowser/displayText/context.mjs +5 -1
  9. package/dist/esm/components/StorageBrowser/displayText/libraries/en/default.mjs +2 -0
  10. package/dist/esm/components/StorageBrowser/displayText/libraries/en/downloadView.mjs +23 -0
  11. package/dist/esm/components/StorageBrowser/displayText/libraries/en/locationDetailView.mjs +2 -0
  12. package/dist/esm/components/StorageBrowser/displayText/utils.mjs +3 -1
  13. package/dist/esm/components/StorageBrowser/useAction/utils.mjs +2 -2
  14. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +47 -0
  15. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.mjs +38 -0
  16. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.mjs +66 -0
  17. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +3 -0
  18. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadViewProvider.mjs +7 -2
  19. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/useUploadView.mjs +10 -1
  20. package/dist/esm/components/StorageBrowser/views/context/actionViews.mjs +2 -0
  21. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +1 -0
  22. package/dist/esm/components/StorageBrowser/views/hooks/usePaginate.mjs +1 -1
  23. package/dist/esm/components/StorageBrowser/views/useView.mjs +3 -0
  24. package/dist/esm/components/StorageBrowser/views/utils/tableResolvers/downloadResolvers.mjs +36 -0
  25. package/dist/esm/version.mjs +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/styles.css +17 -2
  28. package/dist/types/components/StorageBrowser/actions/configs/defaults.d.ts +4 -3
  29. package/dist/types/components/StorageBrowser/actions/configs/types.d.ts +3 -1
  30. package/dist/types/components/StorageBrowser/actions/handlers/download.d.ts +2 -2
  31. package/dist/types/components/StorageBrowser/createStorageBrowser/types.d.ts +2 -1
  32. package/dist/types/components/StorageBrowser/displayText/index.d.ts +2 -2
  33. package/dist/types/components/StorageBrowser/displayText/libraries/en/downloadView.d.ts +2 -0
  34. package/dist/types/components/StorageBrowser/displayText/types.d.ts +7 -1
  35. package/dist/types/components/StorageBrowser/displayText/utils.d.ts +2 -1
  36. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.d.ts +2 -0
  37. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadViewProvider.d.ts +3 -0
  38. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/index.d.ts +3 -0
  39. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/types.d.ts +22 -0
  40. package/dist/types/components/StorageBrowser/views/LocationActionView/DownloadView/useDownloadView.d.ts +2 -0
  41. package/dist/types/components/StorageBrowser/views/LocationActionView/UploadView/types.d.ts +5 -0
  42. package/dist/types/components/StorageBrowser/views/LocationActionView/index.d.ts +2 -0
  43. package/dist/types/components/StorageBrowser/views/index.d.ts +2 -2
  44. package/dist/types/components/StorageBrowser/views/types.d.ts +5 -3
  45. package/dist/types/components/StorageBrowser/views/useView.d.ts +2 -1
  46. package/dist/types/components/StorageBrowser/views/utils/index.d.ts +1 -1
  47. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/__testUtils__/tasks.d.ts +1 -1
  48. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/downloadResolvers.d.ts +2 -0
  49. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/index.d.ts +2 -1
  50. package/dist/types/components/StorageBrowser/views/utils/tableResolvers/types.d.ts +6 -2
  51. package/dist/types/version.d.ts +1 -1
  52. package/package.json +4 -4
package/dist/browser.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var internals = require('@aws-amplify/storage/internals');
6
6
  require('@aws-amplify/ui');
7
- var createStorageBrowser = require('./createStorageBrowser-CVfazB4S.js');
7
+ var createStorageBrowser = require('./createStorageBrowser-C7xCWNpG.js');
8
8
  require('aws-amplify/storage');
9
9
  require('react');
10
10
  require('@aws-amplify/ui-react');
@@ -32,7 +32,7 @@ function _interopNamespace(e) {
32
32
 
33
33
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
34
 
35
- const VERSION = '3.11.0';
35
+ const VERSION = '3.12.1';
36
36
 
37
37
  const toAccessGrantPermission = (permission) => {
38
38
  let result = '';
@@ -389,7 +389,7 @@ const downloadHandler = ({ config, data: { key }, }) => {
389
389
  return { result };
390
390
  };
391
391
 
392
- const DEFAULT_PAGE_SIZE$4 = 1000;
392
+ const DEFAULT_PAGE_SIZE$5 = 1000;
393
393
  const parseItems = (items, excludedPath) => items
394
394
  // remove root `key` from results
395
395
  .filter(({ path }) => path !== excludedPath)
@@ -422,7 +422,7 @@ const parseResult = ({ excludedSubpaths, items }, prefix) => filterDotItems([...
422
422
  const listLocationItemsHandler = async (input) => {
423
423
  const { config, prefix, options } = input;
424
424
  const { bucket: _bucket, credentials, customEndpoint, region, accountId, } = config;
425
- const { exclude, delimiter, nextToken, pageSize: _pageSize = DEFAULT_PAGE_SIZE$4, ..._options } = options ?? {};
425
+ const { exclude, delimiter, nextToken, pageSize: _pageSize = DEFAULT_PAGE_SIZE$5, ..._options } = options ?? {};
426
426
  const bucket = { bucketName: _bucket, region };
427
427
  const subpathStrategy = {
428
428
  delimiter,
@@ -455,7 +455,7 @@ const listLocationItemsHandler = async (input) => {
455
455
  nextNextToken = output.nextToken;
456
456
  const items = parseResult(output, prefix);
457
457
  result.push(...(exclude ? items.filter((item) => item.type !== exclude) : items));
458
- } while (nextNextToken && result.length < pageSize);
458
+ } while (nextNextToken && result.length < _pageSize);
459
459
  return { items: result, nextToken: nextNextToken };
460
460
  };
461
461
 
@@ -584,12 +584,21 @@ const uploadActionConfig = {
584
584
  },
585
585
  handler: defaultHandlers.upload,
586
586
  };
587
+ const downloadActionConfig = {
588
+ viewName: 'DownloadView',
589
+ actionListItem: {
590
+ disable: (selected) => !selected || selected.length === 0,
591
+ hide: (permissions) => !permissions.includes('get'),
592
+ icon: 'download',
593
+ label: 'Download',
594
+ },
595
+ handler: defaultHandlers.download,
596
+ };
587
597
  // Action view configs only, does not include `listLocationItems`
588
598
  const defaultActionViewConfigs = {
589
599
  copy: copyActionConfig,
590
600
  createFolder: createFolderActionConfig,
591
- // provide `download` handler only; `download` does not have a dedicated view/config
592
- download: defaultHandlers.download,
601
+ download: downloadActionConfig,
593
602
  delete: deleteActionConfig,
594
603
  upload: uploadActionConfig,
595
604
  };
@@ -2178,12 +2187,12 @@ const useList = (type) => {
2178
2187
 
2179
2188
  const resolveHandler = (value) => (ui.isFunction(value) ? value : value.handler);
2180
2189
  const getActionHandlers = (configs) => {
2181
- const { copy: copyConfig, createFolder: createFolderConfig, delete: deleteConfig, download, upload: uploadConfig, listLocationItems, listLocations, } = configs.default;
2190
+ const { copy: copyConfig, createFolder: createFolderConfig, delete: deleteConfig, download: downloadConfig, upload: uploadConfig, listLocationItems, listLocations, } = configs.default;
2182
2191
  const defaultHandlers = {
2183
2192
  copy: copyConfig.handler,
2184
2193
  createFolder: createFolderConfig.handler,
2185
2194
  delete: deleteConfig.handler,
2186
- download,
2195
+ download: 'handler' in downloadConfig ? downloadConfig.handler : downloadConfig,
2187
2196
  listLocationItems,
2188
2197
  listLocations,
2189
2198
  upload: uploadConfig.handler,
@@ -2905,6 +2914,8 @@ const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT = {
2905
2914
  return 'Create folder';
2906
2915
  case 'Upload':
2907
2916
  return 'Upload';
2917
+ case 'Download':
2918
+ return 'Download';
2908
2919
  default:
2909
2920
  return key;
2910
2921
  }
@@ -3049,10 +3060,31 @@ const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT = {
3049
3060
  title: 'Upload',
3050
3061
  };
3051
3062
 
3063
+ const DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT = {
3064
+ ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
3065
+ title: 'Download',
3066
+ actionStartLabel: 'Download',
3067
+ getActionCompleteMessage: (data) => {
3068
+ const { counts } = data ?? {};
3069
+ const { COMPLETE, FAILED, TOTAL } = counts ?? {};
3070
+ if (COMPLETE === TOTAL) {
3071
+ return { content: 'All files downloaded.', type: 'success' };
3072
+ }
3073
+ if (FAILED === TOTAL) {
3074
+ return { content: 'All files failed to download.', type: 'error' };
3075
+ }
3076
+ return {
3077
+ content: `${COMPLETE} files downloaded, ${FAILED} files failed to download.`,
3078
+ type: 'error',
3079
+ };
3080
+ },
3081
+ };
3082
+
3052
3083
  const DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT = {
3053
3084
  CopyView: DEFAULT_COPY_VIEW_DISPLAY_TEXT,
3054
3085
  CreateFolderView: DEFAULT_CREATE_FOLDER_VIEW_DISPLAY_TEXT,
3055
3086
  DeleteView: DEFAULT_DELETE_VIEW_DISPLAY_TEXT,
3087
+ DownloadView: DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT,
3056
3088
  LocationDetailView: DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT,
3057
3089
  LocationsView: DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT,
3058
3090
  UploadView: DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT,
@@ -3066,7 +3098,7 @@ function resolveDisplayText(displayText) {
3066
3098
  if (!displayText)
3067
3099
  return DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT;
3068
3100
  // override
3069
- const { CopyView, CreateFolderView, DeleteView, LocationDetailView, LocationsView, UploadView, } = displayText;
3101
+ const { CopyView, CreateFolderView, DeleteView, DownloadView, LocationDetailView, LocationsView, UploadView, } = displayText;
3070
3102
  return {
3071
3103
  CopyView: { ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.CopyView, ...CopyView },
3072
3104
  CreateFolderView: {
@@ -3077,6 +3109,10 @@ function resolveDisplayText(displayText) {
3077
3109
  ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.DeleteView,
3078
3110
  ...DeleteView,
3079
3111
  },
3112
+ DownloadView: {
3113
+ ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.DownloadView,
3114
+ ...DownloadView,
3115
+ },
3080
3116
  LocationDetailView: {
3081
3117
  ...DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView,
3082
3118
  ...LocationDetailView,
@@ -3099,6 +3135,7 @@ function DisplayTextProvider({ children, displayText: _override, }) {
3099
3135
 
3100
3136
  const isCopyViewDisplayTextKey = (value) => !!DEFAULT_COPY_VIEW_DISPLAY_TEXT[value];
3101
3137
  const isDeleteViewDisplayTextKey = (value) => !!DEFAULT_DELETE_VIEW_DISPLAY_TEXT[value];
3138
+ const isDownloadViewDisplayTextKey = (value) => !!DEFAULT_DOWNLOAD_VIEW_DISPLAY_TEXT[value];
3102
3139
 
3103
3140
  function useResolveTableData(keys, { getCell, getHeader, getRowKey }, { items, props }) {
3104
3141
  return React__namespace["default"].useMemo(() => {
@@ -3222,7 +3259,7 @@ const cancel$1 = (data) => {
3222
3259
  return { key, type: 'button', content };
3223
3260
  };
3224
3261
 
3225
- const status$2 = (data) => {
3262
+ const status$3 = (data) => {
3226
3263
  const key = getFileDataCellKey(data);
3227
3264
  const { item: { status }, props: { displayText }, } = data;
3228
3265
  const statusLabelKey = STATUS_LABELS[status];
@@ -3236,7 +3273,7 @@ const COPY_CELL_RESOLVERS = {
3236
3273
  folder: folder$1,
3237
3274
  type: type$1,
3238
3275
  size: size$1,
3239
- status: status$2,
3276
+ status: status$3,
3240
3277
  cancel: cancel$1,
3241
3278
  /**
3242
3279
  * @deprecated
@@ -3259,6 +3296,72 @@ const COPY_TABLE_RESOLVERS = {
3259
3296
  getRowKey: ({ item }) => item.data.id,
3260
3297
  };
3261
3298
 
3299
+ const status$2 = (data) => {
3300
+ const key = getFileDataCellKey(data);
3301
+ const { item: { status }, props: { displayText }, } = data;
3302
+ const statusLabelKey = STATUS_LABELS[status];
3303
+ const text = isDeleteViewDisplayTextKey(statusLabelKey)
3304
+ ? displayText[statusLabelKey]
3305
+ : '';
3306
+ return { key, type: 'text', content: { text } };
3307
+ };
3308
+ const DELETE_CELL_RESOLVERS = {
3309
+ name: name$1,
3310
+ folder: folder$1,
3311
+ type: type$1,
3312
+ size: size$1,
3313
+ status: status$2,
3314
+ cancel: cancel$1,
3315
+ /**
3316
+ * @deprecated
3317
+ *
3318
+ * non-upload view tables do not include "progress" headers but include here to
3319
+ * keep TS happy as "progress" headers were included in display text interfaces
3320
+ * and cannot be removed from the tables without a breaking change
3321
+ */
3322
+ progress: ui.noop,
3323
+ };
3324
+ const DELETE_TABLE_RESOLVERS = {
3325
+ getCell: (data) => DELETE_CELL_RESOLVERS[data.key](data),
3326
+ getHeader: ({ key, props: { displayText } }) => {
3327
+ const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
3328
+ if (key === 'cancel') {
3329
+ return { key, type: 'text', content: { text } };
3330
+ }
3331
+ return { key, type: 'sort', content: { label: text } };
3332
+ },
3333
+ getRowKey: ({ item }) => item.data.id,
3334
+ };
3335
+
3336
+ const status$1 = (data) => {
3337
+ const key = getFileDataCellKey(data);
3338
+ const { item: { status }, props: { displayText }, } = data;
3339
+ const statusLabelKey = STATUS_LABELS[status];
3340
+ const text = isDownloadViewDisplayTextKey(statusLabelKey)
3341
+ ? displayText[statusLabelKey]
3342
+ : '';
3343
+ return { key, type: 'text', content: { text } };
3344
+ };
3345
+ const DOWNLOAD_CELL_RESOLVERS = {
3346
+ name: name$1,
3347
+ folder: folder$1,
3348
+ type: type$1,
3349
+ size: size$1,
3350
+ status: status$1,
3351
+ cancel: cancel$1,
3352
+ };
3353
+ const DOWNLOAD_TABLE_RESOLVERS = {
3354
+ getCell: (data) => DOWNLOAD_CELL_RESOLVERS[data.key](data),
3355
+ getHeader: ({ key, props: { displayText } }) => {
3356
+ const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
3357
+ if (key === 'cancel') {
3358
+ return { key, type: 'text', content: { text } };
3359
+ }
3360
+ return { key, type: 'sort', content: { label: text } };
3361
+ },
3362
+ getRowKey: ({ item }) => item.data.id,
3363
+ };
3364
+
3262
3365
  const UPLOAD_TABLE_KEYS = [
3263
3366
  'name',
3264
3367
  'folder',
@@ -3293,7 +3396,7 @@ const size = (data) => {
3293
3396
  const displayValue = getFileSize(value);
3294
3397
  return { key, type: 'number', content: { value, displayValue } };
3295
3398
  };
3296
- const status$1 = (data) => {
3399
+ const status = (data) => {
3297
3400
  const key = getUploadCellKey(data);
3298
3401
  const { item: { status }, props: { displayText }, } = data;
3299
3402
  const text = displayText[STATUS_LABELS[status]];
@@ -3351,7 +3454,7 @@ const UPLOAD_CELL_RESOLVERS = {
3351
3454
  name,
3352
3455
  progress,
3353
3456
  size,
3354
- status: status$1,
3457
+ status,
3355
3458
  type,
3356
3459
  };
3357
3460
  const UPLOAD_TABLE_RESOLVERS = {
@@ -3366,47 +3469,10 @@ const UPLOAD_TABLE_RESOLVERS = {
3366
3469
  getRowKey: ({ item }) => item.data.id,
3367
3470
  };
3368
3471
 
3369
- const status = (data) => {
3370
- const key = getFileDataCellKey(data);
3371
- const { item: { status }, props: { displayText }, } = data;
3372
- const statusLabelKey = STATUS_LABELS[status];
3373
- const text = isDeleteViewDisplayTextKey(statusLabelKey)
3374
- ? displayText[statusLabelKey]
3375
- : '';
3376
- return { key, type: 'text', content: { text } };
3377
- };
3378
- const DELETE_CELL_RESOLVERS = {
3379
- name: name$1,
3380
- folder: folder$1,
3381
- type: type$1,
3382
- size: size$1,
3383
- status,
3384
- cancel: cancel$1,
3385
- /**
3386
- * @deprecated
3387
- *
3388
- * non-upload view tables do not include "progress" headers but include here to
3389
- * keep TS happy as "progress" headers were included in display text interfaces
3390
- * and cannot be removed from the tables without a breaking change
3391
- */
3392
- progress: ui.noop,
3393
- };
3394
- const DELETE_TABLE_RESOLVERS = {
3395
- getCell: (data) => DELETE_CELL_RESOLVERS[data.key](data),
3396
- getHeader: ({ key, props: { displayText } }) => {
3397
- const text = displayText[`tableColumn${ui.capitalize(key)}Header`];
3398
- if (key === 'cancel') {
3399
- return { key, type: 'text', content: { text } };
3400
- }
3401
- return { key, type: 'sort', content: { label: text } };
3402
- },
3403
- getRowKey: ({ item }) => item.data.id,
3404
- };
3405
-
3406
3472
  function UploadViewProvider({ children, ...props }) {
3407
3473
  const { UploadView: displayText } = useDisplayText();
3408
3474
  const { actionCancelLabel, actionDestinationLabel, actionExitLabel, actionStartLabel, addFilesLabel, addFolderLabel, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, overwriteToggleLabel, title, getActionCompleteMessage, getFilesValidationMessage, } = displayText;
3409
- const { isOverwritingEnabled, isProcessing, isProcessingComplete, location, tasks: items, statusCounts, invalidFiles, onActionStart, onActionCancel, onDropFiles, onActionExit, onTaskRemove, onSelectFiles, onToggleOverwrite, } = props;
3475
+ const { hasNextPage, highestPageVisited, page, isOverwritingEnabled, isProcessing, isProcessingComplete, location, tasks: items, statusCounts, invalidFiles, onActionStart, onActionCancel, onDropFiles, onPaginate, onActionExit, onTaskRemove, onSelectFiles, onToggleOverwrite, } = props;
3410
3476
  const isActionStartDisabled = isProcessing || isProcessingComplete || statusCounts.TOTAL === 0;
3411
3477
  const isActionCancelDisabled = !isProcessing || isProcessingComplete;
3412
3478
  const isAddFilesDisabled = isProcessing || isProcessingComplete;
@@ -3440,6 +3506,11 @@ function UploadViewProvider({ children, ...props }) {
3440
3506
  isOverwriteToggleDisabled: isProcessing || isProcessingComplete,
3441
3507
  isOverwritingEnabled,
3442
3508
  overwriteToggleLabel,
3509
+ paginationData: {
3510
+ page,
3511
+ hasNextPage,
3512
+ highestPageVisited,
3513
+ },
3443
3514
  destination: location,
3444
3515
  message: actionCompleteMessage ?? filesValidationMessage,
3445
3516
  statusCounts,
@@ -3449,7 +3520,7 @@ function UploadViewProvider({ children, ...props }) {
3449
3520
  statusDisplayQueuedLabel,
3450
3521
  tableData,
3451
3522
  title,
3452
- }, onActionCancel: onActionCancel, onActionExit: onActionExit, onActionStart: onActionStart, onAddFiles: () => {
3523
+ }, onActionCancel: onActionCancel, onActionExit: onActionExit, onActionStart: onActionStart, onPaginate: onPaginate, onAddFiles: () => {
3453
3524
  onSelectFiles('FILE');
3454
3525
  }, onAddFolder: () => {
3455
3526
  onSelectFiles('FOLDER');
@@ -3581,6 +3652,41 @@ function FileItemsProvider({ children, validateFile, }) {
3581
3652
 
3582
3653
  const DEFAULT_OVERWRITE_ENABLED = false;
3583
3654
 
3655
+ const DEFAULT_PAGE_SIZE$4 = 100;
3656
+ const usePaginate = ({ items, onPaginate, page = 1, pageSize = DEFAULT_PAGE_SIZE$4, }) => {
3657
+ const [currentPage, setCurrentPage] = React__namespace["default"].useState(page);
3658
+ const visitedRef = React__namespace["default"].useRef(page);
3659
+ const handleReset = React__namespace["default"].useRef(() => {
3660
+ setCurrentPage(page);
3661
+ // set `visitedRef` to initially provided `page`
3662
+ visitedRef.current = page;
3663
+ }).current;
3664
+ return React__namespace["default"].useMemo(() => {
3665
+ const hasItems = Array.isArray(items);
3666
+ const highestPageVisited = visitedRef.current;
3667
+ const isFirstPage = currentPage === 1;
3668
+ const start = isFirstPage ? 0 : (currentPage - 1) * pageSize;
3669
+ const end = isFirstPage ? pageSize : currentPage * pageSize;
3670
+ const pageItems = hasItems ? items.slice(start, end) : [];
3671
+ return {
3672
+ currentPage,
3673
+ handlePaginate: (page) => {
3674
+ if (page < 1)
3675
+ return;
3676
+ if (ui.isFunction(onPaginate))
3677
+ onPaginate(page);
3678
+ if (page > currentPage && page > highestPageVisited)
3679
+ visitedRef.current = page;
3680
+ setCurrentPage(page);
3681
+ },
3682
+ handleReset,
3683
+ highestPageVisited,
3684
+ pageItems,
3685
+ };
3686
+ }, [currentPage, handleReset, items, onPaginate, pageSize]);
3687
+ };
3688
+
3689
+ const DEFAULT_PAGE_SIZE$3 = 100;
3584
3690
  const useUploadView = (options) => {
3585
3691
  const { onExit: _onExit } = options ?? {};
3586
3692
  const [{ location }, storeDispatch] = useStore();
@@ -3593,6 +3699,9 @@ const useUploadView = (options) => {
3593
3699
  preventOverwrite: !isOverwritingEnabled,
3594
3700
  })), [validItems, isOverwritingEnabled, location.key]);
3595
3701
  const [{ isProcessing, isProcessingComplete, statusCounts, tasks }, handleUploads,] = useAction('upload', { items });
3702
+ const { currentPage, handlePaginate, pageItems: pageTasks, } = usePaginate({
3703
+ items: tasks,
3704
+ });
3596
3705
  const onDropFiles = (files) => {
3597
3706
  if (files) {
3598
3707
  fileItemsDispatch({ type: 'ADD_FILES', files });
@@ -3627,11 +3736,15 @@ const useUploadView = (options) => {
3627
3736
  location,
3628
3737
  invalidFiles,
3629
3738
  statusCounts,
3630
- tasks,
3739
+ tasks: pageTasks,
3740
+ page: currentPage,
3741
+ hasNextPage: currentPage * DEFAULT_PAGE_SIZE$3 < items.length,
3742
+ highestPageVisited: Math.ceil(items.length / DEFAULT_PAGE_SIZE$3),
3631
3743
  onActionCancel,
3632
3744
  onActionExit,
3633
3745
  onActionStart,
3634
3746
  onDropFiles,
3747
+ onPaginate: handlePaginate,
3635
3748
  onTaskRemove,
3636
3749
  onSelectFiles,
3637
3750
  onToggleOverwrite,
@@ -3647,6 +3760,7 @@ const UploadView = ({ className, ...props }) => {
3647
3760
  React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__controls` },
3648
3761
  React__namespace["default"].createElement(OverwriteToggleControl, null),
3649
3762
  React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__buttons` },
3763
+ React__namespace["default"].createElement(PaginationControl, null),
3650
3764
  React__namespace["default"].createElement(AddFolderControl, null),
3651
3765
  React__namespace["default"].createElement(AddFilesControl, null))),
3652
3766
  React__namespace["default"].createElement(DropZoneControl, null,
@@ -3666,6 +3780,7 @@ UploadView.displayName = 'UploadView';
3666
3780
  UploadView.Provider = UploadViewProvider;
3667
3781
  UploadView.AddFiles = AddFilesControl;
3668
3782
  UploadView.AddFolder = AddFolderControl;
3783
+ UploadView.Pagination = PaginationControl;
3669
3784
  UploadView.Cancel = ActionCancelControl;
3670
3785
  UploadView.Destination = ActionDestinationControl;
3671
3786
  UploadView.DropZone = DropZoneControl;
@@ -3935,40 +4050,6 @@ function LocationItemsProvider({ children, }) {
3935
4050
  return (React__namespace["default"].createElement(LocationItemsContext.Provider, { value: value }, children));
3936
4051
  }
3937
4052
 
3938
- const DEFAULT_PAGE_SIZE$3 = 100;
3939
- const usePaginate = ({ items, onPaginate, page = 1, pageSize = DEFAULT_PAGE_SIZE$3, }) => {
3940
- const [currentPage, setCurrentPage] = React__namespace["default"].useState(page);
3941
- const visitedRef = React__namespace["default"].useRef(page);
3942
- const handleReset = React__namespace["default"].useRef(() => {
3943
- setCurrentPage(page);
3944
- // set `visitedRef` to initially provided `page`
3945
- visitedRef.current = page;
3946
- }).current;
3947
- return React__namespace["default"].useMemo(() => {
3948
- const hasItems = Array.isArray(items);
3949
- const highestPageVisited = visitedRef.current;
3950
- const isFirstPage = currentPage === 1;
3951
- const start = isFirstPage ? 0 : (currentPage - 1) * pageSize;
3952
- const end = isFirstPage ? pageSize : currentPage * pageSize;
3953
- const pageItems = hasItems ? items.slice(start, end) : [];
3954
- return {
3955
- currentPage,
3956
- handlePaginate: (page) => {
3957
- if (page < 1)
3958
- return;
3959
- if (ui.isFunction(onPaginate))
3960
- onPaginate(page);
3961
- if (page > currentPage)
3962
- visitedRef.current = page;
3963
- setCurrentPage(page);
3964
- },
3965
- handleReset,
3966
- highestPageVisited,
3967
- pageItems,
3968
- };
3969
- }, [currentPage, handleReset, items, onPaginate, pageSize]);
3970
- };
3971
-
3972
4053
  function useSearch(props) {
3973
4054
  const { onSearch } = props;
3974
4055
  const [searchQuery, setQuery] = React__namespace["default"].useState('');
@@ -4218,13 +4299,13 @@ function DeleteViewProvider({ children, ...props }) {
4218
4299
  }
4219
4300
 
4220
4301
  // assign to constant to ensure referential equality
4221
- const EMPTY_ITEMS = [];
4302
+ const EMPTY_ITEMS$1 = [];
4222
4303
  const useDeleteView = (options) => {
4223
4304
  const { onExit: _onExit } = options ?? {};
4224
4305
  const [{ location }, storeDispatch] = useStore();
4225
4306
  const [locationItems, locationItemsDispatch] = useLocationItems();
4226
4307
  const { current } = location;
4227
- const { fileDataItems: items = EMPTY_ITEMS } = locationItems;
4308
+ const { fileDataItems: items = EMPTY_ITEMS$1 } = locationItems;
4228
4309
  const [processState, handleProcess] = useAction('delete', { items });
4229
4310
  const { isProcessing, isProcessingComplete, statusCounts, tasks } = processState;
4230
4311
  const onActionStart = () => {
@@ -4290,10 +4371,117 @@ DeleteView.Statuses = StatusDisplayControl;
4290
4371
  DeleteView.TasksTable = DataTableControl;
4291
4372
  DeleteView.Title = TitleControl;
4292
4373
 
4374
+ function DownloadViewProvider({ children, ...props }) {
4375
+ const { DownloadView: displayText } = useDisplayText();
4376
+ const { actionCancelLabel, actionExitLabel, actionStartLabel, title, statusDisplayCanceledLabel, statusDisplayCompletedLabel, statusDisplayFailedLabel, statusDisplayQueuedLabel, getActionCompleteMessage, } = displayText;
4377
+ const { isProcessing, isProcessingComplete, statusCounts, tasks: items, onActionCancel, onActionStart, onActionExit, onTaskRemove, } = props;
4378
+ const message = isProcessingComplete
4379
+ ? getActionCompleteMessage({ counts: statusCounts })
4380
+ : undefined;
4381
+ const tableData = useResolveTableData(FILE_DATA_ITEM_TABLE_KEYS, DOWNLOAD_TABLE_RESOLVERS, {
4382
+ items,
4383
+ props: { displayText, isProcessing, onTaskRemove },
4384
+ });
4385
+ return (React__namespace["default"].createElement(ControlsContextProvider, { data: {
4386
+ actionCancelLabel,
4387
+ actionExitLabel,
4388
+ actionStartLabel,
4389
+ isActionCancelDisabled: !isProcessing || isProcessingComplete,
4390
+ isActionExitDisabled: isProcessing,
4391
+ isActionStartDisabled: isProcessing || isProcessingComplete,
4392
+ statusDisplayCanceledLabel,
4393
+ statusDisplayCompletedLabel,
4394
+ statusDisplayFailedLabel,
4395
+ statusDisplayQueuedLabel,
4396
+ statusCounts,
4397
+ tableData,
4398
+ title,
4399
+ message,
4400
+ }, onActionStart: onActionStart, onActionExit: onActionExit, onActionCancel: onActionCancel }, children));
4401
+ }
4402
+
4403
+ // assign to constant to ensure referential equality
4404
+ const EMPTY_ITEMS = [];
4405
+ const useDownloadView = (options) => {
4406
+ const { onExit: _onExit } = options ?? {};
4407
+ const [{ location }, storeDispatch] = useStore();
4408
+ const [locationItems, locationItemsDispatch] = useLocationItems();
4409
+ const { current } = location;
4410
+ const { fileDataItems: items = EMPTY_ITEMS } = locationItems;
4411
+ const [processState, handleProcess] = useAction('download', {
4412
+ items,
4413
+ });
4414
+ const { isProcessing, isProcessingComplete, statusCounts, tasks } = processState;
4415
+ const onActionStart = () => {
4416
+ if (!current)
4417
+ return;
4418
+ handleProcess();
4419
+ };
4420
+ const onActionCancel = () => {
4421
+ tasks.forEach((task) => {
4422
+ // Calling cancel on task works only on queued tasks.
4423
+ // In case of download, all download presigned url open at once
4424
+ // When certain threshold is reached for queuing inside StorageBrowser, cancel might be possible.
4425
+ if (ui.isFunction(task.cancel))
4426
+ task.cancel();
4427
+ });
4428
+ };
4429
+ const onActionExit = () => {
4430
+ // clear files state
4431
+ locationItemsDispatch({ type: 'RESET_LOCATION_ITEMS' });
4432
+ // clear selected action
4433
+ storeDispatch({ type: 'RESET_ACTION_TYPE' });
4434
+ if (ui.isFunction(_onExit))
4435
+ _onExit(current);
4436
+ };
4437
+ const onTaskRemove = React__namespace["default"].useCallback(({ data }) => {
4438
+ locationItemsDispatch({ type: 'REMOVE_LOCATION_ITEM', id: data.id });
4439
+ }, [locationItemsDispatch]);
4440
+ return {
4441
+ isProcessing,
4442
+ isProcessingComplete,
4443
+ location,
4444
+ statusCounts,
4445
+ tasks,
4446
+ onActionCancel,
4447
+ onActionExit,
4448
+ onActionStart,
4449
+ onTaskRemove,
4450
+ };
4451
+ };
4452
+
4453
+ const DownloadView = ({ className, ...props }) => {
4454
+ const state = useDownloadView(props);
4455
+ return (React__namespace["default"].createElement(ViewElement, { className: ui.classNames(STORAGE_BROWSER_BLOCK, className) },
4456
+ React__namespace["default"].createElement(DownloadViewProvider, { ...state },
4457
+ React__namespace["default"].createElement(ActionExitControl, null),
4458
+ React__namespace["default"].createElement(TitleControl, null),
4459
+ React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__data-table` },
4460
+ React__namespace["default"].createElement(DataTableControl, null)),
4461
+ React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__summary` },
4462
+ React__namespace["default"].createElement(StatusDisplayControl, null)),
4463
+ React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__footer` },
4464
+ React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__message` },
4465
+ React__namespace["default"].createElement(MessageControl, null)),
4466
+ React__namespace["default"].createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__buttons` },
4467
+ React__namespace["default"].createElement(ActionCancelControl, null),
4468
+ React__namespace["default"].createElement(ActionStartControl, null))))));
4469
+ };
4470
+ DownloadView.displayName = 'DownloadView';
4471
+ DownloadView.Provider = DownloadViewProvider;
4472
+ DownloadView.Cancel = ActionCancelControl;
4473
+ DownloadView.Exit = ActionExitControl;
4474
+ DownloadView.Message = MessageControl;
4475
+ DownloadView.Start = ActionStartControl;
4476
+ DownloadView.Statuses = StatusDisplayControl;
4477
+ DownloadView.TasksTable = DataTableControl;
4478
+ DownloadView.Title = TitleControl;
4479
+
4293
4480
  const DEFAULT_ACTION_VIEWS = {
4294
4481
  createFolder: CreateFolderView,
4295
4482
  copy: CopyView,
4296
4483
  delete: DeleteView,
4484
+ download: DownloadView,
4297
4485
  upload: UploadView,
4298
4486
  };
4299
4487
  const ActionViewsContext = React__namespace["default"].createContext({
@@ -5141,6 +5329,7 @@ function useViews() {
5141
5329
  const USE_VIEW_HOOKS = {
5142
5330
  Copy: useCopyView,
5143
5331
  CreateFolder: useCreateFolderView,
5332
+ Download: useDownloadView,
5144
5333
  Delete: useDeleteView,
5145
5334
  LocationDetail: useLocationDetailView,
5146
5335
  Locations: useLocationsView,
@@ -5254,6 +5443,7 @@ function createStorageBrowser(input) {
5254
5443
  StorageBrowser.CopyView = CopyView;
5255
5444
  StorageBrowser.CreateFolderView = CreateFolderView;
5256
5445
  StorageBrowser.DeleteView = DeleteView;
5446
+ StorageBrowser.DownloadView = DownloadView;
5257
5447
  StorageBrowser.UploadView = UploadView;
5258
5448
  StorageBrowser.Provider = Provider;
5259
5449
  StorageBrowser.displayName = 'StorageBrowser';
@@ -41,12 +41,21 @@ const uploadActionConfig = {
41
41
  },
42
42
  handler: defaultHandlers.upload,
43
43
  };
44
+ const downloadActionConfig = {
45
+ viewName: 'DownloadView',
46
+ actionListItem: {
47
+ disable: (selected) => !selected || selected.length === 0,
48
+ hide: (permissions) => !permissions.includes('get'),
49
+ icon: 'download',
50
+ label: 'Download',
51
+ },
52
+ handler: defaultHandlers.download,
53
+ };
44
54
  // Action view configs only, does not include `listLocationItems`
45
55
  const defaultActionViewConfigs = {
46
56
  copy: copyActionConfig,
47
57
  createFolder: createFolderActionConfig,
48
- // provide `download` handler only; `download` does not have a dedicated view/config
49
- download: defaultHandlers.download,
58
+ download: downloadActionConfig,
50
59
  delete: deleteActionConfig,
51
60
  upload: uploadActionConfig,
52
61
  };
@@ -57,4 +66,4 @@ const defaultActionConfigs = {
57
66
  listLocationItems: defaultHandlers.listLocationItems,
58
67
  };
59
68
 
60
- export { DEFAULT_ACTION_VIEW_TYPES, copyActionConfig, createFolderActionConfig, defaultActionConfigs, defaultActionViewConfigs, deleteActionConfig, isDefaultActionViewType, uploadActionConfig };
69
+ export { DEFAULT_ACTION_VIEW_TYPES, copyActionConfig, createFolderActionConfig, defaultActionConfigs, defaultActionViewConfigs, deleteActionConfig, downloadActionConfig, isDefaultActionViewType, uploadActionConfig };
@@ -66,7 +66,7 @@ const listLocationItemsHandler = async (input) => {
66
66
  nextNextToken = output.nextToken;
67
67
  const items = parseResult(output, prefix);
68
68
  result.push(...(exclude ? items.filter((item) => item.type !== exclude) : items));
69
- } while (nextNextToken && result.length < pageSize);
69
+ } while (nextNextToken && result.length < _pageSize);
70
70
  return { items: result, nextToken: nextNextToken };
71
71
  };
72
72
 
@@ -15,6 +15,7 @@ import '../actions/configs/context.mjs';
15
15
  import '../actions/configs/defaults.mjs';
16
16
  import '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
17
17
  import '../views/LocationActionView/DeleteView/DeleteView.mjs';
18
+ import '../views/LocationActionView/DownloadView/DownloadView.mjs';
18
19
  import '../views/context/actionViews.mjs';
19
20
  import '../views/LocationActionView/UploadView/UploadView.mjs';
20
21
  import '../fileItems/context.mjs';
@@ -26,6 +26,7 @@ import { ViewsProvider } from '../views/context/views.mjs';
26
26
  import '../views/LocationActionView/CopyView/CopyView.mjs';
27
27
  import '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
28
28
  import '../views/LocationActionView/DeleteView/DeleteView.mjs';
29
+ import '../views/LocationActionView/DownloadView/DownloadView.mjs';
29
30
  import '../views/context/actionViews.mjs';
30
31
  import '../views/LocationActionView/UploadView/UploadView.mjs';
31
32
  import '../views/LocationDetailView/LocationDetailView.mjs';
@@ -20,6 +20,7 @@ import '../locationItems/context.mjs';
20
20
  import '../store/context.mjs';
21
21
  import { CreateFolderView } from '../views/LocationActionView/CreateFolderView/CreateFolderView.mjs';
22
22
  import { DeleteView } from '../views/LocationActionView/DeleteView/DeleteView.mjs';
23
+ import { DownloadView } from '../views/LocationActionView/DownloadView/DownloadView.mjs';
23
24
  import { LocationActionView } from '../views/LocationActionView/LocationActionView.mjs';
24
25
  import { UploadView } from '../views/LocationActionView/UploadView/UploadView.mjs';
25
26
  import '../fileItems/context.mjs';
@@ -61,6 +62,7 @@ function createStorageBrowser(input) {
61
62
  StorageBrowser.CopyView = CopyView;
62
63
  StorageBrowser.CreateFolderView = CreateFolderView;
63
64
  StorageBrowser.DeleteView = DeleteView;
65
+ StorageBrowser.DownloadView = DownloadView;
64
66
  StorageBrowser.UploadView = UploadView;
65
67
  StorageBrowser.Provider = Provider;
66
68
  StorageBrowser.displayName = 'StorageBrowser';