@aws-amplify/ui-react-storage 3.12.2 → 3.13.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 (92) hide show
  1. package/dist/browser.js +1 -1
  2. package/dist/{createStorageBrowser-pzJe4BD8.js → createStorageBrowser-DaVWyJzC.js} +1884 -1068
  3. package/dist/esm/browser.mjs +6 -2
  4. package/dist/esm/components/StorageBrowser/ErrorBoundary/ErrorBoundary.mjs +9 -0
  5. package/dist/esm/components/StorageBrowser/components/ComponentsProvider.mjs +9 -0
  6. package/dist/esm/components/StorageBrowser/components/base/Table.mjs +1 -1
  7. package/dist/esm/components/StorageBrowser/components/base/preview/DownloadButton.mjs +39 -0
  8. package/dist/esm/components/StorageBrowser/components/base/preview/FileMetadata.mjs +40 -0
  9. package/dist/esm/components/StorageBrowser/components/base/preview/FilePreviewLayout.mjs +19 -0
  10. package/dist/esm/components/StorageBrowser/components/base/preview/ImagePreview.mjs +37 -0
  11. package/dist/esm/components/StorageBrowser/components/base/preview/PreviewFallback.mjs +34 -0
  12. package/dist/esm/components/StorageBrowser/components/base/preview/PreviewPlaceholder.mjs +13 -0
  13. package/dist/esm/components/StorageBrowser/components/base/preview/TextPreview.mjs +64 -0
  14. package/dist/esm/components/StorageBrowser/components/base/preview/VideoPreview.mjs +61 -0
  15. package/dist/esm/components/StorageBrowser/components/composables/DataTable/DataTable.mjs +2 -1
  16. package/dist/esm/components/StorageBrowser/components/composables/FilePreview.mjs +85 -0
  17. package/dist/esm/components/StorageBrowser/components/composables/defaults.mjs +2 -0
  18. package/dist/esm/components/StorageBrowser/components/elements/definitions.mjs +2 -2
  19. package/dist/esm/components/StorageBrowser/controls/DataTableControl.mjs +9 -0
  20. package/dist/esm/components/StorageBrowser/controls/FilePreviewControl.mjs +24 -0
  21. package/dist/esm/components/StorageBrowser/createStorageBrowser/StorageBrowserDefault.mjs +1 -0
  22. package/dist/esm/components/StorageBrowser/createStorageBrowser/createProvider.mjs +4 -2
  23. package/dist/esm/components/StorageBrowser/createStorageBrowser/createStorageBrowser.mjs +1 -0
  24. package/dist/esm/components/StorageBrowser/displayText/context.mjs +4 -0
  25. package/dist/esm/components/StorageBrowser/displayText/libraries/en/locationDetailView.mjs +28 -0
  26. package/dist/esm/components/StorageBrowser/filePreview/context.mjs +12 -0
  27. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyView.mjs +9 -0
  28. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/CopyViewProvider.mjs +8 -0
  29. package/dist/esm/components/StorageBrowser/views/LocationActionView/CopyView/FoldersMessageControl.mjs +8 -0
  30. package/dist/esm/components/StorageBrowser/views/LocationActionView/CreateFolderView/CreateFolderView.mjs +9 -0
  31. package/dist/esm/components/StorageBrowser/views/LocationActionView/DeleteView/DeleteView.mjs +9 -0
  32. package/dist/esm/components/StorageBrowser/views/LocationActionView/DownloadView/DownloadView.mjs +9 -0
  33. package/dist/esm/components/StorageBrowser/views/LocationActionView/UploadView/UploadView.mjs +9 -0
  34. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailView.mjs +17 -4
  35. package/dist/esm/components/StorageBrowser/views/LocationDetailView/LocationDetailViewProvider.mjs +9 -2
  36. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/constants.mjs +69 -1
  37. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/fileIcon.mjs +11 -0
  38. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFileRowContent.mjs +8 -5
  39. package/dist/esm/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.mjs +8 -1
  40. package/dist/esm/components/StorageBrowser/views/LocationDetailView/useLocationDetailView.mjs +76 -3
  41. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsView.mjs +9 -0
  42. package/dist/esm/components/StorageBrowser/views/LocationsView/LocationsViewProvider.mjs +8 -0
  43. package/dist/esm/components/StorageBrowser/views/context/primaryViews.mjs +1 -0
  44. package/dist/esm/components/StorageBrowser/views/hooks/useFilePreview/useFilePreview.mjs +115 -0
  45. package/dist/esm/components/StorageBrowser/views/utils/files/const.mjs +62 -0
  46. package/dist/esm/components/StorageBrowser/views/utils/files/fileName.mjs +12 -0
  47. package/dist/esm/components/StorageBrowser/views/utils/files/fileSize.mjs +23 -0
  48. package/dist/esm/components/StorageBrowser/views/utils/files/fileType.mjs +87 -0
  49. package/dist/esm/components/StorageBrowser/views/utils/files/safeGetProperties.mjs +12 -0
  50. package/dist/esm/components/StorageBrowser/views/utils/files/url.mjs +16 -0
  51. package/dist/esm/version.mjs +1 -1
  52. package/dist/index.js +1 -1
  53. package/dist/styles.css +250 -0
  54. package/dist/types/components/StorageBrowser/actions/configs/defaults.d.ts +2 -2
  55. package/dist/types/components/StorageBrowser/actions/handlers/types.d.ts +4 -0
  56. package/dist/types/components/StorageBrowser/components/base/Table.d.ts +1 -0
  57. package/dist/types/components/StorageBrowser/components/base/preview/DownloadButton.d.ts +4 -0
  58. package/dist/types/components/StorageBrowser/components/base/preview/FileMetadata.d.ts +7 -0
  59. package/dist/types/components/StorageBrowser/components/base/preview/FilePreviewLayout.d.ts +8 -0
  60. package/dist/types/components/StorageBrowser/components/base/preview/ImagePreview.d.ts +3 -0
  61. package/dist/types/components/StorageBrowser/components/base/preview/PreviewFallback.d.ts +10 -0
  62. package/dist/types/components/StorageBrowser/components/base/preview/PreviewPlaceholder.d.ts +2 -0
  63. package/dist/types/components/StorageBrowser/components/base/preview/TextPreview.d.ts +3 -0
  64. package/dist/types/components/StorageBrowser/components/base/preview/VideoPreview.d.ts +3 -0
  65. package/dist/types/components/StorageBrowser/components/base/preview/type.d.ts +6 -0
  66. package/dist/types/components/StorageBrowser/components/composables/DataTable/DataTable.d.ts +1 -0
  67. package/dist/types/components/StorageBrowser/components/composables/FilePreview.d.ts +12 -0
  68. package/dist/types/components/StorageBrowser/components/composables/types.d.ts +2 -0
  69. package/dist/types/components/StorageBrowser/controls/FilePreviewControl.d.ts +2 -0
  70. package/dist/types/components/StorageBrowser/controls/types.d.ts +11 -2
  71. package/dist/types/components/StorageBrowser/createStorageBrowser/createProvider.d.ts +2 -1
  72. package/dist/types/components/StorageBrowser/createStorageBrowser/createStorageBrowser.d.ts +4 -1
  73. package/dist/types/components/StorageBrowser/createStorageBrowser/types.d.ts +78 -2
  74. package/dist/types/components/StorageBrowser/displayText/types.d.ts +30 -1
  75. package/dist/types/components/StorageBrowser/filePreview/context.d.ts +10 -0
  76. package/dist/types/components/StorageBrowser/filePreview/index.d.ts +1 -0
  77. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/constants.d.ts +6 -0
  78. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/fileIcon.d.ts +2 -0
  79. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getFileRowContent.d.ts +3 -1
  80. package/dist/types/components/StorageBrowser/views/LocationDetailView/getLocationDetailViewTableData/getLocationDetailViewTableData.d.ts +5 -2
  81. package/dist/types/components/StorageBrowser/views/LocationDetailView/types.d.ts +10 -0
  82. package/dist/types/components/StorageBrowser/views/hooks/useFilePreview/index.d.ts +2 -0
  83. package/dist/types/components/StorageBrowser/views/hooks/useFilePreview/types.d.ts +28 -0
  84. package/dist/types/components/StorageBrowser/views/hooks/useFilePreview/useFilePreview.d.ts +5 -0
  85. package/dist/types/components/StorageBrowser/views/utils/files/const.d.ts +9 -0
  86. package/dist/types/components/StorageBrowser/views/utils/files/fileName.d.ts +6 -0
  87. package/dist/types/components/StorageBrowser/views/utils/files/fileSize.d.ts +2 -0
  88. package/dist/types/components/StorageBrowser/views/utils/files/fileType.d.ts +12 -0
  89. package/dist/types/components/StorageBrowser/views/utils/files/safeGetProperties.d.ts +2 -0
  90. package/dist/types/components/StorageBrowser/views/utils/files/url.d.ts +2 -0
  91. package/dist/types/version.d.ts +1 -1
  92. package/package.json +6 -6
@@ -1,6 +1,33 @@
1
1
  import { DEFAULT_LIST_VIEW_DISPLAY_TEXT } from './shared.mjs';
2
2
 
3
3
  const DEFAULT_ERROR_MESSAGE = 'There was an error loading items.';
4
+ const DEFAULT_FILE_PREVIEW_DISPLAY_TEXT = {
5
+ closeButtonLabel: 'Close',
6
+ filePreviewTitle: 'File Preview',
7
+ fileInformationTitle: 'File Information',
8
+ errorMessage: 'Something went wrong',
9
+ sizeLimitMessage: 'File preview not possible due to preview size limit',
10
+ unsupportedFileMessage: 'File preview not supported for this file type',
11
+ keyLabel: 'Key',
12
+ sizeLabel: 'Size',
13
+ versionIdLabel: 'Version Id',
14
+ lastModifiedLabel: 'Last Modified',
15
+ entityTagLabel: 'Entity tag',
16
+ typeLabel: 'Type',
17
+ unknownValue: 'Unknown',
18
+ errorDescription: 'We encountered an issue while loading the file preview.',
19
+ unsupportedFileDescription: 'This file format is not supported for preview. You can download the file to view it with an appropriate application.',
20
+ imageLoadErrorDescription: 'The image could not be loaded. This may be due to network issues, file corruption, or an unsupported image format.',
21
+ videoLoadErrorDescription: 'The video could not be played. This may be due to network issues, file corruption, or an unsupported video format or codec.',
22
+ textLoadErrorDescription: 'The text file could not be loaded. This may be due to network issues, file access permissions, or the file being too large to display.',
23
+ generalPreviewErrorDescription: 'An unexpected error occurred while loading the file preview. Please try again or download the file to view it with an appropriate application.',
24
+ fileSizeLimitDescription: 'This file is too large to preview in the browser. You can download the file to view it with an appropriate application.',
25
+ filePrefix: 'File: ',
26
+ retryButtonLabel: 'Retry',
27
+ downloadButtonLabel: 'Download',
28
+ getTextErrorMessage: (error) => `Error loading file: ${error}`,
29
+ emptyFileMessage: 'File is empty',
30
+ };
4
31
  const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT = {
5
32
  ...DEFAULT_LIST_VIEW_DISPLAY_TEXT,
6
33
  getListItemsResultMessage: (data) => {
@@ -64,6 +91,7 @@ const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT = {
64
91
  const { bucket = '' } = current ?? {};
65
92
  return key || bucket;
66
93
  },
94
+ filePreview: DEFAULT_FILE_PREVIEW_DISPLAY_TEXT,
67
95
  };
68
96
 
69
97
  export { DEFAULT_ERROR_MESSAGE, DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT };
@@ -0,0 +1,12 @@
1
+ import React__default from 'react';
2
+ import { createContextUtilities } from '@aws-amplify/ui-react-core';
3
+
4
+ const { FilePreviewContext, useFilePreview: useFilePreviewContext } = createContextUtilities({
5
+ contextName: 'FilePreview',
6
+ defaultValue: {},
7
+ });
8
+ function FilePreviewProvider({ children, filePreview, }) {
9
+ return (React__default.createElement(FilePreviewContext.Provider, { value: filePreview }, children));
10
+ }
11
+
12
+ export { FilePreviewContext, FilePreviewProvider, useFilePreviewContext };
@@ -6,7 +6,16 @@ import '../../../components/elements/IconElement.mjs';
6
6
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
7
7
  import '../../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../../actions/configs/context.mjs';
16
+ import '../../../actions/configs/defaults.mjs';
17
+ import '../../../displayText/context.mjs';
18
+ import '../../../filePreview/context.mjs';
10
19
  import { ActionCancelControl } from '../../../controls/ActionCancelControl.mjs';
11
20
  import { ActionExitControl } from '../../../controls/ActionExitControl.mjs';
12
21
  import { ActionStartControl } from '../../../controls/ActionStartControl.mjs';
@@ -6,8 +6,16 @@ import '../../../components/elements/IconElement.mjs';
6
6
  import { ControlsContextProvider } from '../../../controls/context.mjs';
7
7
  import '../../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../../actions/configs/context.mjs';
16
+ import '../../../actions/configs/defaults.mjs';
10
17
  import { useDisplayText } from '../../../displayText/context.mjs';
18
+ import '../../../filePreview/context.mjs';
11
19
  import useResolveTableData from '../../hooks/useResolveTableData/useResolveTableData.mjs';
12
20
  import { COPY_TABLE_RESOLVERS } from '../../utils/tableResolvers/copyResolvers.mjs';
13
21
  import { FILE_DATA_ITEM_TABLE_KEYS } from '../../utils/tableResolvers/constants.mjs';
@@ -8,8 +8,16 @@ import '../../../components/elements/IconElement.mjs';
8
8
  import '@aws-amplify/ui';
9
9
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
10
10
  import '../../../components/composables/context.mjs';
11
+ import '../../../useAction/context.mjs';
11
12
  import '@aws-amplify/ui-react-core/elements';
13
+ import '../../../credentials/context.mjs';
14
+ import '@aws-amplify/storage/internals';
15
+ import '../../../configuration/context.mjs';
16
+ import 'aws-amplify/storage';
17
+ import '../../../actions/configs/context.mjs';
18
+ import '../../../actions/configs/defaults.mjs';
12
19
  import { useDisplayText } from '../../../displayText/context.mjs';
20
+ import '../../../filePreview/context.mjs';
13
21
 
14
22
  const defaultValue = {};
15
23
  const { useFoldersMessage, FoldersMessageProvider } = createContextUtilities({ contextName: 'FoldersMessage', defaultValue });
@@ -6,7 +6,16 @@ import '../../../components/elements/IconElement.mjs';
6
6
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
7
7
  import '../../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../../actions/configs/context.mjs';
16
+ import '../../../actions/configs/defaults.mjs';
17
+ import '../../../displayText/context.mjs';
18
+ import '../../../filePreview/context.mjs';
10
19
  import { ActionStartControl } from '../../../controls/ActionStartControl.mjs';
11
20
  import { ActionExitControl } from '../../../controls/ActionExitControl.mjs';
12
21
  import { FolderNameFieldControl } from '../../../controls/FolderNameFieldControl.mjs';
@@ -13,7 +13,16 @@ import { classNames } from '@aws-amplify/ui';
13
13
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
14
14
  import '../../../components/composables/context.mjs';
15
15
  import '@aws-amplify/ui-react-core';
16
+ import '../../../useAction/context.mjs';
16
17
  import '@aws-amplify/ui-react-core/elements';
18
+ import '../../../credentials/context.mjs';
19
+ import '@aws-amplify/storage/internals';
20
+ import '../../../configuration/context.mjs';
21
+ import 'aws-amplify/storage';
22
+ import '../../../actions/configs/context.mjs';
23
+ import '../../../actions/configs/defaults.mjs';
24
+ import '../../../displayText/context.mjs';
25
+ import '../../../filePreview/context.mjs';
17
26
  import { DeleteViewProvider } from './DeleteViewProvider.mjs';
18
27
  import { useDeleteView } from './useDeleteView.mjs';
19
28
 
@@ -13,7 +13,16 @@ import { classNames } from '@aws-amplify/ui';
13
13
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
14
14
  import '../../../components/composables/context.mjs';
15
15
  import '@aws-amplify/ui-react-core';
16
+ import '../../../useAction/context.mjs';
16
17
  import '@aws-amplify/ui-react-core/elements';
18
+ import '../../../credentials/context.mjs';
19
+ import '@aws-amplify/storage/internals';
20
+ import '../../../configuration/context.mjs';
21
+ import 'aws-amplify/storage';
22
+ import '../../../actions/configs/context.mjs';
23
+ import '../../../actions/configs/defaults.mjs';
24
+ import '../../../displayText/context.mjs';
25
+ import '../../../filePreview/context.mjs';
17
26
  import { DownloadViewProvider } from './DownloadViewProvider.mjs';
18
27
  import { useDownloadView } from './useDownloadView.mjs';
19
28
 
@@ -6,7 +6,16 @@ import '../../../components/elements/IconElement.mjs';
6
6
  import { STORAGE_BROWSER_BLOCK } from '../../../components/base/constants.mjs';
7
7
  import '../../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../../actions/configs/context.mjs';
16
+ import '../../../actions/configs/defaults.mjs';
17
+ import '../../../displayText/context.mjs';
18
+ import '../../../filePreview/context.mjs';
10
19
  import { ActionCancelControl } from '../../../controls/ActionCancelControl.mjs';
11
20
  import { ActionDestinationControl } from '../../../controls/ActionDestinationControl.mjs';
12
21
  import { ActionExitControl } from '../../../controls/ActionExitControl.mjs';
@@ -6,7 +6,16 @@ import '../../components/elements/IconElement.mjs';
6
6
  import { STORAGE_BROWSER_BLOCK } from '../../components/base/constants.mjs';
7
7
  import '../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../actions/configs/context.mjs';
16
+ import '../../actions/configs/defaults.mjs';
17
+ import '../../displayText/context.mjs';
18
+ import '../../filePreview/context.mjs';
10
19
  import '../../controls/context.mjs';
11
20
  import { ActionsListControl } from '../../controls/ActionsListControl.mjs';
12
21
  import { DataRefreshControl } from '../../controls/DataRefreshControl.mjs';
@@ -21,6 +30,7 @@ import { SearchSubfoldersToggleControl } from '../../controls/SearchSubfoldersTo
21
30
  import { TitleControl } from '../../controls/TitleControl.mjs';
22
31
  import { LocationDetailViewProvider } from './LocationDetailViewProvider.mjs';
23
32
  import { useLocationDetailView } from './useLocationDetailView.mjs';
33
+ import { FilePreviewControl } from '../../controls/FilePreviewControl.mjs';
24
34
 
25
35
  const LocationDetailView = ({ className, ...props }) => {
26
36
  const state = useLocationDetailView(props);
@@ -36,10 +46,12 @@ const LocationDetailView = ({ className, ...props }) => {
36
46
  React__default.createElement(PaginationControl, null),
37
47
  React__default.createElement(DataRefreshControl, null),
38
48
  React__default.createElement(ActionsListControl, null)),
39
- hasError ? null : (React__default.createElement(DropZoneControl, null,
40
- React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__data-table` },
41
- React__default.createElement(LoadingIndicatorControl, null),
42
- React__default.createElement(DataTableControl, null)))),
49
+ hasError ? null : (React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__content-with-preview` },
50
+ React__default.createElement(DropZoneControl, null,
51
+ React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__data-table` },
52
+ React__default.createElement(LoadingIndicatorControl, null),
53
+ React__default.createElement(DataTableControl, null))),
54
+ React__default.createElement(FilePreviewControl, null))),
43
55
  React__default.createElement(ViewElement, { className: `${STORAGE_BROWSER_BLOCK}__footer` },
44
56
  React__default.createElement(MessageControl, null)))));
45
57
  };
@@ -56,5 +68,6 @@ LocationDetailView.Refresh = DataRefreshControl;
56
68
  LocationDetailView.Search = SearchFieldControl;
57
69
  LocationDetailView.SearchSubfoldersToggle = SearchSubfoldersToggleControl;
58
70
  LocationDetailView.Title = TitleControl;
71
+ LocationDetailView.FilePreview = FilePreviewControl;
59
72
 
60
73
  export { LocationDetailView };
@@ -6,7 +6,7 @@ import { getLocationDetailViewTableData } from './getLocationDetailViewTableData
6
6
  function LocationDetailViewProvider({ children, ...props }) {
7
7
  const { LocationDetailView: displayText } = useDisplayText();
8
8
  const { LocationDetailView: { loadingIndicatorLabel, searchSubfoldersToggleLabel, selectFileLabel, selectAllFilesLabel, searchPlaceholder, searchSubmitLabel, searchClearLabel, getActionListItemLabel, getDateDisplayValue, getTitle, getListItemsResultMessage, }, } = useDisplayText();
9
- const { actionItems, page, pageItems, hasNextPage, highestPageVisited, isLoading, isSearchSubfoldersEnabled, location, fileDataItems, hasError, hasDownloadError, message, downloadErrorMessage, searchQuery, hasExhaustedSearch, onActionSelect, onDropFiles, onRefresh, onPaginate, onDownload, onNavigate, onNavigateHome, onSelect, onToggleSelectAll, onSearch, onSearchQueryChange, onSearchClear, onToggleSearchSubfolders, } = props;
9
+ const { actionItems, activeFile, activeFileHasNext, activeFileHasPrev, page, pageItems, hasNextPage, highestPageVisited, isLoading, isSearchSubfoldersEnabled, location, fileDataItems, hasError, hasDownloadError, message, downloadErrorMessage, searchQuery, hasExhaustedSearch, onActionSelect, onDropFiles, onRefresh, onPaginate, onDownload, onNavigate, onNavigateHome, onSelect, onSelectActiveFile, onToggleSelectAll, onSearch, onSearchQueryChange, onSearchClear, onToggleSearchSubfolders, filePreviewState, filePreviewEnabled, onRetryFilePreview, } = props;
10
10
  const actionsWithDisplayText = actionItems.map((item) => ({
11
11
  ...item,
12
12
  label: getActionListItemLabel(item.label),
@@ -26,6 +26,9 @@ function LocationDetailViewProvider({ children, ...props }) {
26
26
  actionItems.every(({ isHidden }) => isHidden);
27
27
  return (React__default.createElement(ControlsContextProvider, { data: {
28
28
  actions: actionsWithDisplayText,
29
+ activeFile,
30
+ activeFileHasNext,
31
+ activeFileHasPrev,
29
32
  isActionsListDisabled,
30
33
  isDataRefreshDisabled: isLoading,
31
34
  isLoading,
@@ -42,7 +45,11 @@ function LocationDetailViewProvider({ children, ...props }) {
42
45
  searchSubmitLabel,
43
46
  searchClearLabel,
44
47
  searchQuery,
48
+ filePreviewState,
45
49
  tableData: getLocationDetailViewTableData({
50
+ filePreviewEnabled,
51
+ activeFile,
52
+ onSelectActiveFile,
46
53
  areAllFilesSelected,
47
54
  displayText,
48
55
  location,
@@ -59,7 +66,7 @@ function LocationDetailViewProvider({ children, ...props }) {
59
66
  }),
60
67
  title: getTitle(location),
61
68
  message: messageControlContent,
62
- }, onActionSelect: onActionSelect, onDropFiles: onDropFiles, onNavigate: onNavigate, onNavigateHome: onNavigateHome, onPaginate: onPaginate, onRefresh: onRefresh, onSearch: onSearch, onSearchQueryChange: onSearchQueryChange, onSearchClear: onSearchClear, onToggleSearchSubfolders: onToggleSearchSubfolders }, children));
69
+ }, onActionSelect: onActionSelect, onDropFiles: onDropFiles, onNavigate: onNavigate, onNavigateHome: onNavigateHome, onPaginate: onPaginate, onRefresh: onRefresh, onSearch: onSearch, onSelectActiveFile: onSelectActiveFile, onSearchQueryChange: onSearchQueryChange, onSearchClear: onSearchClear, onToggleSearchSubfolders: onToggleSearchSubfolders, onRetryFilePreview: onRetryFilePreview }, children));
63
70
  }
64
71
 
65
72
  export { LocationDetailViewProvider };
@@ -6,5 +6,73 @@ const LOCATION_DETAIL_VIEW_HEADERS = [
6
6
  'size',
7
7
  'download',
8
8
  ];
9
+ const GENERIC_FILE_ICON = 'file';
10
+ const EXTENSION_THUMBNAIL_MAPPINGS = {
11
+ // Images
12
+ jpg: 'file-image',
13
+ jpeg: 'file-image',
14
+ png: 'file-image',
15
+ gif: 'file-image',
16
+ webp: 'file-image',
17
+ svg: 'file-image',
18
+ bmp: 'file-image',
19
+ tiff: 'file-image',
20
+ tif: 'file-image',
21
+ ico: 'file-image',
22
+ heic: 'file-image',
23
+ heif: 'file-image',
24
+ avif: 'file-image',
25
+ // Videos
26
+ mp4: 'file-video',
27
+ avi: 'file-video',
28
+ mov: 'file-video',
29
+ wmv: 'file-video',
30
+ flv: 'file-video',
31
+ webm: 'file-video',
32
+ mkv: 'file-video',
33
+ m4v: 'file-video',
34
+ mpg: 'file-video',
35
+ mpeg: 'file-video',
36
+ '3gp': 'file-video',
37
+ ogv: 'file-video',
38
+ // Plain text files only
39
+ txt: 'file-text',
40
+ log: 'file-text',
41
+ json: 'file-text',
42
+ xml: 'file-text',
43
+ yaml: 'file-text',
44
+ yml: 'file-text',
45
+ ini: 'file-text',
46
+ conf: 'file-text',
47
+ cfg: 'file-text',
48
+ // Audio
49
+ mp3: 'file-audio',
50
+ wav: 'file-audio',
51
+ flac: 'file-audio',
52
+ aac: 'file-audio',
53
+ ogg: 'file-audio',
54
+ wma: 'file-audio',
55
+ m4a: 'file-audio',
56
+ // Documents
57
+ pdf: 'file-pdf',
58
+ // Excel
59
+ xls: 'file-excel',
60
+ xlsx: 'file-excel',
61
+ csv: 'file-excel',
62
+ // Word
63
+ doc: 'file-word',
64
+ docx: 'file-word',
65
+ rtf: 'file-word',
66
+ // PowerPoint
67
+ ppt: 'file-powerpoint',
68
+ pptx: 'file-powerpoint',
69
+ // Archives
70
+ zip: 'file-archive',
71
+ rar: 'file-archive',
72
+ '7z': 'file-archive',
73
+ tar: 'file-archive',
74
+ gz: 'file-archive',
75
+ bz2: 'file-archive',
76
+ };
9
77
 
10
- export { LOCATION_DETAIL_VIEW_HEADERS };
78
+ export { EXTENSION_THUMBNAIL_MAPPINGS, GENERIC_FILE_ICON, LOCATION_DETAIL_VIEW_HEADERS };
@@ -0,0 +1,11 @@
1
+ import { getFileExtension } from '../../utils/files/fileType.mjs';
2
+ import { GENERIC_FILE_ICON, EXTENSION_THUMBNAIL_MAPPINGS } from './constants.mjs';
3
+
4
+ function getFileThumbnail(fileKey) {
5
+ const extension = getFileExtension(fileKey);
6
+ if (!fileKey || !extension)
7
+ return GENERIC_FILE_ICON;
8
+ return EXTENSION_THUMBNAIL_MAPPINGS[extension] || GENERIC_FILE_ICON;
9
+ }
10
+
11
+ export { getFileThumbnail };
@@ -1,7 +1,8 @@
1
1
  import { humanFileSize } from '@aws-amplify/ui';
2
2
  import { LOCATION_DETAIL_VIEW_HEADERS } from './constants.mjs';
3
+ import { getFileThumbnail } from './fileIcon.mjs';
3
4
 
4
- const getFileRowContent = ({ permissions, isSelected, itemLocationKey, getDateDisplayValue, lastModified, rowId, rowKey, selectFileLabel, size, onDownload, onSelect, }) => LOCATION_DETAIL_VIEW_HEADERS.map((columnKey) => {
5
+ const getFileRowContent = ({ filePreviewEnabled, permissions, isSelected, itemLocationKey, getDateDisplayValue, lastModified, rowId, rowKey, selectFileLabel, size, onDownload, onSelect, onClick, }) => LOCATION_DETAIL_VIEW_HEADERS.map((columnKey) => {
5
6
  const key = `${columnKey}-${rowId}`;
6
7
  switch (columnKey) {
7
8
  case 'checkbox': {
@@ -19,11 +20,13 @@ const getFileRowContent = ({ permissions, isSelected, itemLocationKey, getDateDi
19
20
  case 'name': {
20
21
  return {
21
22
  key,
22
- type: 'text',
23
+ type: filePreviewEnabled ? 'button' : 'text',
23
24
  content: {
24
- icon: 'file',
25
- ariaLabel: 'file',
26
- text: rowKey.slice(itemLocationKey.length),
25
+ icon: getFileThumbnail(rowKey),
26
+ ariaLabel: `${rowKey.slice(itemLocationKey.length)} file`,
27
+ ...(filePreviewEnabled
28
+ ? { label: rowKey.slice(itemLocationKey.length), onClick }
29
+ : { text: rowKey.slice(itemLocationKey.length) }),
27
30
  },
28
31
  };
29
32
  }
@@ -8,7 +8,7 @@ import { getFileRowContent } from './getFileRowContent.mjs';
8
8
  import { getFolderRowContent } from './getFolderRowContent.mjs';
9
9
  import { getHeaders } from './getHeaders.mjs';
10
10
 
11
- const getLocationDetailViewTableData = ({ areAllFilesSelected, displayText, location, fileDataItems, hasFiles, pageItems, selectFileLabel, selectAllFilesLabel, getDateDisplayValue, onDownload, onNavigate, onSelect, onSelectAll, }) => {
11
+ const getLocationDetailViewTableData = ({ filePreviewEnabled, activeFile, onSelectActiveFile, areAllFilesSelected, displayText, location, fileDataItems, hasFiles, pageItems, selectFileLabel, selectAllFilesLabel, getDateDisplayValue, onDownload, onNavigate, onSelect, onSelectAll, }) => {
12
12
  const { tableColumnLastModifiedHeader, tableColumnNameHeader, tableColumnSizeHeader, tableColumnTypeHeader, } = displayText;
13
13
  const headers = getHeaders({
14
14
  areAllFilesSelected,
@@ -33,9 +33,14 @@ const getLocationDetailViewTableData = ({ areAllFilesSelected, displayText, loca
33
33
  const onFileSelect = () => {
34
34
  onSelect(isSelected, locationItem);
35
35
  };
36
+ const onClick = () => {
37
+ onSelectActiveFile(locationItem);
38
+ };
36
39
  return {
37
40
  key: id,
41
+ active: activeFile?.id === id,
38
42
  content: getFileRowContent({
43
+ filePreviewEnabled,
39
44
  permissions: current?.permissions ?? [],
40
45
  isSelected,
41
46
  itemLocationKey: `${current?.prefix ?? ''}${path}`,
@@ -47,6 +52,7 @@ const getLocationDetailViewTableData = ({ areAllFilesSelected, displayText, loca
47
52
  size,
48
53
  onDownload: onFileDownload,
49
54
  onSelect: onFileSelect,
55
+ onClick,
50
56
  }),
51
57
  };
52
58
  }
@@ -62,6 +68,7 @@ const getLocationDetailViewTableData = ({ areAllFilesSelected, displayText, loca
62
68
  };
63
69
  return {
64
70
  key: id,
71
+ active: false,
65
72
  content: getFolderRowContent({
66
73
  itemSubPath,
67
74
  rowId: id,
@@ -1,4 +1,4 @@
1
- import React__default from 'react';
1
+ import React__default, { useCallback } from 'react';
2
2
  import { isUndefined, isFunction } from '@aws-amplify/ui';
3
3
  import { usePaginate } from '../hooks/usePaginate.mjs';
4
4
  import '@aws-amplify/storage/internals';
@@ -12,6 +12,7 @@ import '../../useAction/context.mjs';
12
12
  import { useAction } from '../../useAction/useAction.mjs';
13
13
  import { useList } from '../../useAction/useList.mjs';
14
14
  import { useSearch } from '../hooks/useSearch.mjs';
15
+ import { useFilePreview } from '../hooks/useFilePreview/useFilePreview.mjs';
15
16
 
16
17
  const DEFAULT_PAGE_SIZE = 100;
17
18
  const DEFAULT_LIST_OPTIONS = {
@@ -33,6 +34,7 @@ const useLocationDetailView = (options) => {
33
34
  const [{ location, actionType }, storeDispatch] = useStore();
34
35
  const [locationItems, locationItemsDispatch] = useLocationItems();
35
36
  const fileItemsDispatch = useFileItems()[1];
37
+ const [activeFile, setActiveFile] = React__default.useState();
36
38
  const { current, key } = location;
37
39
  const { permissions, prefix } = current ?? {};
38
40
  const { fileDataItems } = locationItems;
@@ -71,7 +73,62 @@ const useLocationDetailView = (options) => {
71
73
  handleList({ prefix: key, options: searchOptions });
72
74
  locationItemsDispatch({ type: 'RESET_LOCATION_ITEMS' });
73
75
  };
76
+ const { activeFileHasPrev, activeFileHasNext } = React__default.useMemo(() => {
77
+ if (!activeFile)
78
+ return {
79
+ activeFileHasNext: false,
80
+ activeFileHasPrev: false,
81
+ };
82
+ const idx = pageItems.findIndex((item) => item.id === activeFile?.id);
83
+ let pIdx = idx;
84
+ do {
85
+ --pIdx;
86
+ } while (pIdx >= 0 && pageItems[pIdx].type !== 'FILE');
87
+ let nIdx = idx;
88
+ do {
89
+ ++nIdx;
90
+ } while (nIdx <= pageItems.length - 1 && pageItems[nIdx].type !== 'FILE');
91
+ return {
92
+ activeFileHasPrev: pIdx >= 0,
93
+ activeFileHasNext: nIdx <= pageItems.length - 1,
94
+ };
95
+ }, [activeFile, pageItems]);
96
+ const getSuitableNextItem = useCallback((direction, type) => {
97
+ // first find the position
98
+ let newIdx = pageItems.findIndex((item) => item.id === activeFile?.id);
99
+ if (direction === 'prev') {
100
+ do {
101
+ --newIdx;
102
+ } while (newIdx >= 0 && pageItems[newIdx].type !== type);
103
+ if (pageItems[newIdx].type === type) {
104
+ return pageItems[newIdx];
105
+ }
106
+ }
107
+ else {
108
+ do {
109
+ ++newIdx;
110
+ } while (newIdx <= pageItems.length - 1 &&
111
+ pageItems[newIdx].type !== type);
112
+ if (pageItems[newIdx].type === type) {
113
+ return pageItems[newIdx];
114
+ }
115
+ }
116
+ }, [activeFile, pageItems]);
117
+ const onSelectActiveFile = (arg) => {
118
+ if (arg === 'prev') {
119
+ setActiveFile(getSuitableNextItem('prev', 'FILE'));
120
+ }
121
+ else if (arg === 'next') {
122
+ setActiveFile(getSuitableNextItem('next', 'FILE'));
123
+ }
124
+ else {
125
+ setActiveFile(arg);
126
+ }
127
+ };
74
128
  const { searchQuery, isSearchingSubfolders: isSearchSubfoldersEnabled, onSearchQueryChange, onSearchSubmit, onToggleSearchSubfolders, resetSearch, } = useSearch({ onSearch });
129
+ const { handleRetry, optout, ...filePreviewState } = useFilePreview({
130
+ activeFile,
131
+ });
75
132
  const onRefresh = () => {
76
133
  if (hasInvalidPrefix)
77
134
  return;
@@ -81,6 +138,7 @@ const useLocationDetailView = (options) => {
81
138
  prefix: key,
82
139
  options: { ...listOptions, refresh: true },
83
140
  });
141
+ setActiveFile(undefined);
84
142
  locationItemsDispatch({ type: 'RESET_LOCATION_ITEMS' });
85
143
  };
86
144
  React__default.useEffect(() => {
@@ -91,6 +149,7 @@ const useLocationDetailView = (options) => {
91
149
  options: { ...listOptions, refresh: true },
92
150
  });
93
151
  handleReset();
152
+ setActiveFile(undefined);
94
153
  }, [handleList, handleReset, listOptions, hasInvalidPrefix, key]);
95
154
  const { actionConfigs } = useActionConfigs();
96
155
  const actionItems = React__default.useMemo(() => {
@@ -115,6 +174,10 @@ const useLocationDetailView = (options) => {
115
174
  return {
116
175
  actionItems,
117
176
  actionType,
177
+ activeFile,
178
+ activeFileHasNext,
179
+ activeFileHasPrev,
180
+ onSelectActiveFile,
118
181
  page: currentPage,
119
182
  pageItems,
120
183
  location,
@@ -127,8 +190,13 @@ const useLocationDetailView = (options) => {
127
190
  downloadErrorMessage: getDownloadErrorMessageFromFailedDownloadTask(task),
128
191
  isLoading,
129
192
  isSearchSubfoldersEnabled,
130
- onPaginate: handlePaginate,
193
+ onPaginate: (p) => {
194
+ handlePaginate(p);
195
+ setActiveFile(undefined);
196
+ },
131
197
  searchQuery,
198
+ filePreviewState,
199
+ filePreviewEnabled: !optout,
132
200
  hasExhaustedSearch,
133
201
  onRefresh,
134
202
  onActionExit: () => {
@@ -146,6 +214,7 @@ const useLocationDetailView = (options) => {
146
214
  resetSearch();
147
215
  storeDispatch({ type: 'CHANGE_LOCATION', location, path });
148
216
  locationItemsDispatch({ type: 'RESET_LOCATION_ITEMS' });
217
+ setActiveFile(undefined);
149
218
  },
150
219
  onDropFiles: (files) => {
151
220
  fileItemsDispatch({ type: 'ADD_FILES', files });
@@ -178,7 +247,10 @@ const useLocationDetailView = (options) => {
178
247
  ? { type: 'RESET_LOCATION_ITEMS' }
179
248
  : { type: 'SET_LOCATION_ITEMS', items: fileItems });
180
249
  },
181
- onSearch: onSearchSubmit,
250
+ onSearch: () => {
251
+ setActiveFile(undefined);
252
+ onSearchSubmit();
253
+ },
182
254
  onSearchClear: () => {
183
255
  resetSearch();
184
256
  if (hasInvalidPrefix)
@@ -187,6 +259,7 @@ const useLocationDetailView = (options) => {
187
259
  handleReset();
188
260
  },
189
261
  onSearchQueryChange,
262
+ onRetryFilePreview: handleRetry,
190
263
  onToggleSearchSubfolders,
191
264
  };
192
265
  };
@@ -6,7 +6,16 @@ import '../../components/elements/IconElement.mjs';
6
6
  import { STORAGE_BROWSER_BLOCK } from '../../components/base/constants.mjs';
7
7
  import '../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../actions/configs/context.mjs';
16
+ import '../../actions/configs/defaults.mjs';
17
+ import '../../displayText/context.mjs';
18
+ import '../../filePreview/context.mjs';
10
19
  import '../../controls/context.mjs';
11
20
  import { DataRefreshControl } from '../../controls/DataRefreshControl.mjs';
12
21
  import { DataTableControl } from '../../controls/DataTableControl.mjs';
@@ -6,8 +6,16 @@ import '../../components/elements/IconElement.mjs';
6
6
  import { ControlsContextProvider } from '../../controls/context.mjs';
7
7
  import '../../components/composables/context.mjs';
8
8
  import '@aws-amplify/ui-react-core';
9
+ import '../../useAction/context.mjs';
9
10
  import '@aws-amplify/ui-react-core/elements';
11
+ import '../../credentials/context.mjs';
12
+ import '@aws-amplify/storage/internals';
13
+ import '../../configuration/context.mjs';
14
+ import 'aws-amplify/storage';
15
+ import '../../actions/configs/context.mjs';
16
+ import '../../actions/configs/defaults.mjs';
10
17
  import { useDisplayText } from '../../displayText/context.mjs';
18
+ import '../../filePreview/context.mjs';
11
19
  import { getLocationsViewTableData } from './getLocationsViewTableData/getLocationsViewTableData.mjs';
12
20
 
13
21
  function LocationsViewProvider({ children, ...props }) {
@@ -19,6 +19,7 @@ import { LocationActionView } from '../LocationActionView/LocationActionView.mjs
19
19
  import '../LocationActionView/UploadView/UploadView.mjs';
20
20
  import '../../fileItems/context.mjs';
21
21
  import { LocationDetailView } from '../LocationDetailView/LocationDetailView.mjs';
22
+ import '../../filePreview/context.mjs';
22
23
  import { LocationsView } from '../LocationsView/LocationsView.mjs';
23
24
 
24
25
  const DEFAULT_PRIMARY_VIEWS = {