@webiny/app-file-manager 6.6.0-alpha.0 → 6.6.0-alpha.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.
- package/app.js +8 -0
- package/app.js.map +1 -1
- package/features/shared/FILE_FIELDS.js +4 -0
- package/features/shared/FILE_FIELDS.js.map +1 -1
- package/features/shared/FileFieldsProviderWithWcp.d.ts +5 -5
- package/features/shared/FileFieldsProviderWithWcp.js +7 -7
- package/features/shared/FileFieldsProviderWithWcp.js.map +1 -1
- package/modules/AiEnrichment/ReenrichFileGateway.d.ts +12 -0
- package/modules/AiEnrichment/ReenrichFileGateway.js +23 -0
- package/modules/AiEnrichment/ReenrichFileGateway.js.map +1 -0
- package/modules/AiEnrichment/ReenrichWithAi.d.ts +11 -0
- package/modules/AiEnrichment/ReenrichWithAi.js +57 -0
- package/modules/AiEnrichment/ReenrichWithAi.js.map +1 -0
- package/modules/AiEnrichment/ReenrichWithAiPresenter.d.ts +50 -0
- package/modules/AiEnrichment/ReenrichWithAiPresenter.js +114 -0
- package/modules/AiEnrichment/ReenrichWithAiPresenter.js.map +1 -0
- package/modules/AiEnrichment/StreamingPlaceholder.d.ts +15 -0
- package/modules/AiEnrichment/StreamingPlaceholder.js +32 -0
- package/modules/AiEnrichment/StreamingPlaceholder.js.map +1 -0
- package/modules/AiEnrichment/abstractions.d.ts +70 -0
- package/modules/AiEnrichment/abstractions.js +6 -0
- package/modules/AiEnrichment/abstractions.js.map +1 -0
- package/modules/AiEnrichment/feature.d.ts +3 -1
- package/modules/AiEnrichment/feature.js +10 -0
- package/modules/AiEnrichment/feature.js.map +1 -1
- package/modules/Enterprise/index.js +3 -3
- package/modules/Enterprise/index.js.map +1 -1
- package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.d.ts +26 -0
- package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.js +39 -0
- package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.js.map +1 -0
- package/modules/HeadlessCms/fieldType/AssetFieldType.d.ts +34 -0
- package/modules/HeadlessCms/fieldType/AssetFieldType.js +42 -0
- package/modules/HeadlessCms/fieldType/AssetFieldType.js.map +1 -0
- package/modules/HeadlessCms/fieldType/AssetFormFieldType.d.ts +21 -0
- package/modules/HeadlessCms/fieldType/AssetFormFieldType.js +42 -0
- package/modules/HeadlessCms/fieldType/AssetFormFieldType.js.map +1 -0
- package/modules/HeadlessCms/fieldType/AssetInputRenderer.d.ts +15 -0
- package/modules/HeadlessCms/fieldType/AssetInputRenderer.js +20 -0
- package/modules/HeadlessCms/fieldType/AssetInputRenderer.js.map +1 -0
- package/modules/HeadlessCms/fieldType/AssetInputsRenderer.d.ts +15 -0
- package/modules/HeadlessCms/fieldType/AssetInputsRenderer.js +20 -0
- package/modules/HeadlessCms/fieldType/AssetInputsRenderer.js.map +1 -0
- package/modules/HeadlessCms/fieldType/FileFieldType.d.ts +1 -0
- package/modules/HeadlessCms/fieldType/FileFieldType.js +1 -0
- package/modules/HeadlessCms/fieldType/FileFieldType.js.map +1 -1
- package/modules/HeadlessCms/fieldType/feature.js +10 -0
- package/modules/HeadlessCms/fieldType/feature.js.map +1 -1
- package/modules/HeadlessCms/fieldType/isAssetField.d.ts +2 -0
- package/modules/HeadlessCms/fieldType/isAssetField.js +4 -0
- package/modules/HeadlessCms/fieldType/isAssetField.js.map +1 -0
- package/package.json +22 -22
- package/presentation/FileActions/FileDetails/EditImage.d.ts +2 -0
- package/presentation/FileActions/FileDetails/EditImage.js +39 -0
- package/presentation/FileActions/FileDetails/EditImage.js.map +1 -0
- package/presentation/FileActions/index.js +8 -0
- package/presentation/FileActions/index.js.map +1 -1
- package/presentation/FileDetails/FileDetailsPresenter.d.ts +2 -0
- package/presentation/FileDetails/FileDetailsPresenter.js +5 -0
- package/presentation/FileDetails/FileDetailsPresenter.js.map +1 -1
- package/presentation/FileDetails/FileDetailsPresenter.test.js +37 -4
- package/presentation/FileDetails/FileDetailsPresenter.test.js.map +1 -1
- package/presentation/FileDetails/abstractions.d.ts +2 -0
- package/presentation/FileDetails/abstractions.js.map +1 -1
- package/presentation/FileDetails/components/Content.d.ts +2 -1
- package/presentation/FileDetails/components/Content.js +2 -2
- package/presentation/FileDetails/components/Content.js.map +1 -1
- package/presentation/FileDetails/components/FileDetailsDrawer.d.ts +2 -2
- package/presentation/FileDetails/components/FileDetailsDrawer.js +11 -5
- package/presentation/FileDetails/components/FileDetailsDrawer.js.map +1 -1
- package/presentation/FileList/FileListDataSource.js +34 -1
- package/presentation/FileList/FileListDataSource.js.map +1 -1
- package/presentation/FileList/FileListPresenter.test.js +2 -1
- package/presentation/FileList/FileListPresenter.test.js.map +1 -1
- package/presentation/FileList/FileManagerPresenter.js +6 -4
- package/presentation/FileList/FileManagerPresenter.js.map +1 -1
- package/presentation/FileList/abstractions.d.ts +1 -0
- package/presentation/FileList/abstractions.js.map +1 -1
- package/presentation/FileList/components/BulkActions/BulkActionBar.d.ts +2 -2
- package/presentation/FileList/components/BulkActions/BulkActionDelete.d.ts +2 -2
- package/presentation/FileList/components/BulkActions/BulkActionMove.d.ts +2 -2
- package/presentation/FileList/components/Filters/SubFoldersToggle.d.ts +2 -2
- package/presentation/FileList/components/Filters/TagsFilter.d.ts +2 -2
- package/presentation/FileList/components/Filters/TypeFilter.d.ts +2 -2
- package/presentation/FileList/components/Grid/FileGrid.d.ts +2 -2
- package/presentation/FileList/components/Header/FileManagerHeader.d.ts +2 -2
- package/presentation/FileList/components/Search/SearchBar.d.ts +2 -2
- package/presentation/FileList/components/Table/FileTable.d.ts +2 -2
- package/presentation/FileList/components/Upload/UploadProgress.d.ts +2 -2
- package/presentation/FileManager/FileManagerBreadcrumbs.d.ts +12 -0
- package/presentation/FileManager/FileManagerBreadcrumbs.js +37 -0
- package/presentation/FileManager/FileManagerBreadcrumbs.js.map +1 -0
- package/presentation/FileManager/FileManagerView.js +40 -8
- package/presentation/FileManager/FileManagerView.js.map +1 -1
- package/presentation/Settings/components/SettingsView.d.ts +2 -2
- package/presentation/config/DefaultFileManagerConfig.js +12 -7
- package/presentation/config/DefaultFileManagerConfig.js.map +1 -1
- package/presentation/config/thumbnailRenderers/CroppedFileImage.d.ts +18 -0
- package/presentation/config/thumbnailRenderers/CroppedFileImage.js +66 -0
- package/presentation/config/thumbnailRenderers/CroppedFileImage.js.map +1 -0
- package/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js +6 -9
- package/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js.map +1 -1
- package/presentation/config/thumbnailRenderers/GridItemImageRenderer.js +6 -9
- package/presentation/config/thumbnailRenderers/GridItemImageRenderer.js.map +1 -1
- package/presentation/config/thumbnailRenderers/TableItemImageRenderer.js +6 -9
- package/presentation/config/thumbnailRenderers/TableItemImageRenderer.js.map +1 -1
- package/presentation/fieldRenderers/CmsAssetPickerRenderer.d.ts +22 -0
- package/presentation/fieldRenderers/CmsAssetPickerRenderer.js +56 -0
- package/presentation/fieldRenderers/CmsAssetPickerRenderer.js.map +1 -0
- package/presentation/fieldRenderers/CmsFilePickerRenderer.d.ts +1 -1
- package/presentation/fieldRenderers/CmsFilePickerRenderer.js +11 -4
- package/presentation/fieldRenderers/CmsFilePickerRenderer.js.map +1 -1
- package/presentation/fieldRenderers/CmsImageEditorDialog.d.ts +7 -0
- package/presentation/fieldRenderers/CmsImageEditorDialog.js +32 -0
- package/presentation/fieldRenderers/CmsImageEditorDialog.js.map +1 -0
- package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.d.ts +18 -0
- package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.js +88 -0
- package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.js.map +1 -0
- package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.d.ts +1 -1
- package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.js +11 -2
- package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.js.map +1 -1
- package/presentation/fieldRenderers/CroppedAssetThumb.d.ts +15 -0
- package/presentation/fieldRenderers/CroppedAssetThumb.js +25 -0
- package/presentation/fieldRenderers/CroppedAssetThumb.js.map +1 -0
- package/presentation/fieldRenderers/assetValue.d.ts +10 -0
- package/presentation/fieldRenderers/assetValue.js +88 -0
- package/presentation/fieldRenderers/assetValue.js.map +1 -0
- package/presentation/hooks/useCmsImageEditor.d.ts +10 -0
- package/presentation/hooks/useCmsImageEditor.js +76 -0
- package/presentation/hooks/useCmsImageEditor.js.map +1 -0
- package/presentation/hooks/useEditImage.d.ts +14 -0
- package/presentation/hooks/useEditImage.js +67 -0
- package/presentation/hooks/useEditImage.js.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/FileManager/FileManagerView.js","sources":["../../../src/presentation/FileManager/FileManagerView.tsx"],"sourcesContent":["import React, { useMemo, useEffect, useCallback } from \"react\";\nimport { DiContainerProvider, useContainer, useFeature } from \"@webiny/app\";\nimport { observer } from \"mobx-react-lite\";\nimport {\n BrowserFilePicker,\n type BrowserFilePickerRenderProps\n} from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport debounce from \"lodash/debounce.js\";\nimport { Heading, OverlayLoader, ScrollArea, Separator, useToast } from \"@webiny/admin-ui\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport {\n LeftPanel,\n OverlayLayout,\n RightPanel,\n SplitView,\n DialogsProvider,\n useHotkeys\n} from \"@webiny/app-admin\";\nimport { FoldersFeature } from \"@webiny/app-aco/features/folders/feature.js\";\nimport { FolderTreePresenterFeature } from \"@webiny/app-aco/presentation/folderTree/feature.js\";\nimport { FileManagerPresenterFeature } from \"~/presentation/FileList/feature.js\";\nimport {\n FileManagerPresenterProvider,\n useFileManagerPresenter\n} from \"~/presentation/FileList/FileManagerPresenterProvider.js\";\nimport { FileDetailsPresenterFeature } from \"~/presentation/FileDetails/feature.js\";\nimport { SharedCacheFeature } from \"~/features/shared/feature.js\";\nimport { ListFilesFeature } from \"~/features/listFiles/feature.js\";\nimport { GetFileFeature } from \"~/features/getFile/feature.js\";\nimport { DeleteFileFeature } from \"~/features/deleteFile/feature.js\";\nimport { UpdateFileFeature } from \"~/features/updateFile/feature.js\";\nimport { FileUploaderFeature } from \"~/features/fileUploader/feature.js\";\nimport { ListTagsFeature } from \"~/features/tags/feature.js\";\nimport { GetSettingsFeature } from \"~/features/settings/feature.js\";\nimport {\n FileManagerViewWithConfig,\n useFileManagerConfig\n} from \"~/presentation/config/FileManagerViewConfig.js\";\nimport { FolderTree } from \"@webiny/app-aco/presentation/folderTree/FolderTree.js\";\nimport { BottomInfoBar } from \"~/presentation/FileList/components/BottomInfoBar/index.js\";\nimport { BulkActionBar } from \"~/presentation/FileList/components/BulkActions/index.js\";\nimport { FileDropPlaceholder } from \"~/presentation/FileList/components/FileDropPlaceholder/index.js\";\nimport { Empty } from \"~/presentation/FileList/components/Empty/index.js\";\nimport { FileDetailsDrawer } from \"~/presentation/FileDetails/components/FileDetailsDrawer.js\";\nimport { FileGrid } from \"~/presentation/FileList/components/Grid/index.js\";\nimport { FileManagerHeader } from \"~/presentation/FileList/components/Header/FileManagerHeader.js\";\nimport { FileTable } from \"~/presentation/FileList/components/Table/index.js\";\nimport { TagsList } from \"~/presentation/FileList/components/TagsList/index.js\";\nimport { UploadProgress } from \"~/presentation/FileList/components/Upload/index.js\";\nimport { GetSettingsRepository } from \"~/features/settings/abstractions.js\";\nimport { OverlayProvider, useOverlay } from \"./OverlayContext.js\";\nimport { RouteParamsSync } from \"./RouteParamsSync.js\";\n\nimport type { FmFile } from \"~/features/shared/types.js\";\nimport type {\n FileError,\n SelectedFile\n} from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport { outputFileSelectionError } from \"~/presentation/FileManager/outputFileSelectionError.js\";\nimport type { ScrollPosition } from \"@webiny/admin-ui\";\n\nexport interface FileManagerViewProps {\n overlay?: boolean;\n onChange?: (files: FmFile[]) => void;\n onClose?: () => void;\n multiple?: boolean;\n accept?: string[];\n scope?: string;\n children?: React.ReactNode;\n}\n\nconst t = i18n.ns(\"app-admin/file-manager/file-manager-view\");\n\n// ---------------------------------------------------------------------------\n// Layout — uses original UI components, wired to the presenter.\n// ---------------------------------------------------------------------------\n\nconst FileManagerViewLayout = observer(function FileManagerViewLayout() {\n const { vm, actions } = useFileManagerPresenter();\n const { browser } = useFileManagerConfig();\n const overlay = useOverlay();\n const toast = useToast();\n\n useHotkeys({\n zIndex: 20,\n keys: {\n esc: () => overlay && overlay.onClose()\n }\n });\n\n const container = useContainer();\n const settingsRepository = useMemo(() => container.resolve(GetSettingsRepository), [container]);\n const settings = settingsRepository.settings;\n\n const uploadFiles = async (files: SelectedFile[]) => {\n await actions.upload(files);\n toast.showSuccessToast({ title: \"File upload complete.\" });\n };\n\n const onError = useCallback((errors: FileError[]) => {\n const message = outputFileSelectionError(errors);\n if (message) {\n toast.showWarningToast({ title: message });\n } else {\n toast.showWarningToast({ title: \"Couldn't process selected files.\" });\n console.error(errors);\n }\n }, []);\n\n const loadMoreOnScroll = useCallback(\n debounce(async (scrollFrame: ScrollPosition) => {\n if (scrollFrame.top > 0.8) {\n void actions.loadMore();\n }\n }, 200),\n [vm.list.pagination, actions]\n );\n\n if (!vm.fileModel) {\n return <OverlayLoader text={t`Preparing File Manager...`} />;\n }\n\n const renderList = (browseFiles: BrowserFilePickerRenderProps[\"browseFiles\"]) => {\n if (vm.loading) {\n return <OverlayLoader text={t`Loading files...`} size={\"lg\"} />;\n }\n\n if (vm.empty) {\n return <Empty isSearchResult={!vm.showFolders} browseFiles={browseFiles} />;\n }\n\n if (vm.viewMode === \"table\") {\n return (\n <ScrollArea onScroll={loadMoreOnScroll}>\n <FileTable />\n </ScrollArea>\n );\n }\n\n return (\n <ScrollArea onScroll={loadMoreOnScroll}>\n <FileGrid />\n </ScrollArea>\n );\n };\n\n const content = (\n <BrowserFilePicker\n multiple\n maxSize={settings ? settings.uploadMaxFileSize + \"b\" : \"1TB\"}\n multipleMaxSize={\"1TB\"}\n accept={overlay?.accept ?? []}\n onSuccess={uploadFiles}\n onError={onError}\n >\n {({ getDropZoneProps, browseFiles }) => (\n <>\n <FileDetailsDrawer />\n <SplitView namespace={\"fm/file/list\"}>\n <LeftPanel span={2}>\n <div className={\"flex flex-col h-main-content\"}>\n <div className={\"py-sm px-md\"}>\n <Heading level={5}>{t`File Manager`}</Heading>\n </div>\n <Separator />\n <div className={\"shrink-0 overflow-y-auto max-h-[66vh]\"}>\n <FolderTree\n vm={vm.folders}\n actions={actions.folders}\n folderActions={browser.folder.actions}\n dropConfirmation={browser.folder.dropConfirmation}\n enableActions={true}\n enableCreate={true}\n />\n </div>\n {browser.filterByTags ? (\n <>\n <Separator />\n <div className={\"flex-1 overflow-y-auto min-h-0\"}>\n <TagsList\n loading={false}\n activeTags={\n (vm.list.filters[\"tags\"] as string[]) ?? []\n }\n tags={vm.tags.map(tag => ({\n tag: tag.tag,\n count: tag.count\n }))}\n onActivatedTagsChange={tags => {\n if (tags.length > 0) {\n actions.filter.set(\"tags\", tags);\n } else {\n actions.filter.clear(\"tags\");\n actions.filter.clear(\"tags_rule\");\n }\n }}\n />\n </div>\n </>\n ) : null}\n </div>\n </LeftPanel>\n <RightPanel span={10}>\n <div\n className={\"flex flex-col relative\"}\n style={{ height: \"calc(100vh - 45px\" }}\n >\n <FileManagerHeader browseFiles={browseFiles} />\n <div\n className={\"flex-1\"}\n {...getDropZoneProps({\n onDragEnter: () => actions.setDragging(true),\n onDrop: () => actions.setDragging(false),\n onDragLeave: (e: React.DragEvent) => {\n if (\n !e.relatedTarget ||\n !e.currentTarget.contains(e.relatedTarget as Node)\n ) {\n actions.setDragging(false);\n }\n }\n })}\n data-testid={\"fm-list-wrapper\"}\n >\n {!overlay && <BulkActionBar />}\n {renderList(browseFiles)}\n {vm.dragging && <FileDropPlaceholder />}\n <UploadProgress />\n </div>\n <BottomInfoBar\n accept={overlay?.accept ?? []}\n listing={vm.list.pagination.loadingMore}\n loading={vm.list.pagination.loading}\n totalCount={vm.list.pagination.totalCount}\n currentCount={vm.list.pagination.currentCount}\n />\n </div>\n </RightPanel>\n </SplitView>\n </>\n )}\n </BrowserFilePicker>\n );\n\n if (overlay) {\n return (\n <OverlayLayout variant={\"strong\"} onExited={() => overlay.onClose()}>\n {content}\n </OverlayLayout>\n );\n }\n\n return content;\n});\n\n// ---------------------------------------------------------------------------\n// Inner component that resolves the presenter from the scoped container.\n// ---------------------------------------------------------------------------\n\nconst FileManagerViewInner = observer(\n ({\n overlay = false,\n onChange,\n onClose,\n multiple,\n accept,\n scope,\n children\n }: FileManagerViewProps) => {\n const { presenter } = useFeature(FileManagerPresenterFeature);\n\n const overlayConfig = useMemo(() => {\n if (!overlay || !onChange || !onClose) {\n return null;\n }\n\n const handleFileClick = (file: FmFile) => {\n if (multiple) {\n presenter.actions.selection.toggle(file.id);\n } else {\n onChange([file]);\n }\n };\n\n const confirmSelection = () => {\n const selectedIds = presenter.vm.list.selection.selectedIds;\n const selectedFiles = presenter.vm.list.rows.filter(f => selectedIds.has(f.id));\n if (selectedFiles.length > 0) {\n onChange(selectedFiles);\n }\n };\n\n return {\n onFileClick: handleFileClick,\n confirmSelection,\n onClose,\n accept: accept ?? [],\n multiple: multiple ?? false\n };\n }, [overlay, onChange, onClose, multiple, accept]);\n\n useEffect(() => {\n presenter.init({ scope });\n return () => presenter.dispose();\n }, [presenter, overlay, scope]);\n\n const inner = (\n <DialogsProvider>\n <FileManagerViewWithConfig>\n <FileManagerPresenterProvider presenter={presenter}>\n <FileManagerViewLayout />\n {children}\n {!overlayConfig && <RouteParamsSync />}\n </FileManagerPresenterProvider>\n </FileManagerViewWithConfig>\n </DialogsProvider>\n );\n\n if (overlayConfig) {\n return <OverlayProvider config={overlayConfig}>{inner}</OverlayProvider>;\n }\n\n return inner;\n }\n);\n\n// ---------------------------------------------------------------------------\n// FileManagerView — sets up DI container and renders the inner component.\n// ---------------------------------------------------------------------------\n\nexport const FileManagerView = (props: FileManagerViewProps) => {\n const container = useContainer();\n\n const scopedContainer = useMemo(() => {\n const child = container.createChildContainer();\n\n SharedCacheFeature.register(child);\n FoldersFeature.register(child, { type: \"FmFile\" });\n FolderTreePresenterFeature.register(child);\n ListFilesFeature.register(child);\n GetFileFeature.register(child);\n DeleteFileFeature.register(child);\n UpdateFileFeature.register(child);\n FileUploaderFeature.register(child);\n ListTagsFeature.register(child);\n GetSettingsFeature.register(child);\n FileDetailsPresenterFeature.register(child);\n FileManagerPresenterFeature.register(child);\n\n return child;\n }, []);\n\n return (\n <DiContainerProvider container={scopedContainer}>\n <FileManagerViewInner {...props} />\n </DiContainerProvider>\n );\n};\n"],"names":["t","i18n","FileManagerViewLayout","observer","vm","actions","useFileManagerPresenter","browser","useFileManagerConfig","overlay","useOverlay","toast","useToast","useHotkeys","container","useContainer","settingsRepository","useMemo","GetSettingsRepository","settings","uploadFiles","files","onError","useCallback","errors","message","outputFileSelectionError","console","loadMoreOnScroll","debounce","scrollFrame","OverlayLoader","renderList","browseFiles","Empty","ScrollArea","FileTable","FileGrid","content","BrowserFilePicker","getDropZoneProps","FileDetailsDrawer","SplitView","LeftPanel","Heading","Separator","FolderTree","TagsList","tag","tags","RightPanel","FileManagerHeader","e","BulkActionBar","FileDropPlaceholder","UploadProgress","BottomInfoBar","OverlayLayout","FileManagerViewInner","onChange","onClose","multiple","accept","scope","children","presenter","useFeature","FileManagerPresenterFeature","overlayConfig","handleFileClick","file","confirmSelection","selectedIds","selectedFiles","f","useEffect","inner","DialogsProvider","FileManagerViewWithConfig","FileManagerPresenterProvider","RouteParamsSync","OverlayProvider","FileManagerView","props","scopedContainer","child","SharedCacheFeature","FoldersFeature","FolderTreePresenterFeature","ListFilesFeature","GetFileFeature","DeleteFileFeature","UpdateFileFeature","FileUploaderFeature","ListTagsFeature","GetSettingsFeature","FileDetailsPresenterFeature","DiContainerProvider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentation/FileManager/FileManagerView.js","sources":["../../../src/presentation/FileManager/FileManagerView.tsx"],"sourcesContent":["import React, { useMemo, useEffect, useCallback } from \"react\";\nimport { DiContainerProvider, useContainer, useFeature } from \"@webiny/app\";\nimport { observer } from \"mobx-react-lite\";\nimport {\n BrowserFilePicker,\n type BrowserFilePickerRenderProps\n} from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport debounce from \"lodash/debounce.js\";\nimport { Heading, OverlayLoader, ScrollArea, Separator, useToast } from \"@webiny/admin-ui\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport {\n LeftPanel,\n OverlayLayout,\n RightPanel,\n SplitView,\n DialogsProvider,\n useHotkeys\n} from \"@webiny/app-admin\";\nimport { FoldersFeature } from \"@webiny/app-aco/features/folders/feature.js\";\nimport { FolderTreePresenterFeature } from \"@webiny/app-aco/presentation/folderTree/feature.js\";\nimport { FileManagerPresenterFeature } from \"~/presentation/FileList/feature.js\";\nimport {\n FileManagerPresenterProvider,\n useFileManagerPresenter\n} from \"~/presentation/FileList/FileManagerPresenterProvider.js\";\nimport { FileDetailsPresenterFeature } from \"~/presentation/FileDetails/feature.js\";\nimport { SharedCacheFeature } from \"~/features/shared/feature.js\";\nimport { ListFilesFeature } from \"~/features/listFiles/feature.js\";\nimport { GetFileFeature } from \"~/features/getFile/feature.js\";\nimport { DeleteFileFeature } from \"~/features/deleteFile/feature.js\";\nimport { UpdateFileFeature } from \"~/features/updateFile/feature.js\";\nimport { FileUploaderFeature } from \"~/features/fileUploader/feature.js\";\nimport { ListTagsFeature } from \"~/features/tags/feature.js\";\nimport { GetSettingsFeature } from \"~/features/settings/feature.js\";\nimport {\n FileManagerViewWithConfig,\n useFileManagerConfig\n} from \"~/presentation/config/FileManagerViewConfig.js\";\nimport { FolderTree } from \"@webiny/app-aco/presentation/folderTree/FolderTree.js\";\nimport { BottomInfoBar } from \"~/presentation/FileList/components/BottomInfoBar/index.js\";\nimport { BulkActionBar } from \"~/presentation/FileList/components/BulkActions/index.js\";\nimport { FileDropPlaceholder } from \"~/presentation/FileList/components/FileDropPlaceholder/index.js\";\nimport { Empty } from \"~/presentation/FileList/components/Empty/index.js\";\nimport { FileDetailsDrawer } from \"~/presentation/FileDetails/components/FileDetailsDrawer.js\";\nimport { FileGrid } from \"~/presentation/FileList/components/Grid/index.js\";\nimport { FileManagerHeader } from \"~/presentation/FileList/components/Header/FileManagerHeader.js\";\nimport { FileTable } from \"~/presentation/FileList/components/Table/index.js\";\nimport { TagsList } from \"~/presentation/FileList/components/TagsList/index.js\";\nimport { UploadProgress } from \"~/presentation/FileList/components/Upload/index.js\";\nimport { GetSettingsRepository } from \"~/features/settings/abstractions.js\";\nimport { OverlayProvider, useOverlay } from \"./OverlayContext.js\";\nimport { RouteParamsSync } from \"./RouteParamsSync.js\";\nimport { FileManagerBreadcrumbs } from \"./FileManagerBreadcrumbs.js\";\n\nimport type { FmFile } from \"~/features/shared/types.js\";\nimport type {\n FileError,\n SelectedFile\n} from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport { outputFileSelectionError } from \"~/presentation/FileManager/outputFileSelectionError.js\";\nimport type { ScrollPosition } from \"@webiny/admin-ui\";\n\nexport interface FileManagerViewProps {\n overlay?: boolean;\n onChange?: (files: FmFile[]) => void;\n onClose?: () => void;\n multiple?: boolean;\n accept?: string[];\n scope?: string;\n children?: React.ReactNode;\n}\n\nconst t = i18n.ns(\"app-admin/file-manager/file-manager-view\");\n\n// ---------------------------------------------------------------------------\n// Layout — uses original UI components, wired to the presenter.\n// ---------------------------------------------------------------------------\n\nconst FileManagerViewLayout = observer(function FileManagerViewLayout() {\n const { vm, actions } = useFileManagerPresenter();\n const { browser } = useFileManagerConfig();\n const overlay = useOverlay();\n const toast = useToast();\n\n useHotkeys({\n zIndex: 20,\n keys: {\n esc: () => overlay && overlay.onClose()\n }\n });\n\n const container = useContainer();\n const settingsRepository = useMemo(() => container.resolve(GetSettingsRepository), [container]);\n const settings = settingsRepository.settings;\n\n const uploadFiles = async (files: SelectedFile[]) => {\n await actions.upload(files);\n toast.showSuccessToast({ title: \"File upload complete.\" });\n };\n\n useEffect(() => {\n const handlePaste = (e: ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items) {\n return;\n }\n\n const files: SelectedFile[] = [];\n for (let i = 0; i < items.length; i++) {\n if (items[i].kind === \"file\") {\n const file = items[i].getAsFile();\n if (file) {\n const name =\n file.name && file.name !== \"image.png\"\n ? file.name\n : `pasted-${Date.now()}.${file.type.split(\"/\")[1] || \"png\"}`;\n\n files.push({\n id: String(Date.now()) + \"-\" + i,\n name,\n type: file.type,\n size: file.size,\n src: { file, base64: null }\n });\n }\n }\n }\n\n if (files.length > 0) {\n e.preventDefault();\n void uploadFiles(files);\n }\n };\n\n document.addEventListener(\"paste\", handlePaste);\n return () => document.removeEventListener(\"paste\", handlePaste);\n }, [actions]);\n\n const onError = useCallback((errors: FileError[]) => {\n const message = outputFileSelectionError(errors);\n if (message) {\n toast.showWarningToast({ title: message });\n } else {\n toast.showWarningToast({ title: \"Couldn't process selected files.\" });\n console.error(errors);\n }\n }, []);\n\n const loadMoreOnScroll = useCallback(\n debounce(async (scrollFrame: ScrollPosition) => {\n if (scrollFrame.top > 0.8) {\n void actions.loadMore();\n }\n }, 200),\n [vm.list.pagination, actions]\n );\n\n if (!vm.fileModel) {\n return <OverlayLoader text={t`Preparing File Manager...`} />;\n }\n\n const renderList = (browseFiles: BrowserFilePickerRenderProps[\"browseFiles\"]) => {\n if (vm.loading) {\n return <OverlayLoader text={t`Loading files...`} size={\"lg\"} />;\n }\n\n if (vm.empty) {\n return <Empty isSearchResult={!vm.showFolders} browseFiles={browseFiles} />;\n }\n\n if (vm.viewMode === \"table\") {\n return (\n <ScrollArea className={\"h-full\"} onScroll={loadMoreOnScroll}>\n <FileTable />\n </ScrollArea>\n );\n }\n\n return (\n <ScrollArea className={\"h-full\"} onScroll={loadMoreOnScroll}>\n <FileGrid />\n </ScrollArea>\n );\n };\n\n const content = (\n <BrowserFilePicker\n multiple\n maxSize={settings ? settings.uploadMaxFileSize + \"b\" : \"1TB\"}\n multipleMaxSize={\"1TB\"}\n accept={overlay?.accept ?? []}\n onSuccess={uploadFiles}\n onError={onError}\n >\n {({ getDropZoneProps, browseFiles }) => (\n <>\n <FileDetailsDrawer />\n <SplitView namespace={\"fm/file/list\"}>\n <LeftPanel span={2}>\n <div className={\"flex flex-col h-full\"}>\n <div className={\"py-sm px-md\"}>\n <Heading level={5}>{t`File Manager`}</Heading>\n </div>\n <Separator />\n <div className={\"shrink-0 overflow-y-auto max-h-[66vh]\"}>\n <FolderTree\n vm={vm.folders}\n actions={actions.folders}\n folderActions={browser.folder.actions}\n dropConfirmation={browser.folder.dropConfirmation}\n enableActions={true}\n enableCreate={true}\n />\n </div>\n {browser.filterByTags ? (\n <>\n <Separator />\n <div className={\"flex-1 overflow-y-auto min-h-0\"}>\n <TagsList\n loading={false}\n activeTags={\n (vm.list.filters[\"tags\"] as string[]) ?? []\n }\n tags={vm.tags.map(tag => ({\n tag: tag.tag,\n count: tag.count\n }))}\n onActivatedTagsChange={tags => {\n if (tags.length > 0) {\n actions.filter.set(\"tags\", tags);\n } else {\n actions.filter.clear(\"tags\");\n actions.filter.clear(\"tags_rule\");\n }\n }}\n />\n </div>\n </>\n ) : null}\n </div>\n </LeftPanel>\n <RightPanel span={10}>\n <div className={\"flex flex-col relative h-full overflow-hidden\"}>\n <FileManagerHeader browseFiles={browseFiles} />\n <div\n className={\"flex-1 min-h-0 overflow-hidden\"}\n {...getDropZoneProps({\n onDragEnter: () => actions.setDragging(true),\n onDrop: () => actions.setDragging(false),\n onDragLeave: (e: React.DragEvent) => {\n if (\n !e.relatedTarget ||\n !e.currentTarget.contains(e.relatedTarget as Node)\n ) {\n actions.setDragging(false);\n }\n }\n })}\n data-testid={\"fm-list-wrapper\"}\n >\n {!overlay && <BulkActionBar />}\n {renderList(browseFiles)}\n {vm.dragging && <FileDropPlaceholder />}\n <UploadProgress />\n </div>\n <BottomInfoBar\n accept={overlay?.accept ?? []}\n listing={vm.list.pagination.loadingMore}\n loading={vm.list.pagination.loading}\n totalCount={vm.list.pagination.totalCount}\n currentCount={vm.list.pagination.currentCount}\n />\n </div>\n </RightPanel>\n </SplitView>\n </>\n )}\n </BrowserFilePicker>\n );\n\n if (overlay) {\n return (\n <OverlayLayout variant={\"strong\"} onExited={() => overlay.onClose()}>\n {content}\n </OverlayLayout>\n );\n }\n\n return content;\n});\n\n// ---------------------------------------------------------------------------\n// Inner component that resolves the presenter from the scoped container.\n// ---------------------------------------------------------------------------\n\nconst FileManagerViewInner = observer(\n ({\n overlay = false,\n onChange,\n onClose,\n multiple,\n accept,\n scope,\n children\n }: FileManagerViewProps) => {\n const { presenter } = useFeature(FileManagerPresenterFeature);\n\n const overlayConfig = useMemo(() => {\n if (!overlay || !onChange || !onClose) {\n return null;\n }\n\n const handleFileClick = (file: FmFile) => {\n if (multiple) {\n presenter.actions.selection.toggle(file.id);\n } else {\n onChange([file]);\n }\n };\n\n const confirmSelection = () => {\n const selectedIds = presenter.vm.list.selection.selectedIds;\n const selectedFiles = presenter.vm.list.rows.filter(f => selectedIds.has(f.id));\n if (selectedFiles.length > 0) {\n onChange(selectedFiles);\n }\n };\n\n return {\n onFileClick: handleFileClick,\n confirmSelection,\n onClose,\n accept: accept ?? [],\n multiple: multiple ?? false\n };\n }, [overlay, onChange, onClose, multiple, accept]);\n\n useEffect(() => {\n presenter.init({ scope, accept: accept ?? undefined });\n return () => presenter.dispose();\n }, [presenter, overlay, scope]);\n\n const inner = (\n <DialogsProvider>\n <FileManagerViewWithConfig>\n <FileManagerPresenterProvider presenter={presenter}>\n <FileManagerViewLayout />\n {children}\n {!overlayConfig && <RouteParamsSync />}\n {!overlayConfig && <FileManagerBreadcrumbs />}\n </FileManagerPresenterProvider>\n </FileManagerViewWithConfig>\n </DialogsProvider>\n );\n\n if (overlayConfig) {\n return <OverlayProvider config={overlayConfig}>{inner}</OverlayProvider>;\n }\n\n return inner;\n }\n);\n\n// ---------------------------------------------------------------------------\n// FileManagerView — sets up DI container and renders the inner component.\n// ---------------------------------------------------------------------------\n\nexport const FileManagerView = (props: FileManagerViewProps) => {\n const container = useContainer();\n\n const scopedContainer = useMemo(() => {\n const child = container.createChildContainer();\n\n SharedCacheFeature.register(child);\n FoldersFeature.register(child, { type: \"FmFile\" });\n FolderTreePresenterFeature.register(child);\n ListFilesFeature.register(child);\n GetFileFeature.register(child);\n DeleteFileFeature.register(child);\n UpdateFileFeature.register(child);\n FileUploaderFeature.register(child);\n ListTagsFeature.register(child);\n GetSettingsFeature.register(child);\n FileDetailsPresenterFeature.register(child);\n FileManagerPresenterFeature.register(child);\n\n return child;\n }, []);\n\n return (\n <DiContainerProvider container={scopedContainer}>\n <FileManagerViewInner {...props} />\n </DiContainerProvider>\n );\n};\n"],"names":["t","i18n","FileManagerViewLayout","observer","vm","actions","useFileManagerPresenter","browser","useFileManagerConfig","overlay","useOverlay","toast","useToast","useHotkeys","container","useContainer","settingsRepository","useMemo","GetSettingsRepository","settings","uploadFiles","files","useEffect","handlePaste","e","items","i","file","name","Date","String","document","onError","useCallback","errors","message","outputFileSelectionError","console","loadMoreOnScroll","debounce","scrollFrame","OverlayLoader","renderList","browseFiles","Empty","ScrollArea","FileTable","FileGrid","content","BrowserFilePicker","getDropZoneProps","FileDetailsDrawer","SplitView","LeftPanel","Heading","Separator","FolderTree","TagsList","tag","tags","RightPanel","FileManagerHeader","BulkActionBar","FileDropPlaceholder","UploadProgress","BottomInfoBar","OverlayLayout","FileManagerViewInner","onChange","onClose","multiple","accept","scope","children","presenter","useFeature","FileManagerPresenterFeature","overlayConfig","handleFileClick","confirmSelection","selectedIds","selectedFiles","f","undefined","inner","DialogsProvider","FileManagerViewWithConfig","FileManagerPresenterProvider","RouteParamsSync","FileManagerBreadcrumbs","OverlayProvider","FileManagerView","props","scopedContainer","child","SharedCacheFeature","FoldersFeature","FolderTreePresenterFeature","ListFilesFeature","GetFileFeature","DeleteFileFeature","UpdateFileFeature","FileUploaderFeature","ListTagsFeature","GetSettingsFeature","FileDetailsPresenterFeature","DiContainerProvider"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import react from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { useFeatureFlags } from "@webiny/app-admin";
|
|
3
3
|
import { DeleteFolder, EditFolder, SetFolderPermissions } from "@webiny/app-aco";
|
|
4
4
|
import { FileManagerViewConfig } from "./FileManagerViewConfig.js";
|
|
5
5
|
import { FilterByType } from "../FileList/components/Filters/FilterByType.js";
|
|
@@ -14,6 +14,16 @@ import { TableItemDefaultRenderer } from "./thumbnailRenderers/TableItemDefaultR
|
|
|
14
14
|
import { TableItemImageRenderer } from "./thumbnailRenderers/TableItemImageRenderer.js";
|
|
15
15
|
import { FilePreviewDefaultRenderer } from "./thumbnailRenderers/FilePreviewDefaultRenderer.js";
|
|
16
16
|
const { Browser: Browser, FileDetails: FileDetails } = FileManagerViewConfig;
|
|
17
|
+
const PrivateFilesBulkEditField = ()=>{
|
|
18
|
+
const featureFlags = useFeatureFlags();
|
|
19
|
+
if (!featureFlags.isEnabled("advancedAccessControlLayer.privateFiles")) return null;
|
|
20
|
+
return /*#__PURE__*/ react.createElement(Browser.BulkEditField, {
|
|
21
|
+
name: "accessControl",
|
|
22
|
+
element: /*#__PURE__*/ react.createElement(AccessControl, {
|
|
23
|
+
placeholder: "Select privacy settings"
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
};
|
|
17
27
|
const DefaultFileManagerConfig = ()=>/*#__PURE__*/ react.createElement(FileManagerViewConfig, null, /*#__PURE__*/ react.createElement(Browser.FilterByTags, null), /*#__PURE__*/ react.createElement(Browser.Filter, {
|
|
18
28
|
name: "type",
|
|
19
29
|
element: /*#__PURE__*/ react.createElement(FilterByType, null)
|
|
@@ -86,12 +96,7 @@ const DefaultFileManagerConfig = ()=>/*#__PURE__*/ react.createElement(FileManag
|
|
|
86
96
|
}), /*#__PURE__*/ react.createElement(Browser.BulkEditField, {
|
|
87
97
|
name: "tags",
|
|
88
98
|
element: /*#__PURE__*/ react.createElement(Tags, null)
|
|
89
|
-
}), /*#__PURE__*/ react.createElement(FileActions, null), /*#__PURE__*/ react.createElement(
|
|
90
|
-
name: "accessControl",
|
|
91
|
-
element: /*#__PURE__*/ react.createElement(AccessControl, {
|
|
92
|
-
placeholder: "Select privacy settings"
|
|
93
|
-
})
|
|
94
|
-
})), /*#__PURE__*/ react.createElement(Browser.Grid.Item.Thumbnail, {
|
|
99
|
+
}), /*#__PURE__*/ react.createElement(FileActions, null), /*#__PURE__*/ react.createElement(PrivateFilesBulkEditField, null), /*#__PURE__*/ react.createElement(Browser.Grid.Item.Thumbnail, {
|
|
95
100
|
type: "*/*",
|
|
96
101
|
element: /*#__PURE__*/ react.createElement(GridItemDefaultRenderer, null)
|
|
97
102
|
}), /*#__PURE__*/ react.createElement(Browser.Grid.Item.Thumbnail, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/config/DefaultFileManagerConfig.js","sources":["../../../src/presentation/config/DefaultFileManagerConfig.tsx"],"sourcesContent":["import React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/config/DefaultFileManagerConfig.js","sources":["../../../src/presentation/config/DefaultFileManagerConfig.tsx"],"sourcesContent":["import React from \"react\";\nimport { useFeatureFlags } from \"@webiny/app-admin\";\nimport { DeleteFolder, EditFolder, SetFolderPermissions } from \"@webiny/app-aco\";\nimport { FileManagerViewConfig as FileManagerConfig } from \"~/presentation/config/FileManagerViewConfig.js\";\nimport { FilterByType } from \"~/presentation/FileList/components/Filters/FilterByType.js\";\nimport {\n BulkActionDelete,\n BulkActionMove\n} from \"~/presentation/FileList/components/BulkActions/index.js\";\nimport { Tags, AccessControl } from \"~/presentation/config/fields/index.js\";\nimport {\n CellActions,\n CellAuthor,\n CellCreated,\n CellModified,\n CellName,\n CellSize,\n CellType,\n CopyFile,\n DeleteFile,\n EditFile,\n MoveFile\n} from \"~/presentation/FileList/components/Table/index.js\";\nimport { GridItemDefaultRenderer } from \"~/presentation/config/thumbnailRenderers/GridItemDefaultRenderer.js\";\nimport { GridItemImageRenderer } from \"~/presentation/config/thumbnailRenderers/GridItemImageRenderer.js\";\nimport { FileActions } from \"~/presentation/FileActions/index.js\";\nimport { FilePreviewImageRenderer } from \"~/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js\";\nimport { TableItemDefaultRenderer } from \"~/presentation/config/thumbnailRenderers/TableItemDefaultRenderer.js\";\nimport { TableItemImageRenderer } from \"~/presentation/config/thumbnailRenderers/TableItemImageRenderer.js\";\nimport { FilePreviewDefaultRenderer } from \"~/presentation/config/thumbnailRenderers/FilePreviewDefaultRenderer.js\";\n\nconst { Browser, FileDetails } = FileManagerConfig;\n\nconst PrivateFilesBulkEditField = () => {\n const featureFlags = useFeatureFlags();\n if (!featureFlags.isEnabled(\"advancedAccessControlLayer.privateFiles\")) {\n return null;\n }\n return (\n <Browser.BulkEditField\n name={\"accessControl\"}\n element={<AccessControl placeholder={\"Select privacy settings\"} />}\n />\n );\n};\n\nexport const DefaultFileManagerConfig = () => {\n return (\n <FileManagerConfig>\n {/* Filters */}\n <Browser.FilterByTags />\n <Browser.Filter name={\"type\"} element={<FilterByType />} />\n {/* Bulk Actions */}\n <Browser.BulkAction name={\"move\"} element={<BulkActionMove />} />\n <Browser.BulkAction name={\"delete\"} element={<BulkActionDelete />} />\n {/* Folder Actions */}\n <Browser.Folder.Action name={\"edit\"} element={<EditFolder />} />\n <Browser.Folder.Action name={\"permissions\"} element={<SetFolderPermissions />} />\n <Browser.Folder.Action name={\"delete\"} element={<DeleteFolder />} />\n {/* File Actions */}\n <Browser.File.Action name={\"copy\"} element={<CopyFile />} />\n <Browser.File.Action name={\"edit\"} element={<EditFile />} />\n <Browser.File.Action name={\"move\"} element={<MoveFile />} />\n <Browser.File.Action name={\"delete\"} element={<DeleteFile />} />\n {/* Table Columns */}\n <Browser.Table.Column\n name={\"name\"}\n header={\"Name\"}\n cell={<CellName />}\n sortable={true}\n hideable={false}\n size={200}\n />\n <Browser.Table.Column name={\"type\"} header={\"Type\"} cell={<CellType />} />\n <Browser.Table.Column\n name={\"size\"}\n header={\"Size\"}\n cell={<CellSize />}\n sortable={true}\n />\n <Browser.Table.Column name={\"createdBy\"} header={\"Author\"} cell={<CellAuthor />} />\n <Browser.Table.Column\n name={\"createdOn\"}\n header={\"Created\"}\n cell={<CellCreated />}\n sortable={true}\n />\n <Browser.Table.Column\n name={\"savedOn\"}\n header={\"Modified\"}\n cell={<CellModified />}\n sortable={true}\n />\n <Browser.Table.Column\n name={\"actions\"}\n header={\" \"}\n cell={<CellActions />}\n size={56}\n truncate={false}\n className={\"flex justify-center\"}\n hideable={false}\n resizable={false}\n />\n <Browser.BulkEditField name={\"tags\"} element={<Tags />} />\n {/* File Details Actions */}\n <FileActions />\n {/* Access Control */}\n <PrivateFilesBulkEditField />\n {/* Grid Thumbnail */}\n <Browser.Grid.Item.Thumbnail type={\"*/*\"} element={<GridItemDefaultRenderer />} />\n <Browser.Grid.Item.Thumbnail type={\"image/*\"} element={<GridItemImageRenderer />} />\n {/* Table Thumbnail */}\n <Browser.Table.Cell.Thumbnail type={\"image/*\"} element={<TableItemImageRenderer />} />\n <Browser.Table.Cell.Thumbnail type={\"*/*\"} element={<TableItemDefaultRenderer />} />\n {/* File Details Thumbnail */}\n <FileDetails.Preview.Thumbnail type={\"*/*\"} element={<FilePreviewDefaultRenderer />} />\n <FileDetails.Preview.Thumbnail\n type={\"image/*\"}\n element={<FilePreviewImageRenderer />}\n />\n </FileManagerConfig>\n );\n};\n"],"names":["Browser","FileDetails","FileManagerConfig","PrivateFilesBulkEditField","featureFlags","useFeatureFlags","AccessControl","DefaultFileManagerConfig","FilterByType","BulkActionMove","BulkActionDelete","EditFolder","SetFolderPermissions","DeleteFolder","CopyFile","EditFile","MoveFile","DeleteFile","CellName","CellType","CellSize","CellAuthor","CellCreated","CellModified","CellActions","Tags","FileActions","GridItemDefaultRenderer","GridItemImageRenderer","TableItemImageRenderer","TableItemDefaultRenderer","FilePreviewDefaultRenderer","FilePreviewImageRenderer"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { FileItem } from "../../../domain/types.js";
|
|
3
|
+
interface CroppedFileImageProps {
|
|
4
|
+
file: FileItem;
|
|
5
|
+
/** Width passed to the delivery transform (`?width=`). */
|
|
6
|
+
width: number;
|
|
7
|
+
/** How the (cropped) image fits its slot. */
|
|
8
|
+
fit: "cover" | "contain";
|
|
9
|
+
/** Class applied to the `<Image>` when there is no crop (original behavior). */
|
|
10
|
+
fallbackClassName?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Renders a File Manager image thumbnail/preview honoring the saved crop (and, for
|
|
14
|
+
* `cover`, the hotspot). Falls back to the plain image when the file has no crop,
|
|
15
|
+
* so un-edited files render exactly as before.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CroppedFileImage: ({ file, width, fit, fallbackClassName }: CroppedFileImageProps) => React.JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Image } from "@webiny/app/components/index.js";
|
|
2
|
+
import { cn, getCroppedImageRenderStyles } from "@webiny/admin-ui";
|
|
3
|
+
import * as __rspack_external_react from "react";
|
|
4
|
+
const isFullCrop = (crop)=>!crop || 0 === crop.top && 0 === crop.left && 0 === crop.bottom && 0 === crop.right;
|
|
5
|
+
const CroppedFileImage = ({ file, width, fit, fallbackClassName })=>{
|
|
6
|
+
const ref = (0, __rspack_external_react.useRef)(null);
|
|
7
|
+
const [box, setBox] = (0, __rspack_external_react.useState)({
|
|
8
|
+
w: 0,
|
|
9
|
+
h: 0
|
|
10
|
+
});
|
|
11
|
+
(0, __rspack_external_react.useLayoutEffect)(()=>{
|
|
12
|
+
const el = ref.current;
|
|
13
|
+
if (!el) return;
|
|
14
|
+
const measure = ()=>{
|
|
15
|
+
const rect = el.getBoundingClientRect();
|
|
16
|
+
setBox({
|
|
17
|
+
w: rect.width,
|
|
18
|
+
h: rect.height
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
measure();
|
|
22
|
+
if ("u" < typeof ResizeObserver) return;
|
|
23
|
+
const ro = new ResizeObserver(measure);
|
|
24
|
+
ro.observe(el);
|
|
25
|
+
return ()=>ro.disconnect();
|
|
26
|
+
}, []);
|
|
27
|
+
const img = file.metadata?.image;
|
|
28
|
+
const imageWidth = img?.width ?? 0;
|
|
29
|
+
const imageHeight = img?.height ?? 0;
|
|
30
|
+
if (isFullCrop(img?.crop) || imageWidth <= 0 || imageHeight <= 0) return /*#__PURE__*/ __rspack_external_react.createElement(Image, {
|
|
31
|
+
src: file.src,
|
|
32
|
+
alt: file.name,
|
|
33
|
+
transform: {
|
|
34
|
+
width
|
|
35
|
+
},
|
|
36
|
+
className: fallbackClassName
|
|
37
|
+
});
|
|
38
|
+
const focalPoint = img?.focalPoint;
|
|
39
|
+
const hotspot = focalPoint ? {
|
|
40
|
+
x: focalPoint.x,
|
|
41
|
+
y: focalPoint.y,
|
|
42
|
+
width: 1,
|
|
43
|
+
height: 1
|
|
44
|
+
} : void 0;
|
|
45
|
+
const { wrapper, image } = getCroppedImageRenderStyles(imageWidth, imageHeight, img?.crop, hotspot, {
|
|
46
|
+
boxWidth: box.w,
|
|
47
|
+
boxHeight: box.h,
|
|
48
|
+
fit
|
|
49
|
+
});
|
|
50
|
+
return /*#__PURE__*/ __rspack_external_react.createElement("div", {
|
|
51
|
+
ref: ref,
|
|
52
|
+
className: cn("flex h-full w-full items-center justify-center overflow-hidden")
|
|
53
|
+
}, /*#__PURE__*/ __rspack_external_react.createElement("div", {
|
|
54
|
+
style: wrapper
|
|
55
|
+
}, /*#__PURE__*/ __rspack_external_react.createElement(Image, {
|
|
56
|
+
src: file.src,
|
|
57
|
+
alt: file.name,
|
|
58
|
+
transform: {
|
|
59
|
+
width
|
|
60
|
+
},
|
|
61
|
+
style: image
|
|
62
|
+
})));
|
|
63
|
+
};
|
|
64
|
+
export { CroppedFileImage };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=CroppedFileImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/config/thumbnailRenderers/CroppedFileImage.js","sources":["../../../../src/presentation/config/thumbnailRenderers/CroppedFileImage.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport { Image } from \"@webiny/app/components/index.js\";\nimport { cn, getCroppedImageRenderStyles } from \"@webiny/admin-ui\";\nimport type { FileItem } from \"~/domain/types.js\";\n\ninterface CroppedFileImageProps {\n file: FileItem;\n /** Width passed to the delivery transform (`?width=`). */\n width: number;\n /** How the (cropped) image fits its slot. */\n fit: \"cover\" | \"contain\";\n /** Class applied to the `<Image>` when there is no crop (original behavior). */\n fallbackClassName?: string;\n}\n\nconst isFullCrop = (crop: any): boolean => {\n return !crop || (crop.top === 0 && crop.left === 0 && crop.bottom === 0 && crop.right === 0);\n};\n\n/**\n * Renders a File Manager image thumbnail/preview honoring the saved crop (and, for\n * `cover`, the hotspot). Falls back to the plain image when the file has no crop,\n * so un-edited files render exactly as before.\n */\nexport const CroppedFileImage = ({\n file,\n width,\n fit,\n fallbackClassName\n}: CroppedFileImageProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [box, setBox] = useState({ w: 0, h: 0 });\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n const measure = () => {\n const rect = el.getBoundingClientRect();\n setBox({ w: rect.width, h: rect.height });\n };\n measure();\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n const img = file.metadata?.image;\n const imageWidth = img?.width ?? 0;\n const imageHeight = img?.height ?? 0;\n\n if (isFullCrop(img?.crop) || imageWidth <= 0 || imageHeight <= 0) {\n return (\n <Image\n src={file.src}\n alt={file.name}\n transform={{ width }}\n className={fallbackClassName}\n />\n );\n }\n\n const focalPoint = img?.focalPoint;\n const hotspot = focalPoint\n ? { x: focalPoint.x, y: focalPoint.y, width: 1, height: 1 }\n : undefined;\n\n const { wrapper, image } = getCroppedImageRenderStyles(\n imageWidth,\n imageHeight,\n img?.crop,\n hotspot,\n {\n boxWidth: box.w,\n boxHeight: box.h,\n fit\n }\n );\n\n return (\n <div\n ref={ref}\n className={cn(\"flex h-full w-full items-center justify-center overflow-hidden\")}\n >\n <div style={wrapper}>\n <Image src={file.src} alt={file.name} transform={{ width }} style={image} />\n </div>\n </div>\n );\n};\n"],"names":["isFullCrop","crop","CroppedFileImage","file","width","fit","fallbackClassName","ref","useRef","box","setBox","useState","useLayoutEffect","el","measure","rect","ResizeObserver","ro","img","imageWidth","imageHeight","Image","focalPoint","hotspot","undefined","wrapper","image","getCroppedImageRenderStyles","cn"],"mappings":";;;AAgBA,MAAMA,aAAa,CAACC,OACT,CAACA,QAASA,AAAa,MAAbA,KAAK,GAAG,IAAUA,AAAc,MAAdA,KAAK,IAAI,IAAUA,AAAgB,MAAhBA,KAAK,MAAM,IAAUA,AAAe,MAAfA,KAAK,KAAK;AAQlF,MAAMC,mBAAmB,CAAC,EAC7BC,IAAI,EACJC,KAAK,EACLC,GAAG,EACHC,iBAAiB,EACG;IACpB,MAAMC,MAAMC,AAAAA,IAAAA,wBAAAA,MAAAA,AAAAA,EAAuB;IACnC,MAAM,CAACC,KAAKC,OAAO,GAAGC,AAAAA,IAAAA,wBAAAA,QAAAA,AAAAA,EAAS;QAAE,GAAG;QAAG,GAAG;IAAE;IAE5CC,IAAAA,wBAAAA,eAAAA,AAAAA,EAAgB;QACZ,MAAMC,KAAKN,IAAI,OAAO;QACtB,IAAI,CAACM,IACD;QAEJ,MAAMC,UAAU;YACZ,MAAMC,OAAOF,GAAG,qBAAqB;YACrCH,OAAO;gBAAE,GAAGK,KAAK,KAAK;gBAAE,GAAGA,KAAK,MAAM;YAAC;QAC3C;QACAD;QACA,IAAI,AAA0B,MAA1B,OAAOE,gBACP;QAEJ,MAAMC,KAAK,IAAID,eAAeF;QAC9BG,GAAG,OAAO,CAACJ;QACX,OAAO,IAAMI,GAAG,UAAU;IAC9B,GAAG,EAAE;IAEL,MAAMC,MAAMf,KAAK,QAAQ,EAAE;IAC3B,MAAMgB,aAAaD,KAAK,SAAS;IACjC,MAAME,cAAcF,KAAK,UAAU;IAEnC,IAAIlB,WAAWkB,KAAK,SAASC,cAAc,KAAKC,eAAe,GAC3D,OAAO,WAAP,GACI,sCAACC,OAAKA;QACF,KAAKlB,KAAK,GAAG;QACb,KAAKA,KAAK,IAAI;QACd,WAAW;YAAEC;QAAM;QACnB,WAAWE;;IAKvB,MAAMgB,aAAaJ,KAAK;IACxB,MAAMK,UAAUD,aACV;QAAE,GAAGA,WAAW,CAAC;QAAE,GAAGA,WAAW,CAAC;QAAE,OAAO;QAAG,QAAQ;IAAE,IACxDE;IAEN,MAAM,EAAEC,OAAO,EAAEC,KAAK,EAAE,GAAGC,4BACvBR,YACAC,aACAF,KAAK,MACLK,SACA;QACI,UAAUd,IAAI,CAAC;QACf,WAAWA,IAAI,CAAC;QAChBJ;IACJ;IAGJ,OAAO,WAAP,GACI,sCAAC;QACG,KAAKE;QACL,WAAWqB,GAAG;qBAEd,sCAAC;QAAI,OAAOH;qBACR,sCAACJ,OAAKA;QAAC,KAAKlB,KAAK,GAAG;QAAE,KAAKA,KAAK,IAAI;QAAE,WAAW;YAAEC;QAAM;QAAG,OAAOsB;;AAInF"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { Image } from "@webiny/app/components/index.js";
|
|
2
1
|
import { useFile } from "../../hooks/useFile.js";
|
|
2
|
+
import { CroppedFileImage } from "./CroppedFileImage.js";
|
|
3
3
|
import * as __rspack_external_react from "react";
|
|
4
|
-
const width750 = {
|
|
5
|
-
width: 750
|
|
6
|
-
};
|
|
7
4
|
const FilePreviewImageRenderer = ()=>{
|
|
8
5
|
const { file } = useFile();
|
|
9
|
-
return /*#__PURE__*/ __rspack_external_react.createElement(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
return /*#__PURE__*/ __rspack_external_react.createElement(CroppedFileImage, {
|
|
7
|
+
file: file,
|
|
8
|
+
width: 750,
|
|
9
|
+
fit: "contain",
|
|
10
|
+
fallbackClassName: "object-contain max-w-full max-h-full"
|
|
14
11
|
});
|
|
15
12
|
};
|
|
16
13
|
export { FilePreviewImageRenderer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useFile } from \"~/presentation/hooks/useFile.js\";\nimport { CroppedFileImage } from \"./CroppedFileImage.js\";\n\nexport const FilePreviewImageRenderer = () => {\n const { file } = useFile();\n return (\n <CroppedFileImage\n file={file}\n width={750}\n fit={\"contain\"}\n fallbackClassName={\"object-contain max-w-full max-h-full\"}\n />\n );\n};\n"],"names":["FilePreviewImageRenderer","file","useFile","CroppedFileImage"],"mappings":";;;AAIO,MAAMA,2BAA2B;IACpC,MAAM,EAAEC,IAAI,EAAE,GAAGC;IACjB,OAAO,WAAP,GACI,sCAACC,kBAAgBA;QACb,MAAMF;QACN,OAAO;QACP,KAAK;QACL,mBAAmB;;AAG/B"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { Image } from "@webiny/app/components/index.js";
|
|
2
1
|
import { useFile } from "../../hooks/useFile.js";
|
|
2
|
+
import { CroppedFileImage } from "./CroppedFileImage.js";
|
|
3
3
|
import * as __rspack_external_react from "react";
|
|
4
|
-
const width300 = {
|
|
5
|
-
width: 300
|
|
6
|
-
};
|
|
7
4
|
const GridItemImageRenderer = ()=>{
|
|
8
5
|
const { file } = useFile();
|
|
9
|
-
return /*#__PURE__*/ __rspack_external_react.createElement(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
return /*#__PURE__*/ __rspack_external_react.createElement(CroppedFileImage, {
|
|
7
|
+
file: file,
|
|
8
|
+
width: 300,
|
|
9
|
+
fit: "contain",
|
|
10
|
+
fallbackClassName: "object-contain max-w-full max-h-full"
|
|
14
11
|
});
|
|
15
12
|
};
|
|
16
13
|
export { GridItemImageRenderer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/config/thumbnailRenderers/GridItemImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/GridItemImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/config/thumbnailRenderers/GridItemImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/GridItemImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useFile } from \"~/presentation/hooks/useFile.js\";\nimport { CroppedFileImage } from \"./CroppedFileImage.js\";\n\nexport const GridItemImageRenderer = () => {\n const { file } = useFile();\n return (\n <CroppedFileImage\n file={file}\n width={300}\n fit={\"contain\"}\n fallbackClassName={\"object-contain max-w-full max-h-full\"}\n />\n );\n};\n"],"names":["GridItemImageRenderer","file","useFile","CroppedFileImage"],"mappings":";;;AAIO,MAAMA,wBAAwB;IACjC,MAAM,EAAEC,IAAI,EAAE,GAAGC;IACjB,OAAO,WAAP,GACI,sCAACC,kBAAgBA;QACb,MAAMF;QACN,OAAO;QACP,KAAK;QACL,mBAAmB;;AAG/B"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { Image } from "@webiny/app/components/index.js";
|
|
2
1
|
import { useFile } from "../../hooks/useFile.js";
|
|
2
|
+
import { CroppedFileImage } from "./CroppedFileImage.js";
|
|
3
3
|
import * as __rspack_external_react from "react";
|
|
4
|
-
const width100 = {
|
|
5
|
-
width: 100
|
|
6
|
-
};
|
|
7
4
|
const TableItemImageRenderer = ()=>{
|
|
8
5
|
const { file } = useFile();
|
|
9
|
-
return /*#__PURE__*/ __rspack_external_react.createElement(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
return /*#__PURE__*/ __rspack_external_react.createElement(CroppedFileImage, {
|
|
7
|
+
file: file,
|
|
8
|
+
width: 100,
|
|
9
|
+
fit: "cover",
|
|
10
|
+
fallbackClassName: "object-cover w-full h-full"
|
|
14
11
|
});
|
|
15
12
|
};
|
|
16
13
|
export { TableItemImageRenderer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/config/thumbnailRenderers/TableItemImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/TableItemImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/config/thumbnailRenderers/TableItemImageRenderer.js","sources":["../../../../src/presentation/config/thumbnailRenderers/TableItemImageRenderer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useFile } from \"~/presentation/hooks/useFile.js\";\nimport { CroppedFileImage } from \"./CroppedFileImage.js\";\n\nexport const TableItemImageRenderer = () => {\n const { file } = useFile();\n return (\n <CroppedFileImage\n file={file}\n width={100}\n fit={\"cover\"}\n fallbackClassName={\"object-cover w-full h-full\"}\n />\n );\n};\n"],"names":["TableItemImageRenderer","file","useFile","CroppedFileImage"],"mappings":";;;AAIO,MAAMA,yBAAyB;IAClC,MAAM,EAAEC,IAAI,EAAE,GAAGC;IACjB,OAAO,WAAP,GACI,sCAACC,kBAAgBA;QACb,MAAMF;QACN,OAAO;QACP,KAAK;QACL,mBAAmB;;AAG/B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface AssetFieldRendererSettings extends Record<string, unknown> {
|
|
3
|
+
imagesOnly?: boolean;
|
|
4
|
+
accept?: string[];
|
|
5
|
+
}
|
|
6
|
+
declare module "@webiny/app-admin/features/formModel/abstractions.js" {
|
|
7
|
+
interface IFieldRendererRegistry {
|
|
8
|
+
cmsAssetPicker: {
|
|
9
|
+
fieldType: "asset";
|
|
10
|
+
settings: AssetFieldRendererSettings;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Single-asset picker for the CMS Asset field. The field value is the typed Asset
|
|
16
|
+
* object; the picker chrome shows the file's URL, while crop / focal point / alt
|
|
17
|
+
* are edited per-usage via the shared `ImageEditor` and written back onto
|
|
18
|
+
* `value.image`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CmsAssetPickerRenderer: React.ComponentType<{
|
|
21
|
+
field: import("@webiny/app-admin/index.js").IFieldVM;
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import react, { useState } from "react";
|
|
2
|
+
import { createFieldRenderer } from "@webiny/app-admin/features/formModel/createFieldRenderer.js";
|
|
3
|
+
import { FileManager } from "@webiny/app-admin/base/ui/FileManager.js";
|
|
4
|
+
import { FilePicker, ImageEditor, RichItemPreview } from "@webiny/admin-ui";
|
|
5
|
+
import { applyImageEditToAsset, assetImageToEditorValue, fileItemToAsset, hasAsset, hasImageEdit, isImageAsset } from "./assetValue.js";
|
|
6
|
+
import { CroppedAssetThumb } from "./CroppedAssetThumb.js";
|
|
7
|
+
const CmsAssetPickerRenderer = createFieldRenderer(({ field })=>{
|
|
8
|
+
const settings = field.rendererSettings;
|
|
9
|
+
const value = field.value ?? null;
|
|
10
|
+
const [editing, setEditing] = useState(false);
|
|
11
|
+
const src = value?.src ?? void 0;
|
|
12
|
+
const editable = isImageAsset(value) && hasAsset(value);
|
|
13
|
+
const showCroppedPreview = editable && hasImageEdit(value?.image);
|
|
14
|
+
return /*#__PURE__*/ react.createElement(FileManager, {
|
|
15
|
+
images: settings?.imagesOnly,
|
|
16
|
+
accept: settings?.accept,
|
|
17
|
+
render: ({ showFileManager })=>/*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(FilePicker, {
|
|
18
|
+
label: field.label,
|
|
19
|
+
description: field.description,
|
|
20
|
+
note: field.note,
|
|
21
|
+
hint: field.help,
|
|
22
|
+
type: "compact",
|
|
23
|
+
value: src,
|
|
24
|
+
validation: field.validation,
|
|
25
|
+
renderFilePreview: showCroppedPreview && value?.src && value.image ? (previewProps)=>/*#__PURE__*/ react.createElement(RichItemPreview, {
|
|
26
|
+
...previewProps,
|
|
27
|
+
renderImage: ({ name })=>/*#__PURE__*/ react.createElement(CroppedAssetThumb, {
|
|
28
|
+
src: value.src,
|
|
29
|
+
name: name,
|
|
30
|
+
image: value.image
|
|
31
|
+
})
|
|
32
|
+
}) : void 0,
|
|
33
|
+
onSelectItem: ()=>showFileManager((file)=>{
|
|
34
|
+
field.onChange(fileItemToAsset(file));
|
|
35
|
+
}),
|
|
36
|
+
onRemoveItem: ()=>field.onChange(null),
|
|
37
|
+
onEditItem: editable ? ()=>setEditing(true) : void 0
|
|
38
|
+
}), editable && value ? /*#__PURE__*/ react.createElement(ImageEditor, {
|
|
39
|
+
open: editing,
|
|
40
|
+
onClose: ()=>setEditing(false),
|
|
41
|
+
image: {
|
|
42
|
+
src: value.src ?? "",
|
|
43
|
+
width: value.image?.width ?? 0,
|
|
44
|
+
height: value.image?.height ?? 0
|
|
45
|
+
},
|
|
46
|
+
value: assetImageToEditorValue(value.image),
|
|
47
|
+
onSave: (edit)=>{
|
|
48
|
+
field.onChange(applyImageEditToAsset(value, edit));
|
|
49
|
+
setEditing(false);
|
|
50
|
+
}
|
|
51
|
+
}) : null)
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
export { CmsAssetPickerRenderer };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=CmsAssetPickerRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/fieldRenderers/CmsAssetPickerRenderer.js","sources":["../../../src/presentation/fieldRenderers/CmsAssetPickerRenderer.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { createFieldRenderer } from \"@webiny/app-admin/features/formModel/createFieldRenderer.js\";\nimport { FileManager } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport type { FileManagerFileItem } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport { FilePicker, RichItemPreview, ImageEditor, type ImageEditorValue } from \"@webiny/admin-ui\";\nimport {\n applyImageEditToAsset,\n assetImageToEditorValue,\n fileItemToAsset,\n hasAsset,\n hasImageEdit,\n isImageAsset,\n type Asset\n} from \"./assetValue.js\";\nimport { CroppedAssetThumb } from \"./CroppedAssetThumb.js\";\n\nexport interface AssetFieldRendererSettings extends Record<string, unknown> {\n imagesOnly?: boolean;\n accept?: string[];\n}\n\ndeclare module \"@webiny/app-admin/features/formModel/abstractions.js\" {\n interface IFieldRendererRegistry {\n cmsAssetPicker: { fieldType: \"asset\"; settings: AssetFieldRendererSettings };\n }\n}\n\n/**\n * Single-asset picker for the CMS Asset field. The field value is the typed Asset\n * object; the picker chrome shows the file's URL, while crop / focal point / alt\n * are edited per-usage via the shared `ImageEditor` and written back onto\n * `value.image`.\n */\nexport const CmsAssetPickerRenderer = createFieldRenderer<\"cmsAssetPicker\">(({ field }) => {\n const settings = field.rendererSettings as AssetFieldRendererSettings | undefined;\n const value = (field.value as Asset | null) ?? null;\n const [editing, setEditing] = useState(false);\n\n const src = value?.src ?? undefined;\n const editable = isImageAsset(value) && hasAsset(value);\n const showCroppedPreview = editable && hasImageEdit(value?.image);\n\n return (\n <FileManager\n images={settings?.imagesOnly}\n accept={settings?.accept}\n render={({ showFileManager }) => (\n <>\n <FilePicker\n label={field.label}\n description={field.description}\n note={field.note}\n hint={field.help}\n type=\"compact\"\n value={src}\n validation={field.validation}\n // Reflect the per-usage crop + focal point in the thumbnail.\n renderFilePreview={\n showCroppedPreview && value?.src && value.image\n ? previewProps => (\n <RichItemPreview\n {...previewProps}\n renderImage={({ name }) => (\n <CroppedAssetThumb\n src={value.src as string}\n name={name}\n image={value.image!}\n />\n )}\n />\n )\n : undefined\n }\n onSelectItem={() =>\n showFileManager((file: FileManagerFileItem) => {\n field.onChange(fileItemToAsset(file));\n })\n }\n onRemoveItem={() => field.onChange(null)}\n onEditItem={editable ? () => setEditing(true) : undefined}\n />\n {editable && value ? (\n <ImageEditor\n open={editing}\n onClose={() => setEditing(false)}\n image={{\n src: value.src ?? \"\",\n width: value.image?.width ?? 0,\n height: value.image?.height ?? 0\n }}\n value={assetImageToEditorValue(value.image)}\n onSave={(edit: ImageEditorValue) => {\n field.onChange(applyImageEditToAsset(value, edit));\n setEditing(false);\n }}\n />\n ) : null}\n </>\n )}\n />\n );\n});\n"],"names":["CmsAssetPickerRenderer","createFieldRenderer","field","settings","value","editing","setEditing","useState","src","undefined","editable","isImageAsset","hasAsset","showCroppedPreview","hasImageEdit","FileManager","showFileManager","FilePicker","previewProps","RichItemPreview","name","CroppedAssetThumb","file","fileItemToAsset","ImageEditor","assetImageToEditorValue","edit","applyImageEditToAsset"],"mappings":";;;;;;AAiCO,MAAMA,yBAAyBC,oBAAsC,CAAC,EAAEC,KAAK,EAAE;IAClF,MAAMC,WAAWD,MAAM,gBAAgB;IACvC,MAAME,QAASF,MAAM,KAAK,IAAqB;IAC/C,MAAM,CAACG,SAASC,WAAW,GAAGC,SAAS;IAEvC,MAAMC,MAAMJ,OAAO,OAAOK;IAC1B,MAAMC,WAAWC,aAAaP,UAAUQ,SAASR;IACjD,MAAMS,qBAAqBH,YAAYI,aAAaV,OAAO;IAE3D,OAAO,WAAP,GACI,oBAACW,aAAWA;QACR,QAAQZ,UAAU;QAClB,QAAQA,UAAU;QAClB,QAAQ,CAAC,EAAEa,eAAe,EAAE,iBACxB,wDACI,oBAACC,YAAUA;gBACP,OAAOf,MAAM,KAAK;gBAClB,aAAaA,MAAM,WAAW;gBAC9B,MAAMA,MAAM,IAAI;gBAChB,MAAMA,MAAM,IAAI;gBAChB,MAAK;gBACL,OAAOM;gBACP,YAAYN,MAAM,UAAU;gBAE5B,mBACIW,sBAAsBT,OAAO,OAAOA,MAAM,KAAK,GACzCc,CAAAA,eAAAA,WAAAA,GACI,oBAACC,iBAAeA;wBACX,GAAGD,YAAY;wBAChB,aAAa,CAAC,EAAEE,IAAI,EAAE,iBAClB,oBAACC,mBAAiBA;gCACd,KAAKjB,MAAM,GAAG;gCACd,MAAMgB;gCACN,OAAOhB,MAAM,KAAK;;yBAKlCK;gBAEV,cAAc,IACVO,gBAAgB,CAACM;wBACbpB,MAAM,QAAQ,CAACqB,gBAAgBD;oBACnC;gBAEJ,cAAc,IAAMpB,MAAM,QAAQ,CAAC;gBACnC,YAAYQ,WAAW,IAAMJ,WAAW,QAAQG;gBAEnDC,YAAYN,QAAQ,WAARA,GACT,oBAACoB,aAAWA;gBACR,MAAMnB;gBACN,SAAS,IAAMC,WAAW;gBAC1B,OAAO;oBACH,KAAKF,MAAM,GAAG,IAAI;oBAClB,OAAOA,MAAM,KAAK,EAAE,SAAS;oBAC7B,QAAQA,MAAM,KAAK,EAAE,UAAU;gBACnC;gBACA,OAAOqB,wBAAwBrB,MAAM,KAAK;gBAC1C,QAAQ,CAACsB;oBACLxB,MAAM,QAAQ,CAACyB,sBAAsBvB,OAAOsB;oBAC5CpB,WAAW;gBACf;iBAEJ;;AAKxB"}
|
|
@@ -2,26 +2,33 @@ import react from "react";
|
|
|
2
2
|
import { createFieldRenderer } from "@webiny/app-admin/features/formModel/createFieldRenderer.js";
|
|
3
3
|
import { FileManager } from "@webiny/app-admin/base/ui/FileManager.js";
|
|
4
4
|
import { FilePicker } from "@webiny/admin-ui";
|
|
5
|
+
import { isEditableImageUrl, useCmsImageEditor } from "../hooks/useCmsImageEditor.js";
|
|
6
|
+
import { CmsImageEditorDialog } from "./CmsImageEditorDialog.js";
|
|
5
7
|
const CmsFilePickerRenderer = createFieldRenderer(({ field })=>{
|
|
6
8
|
const settings = field.rendererSettings;
|
|
9
|
+
const value = field.value;
|
|
10
|
+
const editor = useCmsImageEditor();
|
|
7
11
|
return /*#__PURE__*/ react.createElement(FileManager, {
|
|
8
12
|
images: settings?.images,
|
|
9
13
|
accept: settings?.accept,
|
|
10
14
|
own: settings?.own,
|
|
11
15
|
scope: settings?.scope,
|
|
12
|
-
render: ({ showFileManager })=>/*#__PURE__*/ react.createElement(FilePicker, {
|
|
16
|
+
render: ({ showFileManager })=>/*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(FilePicker, {
|
|
13
17
|
label: field.label,
|
|
14
18
|
description: field.description,
|
|
15
19
|
note: field.note,
|
|
16
20
|
hint: field.help,
|
|
17
21
|
type: "compact",
|
|
18
|
-
value:
|
|
22
|
+
value: value,
|
|
19
23
|
validation: field.validation,
|
|
20
24
|
onSelectItem: ()=>showFileManager((file)=>{
|
|
21
25
|
field.onChange(file.src || "");
|
|
22
26
|
}),
|
|
23
|
-
onRemoveItem: ()=>field.onChange(null)
|
|
24
|
-
|
|
27
|
+
onRemoveItem: ()=>field.onChange(null),
|
|
28
|
+
onEditItem: isEditableImageUrl(value) ? ()=>editor.openFor(value) : void 0
|
|
29
|
+
}), /*#__PURE__*/ react.createElement(CmsImageEditorDialog, {
|
|
30
|
+
editor: editor
|
|
31
|
+
}))
|
|
25
32
|
});
|
|
26
33
|
});
|
|
27
34
|
export { CmsFilePickerRenderer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/fieldRenderers/CmsFilePickerRenderer.js","sources":["../../../src/presentation/fieldRenderers/CmsFilePickerRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { createFieldRenderer } from \"@webiny/app-admin/features/formModel/createFieldRenderer.js\";\nimport { FileManager } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport { FilePicker } from \"@webiny/admin-ui\";\nimport type { FileManagerFileItem } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport type { FileFieldSettings } from \"@webiny/app-admin/features/formModel/fieldTypes/FileFieldType.js\";\n\ndeclare module \"@webiny/app-admin/features/formModel/abstractions.js\" {\n interface IFieldRendererRegistry {\n cmsFilePicker: { fieldType: \"file\"; settings: FileFieldSettings };\n }\n}\n\nexport const CmsFilePickerRenderer = createFieldRenderer<\"cmsFilePicker\">(({ field }) => {\n const settings = field.rendererSettings as FileFieldSettings | undefined;\n\n return (\n <FileManager\n images={settings?.images}\n accept={settings?.accept}\n own={settings?.own}\n scope={settings?.scope}\n render={({ showFileManager }) => (\n <FilePicker\n
|
|
1
|
+
{"version":3,"file":"presentation/fieldRenderers/CmsFilePickerRenderer.js","sources":["../../../src/presentation/fieldRenderers/CmsFilePickerRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { createFieldRenderer } from \"@webiny/app-admin/features/formModel/createFieldRenderer.js\";\nimport { FileManager } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport { FilePicker } from \"@webiny/admin-ui\";\nimport type { FileManagerFileItem } from \"@webiny/app-admin/base/ui/FileManager.js\";\nimport type { FileFieldSettings } from \"@webiny/app-admin/features/formModel/fieldTypes/FileFieldType.js\";\nimport { isEditableImageUrl, useCmsImageEditor } from \"~/presentation/hooks/useCmsImageEditor.js\";\nimport { CmsImageEditorDialog } from \"./CmsImageEditorDialog.js\";\n\ndeclare module \"@webiny/app-admin/features/formModel/abstractions.js\" {\n interface IFieldRendererRegistry {\n cmsFilePicker: { fieldType: \"file\"; settings: FileFieldSettings };\n }\n}\n\nexport const CmsFilePickerRenderer = createFieldRenderer<\"cmsFilePicker\">(({ field }) => {\n const settings = field.rendererSettings as FileFieldSettings | undefined;\n const value = field.value as string | undefined;\n const editor = useCmsImageEditor();\n\n return (\n <FileManager\n images={settings?.images}\n accept={settings?.accept}\n own={settings?.own}\n scope={settings?.scope}\n render={({ showFileManager }) => (\n <>\n <FilePicker\n label={field.label}\n description={field.description}\n note={field.note}\n hint={field.help}\n type=\"compact\"\n value={value}\n validation={field.validation}\n onSelectItem={() =>\n showFileManager((file: FileManagerFileItem) => {\n field.onChange(file.src || \"\");\n })\n }\n onRemoveItem={() => field.onChange(null)}\n // The \"Edit\" (pencil) action opens the crop / focal point /\n // alt editor for image values (edits the file's asset-level\n // settings). Hidden for non-images.\n onEditItem={\n isEditableImageUrl(value) ? () => editor.openFor(value) : undefined\n }\n />\n <CmsImageEditorDialog editor={editor} />\n </>\n )}\n />\n );\n});\n"],"names":["CmsFilePickerRenderer","createFieldRenderer","field","settings","value","editor","useCmsImageEditor","FileManager","showFileManager","FilePicker","file","isEditableImageUrl","undefined","CmsImageEditorDialog"],"mappings":";;;;;;AAeO,MAAMA,wBAAwBC,oBAAqC,CAAC,EAAEC,KAAK,EAAE;IAChF,MAAMC,WAAWD,MAAM,gBAAgB;IACvC,MAAME,QAAQF,MAAM,KAAK;IACzB,MAAMG,SAASC;IAEf,OAAO,WAAP,GACI,oBAACC,aAAWA;QACR,QAAQJ,UAAU;QAClB,QAAQA,UAAU;QAClB,KAAKA,UAAU;QACf,OAAOA,UAAU;QACjB,QAAQ,CAAC,EAAEK,eAAe,EAAE,iBACxB,wDACI,oBAACC,YAAUA;gBACP,OAAOP,MAAM,KAAK;gBAClB,aAAaA,MAAM,WAAW;gBAC9B,MAAMA,MAAM,IAAI;gBAChB,MAAMA,MAAM,IAAI;gBAChB,MAAK;gBACL,OAAOE;gBACP,YAAYF,MAAM,UAAU;gBAC5B,cAAc,IACVM,gBAAgB,CAACE;wBACbR,MAAM,QAAQ,CAACQ,KAAK,GAAG,IAAI;oBAC/B;gBAEJ,cAAc,IAAMR,MAAM,QAAQ,CAAC;gBAInC,YACIS,mBAAmBP,SAAS,IAAMC,OAAO,OAAO,CAACD,SAASQ;8BAGlE,oBAACC,sBAAoBA;gBAAC,QAAQR;;;AAKlD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { useCmsImageEditor } from "../../presentation/hooks/useCmsImageEditor.js";
|
|
3
|
+
interface CmsImageEditorDialogProps {
|
|
4
|
+
editor: ReturnType<typeof useCmsImageEditor>;
|
|
5
|
+
}
|
|
6
|
+
export declare const CmsImageEditorDialog: ({ editor }: CmsImageEditorDialogProps) => React.JSX.Element | null;
|
|
7
|
+
export {};
|